1dce5f3abSSteve Kargl /*- 2*4f889260SSteve Kargl * Copyright (c) 2017-2021 Steven G. Kargl 3dce5f3abSSteve Kargl * All rights reserved. 4dce5f3abSSteve Kargl * 5dce5f3abSSteve Kargl * Redistribution and use in source and binary forms, with or without 6dce5f3abSSteve Kargl * modification, are permitted provided that the following conditions 7dce5f3abSSteve Kargl * are met: 8dce5f3abSSteve Kargl * 1. Redistributions of source code must retain the above copyright 9dce5f3abSSteve Kargl * notice unmodified, this list of conditions, and the following 10dce5f3abSSteve Kargl * disclaimer. 11dce5f3abSSteve Kargl * 2. Redistributions in binary form must reproduce the above copyright 12dce5f3abSSteve Kargl * notice, this list of conditions and the following disclaimer in the 13dce5f3abSSteve Kargl * documentation and/or other materials provided with the distribution. 14dce5f3abSSteve Kargl * 15dce5f3abSSteve Kargl * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16dce5f3abSSteve Kargl * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17dce5f3abSSteve Kargl * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18dce5f3abSSteve Kargl * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19dce5f3abSSteve Kargl * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20dce5f3abSSteve Kargl * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21dce5f3abSSteve Kargl * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22dce5f3abSSteve Kargl * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23dce5f3abSSteve Kargl * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24dce5f3abSSteve Kargl * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25dce5f3abSSteve Kargl */ 26dce5f3abSSteve Kargl 27dce5f3abSSteve Kargl /* 28dce5f3abSSteve Kargl * See ../src/s_sinpi.c for implementation details. 29dce5f3abSSteve Kargl */ 30dce5f3abSSteve Kargl 31dce5f3abSSteve Kargl #include "math.h" 32dce5f3abSSteve Kargl #include "math_private.h" 33dce5f3abSSteve Kargl 34dce5f3abSSteve Kargl /* 35dce5f3abSSteve Kargl * pi_hi contains the leading 56 bits of a 169 bit approximation for pi. 36dce5f3abSSteve Kargl */ 37dce5f3abSSteve Kargl static const long double 38dce5f3abSSteve Kargl pi_hi = 3.14159265358979322702026593105983920e+00L, 39dce5f3abSSteve Kargl pi_lo = 1.14423774522196636802434264184180742e-17L; 40dce5f3abSSteve Kargl 41dce5f3abSSteve Kargl #include "k_cospil.h" 42dce5f3abSSteve Kargl #include "k_sinpil.h" 43dce5f3abSSteve Kargl 44dce5f3abSSteve Kargl volatile static const double vzero = 0; 45dce5f3abSSteve Kargl 46dce5f3abSSteve Kargl long double 47dce5f3abSSteve Kargl sinpil(long double x) 48dce5f3abSSteve Kargl { 49dce5f3abSSteve Kargl long double ax, hi, lo, s, xf, xhi, xlo; 50dce5f3abSSteve Kargl uint32_t ix; 51dce5f3abSSteve Kargl 52dce5f3abSSteve Kargl ax = fabsl(x); 53dce5f3abSSteve Kargl 54dce5f3abSSteve Kargl if (ax < 1) { 55dce5f3abSSteve Kargl if (ax < 0.25) { 56dce5f3abSSteve Kargl if (ax < 0x1p-60) { 57dce5f3abSSteve Kargl if (x == 0) 58dce5f3abSSteve Kargl return (x); 59dce5f3abSSteve Kargl hi = (double)x; 60dce5f3abSSteve Kargl hi *= 0x1p113L; 61dce5f3abSSteve Kargl lo = x * 0x1p113L - hi; 62dce5f3abSSteve Kargl s = (pi_lo + pi_hi) * lo + pi_lo * lo + 63dce5f3abSSteve Kargl pi_hi * hi; 64dce5f3abSSteve Kargl return (s * 0x1p-113L); 65dce5f3abSSteve Kargl } 66dce5f3abSSteve Kargl 67dce5f3abSSteve Kargl s = __kernel_sinpil(ax); 68*4f889260SSteve Kargl return (x < 0 ? -s : s); 69dce5f3abSSteve Kargl } 70dce5f3abSSteve Kargl 71dce5f3abSSteve Kargl if (ax < 0.5) 72dce5f3abSSteve Kargl s = __kernel_cospil(0.5 - ax); 73dce5f3abSSteve Kargl else if (ax < 0.75) 74dce5f3abSSteve Kargl s = __kernel_cospil(ax - 0.5); 75dce5f3abSSteve Kargl else 76dce5f3abSSteve Kargl s = __kernel_sinpil(1 - ax); 77*4f889260SSteve Kargl return (x < 0 ? -s : s); 78dce5f3abSSteve Kargl } 79dce5f3abSSteve Kargl 80dce5f3abSSteve Kargl if (ax < 0x1p112) { 81*4f889260SSteve Kargl /* Split x = n + r with 0 <= r < 1. */ 82*4f889260SSteve Kargl xf = (ax + 0x1p112L) - 0x1p112L; /* Integer part */ 83*4f889260SSteve Kargl ax -= xf; /* Remainder */ 84*4f889260SSteve Kargl if (ax < 0) { 85*4f889260SSteve Kargl ax += 1; 86*4f889260SSteve Kargl xf -= 1; 87*4f889260SSteve Kargl } 88*4f889260SSteve Kargl 89dce5f3abSSteve Kargl if (ax == 0) { 90dce5f3abSSteve Kargl s = 0; 91dce5f3abSSteve Kargl } else { 92dce5f3abSSteve Kargl if (ax < 0.5) { 93dce5f3abSSteve Kargl if (ax <= 0.25) 94dce5f3abSSteve Kargl s = __kernel_sinpil(ax); 95dce5f3abSSteve Kargl else 96dce5f3abSSteve Kargl s = __kernel_cospil(0.5 - ax); 97dce5f3abSSteve Kargl } else { 98dce5f3abSSteve Kargl if (ax < 0.75) 99dce5f3abSSteve Kargl s = __kernel_cospil(ax - 0.5); 100dce5f3abSSteve Kargl else 101dce5f3abSSteve Kargl s = __kernel_sinpil(1 - ax); 102dce5f3abSSteve Kargl } 103dce5f3abSSteve Kargl 104*4f889260SSteve Kargl if (xf > 0x1p64) 105*4f889260SSteve Kargl xf -= 0x1p64; 106*4f889260SSteve Kargl if (xf > 0x1p32) 107*4f889260SSteve Kargl xf -= 0x1p32; 108dce5f3abSSteve Kargl ix = (uint32_t)xf; 109dce5f3abSSteve Kargl if (ix & 1) s = -s; 110dce5f3abSSteve Kargl } 111*4f889260SSteve Kargl return (x < 0 ? -s : s); 112dce5f3abSSteve Kargl } 113dce5f3abSSteve Kargl 114dce5f3abSSteve Kargl if (isinf(x) || isnan(x)) 115dce5f3abSSteve Kargl return (vzero / vzero); 116dce5f3abSSteve Kargl 117dce5f3abSSteve Kargl /* 118dce5f3abSSteve Kargl * |x| >= 0x1p112 is always an integer, so return +-0. 119dce5f3abSSteve Kargl */ 120dce5f3abSSteve Kargl return (copysignl(0, x)); 121dce5f3abSSteve Kargl } 122