2 * IBM Accurate Mathematical Library
3 * written by International Business Machines Corp.
4 * Copyright (C) 2001-2013 Free Software Foundation, Inc.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2.1 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
19 /****************************************************************************/
21 /* MODULE_NAME:usncs.c */
38 /* FILES NEEDED: dla.h endian.h mpa.h mydefs.h usncs.h */
39 /* branred.c sincos32.c dosincos.c mpa.c */
42 /* An ultimate sin and routine. Given an IEEE double machine number x */
43 /* it computes the correctly rounded (to nearest) value of sin(x) or cos(x) */
44 /* Assumption: Machine arithmetic operations are performed in */
45 /* round to nearest mode of IEEE 754 standard. */
47 /****************************************************************************/
55 #include <math_private.h>
58 /* Helper macros to compute sin of the input values. */
59 #define POLYNOMIAL2(xx) ((((s5.x * (xx) + s4.x) * (xx) + s3.x) * (xx) + s2.x) \
62 #define POLYNOMIAL(xx) (POLYNOMIAL2 (xx) + s1.x)
64 /* The computed polynomial is a variation of the Taylor series expansion for
67 a - a^3/3! + a^5/5! - a^7/7! + a^9/9! + (1 - a^2) * da / 2
69 The constants s1, s2, s3, etc. are pre-computed values of 1/3!, 1/5! and so
70 on. The result is returned to LHS and correction in COR. */
71 #define TAYLOR_SINCOS(xx, a, da, cor) \
73 double t = ((POLYNOMIAL (xx) * (a) - 0.5 * (da)) * (xx) + (da)); \
74 double res = (a) + t; \
75 (cor) = ((a) - res) + t; \
79 /* This is again a variation of the Taylor series expansion with the term
80 x^3/3! expanded into the following for better accuracy:
82 bb * x ^ 3 + 3 * aa * x * x1 * x2 + aa * x1 ^ 3 + aa * x2 ^ 3
84 The correction term is dx and bb + aa = -1/3!
86 #define TAYLOR_SLOW(x0, dx, cor) \
88 static const double th2_36 = 206158430208.0; /* 1.5*2**37 */ \
89 double xx = (x0) * (x0); \
90 double x1 = ((x0) + th2_36) - th2_36; \
91 double y = aa.x * x1 * x1 * x1; \
92 double r = (x0) + y; \
93 double x2 = ((x0) - x1) + (dx); \
94 double t = (((POLYNOMIAL2 (xx) + bb.x) * xx + 3.0 * aa.x * x1 * x2) \
95 * (x0) + aa.x * x2 * x2 * x2 + (dx)); \
96 t = (((x0) - r) + y) + t; \
98 (cor) = (r - res) + t; \
102 #define SINCOS_TABLE_LOOKUP(u, sn, ssn, cs, ccs) \
104 int4 k = u.i[LOW_HALF] << 2; \
105 sn = __sincostab.x[k]; \
106 ssn = __sincostab.x[k + 1]; \
107 cs = __sincostab.x[k + 2]; \
108 ccs = __sincostab.x[k + 3]; \
119 } __sincostab attribute_hidden
;
122 sn3
= -1.66666666666664880952546298448555E-01,
123 sn5
= 8.33333214285722277379541354343671E-03,
124 cs2
= 4.99999999999999999999950396842453E-01,
125 cs4
= -4.16666666666664434524222570944589E-02,
126 cs6
= 1.38888874007937613028114285595617E-03;
128 void __dubsin (double x
, double dx
, double w
[]);
129 void __docos (double x
, double dx
, double w
[]);
130 double __mpsin (double x
, double dx
);
131 double __mpcos (double x
, double dx
);
132 double __mpsin1 (double x
);
133 double __mpcos1 (double x
);
134 static double slow (double x
);
135 static double slow1 (double x
);
136 static double slow2 (double x
);
137 static double sloww (double x
, double dx
, double orig
);
138 static double sloww1 (double x
, double dx
, double orig
);
139 static double sloww2 (double x
, double dx
, double orig
, int n
);
140 static double bsloww (double x
, double dx
, double orig
, int n
);
141 static double bsloww1 (double x
, double dx
, double orig
, int n
);
142 static double bsloww2 (double x
, double dx
, double orig
, int n
);
143 int __branred (double x
, double *a
, double *aa
);
144 static double cslow2 (double x
);
145 static double csloww (double x
, double dx
, double orig
);
146 static double csloww1 (double x
, double dx
, double orig
);
147 static double csloww2 (double x
, double dx
, double orig
, int n
);
149 /* Reduce range of X and compute sin of a + da. K is the amount by which to
150 rotate the quadrants. This allows us to use the same routine to compute cos
151 by simply rotating the quadrants by 1. */
154 reduce_and_compute (double x
, double a
, double da
, unsigned int k
)
157 unsigned int n
= __branred (x
, &a
, &da
);
163 retval
= bsloww (a
, da
, x
, n
);
165 retval
= bsloww1 (a
, da
, x
, n
);
169 retval
= bsloww (-a
, -da
, x
, n
);
171 retval
= bsloww1 (-a
, -da
, x
, n
);
176 retval
= bsloww2 (a
, da
, x
, n
);
182 /*******************************************************************/
183 /* An ultimate sin routine. Given an IEEE double machine number x */
184 /* it computes the correctly rounded (to nearest) value of sin(x) */
185 /*******************************************************************/
190 double xx
, res
, t
, cor
, y
, s
, c
, sn
, ssn
, cs
, ccs
, xn
, a
, da
, db
, eps
, xn1
,
196 SET_RESTORE_ROUND_53BIT (FE_TONEAREST
);
200 k
= 0x7fffffff & m
; /* no sign */
201 if (k
< 0x3e500000) /* if x->0 =>sin(x)=x */
203 /*---------------------------- 2^-26 < |x|< 0.25 ----------------------*/
204 else if (k
< 0x3fd00000)
208 t
= POLYNOMIAL (xx
) * (xx
* x
);
211 retval
= (res
== res
+ 1.07 * cor
) ? res
: slow (x
);
212 } /* else if (k < 0x3fd00000) */
213 /*---------------------------- 0.25<|x|< 0.855469---------------------- */
214 else if (k
< 0x3feb6000)
216 u
.x
= (m
> 0) ? big
.x
+ x
: big
.x
- x
;
217 y
= (m
> 0) ? x
- (u
.x
- big
.x
) : x
+ (u
.x
- big
.x
);
219 s
= y
+ y
* xx
* (sn3
+ xx
* sn5
);
220 c
= xx
* (cs2
+ xx
* (cs4
+ xx
* cs6
));
221 SINCOS_TABLE_LOOKUP (u
, sn
, ssn
, cs
, ccs
);
227 cor
= (ssn
+ s
* ccs
- sn
* c
) + cs
* s
;
229 cor
= (sn
- res
) + cor
;
230 retval
= (res
== res
+ 1.096 * cor
) ? res
: slow1 (x
);
231 } /* else if (k < 0x3feb6000) */
233 /*----------------------- 0.855469 <|x|<2.426265 ----------------------*/
234 else if (k
< 0x400368fd)
237 y
= (m
> 0) ? hp0
.x
- x
: hp0
.x
+ x
;
241 y
= (y
- (u
.x
- big
.x
)) + hp1
.x
;
246 y
= (-hp1
.x
) - (y
+ (u
.x
- big
.x
));
249 s
= y
+ y
* xx
* (sn3
+ xx
* sn5
);
250 c
= xx
* (cs2
+ xx
* (cs4
+ xx
* cs6
));
251 SINCOS_TABLE_LOOKUP (u
, sn
, ssn
, cs
, ccs
);
252 cor
= (ccs
- s
* ssn
- cs
* c
) - sn
* s
;
254 cor
= (cs
- res
) + cor
;
255 retval
= (res
== res
+ 1.020 * cor
) ? ((m
> 0) ? res
: -res
) : slow2 (x
);
256 } /* else if (k < 0x400368fd) */
258 /*-------------------------- 2.426265<|x|< 105414350 ----------------------*/
259 else if (k
< 0x419921FB)
261 t
= (x
* hpinv
.x
+ toint
.x
);
264 y
= (x
- xn
* mp1
.x
) - xn
* mp2
.x
;
265 n
= v
.i
[LOW_HALF
] & 3;
269 eps
= ABS (x
) * 1.2e-30;
272 { /* quarter of unit circle */
284 res
= TAYLOR_SINCOS (xx
, a
, da
, cor
);
285 cor
= (cor
> 0) ? 1.02 * cor
+ eps
: 1.02 * cor
- eps
;
286 retval
= (res
== res
+ cor
) ? res
: sloww (a
, da
, x
);
303 y
= t
- (u
.x
- big
.x
);
305 s
= y
+ (db
+ y
* xx
* (sn3
+ xx
* sn5
));
306 c
= y
* db
+ xx
* (cs2
+ xx
* (cs4
+ xx
* cs6
));
307 SINCOS_TABLE_LOOKUP (u
, sn
, ssn
, cs
, ccs
);
308 cor
= (ssn
+ s
* ccs
- sn
* c
) + cs
* s
;
310 cor
= (sn
- res
) + cor
;
311 cor
= (cor
> 0) ? 1.035 * cor
+ eps
: 1.035 * cor
- eps
;
312 retval
= ((res
== res
+ cor
) ? ((m
) ? res
: -res
)
313 : sloww1 (a
, da
, x
));
325 y
= a
- (u
.x
- big
.x
) + da
;
327 SINCOS_TABLE_LOOKUP (u
, sn
, ssn
, cs
, ccs
);
328 s
= y
+ y
* xx
* (sn3
+ xx
* sn5
);
329 c
= xx
* (cs2
+ xx
* (cs4
+ xx
* cs6
));
330 cor
= (ccs
- s
* ssn
- cs
* c
) - sn
* s
;
332 cor
= (cs
- res
) + cor
;
333 cor
= (cor
> 0) ? 1.025 * cor
+ eps
: 1.025 * cor
- eps
;
334 retval
= ((res
== res
+ cor
) ? ((n
& 2) ? -res
: res
)
335 : sloww2 (a
, da
, x
, n
));
338 } /* else if (k < 0x419921FB ) */
340 /*---------------------105414350 <|x|< 281474976710656 --------------------*/
341 else if (k
< 0x42F00000)
343 t
= (x
* hpinv
.x
+ toint
.x
);
346 xn1
= (xn
+ 8.0e22
) - 8.0e22
;
348 y
= ((((x
- xn1
* mp1
.x
) - xn1
* mp2
.x
) - xn2
* mp1
.x
) - xn2
* mp2
.x
);
349 n
= v
.i
[LOW_HALF
] & 3;
353 da
= (da
- xn2
* pp3
.x
) - xn
* pp4
.x
;
371 res
= TAYLOR_SINCOS (xx
, a
, da
, cor
);
372 cor
= (cor
> 0) ? 1.02 * cor
+ eps
: 1.02 * cor
- eps
;
373 retval
= (res
== res
+ cor
) ? res
: bsloww (a
, da
, x
, n
);
390 y
= t
- (u
.x
- big
.x
);
392 s
= y
+ (db
+ y
* xx
* (sn3
+ xx
* sn5
));
393 c
= y
* db
+ xx
* (cs2
+ xx
* (cs4
+ xx
* cs6
));
394 SINCOS_TABLE_LOOKUP (u
, sn
, ssn
, cs
, ccs
);
395 cor
= (ssn
+ s
* ccs
- sn
* c
) + cs
* s
;
397 cor
= (sn
- res
) + cor
;
398 cor
= (cor
> 0) ? 1.035 * cor
+ eps
: 1.035 * cor
- eps
;
399 retval
= ((res
== res
+ cor
) ? ((m
) ? res
: -res
)
400 : bsloww1 (a
, da
, x
, n
));
412 y
= a
- (u
.x
- big
.x
) + da
;
414 SINCOS_TABLE_LOOKUP (u
, sn
, ssn
, cs
, ccs
);
415 s
= y
+ y
* xx
* (sn3
+ xx
* sn5
);
416 c
= xx
* (cs2
+ xx
* (cs4
+ xx
* cs6
));
417 cor
= (ccs
- s
* ssn
- cs
* c
) - sn
* s
;
419 cor
= (cs
- res
) + cor
;
420 cor
= (cor
> 0) ? 1.025 * cor
+ eps
: 1.025 * cor
- eps
;
421 retval
= ((res
== res
+ cor
) ? ((n
& 2) ? -res
: res
)
422 : bsloww2 (a
, da
, x
, n
));
425 } /* else if (k < 0x42F00000 ) */
427 /* -----------------281474976710656 <|x| <2^1024----------------------------*/
428 else if (k
< 0x7ff00000)
429 retval
= reduce_and_compute (x
, a
, da
, 0);
431 /*--------------------- |x| > 2^1024 ----------------------------------*/
434 if (k
== 0x7ff00000 && u
.i
[LOW_HALF
] == 0)
443 /*******************************************************************/
444 /* An ultimate cos routine. Given an IEEE double machine number x */
445 /* it computes the correctly rounded (to nearest) value of cos(x) */
446 /*******************************************************************/
452 double y
, xx
, res
, t
, cor
, s
, c
, sn
, ssn
, cs
, ccs
, xn
, a
, da
, db
, eps
, xn1
,
459 SET_RESTORE_ROUND_53BIT (FE_TONEAREST
);
465 /* |x|<2^-27 => cos(x)=1 */
469 else if (k
< 0x3feb6000)
470 { /* 2^-27 < |x| < 0.855469 */
473 y
= y
- (u
.x
- big
.x
);
475 s
= y
+ y
* xx
* (sn3
+ xx
* sn5
);
476 c
= xx
* (cs2
+ xx
* (cs4
+ xx
* cs6
));
477 SINCOS_TABLE_LOOKUP (u
, sn
, ssn
, cs
, ccs
);
478 cor
= (ccs
- s
* ssn
- cs
* c
) - sn
* s
;
480 cor
= (cs
- res
) + cor
;
481 retval
= (res
== res
+ 1.020 * cor
) ? res
: cslow2 (x
);
482 } /* else if (k < 0x3feb6000) */
484 else if (k
< 0x400368fd)
485 { /* 0.855469 <|x|<2.426265 */ ;
488 da
= (y
- a
) + hp1
.x
;
492 res
= TAYLOR_SINCOS (xx
, a
, da
, cor
);
493 cor
= (cor
> 0) ? 1.02 * cor
+ 1.0e-31 : 1.02 * cor
- 1.0e-31;
494 retval
= (res
== res
+ cor
) ? res
: csloww (a
, da
, x
);
511 y
= t
- (u
.x
- big
.x
);
513 s
= y
+ (db
+ y
* xx
* (sn3
+ xx
* sn5
));
514 c
= y
* db
+ xx
* (cs2
+ xx
* (cs4
+ xx
* cs6
));
515 SINCOS_TABLE_LOOKUP (u
, sn
, ssn
, cs
, ccs
);
516 cor
= (ssn
+ s
* ccs
- sn
* c
) + cs
* s
;
518 cor
= (sn
- res
) + cor
;
519 cor
= (cor
> 0) ? 1.035 * cor
+ 1.0e-31 : 1.035 * cor
- 1.0e-31;
520 retval
= ((res
== res
+ cor
) ? ((m
) ? res
: -res
)
521 : csloww1 (a
, da
, x
));
524 } /* else if (k < 0x400368fd) */
527 else if (k
< 0x419921FB)
528 { /* 2.426265<|x|< 105414350 */
529 t
= (x
* hpinv
.x
+ toint
.x
);
532 y
= (x
- xn
* mp1
.x
) - xn
* mp2
.x
;
533 n
= v
.i
[LOW_HALF
] & 3;
537 eps
= ABS (x
) * 1.2e-30;
551 res
= TAYLOR_SINCOS (xx
, a
, da
, cor
);
552 cor
= (cor
> 0) ? 1.02 * cor
+ eps
: 1.02 * cor
- eps
;
553 retval
= (res
== res
+ cor
) ? res
: csloww (a
, da
, x
);
570 y
= t
- (u
.x
- big
.x
);
572 s
= y
+ (db
+ y
* xx
* (sn3
+ xx
* sn5
));
573 c
= y
* db
+ xx
* (cs2
+ xx
* (cs4
+ xx
* cs6
));
574 SINCOS_TABLE_LOOKUP (u
, sn
, ssn
, cs
, ccs
);
575 cor
= (ssn
+ s
* ccs
- sn
* c
) + cs
* s
;
577 cor
= (sn
- res
) + cor
;
578 cor
= (cor
> 0) ? 1.035 * cor
+ eps
: 1.035 * cor
- eps
;
579 retval
= ((res
== res
+ cor
) ? ((m
) ? res
: -res
)
580 : csloww1 (a
, da
, x
));
592 y
= a
- (u
.x
- big
.x
) + da
;
594 SINCOS_TABLE_LOOKUP (u
, sn
, ssn
, cs
, ccs
);
595 s
= y
+ y
* xx
* (sn3
+ xx
* sn5
);
596 c
= xx
* (cs2
+ xx
* (cs4
+ xx
* cs6
));
597 cor
= (ccs
- s
* ssn
- cs
* c
) - sn
* s
;
599 cor
= (cs
- res
) + cor
;
600 cor
= (cor
> 0) ? 1.025 * cor
+ eps
: 1.025 * cor
- eps
;
601 retval
= ((res
== res
+ cor
) ? ((n
) ? -res
: res
)
602 : csloww2 (a
, da
, x
, n
));
605 } /* else if (k < 0x419921FB ) */
607 else if (k
< 0x42F00000)
609 t
= (x
* hpinv
.x
+ toint
.x
);
612 xn1
= (xn
+ 8.0e22
) - 8.0e22
;
614 y
= ((((x
- xn1
* mp1
.x
) - xn1
* mp2
.x
) - xn2
* mp1
.x
) - xn2
* mp2
.x
);
615 n
= v
.i
[LOW_HALF
] & 3;
619 da
= (da
- xn2
* pp3
.x
) - xn
* pp4
.x
;
636 res
= TAYLOR_SINCOS (xx
, a
, da
, cor
);
637 cor
= (cor
> 0) ? 1.02 * cor
+ eps
: 1.02 * cor
- eps
;
638 retval
= (res
== res
+ cor
) ? res
: bsloww (a
, da
, x
, n
);
655 y
= t
- (u
.x
- big
.x
);
657 s
= y
+ (db
+ y
* xx
* (sn3
+ xx
* sn5
));
658 c
= y
* db
+ xx
* (cs2
+ xx
* (cs4
+ xx
* cs6
));
659 SINCOS_TABLE_LOOKUP (u
, sn
, ssn
, cs
, ccs
);
660 cor
= (ssn
+ s
* ccs
- sn
* c
) + cs
* s
;
662 cor
= (sn
- res
) + cor
;
663 cor
= (cor
> 0) ? 1.035 * cor
+ eps
: 1.035 * cor
- eps
;
664 retval
= ((res
== res
+ cor
) ? ((m
) ? res
: -res
)
665 : bsloww1 (a
, da
, x
, n
));
677 y
= a
- (u
.x
- big
.x
) + da
;
679 SINCOS_TABLE_LOOKUP (u
, sn
, ssn
, cs
, ccs
);
680 s
= y
+ y
* xx
* (sn3
+ xx
* sn5
);
681 c
= xx
* (cs2
+ xx
* (cs4
+ xx
* cs6
));
682 cor
= (ccs
- s
* ssn
- cs
* c
) - sn
* s
;
684 cor
= (cs
- res
) + cor
;
685 cor
= (cor
> 0) ? 1.025 * cor
+ eps
: 1.025 * cor
- eps
;
686 retval
= ((res
== res
+ cor
) ? ((n
) ? -res
: res
)
687 : bsloww2 (a
, da
, x
, n
));
690 } /* else if (k < 0x42F00000 ) */
692 /* 281474976710656 <|x| <2^1024 */
693 else if (k
< 0x7ff00000)
694 retval
= reduce_and_compute (x
, a
, da
, 1);
698 if (k
== 0x7ff00000 && u
.i
[LOW_HALF
] == 0)
700 retval
= x
/ x
; /* |x| > 2^1024 */
706 /************************************************************************/
707 /* Routine compute sin(x) for 2^-26 < |x|< 0.25 by Taylor with more */
708 /* precision and if still doesn't accurate enough by mpsin or dubsin */
709 /************************************************************************/
715 double res
, cor
, w
[2];
716 res
= TAYLOR_SLOW (x
, 0, cor
);
717 if (res
== res
+ 1.0007 * cor
)
721 __dubsin (ABS (x
), 0, w
);
722 if (w
[0] == w
[0] + 1.000000001 * w
[1])
723 return (x
> 0) ? w
[0] : -w
[0];
725 return (x
> 0) ? __mpsin (x
, 0) : -__mpsin (-x
, 0);
729 /*******************************************************************************/
730 /* Routine compute sin(x) for 0.25<|x|< 0.855469 by __sincostab.tbl and Taylor */
731 /* and if result still doesn't accurate enough by mpsin or dubsin */
732 /*******************************************************************************/
739 double sn
, ssn
, cs
, ccs
, s
, c
, w
[2], y
, y1
, y2
, c1
, c2
, xx
, cor
, res
;
740 static const double t22
= 6291456.0;
743 y
= y
- (u
.x
- big
.x
);
745 s
= y
* xx
* (sn3
+ xx
* sn5
);
746 c
= xx
* (cs2
+ xx
* (cs4
+ xx
* cs6
));
747 SINCOS_TABLE_LOOKUP (u
, sn
, ssn
, cs
, ccs
);
748 y1
= (y
+ t22
) - t22
;
750 c1
= (cs
+ t22
) - t22
;
751 c2
= (cs
- c1
) + ccs
;
752 cor
= (ssn
+ s
* ccs
+ cs
* s
+ c2
* y
+ c1
* y2
) - sn
* c
;
754 cor
= cor
+ ((sn
- y
) + c1
* y1
);
756 cor
= (y
- res
) + cor
;
757 if (res
== res
+ 1.0005 * cor
)
758 return (x
> 0) ? res
: -res
;
761 __dubsin (ABS (x
), 0, w
);
762 if (w
[0] == w
[0] + 1.000000005 * w
[1])
763 return (x
> 0) ? w
[0] : -w
[0];
765 return (x
> 0) ? __mpsin (x
, 0) : -__mpsin (-x
, 0);
769 /**************************************************************************/
770 /* Routine compute sin(x) for 0.855469 <|x|<2.426265 by __sincostab.tbl */
771 /* and if result still doesn't accurate enough by mpsin or dubsin */
772 /**************************************************************************/
778 double sn
, ssn
, cs
, ccs
, s
, c
, w
[2], y
, y1
, y2
, e1
, e2
, xx
, cor
, res
, del
;
779 static const double t22
= 6291456.0;
785 y
= y
- (u
.x
- big
.x
);
791 y
= -(y
+ (u
.x
- big
.x
));
795 s
= y
* xx
* (sn3
+ xx
* sn5
);
796 c
= y
* del
+ xx
* (cs2
+ xx
* (cs4
+ xx
* cs6
));
797 SINCOS_TABLE_LOOKUP (u
, sn
, ssn
, cs
, ccs
);
798 y1
= (y
+ t22
) - t22
;
800 e1
= (sn
+ t22
) - t22
;
801 e2
= (sn
- e1
) + ssn
;
802 cor
= (ccs
- cs
* c
- e1
* y2
- e2
* y
) - sn
* s
;
804 cor
= cor
+ ((cs
- y
) - e1
* y1
);
806 cor
= (y
- res
) + cor
;
807 if (res
== res
+ 1.0005 * cor
)
808 return (x
> 0) ? res
: -res
;
813 y2
= (y
- y1
) - hp1
.x
;
815 if (w
[0] == w
[0] + 1.000000005 * w
[1])
816 return (x
> 0) ? w
[0] : -w
[0];
818 return (x
> 0) ? __mpsin (x
, 0) : -__mpsin (-x
, 0);
822 /***************************************************************************/
823 /* Routine compute sin(x+dx) (Double-Length number) where x is small enough*/
824 /* to use Taylor series around zero and (x+dx) */
825 /* in first or third quarter of unit circle.Routine receive also */
826 /* (right argument) the original value of x for computing error of */
827 /* result.And if result not accurate enough routine calls mpsin1 or dubsin */
828 /***************************************************************************/
832 sloww (double x
, double dx
, double orig
)
834 double y
, t
, res
, cor
, w
[2], a
, da
, xn
;
841 res
= TAYLOR_SLOW (x
, dx
, cor
);
844 0) ? 1.0005 * cor
+ ABS (orig
) * 3.1e-30 : 1.0005 * cor
-
845 ABS (orig
) * 3.1e-30;
846 if (res
== res
+ cor
)
850 (x
> 0) ? __dubsin (x
, dx
, w
) : __dubsin (-x
, -dx
, w
);
852 cor
= 1.000000001 * w
[1] + ABS (orig
) * 1.1e-30;
854 cor
= 1.000000001 * w
[1] - ABS (orig
) * 1.1e-30;
856 if (w
[0] == w
[0] + cor
)
857 return (x
> 0) ? w
[0] : -w
[0];
860 t
= (orig
* hpinv
.x
+ toint
.x
);
863 y
= (orig
- xn
* mp1
.x
) - xn
* mp2
.x
;
864 n
= v
.i
[LOW_HALF
] & 3;
870 da
= ((t
- a
) - y
) + da
;
876 (a
> 0) ? __dubsin (a
, da
, w
) : __dubsin (-a
, -da
, w
);
878 cor
= 1.000000001 * w
[1] + ABS (orig
) * 1.1e-40;
880 cor
= 1.000000001 * w
[1] - ABS (orig
) * 1.1e-40;
882 if (w
[0] == w
[0] + cor
)
883 return (a
> 0) ? w
[0] : -w
[0];
885 return __mpsin1 (orig
);
890 /***************************************************************************/
891 /* Routine compute sin(x+dx) (Double-Length number) where x in first or */
892 /* third quarter of unit circle.Routine receive also (right argument) the */
893 /* original value of x for computing error of result.And if result not */
894 /* accurate enough routine calls mpsin1 or dubsin */
895 /***************************************************************************/
899 sloww1 (double x
, double dx
, double orig
)
902 double sn
, ssn
, cs
, ccs
, s
, c
, w
[2], y
, y1
, y2
, c1
, c2
, xx
, cor
, res
;
903 static const double t22
= 6291456.0;
907 y
= y
- (u
.x
- big
.x
);
908 dx
= (x
> 0) ? dx
: -dx
;
910 s
= y
* xx
* (sn3
+ xx
* sn5
);
911 c
= xx
* (cs2
+ xx
* (cs4
+ xx
* cs6
));
912 SINCOS_TABLE_LOOKUP (u
, sn
, ssn
, cs
, ccs
);
913 y1
= (y
+ t22
) - t22
;
915 c1
= (cs
+ t22
) - t22
;
916 c2
= (cs
- c1
) + ccs
;
917 cor
= (ssn
+ s
* ccs
+ cs
* s
+ c2
* y
+ c1
* y2
- sn
* y
* dx
) - sn
* c
;
919 cor
= cor
+ ((sn
- y
) + c1
* y1
);
921 cor
= (y
- res
) + cor
;
924 cor
= 1.0005 * cor
+ 3.1e-30 * ABS (orig
);
926 cor
= 1.0005 * cor
- 3.1e-30 * ABS (orig
);
928 if (res
== res
+ cor
)
929 return (x
> 0) ? res
: -res
;
932 __dubsin (ABS (x
), dx
, w
);
935 cor
= 1.000000005 * w
[1] + 1.1e-30 * ABS (orig
);
937 cor
= 1.000000005 * w
[1] - 1.1e-30 * ABS (orig
);
939 if (w
[0] == w
[0] + cor
)
940 return (x
> 0) ? w
[0] : -w
[0];
942 return __mpsin1 (orig
);
946 /***************************************************************************/
947 /* Routine compute sin(x+dx) (Double-Length number) where x in second or */
948 /* fourth quarter of unit circle.Routine receive also the original value */
949 /* and quarter(n= 1or 3)of x for computing error of result.And if result not*/
950 /* accurate enough routine calls mpsin1 or dubsin */
951 /***************************************************************************/
955 sloww2 (double x
, double dx
, double orig
, int n
)
958 double sn
, ssn
, cs
, ccs
, s
, c
, w
[2], y
, y1
, y2
, e1
, e2
, xx
, cor
, res
;
959 static const double t22
= 6291456.0;
963 y
= y
- (u
.x
- big
.x
);
964 dx
= (x
> 0) ? dx
: -dx
;
966 s
= y
* xx
* (sn3
+ xx
* sn5
);
967 c
= y
* dx
+ xx
* (cs2
+ xx
* (cs4
+ xx
* cs6
));
968 SINCOS_TABLE_LOOKUP (u
, sn
, ssn
, cs
, ccs
);
970 y1
= (y
+ t22
) - t22
;
972 e1
= (sn
+ t22
) - t22
;
973 e2
= (sn
- e1
) + ssn
;
974 cor
= (ccs
- cs
* c
- e1
* y2
- e2
* y
) - sn
* s
;
976 cor
= cor
+ ((cs
- y
) - e1
* y1
);
978 cor
= (y
- res
) + cor
;
981 cor
= 1.0005 * cor
+ 3.1e-30 * ABS (orig
);
983 cor
= 1.0005 * cor
- 3.1e-30 * ABS (orig
);
985 if (res
== res
+ cor
)
986 return (n
& 2) ? -res
: res
;
989 __docos (ABS (x
), dx
, w
);
992 cor
= 1.000000005 * w
[1] + 1.1e-30 * ABS (orig
);
994 cor
= 1.000000005 * w
[1] - 1.1e-30 * ABS (orig
);
996 if (w
[0] == w
[0] + cor
)
997 return (n
& 2) ? -w
[0] : w
[0];
999 return __mpsin1 (orig
);
1003 /***************************************************************************/
1004 /* Routine compute sin(x+dx) or cos(x+dx) (Double-Length number) where x */
1005 /* is small enough to use Taylor series around zero and (x+dx) */
1006 /* in first or third quarter of unit circle.Routine receive also */
1007 /* (right argument) the original value of x for computing error of */
1008 /* result.And if result not accurate enough routine calls other routines */
1009 /***************************************************************************/
1013 bsloww (double x
, double dx
, double orig
, int n
)
1015 double res
, cor
, w
[2];
1017 res
= TAYLOR_SLOW (x
, dx
, cor
);
1018 cor
= (cor
> 0) ? 1.0005 * cor
+ 1.1e-24 : 1.0005 * cor
- 1.1e-24;
1019 if (res
== res
+ cor
)
1023 (x
> 0) ? __dubsin (x
, dx
, w
) : __dubsin (-x
, -dx
, w
);
1025 cor
= 1.000000001 * w
[1] + 1.1e-24;
1027 cor
= 1.000000001 * w
[1] - 1.1e-24;
1028 if (w
[0] == w
[0] + cor
)
1029 return (x
> 0) ? w
[0] : -w
[0];
1031 return (n
& 1) ? __mpcos1 (orig
) : __mpsin1 (orig
);
1035 /***************************************************************************/
1036 /* Routine compute sin(x+dx) or cos(x+dx) (Double-Length number) where x */
1037 /* in first or third quarter of unit circle.Routine receive also */
1038 /* (right argument) the original value of x for computing error of result.*/
1039 /* And if result not accurate enough routine calls other routines */
1040 /***************************************************************************/
1044 bsloww1 (double x
, double dx
, double orig
, int n
)
1047 double sn
, ssn
, cs
, ccs
, s
, c
, w
[2], y
, y1
, y2
, c1
, c2
, xx
, cor
, res
;
1048 static const double t22
= 6291456.0;
1052 y
= y
- (u
.x
- big
.x
);
1053 dx
= (x
> 0) ? dx
: -dx
;
1055 s
= y
* xx
* (sn3
+ xx
* sn5
);
1056 c
= xx
* (cs2
+ xx
* (cs4
+ xx
* cs6
));
1057 SINCOS_TABLE_LOOKUP (u
, sn
, ssn
, cs
, ccs
);
1058 y1
= (y
+ t22
) - t22
;
1060 c1
= (cs
+ t22
) - t22
;
1061 c2
= (cs
- c1
) + ccs
;
1062 cor
= (ssn
+ s
* ccs
+ cs
* s
+ c2
* y
+ c1
* y2
- sn
* y
* dx
) - sn
* c
;
1064 cor
= cor
+ ((sn
- y
) + c1
* y1
);
1066 cor
= (y
- res
) + cor
;
1067 cor
= (cor
> 0) ? 1.0005 * cor
+ 1.1e-24 : 1.0005 * cor
- 1.1e-24;
1068 if (res
== res
+ cor
)
1069 return (x
> 0) ? res
: -res
;
1072 __dubsin (ABS (x
), dx
, w
);
1075 cor
= 1.000000005 * w
[1] + 1.1e-24;
1077 cor
= 1.000000005 * w
[1] - 1.1e-24;
1079 if (w
[0] == w
[0] + cor
)
1080 return (x
> 0) ? w
[0] : -w
[0];
1082 return (n
& 1) ? __mpcos1 (orig
) : __mpsin1 (orig
);
1086 /***************************************************************************/
1087 /* Routine compute sin(x+dx) or cos(x+dx) (Double-Length number) where x */
1088 /* in second or fourth quarter of unit circle.Routine receive also the */
1089 /* original value and quarter(n= 1or 3)of x for computing error of result. */
1090 /* And if result not accurate enough routine calls other routines */
1091 /***************************************************************************/
1095 bsloww2 (double x
, double dx
, double orig
, int n
)
1098 double sn
, ssn
, cs
, ccs
, s
, c
, w
[2], y
, y1
, y2
, e1
, e2
, xx
, cor
, res
;
1099 static const double t22
= 6291456.0;
1103 y
= y
- (u
.x
- big
.x
);
1104 dx
= (x
> 0) ? dx
: -dx
;
1106 s
= y
* xx
* (sn3
+ xx
* sn5
);
1107 c
= y
* dx
+ xx
* (cs2
+ xx
* (cs4
+ xx
* cs6
));
1108 SINCOS_TABLE_LOOKUP (u
, sn
, ssn
, cs
, ccs
);
1110 y1
= (y
+ t22
) - t22
;
1112 e1
= (sn
+ t22
) - t22
;
1113 e2
= (sn
- e1
) + ssn
;
1114 cor
= (ccs
- cs
* c
- e1
* y2
- e2
* y
) - sn
* s
;
1116 cor
= cor
+ ((cs
- y
) - e1
* y1
);
1118 cor
= (y
- res
) + cor
;
1119 cor
= (cor
> 0) ? 1.0005 * cor
+ 1.1e-24 : 1.0005 * cor
- 1.1e-24;
1120 if (res
== res
+ cor
)
1121 return (n
& 2) ? -res
: res
;
1124 __docos (ABS (x
), dx
, w
);
1127 cor
= 1.000000005 * w
[1] + 1.1e-24;
1129 cor
= 1.000000005 * w
[1] - 1.1e-24;
1131 if (w
[0] == w
[0] + cor
)
1132 return (n
& 2) ? -w
[0] : w
[0];
1134 return (n
& 1) ? __mpsin1 (orig
) : __mpcos1 (orig
);
1138 /************************************************************************/
1139 /* Routine compute cos(x) for 2^-27 < |x|< 0.25 by Taylor with more */
1140 /* precision and if still doesn't accurate enough by mpcos or docos */
1141 /************************************************************************/
1148 double sn
, ssn
, cs
, ccs
, s
, c
, w
[2], y
, y1
, y2
, e1
, e2
, xx
, cor
, res
;
1149 static const double t22
= 6291456.0;
1153 y
= y
- (u
.x
- big
.x
);
1155 s
= y
* xx
* (sn3
+ xx
* sn5
);
1156 c
= xx
* (cs2
+ xx
* (cs4
+ xx
* cs6
));
1157 SINCOS_TABLE_LOOKUP (u
, sn
, ssn
, cs
, ccs
);
1158 y1
= (y
+ t22
) - t22
;
1160 e1
= (sn
+ t22
) - t22
;
1161 e2
= (sn
- e1
) + ssn
;
1162 cor
= (ccs
- cs
* c
- e1
* y2
- e2
* y
) - sn
* s
;
1164 cor
= cor
+ ((cs
- y
) - e1
* y1
);
1166 cor
= (y
- res
) + cor
;
1167 if (res
== res
+ 1.0005 * cor
)
1173 if (w
[0] == w
[0] + 1.000000005 * w
[1])
1176 return __mpcos (x
, 0);
1180 /***************************************************************************/
1181 /* Routine compute cos(x+dx) (Double-Length number) where x is small enough*/
1182 /* to use Taylor series around zero and (x+dx) .Routine receive also */
1183 /* (right argument) the original value of x for computing error of */
1184 /* result.And if result not accurate enough routine calls other routines */
1185 /***************************************************************************/
1190 csloww (double x
, double dx
, double orig
)
1192 double y
, t
, res
, cor
, w
[2], a
, da
, xn
;
1201 t
= TAYLOR_SLOW (x
, dx
, cor
);
1204 cor
= 1.0005 * cor
+ ABS (orig
) * 3.1e-30;
1206 cor
= 1.0005 * cor
- ABS (orig
) * 3.1e-30;
1208 if (res
== res
+ cor
)
1212 (x
> 0) ? __dubsin (x
, dx
, w
) : __dubsin (-x
, -dx
, w
);
1215 cor
= 1.000000001 * w
[1] + ABS (orig
) * 1.1e-30;
1217 cor
= 1.000000001 * w
[1] - ABS (orig
) * 1.1e-30;
1219 if (w
[0] == w
[0] + cor
)
1220 return (x
> 0) ? w
[0] : -w
[0];
1223 t
= (orig
* hpinv
.x
+ toint
.x
);
1226 y
= (orig
- xn
* mp1
.x
) - xn
* mp2
.x
;
1227 n
= v
.i
[LOW_HALF
] & 3;
1233 da
= ((t
- a
) - y
) + da
;
1239 (a
> 0) ? __dubsin (a
, da
, w
) : __dubsin (-a
, -da
, w
);
1242 cor
= 1.000000001 * w
[1] + ABS (orig
) * 1.1e-40;
1244 cor
= 1.000000001 * w
[1] - ABS (orig
) * 1.1e-40;
1246 if (w
[0] == w
[0] + cor
)
1247 return (a
> 0) ? w
[0] : -w
[0];
1249 return __mpcos1 (orig
);
1254 /***************************************************************************/
1255 /* Routine compute sin(x+dx) (Double-Length number) where x in first or */
1256 /* third quarter of unit circle.Routine receive also (right argument) the */
1257 /* original value of x for computing error of result.And if result not */
1258 /* accurate enough routine calls other routines */
1259 /***************************************************************************/
1263 csloww1 (double x
, double dx
, double orig
)
1266 double sn
, ssn
, cs
, ccs
, s
, c
, w
[2], y
, y1
, y2
, c1
, c2
, xx
, cor
, res
;
1267 static const double t22
= 6291456.0;
1271 y
= y
- (u
.x
- big
.x
);
1272 dx
= (x
> 0) ? dx
: -dx
;
1274 s
= y
* xx
* (sn3
+ xx
* sn5
);
1275 c
= xx
* (cs2
+ xx
* (cs4
+ xx
* cs6
));
1276 SINCOS_TABLE_LOOKUP (u
, sn
, ssn
, cs
, ccs
);
1277 y1
= (y
+ t22
) - t22
;
1279 c1
= (cs
+ t22
) - t22
;
1280 c2
= (cs
- c1
) + ccs
;
1281 cor
= (ssn
+ s
* ccs
+ cs
* s
+ c2
* y
+ c1
* y2
- sn
* y
* dx
) - sn
* c
;
1283 cor
= cor
+ ((sn
- y
) + c1
* y1
);
1285 cor
= (y
- res
) + cor
;
1288 cor
= 1.0005 * cor
+ 3.1e-30 * ABS (orig
);
1290 cor
= 1.0005 * cor
- 3.1e-30 * ABS (orig
);
1292 if (res
== res
+ cor
)
1293 return (x
> 0) ? res
: -res
;
1296 __dubsin (ABS (x
), dx
, w
);
1298 cor
= 1.000000005 * w
[1] + 1.1e-30 * ABS (orig
);
1300 cor
= 1.000000005 * w
[1] - 1.1e-30 * ABS (orig
);
1301 if (w
[0] == w
[0] + cor
)
1302 return (x
> 0) ? w
[0] : -w
[0];
1304 return __mpcos1 (orig
);
1309 /***************************************************************************/
1310 /* Routine compute sin(x+dx) (Double-Length number) where x in second or */
1311 /* fourth quarter of unit circle.Routine receive also the original value */
1312 /* and quarter(n= 1or 3)of x for computing error of result.And if result not*/
1313 /* accurate enough routine calls other routines */
1314 /***************************************************************************/
1318 csloww2 (double x
, double dx
, double orig
, int n
)
1321 double sn
, ssn
, cs
, ccs
, s
, c
, w
[2], y
, y1
, y2
, e1
, e2
, xx
, cor
, res
;
1322 static const double t22
= 6291456.0;
1326 y
= y
- (u
.x
- big
.x
);
1327 dx
= (x
> 0) ? dx
: -dx
;
1329 s
= y
* xx
* (sn3
+ xx
* sn5
);
1330 c
= y
* dx
+ xx
* (cs2
+ xx
* (cs4
+ xx
* cs6
));
1331 SINCOS_TABLE_LOOKUP (u
, sn
, ssn
, cs
, ccs
);
1333 y1
= (y
+ t22
) - t22
;
1335 e1
= (sn
+ t22
) - t22
;
1336 e2
= (sn
- e1
) + ssn
;
1337 cor
= (ccs
- cs
* c
- e1
* y2
- e2
* y
) - sn
* s
;
1339 cor
= cor
+ ((cs
- y
) - e1
* y1
);
1341 cor
= (y
- res
) + cor
;
1344 cor
= 1.0005 * cor
+ 3.1e-30 * ABS (orig
);
1346 cor
= 1.0005 * cor
- 3.1e-30 * ABS (orig
);
1348 if (res
== res
+ cor
)
1349 return (n
) ? -res
: res
;
1352 __docos (ABS (x
), dx
, w
);
1354 cor
= 1.000000005 * w
[1] + 1.1e-30 * ABS (orig
);
1356 cor
= 1.000000005 * w
[1] - 1.1e-30 * ABS (orig
);
1357 if (w
[0] == w
[0] + cor
)
1358 return (n
) ? -w
[0] : w
[0];
1360 return __mpcos1 (orig
);
1365 weak_alias (__cos
, cos
)
1366 # ifdef NO_LONG_DOUBLE
1367 strong_alias (__cos
, __cosl
)
1368 weak_alias (__cos
, cosl
)
1372 weak_alias (__sin
, sin
)
1373 # ifdef NO_LONG_DOUBLE
1374 strong_alias (__sin
, __sinl
)
1375 weak_alias (__sin
, sinl
)