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
;
114 libc_feholdexcept_setround_53bit (&env
, FE_TONEAREST
);
118 k
= 0x7fffffff&m
; /* no sign */
119 if (k
< 0x3e500000) /* if x->0 =>sin(x)=x */
120 { retval
= x
; goto ret
; }
121 /*---------------------------- 2^-26 < |x|< 0.25 ----------------------*/
122 else if (k
< 0x3fd00000){
125 t
= ((((s5
.x
*xx
+ s4
.x
)*xx
+ s3
.x
)*xx
+ s2
.x
)*xx
+ s1
.x
)*(xx
*x
);
128 retval
= (res
== res
+ 1.07*cor
)? res
: slow(x
);
130 } /* else if (k < 0x3fd00000) */
131 /*---------------------------- 0.25<|x|< 0.855469---------------------- */
132 else if (k
< 0x3feb6000) {
133 u
.x
=(m
>0)?big
.x
+x
:big
.x
-x
;
134 y
=(m
>0)?x
-(u
.x
-big
.x
):x
+(u
.x
-big
.x
);
136 s
= y
+ y
*xx
*(sn3
+xx
*sn5
);
137 c
= xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
139 sn
=(m
>0)?__sincostab
.x
[k
]:-__sincostab
.x
[k
];
140 ssn
=(m
>0)?__sincostab
.x
[k
+1]:-__sincostab
.x
[k
+1];
141 cs
=__sincostab
.x
[k
+2];
142 ccs
=__sincostab
.x
[k
+3];
143 cor
=(ssn
+s
*ccs
-sn
*c
)+cs
*s
;
146 retval
= (res
==res
+1.096*cor
)? res
: slow1(x
);
148 } /* else if (k < 0x3feb6000) */
150 /*----------------------- 0.855469 <|x|<2.426265 ----------------------*/
151 else if (k
< 0x400368fd ) {
153 y
= (m
>0)? hp0
.x
-x
:hp0
.x
+x
;
156 y
= (y
-(u
.x
-big
.x
))+hp1
.x
;
160 y
= (-hp1
.x
) - (y
+(u
.x
-big
.x
));
163 s
= y
+ y
*xx
*(sn3
+xx
*sn5
);
164 c
= xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
167 ssn
=__sincostab
.x
[k
+1];
168 cs
=__sincostab
.x
[k
+2];
169 ccs
=__sincostab
.x
[k
+3];
170 cor
=(ccs
-s
*ssn
-cs
*c
)-sn
*s
;
173 retval
= (res
==res
+1.020*cor
)? ((m
>0)?res
:-res
) : slow2(x
);
175 } /* else if (k < 0x400368fd) */
177 /*-------------------------- 2.426265<|x|< 105414350 ----------------------*/
178 else if (k
< 0x419921FB ) {
179 t
= (x
*hpinv
.x
+ toint
.x
);
182 y
= (x
- xn
*mp1
.x
) - xn
*mp2
.x
;
187 eps
= ABS(x
)*1.2e-30;
189 switch (n
) { /* quarter of unit circle */
193 if (n
) {a
=-a
;da
=-da
;}
196 t
= (((((s5
.x
*xx
+ s4
.x
)*xx
+ s3
.x
)*xx
+ s2
.x
)*xx
+ s1
.x
)*a
- 0.5*da
)*xx
+da
;
199 cor
= (cor
>0)? 1.02*cor
+eps
: 1.02*cor
-eps
;
200 retval
= (res
== res
+ cor
)? res
: sloww(a
,da
,x
);
211 s
= y
+ (db
+y
*xx
*(sn3
+xx
*sn5
));
212 c
= y
*db
+xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
215 ssn
=__sincostab
.x
[k
+1];
216 cs
=__sincostab
.x
[k
+2];
217 ccs
=__sincostab
.x
[k
+3];
218 cor
=(ssn
+s
*ccs
-sn
*c
)+cs
*s
;
221 cor
= (cor
>0)? 1.035*cor
+eps
: 1.035*cor
-eps
;
222 retval
= (res
==res
+cor
)? ((m
)?res
:-res
) : sloww1(a
,da
,x
);
236 ssn
=__sincostab
.x
[k
+1];
237 cs
=__sincostab
.x
[k
+2];
238 ccs
=__sincostab
.x
[k
+3];
239 s
= y
+ y
*xx
*(sn3
+xx
*sn5
);
240 c
= xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
241 cor
=(ccs
-s
*ssn
-cs
*c
)-sn
*s
;
244 cor
= (cor
>0)? 1.025*cor
+eps
: 1.025*cor
-eps
;
245 retval
= (res
==res
+cor
)? ((n
&2)?-res
:res
) : sloww2(a
,da
,x
,n
);
252 } /* else if (k < 0x419921FB ) */
254 /*---------------------105414350 <|x|< 281474976710656 --------------------*/
255 else if (k
< 0x42F00000 ) {
256 t
= (x
*hpinv
.x
+ toint
.x
);
259 xn1
= (xn
+8.0e22
)-8.0e22
;
261 y
= ((((x
- xn1
*mp1
.x
) - xn1
*mp2
.x
)-xn2
*mp1
.x
)-xn2
*mp2
.x
);
266 da
= (da
- xn2
*pp3
.x
) -xn
*pp4
.x
;
275 if (n
) {a
=-a
;da
=-da
;}
278 t
= (((((s5
.x
*xx
+ s4
.x
)*xx
+ s3
.x
)*xx
+ s2
.x
)*xx
+ s1
.x
)*a
- 0.5*da
)*xx
+da
;
281 cor
= (cor
>0)? 1.02*cor
+eps
: 1.02*cor
-eps
;
282 retval
= (res
== res
+ cor
)? res
: bsloww(a
,da
,x
,n
);
286 if (a
>0) {m
=1;t
=a
;db
=da
;}
287 else {m
=0;t
=-a
;db
=-da
;}
291 s
= y
+ (db
+y
*xx
*(sn3
+xx
*sn5
));
292 c
= y
*db
+xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
295 ssn
=__sincostab
.x
[k
+1];
296 cs
=__sincostab
.x
[k
+2];
297 ccs
=__sincostab
.x
[k
+3];
298 cor
=(ssn
+s
*ccs
-sn
*c
)+cs
*s
;
301 cor
= (cor
>0)? 1.035*cor
+eps
: 1.035*cor
-eps
;
302 retval
= (res
==res
+cor
)? ((m
)?res
:-res
) : bsloww1(a
,da
,x
,n
);
316 ssn
=__sincostab
.x
[k
+1];
317 cs
=__sincostab
.x
[k
+2];
318 ccs
=__sincostab
.x
[k
+3];
319 s
= y
+ y
*xx
*(sn3
+xx
*sn5
);
320 c
= xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
321 cor
=(ccs
-s
*ssn
-cs
*c
)-sn
*s
;
324 cor
= (cor
>0)? 1.025*cor
+eps
: 1.025*cor
-eps
;
325 retval
= (res
==res
+cor
)? ((n
&2)?-res
:res
) : bsloww2(a
,da
,x
,n
);
332 } /* else if (k < 0x42F00000 ) */
334 /* -----------------281474976710656 <|x| <2^1024----------------------------*/
335 else if (k
< 0x7ff00000) {
337 n
= __branred(x
,&a
,&da
);
340 if (a
*a
< 0.01588) retval
= bsloww(a
,da
,x
,n
);
341 else retval
= bsloww1(a
,da
,x
,n
);
345 if (a
*a
< 0.01588) retval
= bsloww(-a
,-da
,x
,n
);
346 else retval
= bsloww1(-a
,-da
,x
,n
);
352 retval
= bsloww2(a
,da
,x
,n
);
357 } /* else if (k < 0x7ff00000 ) */
359 /*--------------------- |x| > 2^1024 ----------------------------------*/
361 if (k
== 0x7ff00000 && u
.i
[LOW_HALF
] == 0)
368 libc_feupdateenv_53bit (&env
);
373 /*******************************************************************/
374 /* An ultimate cos routine. Given an IEEE double machine number x */
375 /* it computes the correctly rounded (to nearest) value of cos(x) */
376 /*******************************************************************/
382 double y
,xx
,res
,t
,cor
,s
,c
,sn
,ssn
,cs
,ccs
,xn
,a
,da
,db
,eps
,xn1
,xn2
;
389 libc_feholdexcept_setround_53bit (&env
, FE_TONEAREST
);
395 if (k
< 0x3e400000 ) { retval
= 1.0; goto ret
; } /* |x|<2^-27 => cos(x)=1 */
397 else if (k
< 0x3feb6000 ) {/* 2^-27 < |x| < 0.855469 */
402 s
= y
+ y
*xx
*(sn3
+xx
*sn5
);
403 c
= xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
406 ssn
=__sincostab
.x
[k
+1];
407 cs
=__sincostab
.x
[k
+2];
408 ccs
=__sincostab
.x
[k
+3];
409 cor
=(ccs
-s
*ssn
-cs
*c
)-sn
*s
;
412 retval
= (res
==res
+1.020*cor
)? res
: cslow2(x
);
415 } /* else if (k < 0x3feb6000) */
417 else if (k
< 0x400368fd ) {/* 0.855469 <|x|<2.426265 */;
423 t
= (((((s5
.x
*xx
+ s4
.x
)*xx
+ s3
.x
)*xx
+ s2
.x
)*xx
+ s1
.x
)*a
- 0.5*da
)*xx
+da
;
426 cor
= (cor
>0)? 1.02*cor
+1.0e-31 : 1.02*cor
-1.0e-31;
427 retval
= (res
== res
+ cor
)? res
: csloww(a
,da
,x
);
431 if (a
>0) {m
=1;t
=a
;db
=da
;}
432 else {m
=0;t
=-a
;db
=-da
;}
436 s
= y
+ (db
+y
*xx
*(sn3
+xx
*sn5
));
437 c
= y
*db
+xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
440 ssn
=__sincostab
.x
[k
+1];
441 cs
=__sincostab
.x
[k
+2];
442 ccs
=__sincostab
.x
[k
+3];
443 cor
=(ssn
+s
*ccs
-sn
*c
)+cs
*s
;
446 cor
= (cor
>0)? 1.035*cor
+1.0e-31 : 1.035*cor
-1.0e-31;
447 retval
= (res
==res
+cor
)? ((m
)?res
:-res
) : csloww1(a
,da
,x
);
451 } /* else if (k < 0x400368fd) */
454 else if (k
< 0x419921FB ) {/* 2.426265<|x|< 105414350 */
455 t
= (x
*hpinv
.x
+ toint
.x
);
458 y
= (x
- xn
*mp1
.x
) - xn
*mp2
.x
;
463 eps
= ABS(x
)*1.2e-30;
469 if (n
== 1) {a
=-a
;da
=-da
;}
471 t
= (((((s5
.x
*xx
+ s4
.x
)*xx
+ s3
.x
)*xx
+ s2
.x
)*xx
+ s1
.x
)*a
- 0.5*da
)*xx
+da
;
474 cor
= (cor
>0)? 1.02*cor
+eps
: 1.02*cor
-eps
;
475 retval
= (res
== res
+ cor
)? res
: csloww(a
,da
,x
);
479 if (a
>0) {m
=1;t
=a
;db
=da
;}
480 else {m
=0;t
=-a
;db
=-da
;}
484 s
= y
+ (db
+y
*xx
*(sn3
+xx
*sn5
));
485 c
= y
*db
+xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
488 ssn
=__sincostab
.x
[k
+1];
489 cs
=__sincostab
.x
[k
+2];
490 ccs
=__sincostab
.x
[k
+3];
491 cor
=(ssn
+s
*ccs
-sn
*c
)+cs
*s
;
494 cor
= (cor
>0)? 1.035*cor
+eps
: 1.035*cor
-eps
;
495 retval
= (res
==res
+cor
)? ((m
)?res
:-res
) : csloww1(a
,da
,x
);
502 if (a
<0) {a
=-a
;da
=-da
;}
508 ssn
=__sincostab
.x
[k
+1];
509 cs
=__sincostab
.x
[k
+2];
510 ccs
=__sincostab
.x
[k
+3];
511 s
= y
+ y
*xx
*(sn3
+xx
*sn5
);
512 c
= xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
513 cor
=(ccs
-s
*ssn
-cs
*c
)-sn
*s
;
516 cor
= (cor
>0)? 1.025*cor
+eps
: 1.025*cor
-eps
;
517 retval
= (res
==res
+cor
)? ((n
)?-res
:res
) : csloww2(a
,da
,x
,n
);
524 } /* else if (k < 0x419921FB ) */
527 else if (k
< 0x42F00000 ) {
528 t
= (x
*hpinv
.x
+ toint
.x
);
531 xn1
= (xn
+8.0e22
)-8.0e22
;
533 y
= ((((x
- xn1
*mp1
.x
) - xn1
*mp2
.x
)-xn2
*mp1
.x
)-xn2
*mp2
.x
);
538 da
= (da
- xn2
*pp3
.x
) -xn
*pp4
.x
;
547 if (n
==1) {a
=-a
;da
=-da
;}
549 t
= (((((s5
.x
*xx
+ s4
.x
)*xx
+ s3
.x
)*xx
+ s2
.x
)*xx
+ s1
.x
)*a
- 0.5*da
)*xx
+da
;
552 cor
= (cor
>0)? 1.02*cor
+eps
: 1.02*cor
-eps
;
553 retval
= (res
== res
+ cor
)? res
: bsloww(a
,da
,x
,n
);
557 if (a
>0) {m
=1;t
=a
;db
=da
;}
558 else {m
=0;t
=-a
;db
=-da
;}
562 s
= y
+ (db
+y
*xx
*(sn3
+xx
*sn5
));
563 c
= y
*db
+xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
566 ssn
=__sincostab
.x
[k
+1];
567 cs
=__sincostab
.x
[k
+2];
568 ccs
=__sincostab
.x
[k
+3];
569 cor
=(ssn
+s
*ccs
-sn
*c
)+cs
*s
;
572 cor
= (cor
>0)? 1.035*cor
+eps
: 1.035*cor
-eps
;
573 retval
= (res
==res
+cor
)? ((m
)?res
:-res
) : bsloww1(a
,da
,x
,n
);
580 if (a
<0) {a
=-a
;da
=-da
;}
586 ssn
=__sincostab
.x
[k
+1];
587 cs
=__sincostab
.x
[k
+2];
588 ccs
=__sincostab
.x
[k
+3];
589 s
= y
+ y
*xx
*(sn3
+xx
*sn5
);
590 c
= xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
591 cor
=(ccs
-s
*ssn
-cs
*c
)-sn
*s
;
594 cor
= (cor
>0)? 1.025*cor
+eps
: 1.025*cor
-eps
;
595 retval
= (res
==res
+cor
)? ((n
)?-res
:res
) : bsloww2(a
,da
,x
,n
);
601 } /* else if (k < 0x42F00000 ) */
603 else if (k
< 0x7ff00000) {/* 281474976710656 <|x| <2^1024 */
605 n
= __branred(x
,&a
,&da
);
608 if (a
*a
< 0.01588) retval
= bsloww(-a
,-da
,x
,n
);
609 else retval
= bsloww1(-a
,-da
,x
,n
);
613 if (a
*a
< 0.01588) retval
= bsloww(a
,da
,x
,n
);
614 else retval
= bsloww1(a
,da
,x
,n
);
620 retval
= bsloww2(a
,da
,x
,n
);
625 } /* else if (k < 0x7ff00000 ) */
631 if (k
== 0x7ff00000 && u
.i
[LOW_HALF
] == 0)
633 retval
= x
/ x
; /* |x| > 2^1024 */
638 libc_feupdateenv_53bit (&env
);
642 /************************************************************************/
643 /* Routine compute sin(x) for 2^-26 < |x|< 0.25 by Taylor with more */
644 /* precision and if still doesn't accurate enough by mpsin or dubsin */
645 /************************************************************************/
650 static const double th2_36
= 206158430208.0; /* 1.5*2**37 */
651 double y
,x1
,x2
,xx
,r
,t
,res
,cor
,w
[2];
652 x1
=(x
+th2_36
)-th2_36
;
657 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
;
661 if (res
== res
+ 1.0007*cor
) return res
;
663 __dubsin(ABS(x
),0,w
);
664 if (w
[0] == w
[0]+1.000000001*w
[1]) return (x
>0)?w
[0]:-w
[0];
665 else return (x
>0)?__mpsin(x
,0):-__mpsin(-x
,0);
668 /*******************************************************************************/
669 /* Routine compute sin(x) for 0.25<|x|< 0.855469 by __sincostab.tbl and Taylor */
670 /* and if result still doesn't accurate enough by mpsin or dubsin */
671 /*******************************************************************************/
677 double sn
,ssn
,cs
,ccs
,s
,c
,w
[2],y
,y1
,y2
,c1
,c2
,xx
,cor
,res
;
678 static const double t22
= 6291456.0;
684 s
= y
*xx
*(sn3
+xx
*sn5
);
685 c
= xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
687 sn
=__sincostab
.x
[k
]; /* Data */
688 ssn
=__sincostab
.x
[k
+1]; /* from */
689 cs
=__sincostab
.x
[k
+2]; /* tables */
690 ccs
=__sincostab
.x
[k
+3]; /* __sincostab.tbl */
695 cor
=(ssn
+s
*ccs
+cs
*s
+c2
*y
+c1
*y2
)-sn
*c
;
697 cor
= cor
+((sn
-y
)+c1
*y1
);
700 if (res
== res
+1.0005*cor
) return (x
>0)?res
:-res
;
702 __dubsin(ABS(x
),0,w
);
703 if (w
[0] == w
[0]+1.000000005*w
[1]) return (x
>0)?w
[0]:-w
[0];
704 else return (x
>0)?__mpsin(x
,0):-__mpsin(-x
,0);
707 /**************************************************************************/
708 /* Routine compute sin(x) for 0.855469 <|x|<2.426265 by __sincostab.tbl */
709 /* and if result still doesn't accurate enough by mpsin or dubsin */
710 /**************************************************************************/
715 double sn
,ssn
,cs
,ccs
,s
,c
,w
[2],y
,y1
,y2
,e1
,e2
,xx
,cor
,res
,del
;
716 static const double t22
= 6291456.0;
727 y
= -(y
+(u
.x
-big
.x
));
731 s
= y
*xx
*(sn3
+xx
*sn5
);
732 c
= y
*del
+xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
735 ssn
=__sincostab
.x
[k
+1];
736 cs
=__sincostab
.x
[k
+2];
737 ccs
=__sincostab
.x
[k
+3];
742 cor
=(ccs
-cs
*c
-e1
*y2
-e2
*y
)-sn
*s
;
744 cor
= cor
+((cs
-y
)-e1
*y1
);
747 if (res
== res
+1.0005*cor
) return (x
>0)?res
:-res
;
753 if (w
[0] == w
[0]+1.000000005*w
[1]) return (x
>0)?w
[0]:-w
[0];
754 else return (x
>0)?__mpsin(x
,0):-__mpsin(-x
,0);
757 /***************************************************************************/
758 /* Routine compute sin(x+dx) (Double-Length number) where x is small enough*/
759 /* to use Taylor series around zero and (x+dx) */
760 /* in first or third quarter of unit circle.Routine receive also */
761 /* (right argument) the original value of x for computing error of */
762 /* result.And if result not accurate enough routine calls mpsin1 or dubsin */
763 /***************************************************************************/
767 sloww(double x
,double dx
, double orig
) {
768 static const double th2_36
= 206158430208.0; /* 1.5*2**37 */
769 double y
,x1
,x2
,xx
,r
,t
,res
,cor
,w
[2],a
,da
,xn
;
770 union {int4 i
[2]; double x
;} v
;
772 x1
=(x
+th2_36
)-th2_36
;
777 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
;
781 cor
= (cor
>0)? 1.0005*cor
+ABS(orig
)*3.1e-30 : 1.0005*cor
-ABS(orig
)*3.1e-30;
782 if (res
== res
+ cor
) return res
;
784 (x
>0)? __dubsin(x
,dx
,w
) : __dubsin(-x
,-dx
,w
);
785 cor
= (w
[1]>0)? 1.000000001*w
[1] + ABS(orig
)*1.1e-30 : 1.000000001*w
[1] - ABS(orig
)*1.1e-30;
786 if (w
[0] == w
[0]+cor
) return (x
>0)?w
[0]:-w
[0];
788 t
= (orig
*hpinv
.x
+ toint
.x
);
791 y
= (orig
- xn
*mp1
.x
) - xn
*mp2
.x
;
799 if (n
&2) {a
=-a
; da
=-da
;}
800 (a
>0)? __dubsin(a
,da
,w
) : __dubsin(-a
,-da
,w
);
801 cor
= (w
[1]>0)? 1.000000001*w
[1] + ABS(orig
)*1.1e-40 : 1.000000001*w
[1] - ABS(orig
)*1.1e-40;
802 if (w
[0] == w
[0]+cor
) return (a
>0)?w
[0]:-w
[0];
803 else return __mpsin1(orig
);
807 /***************************************************************************/
808 /* Routine compute sin(x+dx) (Double-Length number) where x in first or */
809 /* third quarter of unit circle.Routine receive also (right argument) the */
810 /* original value of x for computing error of result.And if result not */
811 /* accurate enough routine calls mpsin1 or dubsin */
812 /***************************************************************************/
816 sloww1(double x
, double dx
, double orig
) {
818 double sn
,ssn
,cs
,ccs
,s
,c
,w
[2],y
,y1
,y2
,c1
,c2
,xx
,cor
,res
;
819 static const double t22
= 6291456.0;
826 s
= y
*xx
*(sn3
+xx
*sn5
);
827 c
= xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
830 ssn
=__sincostab
.x
[k
+1];
831 cs
=__sincostab
.x
[k
+2];
832 ccs
=__sincostab
.x
[k
+3];
837 cor
=(ssn
+s
*ccs
+cs
*s
+c2
*y
+c1
*y2
-sn
*y
*dx
)-sn
*c
;
839 cor
= cor
+((sn
-y
)+c1
*y1
);
842 cor
= (cor
>0)? 1.0005*cor
+3.1e-30*ABS(orig
) : 1.0005*cor
-3.1e-30*ABS(orig
);
843 if (res
== res
+ cor
) return (x
>0)?res
:-res
;
845 __dubsin(ABS(x
),dx
,w
);
846 cor
= (w
[1]>0)? 1.000000005*w
[1]+1.1e-30*ABS(orig
) : 1.000000005*w
[1]-1.1e-30*ABS(orig
);
847 if (w
[0] == w
[0]+cor
) return (x
>0)?w
[0]:-w
[0];
848 else return __mpsin1(orig
);
851 /***************************************************************************/
852 /* Routine compute sin(x+dx) (Double-Length number) where x in second or */
853 /* fourth quarter of unit circle.Routine receive also the original value */
854 /* and quarter(n= 1or 3)of x for computing error of result.And if result not*/
855 /* accurate enough routine calls mpsin1 or dubsin */
856 /***************************************************************************/
860 sloww2(double x
, double dx
, double orig
, int n
) {
862 double sn
,ssn
,cs
,ccs
,s
,c
,w
[2],y
,y1
,y2
,e1
,e2
,xx
,cor
,res
;
863 static const double t22
= 6291456.0;
870 s
= y
*xx
*(sn3
+xx
*sn5
);
871 c
= y
*dx
+xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
874 ssn
=__sincostab
.x
[k
+1];
875 cs
=__sincostab
.x
[k
+2];
876 ccs
=__sincostab
.x
[k
+3];
882 cor
=(ccs
-cs
*c
-e1
*y2
-e2
*y
)-sn
*s
;
884 cor
= cor
+((cs
-y
)-e1
*y1
);
887 cor
= (cor
>0)? 1.0005*cor
+3.1e-30*ABS(orig
) : 1.0005*cor
-3.1e-30*ABS(orig
);
888 if (res
== res
+ cor
) return (n
&2)?-res
:res
;
890 __docos(ABS(x
),dx
,w
);
891 cor
= (w
[1]>0)? 1.000000005*w
[1]+1.1e-30*ABS(orig
) : 1.000000005*w
[1]-1.1e-30*ABS(orig
);
892 if (w
[0] == w
[0]+cor
) return (n
&2)?-w
[0]:w
[0];
893 else return __mpsin1(orig
);
896 /***************************************************************************/
897 /* Routine compute sin(x+dx) or cos(x+dx) (Double-Length number) where x */
898 /* is small enough to use Taylor series around zero and (x+dx) */
899 /* in first or third quarter of unit circle.Routine receive also */
900 /* (right argument) the original value of x for computing error of */
901 /* result.And if result not accurate enough routine calls other routines */
902 /***************************************************************************/
906 bsloww(double x
,double dx
, double orig
,int n
) {
907 static const double th2_36
= 206158430208.0; /* 1.5*2**37 */
908 double y
,x1
,x2
,xx
,r
,t
,res
,cor
,w
[2];
911 union {int4 i
[2]; double x
;} v
;
913 x1
=(x
+th2_36
)-th2_36
;
918 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
;
922 cor
= (cor
>0)? 1.0005*cor
+1.1e-24 : 1.0005*cor
-1.1e-24;
923 if (res
== res
+ cor
) return res
;
925 (x
>0)? __dubsin(x
,dx
,w
) : __dubsin(-x
,-dx
,w
);
926 cor
= (w
[1]>0)? 1.000000001*w
[1] + 1.1e-24 : 1.000000001*w
[1] - 1.1e-24;
927 if (w
[0] == w
[0]+cor
) return (x
>0)?w
[0]:-w
[0];
928 else return (n
&1)?__mpcos1(orig
):__mpsin1(orig
);
932 /***************************************************************************/
933 /* Routine compute sin(x+dx) or cos(x+dx) (Double-Length number) where x */
934 /* in first or third quarter of unit circle.Routine receive also */
935 /* (right argument) the original value of x for computing error of result.*/
936 /* And if result not accurate enough routine calls other routines */
937 /***************************************************************************/
941 bsloww1(double x
, double dx
, double orig
,int n
) {
943 double sn
,ssn
,cs
,ccs
,s
,c
,w
[2],y
,y1
,y2
,c1
,c2
,xx
,cor
,res
;
944 static const double t22
= 6291456.0;
951 s
= y
*xx
*(sn3
+xx
*sn5
);
952 c
= xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
955 ssn
=__sincostab
.x
[k
+1];
956 cs
=__sincostab
.x
[k
+2];
957 ccs
=__sincostab
.x
[k
+3];
962 cor
=(ssn
+s
*ccs
+cs
*s
+c2
*y
+c1
*y2
-sn
*y
*dx
)-sn
*c
;
964 cor
= cor
+((sn
-y
)+c1
*y1
);
967 cor
= (cor
>0)? 1.0005*cor
+1.1e-24 : 1.0005*cor
-1.1e-24;
968 if (res
== res
+ cor
) return (x
>0)?res
:-res
;
970 __dubsin(ABS(x
),dx
,w
);
971 cor
= (w
[1]>0)? 1.000000005*w
[1]+1.1e-24: 1.000000005*w
[1]-1.1e-24;
972 if (w
[0] == w
[0]+cor
) return (x
>0)?w
[0]:-w
[0];
973 else return (n
&1)?__mpcos1(orig
):__mpsin1(orig
);
977 /***************************************************************************/
978 /* Routine compute sin(x+dx) or cos(x+dx) (Double-Length number) where x */
979 /* in second or fourth quarter of unit circle.Routine receive also the */
980 /* original value and quarter(n= 1or 3)of x for computing error of result. */
981 /* And if result not accurate enough routine calls other routines */
982 /***************************************************************************/
986 bsloww2(double x
, double dx
, double orig
, int n
) {
988 double sn
,ssn
,cs
,ccs
,s
,c
,w
[2],y
,y1
,y2
,e1
,e2
,xx
,cor
,res
;
989 static const double t22
= 6291456.0;
996 s
= y
*xx
*(sn3
+xx
*sn5
);
997 c
= y
*dx
+xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
1000 ssn
=__sincostab
.x
[k
+1];
1001 cs
=__sincostab
.x
[k
+2];
1002 ccs
=__sincostab
.x
[k
+3];
1008 cor
=(ccs
-cs
*c
-e1
*y2
-e2
*y
)-sn
*s
;
1010 cor
= cor
+((cs
-y
)-e1
*y1
);
1013 cor
= (cor
>0)? 1.0005*cor
+1.1e-24 : 1.0005*cor
-1.1e-24;
1014 if (res
== res
+ cor
) return (n
&2)?-res
:res
;
1016 __docos(ABS(x
),dx
,w
);
1017 cor
= (w
[1]>0)? 1.000000005*w
[1]+1.1e-24 : 1.000000005*w
[1]-1.1e-24;
1018 if (w
[0] == w
[0]+cor
) return (n
&2)?-w
[0]:w
[0];
1019 else return (n
&1)?__mpsin1(orig
):__mpcos1(orig
);
1023 /************************************************************************/
1024 /* Routine compute cos(x) for 2^-27 < |x|< 0.25 by Taylor with more */
1025 /* precision and if still doesn't accurate enough by mpcos or docos */
1026 /************************************************************************/
1032 double sn
,ssn
,cs
,ccs
,s
,c
,w
[2],y
,y1
,y2
,e1
,e2
,xx
,cor
,res
;
1033 static const double t22
= 6291456.0;
1039 s
= y
*xx
*(sn3
+xx
*sn5
);
1040 c
= xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
1042 sn
=__sincostab
.x
[k
];
1043 ssn
=__sincostab
.x
[k
+1];
1044 cs
=__sincostab
.x
[k
+2];
1045 ccs
=__sincostab
.x
[k
+3];
1050 cor
=(ccs
-cs
*c
-e1
*y2
-e2
*y
)-sn
*s
;
1052 cor
= cor
+((cs
-y
)-e1
*y1
);
1055 if (res
== res
+1.0005*cor
)
1060 if (w
[0] == w
[0]+1.000000005*w
[1]) return w
[0];
1061 else return __mpcos(x
,0);
1065 /***************************************************************************/
1066 /* Routine compute cos(x+dx) (Double-Length number) where x is small enough*/
1067 /* to use Taylor series around zero and (x+dx) .Routine receive also */
1068 /* (right argument) the original value of x for computing error of */
1069 /* result.And if result not accurate enough routine calls other routines */
1070 /***************************************************************************/
1075 csloww(double x
,double dx
, double orig
) {
1076 static const double th2_36
= 206158430208.0; /* 1.5*2**37 */
1077 double y
,x1
,x2
,xx
,r
,t
,res
,cor
,w
[2],a
,da
,xn
;
1078 union {int4 i
[2]; double x
;} v
;
1080 x1
=(x
+th2_36
)-th2_36
;
1086 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
;
1090 cor
= (cor
>0)? 1.0005*cor
+ABS(orig
)*3.1e-30 : 1.0005*cor
-ABS(orig
)*3.1e-30;
1091 if (res
== res
+ cor
) return res
;
1093 (x
>0)? __dubsin(x
,dx
,w
) : __dubsin(-x
,-dx
,w
);
1094 cor
= (w
[1]>0)? 1.000000001*w
[1] + ABS(orig
)*1.1e-30 : 1.000000001*w
[1] - ABS(orig
)*1.1e-30;
1095 if (w
[0] == w
[0]+cor
) return (x
>0)?w
[0]:-w
[0];
1097 t
= (orig
*hpinv
.x
+ toint
.x
);
1100 y
= (orig
- xn
*mp1
.x
) - xn
*mp2
.x
;
1108 if (n
==1) {a
=-a
; da
=-da
;}
1109 (a
>0)? __dubsin(a
,da
,w
) : __dubsin(-a
,-da
,w
);
1110 cor
= (w
[1]>0)? 1.000000001*w
[1] + ABS(orig
)*1.1e-40 : 1.000000001*w
[1] - ABS(orig
)*1.1e-40;
1111 if (w
[0] == w
[0]+cor
) return (a
>0)?w
[0]:-w
[0];
1112 else return __mpcos1(orig
);
1117 /***************************************************************************/
1118 /* Routine compute sin(x+dx) (Double-Length number) where x in first or */
1119 /* third quarter of unit circle.Routine receive also (right argument) the */
1120 /* original value of x for computing error of result.And if result not */
1121 /* accurate enough routine calls other routines */
1122 /***************************************************************************/
1126 csloww1(double x
, double dx
, double orig
) {
1128 double sn
,ssn
,cs
,ccs
,s
,c
,w
[2],y
,y1
,y2
,c1
,c2
,xx
,cor
,res
;
1129 static const double t22
= 6291456.0;
1136 s
= y
*xx
*(sn3
+xx
*sn5
);
1137 c
= xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
1139 sn
=__sincostab
.x
[k
];
1140 ssn
=__sincostab
.x
[k
+1];
1141 cs
=__sincostab
.x
[k
+2];
1142 ccs
=__sincostab
.x
[k
+3];
1147 cor
=(ssn
+s
*ccs
+cs
*s
+c2
*y
+c1
*y2
-sn
*y
*dx
)-sn
*c
;
1149 cor
= cor
+((sn
-y
)+c1
*y1
);
1152 cor
= (cor
>0)? 1.0005*cor
+3.1e-30*ABS(orig
) : 1.0005*cor
-3.1e-30*ABS(orig
);
1153 if (res
== res
+ cor
) return (x
>0)?res
:-res
;
1155 __dubsin(ABS(x
),dx
,w
);
1156 cor
= (w
[1]>0)? 1.000000005*w
[1]+1.1e-30*ABS(orig
) : 1.000000005*w
[1]-1.1e-30*ABS(orig
);
1157 if (w
[0] == w
[0]+cor
) return (x
>0)?w
[0]:-w
[0];
1158 else return __mpcos1(orig
);
1163 /***************************************************************************/
1164 /* Routine compute sin(x+dx) (Double-Length number) where x in second or */
1165 /* fourth quarter of unit circle.Routine receive also the original value */
1166 /* and quarter(n= 1or 3)of x for computing error of result.And if result not*/
1167 /* accurate enough routine calls other routines */
1168 /***************************************************************************/
1172 csloww2(double x
, double dx
, double orig
, int n
) {
1174 double sn
,ssn
,cs
,ccs
,s
,c
,w
[2],y
,y1
,y2
,e1
,e2
,xx
,cor
,res
;
1175 static const double t22
= 6291456.0;
1182 s
= y
*xx
*(sn3
+xx
*sn5
);
1183 c
= y
*dx
+xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
1185 sn
=__sincostab
.x
[k
];
1186 ssn
=__sincostab
.x
[k
+1];
1187 cs
=__sincostab
.x
[k
+2];
1188 ccs
=__sincostab
.x
[k
+3];
1194 cor
=(ccs
-cs
*c
-e1
*y2
-e2
*y
)-sn
*s
;
1196 cor
= cor
+((cs
-y
)-e1
*y1
);
1199 cor
= (cor
>0)? 1.0005*cor
+3.1e-30*ABS(orig
) : 1.0005*cor
-3.1e-30*ABS(orig
);
1200 if (res
== res
+ cor
) return (n
)?-res
:res
;
1202 __docos(ABS(x
),dx
,w
);
1203 cor
= (w
[1]>0)? 1.000000005*w
[1]+1.1e-30*ABS(orig
) : 1.000000005*w
[1]-1.1e-30*ABS(orig
);
1204 if (w
[0] == w
[0]+cor
) return (n
)?-w
[0]:w
[0];
1205 else return __mpcos1(orig
);
1210 weak_alias (__cos
, cos
)
1211 # ifdef NO_LONG_DOUBLE
1212 strong_alias (__cos
, __cosl
)
1213 weak_alias (__cos
, cosl
)
1217 weak_alias (__sin
, sin
)
1218 # ifdef NO_LONG_DOUBLE
1219 strong_alias (__sin
, __sinl
)
1220 weak_alias (__sin
, sinl
)