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