2 * IBM Accurate Mathematical Library
3 * written by International Business Machines Corp.
4 * Copyright (C) 2001-2012 Free Software Foundation
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>
66 } __sincostab attribute_hidden
;
69 sn3
= -1.66666666666664880952546298448555E-01,
70 sn5
= 8.33333214285722277379541354343671E-03,
71 cs2
= 4.99999999999999999999950396842453E-01,
72 cs4
= -4.16666666666664434524222570944589E-02,
73 cs6
= 1.38888874007937613028114285595617E-03;
75 void __dubsin(double x
, double dx
, double w
[]);
76 void __docos(double x
, double dx
, double w
[]);
77 double __mpsin(double x
, double dx
);
78 double __mpcos(double x
, double dx
);
79 double __mpsin1(double x
);
80 double __mpcos1(double x
);
81 static double slow(double x
);
82 static double slow1(double x
);
83 static double slow2(double x
);
84 static double sloww(double x
, double dx
, double orig
);
85 static double sloww1(double x
, double dx
, double orig
);
86 static double sloww2(double x
, double dx
, double orig
, int n
);
87 static double bsloww(double x
, double dx
, double orig
, int n
);
88 static double bsloww1(double x
, double dx
, double orig
, int n
);
89 static double bsloww2(double x
, double dx
, double orig
, int n
);
90 int __branred(double x
, double *a
, double *aa
);
91 static double cslow2(double x
);
92 static double csloww(double x
, double dx
, double orig
);
93 static double csloww1(double x
, double dx
, double orig
);
94 static double csloww2(double x
, double dx
, double orig
, int n
);
95 /*******************************************************************/
96 /* An ultimate sin routine. Given an IEEE double machine number x */
97 /* it computes the correctly rounded (to nearest) value of sin(x) */
98 /*******************************************************************/
102 double xx
,res
,t
,cor
,y
,s
,c
,sn
,ssn
,cs
,ccs
,xn
,a
,da
,db
,eps
,xn1
,xn2
;
113 SET_RESTORE_ROUND_53BIT (FE_TONEAREST
);
117 k
= 0x7fffffff&m
; /* no sign */
118 if (k
< 0x3e500000) /* if x->0 =>sin(x)=x */
119 { retval
= x
; goto ret
; }
120 /*---------------------------- 2^-26 < |x|< 0.25 ----------------------*/
121 else if (k
< 0x3fd00000){
124 t
= ((((s5
.x
*xx
+ s4
.x
)*xx
+ s3
.x
)*xx
+ s2
.x
)*xx
+ s1
.x
)*(xx
*x
);
127 retval
= (res
== res
+ 1.07*cor
)? res
: slow(x
);
129 } /* else if (k < 0x3fd00000) */
130 /*---------------------------- 0.25<|x|< 0.855469---------------------- */
131 else if (k
< 0x3feb6000) {
132 u
.x
=(m
>0)?big
.x
+x
:big
.x
-x
;
133 y
=(m
>0)?x
-(u
.x
-big
.x
):x
+(u
.x
-big
.x
);
135 s
= y
+ y
*xx
*(sn3
+xx
*sn5
);
136 c
= xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
138 sn
=(m
>0)?__sincostab
.x
[k
]:-__sincostab
.x
[k
];
139 ssn
=(m
>0)?__sincostab
.x
[k
+1]:-__sincostab
.x
[k
+1];
140 cs
=__sincostab
.x
[k
+2];
141 ccs
=__sincostab
.x
[k
+3];
142 cor
=(ssn
+s
*ccs
-sn
*c
)+cs
*s
;
145 retval
= (res
==res
+1.096*cor
)? res
: slow1(x
);
147 } /* else if (k < 0x3feb6000) */
149 /*----------------------- 0.855469 <|x|<2.426265 ----------------------*/
150 else if (k
< 0x400368fd ) {
152 y
= (m
>0)? hp0
.x
-x
:hp0
.x
+x
;
155 y
= (y
-(u
.x
-big
.x
))+hp1
.x
;
159 y
= (-hp1
.x
) - (y
+(u
.x
-big
.x
));
162 s
= y
+ y
*xx
*(sn3
+xx
*sn5
);
163 c
= xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
166 ssn
=__sincostab
.x
[k
+1];
167 cs
=__sincostab
.x
[k
+2];
168 ccs
=__sincostab
.x
[k
+3];
169 cor
=(ccs
-s
*ssn
-cs
*c
)-sn
*s
;
172 retval
= (res
==res
+1.020*cor
)? ((m
>0)?res
:-res
) : slow2(x
);
174 } /* else if (k < 0x400368fd) */
176 /*-------------------------- 2.426265<|x|< 105414350 ----------------------*/
177 else if (k
< 0x419921FB ) {
178 t
= (x
*hpinv
.x
+ toint
.x
);
181 y
= (x
- xn
*mp1
.x
) - xn
*mp2
.x
;
186 eps
= ABS(x
)*1.2e-30;
188 switch (n
) { /* quarter of unit circle */
192 if (n
) {a
=-a
;da
=-da
;}
195 t
= (((((s5
.x
*xx
+ s4
.x
)*xx
+ s3
.x
)*xx
+ s2
.x
)*xx
+ s1
.x
)*a
- 0.5*da
)*xx
+da
;
198 cor
= (cor
>0)? 1.02*cor
+eps
: 1.02*cor
-eps
;
199 retval
= (res
== res
+ cor
)? res
: sloww(a
,da
,x
);
210 s
= y
+ (db
+y
*xx
*(sn3
+xx
*sn5
));
211 c
= y
*db
+xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
214 ssn
=__sincostab
.x
[k
+1];
215 cs
=__sincostab
.x
[k
+2];
216 ccs
=__sincostab
.x
[k
+3];
217 cor
=(ssn
+s
*ccs
-sn
*c
)+cs
*s
;
220 cor
= (cor
>0)? 1.035*cor
+eps
: 1.035*cor
-eps
;
221 retval
= (res
==res
+cor
)? ((m
)?res
:-res
) : sloww1(a
,da
,x
);
235 ssn
=__sincostab
.x
[k
+1];
236 cs
=__sincostab
.x
[k
+2];
237 ccs
=__sincostab
.x
[k
+3];
238 s
= y
+ y
*xx
*(sn3
+xx
*sn5
);
239 c
= xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
240 cor
=(ccs
-s
*ssn
-cs
*c
)-sn
*s
;
243 cor
= (cor
>0)? 1.025*cor
+eps
: 1.025*cor
-eps
;
244 retval
= (res
==res
+cor
)? ((n
&2)?-res
:res
) : sloww2(a
,da
,x
,n
);
251 } /* else if (k < 0x419921FB ) */
253 /*---------------------105414350 <|x|< 281474976710656 --------------------*/
254 else if (k
< 0x42F00000 ) {
255 t
= (x
*hpinv
.x
+ toint
.x
);
258 xn1
= (xn
+8.0e22
)-8.0e22
;
260 y
= ((((x
- xn1
*mp1
.x
) - xn1
*mp2
.x
)-xn2
*mp1
.x
)-xn2
*mp2
.x
);
265 da
= (da
- xn2
*pp3
.x
) -xn
*pp4
.x
;
274 if (n
) {a
=-a
;da
=-da
;}
277 t
= (((((s5
.x
*xx
+ s4
.x
)*xx
+ s3
.x
)*xx
+ s2
.x
)*xx
+ s1
.x
)*a
- 0.5*da
)*xx
+da
;
280 cor
= (cor
>0)? 1.02*cor
+eps
: 1.02*cor
-eps
;
281 retval
= (res
== res
+ cor
)? res
: bsloww(a
,da
,x
,n
);
285 if (a
>0) {m
=1;t
=a
;db
=da
;}
286 else {m
=0;t
=-a
;db
=-da
;}
290 s
= y
+ (db
+y
*xx
*(sn3
+xx
*sn5
));
291 c
= y
*db
+xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
294 ssn
=__sincostab
.x
[k
+1];
295 cs
=__sincostab
.x
[k
+2];
296 ccs
=__sincostab
.x
[k
+3];
297 cor
=(ssn
+s
*ccs
-sn
*c
)+cs
*s
;
300 cor
= (cor
>0)? 1.035*cor
+eps
: 1.035*cor
-eps
;
301 retval
= (res
==res
+cor
)? ((m
)?res
:-res
) : bsloww1(a
,da
,x
,n
);
315 ssn
=__sincostab
.x
[k
+1];
316 cs
=__sincostab
.x
[k
+2];
317 ccs
=__sincostab
.x
[k
+3];
318 s
= y
+ y
*xx
*(sn3
+xx
*sn5
);
319 c
= xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
320 cor
=(ccs
-s
*ssn
-cs
*c
)-sn
*s
;
323 cor
= (cor
>0)? 1.025*cor
+eps
: 1.025*cor
-eps
;
324 retval
= (res
==res
+cor
)? ((n
&2)?-res
:res
) : bsloww2(a
,da
,x
,n
);
331 } /* else if (k < 0x42F00000 ) */
333 /* -----------------281474976710656 <|x| <2^1024----------------------------*/
334 else if (k
< 0x7ff00000) {
336 n
= __branred(x
,&a
,&da
);
339 if (a
*a
< 0.01588) retval
= bsloww(a
,da
,x
,n
);
340 else retval
= bsloww1(a
,da
,x
,n
);
344 if (a
*a
< 0.01588) retval
= bsloww(-a
,-da
,x
,n
);
345 else retval
= bsloww1(-a
,-da
,x
,n
);
351 retval
= bsloww2(a
,da
,x
,n
);
356 } /* else if (k < 0x7ff00000 ) */
358 /*--------------------- |x| > 2^1024 ----------------------------------*/
360 if (k
== 0x7ff00000 && u
.i
[LOW_HALF
] == 0)
371 /*******************************************************************/
372 /* An ultimate cos routine. Given an IEEE double machine number x */
373 /* it computes the correctly rounded (to nearest) value of cos(x) */
374 /*******************************************************************/
380 double y
,xx
,res
,t
,cor
,s
,c
,sn
,ssn
,cs
,ccs
,xn
,a
,da
,db
,eps
,xn1
,xn2
;
386 SET_RESTORE_ROUND_53BIT (FE_TONEAREST
);
392 if (k
< 0x3e400000 ) { retval
= 1.0; goto ret
; } /* |x|<2^-27 => cos(x)=1 */
394 else if (k
< 0x3feb6000 ) {/* 2^-27 < |x| < 0.855469 */
399 s
= y
+ y
*xx
*(sn3
+xx
*sn5
);
400 c
= xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
403 ssn
=__sincostab
.x
[k
+1];
404 cs
=__sincostab
.x
[k
+2];
405 ccs
=__sincostab
.x
[k
+3];
406 cor
=(ccs
-s
*ssn
-cs
*c
)-sn
*s
;
409 retval
= (res
==res
+1.020*cor
)? res
: cslow2(x
);
412 } /* else if (k < 0x3feb6000) */
414 else if (k
< 0x400368fd ) {/* 0.855469 <|x|<2.426265 */;
420 t
= (((((s5
.x
*xx
+ s4
.x
)*xx
+ s3
.x
)*xx
+ s2
.x
)*xx
+ s1
.x
)*a
- 0.5*da
)*xx
+da
;
423 cor
= (cor
>0)? 1.02*cor
+1.0e-31 : 1.02*cor
-1.0e-31;
424 retval
= (res
== res
+ cor
)? res
: csloww(a
,da
,x
);
428 if (a
>0) {m
=1;t
=a
;db
=da
;}
429 else {m
=0;t
=-a
;db
=-da
;}
433 s
= y
+ (db
+y
*xx
*(sn3
+xx
*sn5
));
434 c
= y
*db
+xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
437 ssn
=__sincostab
.x
[k
+1];
438 cs
=__sincostab
.x
[k
+2];
439 ccs
=__sincostab
.x
[k
+3];
440 cor
=(ssn
+s
*ccs
-sn
*c
)+cs
*s
;
443 cor
= (cor
>0)? 1.035*cor
+1.0e-31 : 1.035*cor
-1.0e-31;
444 retval
= (res
==res
+cor
)? ((m
)?res
:-res
) : csloww1(a
,da
,x
);
448 } /* else if (k < 0x400368fd) */
451 else if (k
< 0x419921FB ) {/* 2.426265<|x|< 105414350 */
452 t
= (x
*hpinv
.x
+ toint
.x
);
455 y
= (x
- xn
*mp1
.x
) - xn
*mp2
.x
;
460 eps
= ABS(x
)*1.2e-30;
466 if (n
== 1) {a
=-a
;da
=-da
;}
468 t
= (((((s5
.x
*xx
+ s4
.x
)*xx
+ s3
.x
)*xx
+ s2
.x
)*xx
+ s1
.x
)*a
- 0.5*da
)*xx
+da
;
471 cor
= (cor
>0)? 1.02*cor
+eps
: 1.02*cor
-eps
;
472 retval
= (res
== res
+ cor
)? res
: csloww(a
,da
,x
);
476 if (a
>0) {m
=1;t
=a
;db
=da
;}
477 else {m
=0;t
=-a
;db
=-da
;}
481 s
= y
+ (db
+y
*xx
*(sn3
+xx
*sn5
));
482 c
= y
*db
+xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
485 ssn
=__sincostab
.x
[k
+1];
486 cs
=__sincostab
.x
[k
+2];
487 ccs
=__sincostab
.x
[k
+3];
488 cor
=(ssn
+s
*ccs
-sn
*c
)+cs
*s
;
491 cor
= (cor
>0)? 1.035*cor
+eps
: 1.035*cor
-eps
;
492 retval
= (res
==res
+cor
)? ((m
)?res
:-res
) : csloww1(a
,da
,x
);
499 if (a
<0) {a
=-a
;da
=-da
;}
505 ssn
=__sincostab
.x
[k
+1];
506 cs
=__sincostab
.x
[k
+2];
507 ccs
=__sincostab
.x
[k
+3];
508 s
= y
+ y
*xx
*(sn3
+xx
*sn5
);
509 c
= xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
510 cor
=(ccs
-s
*ssn
-cs
*c
)-sn
*s
;
513 cor
= (cor
>0)? 1.025*cor
+eps
: 1.025*cor
-eps
;
514 retval
= (res
==res
+cor
)? ((n
)?-res
:res
) : csloww2(a
,da
,x
,n
);
521 } /* else if (k < 0x419921FB ) */
524 else if (k
< 0x42F00000 ) {
525 t
= (x
*hpinv
.x
+ toint
.x
);
528 xn1
= (xn
+8.0e22
)-8.0e22
;
530 y
= ((((x
- xn1
*mp1
.x
) - xn1
*mp2
.x
)-xn2
*mp1
.x
)-xn2
*mp2
.x
);
535 da
= (da
- xn2
*pp3
.x
) -xn
*pp4
.x
;
544 if (n
==1) {a
=-a
;da
=-da
;}
546 t
= (((((s5
.x
*xx
+ s4
.x
)*xx
+ s3
.x
)*xx
+ s2
.x
)*xx
+ s1
.x
)*a
- 0.5*da
)*xx
+da
;
549 cor
= (cor
>0)? 1.02*cor
+eps
: 1.02*cor
-eps
;
550 retval
= (res
== res
+ cor
)? res
: bsloww(a
,da
,x
,n
);
554 if (a
>0) {m
=1;t
=a
;db
=da
;}
555 else {m
=0;t
=-a
;db
=-da
;}
559 s
= y
+ (db
+y
*xx
*(sn3
+xx
*sn5
));
560 c
= y
*db
+xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
563 ssn
=__sincostab
.x
[k
+1];
564 cs
=__sincostab
.x
[k
+2];
565 ccs
=__sincostab
.x
[k
+3];
566 cor
=(ssn
+s
*ccs
-sn
*c
)+cs
*s
;
569 cor
= (cor
>0)? 1.035*cor
+eps
: 1.035*cor
-eps
;
570 retval
= (res
==res
+cor
)? ((m
)?res
:-res
) : bsloww1(a
,da
,x
,n
);
577 if (a
<0) {a
=-a
;da
=-da
;}
583 ssn
=__sincostab
.x
[k
+1];
584 cs
=__sincostab
.x
[k
+2];
585 ccs
=__sincostab
.x
[k
+3];
586 s
= y
+ y
*xx
*(sn3
+xx
*sn5
);
587 c
= xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
588 cor
=(ccs
-s
*ssn
-cs
*c
)-sn
*s
;
591 cor
= (cor
>0)? 1.025*cor
+eps
: 1.025*cor
-eps
;
592 retval
= (res
==res
+cor
)? ((n
)?-res
:res
) : bsloww2(a
,da
,x
,n
);
598 } /* else if (k < 0x42F00000 ) */
600 else if (k
< 0x7ff00000) {/* 281474976710656 <|x| <2^1024 */
602 n
= __branred(x
,&a
,&da
);
605 if (a
*a
< 0.01588) retval
= bsloww(-a
,-da
,x
,n
);
606 else retval
= bsloww1(-a
,-da
,x
,n
);
610 if (a
*a
< 0.01588) retval
= bsloww(a
,da
,x
,n
);
611 else retval
= bsloww1(a
,da
,x
,n
);
617 retval
= bsloww2(a
,da
,x
,n
);
622 } /* else if (k < 0x7ff00000 ) */
628 if (k
== 0x7ff00000 && u
.i
[LOW_HALF
] == 0)
630 retval
= x
/ x
; /* |x| > 2^1024 */
638 /************************************************************************/
639 /* Routine compute sin(x) for 2^-26 < |x|< 0.25 by Taylor with more */
640 /* precision and if still doesn't accurate enough by mpsin or dubsin */
641 /************************************************************************/
646 static const double th2_36
= 206158430208.0; /* 1.5*2**37 */
647 double y
,x1
,x2
,xx
,r
,t
,res
,cor
,w
[2];
648 x1
=(x
+th2_36
)-th2_36
;
653 t
= (((((s5
.x
*xx
+ s4
.x
)*xx
+ s3
.x
)*xx
+ s2
.x
)*xx
+ bb
.x
)*xx
+ 3.0*aa
.x
*x1
*x2
)*x
+aa
.x
*x2
*x2
*x2
;
657 if (res
== res
+ 1.0007*cor
) return res
;
659 __dubsin(ABS(x
),0,w
);
660 if (w
[0] == w
[0]+1.000000001*w
[1]) return (x
>0)?w
[0]:-w
[0];
661 else return (x
>0)?__mpsin(x
,0):-__mpsin(-x
,0);
664 /*******************************************************************************/
665 /* Routine compute sin(x) for 0.25<|x|< 0.855469 by __sincostab.tbl and Taylor */
666 /* and if result still doesn't accurate enough by mpsin or dubsin */
667 /*******************************************************************************/
673 double sn
,ssn
,cs
,ccs
,s
,c
,w
[2],y
,y1
,y2
,c1
,c2
,xx
,cor
,res
;
674 static const double t22
= 6291456.0;
680 s
= y
*xx
*(sn3
+xx
*sn5
);
681 c
= xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
683 sn
=__sincostab
.x
[k
]; /* Data */
684 ssn
=__sincostab
.x
[k
+1]; /* from */
685 cs
=__sincostab
.x
[k
+2]; /* tables */
686 ccs
=__sincostab
.x
[k
+3]; /* __sincostab.tbl */
691 cor
=(ssn
+s
*ccs
+cs
*s
+c2
*y
+c1
*y2
)-sn
*c
;
693 cor
= cor
+((sn
-y
)+c1
*y1
);
696 if (res
== res
+1.0005*cor
) return (x
>0)?res
:-res
;
698 __dubsin(ABS(x
),0,w
);
699 if (w
[0] == w
[0]+1.000000005*w
[1]) return (x
>0)?w
[0]:-w
[0];
700 else return (x
>0)?__mpsin(x
,0):-__mpsin(-x
,0);
703 /**************************************************************************/
704 /* Routine compute sin(x) for 0.855469 <|x|<2.426265 by __sincostab.tbl */
705 /* and if result still doesn't accurate enough by mpsin or dubsin */
706 /**************************************************************************/
711 double sn
,ssn
,cs
,ccs
,s
,c
,w
[2],y
,y1
,y2
,e1
,e2
,xx
,cor
,res
,del
;
712 static const double t22
= 6291456.0;
723 y
= -(y
+(u
.x
-big
.x
));
727 s
= y
*xx
*(sn3
+xx
*sn5
);
728 c
= y
*del
+xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
731 ssn
=__sincostab
.x
[k
+1];
732 cs
=__sincostab
.x
[k
+2];
733 ccs
=__sincostab
.x
[k
+3];
738 cor
=(ccs
-cs
*c
-e1
*y2
-e2
*y
)-sn
*s
;
740 cor
= cor
+((cs
-y
)-e1
*y1
);
743 if (res
== res
+1.0005*cor
) return (x
>0)?res
:-res
;
749 if (w
[0] == w
[0]+1.000000005*w
[1]) return (x
>0)?w
[0]:-w
[0];
750 else return (x
>0)?__mpsin(x
,0):-__mpsin(-x
,0);
753 /***************************************************************************/
754 /* Routine compute sin(x+dx) (Double-Length number) where x is small enough*/
755 /* to use Taylor series around zero and (x+dx) */
756 /* in first or third quarter of unit circle.Routine receive also */
757 /* (right argument) the original value of x for computing error of */
758 /* result.And if result not accurate enough routine calls mpsin1 or dubsin */
759 /***************************************************************************/
763 sloww(double x
,double dx
, double orig
) {
764 static const double th2_36
= 206158430208.0; /* 1.5*2**37 */
765 double y
,x1
,x2
,xx
,r
,t
,res
,cor
,w
[2],a
,da
,xn
;
766 union {int4 i
[2]; double x
;} v
;
768 x1
=(x
+th2_36
)-th2_36
;
773 t
= (((((s5
.x
*xx
+ s4
.x
)*xx
+ s3
.x
)*xx
+ s2
.x
)*xx
+ bb
.x
)*xx
+ 3.0*aa
.x
*x1
*x2
)*x
+aa
.x
*x2
*x2
*x2
+dx
;
777 cor
= (cor
>0)? 1.0005*cor
+ABS(orig
)*3.1e-30 : 1.0005*cor
-ABS(orig
)*3.1e-30;
778 if (res
== res
+ cor
) return res
;
780 (x
>0)? __dubsin(x
,dx
,w
) : __dubsin(-x
,-dx
,w
);
781 cor
= (w
[1]>0)? 1.000000001*w
[1] + ABS(orig
)*1.1e-30 : 1.000000001*w
[1] - ABS(orig
)*1.1e-30;
782 if (w
[0] == w
[0]+cor
) return (x
>0)?w
[0]:-w
[0];
784 t
= (orig
*hpinv
.x
+ toint
.x
);
787 y
= (orig
- xn
*mp1
.x
) - xn
*mp2
.x
;
795 if (n
&2) {a
=-a
; da
=-da
;}
796 (a
>0)? __dubsin(a
,da
,w
) : __dubsin(-a
,-da
,w
);
797 cor
= (w
[1]>0)? 1.000000001*w
[1] + ABS(orig
)*1.1e-40 : 1.000000001*w
[1] - ABS(orig
)*1.1e-40;
798 if (w
[0] == w
[0]+cor
) return (a
>0)?w
[0]:-w
[0];
799 else return __mpsin1(orig
);
803 /***************************************************************************/
804 /* Routine compute sin(x+dx) (Double-Length number) where x in first or */
805 /* third quarter of unit circle.Routine receive also (right argument) the */
806 /* original value of x for computing error of result.And if result not */
807 /* accurate enough routine calls mpsin1 or dubsin */
808 /***************************************************************************/
812 sloww1(double x
, double dx
, double orig
) {
814 double sn
,ssn
,cs
,ccs
,s
,c
,w
[2],y
,y1
,y2
,c1
,c2
,xx
,cor
,res
;
815 static const double t22
= 6291456.0;
822 s
= y
*xx
*(sn3
+xx
*sn5
);
823 c
= xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
826 ssn
=__sincostab
.x
[k
+1];
827 cs
=__sincostab
.x
[k
+2];
828 ccs
=__sincostab
.x
[k
+3];
833 cor
=(ssn
+s
*ccs
+cs
*s
+c2
*y
+c1
*y2
-sn
*y
*dx
)-sn
*c
;
835 cor
= cor
+((sn
-y
)+c1
*y1
);
838 cor
= (cor
>0)? 1.0005*cor
+3.1e-30*ABS(orig
) : 1.0005*cor
-3.1e-30*ABS(orig
);
839 if (res
== res
+ cor
) return (x
>0)?res
:-res
;
841 __dubsin(ABS(x
),dx
,w
);
842 cor
= (w
[1]>0)? 1.000000005*w
[1]+1.1e-30*ABS(orig
) : 1.000000005*w
[1]-1.1e-30*ABS(orig
);
843 if (w
[0] == w
[0]+cor
) return (x
>0)?w
[0]:-w
[0];
844 else return __mpsin1(orig
);
847 /***************************************************************************/
848 /* Routine compute sin(x+dx) (Double-Length number) where x in second or */
849 /* fourth quarter of unit circle.Routine receive also the original value */
850 /* and quarter(n= 1or 3)of x for computing error of result.And if result not*/
851 /* accurate enough routine calls mpsin1 or dubsin */
852 /***************************************************************************/
856 sloww2(double x
, double dx
, double orig
, int n
) {
858 double sn
,ssn
,cs
,ccs
,s
,c
,w
[2],y
,y1
,y2
,e1
,e2
,xx
,cor
,res
;
859 static const double t22
= 6291456.0;
866 s
= y
*xx
*(sn3
+xx
*sn5
);
867 c
= y
*dx
+xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
870 ssn
=__sincostab
.x
[k
+1];
871 cs
=__sincostab
.x
[k
+2];
872 ccs
=__sincostab
.x
[k
+3];
878 cor
=(ccs
-cs
*c
-e1
*y2
-e2
*y
)-sn
*s
;
880 cor
= cor
+((cs
-y
)-e1
*y1
);
883 cor
= (cor
>0)? 1.0005*cor
+3.1e-30*ABS(orig
) : 1.0005*cor
-3.1e-30*ABS(orig
);
884 if (res
== res
+ cor
) return (n
&2)?-res
:res
;
886 __docos(ABS(x
),dx
,w
);
887 cor
= (w
[1]>0)? 1.000000005*w
[1]+1.1e-30*ABS(orig
) : 1.000000005*w
[1]-1.1e-30*ABS(orig
);
888 if (w
[0] == w
[0]+cor
) return (n
&2)?-w
[0]:w
[0];
889 else return __mpsin1(orig
);
892 /***************************************************************************/
893 /* Routine compute sin(x+dx) or cos(x+dx) (Double-Length number) where x */
894 /* is small enough to use Taylor series around zero and (x+dx) */
895 /* in first or third quarter of unit circle.Routine receive also */
896 /* (right argument) the original value of x for computing error of */
897 /* result.And if result not accurate enough routine calls other routines */
898 /***************************************************************************/
902 bsloww(double x
,double dx
, double orig
,int n
) {
903 static const double th2_36
= 206158430208.0; /* 1.5*2**37 */
904 double y
,x1
,x2
,xx
,r
,t
,res
,cor
,w
[2];
907 union {int4 i
[2]; double x
;} v
;
909 x1
=(x
+th2_36
)-th2_36
;
914 t
= (((((s5
.x
*xx
+ s4
.x
)*xx
+ s3
.x
)*xx
+ s2
.x
)*xx
+ bb
.x
)*xx
+ 3.0*aa
.x
*x1
*x2
)*x
+aa
.x
*x2
*x2
*x2
+dx
;
918 cor
= (cor
>0)? 1.0005*cor
+1.1e-24 : 1.0005*cor
-1.1e-24;
919 if (res
== res
+ cor
) return res
;
921 (x
>0)? __dubsin(x
,dx
,w
) : __dubsin(-x
,-dx
,w
);
922 cor
= (w
[1]>0)? 1.000000001*w
[1] + 1.1e-24 : 1.000000001*w
[1] - 1.1e-24;
923 if (w
[0] == w
[0]+cor
) return (x
>0)?w
[0]:-w
[0];
924 else return (n
&1)?__mpcos1(orig
):__mpsin1(orig
);
928 /***************************************************************************/
929 /* Routine compute sin(x+dx) or cos(x+dx) (Double-Length number) where x */
930 /* in first or third quarter of unit circle.Routine receive also */
931 /* (right argument) the original value of x for computing error of result.*/
932 /* And if result not accurate enough routine calls other routines */
933 /***************************************************************************/
937 bsloww1(double x
, double dx
, double orig
,int n
) {
939 double sn
,ssn
,cs
,ccs
,s
,c
,w
[2],y
,y1
,y2
,c1
,c2
,xx
,cor
,res
;
940 static const double t22
= 6291456.0;
947 s
= y
*xx
*(sn3
+xx
*sn5
);
948 c
= xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
951 ssn
=__sincostab
.x
[k
+1];
952 cs
=__sincostab
.x
[k
+2];
953 ccs
=__sincostab
.x
[k
+3];
958 cor
=(ssn
+s
*ccs
+cs
*s
+c2
*y
+c1
*y2
-sn
*y
*dx
)-sn
*c
;
960 cor
= cor
+((sn
-y
)+c1
*y1
);
963 cor
= (cor
>0)? 1.0005*cor
+1.1e-24 : 1.0005*cor
-1.1e-24;
964 if (res
== res
+ cor
) return (x
>0)?res
:-res
;
966 __dubsin(ABS(x
),dx
,w
);
967 cor
= (w
[1]>0)? 1.000000005*w
[1]+1.1e-24: 1.000000005*w
[1]-1.1e-24;
968 if (w
[0] == w
[0]+cor
) return (x
>0)?w
[0]:-w
[0];
969 else return (n
&1)?__mpcos1(orig
):__mpsin1(orig
);
973 /***************************************************************************/
974 /* Routine compute sin(x+dx) or cos(x+dx) (Double-Length number) where x */
975 /* in second or fourth quarter of unit circle.Routine receive also the */
976 /* original value and quarter(n= 1or 3)of x for computing error of result. */
977 /* And if result not accurate enough routine calls other routines */
978 /***************************************************************************/
982 bsloww2(double x
, double dx
, double orig
, int n
) {
984 double sn
,ssn
,cs
,ccs
,s
,c
,w
[2],y
,y1
,y2
,e1
,e2
,xx
,cor
,res
;
985 static const double t22
= 6291456.0;
992 s
= y
*xx
*(sn3
+xx
*sn5
);
993 c
= y
*dx
+xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
996 ssn
=__sincostab
.x
[k
+1];
997 cs
=__sincostab
.x
[k
+2];
998 ccs
=__sincostab
.x
[k
+3];
1004 cor
=(ccs
-cs
*c
-e1
*y2
-e2
*y
)-sn
*s
;
1006 cor
= cor
+((cs
-y
)-e1
*y1
);
1009 cor
= (cor
>0)? 1.0005*cor
+1.1e-24 : 1.0005*cor
-1.1e-24;
1010 if (res
== res
+ cor
) return (n
&2)?-res
:res
;
1012 __docos(ABS(x
),dx
,w
);
1013 cor
= (w
[1]>0)? 1.000000005*w
[1]+1.1e-24 : 1.000000005*w
[1]-1.1e-24;
1014 if (w
[0] == w
[0]+cor
) return (n
&2)?-w
[0]:w
[0];
1015 else return (n
&1)?__mpsin1(orig
):__mpcos1(orig
);
1019 /************************************************************************/
1020 /* Routine compute cos(x) for 2^-27 < |x|< 0.25 by Taylor with more */
1021 /* precision and if still doesn't accurate enough by mpcos or docos */
1022 /************************************************************************/
1028 double sn
,ssn
,cs
,ccs
,s
,c
,w
[2],y
,y1
,y2
,e1
,e2
,xx
,cor
,res
;
1029 static const double t22
= 6291456.0;
1035 s
= y
*xx
*(sn3
+xx
*sn5
);
1036 c
= xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
1038 sn
=__sincostab
.x
[k
];
1039 ssn
=__sincostab
.x
[k
+1];
1040 cs
=__sincostab
.x
[k
+2];
1041 ccs
=__sincostab
.x
[k
+3];
1046 cor
=(ccs
-cs
*c
-e1
*y2
-e2
*y
)-sn
*s
;
1048 cor
= cor
+((cs
-y
)-e1
*y1
);
1051 if (res
== res
+1.0005*cor
)
1056 if (w
[0] == w
[0]+1.000000005*w
[1]) return w
[0];
1057 else return __mpcos(x
,0);
1061 /***************************************************************************/
1062 /* Routine compute cos(x+dx) (Double-Length number) where x is small enough*/
1063 /* to use Taylor series around zero and (x+dx) .Routine receive also */
1064 /* (right argument) the original value of x for computing error of */
1065 /* result.And if result not accurate enough routine calls other routines */
1066 /***************************************************************************/
1071 csloww(double x
,double dx
, double orig
) {
1072 static const double th2_36
= 206158430208.0; /* 1.5*2**37 */
1073 double y
,x1
,x2
,xx
,r
,t
,res
,cor
,w
[2],a
,da
,xn
;
1074 union {int4 i
[2]; double x
;} v
;
1076 x1
=(x
+th2_36
)-th2_36
;
1082 t
= (((((s5
.x
*xx
+ s4
.x
)*xx
+ s3
.x
)*xx
+ s2
.x
)*xx
+ bb
.x
)*xx
+ 3.0*aa
.x
*x1
*x2
)*x
+aa
.x
*x2
*x2
*x2
+dx
;
1086 cor
= (cor
>0)? 1.0005*cor
+ABS(orig
)*3.1e-30 : 1.0005*cor
-ABS(orig
)*3.1e-30;
1087 if (res
== res
+ cor
) return res
;
1089 (x
>0)? __dubsin(x
,dx
,w
) : __dubsin(-x
,-dx
,w
);
1090 cor
= (w
[1]>0)? 1.000000001*w
[1] + ABS(orig
)*1.1e-30 : 1.000000001*w
[1] - ABS(orig
)*1.1e-30;
1091 if (w
[0] == w
[0]+cor
) return (x
>0)?w
[0]:-w
[0];
1093 t
= (orig
*hpinv
.x
+ toint
.x
);
1096 y
= (orig
- xn
*mp1
.x
) - xn
*mp2
.x
;
1104 if (n
==1) {a
=-a
; da
=-da
;}
1105 (a
>0)? __dubsin(a
,da
,w
) : __dubsin(-a
,-da
,w
);
1106 cor
= (w
[1]>0)? 1.000000001*w
[1] + ABS(orig
)*1.1e-40 : 1.000000001*w
[1] - ABS(orig
)*1.1e-40;
1107 if (w
[0] == w
[0]+cor
) return (a
>0)?w
[0]:-w
[0];
1108 else return __mpcos1(orig
);
1113 /***************************************************************************/
1114 /* Routine compute sin(x+dx) (Double-Length number) where x in first or */
1115 /* third quarter of unit circle.Routine receive also (right argument) the */
1116 /* original value of x for computing error of result.And if result not */
1117 /* accurate enough routine calls other routines */
1118 /***************************************************************************/
1122 csloww1(double x
, double dx
, double orig
) {
1124 double sn
,ssn
,cs
,ccs
,s
,c
,w
[2],y
,y1
,y2
,c1
,c2
,xx
,cor
,res
;
1125 static const double t22
= 6291456.0;
1132 s
= y
*xx
*(sn3
+xx
*sn5
);
1133 c
= xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
1135 sn
=__sincostab
.x
[k
];
1136 ssn
=__sincostab
.x
[k
+1];
1137 cs
=__sincostab
.x
[k
+2];
1138 ccs
=__sincostab
.x
[k
+3];
1143 cor
=(ssn
+s
*ccs
+cs
*s
+c2
*y
+c1
*y2
-sn
*y
*dx
)-sn
*c
;
1145 cor
= cor
+((sn
-y
)+c1
*y1
);
1148 cor
= (cor
>0)? 1.0005*cor
+3.1e-30*ABS(orig
) : 1.0005*cor
-3.1e-30*ABS(orig
);
1149 if (res
== res
+ cor
) return (x
>0)?res
:-res
;
1151 __dubsin(ABS(x
),dx
,w
);
1152 cor
= (w
[1]>0)? 1.000000005*w
[1]+1.1e-30*ABS(orig
) : 1.000000005*w
[1]-1.1e-30*ABS(orig
);
1153 if (w
[0] == w
[0]+cor
) return (x
>0)?w
[0]:-w
[0];
1154 else return __mpcos1(orig
);
1159 /***************************************************************************/
1160 /* Routine compute sin(x+dx) (Double-Length number) where x in second or */
1161 /* fourth quarter of unit circle.Routine receive also the original value */
1162 /* and quarter(n= 1or 3)of x for computing error of result.And if result not*/
1163 /* accurate enough routine calls other routines */
1164 /***************************************************************************/
1168 csloww2(double x
, double dx
, double orig
, int n
) {
1170 double sn
,ssn
,cs
,ccs
,s
,c
,w
[2],y
,y1
,y2
,e1
,e2
,xx
,cor
,res
;
1171 static const double t22
= 6291456.0;
1178 s
= y
*xx
*(sn3
+xx
*sn5
);
1179 c
= y
*dx
+xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
1181 sn
=__sincostab
.x
[k
];
1182 ssn
=__sincostab
.x
[k
+1];
1183 cs
=__sincostab
.x
[k
+2];
1184 ccs
=__sincostab
.x
[k
+3];
1190 cor
=(ccs
-cs
*c
-e1
*y2
-e2
*y
)-sn
*s
;
1192 cor
= cor
+((cs
-y
)-e1
*y1
);
1195 cor
= (cor
>0)? 1.0005*cor
+3.1e-30*ABS(orig
) : 1.0005*cor
-3.1e-30*ABS(orig
);
1196 if (res
== res
+ cor
) return (n
)?-res
:res
;
1198 __docos(ABS(x
),dx
,w
);
1199 cor
= (w
[1]>0)? 1.000000005*w
[1]+1.1e-30*ABS(orig
) : 1.000000005*w
[1]-1.1e-30*ABS(orig
);
1200 if (w
[0] == w
[0]+cor
) return (n
)?-w
[0]:w
[0];
1201 else return __mpcos1(orig
);
1206 weak_alias (__cos
, cos
)
1207 # ifdef NO_LONG_DOUBLE
1208 strong_alias (__cos
, __cosl
)
1209 weak_alias (__cos
, cosl
)
1213 weak_alias (__sin
, sin
)
1214 # ifdef NO_LONG_DOUBLE
1215 strong_alias (__sin
, __sinl
)
1216 weak_alias (__sin
, sinl
)