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  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  23  */
  24 /*
  25  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
  26  * Use is subject to license terms.
  27  */
  28 
  29 #pragma weak sincosf = __sincosf
  30 
  31 /* INDENT OFF */
  32 /*
  33  * For |x| < pi/4, let z = x * x, and approximate sin(x) by
  34  *
  35  *      S(x) = x(S0 + S1*z)(S2 + S3*z + z*z)
  36  * where
  37  *      S0 =   1.85735322054308378716204874632872525989806770558e-0003,
  38  *      S1 =  -1.95035094218403635082921458859320791358115801259e-0004,
  39  *      S2 =   5.38400550766074785970952495168558701485841707252e+0002,
  40  *      S3 =  -3.31975110777873728964197739157371509422022905947e+0001,
  41  *
  42  * with error bounded by |(sin(x) - S(x))/x| < 2**(-28.2), and
  43  * cos(x) by
  44  *
  45  *      C(x) = (C0 + C1*z + C2*z*z) * (C3 + C4*z + z*z)
  46  * where
  47  *      C0 =   1.09349482127188401868272000389539985058873853699e-0003
  48  *      C1 =  -5.03324285989964979398034700054920226866107675091e-0004
  49  *      C2 =   2.43792880266971107750418061559602239831538067410e-0005
  50  *      C3 =   9.14499072605666582228127405245558035523741471271e+0002
  51  *      C4 =  -3.63151270591815439197122504991683846785293207730e+0001
  52  *
  53  * with error bounded by |cos(x) - C(x)| < 2**(-34.2).
  54  */
  55 /* INDENT ON */
  56 
  57 #include "libm.h"
  58 
  59 extern const int _TBL_ipio2_inf[];
  60 extern int __rem_pio2m(double *, double *, int, int, int, const int *);
  61 #if defined(__i386) && !defined(__amd64)
  62 extern int __swapRP(int);
  63 #endif
  64 
  65 static const double C[] = {
  66         1.85735322054308378716204874632872525989806770558e-0003,
  67         -1.95035094218403635082921458859320791358115801259e-0004,
  68         5.38400550766074785970952495168558701485841707252e+0002,
  69         -3.31975110777873728964197739157371509422022905947e+0001,
  70         1.09349482127188401868272000389539985058873853699e-0003,
  71         -5.03324285989964979398034700054920226866107675091e-0004,
  72         2.43792880266971107750418061559602239831538067410e-0005,
  73         9.14499072605666582228127405245558035523741471271e+0002,
  74         -3.63151270591815439197122504991683846785293207730e+0001,
  75         0.636619772367581343075535,     /* 2^ -1  * 1.45F306DC9C883 */
  76         0.5,
  77         1.570796326734125614166,        /* 2^  0  * 1.921FB54400000 */
  78         6.077100506506192601475e-11,    /* 2^-34  * 1.0B4611A626331 */
  79 };
  80 
  81 #define S0      C[0]
  82 #define S1      C[1]
  83 #define S2      C[2]
  84 #define S3      C[3]
  85 #define C0      C[4]
  86 #define C1      C[5]
  87 #define C2      C[6]
  88 #define C3      C[7]
  89 #define C4      C[8]
  90 #define invpio2 C[9]
  91 #define half    C[10]
  92 #define pio2_1  C[11]
  93 #define pio2_t  C[12]
  94 
  95 void
  96 sincosf(float x, float *s, float *c)
  97 {
  98         double  y, z, w;
  99         float   f, g;
 100         int     n, ix, hx, hy;
 101 
 102         hx = *((int *)&x);
 103         ix = hx & 0x7fffffff;
 104 
 105         y = (double)x;
 106 
 107         if (ix <= 0x4016cbe4) {              /* |x| < 3*pi/4 */
 108                 if (ix <= 0x3f490fdb) {              /* |x| < pi/4 */
 109                         if (ix <= 0x39800000) {      /* |x| <= 2**-12 */
 110                                 volatile int    i = (int)y;
 111 #ifdef lint
 112                                 i = i;
 113 #endif
 114                                 *s = x;
 115                                 *c = 1.0f;
 116                                 return;
 117                         }
 118                         z = y * y;
 119                         *s = (float)((y * (S0 + z * S1)) *
 120                             (S2 + z * (S3 + z)));
 121                         *c = (float)(((C0 + z * C1) + (z * z) * C2) *
 122                             (C3 + z * (C4 + z)));
 123                 } else if (hx > 0) {
 124                         y = (y - pio2_1) - pio2_t;
 125                         z = y * y;
 126                         *s = (float)(((C0 + z * C1) + (z * z) * C2) *
 127                             (C3 + z * (C4 + z)));
 128                         *c = (float)-((y * (S0 + z * S1)) *
 129                             (S2 + z * (S3 + z)));
 130                 } else {
 131                         y = (y + pio2_1) + pio2_t;
 132                         z = y * y;
 133                         *s = (float)-(((C0 + z * C1) + (z * z) * C2) *
 134                             (C3 + z * (C4 + z)));
 135                         *c = (float)((y * (S0 + z * S1)) *
 136                             (S2 + z * (S3 + z)));
 137                 }
 138                 return;
 139         } else if (ix <= 0x49c90fdb) {       /* |x| < 2^19*pi */
 140 #if defined(__i386) && !defined(__amd64)
 141                 int     rp;
 142 
 143                 rp = __swapRP(fp_extended);
 144 #endif
 145                 w = y * invpio2;
 146                 if (hx < 0)
 147                         n = (int)(w - half);
 148                 else
 149                         n = (int)(w + half);
 150                 y = (y - n * pio2_1) - n * pio2_t;
 151 #if defined(__i386) && !defined(__amd64)
 152                 if (rp != fp_extended)
 153                         (void) __swapRP(rp);
 154 #endif
 155         } else {
 156                 if (ix >= 0x7f800000) {
 157                         *s = *c = x / x;
 158                         return;
 159                 }
 160                 hy = ((int *)&y)[HIWORD];
 161                 n = ((hy >> 20) & 0x7ff) - 1046;
 162                 ((int *)&w)[HIWORD] = (hy & 0xfffff) | 0x41600000;
 163                 ((int *)&w)[LOWORD] = ((int *)&y)[LOWORD];
 164                 n = __rem_pio2m(&w, &y, n, 1, 0, _TBL_ipio2_inf);
 165                 if (hy < 0) {
 166                         y = -y;
 167                         n = -n;
 168                 }
 169         }
 170 
 171         z = y * y;
 172         f = (float)((y * (S0 + z * S1)) * (S2 + z * (S3 + z)));
 173         g = (float)(((C0 + z * C1) + (z * z) * C2) *
 174             (C3 + z * (C4 + z)));
 175         if (n & 2) {
 176                 f = -f;
 177                 g = -g;
 178         }
 179         if (n & 1) {
 180                 *s = g;
 181                 *c = -f;
 182         } else {
 183                 *s = f;
 184                 *c = g;
 185         }
 186 }