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 * (xx) + s4) * (xx) + s3) * (xx) + s2) * (xx))
61 #define POLYNOMIAL(xx) (POLYNOMIAL2 (xx) + s1)
63 /* The computed polynomial is a variation of the Taylor series expansion for
66 a - a^3/3! + a^5/5! - a^7/7! + a^9/9! + (1 - a^2) * da / 2
68 The constants s1, s2, s3, etc. are pre-computed values of 1/3!, 1/5! and so
69 on. The result is returned to LHS and correction in COR. */
70 #define TAYLOR_SIN(xx, a, da, cor) \
72 double t = ((POLYNOMIAL (xx) * (a) - 0.5 * (da)) * (xx) + (da)); \
73 double res = (a) + t; \
74 (cor) = ((a) - res) + t; \
78 /* This is again a variation of the Taylor series expansion with the term
79 x^3/3! expanded into the following for better accuracy:
81 bb * x ^ 3 + 3 * aa * x * x1 * x2 + aa * x1 ^ 3 + aa * x2 ^ 3
83 The correction term is dx and bb + aa = -1/3!
85 #define TAYLOR_SLOW(x0, dx, cor) \
87 static const double th2_36 = 206158430208.0; /* 1.5*2**37 */ \
88 double xx = (x0) * (x0); \
89 double x1 = ((x0) + th2_36) - th2_36; \
90 double y = aa * x1 * x1 * x1; \
91 double r = (x0) + y; \
92 double x2 = ((x0) - x1) + (dx); \
93 double t = (((POLYNOMIAL2 (xx) + bb) * xx + 3.0 * aa * x1 * x2) \
94 * (x0) + aa * x2 * x2 * x2 + (dx)); \
95 t = (((x0) - r) + y) + t; \
97 (cor) = (r - res) + t; \
101 #define SINCOS_TABLE_LOOKUP(u, sn, ssn, cs, ccs) \
103 int4 k = u.i[LOW_HALF] << 2; \
104 sn = __sincostab.x[k]; \
105 ssn = __sincostab.x[k + 1]; \
106 cs = __sincostab.x[k + 2]; \
107 ccs = __sincostab.x[k + 3]; \
118 } __sincostab attribute_hidden
;
121 sn3
= -1.66666666666664880952546298448555E-01,
122 sn5
= 8.33333214285722277379541354343671E-03,
123 cs2
= 4.99999999999999999999950396842453E-01,
124 cs4
= -4.16666666666664434524222570944589E-02,
125 cs6
= 1.38888874007937613028114285595617E-03;
127 static const double t22
= 0x1.8p22
;
129 void __dubsin (double x
, double dx
, double w
[]);
130 void __docos (double x
, double dx
, double w
[]);
131 double __mpsin (double x
, double dx
, bool reduce_range
);
132 double __mpcos (double x
, double dx
, bool reduce_range
);
133 static double slow (double x
);
134 static double slow1 (double x
);
135 static double slow2 (double x
);
136 static double sloww (double x
, double dx
, double orig
);
137 static double sloww1 (double x
, double dx
, double orig
);
138 static double sloww2 (double x
, double dx
, double orig
, int n
);
139 static double bsloww (double x
, double dx
, double orig
, int n
);
140 static double bsloww1 (double x
, double dx
, double orig
, int n
);
141 static double bsloww2 (double x
, double dx
, double orig
, int n
);
142 int __branred (double x
, double *a
, double *aa
);
143 static double cslow2 (double x
);
144 static double csloww (double x
, double dx
, double orig
);
145 static double csloww1 (double x
, double dx
, double orig
);
146 static double csloww2 (double x
, double dx
, double orig
, int n
);
148 /* Reduce range of X and compute sin of a + da. K is the amount by which to
149 rotate the quadrants. This allows us to use the same routine to compute cos
150 by simply rotating the quadrants by 1. */
153 reduce_and_compute (double x
, unsigned int k
)
155 double retval
= 0, a
, da
;
156 unsigned int n
= __branred (x
, &a
, &da
);
162 retval
= bsloww (a
, da
, x
, n
);
164 retval
= bsloww1 (a
, da
, x
, n
);
168 retval
= bsloww (-a
, -da
, x
, n
);
170 retval
= bsloww1 (-a
, -da
, x
, n
);
175 retval
= bsloww2 (a
, da
, x
, n
);
181 /*******************************************************************/
182 /* An ultimate sin routine. Given an IEEE double machine number x */
183 /* it computes the correctly rounded (to nearest) value of sin(x) */
184 /*******************************************************************/
189 double xx
, res
, t
, cor
, y
, s
, c
, sn
, ssn
, cs
, ccs
, xn
, a
, da
, db
, eps
, xn1
,
195 SET_RESTORE_ROUND_53BIT (FE_TONEAREST
);
199 k
= 0x7fffffff & m
; /* no sign */
200 if (k
< 0x3e500000) /* if x->0 =>sin(x)=x */
202 /*---------------------------- 2^-26 < |x|< 0.25 ----------------------*/
203 else if (k
< 0x3fd00000)
207 t
= POLYNOMIAL (xx
) * (xx
* x
);
210 retval
= (res
== res
+ 1.07 * cor
) ? res
: slow (x
);
211 } /* else if (k < 0x3fd00000) */
212 /*---------------------------- 0.25<|x|< 0.855469---------------------- */
213 else if (k
< 0x3feb6000)
215 u
.x
= (m
> 0) ? big
+ x
: big
- x
;
216 y
= (m
> 0) ? x
- (u
.x
- big
) : x
+ (u
.x
- big
);
218 s
= y
+ y
* xx
* (sn3
+ xx
* sn5
);
219 c
= xx
* (cs2
+ xx
* (cs4
+ xx
* cs6
));
220 SINCOS_TABLE_LOOKUP (u
, sn
, ssn
, cs
, ccs
);
226 cor
= (ssn
+ s
* ccs
- sn
* c
) + cs
* s
;
228 cor
= (sn
- res
) + cor
;
229 retval
= (res
== res
+ 1.096 * cor
) ? res
: slow1 (x
);
230 } /* else if (k < 0x3feb6000) */
232 /*----------------------- 0.855469 <|x|<2.426265 ----------------------*/
233 else if (k
< 0x400368fd)
236 y
= (m
> 0) ? hp0
- x
: hp0
+ x
;
240 y
= (y
- (u
.x
- big
)) + hp1
;
245 y
= (-hp1
) - (y
+ (u
.x
- big
));
248 s
= y
+ y
* xx
* (sn3
+ xx
* sn5
);
249 c
= xx
* (cs2
+ xx
* (cs4
+ xx
* cs6
));
250 SINCOS_TABLE_LOOKUP (u
, sn
, ssn
, cs
, ccs
);
251 cor
= (ccs
- s
* ssn
- cs
* c
) - sn
* s
;
253 cor
= (cs
- res
) + cor
;
254 retval
= (res
== res
+ 1.020 * cor
) ? ((m
> 0) ? res
: -res
) : slow2 (x
);
255 } /* else if (k < 0x400368fd) */
257 /*-------------------------- 2.426265<|x|< 105414350 ----------------------*/
258 else if (k
< 0x419921FB)
260 t
= (x
* hpinv
+ toint
);
263 y
= (x
- xn
* mp1
) - xn
* mp2
;
264 n
= v
.i
[LOW_HALF
] & 3;
268 eps
= ABS (x
) * 1.2e-30;
271 { /* quarter of unit circle */
283 res
= TAYLOR_SIN (xx
, a
, da
, cor
);
284 cor
= (cor
> 0) ? 1.02 * cor
+ eps
: 1.02 * cor
- eps
;
285 retval
= (res
== res
+ cor
) ? res
: sloww (a
, da
, x
);
303 s
= y
+ (da
+ y
* xx
* (sn3
+ xx
* sn5
));
304 c
= y
* da
+ xx
* (cs2
+ xx
* (cs4
+ xx
* cs6
));
305 SINCOS_TABLE_LOOKUP (u
, sn
, ssn
, cs
, ccs
);
306 cor
= (ssn
+ s
* ccs
- sn
* c
) + cs
* s
;
308 cor
= (sn
- res
) + cor
;
309 cor
= (cor
> 0) ? 1.035 * cor
+ eps
: 1.035 * cor
- eps
;
310 retval
= ((res
== res
+ cor
) ? ((m
) ? res
: -res
)
311 : sloww1 (a
, da
, x
));
323 y
= a
- (u
.x
- big
) + da
;
325 SINCOS_TABLE_LOOKUP (u
, sn
, ssn
, cs
, ccs
);
326 s
= y
+ y
* xx
* (sn3
+ xx
* sn5
);
327 c
= xx
* (cs2
+ xx
* (cs4
+ xx
* cs6
));
328 cor
= (ccs
- s
* ssn
- cs
* c
) - sn
* s
;
330 cor
= (cs
- res
) + cor
;
331 cor
= (cor
> 0) ? 1.025 * cor
+ eps
: 1.025 * cor
- eps
;
332 retval
= ((res
== res
+ cor
) ? ((n
& 2) ? -res
: res
)
333 : sloww2 (a
, da
, x
, n
));
336 } /* else if (k < 0x419921FB ) */
338 /*---------------------105414350 <|x|< 281474976710656 --------------------*/
339 else if (k
< 0x42F00000)
341 t
= (x
* hpinv
+ toint
);
344 xn1
= (xn
+ 8.0e22
) - 8.0e22
;
346 y
= ((((x
- xn1
* mp1
) - xn1
* mp2
) - xn2
* mp1
) - xn2
* mp2
);
347 n
= v
.i
[LOW_HALF
] & 3;
351 da
= (da
- xn2
* pp3
) - xn
* pp4
;
369 res
= TAYLOR_SIN (xx
, a
, da
, cor
);
370 cor
= (cor
> 0) ? 1.02 * cor
+ eps
: 1.02 * cor
- eps
;
371 retval
= (res
== res
+ cor
) ? res
: bsloww (a
, da
, x
, n
);
390 s
= y
+ (db
+ y
* xx
* (sn3
+ xx
* sn5
));
391 c
= y
* db
+ xx
* (cs2
+ xx
* (cs4
+ xx
* cs6
));
392 SINCOS_TABLE_LOOKUP (u
, sn
, ssn
, cs
, ccs
);
393 cor
= (ssn
+ s
* ccs
- sn
* c
) + cs
* s
;
395 cor
= (sn
- res
) + cor
;
396 cor
= (cor
> 0) ? 1.035 * cor
+ eps
: 1.035 * cor
- eps
;
397 retval
= ((res
== res
+ cor
) ? ((m
) ? res
: -res
)
398 : bsloww1 (a
, da
, x
, n
));
410 y
= a
- (u
.x
- big
) + da
;
412 SINCOS_TABLE_LOOKUP (u
, sn
, ssn
, cs
, ccs
);
413 s
= y
+ y
* xx
* (sn3
+ xx
* sn5
);
414 c
= xx
* (cs2
+ xx
* (cs4
+ xx
* cs6
));
415 cor
= (ccs
- s
* ssn
- cs
* c
) - sn
* s
;
417 cor
= (cs
- res
) + cor
;
418 cor
= (cor
> 0) ? 1.025 * cor
+ eps
: 1.025 * cor
- eps
;
419 retval
= ((res
== res
+ cor
) ? ((n
& 2) ? -res
: res
)
420 : bsloww2 (a
, da
, x
, n
));
423 } /* else if (k < 0x42F00000 ) */
425 /* -----------------281474976710656 <|x| <2^1024----------------------------*/
426 else if (k
< 0x7ff00000)
427 retval
= reduce_and_compute (x
, 0);
429 /*--------------------- |x| > 2^1024 ----------------------------------*/
432 if (k
== 0x7ff00000 && u
.i
[LOW_HALF
] == 0)
441 /*******************************************************************/
442 /* An ultimate cos routine. Given an IEEE double machine number x */
443 /* it computes the correctly rounded (to nearest) value of cos(x) */
444 /*******************************************************************/
450 double y
, xx
, res
, t
, cor
, s
, c
, sn
, ssn
, cs
, ccs
, xn
, a
, da
, db
, eps
, xn1
,
457 SET_RESTORE_ROUND_53BIT (FE_TONEAREST
);
463 /* |x|<2^-27 => cos(x)=1 */
467 else if (k
< 0x3feb6000)
468 { /* 2^-27 < |x| < 0.855469 */
473 s
= y
+ y
* xx
* (sn3
+ xx
* sn5
);
474 c
= xx
* (cs2
+ xx
* (cs4
+ xx
* cs6
));
475 SINCOS_TABLE_LOOKUP (u
, sn
, ssn
, cs
, ccs
);
476 cor
= (ccs
- s
* ssn
- cs
* c
) - sn
* s
;
478 cor
= (cs
- res
) + cor
;
479 retval
= (res
== res
+ 1.020 * cor
) ? res
: cslow2 (x
);
480 } /* else if (k < 0x3feb6000) */
482 else if (k
< 0x400368fd)
483 { /* 0.855469 <|x|<2.426265 */ ;
490 res
= TAYLOR_SIN (xx
, a
, da
, cor
);
491 cor
= (cor
> 0) ? 1.02 * cor
+ 1.0e-31 : 1.02 * cor
- 1.0e-31;
492 retval
= (res
== res
+ cor
) ? res
: csloww (a
, da
, x
);
510 s
= y
+ (da
+ y
* xx
* (sn3
+ xx
* sn5
));
511 c
= y
* da
+ xx
* (cs2
+ xx
* (cs4
+ xx
* cs6
));
512 SINCOS_TABLE_LOOKUP (u
, sn
, ssn
, cs
, ccs
);
513 cor
= (ssn
+ s
* ccs
- sn
* c
) + cs
* s
;
515 cor
= (sn
- res
) + cor
;
516 cor
= (cor
> 0) ? 1.035 * cor
+ 1.0e-31 : 1.035 * cor
- 1.0e-31;
517 retval
= ((res
== res
+ cor
) ? ((m
) ? res
: -res
)
518 : csloww1 (a
, da
, x
));
521 } /* else if (k < 0x400368fd) */
524 else if (k
< 0x419921FB)
525 { /* 2.426265<|x|< 105414350 */
526 t
= (x
* hpinv
+ toint
);
529 y
= (x
- xn
* mp1
) - xn
* mp2
;
530 n
= v
.i
[LOW_HALF
] & 3;
534 eps
= ABS (x
) * 1.2e-30;
548 res
= TAYLOR_SIN (xx
, a
, da
, cor
);
549 cor
= (cor
> 0) ? 1.02 * cor
+ eps
: 1.02 * cor
- eps
;
550 retval
= (res
== res
+ cor
) ? res
: csloww (a
, da
, x
);
568 s
= y
+ (da
+ y
* xx
* (sn3
+ xx
* sn5
));
569 c
= y
* da
+ xx
* (cs2
+ xx
* (cs4
+ xx
* cs6
));
570 SINCOS_TABLE_LOOKUP (u
, sn
, ssn
, cs
, ccs
);
571 cor
= (ssn
+ s
* ccs
- sn
* c
) + cs
* s
;
573 cor
= (sn
- res
) + cor
;
574 cor
= (cor
> 0) ? 1.035 * cor
+ eps
: 1.035 * cor
- eps
;
575 retval
= ((res
== res
+ cor
) ? ((m
) ? res
: -res
)
576 : csloww1 (a
, da
, x
));
588 y
= a
- (u
.x
- big
) + da
;
590 SINCOS_TABLE_LOOKUP (u
, sn
, ssn
, cs
, ccs
);
591 s
= y
+ y
* xx
* (sn3
+ xx
* sn5
);
592 c
= xx
* (cs2
+ xx
* (cs4
+ xx
* cs6
));
593 cor
= (ccs
- s
* ssn
- cs
* c
) - sn
* s
;
595 cor
= (cs
- res
) + cor
;
596 cor
= (cor
> 0) ? 1.025 * cor
+ eps
: 1.025 * cor
- eps
;
597 retval
= ((res
== res
+ cor
) ? ((n
) ? -res
: res
)
598 : csloww2 (a
, da
, x
, n
));
601 } /* else if (k < 0x419921FB ) */
603 else if (k
< 0x42F00000)
605 t
= (x
* hpinv
+ toint
);
608 xn1
= (xn
+ 8.0e22
) - 8.0e22
;
610 y
= ((((x
- xn1
* mp1
) - xn1
* mp2
) - xn2
* mp1
) - xn2
* mp2
);
611 n
= v
.i
[LOW_HALF
] & 3;
615 da
= (da
- xn2
* pp3
) - xn
* pp4
;
632 res
= TAYLOR_SIN (xx
, a
, da
, cor
);
633 cor
= (cor
> 0) ? 1.02 * cor
+ eps
: 1.02 * cor
- eps
;
634 retval
= (res
== res
+ cor
) ? res
: bsloww (a
, da
, x
, n
);
653 s
= y
+ (db
+ y
* xx
* (sn3
+ xx
* sn5
));
654 c
= y
* db
+ xx
* (cs2
+ xx
* (cs4
+ xx
* cs6
));
655 SINCOS_TABLE_LOOKUP (u
, sn
, ssn
, cs
, ccs
);
656 cor
= (ssn
+ s
* ccs
- sn
* c
) + cs
* s
;
658 cor
= (sn
- res
) + cor
;
659 cor
= (cor
> 0) ? 1.035 * cor
+ eps
: 1.035 * cor
- eps
;
660 retval
= ((res
== res
+ cor
) ? ((m
) ? res
: -res
)
661 : bsloww1 (a
, da
, x
, n
));
673 y
= a
- (u
.x
- big
) + da
;
675 SINCOS_TABLE_LOOKUP (u
, sn
, ssn
, cs
, ccs
);
676 s
= y
+ y
* xx
* (sn3
+ xx
* sn5
);
677 c
= xx
* (cs2
+ xx
* (cs4
+ xx
* cs6
));
678 cor
= (ccs
- s
* ssn
- cs
* c
) - sn
* s
;
680 cor
= (cs
- res
) + cor
;
681 cor
= (cor
> 0) ? 1.025 * cor
+ eps
: 1.025 * cor
- eps
;
682 retval
= ((res
== res
+ cor
) ? ((n
) ? -res
: res
)
683 : bsloww2 (a
, da
, x
, n
));
686 } /* else if (k < 0x42F00000 ) */
688 /* 281474976710656 <|x| <2^1024 */
689 else if (k
< 0x7ff00000)
690 retval
= reduce_and_compute (x
, 1);
694 if (k
== 0x7ff00000 && u
.i
[LOW_HALF
] == 0)
696 retval
= x
/ x
; /* |x| > 2^1024 */
702 /************************************************************************/
703 /* Routine compute sin(x) for 2^-26 < |x|< 0.25 by Taylor with more */
704 /* precision and if still doesn't accurate enough by mpsin or dubsin */
705 /************************************************************************/
711 double res
, cor
, w
[2];
712 res
= TAYLOR_SLOW (x
, 0, cor
);
713 if (res
== res
+ 1.0007 * cor
)
717 __dubsin (ABS (x
), 0, w
);
718 if (w
[0] == w
[0] + 1.000000001 * w
[1])
719 return (x
> 0) ? w
[0] : -w
[0];
721 return (x
> 0) ? __mpsin (x
, 0, false) : -__mpsin (-x
, 0, false);
725 /*******************************************************************************/
726 /* Routine compute sin(x) for 0.25<|x|< 0.855469 by __sincostab.tbl and Taylor */
727 /* and if result still doesn't accurate enough by mpsin or dubsin */
728 /*******************************************************************************/
735 double sn
, ssn
, cs
, ccs
, s
, c
, w
[2], y
, y1
, y2
, c1
, c2
, xx
, cor
, res
;
740 s
= y
* xx
* (sn3
+ xx
* sn5
);
741 c
= xx
* (cs2
+ xx
* (cs4
+ xx
* cs6
));
742 SINCOS_TABLE_LOOKUP (u
, sn
, ssn
, cs
, ccs
);
743 y1
= (y
+ t22
) - t22
;
745 c1
= (cs
+ t22
) - t22
;
746 c2
= (cs
- c1
) + ccs
;
747 cor
= (ssn
+ s
* ccs
+ cs
* s
+ c2
* y
+ c1
* y2
) - sn
* c
;
749 cor
= cor
+ ((sn
- y
) + c1
* y1
);
751 cor
= (y
- res
) + cor
;
752 if (res
== res
+ 1.0005 * cor
)
753 return (x
> 0) ? res
: -res
;
756 __dubsin (ABS (x
), 0, w
);
757 if (w
[0] == w
[0] + 1.000000005 * w
[1])
758 return (x
> 0) ? w
[0] : -w
[0];
760 return (x
> 0) ? __mpsin (x
, 0, false) : -__mpsin (-x
, 0, false);
764 /**************************************************************************/
765 /* Routine compute sin(x) for 0.855469 <|x|<2.426265 by __sincostab.tbl */
766 /* and if result still doesn't accurate enough by mpsin or dubsin */
767 /**************************************************************************/
773 double sn
, ssn
, cs
, ccs
, s
, c
, w
[2], y
, y1
, y2
, e1
, e2
, xx
, cor
, res
, del
;
786 y
= -(y
+ (u
.x
- big
));
790 s
= y
* xx
* (sn3
+ xx
* sn5
);
791 c
= y
* del
+ xx
* (cs2
+ xx
* (cs4
+ xx
* cs6
));
792 SINCOS_TABLE_LOOKUP (u
, sn
, ssn
, cs
, ccs
);
793 y1
= (y
+ t22
) - t22
;
795 e1
= (sn
+ t22
) - t22
;
796 e2
= (sn
- e1
) + ssn
;
797 cor
= (ccs
- cs
* c
- e1
* y2
- e2
* y
) - sn
* s
;
799 cor
= cor
+ ((cs
- y
) - e1
* y1
);
801 cor
= (y
- res
) + cor
;
802 if (res
== res
+ 1.0005 * cor
)
803 return (x
> 0) ? res
: -res
;
810 if (w
[0] == w
[0] + 1.000000005 * w
[1])
811 return (x
> 0) ? w
[0] : -w
[0];
813 return (x
> 0) ? __mpsin (x
, 0, false) : -__mpsin (-x
, 0, false);
817 /***************************************************************************/
818 /* Routine compute sin(x+dx) (Double-Length number) where x is small enough*/
819 /* to use Taylor series around zero and (x+dx) */
820 /* in first or third quarter of unit circle.Routine receive also */
821 /* (right argument) the original value of x for computing error of */
822 /* result.And if result not accurate enough routine calls mpsin1 or dubsin */
823 /***************************************************************************/
827 sloww (double x
, double dx
, double orig
)
829 double y
, t
, res
, cor
, w
[2], a
, da
, xn
;
832 res
= TAYLOR_SLOW (x
, dx
, cor
);
834 cor
= 1.0005 * cor
+ ABS (orig
) * 3.1e-30;
836 cor
= 1.0005 * cor
- ABS (orig
) * 3.1e-30;
838 if (res
== res
+ cor
)
842 (x
> 0) ? __dubsin (x
, dx
, w
) : __dubsin (-x
, -dx
, w
);
844 cor
= 1.000000001 * w
[1] + ABS (orig
) * 1.1e-30;
846 cor
= 1.000000001 * w
[1] - ABS (orig
) * 1.1e-30;
848 if (w
[0] == w
[0] + cor
)
849 return (x
> 0) ? w
[0] : -w
[0];
852 t
= (orig
* hpinv
+ toint
);
855 y
= (orig
- xn
* mp1
) - xn
* mp2
;
856 n
= v
.i
[LOW_HALF
] & 3;
862 da
= ((t
- a
) - y
) + da
;
868 (a
> 0) ? __dubsin (a
, da
, w
) : __dubsin (-a
, -da
, w
);
870 cor
= 1.000000001 * w
[1] + ABS (orig
) * 1.1e-40;
872 cor
= 1.000000001 * w
[1] - ABS (orig
) * 1.1e-40;
874 if (w
[0] == w
[0] + cor
)
875 return (a
> 0) ? w
[0] : -w
[0];
877 return __mpsin (orig
, 0, true);
882 /***************************************************************************/
883 /* Routine compute sin(x+dx) (Double-Length number) where x in first or */
884 /* third quarter of unit circle.Routine receive also (right argument) the */
885 /* original value of x for computing error of result.And if result not */
886 /* accurate enough routine calls mpsin1 or dubsin */
887 /***************************************************************************/
891 sloww1 (double x
, double dx
, double orig
)
894 double sn
, ssn
, cs
, ccs
, s
, c
, w
[2], y
, y1
, y2
, c1
, c2
, xx
, cor
, res
;
900 s
= y
* xx
* (sn3
+ xx
* sn5
);
901 c
= xx
* (cs2
+ xx
* (cs4
+ xx
* cs6
));
902 SINCOS_TABLE_LOOKUP (u
, sn
, ssn
, cs
, ccs
);
903 y1
= (y
+ t22
) - t22
;
905 c1
= (cs
+ t22
) - t22
;
906 c2
= (cs
- c1
) + ccs
;
907 cor
= (ssn
+ s
* ccs
+ cs
* s
+ c2
* y
+ c1
* y2
- sn
* y
* dx
) - sn
* c
;
909 cor
= cor
+ ((sn
- y
) + c1
* y1
);
911 cor
= (y
- res
) + cor
;
914 cor
= 1.0005 * cor
+ 3.1e-30 * ABS (orig
);
916 cor
= 1.0005 * cor
- 3.1e-30 * ABS (orig
);
918 if (res
== res
+ cor
)
919 return (x
> 0) ? res
: -res
;
922 __dubsin (ABS (x
), dx
, w
);
925 cor
= 1.000000005 * w
[1] + 1.1e-30 * ABS (orig
);
927 cor
= 1.000000005 * w
[1] - 1.1e-30 * ABS (orig
);
929 if (w
[0] == w
[0] + cor
)
930 return (x
> 0) ? w
[0] : -w
[0];
932 return __mpsin (orig
, 0, true);
936 /***************************************************************************/
937 /* Routine compute sin(x+dx) (Double-Length number) where x in second or */
938 /* fourth quarter of unit circle.Routine receive also the original value */
939 /* and quarter(n= 1or 3)of x for computing error of result.And if result not*/
940 /* accurate enough routine calls mpsin1 or dubsin */
941 /***************************************************************************/
945 sloww2 (double x
, double dx
, double orig
, int n
)
948 double sn
, ssn
, cs
, ccs
, s
, c
, w
[2], y
, y1
, y2
, e1
, e2
, xx
, cor
, res
;
953 s
= y
* xx
* (sn3
+ xx
* sn5
);
954 c
= y
* dx
+ xx
* (cs2
+ xx
* (cs4
+ xx
* cs6
));
955 SINCOS_TABLE_LOOKUP (u
, sn
, ssn
, cs
, ccs
);
957 y1
= (y
+ t22
) - t22
;
959 e1
= (sn
+ t22
) - t22
;
960 e2
= (sn
- e1
) + ssn
;
961 cor
= (ccs
- cs
* c
- e1
* y2
- e2
* y
) - sn
* s
;
963 cor
= cor
+ ((cs
- y
) - e1
* y1
);
965 cor
= (y
- res
) + cor
;
968 cor
= 1.0005 * cor
+ 3.1e-30 * ABS (orig
);
970 cor
= 1.0005 * cor
- 3.1e-30 * ABS (orig
);
972 if (res
== res
+ cor
)
973 return (n
& 2) ? -res
: res
;
979 cor
= 1.000000005 * w
[1] + 1.1e-30 * ABS (orig
);
981 cor
= 1.000000005 * w
[1] - 1.1e-30 * ABS (orig
);
983 if (w
[0] == w
[0] + cor
)
984 return (n
& 2) ? -w
[0] : w
[0];
986 return __mpsin (orig
, 0, true);
990 /***************************************************************************/
991 /* Routine compute sin(x+dx) or cos(x+dx) (Double-Length number) where x */
992 /* is small enough to use Taylor series around zero and (x+dx) */
993 /* in first or third quarter of unit circle.Routine receive also */
994 /* (right argument) the original value of x for computing error of */
995 /* result.And if result not accurate enough routine calls other routines */
996 /***************************************************************************/
1000 bsloww (double x
, double dx
, double orig
, int n
)
1002 double res
, cor
, w
[2];
1004 res
= TAYLOR_SLOW (x
, dx
, cor
);
1005 cor
= (cor
> 0) ? 1.0005 * cor
+ 1.1e-24 : 1.0005 * cor
- 1.1e-24;
1006 if (res
== res
+ cor
)
1010 (x
> 0) ? __dubsin (x
, dx
, w
) : __dubsin (-x
, -dx
, w
);
1012 cor
= 1.000000001 * w
[1] + 1.1e-24;
1014 cor
= 1.000000001 * w
[1] - 1.1e-24;
1015 if (w
[0] == w
[0] + cor
)
1016 return (x
> 0) ? w
[0] : -w
[0];
1018 return (n
& 1) ? __mpcos (orig
, 0, true) : __mpsin (orig
, 0, true);
1022 /***************************************************************************/
1023 /* Routine compute sin(x+dx) or cos(x+dx) (Double-Length number) where x */
1024 /* in first or third quarter of unit circle.Routine receive also */
1025 /* (right argument) the original value of x for computing error of result.*/
1026 /* And if result not accurate enough routine calls other routines */
1027 /***************************************************************************/
1031 bsloww1 (double x
, double dx
, double orig
, int n
)
1034 double sn
, ssn
, cs
, ccs
, s
, c
, w
[2], y
, y1
, y2
, c1
, c2
, xx
, cor
, res
;
1038 y
= y
- (u
.x
- big
);
1039 dx
= (x
> 0) ? dx
: -dx
;
1041 s
= y
* xx
* (sn3
+ xx
* sn5
);
1042 c
= xx
* (cs2
+ xx
* (cs4
+ xx
* cs6
));
1043 SINCOS_TABLE_LOOKUP (u
, sn
, ssn
, cs
, ccs
);
1044 y1
= (y
+ t22
) - t22
;
1046 c1
= (cs
+ t22
) - t22
;
1047 c2
= (cs
- c1
) + ccs
;
1048 cor
= (ssn
+ s
* ccs
+ cs
* s
+ c2
* y
+ c1
* y2
- sn
* y
* dx
) - sn
* c
;
1050 cor
= cor
+ ((sn
- y
) + c1
* y1
);
1052 cor
= (y
- res
) + cor
;
1053 cor
= (cor
> 0) ? 1.0005 * cor
+ 1.1e-24 : 1.0005 * cor
- 1.1e-24;
1054 if (res
== res
+ cor
)
1055 return (x
> 0) ? res
: -res
;
1058 __dubsin (ABS (x
), dx
, w
);
1061 cor
= 1.000000005 * w
[1] + 1.1e-24;
1063 cor
= 1.000000005 * w
[1] - 1.1e-24;
1065 if (w
[0] == w
[0] + cor
)
1066 return (x
> 0) ? w
[0] : -w
[0];
1068 return (n
& 1) ? __mpcos (orig
, 0, true) : __mpsin (orig
, 0, true);
1072 /***************************************************************************/
1073 /* Routine compute sin(x+dx) or cos(x+dx) (Double-Length number) where x */
1074 /* in second or fourth quarter of unit circle.Routine receive also the */
1075 /* original value and quarter(n= 1or 3)of x for computing error of result. */
1076 /* And if result not accurate enough routine calls other routines */
1077 /***************************************************************************/
1081 bsloww2 (double x
, double dx
, double orig
, int n
)
1084 double sn
, ssn
, cs
, ccs
, s
, c
, w
[2], y
, y1
, y2
, e1
, e2
, xx
, cor
, res
;
1088 y
= y
- (u
.x
- big
);
1089 dx
= (x
> 0) ? dx
: -dx
;
1091 s
= y
* xx
* (sn3
+ xx
* sn5
);
1092 c
= y
* dx
+ xx
* (cs2
+ xx
* (cs4
+ xx
* cs6
));
1093 SINCOS_TABLE_LOOKUP (u
, sn
, ssn
, cs
, ccs
);
1095 y1
= (y
+ t22
) - t22
;
1097 e1
= (sn
+ t22
) - t22
;
1098 e2
= (sn
- e1
) + ssn
;
1099 cor
= (ccs
- cs
* c
- e1
* y2
- e2
* y
) - sn
* s
;
1101 cor
= cor
+ ((cs
- y
) - e1
* y1
);
1103 cor
= (y
- res
) + cor
;
1104 cor
= (cor
> 0) ? 1.0005 * cor
+ 1.1e-24 : 1.0005 * cor
- 1.1e-24;
1105 if (res
== res
+ cor
)
1106 return (n
& 2) ? -res
: res
;
1109 __docos (ABS (x
), dx
, w
);
1112 cor
= 1.000000005 * w
[1] + 1.1e-24;
1114 cor
= 1.000000005 * w
[1] - 1.1e-24;
1116 if (w
[0] == w
[0] + cor
)
1117 return (n
& 2) ? -w
[0] : w
[0];
1119 return (n
& 1) ? __mpsin (orig
, 0, true) : __mpcos (orig
, 0, true);
1123 /************************************************************************/
1124 /* Routine compute cos(x) for 2^-27 < |x|< 0.25 by Taylor with more */
1125 /* precision and if still doesn't accurate enough by mpcos or docos */
1126 /************************************************************************/
1133 double sn
, ssn
, cs
, ccs
, s
, c
, w
[2], y
, y1
, y2
, e1
, e2
, xx
, cor
, res
;
1137 y
= y
- (u
.x
- big
);
1139 s
= y
* xx
* (sn3
+ xx
* sn5
);
1140 c
= xx
* (cs2
+ xx
* (cs4
+ xx
* cs6
));
1141 SINCOS_TABLE_LOOKUP (u
, sn
, ssn
, cs
, ccs
);
1142 y1
= (y
+ t22
) - t22
;
1144 e1
= (sn
+ t22
) - t22
;
1145 e2
= (sn
- e1
) + ssn
;
1146 cor
= (ccs
- cs
* c
- e1
* y2
- e2
* y
) - sn
* s
;
1148 cor
= cor
+ ((cs
- y
) - e1
* y1
);
1150 cor
= (y
- res
) + cor
;
1151 if (res
== res
+ 1.0005 * cor
)
1157 if (w
[0] == w
[0] + 1.000000005 * w
[1])
1160 return __mpcos (x
, 0, false);
1164 /***************************************************************************/
1165 /* Routine compute cos(x+dx) (Double-Length number) where x is small enough*/
1166 /* to use Taylor series around zero and (x+dx) .Routine receive also */
1167 /* (right argument) the original value of x for computing error of */
1168 /* result.And if result not accurate enough routine calls other routines */
1169 /***************************************************************************/
1174 csloww (double x
, double dx
, double orig
)
1176 double y
, t
, res
, cor
, w
[2], a
, da
, xn
;
1181 t
= TAYLOR_SLOW (x
, dx
, cor
);
1184 cor
= 1.0005 * cor
+ ABS (orig
) * 3.1e-30;
1186 cor
= 1.0005 * cor
- ABS (orig
) * 3.1e-30;
1188 if (res
== res
+ cor
)
1192 (x
> 0) ? __dubsin (x
, dx
, w
) : __dubsin (-x
, -dx
, w
);
1195 cor
= 1.000000001 * w
[1] + ABS (orig
) * 1.1e-30;
1197 cor
= 1.000000001 * w
[1] - ABS (orig
) * 1.1e-30;
1199 if (w
[0] == w
[0] + cor
)
1200 return (x
> 0) ? w
[0] : -w
[0];
1203 t
= (orig
* hpinv
+ toint
);
1206 y
= (orig
- xn
* mp1
) - xn
* mp2
;
1207 n
= v
.i
[LOW_HALF
] & 3;
1213 da
= ((t
- a
) - y
) + da
;
1219 (a
> 0) ? __dubsin (a
, da
, w
) : __dubsin (-a
, -da
, w
);
1222 cor
= 1.000000001 * w
[1] + ABS (orig
) * 1.1e-40;
1224 cor
= 1.000000001 * w
[1] - ABS (orig
) * 1.1e-40;
1226 if (w
[0] == w
[0] + cor
)
1227 return (a
> 0) ? w
[0] : -w
[0];
1229 return __mpcos (orig
, 0, true);
1234 /***************************************************************************/
1235 /* Routine compute sin(x+dx) (Double-Length number) where x in first or */
1236 /* third quarter of unit circle.Routine receive also (right argument) the */
1237 /* original value of x for computing error of result.And if result not */
1238 /* accurate enough routine calls other routines */
1239 /***************************************************************************/
1243 csloww1 (double x
, double dx
, double orig
)
1246 double sn
, ssn
, cs
, ccs
, s
, c
, w
[2], y
, y1
, y2
, c1
, c2
, xx
, cor
, res
;
1250 y
= y
- (u
.x
- big
);
1252 s
= y
* xx
* (sn3
+ xx
* sn5
);
1253 c
= xx
* (cs2
+ xx
* (cs4
+ xx
* cs6
));
1254 SINCOS_TABLE_LOOKUP (u
, sn
, ssn
, cs
, ccs
);
1255 y1
= (y
+ t22
) - t22
;
1257 c1
= (cs
+ t22
) - t22
;
1258 c2
= (cs
- c1
) + ccs
;
1259 cor
= (ssn
+ s
* ccs
+ cs
* s
+ c2
* y
+ c1
* y2
- sn
* y
* dx
) - sn
* c
;
1261 cor
= cor
+ ((sn
- y
) + c1
* y1
);
1263 cor
= (y
- res
) + cor
;
1266 cor
= 1.0005 * cor
+ 3.1e-30 * ABS (orig
);
1268 cor
= 1.0005 * cor
- 3.1e-30 * ABS (orig
);
1270 if (res
== res
+ cor
)
1271 return (x
> 0) ? res
: -res
;
1274 __dubsin (ABS (x
), dx
, w
);
1276 cor
= 1.000000005 * w
[1] + 1.1e-30 * ABS (orig
);
1278 cor
= 1.000000005 * w
[1] - 1.1e-30 * ABS (orig
);
1279 if (w
[0] == w
[0] + cor
)
1280 return (x
> 0) ? w
[0] : -w
[0];
1282 return __mpcos (orig
, 0, true);
1287 /***************************************************************************/
1288 /* Routine compute sin(x+dx) (Double-Length number) where x in second or */
1289 /* fourth quarter of unit circle.Routine receive also the original value */
1290 /* and quarter(n= 1or 3)of x for computing error of result.And if result not*/
1291 /* accurate enough routine calls other routines */
1292 /***************************************************************************/
1296 csloww2 (double x
, double dx
, double orig
, int n
)
1299 double sn
, ssn
, cs
, ccs
, s
, c
, w
[2], y
, y1
, y2
, e1
, e2
, xx
, cor
, res
;
1302 y
= x
- (u
.x
- big
);
1304 s
= y
* xx
* (sn3
+ xx
* sn5
);
1305 c
= y
* dx
+ xx
* (cs2
+ xx
* (cs4
+ xx
* cs6
));
1306 SINCOS_TABLE_LOOKUP (u
, sn
, ssn
, cs
, ccs
);
1308 y1
= (y
+ t22
) - t22
;
1310 e1
= (sn
+ t22
) - t22
;
1311 e2
= (sn
- e1
) + ssn
;
1312 cor
= (ccs
- cs
* c
- e1
* y2
- e2
* y
) - sn
* s
;
1314 cor
= cor
+ ((cs
- y
) - e1
* y1
);
1316 cor
= (y
- res
) + cor
;
1319 cor
= 1.0005 * cor
+ 3.1e-30 * ABS (orig
);
1321 cor
= 1.0005 * cor
- 3.1e-30 * ABS (orig
);
1323 if (res
== res
+ cor
)
1324 return (n
) ? -res
: res
;
1329 cor
= 1.000000005 * w
[1] + 1.1e-30 * ABS (orig
);
1331 cor
= 1.000000005 * w
[1] - 1.1e-30 * ABS (orig
);
1332 if (w
[0] == w
[0] + cor
)
1333 return (n
) ? -w
[0] : w
[0];
1335 return __mpcos (orig
, 0, true);
1340 weak_alias (__cos
, cos
)
1341 # ifdef NO_LONG_DOUBLE
1342 strong_alias (__cos
, __cosl
)
1343 weak_alias (__cos
, cosl
)
1347 weak_alias (__sin
, sin
)
1348 # ifdef NO_LONG_DOUBLE
1349 strong_alias (__sin
, __sinl
)
1350 weak_alias (__sin
, sinl
)