131914882SAlex Richardson /* 231914882SAlex Richardson * Single-precision sin function. 331914882SAlex Richardson * 4*072a4ba8SAndrew Turner * Copyright (c) 2018-2021, Arm Limited. 5*072a4ba8SAndrew Turner * SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception 631914882SAlex Richardson */ 731914882SAlex Richardson 831914882SAlex Richardson #include <math.h> 931914882SAlex Richardson #include "math_config.h" 1031914882SAlex Richardson #include "sincosf.h" 1131914882SAlex Richardson 1231914882SAlex Richardson /* Fast sinf implementation. Worst-case ULP is 0.5607, maximum relative 1331914882SAlex Richardson error is 0.5303 * 2^-23. A single-step range reduction is used for 1431914882SAlex Richardson small values. Large inputs have their range reduced using fast integer 1531914882SAlex Richardson arithmetic. */ 1631914882SAlex Richardson float 1731914882SAlex Richardson sinf (float y) 1831914882SAlex Richardson { 1931914882SAlex Richardson double x = y; 2031914882SAlex Richardson double s; 2131914882SAlex Richardson int n; 2231914882SAlex Richardson const sincos_t *p = &__sincosf_table[0]; 2331914882SAlex Richardson 24d49ad206SAndrew Turner if (abstop12 (y) < abstop12 (pio4f)) 2531914882SAlex Richardson { 2631914882SAlex Richardson s = x * x; 2731914882SAlex Richardson 2831914882SAlex Richardson if (unlikely (abstop12 (y) < abstop12 (0x1p-12f))) 2931914882SAlex Richardson { 3031914882SAlex Richardson if (unlikely (abstop12 (y) < abstop12 (0x1p-126f))) 3131914882SAlex Richardson /* Force underflow for tiny y. */ 3231914882SAlex Richardson force_eval_float (s); 3331914882SAlex Richardson return y; 3431914882SAlex Richardson } 3531914882SAlex Richardson 3631914882SAlex Richardson return sinf_poly (x, s, p, 0); 3731914882SAlex Richardson } 3831914882SAlex Richardson else if (likely (abstop12 (y) < abstop12 (120.0f))) 3931914882SAlex Richardson { 4031914882SAlex Richardson x = reduce_fast (x, p, &n); 4131914882SAlex Richardson 4231914882SAlex Richardson /* Setup the signs for sin and cos. */ 4331914882SAlex Richardson s = p->sign[n & 3]; 4431914882SAlex Richardson 4531914882SAlex Richardson if (n & 2) 4631914882SAlex Richardson p = &__sincosf_table[1]; 4731914882SAlex Richardson 4831914882SAlex Richardson return sinf_poly (x * s, x * x, p, n); 4931914882SAlex Richardson } 5031914882SAlex Richardson else if (abstop12 (y) < abstop12 (INFINITY)) 5131914882SAlex Richardson { 5231914882SAlex Richardson uint32_t xi = asuint (y); 5331914882SAlex Richardson int sign = xi >> 31; 5431914882SAlex Richardson 5531914882SAlex Richardson x = reduce_large (xi, &n); 5631914882SAlex Richardson 5731914882SAlex Richardson /* Setup signs for sin and cos - include original sign. */ 5831914882SAlex Richardson s = p->sign[(n + sign) & 3]; 5931914882SAlex Richardson 6031914882SAlex Richardson if ((n + sign) & 2) 6131914882SAlex Richardson p = &__sincosf_table[1]; 6231914882SAlex Richardson 6331914882SAlex Richardson return sinf_poly (x * s, x * x, p, n); 6431914882SAlex Richardson } 6531914882SAlex Richardson else 6631914882SAlex Richardson return __math_invalidf (y); 6731914882SAlex Richardson } 68