2 * IBM Accurate Mathematical Library
3 * written by International Business Machines Corp.
4 * Copyright (C) 2001 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, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 /****************************************************************/
21 /* MODULE_NAME: sincos32.c */
34 /* FILES NEEDED: endian.h mpa.h sincos32.h */
37 /* Multi Precision sin() and cos() function with p=32 for sin()*/
38 /* cos() arcsin() and arccos() routines */
39 /* In addition mpranred() routine performs range reduction of */
40 /* a double number x into multi precision number y, */
41 /* such that y=x-n*pi/2, abs(y)<pi/4, n=0,+-1,+-2,.... */
42 /****************************************************************/
46 #include "math_private.h"
48 /****************************************************************/
49 /* Compute Multi-Precision sin() function for given p. Receive */
50 /* Multi Precision number x and result stored at y */
51 /****************************************************************/
52 static void ss32(mp_no
*x
, mp_no
*y
, int p
) {
57 static const mp_no mpone
= {1,{1.0,1.0}};
59 mp_no mpt1
,x2
,gor
,sum
,mpk
={1,{1.0}};
63 for (i
=1;i
<=p
;i
++) mpk
.d
[i
]=0;
66 __cpy(&oofac27
,&gor
,p
);
68 for (a
=27.0;a
>1.0;a
-=2.0) {
70 __mul(&gor
,&mpk
,&mpt1
,p
);
72 __mul(&x2
,&sum
,&mpt1
,p
);
73 __sub(&gor
,&mpt1
,&sum
,p
);
78 /**********************************************************************/
79 /* Compute Multi-Precision cos() function for given p. Receive Multi */
80 /* Precision number x and result stored at y */
81 /**********************************************************************/
82 static void cc32(mp_no
*x
, mp_no
*y
, int p
) {
87 static const mp_no mpone
= {1,{1.0,1.0}};
89 mp_no mpt1
,x2
,gor
,sum
,mpk
={1,{1.0}};
93 for (i
=1;i
<=p
;i
++) mpk
.d
[i
]=0;
97 __mul(&oofac27
,&mpk
,&gor
,p
);
99 for (a
=26.0;a
>2.0;a
-=2.0) {
101 __mul(&gor
,&mpk
,&mpt1
,p
);
103 __mul(&x2
,&sum
,&mpt1
,p
);
104 __sub(&gor
,&mpt1
,&sum
,p
);
109 /***************************************************************************/
110 /* c32() computes both sin(x), cos(x) as Multi precision numbers */
111 /***************************************************************************/
112 void __c32(mp_no
*x
, mp_no
*y
, mp_no
*z
, int p
) {
113 static const mp_no mpt
={1,{1.0,2.0}}, one
={1,{1.0,1.0}};
124 __sub(&mpt
,&c
,&t1
,p
);
132 /************************************************************************/
133 /*Routine receive double x and two double results of sin(x) and return */
134 /*result which is more accurate */
135 /*Computing sin(x) with multi precision routine c32 */
136 /************************************************************************/
137 double __sin32(double x
, double res
, double res1
) {
142 __dbl_mp(0.5*(res1
-res
),&b
,p
);
145 { __sub(&hp
,&c
,&a
,p
);
148 else __c32(&c
,&a
,&b
,p
); /* b=sin(0.5*(res+res1)) */
149 __dbl_mp(x
,&c
,p
); /* c = x */
151 /* if a>0 return min(res,res1), otherwise return max(res,res1) */
152 if (a
.d
[0]>0) return (res
<res1
)?res
:res1
;
153 else return (res
>res1
)?res
:res1
;
156 /************************************************************************/
157 /*Routine receive double x and two double results of cos(x) and return */
158 /*result which is more accurate */
159 /*Computing cos(x) with multi precision routine c32 */
160 /************************************************************************/
161 double __cos32(double x
, double res
, double res1
) {
166 __dbl_mp(0.5*(res1
-res
),&b
,p
);
169 { __sub(&pi
,&c
,&a
,p
);
174 { __sub(&hp
,&c
,&a
,p
);
177 else __c32(&c
,&b
,&a
,p
); /* b=cos(0.5*(res+res1)) */
178 __dbl_mp(x
,&c
,p
); /* c = x */
180 /* if a>0 return max(res,res1), otherwise return min(res,res1) */
181 if (a
.d
[0]>0) return (res
>res1
)?res
:res1
;
182 else return (res
<res1
)?res
:res1
;
185 /*******************************************************************/
186 /*Compute sin(x+dx) as Multi Precision number and return result as */
188 /*******************************************************************/
189 double __mpsin(double x
, double dx
) {
197 if (x
>0.8) { __sub(&hp
,&c
,&a
,p
); __c32(&a
,&b
,&c
,p
); }
198 else __c32(&c
,&a
,&b
,p
); /* b = sin(x+dx) */
203 /*******************************************************************/
204 /* Compute cos()of double-length number (x+dx) as Multi Precision */
205 /* number and return result as double */
206 /*******************************************************************/
207 double __mpcos(double x
, double dx
) {
216 { __sub(&hp
,&c
,&b
,p
);
219 else __c32(&c
,&a
,&b
,p
); /* a = cos(x+dx) */
224 /******************************************************************/
225 /* mpranred() performs range reduction of a double number x into */
226 /* multi precision number y, such that y=x-n*pi/2, abs(y)<pi/4, */
227 /* n=0,+-1,+-2,.... */
228 /* Return int which indicates in which quarter of circle x is */
229 /******************************************************************/
230 int __mpranred(double x
, mp_no
*y
, int p
)
235 static const mp_no one
= {1,{1.0,1.0}};
238 if (ABS(x
) < 2.8e14
) {
239 t
= (x
*hpinv
.d
+ toint
.d
);
249 else { /* if x is very big more precision required */
256 for (i
=0;i
<p
;i
++) b
.d
[i
+1] = toverp
[i
+k
];
259 for (i
=1;i
<=p
-c
.e
;i
++) c
.d
[i
]=c
.d
[i
+c
.e
];
260 for (i
=p
+1-c
.e
;i
<=p
;i
++) c
.d
[i
]=0;
262 if (c
.d
[1] >= 8388608.0)
267 else __mul(&c
,&hp
,y
,p
);
269 if (x
< 0) { y
->d
[0] = - y
->d
[0]; n
= -n
; }
274 /*******************************************************************/
275 /* Multi-Precision sin() function subroutine, for p=32. It is */
276 /* based on the routines mpranred() and c32(). */
277 /*******************************************************************/
278 double __mpsin1(double x
)
285 n
=__mpranred(x
,&u
,p
); /* n is 0, 1, 2 or 3 */
287 switch (n
) { /* in which quarter of unit circle y is*/
309 return 0; /* unreachable, to make the compiler happy */
312 /*****************************************************************/
313 /* Multi-Precision cos() function subroutine, for p=32. It is */
314 /* based on the routines mpranred() and c32(). */
315 /*****************************************************************/
317 double __mpcos1(double x
)
325 n
=__mpranred(x
,&u
,p
); /* n is 0, 1, 2 or 3 */
327 switch (n
) { /* in what quarter of unit circle y is*/
350 return 0; /* unreachable, to make the compiler happy */
352 /******************************************************************/