00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055 static char *rcs_id = "$Source$ $Revision$";
00056
00057 #ifdef _CALL_MATHERR
00058 #include <stdio.h>
00059 #include <math.h>
00060 #include <errno.h>
00061 #endif
00062
00063 #include "libm.h"
00064
00065 #ifdef mips
00066 extern double sin(double);
00067
00068 #pragma weak sin = __sin
00069 #endif
00070
00071 #if defined(BUILD_OS_DARWIN)
00072 extern double __sin(double);
00073 #pragma weak sin
00074 double sin( double x) {
00075 return __sin( x );
00076 }
00077 #elif defined(__GNUC__)
00078 extern double __sin(double);
00079
00080 double sin() __attribute__ ((weak, alias ("__sin")));
00081
00082 #endif
00083
00084 static const du Qnan =
00085 {D(QNANHI, QNANLO)};
00086
00087 static const du Inf =
00088 {D(0x7ff00000, 0x00000000)};
00089
00090 static const du half =
00091 {D(0x3fe00000, 0x00000000)};
00092
00093 static const du one =
00094 {D(0x3ff00000, 0x00000000)};
00095
00096 static const du rpiby2 =
00097 {D(0x3fe45f30, 0x6dc9c883)};
00098
00099 static const du piby2hi =
00100 {D(0x3ff921fb, 0x54400000)};
00101
00102 static const du piby2lo =
00103 {D(0x3dd0b461, 0x1a600000)};
00104
00105 static const du piby2tiny =
00106 {D(0x3ba3198a, 0x2e037073)};
00107
00108 static const du ph =
00109 {D(0x3ff921fb, 0x50000000)};
00110
00111 static const du pl =
00112 {D(0x3e5110b4, 0x60000000)};
00113
00114 static const du pt =
00115 {D(0x3c91a626, 0x30000000)};
00116
00117 static const du pe =
00118 {D(0x3ae8a2e0, 0x30000000)};
00119
00120 static const du pe2 =
00121 {D(0x394c1cd1, 0x29024e09)};
00122
00123 static const du Ph =
00124 {D(0x3ff921fb, 0x54000000)};
00125
00126 static const du Pl =
00127 {D(0x3e110b46, 0x10000000)};
00128
00129 static const du Pt =
00130 {D(0x3c5a6263, 0x3145c06e)};
00131
00132
00133
00134 static const du P[] =
00135 {
00136 {D(0x3ff00000, 0x00000000)},
00137 {D(0xbfc55555, 0x55555548)},
00138 {D(0x3f811111, 0x1110f7d0)},
00139 {D(0xbf2a01a0, 0x19bfdf03)},
00140 {D(0x3ec71de3, 0x567d4896)},
00141 {D(0xbe5ae5e5, 0xa9291691)},
00142 {D(0x3de5d8fd, 0x1fcf0ec1)},
00143 };
00144
00145
00146
00147 static const du Q[] =
00148 {
00149 {D(0x3ff00000, 0x00000000)},
00150 {D(0xbfdfffff, 0xffffff96)},
00151 {D(0x3fa55555, 0x5554f0ab)},
00152 {D(0xbf56c16c, 0x1640aaca)},
00153 {D(0x3efa019f, 0x81cb6a1d)},
00154 {D(0xbe927df4, 0x609cb202)},
00155 {D(0x3e21b8b9, 0x947ab5c8)},
00156 };
00157
00158 #ifdef _TABLE_BASED_REDUCTION
00159
00160
00161
00162
00163
00164 static const du tblh[] =
00165 {
00166 {D(0xc02f6a7a, 0x2955385e)},
00167 {D(0xc02c463a, 0xbeccb2bb)},
00168 {D(0xc02921fb, 0x54442d18)},
00169 {D(0xc025fdbb, 0xe9bba775)},
00170 {D(0xc022d97c, 0x7f3321d2)},
00171 {D(0xc01f6a7a, 0x2955385e)},
00172 {D(0xc01921fb, 0x54442d18)},
00173 {D(0xc012d97c, 0x7f3321d2)},
00174 {D(0xc00921fb, 0x54442d18)},
00175 {D(0xbff921fb, 0x54442d18)},
00176 {D(0x00000000, 0x00000000)},
00177 {D(0x3ff921fb, 0x54442d18)},
00178 {D(0x400921fb, 0x54442d18)},
00179 {D(0x4012d97c, 0x7f3321d2)},
00180 {D(0x401921fb, 0x54442d18)},
00181 {D(0x401f6a7a, 0x2955385e)},
00182 {D(0x4022d97c, 0x7f3321d2)},
00183 {D(0x4025fdbb, 0xe9bba775)},
00184 {D(0x402921fb, 0x54442d18)},
00185 {D(0x402c463a, 0xbeccb2bb)},
00186 {D(0x402f6a7a, 0x2955385e)},
00187 };
00188
00189 static const du tbll[] =
00190 {
00191 {D(0xbcc60faf, 0xbfd97309)},
00192 {D(0xbcc3daea, 0xf976e788)},
00193 {D(0xbcc1a626, 0x33145c07)},
00194 {D(0xbcbee2c2, 0xd963a10c)},
00195 {D(0xbcba7939, 0x4c9e8a0a)},
00196 {D(0xbcb60faf, 0xbfd97309)},
00197 {D(0xbcb1a626, 0x33145c07)},
00198 {D(0xbcaa7939, 0x4c9e8a0a)},
00199 {D(0xbca1a626, 0x33145c07)},
00200 {D(0xbc91a626, 0x33145c07)},
00201 {D(0x00000000, 0x00000000)},
00202 {D(0x3c91a626, 0x33145c07)},
00203 {D(0x3ca1a626, 0x33145c07)},
00204 {D(0x3caa7939, 0x4c9e8a0a)},
00205 {D(0x3cb1a626, 0x33145c07)},
00206 {D(0x3cb60faf, 0xbfd97309)},
00207 {D(0x3cba7939, 0x4c9e8a0a)},
00208 {D(0x3cbee2c2, 0xd963a10c)},
00209 {D(0x3cc1a626, 0x33145c07)},
00210 {D(0x3cc3daea, 0xf976e788)},
00211 {D(0x3cc60faf, 0xbfd97309)},
00212 };
00213 #endif
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230 double
00231 __sin( x )
00232 double x;
00233 {
00234 #ifdef _32BIT_MACHINE
00235 int ix, xpt, m, l;
00236 #else
00237 long long ix, xpt, m, l;
00238 #endif
00239
00240 int n;
00241 double xsq;
00242 double poly;
00243 double result;
00244 double *p;
00245 double z, dn;
00246 double absx, dn1, dn2;
00247 double s, ss;
00248 double t, w, ww;
00249 #ifdef _CALL_MATHERR
00250 struct exception exstruct;
00251 #endif
00252
00253
00254
00255 #ifdef _32BIT_MACHINE
00256
00257 DBLHI2INT(x, ix);
00258 #else
00259 DBL2LL(x, ix);
00260 #endif
00261 xpt = (ix >> (DMANTWIDTH-1));
00262 xpt &= 0xfff;
00263
00264 if ( xpt < 0x7fd )
00265 {
00266
00267
00268 if ( xpt >= 0x7c2 )
00269 {
00270
00271
00272
00273
00274 xsq = x*x;
00275
00276 poly = (((((P[6].d*xsq + P[5].d)*xsq + P[4].d)*xsq +
00277 P[3].d)*xsq + P[2].d)*xsq + P[1].d)*(xsq*x) + x;
00278
00279 return ( poly );
00280 }
00281
00282 return ( x );
00283 }
00284
00285 #ifdef _TABLE_BASED_REDUCTION
00286
00287 if ( xpt < 0x806 )
00288 {
00289
00290
00291
00292
00293 dn = x*rpiby2.d;
00294 n = ROUND(dn);
00295
00296
00297
00298 x = x - tblh[n+10].d;
00299 x = x - tbll[n+10].d;
00300
00301 xsq = x*x;
00302
00303 p = (double *)&P[0].d;
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314 if ( n&1 )
00315 {
00316 p = (double *)&Q[0].d;
00317 x = 1.0;
00318 }
00319
00320 result = (((((p[6]*xsq + p[5])*xsq + p[4])*xsq
00321 + p[3])*xsq + p[2])*xsq + p[1])*(xsq*x) + x;
00322
00323 if ( n&2 )
00324 result = -result;
00325
00326 return ( result );
00327 }
00328 #endif
00329
00330 if ( xpt < 0x827 )
00331 {
00332
00333
00334 dn = x*rpiby2.d;
00335 n = ROUND(dn);
00336 dn = n;
00337
00338 x = x - dn*piby2hi.d;
00339 x = x - dn*piby2lo.d;
00340 x = x - dn*piby2tiny.d;
00341
00342 xsq = x*x;
00343
00344 p = (double *)&P[0].d;
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355 if ( n&1 )
00356 {
00357 p = (double *)&Q[0].d;
00358 x = 1.0;
00359 }
00360
00361 result = (((((p[6]*xsq + p[5])*xsq + p[4])*xsq
00362 + p[3])*xsq + p[2])*xsq + p[1])*(xsq*x) + x;
00363
00364 if ( n&2 )
00365 result = -result;
00366
00367 return ( result );
00368 }
00369
00370 if ( xpt < 0x836 )
00371 {
00372
00373
00374 dn = x*rpiby2.d;
00375 n = ROUND(dn);
00376 dn = n;
00377
00378 x = x - dn*ph.d;
00379 x = x - dn*pl.d;
00380 x = x - dn*pt.d;
00381 x = x - dn*pe.d;
00382 x = x - dn*pe2.d;
00383
00384 xsq = x*x;
00385
00386 p = (double *)&P[0].d;
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397 if ( n&1 )
00398 {
00399 p = (double *)&Q[0].d;
00400 x = 1.0;
00401 }
00402
00403 result = (((((p[6]*xsq + p[5])*xsq + p[4])*xsq
00404 + p[3])*xsq + p[2])*xsq + p[1])*(xsq*x) + x;
00405
00406 if ( n&2 )
00407 result = -result;
00408
00409 return ( result );
00410 }
00411
00412 if ( xpt < 0x862 )
00413 {
00414
00415
00416 absx = fabs(x);
00417
00418 dn = z = absx*rpiby2.d;
00419
00420
00421
00422 #ifdef _32BIT_MACHINE
00423
00424 DBLHI2INT(dn, l);
00425 m = (l >> DMANTWIDTH);
00426 m &= 0x7ff;
00427
00428
00429
00430 DBLLO2INT(dn, l);
00431
00432 l >>= (0x433 - m);
00433 n = l;
00434 l <<= (0x433 - m);
00435 INT2DBLLO(l, dn);
00436 #else
00437 DBL2LL(dn, l);
00438 m = (l >> DMANTWIDTH);
00439 m &= 0x7ff;
00440
00441
00442
00443 l >>= (0x433 - m);
00444 n = l;
00445 l <<= (0x433 - m);
00446 LL2DBL(l, dn);
00447 #endif
00448
00449
00450
00451
00452 n &= 3;
00453
00454 if ( (z - dn) >= half.d )
00455 {
00456 dn += one.d;
00457 n += 1;
00458 }
00459
00460
00461
00462
00463
00464
00465
00466 dn1 = dn;
00467
00468 #ifdef _32BIT_MACHINE
00469
00470 DBLLO2INT(dn1, m);
00471 m >>= 28;
00472 m <<= 28;
00473 INT2DBLLO(m, dn1);
00474 #else
00475 DBL2LL(dn1, m);
00476 m >>= 28;
00477 m <<= 28;
00478 LL2DBL(m, dn1);
00479 #endif
00480 dn2 = dn - dn1;
00481
00482 z = absx - dn1*Ph.d;
00483
00484 t = dn2*Ph.d;
00485 s = z - t;
00486 ss = z - s - t;
00487
00488 t = ss - dn1*Pl.d;
00489 w = s + t;
00490 ww = s - w + t;
00491
00492 t = ww - dn2*Pl.d;
00493 s = w + t;
00494 ss = w - s + t;
00495
00496 t = ss - dn1*Pt.d;
00497 w = s + t;
00498 ww = s - w + t;
00499
00500 t = ww - dn2*Pt.d;
00501 z = w + t;
00502
00503 if ( x < 0.0 )
00504 {
00505
00506 z = -z;
00507 n = -n;
00508 }
00509
00510 xsq = z*z;
00511
00512 p = (double *)&P[0].d;
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523 if ( n&1 )
00524 {
00525 p = (double *)&Q[0].d;
00526 z = 1.0;
00527 }
00528
00529 result = (((((p[6]*xsq + p[5])*xsq + p[4])*xsq
00530 + p[3])*xsq + p[2])*xsq + p[1])*(xsq*z) + z;
00531
00532 if ( n&2 )
00533 result = -result;
00534
00535 return ( result );
00536 }
00537
00538 if ( (x != x) || (fabs(x) == Inf.d) )
00539 {
00540
00541
00542 #ifdef _CALL_MATHERR
00543
00544 exstruct.type = DOMAIN;
00545 exstruct.name = "sin";
00546 exstruct.arg1 = x;
00547 exstruct.retval = Qnan.d;
00548
00549 if ( matherr( &exstruct ) == 0 )
00550 {
00551 fprintf(stderr, "domain error in sin\n");
00552 SETERRNO(EDOM);
00553 }
00554
00555 return ( exstruct.retval );
00556 #else
00557 NAN_SETERRNO(EDOM);
00558
00559 return ( Qnan.d );
00560 #endif
00561 }
00562
00563
00564
00565 #ifdef _CALL_MATHERR
00566
00567 exstruct.type = TLOSS;
00568 exstruct.name = "sin";
00569 exstruct.arg1 = x;
00570 exstruct.retval = 0.0;
00571
00572 if ( matherr( &exstruct ) == 0 )
00573 {
00574 fprintf(stderr, "range error in sin (total loss \
00575 of significance)\n");
00576 SETERRNO(ERANGE);
00577 }
00578
00579 return ( exstruct.retval );
00580 #else
00581 SETERRNO(ERANGE);
00582
00583 return ( 0.0 );
00584 #endif
00585 }
00586
00587 #ifdef NO_LONG_DOUBLE
00588
00589 #if defined(BUILD_OS_DARWIN)
00590 extern long double __sinl(long double);
00591 long double sinl( long double x ) {
00592 return ( (long double)__sin((double)x) );
00593 }
00594 #elif defined(__GNUC__)
00595 extern long double __sinl(long double);
00596
00597 long double sinl() __attribute__ ((weak, alias ("__sinl")));
00598
00599 #endif
00600
00601 long double
00602 __sinl( long double x )
00603 {
00604 return ( (long double)__sin((double)x) );
00605 }
00606
00607 #endif
00608