2 * IBM Accurate Mathematical Library
3 * written by International Business Machines Corp.
4 * Copyright (C) 2001-2015 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 /****************************************************************************/
57 #include <math_private.h>
60 /* Helper macros to compute sin of the input values. */
61 #define POLYNOMIAL2(xx) ((((s5 * (xx) + s4) * (xx) + s3) * (xx) + s2) * (xx))
63 #define POLYNOMIAL(xx) (POLYNOMIAL2 (xx) + s1)
65 /* The computed polynomial is a variation of the Taylor series expansion for
68 a - a^3/3! + a^5/5! - a^7/7! + a^9/9! + (1 - a^2) * da / 2
70 The constants s1, s2, s3, etc. are pre-computed values of 1/3!, 1/5! and so
71 on. The result is returned to LHS and correction in COR. */
72 #define TAYLOR_SIN(xx, a, da, cor) \
74 double t = ((POLYNOMIAL (xx) * (a) - 0.5 * (da)) * (xx) + (da)); \
75 double res = (a) + t; \
76 (cor) = ((a) - res) + t; \
80 /* This is again a variation of the Taylor series expansion with the term
81 x^3/3! expanded into the following for better accuracy:
83 bb * x ^ 3 + 3 * aa * x * x1 * x2 + aa * x1 ^ 3 + aa * x2 ^ 3
85 The correction term is dx and bb + aa = -1/3!
87 #define TAYLOR_SLOW(x0, dx, cor) \
89 static const double th2_36 = 206158430208.0; /* 1.5*2**37 */ \
90 double xx = (x0) * (x0); \
91 double x1 = ((x0) + th2_36) - th2_36; \
92 double y = aa * x1 * x1 * x1; \
93 double r = (x0) + y; \
94 double x2 = ((x0) - x1) + (dx); \
95 double t = (((POLYNOMIAL2 (xx) + bb) * xx + 3.0 * aa * x1 * x2) \
96 * (x0) + aa * x2 * x2 * x2 + (dx)); \
97 t = (((x0) - r) + y) + t; \
99 (cor) = (r - res) + t; \
103 #define SINCOS_TABLE_LOOKUP(u, sn, ssn, cs, ccs) \
105 int4 k = u.i[LOW_HALF] << 2; \
106 sn = __sincostab.x[k]; \
107 ssn = __sincostab.x[k + 1]; \
108 cs = __sincostab.x[k + 2]; \
109 ccs = __sincostab.x[k + 3]; \
120 } __sincostab attribute_hidden
;
123 sn3
= -1.66666666666664880952546298448555E-01,
124 sn5
= 8.33333214285722277379541354343671E-03,
125 cs2
= 4.99999999999999999999950396842453E-01,
126 cs4
= -4.16666666666664434524222570944589E-02,
127 cs6
= 1.38888874007937613028114285595617E-03;
129 static const double t22
= 0x1.8p22
;
131 void __dubsin (double x
, double dx
, double w
[]);
132 void __docos (double x
, double dx
, double w
[]);
133 double __mpsin (double x
, double dx
, bool reduce_range
);
134 double __mpcos (double x
, double dx
, bool reduce_range
);
135 static double slow (double x
);
136 static double slow1 (double x
);
137 static double slow2 (double x
);
138 static double sloww (double x
, double dx
, double orig
);
139 static double sloww1 (double x
, double dx
, double orig
, int m
);
140 static double sloww2 (double x
, double dx
, double orig
, int n
);
141 static double bsloww (double x
, double dx
, double orig
, int n
);
142 static double bsloww1 (double x
, double dx
, double orig
, int n
);
143 static double bsloww2 (double x
, double dx
, double orig
, int n
);
144 int __branred (double x
, double *a
, double *aa
);
145 static double cslow2 (double x
);
146 static double csloww (double x
, double dx
, double orig
);
147 static double csloww1 (double x
, double dx
, double orig
, int m
);
148 static double csloww2 (double x
, double dx
, double orig
, int n
);
150 /* Given a number partitioned into U and X such that U is an index into the
151 sin/cos table, this macro computes the cosine of the number by combining
152 the sin and cos of X (as computed by a variation of the Taylor series) with
153 the values looked up from the sin/cos table to get the result in RES and a
154 correction value in COR. */
156 do_cos (mynumber u
, double x
, double *corp
)
158 double xx
, s
, sn
, ssn
, c
, cs
, ccs
, res
, cor
;
160 s
= x
+ x
* xx
* (sn3
+ xx
* sn5
);
161 c
= xx
* (cs2
+ xx
* (cs4
+ xx
* cs6
));
162 SINCOS_TABLE_LOOKUP (u
, sn
, ssn
, cs
, ccs
);
163 cor
= (ccs
- s
* ssn
- cs
* c
) - sn
* s
;
165 cor
= (cs
- res
) + cor
;
170 /* A more precise variant of DO_COS where the number is partitioned into U, X
171 and DX. EPS is the adjustment to the correction COR. */
173 do_cos_slow (mynumber u
, double x
, double dx
, double eps
, double *corp
)
175 double xx
, y
, x1
, x2
, e1
, e2
, res
, cor
;
176 double s
, sn
, ssn
, c
, cs
, ccs
;
178 s
= x
* xx
* (sn3
+ xx
* sn5
);
179 c
= x
* dx
+ xx
* (cs2
+ xx
* (cs4
+ xx
* cs6
));
180 SINCOS_TABLE_LOOKUP (u
, sn
, ssn
, cs
, ccs
);
181 x1
= (x
+ t22
) - t22
;
183 e1
= (sn
+ t22
) - t22
;
184 e2
= (sn
- e1
) + ssn
;
185 cor
= (ccs
- cs
* c
- e1
* x2
- e2
* x
) - sn
* s
;
187 cor
= cor
+ ((cs
- y
) - e1
* x1
);
189 cor
= (y
- res
) + cor
;
191 cor
= 1.0005 * cor
+ eps
;
193 cor
= 1.0005 * cor
- eps
;
198 /* Given a number partitioned into U and X and DX such that U is an index into
199 the sin/cos table, this macro computes the sine of the number by combining
200 the sin and cos of X (as computed by a variation of the Taylor series) with
201 the values looked up from the sin/cos table to get the result in RES and a
202 correction value in COR. */
204 do_sin (mynumber u
, double x
, double dx
, double *corp
)
206 double xx
, s
, sn
, ssn
, c
, cs
, ccs
, cor
, res
;
208 s
= x
+ (dx
+ x
* xx
* (sn3
+ xx
* sn5
));
209 c
= x
* dx
+ xx
* (cs2
+ xx
* (cs4
+ xx
* cs6
));
210 SINCOS_TABLE_LOOKUP (u
, sn
, ssn
, cs
, ccs
);
211 cor
= (ssn
+ s
* ccs
- sn
* c
) + cs
* s
;
213 cor
= (sn
- res
) + cor
;
218 /* A more precise variant of res = do_sin where the number is partitioned into U, X
219 and DX. EPS is the adjustment to the correction COR. */
221 do_sin_slow (mynumber u
, double x
, double dx
, double eps
, double *corp
)
223 double xx
, y
, x1
, x2
, c1
, c2
, res
, cor
;
224 double s
, sn
, ssn
, c
, cs
, ccs
;
226 s
= x
* xx
* (sn3
+ xx
* sn5
);
227 c
= xx
* (cs2
+ xx
* (cs4
+ xx
* cs6
));
228 SINCOS_TABLE_LOOKUP (u
, sn
, ssn
, cs
, ccs
);
229 x1
= (x
+ t22
) - t22
;
231 c1
= (cs
+ t22
) - t22
;
232 c2
= (cs
- c1
) + ccs
;
233 cor
= (ssn
+ s
* ccs
+ cs
* s
+ c2
* x
+ c1
* x2
- sn
* x
* dx
) - sn
* c
;
235 cor
= cor
+ ((sn
- y
) + c1
* x1
);
237 cor
= (y
- res
) + cor
;
239 cor
= 1.0005 * cor
+ eps
;
241 cor
= 1.0005 * cor
- eps
;
246 /* Reduce range of X and compute sin of a + da. K is the amount by which to
247 rotate the quadrants. This allows us to use the same routine to compute cos
248 by simply rotating the quadrants by 1. */
251 reduce_and_compute (double x
, unsigned int k
)
253 double retval
= 0, a
, da
;
254 unsigned int n
= __branred (x
, &a
, &da
);
260 retval
= bsloww (a
, da
, x
, n
);
262 retval
= bsloww1 (a
, da
, x
, n
);
266 retval
= bsloww (-a
, -da
, x
, n
);
268 retval
= bsloww1 (-a
, -da
, x
, n
);
273 retval
= bsloww2 (a
, da
, x
, n
);
279 /*******************************************************************/
280 /* An ultimate sin routine. Given an IEEE double machine number x */
281 /* it computes the correctly rounded (to nearest) value of sin(x) */
282 /*******************************************************************/
287 double xx
, res
, t
, cor
, y
, s
, c
, sn
, ssn
, cs
, ccs
, xn
, a
, da
, db
, eps
, xn1
,
293 SET_RESTORE_ROUND_53BIT (FE_TONEAREST
);
297 k
= 0x7fffffff & m
; /* no sign */
298 if (k
< 0x3e500000) /* if x->0 =>sin(x)=x */
300 if (fabs (x
) < DBL_MIN
)
302 double force_underflow
= x
* x
;
303 math_force_eval (force_underflow
);
307 /*---------------------------- 2^-26 < |x|< 0.25 ----------------------*/
308 else if (k
< 0x3fd00000)
312 t
= POLYNOMIAL (xx
) * (xx
* x
);
315 retval
= (res
== res
+ 1.07 * cor
) ? res
: slow (x
);
316 } /* else if (k < 0x3fd00000) */
317 /*---------------------------- 0.25<|x|< 0.855469---------------------- */
318 else if (k
< 0x3feb6000)
320 u
.x
= (m
> 0) ? big
+ x
: big
- x
;
321 y
= (m
> 0) ? x
- (u
.x
- big
) : x
+ (u
.x
- big
);
323 s
= y
+ y
* xx
* (sn3
+ xx
* sn5
);
324 c
= xx
* (cs2
+ xx
* (cs4
+ xx
* cs6
));
325 SINCOS_TABLE_LOOKUP (u
, sn
, ssn
, cs
, ccs
);
331 cor
= (ssn
+ s
* ccs
- sn
* c
) + cs
* s
;
333 cor
= (sn
- res
) + cor
;
334 retval
= (res
== res
+ 1.096 * cor
) ? res
: slow1 (x
);
335 } /* else if (k < 0x3feb6000) */
337 /*----------------------- 0.855469 <|x|<2.426265 ----------------------*/
338 else if (k
< 0x400368fd)
341 y
= (m
> 0) ? hp0
- x
: hp0
+ x
;
345 y
= (y
- (u
.x
- big
)) + hp1
;
350 y
= (-hp1
) - (y
+ (u
.x
- big
));
352 res
= do_cos (u
, y
, &cor
);
353 retval
= (res
== res
+ 1.020 * cor
) ? ((m
> 0) ? res
: -res
) : slow2 (x
);
354 } /* else if (k < 0x400368fd) */
356 /*-------------------------- 2.426265<|x|< 105414350 ----------------------*/
357 else if (k
< 0x419921FB)
359 t
= (x
* hpinv
+ toint
);
362 y
= (x
- xn
* mp1
) - xn
* mp2
;
363 n
= v
.i
[LOW_HALF
] & 3;
367 eps
= fabs (x
) * 1.2e-30;
370 { /* quarter of unit circle */
382 res
= TAYLOR_SIN (xx
, a
, da
, cor
);
383 cor
= (cor
> 0) ? 1.02 * cor
+ eps
: 1.02 * cor
- eps
;
384 retval
= (res
== res
+ cor
) ? res
: sloww (a
, da
, x
);
398 res
= do_sin (u
, y
, da
, &cor
);
399 cor
= (cor
> 0) ? 1.035 * cor
+ eps
: 1.035 * cor
- eps
;
400 retval
= ((res
== res
+ cor
) ? ((m
) ? res
: -res
)
401 : sloww1 (a
, da
, x
, m
));
413 y
= a
- (u
.x
- big
) + da
;
414 res
= do_cos (u
, y
, &cor
);
415 cor
= (cor
> 0) ? 1.025 * cor
+ eps
: 1.025 * cor
- eps
;
416 retval
= ((res
== res
+ cor
) ? ((n
& 2) ? -res
: res
)
417 : sloww2 (a
, da
, x
, n
));
420 } /* else if (k < 0x419921FB ) */
422 /*---------------------105414350 <|x|< 281474976710656 --------------------*/
423 else if (k
< 0x42F00000)
425 t
= (x
* hpinv
+ toint
);
428 xn1
= (xn
+ 8.0e22
) - 8.0e22
;
430 y
= ((((x
- xn1
* mp1
) - xn1
* mp2
) - xn2
* mp1
) - xn2
* mp2
);
431 n
= v
.i
[LOW_HALF
] & 3;
435 da
= (da
- xn2
* pp3
) - xn
* pp4
;
453 res
= TAYLOR_SIN (xx
, a
, da
, cor
);
454 cor
= (cor
> 0) ? 1.02 * cor
+ eps
: 1.02 * cor
- eps
;
455 retval
= (res
== res
+ cor
) ? res
: bsloww (a
, da
, x
, n
);
474 res
= do_sin (u
, y
, db
, &cor
);
475 cor
= (cor
> 0) ? 1.035 * cor
+ eps
: 1.035 * cor
- eps
;
476 retval
= ((res
== res
+ cor
) ? ((m
) ? res
: -res
)
477 : bsloww1 (a
, da
, x
, n
));
489 y
= a
- (u
.x
- big
) + da
;
490 res
= do_cos (u
, y
, &cor
);
491 cor
= (cor
> 0) ? 1.025 * cor
+ eps
: 1.025 * cor
- eps
;
492 retval
= ((res
== res
+ cor
) ? ((n
& 2) ? -res
: res
)
493 : bsloww2 (a
, da
, x
, n
));
496 } /* else if (k < 0x42F00000 ) */
498 /* -----------------281474976710656 <|x| <2^1024----------------------------*/
499 else if (k
< 0x7ff00000)
500 retval
= reduce_and_compute (x
, 0);
502 /*--------------------- |x| > 2^1024 ----------------------------------*/
505 if (k
== 0x7ff00000 && u
.i
[LOW_HALF
] == 0)
514 /*******************************************************************/
515 /* An ultimate cos routine. Given an IEEE double machine number x */
516 /* it computes the correctly rounded (to nearest) value of cos(x) */
517 /*******************************************************************/
523 double y
, xx
, res
, t
, cor
, xn
, a
, da
, db
, eps
, xn1
,
530 SET_RESTORE_ROUND_53BIT (FE_TONEAREST
);
536 /* |x|<2^-27 => cos(x)=1 */
540 else if (k
< 0x3feb6000)
541 { /* 2^-27 < |x| < 0.855469 */
545 res
= do_cos (u
, y
, &cor
);
546 retval
= (res
== res
+ 1.020 * cor
) ? res
: cslow2 (x
);
547 } /* else if (k < 0x3feb6000) */
549 else if (k
< 0x400368fd)
550 { /* 0.855469 <|x|<2.426265 */ ;
557 res
= TAYLOR_SIN (xx
, a
, da
, cor
);
558 cor
= (cor
> 0) ? 1.02 * cor
+ 1.0e-31 : 1.02 * cor
- 1.0e-31;
559 retval
= (res
== res
+ cor
) ? res
: csloww (a
, da
, x
);
575 res
= do_sin (u
, y
, da
, &cor
);
576 cor
= (cor
> 0) ? 1.035 * cor
+ 1.0e-31 : 1.035 * cor
- 1.0e-31;
577 retval
= ((res
== res
+ cor
) ? ((m
) ? res
: -res
)
578 : csloww1 (a
, da
, x
, m
));
581 } /* else if (k < 0x400368fd) */
584 else if (k
< 0x419921FB)
585 { /* 2.426265<|x|< 105414350 */
586 t
= (x
* hpinv
+ toint
);
589 y
= (x
- xn
* mp1
) - xn
* mp2
;
590 n
= v
.i
[LOW_HALF
] & 3;
594 eps
= fabs (x
) * 1.2e-30;
608 res
= TAYLOR_SIN (xx
, a
, da
, cor
);
609 cor
= (cor
> 0) ? 1.02 * cor
+ eps
: 1.02 * cor
- eps
;
610 retval
= (res
== res
+ cor
) ? res
: csloww (a
, da
, x
);
626 res
= do_sin (u
, y
, da
, &cor
);
627 cor
= (cor
> 0) ? 1.035 * cor
+ eps
: 1.035 * cor
- eps
;
628 retval
= ((res
== res
+ cor
) ? ((m
) ? res
: -res
)
629 : csloww1 (a
, da
, x
, m
));
641 y
= a
- (u
.x
- big
) + da
;
642 res
= do_cos (u
, y
, &cor
);
643 cor
= (cor
> 0) ? 1.025 * cor
+ eps
: 1.025 * cor
- eps
;
644 retval
= ((res
== res
+ cor
) ? ((n
) ? -res
: res
)
645 : csloww2 (a
, da
, x
, n
));
648 } /* else if (k < 0x419921FB ) */
650 else if (k
< 0x42F00000)
652 t
= (x
* hpinv
+ toint
);
655 xn1
= (xn
+ 8.0e22
) - 8.0e22
;
657 y
= ((((x
- xn1
* mp1
) - xn1
* mp2
) - xn2
* mp1
) - xn2
* mp2
);
658 n
= v
.i
[LOW_HALF
] & 3;
662 da
= (da
- xn2
* pp3
) - xn
* pp4
;
679 res
= TAYLOR_SIN (xx
, a
, da
, cor
);
680 cor
= (cor
> 0) ? 1.02 * cor
+ eps
: 1.02 * cor
- eps
;
681 retval
= (res
== res
+ cor
) ? res
: bsloww (a
, da
, x
, n
);
700 res
= do_sin (u
, y
, db
, &cor
);
701 cor
= (cor
> 0) ? 1.035 * cor
+ eps
: 1.035 * cor
- eps
;
702 retval
= ((res
== res
+ cor
) ? ((m
) ? res
: -res
)
703 : bsloww1 (a
, da
, x
, n
));
715 y
= a
- (u
.x
- big
) + da
;
716 res
= do_cos (u
, y
, &cor
);
717 cor
= (cor
> 0) ? 1.025 * cor
+ eps
: 1.025 * cor
- eps
;
718 retval
= ((res
== res
+ cor
) ? ((n
) ? -res
: res
)
719 : bsloww2 (a
, da
, x
, n
));
722 } /* else if (k < 0x42F00000 ) */
724 /* 281474976710656 <|x| <2^1024 */
725 else if (k
< 0x7ff00000)
726 retval
= reduce_and_compute (x
, 1);
730 if (k
== 0x7ff00000 && u
.i
[LOW_HALF
] == 0)
732 retval
= x
/ x
; /* |x| > 2^1024 */
738 /************************************************************************/
739 /* Routine compute sin(x) for 2^-26 < |x|< 0.25 by Taylor with more */
740 /* precision and if still doesn't accurate enough by mpsin or dubsin */
741 /************************************************************************/
747 double res
, cor
, w
[2];
748 res
= TAYLOR_SLOW (x
, 0, cor
);
749 if (res
== res
+ 1.0007 * cor
)
753 __dubsin (fabs (x
), 0, w
);
754 if (w
[0] == w
[0] + 1.000000001 * w
[1])
755 return (x
> 0) ? w
[0] : -w
[0];
757 return (x
> 0) ? __mpsin (x
, 0, false) : -__mpsin (-x
, 0, false);
761 /*******************************************************************************/
762 /* Routine compute sin(x) for 0.25<|x|< 0.855469 by __sincostab.tbl and Taylor */
763 /* and if result still doesn't accurate enough by mpsin or dubsin */
764 /*******************************************************************************/
771 double w
[2], y
, cor
, res
;
775 res
= do_sin_slow (u
, y
, 0, 0, &cor
);
776 if (res
== res
+ cor
)
777 return (x
> 0) ? res
: -res
;
780 __dubsin (fabs (x
), 0, w
);
781 if (w
[0] == w
[0] + 1.000000005 * w
[1])
782 return (x
> 0) ? w
[0] : -w
[0];
784 return (x
> 0) ? __mpsin (x
, 0, false) : -__mpsin (-x
, 0, false);
788 /**************************************************************************/
789 /* Routine compute sin(x) for 0.855469 <|x|<2.426265 by __sincostab.tbl */
790 /* and if result still doesn't accurate enough by mpsin or dubsin */
791 /**************************************************************************/
797 double w
[2], y
, y1
, y2
, cor
, res
, del
;
810 y
= -(y
+ (u
.x
- big
));
813 res
= do_cos_slow (u
, y
, del
, 0, &cor
);
814 if (res
== res
+ cor
)
815 return (x
> 0) ? res
: -res
;
822 if (w
[0] == w
[0] + 1.000000005 * w
[1])
823 return (x
> 0) ? w
[0] : -w
[0];
825 return (x
> 0) ? __mpsin (x
, 0, false) : -__mpsin (-x
, 0, false);
829 /***************************************************************************/
830 /* Routine compute sin(x+dx) (Double-Length number) where x is small enough*/
831 /* to use Taylor series around zero and (x+dx) */
832 /* in first or third quarter of unit circle.Routine receive also */
833 /* (right argument) the original value of x for computing error of */
834 /* result.And if result not accurate enough routine calls mpsin1 or dubsin */
835 /***************************************************************************/
839 sloww (double x
, double dx
, double orig
)
841 double y
, t
, res
, cor
, w
[2], a
, da
, xn
;
844 res
= TAYLOR_SLOW (x
, dx
, cor
);
846 cor
= 1.0005 * cor
+ fabs (orig
) * 3.1e-30;
848 cor
= 1.0005 * cor
- fabs (orig
) * 3.1e-30;
850 if (res
== res
+ cor
)
854 (x
> 0) ? __dubsin (x
, dx
, w
) : __dubsin (-x
, -dx
, w
);
856 cor
= 1.000000001 * w
[1] + fabs (orig
) * 1.1e-30;
858 cor
= 1.000000001 * w
[1] - fabs (orig
) * 1.1e-30;
860 if (w
[0] == w
[0] + cor
)
861 return (x
> 0) ? w
[0] : -w
[0];
864 t
= (orig
* hpinv
+ toint
);
867 y
= (orig
- xn
* mp1
) - xn
* mp2
;
868 n
= v
.i
[LOW_HALF
] & 3;
874 da
= ((t
- a
) - y
) + da
;
880 (a
> 0) ? __dubsin (a
, da
, w
) : __dubsin (-a
, -da
, w
);
882 cor
= 1.000000001 * w
[1] + fabs (orig
) * 1.1e-40;
884 cor
= 1.000000001 * w
[1] - fabs (orig
) * 1.1e-40;
886 if (w
[0] == w
[0] + cor
)
887 return (a
> 0) ? w
[0] : -w
[0];
889 return __mpsin (orig
, 0, true);
894 /***************************************************************************/
895 /* Routine compute sin(x+dx) (Double-Length number) where x in first or */
896 /* third quarter of unit circle.Routine receive also (right argument) the */
897 /* original value of x for computing error of result.And if result not */
898 /* accurate enough routine calls mpsin1 or dubsin */
899 /***************************************************************************/
903 sloww1 (double x
, double dx
, double orig
, int m
)
906 double w
[2], y
, cor
, res
;
910 res
= do_sin_slow (u
, y
, dx
, 3.1e-30 * fabs (orig
), &cor
);
912 if (res
== res
+ cor
)
913 return (m
> 0) ? res
: -res
;
919 cor
= 1.000000005 * w
[1] + 1.1e-30 * fabs (orig
);
921 cor
= 1.000000005 * w
[1] - 1.1e-30 * fabs (orig
);
923 if (w
[0] == w
[0] + cor
)
924 return (m
> 0) ? w
[0] : -w
[0];
926 return __mpsin (orig
, 0, true);
930 /***************************************************************************/
931 /* Routine compute sin(x+dx) (Double-Length number) where x in second or */
932 /* fourth quarter of unit circle.Routine receive also the original value */
933 /* and quarter(n= 1or 3)of x for computing error of result.And if result not*/
934 /* accurate enough routine calls mpsin1 or dubsin */
935 /***************************************************************************/
939 sloww2 (double x
, double dx
, double orig
, int n
)
942 double w
[2], y
, cor
, res
;
946 res
= do_cos_slow (u
, y
, dx
, 3.1e-30 * fabs (orig
), &cor
);
948 if (res
== res
+ cor
)
949 return (n
& 2) ? -res
: res
;
955 cor
= 1.000000005 * w
[1] + 1.1e-30 * fabs (orig
);
957 cor
= 1.000000005 * w
[1] - 1.1e-30 * fabs (orig
);
959 if (w
[0] == w
[0] + cor
)
960 return (n
& 2) ? -w
[0] : w
[0];
962 return __mpsin (orig
, 0, true);
966 /***************************************************************************/
967 /* Routine compute sin(x+dx) or cos(x+dx) (Double-Length number) where x */
968 /* is small enough to use Taylor series around zero and (x+dx) */
969 /* in first or third quarter of unit circle.Routine receive also */
970 /* (right argument) the original value of x for computing error of */
971 /* result.And if result not accurate enough routine calls other routines */
972 /***************************************************************************/
976 bsloww (double x
, double dx
, double orig
, int n
)
978 double res
, cor
, w
[2];
980 res
= TAYLOR_SLOW (x
, dx
, cor
);
981 cor
= (cor
> 0) ? 1.0005 * cor
+ 1.1e-24 : 1.0005 * cor
- 1.1e-24;
982 if (res
== res
+ cor
)
986 (x
> 0) ? __dubsin (x
, dx
, w
) : __dubsin (-x
, -dx
, w
);
988 cor
= 1.000000001 * w
[1] + 1.1e-24;
990 cor
= 1.000000001 * w
[1] - 1.1e-24;
991 if (w
[0] == w
[0] + cor
)
992 return (x
> 0) ? w
[0] : -w
[0];
994 return (n
& 1) ? __mpcos (orig
, 0, true) : __mpsin (orig
, 0, true);
998 /***************************************************************************/
999 /* Routine compute sin(x+dx) or cos(x+dx) (Double-Length number) where x */
1000 /* in first or third quarter of unit circle.Routine receive also */
1001 /* (right argument) the original value of x for computing error of result.*/
1002 /* And if result not accurate enough routine calls other routines */
1003 /***************************************************************************/
1007 bsloww1 (double x
, double dx
, double orig
, int n
)
1010 double w
[2], y
, cor
, res
;
1014 y
= y
- (u
.x
- big
);
1015 dx
= (x
> 0) ? dx
: -dx
;
1016 res
= do_sin_slow (u
, y
, dx
, 1.1e-24, &cor
);
1017 if (res
== res
+ cor
)
1018 return (x
> 0) ? res
: -res
;
1021 __dubsin (fabs (x
), dx
, w
);
1024 cor
= 1.000000005 * w
[1] + 1.1e-24;
1026 cor
= 1.000000005 * w
[1] - 1.1e-24;
1028 if (w
[0] == w
[0] + cor
)
1029 return (x
> 0) ? w
[0] : -w
[0];
1031 return (n
& 1) ? __mpcos (orig
, 0, true) : __mpsin (orig
, 0, true);
1035 /***************************************************************************/
1036 /* Routine compute sin(x+dx) or cos(x+dx) (Double-Length number) where x */
1037 /* in second or fourth quarter of unit circle.Routine receive also the */
1038 /* original value and quarter(n= 1or 3)of x for computing error of result. */
1039 /* And if result not accurate enough routine calls other routines */
1040 /***************************************************************************/
1044 bsloww2 (double x
, double dx
, double orig
, int n
)
1047 double w
[2], y
, cor
, res
;
1051 y
= y
- (u
.x
- big
);
1052 dx
= (x
> 0) ? dx
: -dx
;
1053 res
= do_cos_slow (u
, y
, dx
, 1.1e-24, &cor
);
1054 if (res
== res
+ cor
)
1055 return (n
& 2) ? -res
: res
;
1058 __docos (fabs (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 (n
& 2) ? -w
[0] : w
[0];
1068 return (n
& 1) ? __mpsin (orig
, 0, true) : __mpcos (orig
, 0, true);
1072 /************************************************************************/
1073 /* Routine compute cos(x) for 2^-27 < |x|< 0.25 by Taylor with more */
1074 /* precision and if still doesn't accurate enough by mpcos or docos */
1075 /************************************************************************/
1082 double w
[2], y
, cor
, res
;
1086 y
= y
- (u
.x
- big
);
1087 res
= do_cos_slow (u
, y
, 0, 0, &cor
);
1088 if (res
== res
+ cor
)
1094 if (w
[0] == w
[0] + 1.000000005 * w
[1])
1097 return __mpcos (x
, 0, false);
1101 /***************************************************************************/
1102 /* Routine compute cos(x+dx) (Double-Length number) where x is small enough*/
1103 /* to use Taylor series around zero and (x+dx) .Routine receive also */
1104 /* (right argument) the original value of x for computing error of */
1105 /* result.And if result not accurate enough routine calls other routines */
1106 /***************************************************************************/
1111 csloww (double x
, double dx
, double orig
)
1113 double y
, t
, res
, cor
, w
[2], a
, da
, xn
;
1118 res
= TAYLOR_SLOW (x
, dx
, cor
);
1121 cor
= 1.0005 * cor
+ fabs (orig
) * 3.1e-30;
1123 cor
= 1.0005 * cor
- fabs (orig
) * 3.1e-30;
1125 if (res
== res
+ cor
)
1129 (x
> 0) ? __dubsin (x
, dx
, w
) : __dubsin (-x
, -dx
, w
);
1132 cor
= 1.000000001 * w
[1] + fabs (orig
) * 1.1e-30;
1134 cor
= 1.000000001 * w
[1] - fabs (orig
) * 1.1e-30;
1136 if (w
[0] == w
[0] + cor
)
1137 return (x
> 0) ? w
[0] : -w
[0];
1140 t
= (orig
* hpinv
+ toint
);
1143 y
= (orig
- xn
* mp1
) - xn
* mp2
;
1144 n
= v
.i
[LOW_HALF
] & 3;
1150 da
= ((t
- a
) - y
) + da
;
1156 (a
> 0) ? __dubsin (a
, da
, w
) : __dubsin (-a
, -da
, w
);
1159 cor
= 1.000000001 * w
[1] + fabs (orig
) * 1.1e-40;
1161 cor
= 1.000000001 * w
[1] - fabs (orig
) * 1.1e-40;
1163 if (w
[0] == w
[0] + cor
)
1164 return (a
> 0) ? w
[0] : -w
[0];
1166 return __mpcos (orig
, 0, true);
1171 /***************************************************************************/
1172 /* Routine compute sin(x+dx) (Double-Length number) where x in first or */
1173 /* third quarter of unit circle.Routine receive also (right argument) the */
1174 /* original value of x for computing error of result.And if result not */
1175 /* accurate enough routine calls other routines */
1176 /***************************************************************************/
1180 csloww1 (double x
, double dx
, double orig
, int m
)
1183 double w
[2], y
, cor
, res
;
1186 y
= x
- (u
.x
- big
);
1187 res
= do_sin_slow (u
, y
, dx
, 3.1e-30 * fabs (orig
), &cor
);
1189 if (res
== res
+ cor
)
1190 return (m
> 0) ? res
: -res
;
1193 __dubsin (x
, dx
, w
);
1195 cor
= 1.000000005 * w
[1] + 1.1e-30 * fabs (orig
);
1197 cor
= 1.000000005 * w
[1] - 1.1e-30 * fabs (orig
);
1198 if (w
[0] == w
[0] + cor
)
1199 return (m
> 0) ? w
[0] : -w
[0];
1201 return __mpcos (orig
, 0, true);
1206 /***************************************************************************/
1207 /* Routine compute sin(x+dx) (Double-Length number) where x in second or */
1208 /* fourth quarter of unit circle.Routine receive also the original value */
1209 /* and quarter(n= 1or 3)of x for computing error of result.And if result not*/
1210 /* accurate enough routine calls other routines */
1211 /***************************************************************************/
1215 csloww2 (double x
, double dx
, double orig
, int n
)
1218 double w
[2], y
, cor
, res
;
1221 y
= x
- (u
.x
- big
);
1222 res
= do_cos_slow (u
, y
, dx
, 3.1e-30 * fabs (orig
), &cor
);
1224 if (res
== res
+ cor
)
1225 return (n
) ? -res
: res
;
1230 cor
= 1.000000005 * w
[1] + 1.1e-30 * fabs (orig
);
1232 cor
= 1.000000005 * w
[1] - 1.1e-30 * fabs (orig
);
1233 if (w
[0] == w
[0] + cor
)
1234 return (n
) ? -w
[0] : w
[0];
1236 return __mpcos (orig
, 0, true);
1241 weak_alias (__cos
, cos
)
1242 # ifdef NO_LONG_DOUBLE
1243 strong_alias (__cos
, __cosl
)
1244 weak_alias (__cos
, cosl
)
1248 weak_alias (__sin
, sin
)
1249 # ifdef NO_LONG_DOUBLE
1250 strong_alias (__sin
, __sinl
)
1251 weak_alias (__sin
, sinl
)