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