1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  24  */
  25 
  26 /*
  27  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
  28  * Use is subject to license terms.
  29  */
  30 
  31 #pragma weak __sin = sin
  32 
  33 
  34 /*
  35  * sin(x)
  36  * Accurate Table look-up algorithm by K.C. Ng, May, 1995.
  37  *
  38  * Algorithm: see sincos.c
  39  */
  40 
  41 #include "libm.h"
  42 
  43 static const double sc[] = {
  44 /* ONE  = */
  45         1.0,
  46 /* NONE = */ -1.0,
  47 
  48 /*
  49  * |sin(x) - (x+pp1*x^3+pp2*x^5)| <= 2^-58.79 for |x| < 0.008
  50  */
  51 /* PP1  = */-0.166666666666316558867252052378889521480627858683055567,
  52 /* PP2  = */.008333315652997472323564894248466758248475374977974017927,
  53 
  54 /*
  55  * |(sin(x) - (x+p1*x^3+...+p4*x^9)|
  56  * |------------------------------ | <= 2^-57.63 for |x| < 0.1953125
  57  * |                 x             |
  58  */
  59 /* P1   = */ -1.666666666666629669805215138920301589656e-0001,
  60 /* P2   = */ 8.333333332390951295683993455280336376663e-0003,
  61 /* P3   = */ -1.984126237997976692791551778230098403960e-0004,
  62 /* P4   = */ 2.753403624854277237649987622848330351110e-0006,
  63 
  64 /*
  65  * |cos(x) - (1+qq1*x^2+qq2*x^4)| <= 2^-55.99 for |x| <= 0.008 (0x3f80624d)
  66  */
  67 /* QQ1  = */-0.4999999999975492381842911981948418542742729,
  68 /* QQ2  = */0.041666542904352059294545209158357640398771740,
  69 /* PI_H = */ 3.1415926535897931159979634685,
  70 /* PI_L    = */ 1.22464679914735317722606593227425e-16,
  71 /* PI_L0   = */ 1.22464679914558443311283879205095e-16,
  72 /* PI_L1   = */ 1.768744113227140223300005233735517376e-28,
  73 /* PI2_H   = */ 6.2831853071795862319959269370,
  74 /* PI2_L   = */ 2.44929359829470635445213186454850e-16,
  75 /* PI2_L0  = */ 2.44929359829116886622567758410190e-16,
  76 /* PI2_L1  = */ 3.537488226454280446600010467471034752e-28,
  77 };
  78 
  79 
  80 #define ONEA            sc
  81 #define ONE             sc[0]
  82 #define NONE            sc[1]
  83 #define PP1             sc[2]
  84 #define PP2             sc[3]
  85 #define P1              sc[4]
  86 #define P2              sc[5]
  87 #define P3              sc[6]
  88 #define P4              sc[7]
  89 #define QQ1             sc[8]
  90 #define QQ2             sc[9]
  91 #define PI_H            sc[10]
  92 #define PI_L            sc[11]
  93 #define PI_L0           sc[12]
  94 #define PI_L1           sc[13]
  95 #define PI2_H           sc[14]
  96 #define PI2_L           sc[15]
  97 #define PI2_L0          sc[16]
  98 #define PI2_L1          sc[17]
  99 
 100 extern const double _TBL_sincos[], _TBL_sincosx[];
 101 
 102 double
 103 sin(double x)
 104 {
 105         double z, y[2], w, s, v, p, q;
 106         int i, j, n, hx, ix, lx;
 107 
 108         hx = ((int *)&x)[HIWORD];
 109         lx = ((int *)&x)[LOWORD];
 110         ix = hx & ~0x80000000;
 111 
 112         if (ix <= 0x3fc50000) {              /* |x| < .1640625 */
 113                 if (ix < 0x3e400000) /* |x| < 2**-27 */
 114                         if ((int)x == 0)
 115                                 return (x);
 116 
 117                 z = x * x;
 118 
 119                 if (ix < 0x3f800000) /* |x| < 2**-8 */
 120                         w = (z * x) * (PP1 + z * PP2);
 121                 else
 122                         w = (x * z) * ((P1 + z * P2) + (z * z) * (P3 + z * P4));
 123 
 124                 return (x + w);
 125         }
 126 
 127         /* for .1640625 < x < M, */
 128         n = ix >> 20;
 129 
 130         if (n < 0x402) {             /* x < 8 */
 131                 i = (((ix >> 12) & 0xff) | 0x100) >> (0x401 - n);
 132                 j = i - 10;
 133                 x = fabs(x);
 134                 v = x - _TBL_sincosx[j];
 135 
 136                 if (((j - 181) ^ (j - 201)) < 0) {
 137                         /* near pi, sin(x) = sin(pi-x) */
 138                         p = PI_H - x;
 139                         i = ix - 0x400921fb;
 140                         x = p + PI_L;
 141 
 142                         if ((i | ((lx - 0x54442D00) & 0xffffff00)) == 0) {
 143                                 /* very close to pi */
 144                                 x = p + PI_L0;
 145                                 return ((hx >= 0) ? x + PI_L1 : -(x + PI_L1));
 146                         }
 147 
 148                         z = x * x;
 149 
 150                         if (((ix - 0x40092000) >> 11) == 0) {
 151                                 /* |pi-x|<2**-8 */
 152                                 w = PI_L + (z * x) * (PP1 + z * PP2);
 153                         } else {
 154                                 w = PI_L + (z * x) * ((P1 + z * P2) + (z * z) *
 155                                     (P3 + z * P4));
 156                         }
 157 
 158                         return ((hx >= 0) ? p + w : -p - w);
 159                 }
 160 
 161                 s = v * v;
 162 
 163                 if (((j - 382) ^ (j - 402)) < 0) {
 164                         /* near 2pi, sin(x) = sin(x-2pi) */
 165                         p = x - PI2_H;
 166                         i = ix - 0x401921fb;
 167                         x = p - PI2_L;
 168 
 169                         if ((i | ((lx - 0x54442D00) & 0xffffff00)) == 0) {
 170                                 /* very close to 2pi */
 171                                 x = p - PI2_L0;
 172                                 return ((hx >= 0) ? x - PI2_L1 : -(x - PI2_L1));
 173                         }
 174 
 175                         z = x * x;
 176 
 177                         if (((ix - 0x40192000) >> 10) == 0) {
 178                                 /* |x-2pi|<2**-8 */
 179                                 w = (z * x) * (PP1 + z * PP2) - PI2_L;
 180                         } else {
 181                                 w = (z * x) * ((P1 + z * P2) + (z * z) * (P3 +
 182                                     z * P4)) - PI2_L;
 183                         }
 184 
 185                         return ((hx >= 0) ? p + w : -p - w);
 186                 }
 187 
 188                 j <<= 1;
 189                 w = _TBL_sincos[j + 1];
 190                 z = _TBL_sincos[j];
 191                 p = v + (v * s) * (PP1 + s * PP2);
 192                 q = s * (QQ1 + s * QQ2);
 193                 v = w * p + z * q;
 194                 return ((hx >= 0) ? z + v : -z - v);
 195         }
 196 
 197         if (ix >= 0x7ff00000)                /* sin(Inf or NaN) is NaN */
 198                 return (x / x);
 199 
 200         /* argument reduction needed */
 201         n = __rem_pio2(x, y);
 202 
 203         switch (n & 3) {
 204         case 0:
 205                 return (__k_sin(y[0], y[1]));
 206         case 1:
 207                 return (__k_cos(y[0], y[1]));
 208         case 2:
 209                 return (-__k_sin(y[0], y[1]));
 210         default:
 211                 return (-__k_cos(y[0], y[1]));
 212         }
 213 }