1 /* 2 * Single-precision sin function. 3 * 4 * Copyright (c) 2018-2021, Arm Limited. 5 * SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception 6 */ 7 8 #include <math.h> 9 #include "math_config.h" 10 #include "sincosf.h" 11 12 /* Fast sinf implementation. Worst-case ULP is 0.5607, maximum relative 13 error is 0.5303 * 2^-23. A single-step range reduction is used for 14 small values. Large inputs have their range reduced using fast integer 15 arithmetic. */ 16 float 17 sinf (float y) 18 { 19 double x = y; 20 double s; 21 int n; 22 const sincos_t *p = &__sincosf_table[0]; 23 24 if (abstop12 (y) < abstop12 (pio4f)) 25 { 26 s = x * x; 27 28 if (unlikely (abstop12 (y) < abstop12 (0x1p-12f))) 29 { 30 if (unlikely (abstop12 (y) < abstop12 (0x1p-126f))) 31 /* Force underflow for tiny y. */ 32 force_eval_float (s); 33 return y; 34 } 35 36 return sinf_poly (x, s, p, 0); 37 } 38 else if (likely (abstop12 (y) < abstop12 (120.0f))) 39 { 40 x = reduce_fast (x, p, &n); 41 42 /* Setup the signs for sin and cos. */ 43 s = p->sign[n & 3]; 44 45 if (n & 2) 46 p = &__sincosf_table[1]; 47 48 return sinf_poly (x * s, x * x, p, n); 49 } 50 else if (abstop12 (y) < abstop12 (INFINITY)) 51 { 52 uint32_t xi = asuint (y); 53 int sign = xi >> 31; 54 55 x = reduce_large (xi, &n); 56 57 /* Setup signs for sin and cos - include original sign. */ 58 s = p->sign[(n + sign) & 3]; 59 60 if ((n + sign) & 2) 61 p = &__sincosf_table[1]; 62 63 return sinf_poly (x * s, x * x, p, n); 64 } 65 else 66 return __math_invalidf (y); 67 } 68