2 * IBM Accurate Mathematical Library
3 * Copyright (c) International Business Machines Corp., 2001
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
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 sn3
= -1.66666666666664880952546298448555E-01,
59 sn5
= 8.33333214285722277379541354343671E-03,
60 cs2
= 4.99999999999999999999950396842453E-01,
61 cs4
= -4.16666666666664434524222570944589E-02,
62 cs6
= 1.38888874007937613028114285595617E-03;
64 void __dubsin(double x
, double dx
, double w
[]);
65 void __docos(double x
, double dx
, double w
[]);
66 double __mpsin(double x
, double dx
);
67 double __mpcos(double x
, double dx
);
68 double __mpsin1(double x
);
69 double __mpcos1(double x
);
70 static double slow(double x
);
71 static double slow1(double x
);
72 static double slow2(double x
);
73 static double sloww(double x
, double dx
, double orig
);
74 static double sloww1(double x
, double dx
, double orig
);
75 static double sloww2(double x
, double dx
, double orig
, int n
);
76 static double bsloww(double x
, double dx
, double orig
, int n
);
77 static double bsloww1(double x
, double dx
, double orig
, int n
);
78 static double bsloww2(double x
, double dx
, double orig
, int n
);
79 int __branred(double x
, double *a
, double *aa
);
80 static double cslow2(double x
);
81 static double csloww(double x
, double dx
, double orig
);
82 static double csloww1(double x
, double dx
, double orig
);
83 static double csloww2(double x
, double dx
, double orig
, int n
);
84 /*******************************************************************/
85 /* An ultimate sin routine. Given an IEEE double machine number x */
86 /* it computes the correctly rounded (to nearest) value of sin(x) */
87 /*******************************************************************/
88 double __sin(double x
){
89 double xx
,res
,t
,cor
,y
,s
,c
,sn
,ssn
,cs
,ccs
,xn
,a
,da
,db
,eps
,xn1
,xn2
;
101 k
= 0x7fffffff&m
; /* no sign */
102 if (k
< 0x3e500000) /* if x->0 =>sin(x)=x */
104 /*---------------------------- 2^-26 < |x|< 0.25 ----------------------*/
105 else if (k
< 0x3fd00000){
108 t
= ((((s5
.x
*xx
+ s4
.x
)*xx
+ s3
.x
)*xx
+ s2
.x
)*xx
+ s1
.x
)*(xx
*x
);
111 return (res
== res
+ 1.07*cor
)? res
: slow(x
);
112 } /* else if (k < 0x3fd00000) */
113 /*---------------------------- 0.25<|x|< 0.855469---------------------- */
114 else if (k
< 0x3feb6000) {
115 u
.x
=(m
>0)?big
.x
+x
:big
.x
-x
;
116 y
=(m
>0)?x
-(u
.x
-big
.x
):x
+(u
.x
-big
.x
);
118 s
= y
+ y
*xx
*(sn3
+xx
*sn5
);
119 c
= xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
121 sn
=(m
>0)?sincos
.x
[k
]:-sincos
.x
[k
];
122 ssn
=(m
>0)?sincos
.x
[k
+1]:-sincos
.x
[k
+1];
125 cor
=(ssn
+s
*ccs
-sn
*c
)+cs
*s
;
128 return (res
==res
+1.025*cor
)? res
: slow1(x
);
129 } /* else if (k < 0x3feb6000) */
131 /*----------------------- 0.855469 <|x|<2.426265 ----------------------*/
132 else if (k
< 0x400368fd ) {
134 y
= (m
>0)? hp0
.x
-x
:hp0
.x
+x
;
137 y
= (y
-(u
.x
-big
.x
))+hp1
.x
;
141 y
= (-hp1
.x
) - (y
+(u
.x
-big
.x
));
144 s
= y
+ y
*xx
*(sn3
+xx
*sn5
);
145 c
= xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
151 cor
=(ccs
-s
*ssn
-cs
*c
)-sn
*s
;
154 return (res
==res
+1.020*cor
)? ((m
>0)?res
:-res
) : slow2(x
);
155 } /* else if (k < 0x400368fd) */
157 /*-------------------------- 2.426265<|x|< 105414350 ----------------------*/
158 else if (k
< 0x419921FB ) {
159 t
= (x
*hpinv
.x
+ toint
.x
);
162 y
= (x
- xn
*mp1
.x
) - xn
*mp2
.x
;
167 eps
= ABS(x
)*1.2e-30;
169 switch (n
) { /* quarter of unit circle */
173 if (n
) {a
=-a
;da
=-da
;}
176 t
= (((((s5
.x
*xx
+ s4
.x
)*xx
+ s3
.x
)*xx
+ s2
.x
)*xx
+ s1
.x
)*a
- 0.5*da
)*xx
+da
;
179 cor
= (cor
>0)? 1.02*cor
+eps
: 1.02*cor
-eps
;
180 return (res
== res
+ cor
)? res
: sloww(a
,da
,x
);
190 s
= y
+ (db
+y
*xx
*(sn3
+xx
*sn5
));
191 c
= y
*db
+xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
197 cor
=(ssn
+s
*ccs
-sn
*c
)+cs
*s
;
200 cor
= (cor
>0)? 1.035*cor
+eps
: 1.035*cor
-eps
;
201 return (res
==res
+cor
)? ((m
)?res
:-res
) : sloww1(a
,da
,x
);
217 s
= y
+ y
*xx
*(sn3
+xx
*sn5
);
218 c
= xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
219 cor
=(ccs
-s
*ssn
-cs
*c
)-sn
*s
;
222 cor
= (cor
>0)? 1.025*cor
+eps
: 1.025*cor
-eps
;
223 return (res
==res
+cor
)? ((n
&2)?-res
:res
) : sloww2(a
,da
,x
,n
);
229 } /* else if (k < 0x419921FB ) */
231 /*---------------------105414350 <|x|< 281474976710656 --------------------*/
232 else if (k
< 0x42F00000 ) {
233 t
= (x
*hpinv
.x
+ toint
.x
);
236 xn1
= (xn
+8.0e22
)-8.0e22
;
238 y
= ((((x
- xn1
*mp1
.x
) - xn1
*mp2
.x
)-xn2
*mp1
.x
)-xn2
*mp2
.x
);
243 da
= (da
- xn2
*pp3
.x
) -xn
*pp4
.x
;
252 if (n
) {a
=-a
;da
=-da
;}
255 t
= (((((s5
.x
*xx
+ s4
.x
)*xx
+ s3
.x
)*xx
+ s2
.x
)*xx
+ s1
.x
)*a
- 0.5*da
)*xx
+da
;
258 cor
= (cor
>0)? 1.02*cor
+eps
: 1.02*cor
-eps
;
259 return (res
== res
+ cor
)? res
: bsloww(a
,da
,x
,n
);
262 if (a
>0) {m
=1;t
=a
;db
=da
;}
263 else {m
=0;t
=-a
;db
=-da
;}
267 s
= y
+ (db
+y
*xx
*(sn3
+xx
*sn5
));
268 c
= y
*db
+xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
274 cor
=(ssn
+s
*ccs
-sn
*c
)+cs
*s
;
277 cor
= (cor
>0)? 1.035*cor
+eps
: 1.035*cor
-eps
;
278 return (res
==res
+cor
)? ((m
)?res
:-res
) : bsloww1(a
,da
,x
,n
);
294 s
= y
+ y
*xx
*(sn3
+xx
*sn5
);
295 c
= xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
296 cor
=(ccs
-s
*ssn
-cs
*c
)-sn
*s
;
299 cor
= (cor
>0)? 1.025*cor
+eps
: 1.025*cor
-eps
;
300 return (res
==res
+cor
)? ((n
&2)?-res
:res
) : bsloww2(a
,da
,x
,n
);
306 } /* else if (k < 0x42F00000 ) */
308 /* -----------------281474976710656 <|x| <2^1024----------------------------*/
309 else if (k
< 0x7ff00000) {
311 n
= __branred(x
,&a
,&da
);
314 if (a
*a
< 0.01588) return bsloww(a
,da
,x
,n
);
315 else return bsloww1(a
,da
,x
,n
);
318 if (a
*a
< 0.01588) return bsloww(-a
,-da
,x
,n
);
319 else return bsloww1(-a
,-da
,x
,n
);
324 return bsloww2(a
,da
,x
,n
);
328 } /* else if (k < 0x7ff00000 ) */
330 /*--------------------- |x| > 2^1024 ----------------------------------*/
332 return 0; /* unreachable */
336 /*******************************************************************/
337 /* An ultimate cos routine. Given an IEEE double machine number x */
338 /* it computes the correctly rounded (to nearest) value of cos(x) */
339 /*******************************************************************/
341 double __cos(double x
)
343 double y
,xx
,res
,t
,cor
,s
,c
,sn
,ssn
,cs
,ccs
,xn
,a
,da
,db
,eps
,xn1
,xn2
;
351 if (k
< 0x3e400000 ) return 1.0; /* |x|<2^-27 => cos(x)=1 */
353 else if (k
< 0x3feb6000 ) {/* 2^-27 < |x| < 0.855469 */
358 s
= y
+ y
*xx
*(sn3
+xx
*sn5
);
359 c
= xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
365 cor
=(ccs
-s
*ssn
-cs
*c
)-sn
*s
;
368 return (res
==res
+1.020*cor
)? res
: cslow2(x
);
370 } /* else if (k < 0x3feb6000) */
372 else if (k
< 0x400368fd ) {/* 0.855469 <|x|<2.426265 */;
378 t
= (((((s5
.x
*xx
+ s4
.x
)*xx
+ s3
.x
)*xx
+ s2
.x
)*xx
+ s1
.x
)*a
- 0.5*da
)*xx
+da
;
381 cor
= (cor
>0)? 1.02*cor
+1.0e-31 : 1.02*cor
-1.0e-31;
382 return (res
== res
+ cor
)? res
: csloww(a
,da
,x
);
385 if (a
>0) {m
=1;t
=a
;db
=da
;}
386 else {m
=0;t
=-a
;db
=-da
;}
390 s
= y
+ (db
+y
*xx
*(sn3
+xx
*sn5
));
391 c
= y
*db
+xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
397 cor
=(ssn
+s
*ccs
-sn
*c
)+cs
*s
;
400 cor
= (cor
>0)? 1.035*cor
+1.0e-31 : 1.035*cor
-1.0e-31;
401 return (res
==res
+cor
)? ((m
)?res
:-res
) : csloww1(a
,da
,x
);
404 } /* else if (k < 0x400368fd) */
407 else if (k
< 0x419921FB ) {/* 2.426265<|x|< 105414350 */
408 t
= (x
*hpinv
.x
+ toint
.x
);
411 y
= (x
- xn
*mp1
.x
) - xn
*mp2
.x
;
416 eps
= ABS(x
)*1.2e-30;
422 if (n
== 1) {a
=-a
;da
=-da
;}
424 t
= (((((s5
.x
*xx
+ s4
.x
)*xx
+ s3
.x
)*xx
+ s2
.x
)*xx
+ s1
.x
)*a
- 0.5*da
)*xx
+da
;
427 cor
= (cor
>0)? 1.02*cor
+eps
: 1.02*cor
-eps
;
428 return (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
));
443 cor
=(ssn
+s
*ccs
-sn
*c
)+cs
*s
;
446 cor
= (cor
>0)? 1.035*cor
+eps
: 1.035*cor
-eps
;
447 return (res
==res
+cor
)? ((m
)?res
:-res
) : csloww1(a
,da
,x
);
453 if (a
<0) {a
=-a
;da
=-da
;}
462 s
= y
+ y
*xx
*(sn3
+xx
*sn5
);
463 c
= xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
464 cor
=(ccs
-s
*ssn
-cs
*c
)-sn
*s
;
467 cor
= (cor
>0)? 1.025*cor
+eps
: 1.025*cor
-eps
;
468 return (res
==res
+cor
)? ((n
)?-res
:res
) : csloww2(a
,da
,x
,n
);
474 } /* else if (k < 0x419921FB ) */
477 else if (k
< 0x42F00000 ) {
478 t
= (x
*hpinv
.x
+ toint
.x
);
481 xn1
= (xn
+8.0e22
)-8.0e22
;
483 y
= ((((x
- xn1
*mp1
.x
) - xn1
*mp2
.x
)-xn2
*mp1
.x
)-xn2
*mp2
.x
);
488 da
= (da
- xn2
*pp3
.x
) -xn
*pp4
.x
;
497 if (n
==1) {a
=-a
;da
=-da
;}
499 t
= (((((s5
.x
*xx
+ s4
.x
)*xx
+ s3
.x
)*xx
+ s2
.x
)*xx
+ s1
.x
)*a
- 0.5*da
)*xx
+da
;
502 cor
= (cor
>0)? 1.02*cor
+eps
: 1.02*cor
-eps
;
503 return (res
== res
+ cor
)? res
: bsloww(a
,da
,x
,n
);
506 if (a
>0) {m
=1;t
=a
;db
=da
;}
507 else {m
=0;t
=-a
;db
=-da
;}
511 s
= y
+ (db
+y
*xx
*(sn3
+xx
*sn5
));
512 c
= y
*db
+xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
518 cor
=(ssn
+s
*ccs
-sn
*c
)+cs
*s
;
521 cor
= (cor
>0)? 1.035*cor
+eps
: 1.035*cor
-eps
;
522 return (res
==res
+cor
)? ((m
)?res
:-res
) : bsloww1(a
,da
,x
,n
);
528 if (a
<0) {a
=-a
;da
=-da
;}
537 s
= y
+ y
*xx
*(sn3
+xx
*sn5
);
538 c
= xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
539 cor
=(ccs
-s
*ssn
-cs
*c
)-sn
*s
;
542 cor
= (cor
>0)? 1.025*cor
+eps
: 1.025*cor
-eps
;
543 return (res
==res
+cor
)? ((n
)?-res
:res
) : bsloww2(a
,da
,x
,n
);
548 } /* else if (k < 0x42F00000 ) */
550 else if (k
< 0x7ff00000) {/* 281474976710656 <|x| <2^1024 */
552 n
= __branred(x
,&a
,&da
);
555 if (a
*a
< 0.01588) return bsloww(-a
,-da
,x
,n
);
556 else return bsloww1(-a
,-da
,x
,n
);
559 if (a
*a
< 0.01588) return bsloww(a
,da
,x
,n
);
560 else return bsloww1(a
,da
,x
,n
);
565 return bsloww2(a
,da
,x
,n
);
569 } /* else if (k < 0x7ff00000 ) */
574 else return x
/ x
; /* |x| > 2^1024 */
579 /************************************************************************/
580 /* Routine compute sin(x) for 2^-26 < |x|< 0.25 by Taylor with more */
581 /* precision and if still doesn't accurate enough by mpsin or dubsin */
582 /************************************************************************/
584 static double slow(double x
) {
585 static const double th2_36
= 206158430208.0; /* 1.5*2**37 */
586 double y
,x1
,x2
,xx
,r
,t
,res
,cor
,w
[2];
587 x1
=(x
+th2_36
)-th2_36
;
592 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
;
596 if (res
== res
+ 1.0007*cor
) return res
;
598 __dubsin(ABS(x
),0,w
);
599 if (w
[0] == w
[0]+1.000000001*w
[1]) return (x
>0)?w
[0]:-w
[0];
600 else return (x
>0)?__mpsin(x
,0):-__mpsin(-x
,0);
603 /*******************************************************************************/
604 /* Routine compute sin(x) for 0.25<|x|< 0.855469 by sincos.tbl and Taylor */
605 /* and if result still doesn't accurate enough by mpsin or dubsin */
606 /*******************************************************************************/
608 static double slow1(double x
) {
610 double sn
,ssn
,cs
,ccs
,s
,c
,w
[2],y
,y1
,y2
,c1
,c2
,xx
,cor
,res
;
611 static const double t22
= 6291456.0;
617 s
= y
*xx
*(sn3
+xx
*sn5
);
618 c
= xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
620 sn
=sincos
.x
[k
]; /* Data */
621 ssn
=sincos
.x
[k
+1]; /* from */
622 cs
=sincos
.x
[k
+2]; /* tables */
623 ccs
=sincos
.x
[k
+3]; /* sincos.tbl */
628 cor
=(ssn
+s
*ccs
+cs
*s
+c2
*y
+c1
*y2
)-sn
*c
;
630 cor
= cor
+((sn
-y
)+c1
*y1
);
633 if (res
== res
+1.0005*cor
) return (x
>0)?res
:-res
;
635 __dubsin(ABS(x
),0,w
);
636 if (w
[0] == w
[0]+1.000000005*w
[1]) return (x
>0)?w
[0]:-w
[0];
637 else return (x
>0)?__mpsin(x
,0):-__mpsin(-x
,0);
640 /**************************************************************************/
641 /* Routine compute sin(x) for 0.855469 <|x|<2.426265 by sincos.tbl */
642 /* and if result still doesn't accurate enough by mpsin or dubsin */
643 /**************************************************************************/
644 static double slow2(double x
) {
646 double sn
,ssn
,cs
,ccs
,s
,c
,w
[2],y
,y1
,y2
,e1
,e2
,xx
,cor
,res
,del
;
647 static const double t22
= 6291456.0;
658 y
= -(y
+(u
.x
-big
.x
));
662 s
= y
*xx
*(sn3
+xx
*sn5
);
663 c
= y
*del
+xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
673 cor
=(ccs
-cs
*c
-e1
*y2
-e2
*y
)-sn
*s
;
675 cor
= cor
+((cs
-y
)-e1
*y1
);
678 if (res
== res
+1.0005*cor
) return (x
>0)?res
:-res
;
684 if (w
[0] == w
[0]+1.000000005*w
[1]) return (x
>0)?w
[0]:-w
[0];
685 else return (x
>0)?__mpsin(x
,0):-__mpsin(-x
,0);
688 /***************************************************************************/
689 /* Routine compute sin(x+dx) (Double-Length number) where x is small enough*/
690 /* to use Taylor series around zero and (x+dx) */
691 /* in first or third quarter of unit circle.Routine receive also */
692 /* (right argument) the original value of x for computing error of */
693 /* result.And if result not accurate enough routine calls mpsin1 or dubsin */
694 /***************************************************************************/
696 static double sloww(double x
,double dx
, double orig
) {
697 static const double th2_36
= 206158430208.0; /* 1.5*2**37 */
698 double y
,x1
,x2
,xx
,r
,t
,res
,cor
,w
[2],a
,da
,xn
;
699 union {int4 i
[2]; double x
;} v
;
701 x1
=(x
+th2_36
)-th2_36
;
706 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
;
710 cor
= (cor
>0)? 1.0005*cor
+ABS(orig
)*3.1e-30 : 1.0005*cor
-ABS(orig
)*3.1e-30;
711 if (res
== res
+ cor
) return res
;
713 (x
>0)? __dubsin(x
,dx
,w
) : __dubsin(-x
,-dx
,w
);
714 cor
= (w
[1]>0)? 1.000000001*w
[1] + ABS(orig
)*1.1e-30 : 1.000000001*w
[1] - ABS(orig
)*1.1e-30;
715 if (w
[0] == w
[0]+cor
) return (x
>0)?w
[0]:-w
[0];
717 t
= (orig
*hpinv
.x
+ toint
.x
);
720 y
= (orig
- xn
*mp1
.x
) - xn
*mp2
.x
;
728 if (n
&2) {a
=-a
; da
=-da
;}
729 (a
>0)? __dubsin(a
,da
,w
) : __dubsin(-a
,-da
,w
);
730 cor
= (w
[1]>0)? 1.000000001*w
[1] + ABS(orig
)*1.1e-40 : 1.000000001*w
[1] - ABS(orig
)*1.1e-40;
731 if (w
[0] == w
[0]+cor
) return (a
>0)?w
[0]:-w
[0];
732 else return __mpsin1(orig
);
736 /***************************************************************************/
737 /* Routine compute sin(x+dx) (Double-Length number) where x in first or */
738 /* third quarter of unit circle.Routine receive also (right argument) the */
739 /* original value of x for computing error of result.And if result not */
740 /* accurate enough routine calls mpsin1 or dubsin */
741 /***************************************************************************/
743 static double sloww1(double x
, double dx
, double orig
) {
745 double sn
,ssn
,cs
,ccs
,s
,c
,w
[2],y
,y1
,y2
,c1
,c2
,xx
,cor
,res
;
746 static const double t22
= 6291456.0;
753 s
= y
*xx
*(sn3
+xx
*sn5
);
754 c
= xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
764 cor
=(ssn
+s
*ccs
+cs
*s
+c2
*y
+c1
*y2
-sn
*y
*dx
)-sn
*c
;
766 cor
= cor
+((sn
-y
)+c1
*y1
);
769 cor
= (cor
>0)? 1.0005*cor
+3.1e-30*ABS(orig
) : 1.0005*cor
-3.1e-30*ABS(orig
);
770 if (res
== res
+ cor
) return (x
>0)?res
:-res
;
772 __dubsin(ABS(x
),dx
,w
);
773 cor
= (w
[1]>0)? 1.000000005*w
[1]+1.1e-30*ABS(orig
) : 1.000000005*w
[1]-1.1e-30*ABS(orig
);
774 if (w
[0] == w
[0]+cor
) return (x
>0)?w
[0]:-w
[0];
775 else return __mpsin1(orig
);
778 /***************************************************************************/
779 /* Routine compute sin(x+dx) (Double-Length number) where x in second or */
780 /* fourth quarter of unit circle.Routine receive also the original value */
781 /* and quarter(n= 1or 3)of x for computing error of result.And if result not*/
782 /* accurate enough routine calls mpsin1 or dubsin */
783 /***************************************************************************/
785 static double sloww2(double x
, double dx
, double orig
, int n
) {
787 double sn
,ssn
,cs
,ccs
,s
,c
,w
[2],y
,y1
,y2
,e1
,e2
,xx
,cor
,res
;
788 static const double t22
= 6291456.0;
795 s
= y
*xx
*(sn3
+xx
*sn5
);
796 c
= y
*dx
+xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
807 cor
=(ccs
-cs
*c
-e1
*y2
-e2
*y
)-sn
*s
;
809 cor
= cor
+((cs
-y
)-e1
*y1
);
812 cor
= (cor
>0)? 1.0005*cor
+3.1e-30*ABS(orig
) : 1.0005*cor
-3.1e-30*ABS(orig
);
813 if (res
== res
+ cor
) return (n
&2)?-res
:res
;
815 __docos(ABS(x
),dx
,w
);
816 cor
= (w
[1]>0)? 1.000000005*w
[1]+1.1e-30*ABS(orig
) : 1.000000005*w
[1]-1.1e-30*ABS(orig
);
817 if (w
[0] == w
[0]+cor
) return (n
&2)?-w
[0]:w
[0];
818 else return __mpsin1(orig
);
821 /***************************************************************************/
822 /* Routine compute sin(x+dx) or cos(x+dx) (Double-Length number) where x */
823 /* is small enough to use Taylor series around zero and (x+dx) */
824 /* in first or third quarter of unit circle.Routine receive also */
825 /* (right argument) the original value of x for computing error of */
826 /* result.And if result not accurate enough routine calls other routines */
827 /***************************************************************************/
829 static double bsloww(double x
,double dx
, double orig
,int n
) {
830 static const double th2_36
= 206158430208.0; /* 1.5*2**37 */
831 double y
,x1
,x2
,xx
,r
,t
,res
,cor
,w
[2];
834 union {int4 i
[2]; double x
;} v
;
836 x1
=(x
+th2_36
)-th2_36
;
841 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
;
845 cor
= (cor
>0)? 1.0005*cor
+1.1e-24 : 1.0005*cor
-1.1e-24;
846 if (res
== res
+ cor
) return res
;
848 (x
>0)? __dubsin(x
,dx
,w
) : __dubsin(-x
,-dx
,w
);
849 cor
= (w
[1]>0)? 1.000000001*w
[1] + 1.1e-24 : 1.000000001*w
[1] - 1.1e-24;
850 if (w
[0] == w
[0]+cor
) return (x
>0)?w
[0]:-w
[0];
851 else return (n
&1)?__mpcos1(orig
):__mpsin1(orig
);
855 /***************************************************************************/
856 /* Routine compute sin(x+dx) or cos(x+dx) (Double-Length number) where x */
857 /* in first or third quarter of unit circle.Routine receive also */
858 /* (right argument) the original value of x for computing error of result.*/
859 /* And if result not accurate enough routine calls other routines */
860 /***************************************************************************/
862 static double bsloww1(double x
, double dx
, double orig
,int n
) {
864 double sn
,ssn
,cs
,ccs
,s
,c
,w
[2],y
,y1
,y2
,c1
,c2
,xx
,cor
,res
;
865 static const double t22
= 6291456.0;
872 s
= y
*xx
*(sn3
+xx
*sn5
);
873 c
= xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
883 cor
=(ssn
+s
*ccs
+cs
*s
+c2
*y
+c1
*y2
-sn
*y
*dx
)-sn
*c
;
885 cor
= cor
+((sn
-y
)+c1
*y1
);
888 cor
= (cor
>0)? 1.0005*cor
+1.1e-24 : 1.0005*cor
-1.1e-24;
889 if (res
== res
+ cor
) return (x
>0)?res
:-res
;
891 __dubsin(ABS(x
),dx
,w
);
892 cor
= (w
[1]>0)? 1.000000005*w
[1]+1.1e-24: 1.000000005*w
[1]-1.1e-24;
893 if (w
[0] == w
[0]+cor
) return (x
>0)?w
[0]:-w
[0];
894 else return (n
&1)?__mpcos1(orig
):__mpsin1(orig
);
898 /***************************************************************************/
899 /* Routine compute sin(x+dx) or cos(x+dx) (Double-Length number) where x */
900 /* in second or fourth quarter of unit circle.Routine receive also the */
901 /* original value and quarter(n= 1or 3)of x for computing error of result. */
902 /* And if result not accurate enough routine calls other routines */
903 /***************************************************************************/
905 static double bsloww2(double x
, double dx
, double orig
, int n
) {
907 double sn
,ssn
,cs
,ccs
,s
,c
,w
[2],y
,y1
,y2
,e1
,e2
,xx
,cor
,res
;
908 static const double t22
= 6291456.0;
915 s
= y
*xx
*(sn3
+xx
*sn5
);
916 c
= y
*dx
+xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
927 cor
=(ccs
-cs
*c
-e1
*y2
-e2
*y
)-sn
*s
;
929 cor
= cor
+((cs
-y
)-e1
*y1
);
932 cor
= (cor
>0)? 1.0005*cor
+1.1e-24 : 1.0005*cor
-1.1e-24;
933 if (res
== res
+ cor
) return (n
&2)?-res
:res
;
935 __docos(ABS(x
),dx
,w
);
936 cor
= (w
[1]>0)? 1.000000005*w
[1]+1.1e-24 : 1.000000005*w
[1]-1.1e-24;
937 if (w
[0] == w
[0]+cor
) return (n
&2)?-w
[0]:w
[0];
938 else return (n
&1)?__mpsin1(orig
):__mpcos1(orig
);
942 /************************************************************************/
943 /* Routine compute cos(x) for 2^-27 < |x|< 0.25 by Taylor with more */
944 /* precision and if still doesn't accurate enough by mpcos or docos */
945 /************************************************************************/
947 static double cslow2(double x
) {
949 double sn
,ssn
,cs
,ccs
,s
,c
,w
[2],y
,y1
,y2
,e1
,e2
,xx
,cor
,res
;
950 static const double t22
= 6291456.0;
956 s
= y
*xx
*(sn3
+xx
*sn5
);
957 c
= xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
967 cor
=(ccs
-cs
*c
-e1
*y2
-e2
*y
)-sn
*s
;
969 cor
= cor
+((cs
-y
)-e1
*y1
);
972 if (res
== res
+1.0005*cor
)
977 if (w
[0] == w
[0]+1.000000005*w
[1]) return w
[0];
978 else return __mpcos(x
,0);
982 /***************************************************************************/
983 /* Routine compute cos(x+dx) (Double-Length number) where x is small enough*/
984 /* to use Taylor series around zero and (x+dx) .Routine receive also */
985 /* (right argument) the original value of x for computing error of */
986 /* result.And if result not accurate enough routine calls other routines */
987 /***************************************************************************/
990 static double csloww(double x
,double dx
, double orig
) {
991 static const double th2_36
= 206158430208.0; /* 1.5*2**37 */
992 double y
,x1
,x2
,xx
,r
,t
,res
,cor
,w
[2],a
,da
,xn
;
993 union {int4 i
[2]; double x
;} v
;
995 x1
=(x
+th2_36
)-th2_36
;
1001 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
;
1005 cor
= (cor
>0)? 1.0005*cor
+ABS(orig
)*3.1e-30 : 1.0005*cor
-ABS(orig
)*3.1e-30;
1006 if (res
== res
+ cor
) return res
;
1008 (x
>0)? __dubsin(x
,dx
,w
) : __dubsin(-x
,-dx
,w
);
1009 cor
= (w
[1]>0)? 1.000000001*w
[1] + ABS(orig
)*1.1e-30 : 1.000000001*w
[1] - ABS(orig
)*1.1e-30;
1010 if (w
[0] == w
[0]+cor
) return (x
>0)?w
[0]:-w
[0];
1012 t
= (orig
*hpinv
.x
+ toint
.x
);
1015 y
= (orig
- xn
*mp1
.x
) - xn
*mp2
.x
;
1023 if (n
==1) {a
=-a
; da
=-da
;}
1024 (a
>0)? __dubsin(a
,da
,w
) : __dubsin(-a
,-da
,w
);
1025 cor
= (w
[1]>0)? 1.000000001*w
[1] + ABS(orig
)*1.1e-40 : 1.000000001*w
[1] - ABS(orig
)*1.1e-40;
1026 if (w
[0] == w
[0]+cor
) return (a
>0)?w
[0]:-w
[0];
1027 else return __mpcos1(orig
);
1032 /***************************************************************************/
1033 /* Routine compute sin(x+dx) (Double-Length number) where x in first or */
1034 /* third quarter of unit circle.Routine receive also (right argument) the */
1035 /* original value of x for computing error of result.And if result not */
1036 /* accurate enough routine calls other routines */
1037 /***************************************************************************/
1039 static double csloww1(double x
, double dx
, double orig
) {
1041 double sn
,ssn
,cs
,ccs
,s
,c
,w
[2],y
,y1
,y2
,c1
,c2
,xx
,cor
,res
;
1042 static const double t22
= 6291456.0;
1049 s
= y
*xx
*(sn3
+xx
*sn5
);
1050 c
= xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
1060 cor
=(ssn
+s
*ccs
+cs
*s
+c2
*y
+c1
*y2
-sn
*y
*dx
)-sn
*c
;
1062 cor
= cor
+((sn
-y
)+c1
*y1
);
1065 cor
= (cor
>0)? 1.0005*cor
+3.1e-30*ABS(orig
) : 1.0005*cor
-3.1e-30*ABS(orig
);
1066 if (res
== res
+ cor
) return (x
>0)?res
:-res
;
1068 __dubsin(ABS(x
),dx
,w
);
1069 cor
= (w
[1]>0)? 1.000000005*w
[1]+1.1e-30*ABS(orig
) : 1.000000005*w
[1]-1.1e-30*ABS(orig
);
1070 if (w
[0] == w
[0]+cor
) return (x
>0)?w
[0]:-w
[0];
1071 else return __mpcos1(orig
);
1076 /***************************************************************************/
1077 /* Routine compute sin(x+dx) (Double-Length number) where x in second or */
1078 /* fourth quarter of unit circle.Routine receive also the original value */
1079 /* and quarter(n= 1or 3)of x for computing error of result.And if result not*/
1080 /* accurate enough routine calls other routines */
1081 /***************************************************************************/
1083 static double csloww2(double x
, double dx
, double orig
, int n
) {
1085 double sn
,ssn
,cs
,ccs
,s
,c
,w
[2],y
,y1
,y2
,e1
,e2
,xx
,cor
,res
;
1086 static const double t22
= 6291456.0;
1093 s
= y
*xx
*(sn3
+xx
*sn5
);
1094 c
= y
*dx
+xx
*(cs2
+xx
*(cs4
+ xx
*cs6
));
1105 cor
=(ccs
-cs
*c
-e1
*y2
-e2
*y
)-sn
*s
;
1107 cor
= cor
+((cs
-y
)-e1
*y1
);
1110 cor
= (cor
>0)? 1.0005*cor
+3.1e-30*ABS(orig
) : 1.0005*cor
-3.1e-30*ABS(orig
);
1111 if (res
== res
+ cor
) return (n
)?-res
:res
;
1113 __docos(ABS(x
),dx
,w
);
1114 cor
= (w
[1]>0)? 1.000000005*w
[1]+1.1e-30*ABS(orig
) : 1.000000005*w
[1]-1.1e-30*ABS(orig
);
1115 if (w
[0] == w
[0]+cor
) return (n
)?-w
[0]:w
[0];
1116 else return __mpcos1(orig
);
1120 weak_alias (__cos
, cos
)
1121 weak_alias (__sin
, sin
)
1123 #ifdef NO_LONG_DOUBLE
1124 strong_alias (__sin
, __sinl
)
1125 weak_alias (__sin
, sinl
)
1126 strong_alias (__cos
, __cosl
)
1127 weak_alias (__cos
, cosl
)