3 * IBM Accurate Mathematical Library
4 * written by International Business Machines Corp.
5 * Copyright (C) 2001 Free Software Foundation
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published by
9 * the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 /************************************************************************/
22 /* MODULE_NAME: mpa.c */
42 /* Arithmetic functions for multiple precision numbers. */
43 /* Relative errors are bounded */
44 /************************************************************************/
50 #include <sys/param.h> /* For MIN() */
51 /* mcr() compares the sizes of the mantissas of two multiple precision */
52 /* numbers. Mantissas are compared regardless of the signs of the */
53 /* numbers, even if x->d[0] or y->d[0] are zero. Exponents are also */
55 static int mcr(const mp_no
*x
, const mp_no
*y
, int p
) {
57 for (i
=1; i
<=p
; i
++) {
58 if (X
[i
] == Y
[i
]) continue;
59 else if (X
[i
] > Y
[i
]) return 1;
66 /* acr() compares the absolute values of two multiple precision numbers */
67 int __acr(const mp_no
*x
, const mp_no
*y
, int p
) {
71 if (Y
[0] == ZERO
) i
= 0;
74 else if (Y
[0] == ZERO
) i
= 1;
77 else if (EX
< EY
) i
=-1;
85 /* cr90 compares the values of two multiple precision numbers */
86 int __cr(const mp_no
*x
, const mp_no
*y
, int p
) {
89 if (X
[0] > Y
[0]) i
= 1;
90 else if (X
[0] < Y
[0]) i
=-1;
91 else if (X
[0] < ZERO
) i
= __acr(y
,x
,p
);
98 /* Copy a multiple precision number. Set *y=*x. x=y is permissible. */
99 void __cpy(const mp_no
*x
, mp_no
*y
, int p
) {
103 for (i
=0; i
<= p
; i
++) Y
[i
] = X
[i
];
109 /* Copy a multiple precision number x of precision m into a */
110 /* multiple precision number y of precision n. In case n>m, */
111 /* the digits of y beyond the m'th are set to zero. In case */
112 /* n<m, the digits of x beyond the n'th are ignored. */
113 /* x=y is permissible. */
115 void __cpymn(const mp_no
*x
, int m
, mp_no
*y
, int n
) {
120 for (i
=0; i
<= k
; i
++) Y
[i
] = X
[i
];
121 for ( ; i
<= n
; i
++) Y
[i
] = ZERO
;
126 /* Convert a multiple precision number *x into a double precision */
127 /* number *y, normalized case (|x| >= 2**(-1022))) */
128 static void norm(const mp_no
*x
, double *y
, int p
)
138 else if (p
==2) c
= X
[1] + R
* X
[2];
139 else if (p
==3) c
= X
[1] + R
*(X
[2] + R
* X
[3]);
140 else if (p
==4) c
=(X
[1] + R
* X
[2]) + R
*R
*(X
[3] + R
*X
[4]);
143 for (a
=ONE
, z
[1]=X
[1]; z
[1] < TWO23
; )
144 {a
*= TWO
; z
[1] *= TWO
; }
146 for (i
=2; i
<5; i
++) {
148 u
= (z
[i
] + CUTTER
)-CUTTER
;
149 if (u
> z
[i
]) u
-= RADIX
;
154 u
= (z
[3] + TWO71
) - TWO71
;
155 if (u
> z
[3]) u
-= TWO19
;
160 for (i
=5; i
<= p
; i
++) {
161 if (X
[i
] == ZERO
) continue;
162 else {z
[3] += ONE
; break; }
168 c
= (z
[1] + R
*(z
[2] + R
* z
[3]))/a
;
173 for (i
=1; i
<EX
; i
++) c
*= RADIX
;
174 for (i
=1; i
>EX
; i
--) c
*= RADIXI
;
181 /* Convert a multiple precision number *x into a double precision */
182 /* number *y, denormalized case (|x| < 2**(-1022))) */
183 static void denorm(const mp_no
*x
, double *y
, int p
)
192 if (EX
<-44 || (EX
==-44 && X
[1]<TWO5
))
196 if (EX
==-42) {z
[1]=X
[1]+TWO10
; z
[2]=ZERO
; z
[3]=ZERO
; k
=3;}
197 else if (EX
==-43) {z
[1]= TWO10
; z
[2]=X
[1]; z
[3]=ZERO
; k
=2;}
198 else {z
[1]= TWO10
; z
[2]=ZERO
; z
[3]=X
[1]; k
=1;}
201 if (EX
==-42) {z
[1]=X
[1]+TWO10
; z
[2]=X
[2]; z
[3]=ZERO
; k
=3;}
202 else if (EX
==-43) {z
[1]= TWO10
; z
[2]=X
[1]; z
[3]=X
[2]; k
=2;}
203 else {z
[1]= TWO10
; z
[2]=ZERO
; z
[3]=X
[1]; k
=1;}
206 if (EX
==-42) {z
[1]=X
[1]+TWO10
; z
[2]=X
[2]; k
=3;}
207 else if (EX
==-43) {z
[1]= TWO10
; z
[2]=X
[1]; k
=2;}
208 else {z
[1]= TWO10
; z
[2]=ZERO
; k
=1;}
212 u
= (z
[3] + TWO57
) - TWO57
;
213 if (u
> z
[3]) u
-= TWO5
;
216 for (i
=k
+1; i
<= p
; i
++) {
217 if (X
[i
] == ZERO
) continue;
218 else {z
[3] += ONE
; break; }
222 c
= X
[0]*((z
[1] + R
*(z
[2] + R
*z
[3])) - TWO10
);
230 /* Convert a multiple precision number *x into a double precision number *y. */
231 /* The result is correctly rounded to the nearest/even. *x is left unchanged */
233 void __mp_dbl(const mp_no
*x
, double *y
, int p
) {
239 if (X
[0] == ZERO
) {*y
= ZERO
; return; }
241 if (EX
> -42) norm(x
,y
,p
);
242 else if (EX
==-42 && X
[1]>=TWO10
) norm(x
,y
,p
);
247 /* dbl_mp() converts a double precision number x into a multiple precision */
248 /* number *y. If the precision p is too small the result is truncated. x is */
249 /* left unchanged. */
251 void __dbl_mp(double x
, mp_no
*y
, int p
) {
257 if (x
== ZERO
) {Y
[0] = ZERO
; return; }
258 else if (x
> ZERO
) Y
[0] = ONE
;
259 else {Y
[0] = MONE
; x
=-x
; }
262 for (EY
=ONE
; x
>= RADIX
; EY
+= ONE
) x
*= RADIXI
;
263 for ( ; x
< ONE
; EY
-= ONE
) x
*= RADIX
;
267 for (i
=1; i
<=n
; i
++) {
268 u
= (x
+ TWO52
) - TWO52
;
270 Y
[i
] = u
; x
-= u
; x
*= RADIX
; }
271 for ( ; i
<=p
; i
++) Y
[i
] = ZERO
;
276 /* add_magnitudes() adds the magnitudes of *x & *y assuming that */
277 /* abs(*x) >= abs(*y) > 0. */
278 /* The sign of the sum *z is undefined. x&y may overlap but not x&z or y&z. */
279 /* No guard digit is used. The result equals the exact sum, truncated. */
280 /* *x & *y are left unchanged. */
282 static void add_magnitudes(const mp_no
*x
, const mp_no
*y
, mp_no
*z
, int p
) {
288 i
=p
; j
=p
+ EY
- EX
; k
=p
+1;
291 {__cpy(x
,z
,p
); return; }
294 for (; j
>0; i
--,j
--) {
313 for (i
=1; i
<=p
; i
++) Z
[i
] = Z
[i
+1]; }
318 /* sub_magnitudes() subtracts the magnitudes of *x & *y assuming that */
319 /* abs(*x) > abs(*y) > 0. */
320 /* The sign of the difference *z is undefined. x&y may overlap but not x&z */
321 /* or y&z. One guard digit is used. The error is less than one ulp. */
322 /* *x & *y are left unchanged. */
324 static void sub_magnitudes(const mp_no
*x
, const mp_no
*y
, mp_no
*z
, int p
) {
332 Z
[k
] = Z
[k
+1] = ZERO
; }
335 if (j
> p
) {__cpy(x
,z
,p
); return; }
339 Z
[k
+1] = RADIX
- Y
[j
--];
347 for (; j
>0; i
--,j
--) {
348 Z
[k
] += (X
[i
] - Y
[j
]);
365 for (i
=1; Z
[i
] == ZERO
; i
++) ;
367 for (k
=1; i
<= p
+1; )
376 /* Add two multiple precision numbers. Set *z = *x + *y. x&y may overlap */
377 /* but not x&z or y&z. One guard digit is used. The error is less than */
378 /* one ulp. *x & *y are left unchanged. */
380 void __add(const mp_no
*x
, const mp_no
*y
, mp_no
*z
, int p
) {
384 if (X
[0] == ZERO
) {__cpy(y
,z
,p
); return; }
385 else if (Y
[0] == ZERO
) {__cpy(x
,z
,p
); return; }
388 if (__acr(x
,y
,p
) > 0) {add_magnitudes(x
,y
,z
,p
); Z
[0] = X
[0]; }
389 else {add_magnitudes(y
,x
,z
,p
); Z
[0] = Y
[0]; }
392 if ((n
=__acr(x
,y
,p
)) == 1) {sub_magnitudes(x
,y
,z
,p
); Z
[0] = X
[0]; }
393 else if (n
== -1) {sub_magnitudes(y
,x
,z
,p
); Z
[0] = Y
[0]; }
400 /* Subtract two multiple precision numbers. *z is set to *x - *y. x&y may */
401 /* overlap but not x&z or y&z. One guard digit is used. The error is */
402 /* less than one ulp. *x & *y are left unchanged. */
404 void __sub(const mp_no
*x
, const mp_no
*y
, mp_no
*z
, int p
) {
408 if (X
[0] == ZERO
) {__cpy(y
,z
,p
); Z
[0] = -Z
[0]; return; }
409 else if (Y
[0] == ZERO
) {__cpy(x
,z
,p
); return; }
412 if (__acr(x
,y
,p
) > 0) {add_magnitudes(x
,y
,z
,p
); Z
[0] = X
[0]; }
413 else {add_magnitudes(y
,x
,z
,p
); Z
[0] = -Y
[0]; }
416 if ((n
=__acr(x
,y
,p
)) == 1) {sub_magnitudes(x
,y
,z
,p
); Z
[0] = X
[0]; }
417 else if (n
== -1) {sub_magnitudes(y
,x
,z
,p
); Z
[0] = -Y
[0]; }
424 /* Multiply two multiple precision numbers. *z is set to *x * *y. x&y */
425 /* may overlap but not x&z or y&z. In case p=1,2,3 the exact result is */
426 /* truncated to p digits. In case p>3 the error is bounded by 1.001 ulp. */
427 /* *x & *y are left unchanged. */
429 void __mul(const mp_no
*x
, const mp_no
*y
, mp_no
*z
, int p
) {
431 int i
, i1
, i2
, j
, k
, k2
;
436 { Z
[0]=ZERO
; return; }
438 /* Multiply, add and carry */
439 k2
= (p
<3) ? p
+p
: p
+3;
442 if (k
> p
) {i1
=k
-p
; i2
=p
+1; }
444 for (i
=i1
,j
=i2
-1; i
<i2
; i
++,j
--) Z
[k
] += X
[i
]*Y
[j
];
446 u
= (Z
[k
] + CUTTER
)-CUTTER
;
447 if (u
> Z
[k
]) u
-= RADIX
;
452 /* Is there a carry beyond the most significant digit? */
454 for (i
=1; i
<=p
; i
++) Z
[i
]=Z
[i
+1];
464 /* Invert a multiple precision number. Set *y = 1 / *x. */
465 /* Relative error bound = 1.001*r**(1-p) for p=2, 1.063*r**(1-p) for p=3, */
466 /* 2.001*r**(1-p) for p>3. */
467 /* *x=0 is not permissible. *x is left unchanged. */
469 void __inv(const mp_no
*x
, mp_no
*y
, int p
) {
476 static const int np1
[] = {0,0,0,0,1,2,2,2,2,3,3,3,3,3,3,3,3,3,
477 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4};
478 const mp_no mptwo
= {1,{1.0,2.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,
479 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,
480 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,
481 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0}};
483 __cpy(x
,&z
,p
); z
.e
=0; __mp_dbl(&z
,&t
,p
);
484 t
=ONE
/t
; __dbl_mp(t
,y
,p
); EY
-= EX
;
486 for (i
=0; i
<np1
[p
]; i
++) {
489 __sub(&mptwo
,y
,&z
,p
);
496 /* Divide one multiple precision number by another.Set *z = *x / *y. *x & *y */
497 /* are left unchanged. x&y may overlap but not x&z or y&z. */
498 /* Relative error bound = 2.001*r**(1-p) for p=2, 2.063*r**(1-p) for p=3 */
499 /* and 3.001*r**(1-p) for p>3. *y=0 is not permissible. */
501 void __dvd(const mp_no
*x
, const mp_no
*y
, mp_no
*z
, int p
) {
505 if (X
[0] == ZERO
) Z
[0] = ZERO
;
506 else {__inv(y
,&w
,p
); __mul(x
,&w
,z
,p
);}