4 * Copyright (c) 1987-2006 Sun Microsystems, Inc. All Rights Reserved.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU 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
22 /* This maths library is based on the MP multi-precision floating-point
23 * arithmetic package originally written in FORTRAN by Richard Brent,
24 * Computer Centre, Australian National University in the 1970's.
26 * It has been converted from FORTRAN into C using the freely available
27 * f2c translator, available via netlib on research.att.com.
29 * The subsequently converted C code has then been tidied up, mainly to
30 * remove any dependencies on the libI77 and libF77 support libraries.
32 * FOR A GENERAL DESCRIPTION OF THE PHILOSOPHY AND DESIGN OF MP,
33 * SEE - R. P. BRENT, A FORTRAN MULTIPLE-PRECISION ARITHMETIC
34 * PACKAGE, ACM TRANS. MATH. SOFTWARE 4 (MARCH 1978), 57-70.
35 * SOME ADDITIONAL DETAILS ARE GIVEN IN THE SAME ISSUE, 71-81.
36 * FOR DETAILS OF THE IMPLEMENTATION, CALLING SEQUENCES ETC. SEE
45 int b
, t
, m
, mxr
, r
[MP_SIZE
];
48 /* Table of constant values */
56 static int c__12
= 12;
58 static int c__10
= 10;
59 static int c__32
= 32;
62 static int c__14
= 14;
64 static int c__239
= 239;
66 static int c__16
= 16;
68 static double mppow_di(double *, int *);
69 static double mppow_ri(float *, int *);
71 static int mpcmpi(int *, int *);
72 static int mpcmpr(int *, float *);
73 static int mpcomp(int *, int *);
74 static int pow_ii(int *, int *);
76 static void mpadd2(int *, int *, int *, int *, int *);
77 static void mpadd3(int *, int *, int *, int *, int *);
78 static void mpaddq(int *, int *, int *, int *);
79 static void mpart1(int *, int *);
80 static void mpchk(int *, int *);
81 static void mpcmr(int *, float *);
82 static void mpcqm(int *, int *, int *);
83 static void mpcrm(float *, int *);
84 static void mpexp1(int *, int *);
85 static void mpext(int *, int *, int *);
86 static void mpgcd(int *, int *);
87 static void mplns(int *, int *);
88 static void mpmaxr(int *);
89 static void mpmlp(int *, int *, int *, int *);
90 static void mpmul2(int *, int *, int *, int *);
91 static void mpmulq(int *, int *, int *, int *);
92 static void mpnzr(int *, int *, int *, int *);
93 static void mpovfl(int *);
94 static void mprec(int *, int *);
95 static void mproot(int *, int *, int *);
96 static void mpsin1(int *, int *, int *);
97 static void mpunfl(int *);
101 mpabs(int *x
, int *y
)
104 /* SETS Y = ABS(X) FOR MP NUMBERS X AND Y */
106 --y
; /* Parameter adjustments */
115 mpadd(int *x
, int *y
, int *z
)
118 /* ADDS X AND Y, FORMING RESULT IN Z, WHERE X, Y AND Z ARE MP
119 * NUMBERS. FOUR GUARD DIGITS ARE USED, AND THEN R*-ROUNDING.
122 --z
; /* Parameter adjustments */
126 mpadd2(&x
[1], &y
[1], &z
[1], &y
[1], &c__0
);
131 mpadd2(int *x
, int *y
, int *z
, int *y1
, int *trunc
)
136 static int ed
, re
, rs
, med
;
138 /* CALLED BY MPADD, MPSUB ETC.
139 * X, Y AND Z ARE MP NUMBERS, Y1 AND TRUNC ARE INTEGERS.
140 * TO FORCE CALL BY REFERENCE RATHER THAN VALUE/RESULT, Y1 IS
141 * DECLARED AS AN ARRAY, BUT ONLY Y1(1) IS EVER USED.
142 * SETS Z = X + Y1(1)*ABS(Y), WHERE Y1(1) = +- Y(1).
143 * IF TRUNC.EQ.0 R*-ROUNDING IS USED, OTHERWISE TRUNCATION.
144 * R*-ROUNDING IS DEFINED IN KUKI AND CODI, COMM. ACM
145 * 16(1973), 223. (SEE ALSO BRENT, IEEE TC-22(1973), 601.)
146 * CHECK FOR X OR Y ZERO
149 --y1
; /* Parameter adjustments */
154 if (x
[1] != 0) goto L20
;
156 /* X = 0 OR NEGLIGIBLE, SO RESULT = +-Y */
164 if (y1
[1] != 0) goto L40
;
166 /* Y = 0 OR NEGLIGIBLE, SO RESULT = X */
176 if (C_abs(s
) <= 1) goto L60
;
180 FPRINTF(stderr
, "*** SIGN NOT 0, +1 OR -1 IN MPADD2 CALL.\nPOSSIBLE OVERWRITING PROBLEM ***\n");
187 /* COMPARE EXPONENTS */
192 if (ed
< 0) goto L90
;
193 else if (ed
== 0) goto L70
;
196 /* EXPONENTS EQUAL SO COMPARE SIGNS, THEN FRACTIONS IF NEC. */
199 if (s
> 0) goto L100
;
202 for (j
= 1; j
<= i__1
; ++j
) {
203 if ((i__2
= x
[j
+ 2] - y
[j
+ 2]) < 0) goto L100
;
204 else if (i__2
== 0) continue;
213 /* HERE EXPONENT(Y) .GE. EXPONENT(X) */
216 if (med
> MP
.t
) goto L10
;
221 mpadd3(&x
[1], &y
[1], &s
, &med
, &re
);
223 /* NORMALIZE, ROUND OR TRUNCATE, AND RETURN */
226 mpnzr(&rs
, &re
, &z
[1], trunc
);
229 /* ABS(X) .GT. ABS(Y) */
232 if (med
> MP
.t
) goto L30
;
237 mpadd3(&y
[1], &x
[1], &s
, &med
, &re
);
243 mpadd3(int *x
, int *y
, int *s
, int *med
, int *re
)
247 static int c
, i
, j
, i2
, i2p
, ted
;
249 /* CALLED BY MPADD2, DOES INNER LOOPS OF ADDITION */
251 --y
; /* Parameter adjustments */
259 /* CLEAR GUARD DIGITS TO RIGHT OF X DIGITS */
262 if (i
<= ted
) goto L20
;
269 if (*s
< 0) goto L130
;
271 /* HERE DO ADDITION, EXPONENT(Y) .GE. EXPONENT(X) */
273 if (i
<= MP
.t
) goto L40
;
277 MP
.r
[i
- 1] = x
[j
+ 2];
279 if (i
> MP
.t
) goto L30
;
282 if (i
<= *med
) goto L60
;
285 c
= y
[i
+ 2] + x
[j
+ 2] + c
;
286 if (c
< MP
.b
) goto L50
;
288 /* CARRY GENERATED HERE */
290 MP
.r
[i
- 1] = c
- MP
.b
;
295 /* NO CARRY GENERATED HERE */
304 if (i
<= 0) goto L90
;
307 if (c
< MP
.b
) goto L70
;
318 /* NO CARRY POSSIBLE HERE */
323 MP
.r
[i
- 1] = y
[i
+ 2];
330 /* MUST SHIFT RIGHT HERE AS CARRY OFF END */
334 for (j
= 2; j
<= i__1
; ++j
) {
336 MP
.r
[i
] = MP
.r
[i
- 1];
342 /* HERE DO SUBTRACTION, ABS(Y) .GT. ABS(X) */
346 MP
.r
[i
- 1] = c
- x
[j
+ 2];
348 if (MP
.r
[i
- 1] >= 0) goto L120
;
350 /* BORROW GENERATED HERE */
359 if (i
> MP
.t
) goto L110
;
362 if (i
<= *med
) goto L160
;
365 c
= y
[i
+ 2] + c
- x
[j
+ 2];
366 if (c
>= 0) goto L150
;
368 /* BORROW GENERATED HERE */
370 MP
.r
[i
- 1] = c
+ MP
.b
;
375 /* NO BORROW GENERATED HERE */
387 if (c
>= 0) goto L70
;
389 MP
.r
[i
- 1] = c
+ MP
.b
;
397 mpaddi(int *x
, int *iy
, int *z
)
400 /* ADDS MULTIPLE-PRECISION X TO INTEGER IY
401 * GIVING MULTIPLE-PRECISION Z.
402 * DIMENSION OF R IN CALLING PROGRAM MUST BE
403 * AT LEAST 2T+6 (BUT Z(1) MAY BE R(T+5)).
404 * DIMENSION R(6) BECAUSE RALPH COMPILER ON UNIVAC 1100 COMPUTERS
405 * OBJECTS TO DIMENSION R(1).
406 * CHECK LEGALITY OF B, T, M AND MXR
409 --z
; /* Parameter adjustments */
413 mpcim(iy
, &MP
.r
[MP
.t
+ 4]);
414 mpadd(&x
[1], &MP
.r
[MP
.t
+ 4], &z
[1]);
419 mpaddq(int *x
, int *i
, int *j
, int *y
)
422 /* ADDS THE RATIONAL NUMBER I/J TO MP NUMBER X, MP RESULT IN Y
423 * DIMENSION OF R MUST BE AT LEAST 2T+6
424 * CHECK LEGALITY OF B, T, M AND MXR
427 --y
; /* Parameter adjustments */
431 mpcqm(i
, j
, &MP
.r
[MP
.t
+ 4]);
432 mpadd(&x
[1], &MP
.r
[MP
.t
+ 4], &y
[1]);
437 mpart1(int *n
, int *y
)
441 static int i
, b2
, i2
, id
, ts
;
443 /* COMPUTES MP Y = ARCTAN(1/N), ASSUMING INTEGER N .GT. 1.
444 * USES SERIES ARCTAN(X) = X - X**3/3 + X**5/5 - ...
445 * DIMENSION OF R IN CALLING PROGRAM MUST BE
447 * CHECK LEGALITY OF B, T, M AND MXR
450 --y
; /* Parameter adjustments */
453 if (*n
> 1) goto L20
;
456 FPRINTF(stderr
, "*** N .LE. 1 IN CALL TO MPART1 ***\n");
467 /* SET SUM TO X = 1/N */
469 mpcqm(&c__1
, n
, &y
[1]);
471 /* SET ADDITIVE TERM TO X */
473 mpstr(&y
[1], &MP
.r
[i2
- 1]);
477 /* ASSUME AT LEAST 16-BIT WORD. */
480 if (*n
< b2
) id
= b2
* 7 * b2
/ (*n
* *n
);
482 /* MAIN LOOP. FIRST REDUCE T IF POSSIBLE */
485 MP
.t
= ts
+ 2 + MP
.r
[i2
] - y
[2];
486 if (MP
.t
< 2) goto L60
;
490 /* IF (I+2)*N**2 IS NOT REPRESENTABLE AS AN INTEGER THE DIVISION
491 * FOLLOWING HAS TO BE PERFORMED IN SEVERAL STEPS.
494 if (i
>= id
) goto L40
;
497 i__2
= (i
+ 2) * *n
* *n
;
498 mpmulq(&MP
.r
[i2
- 1], &i__1
, &i__2
, &MP
.r
[i2
- 1]);
504 mpmulq(&MP
.r
[i2
- 1], &i__1
, &i__2
, &MP
.r
[i2
- 1]);
505 mpdivi(&MP
.r
[i2
- 1], n
, &MP
.r
[i2
- 1]);
506 mpdivi(&MP
.r
[i2
- 1], n
, &MP
.r
[i2
- 1]);
515 /* ADD TO SUM, USING MPADD2 (FASTER THAN MPADD) */
517 mpadd2(&MP
.r
[i2
- 1], &y
[1], &y
[1], &y
[1], &c__0
);
518 if (MP
.r
[i2
- 1] != 0) goto L30
;
526 mpasin(int *x
, int *y
)
532 /* RETURNS Y = ARCSIN(X), ASSUMING ABS(X) .LE. 1,
533 * FOR MP NUMBERS X AND Y.
534 * Y IS IN THE RANGE -PI/2 TO +PI/2.
535 * METHOD IS TO USE MPATAN, SO TIME IS O(M(T)T).
536 * DIMENSION OF R MUST BE AT LEAST 5T+12
537 * CHECK LEGALITY OF B, T, M AND MXR
540 --y
; /* Parameter adjustments */
543 mpchk(&c__5
, &c__12
);
544 i3
= (MP
.t
<< 2) + 11;
545 if (x
[1] == 0) goto L30
;
547 if (x
[2] <= 0) goto L40
;
549 /* HERE ABS(X) .GE. 1. SEE IF X = +-1 */
551 mpcim(&x
[1], &MP
.r
[i3
- 1]);
552 if (mpcomp(&x
[1], &MP
.r
[i3
- 1]) != 0) goto L10
;
554 /* X = +-1 SO RETURN +-PI/2 */
557 i__1
= MP
.r
[i3
- 1] << 1;
558 mpdivi(&y
[1], &i__1
, &y
[1]);
563 FPRINTF(stderr
, "*** ABS(X) .GT. 1 IN CALL TO MPASIN ***\n");
572 /* HERE ABS(X) .LT. 1 SO USE ARCTAN(X/SQRT(1 - X**2)) */
575 i2
= i3
- (MP
.t
+ 2);
576 mpcim(&c__1
, &MP
.r
[i2
- 1]);
577 mpstr(&MP
.r
[i2
- 1], &MP
.r
[i3
- 1]);
578 mpsub(&MP
.r
[i2
- 1], &x
[1], &MP
.r
[i2
- 1]);
579 mpadd(&MP
.r
[i3
- 1], &x
[1], &MP
.r
[i3
- 1]);
580 mpmul(&MP
.r
[i2
- 1], &MP
.r
[i3
- 1], &MP
.r
[i3
- 1]);
581 mproot(&MP
.r
[i3
- 1], &c_n2
, &MP
.r
[i3
- 1]);
582 mpmul(&x
[1], &MP
.r
[i3
- 1], &y
[1]);
583 mpatan(&y
[1], &y
[1]);
588 mpatan(int *x
, int *y
)
593 static int i
, q
, i2
, i3
, ie
, ts
;
596 /* RETURNS Y = ARCTAN(X) FOR MP X AND Y, USING AN O(T.M(T)) METHOD
597 * WHICH COULD EASILY BE MODIFIED TO AN O(SQRT(T)M(T))
598 * METHOD (AS IN MPEXP1). Y IS IN THE RANGE -PI/2 TO +PI/2.
599 * FOR AN ASYMPTOTICALLY FASTER METHOD, SEE - FAST MULTIPLE-
600 * PRECISION EVALUATION OF ELEMENTARY FUNCTIONS
601 * (BY R. P. BRENT), J. ACM 23 (1976), 242-251,
602 * AND THE COMMENTS IN MPPIGL.
603 * DIMENSION OF R IN CALLING PROGRAM MUST BE AT LEAST 5T+12
604 * CHECK LEGALITY OF B, T, M AND MXR
607 --y
; /* Parameter adjustments */
610 mpchk(&c__5
, &c__12
);
620 mpstr(&x
[1], &MP
.r
[i3
- 1]);
622 if (ie
<= 2) mpcmr(&x
[1], &rx
);
626 /* REDUCE ARGUMENT IF NECESSARY BEFORE USING SERIES */
629 if (MP
.r
[i3
] < 0) goto L30
;
631 if (MP
.r
[i3
] == 0 && (MP
.r
[i3
+ 1] + 1) << 1 <= MP
.b
)
635 mpmul(&MP
.r
[i3
- 1], &MP
.r
[i3
- 1], &y
[1]);
636 mpaddi(&y
[1], &c__1
, &y
[1]);
637 mpsqrt(&y
[1], &y
[1]);
638 mpaddi(&y
[1], &c__1
, &y
[1]);
639 mpdiv(&MP
.r
[i3
- 1], &y
[1], &MP
.r
[i3
- 1]);
642 /* USE POWER SERIES NOW ARGUMENT IN (-0.5, 0.5) */
645 mpstr(&MP
.r
[i3
- 1], &y
[1]);
646 mpmul(&MP
.r
[i3
- 1], &MP
.r
[i3
- 1], &MP
.r
[i2
- 1]);
650 /* SERIES LOOP. REDUCE T IF POSSIBLE. */
653 MP
.t
= ts
+ 2 + MP
.r
[i3
];
654 if (MP
.t
<= 2) goto L50
;
657 mpmul(&MP
.r
[i3
- 1], &MP
.r
[i2
- 1], &MP
.r
[i3
- 1]);
660 mpmulq(&MP
.r
[i3
- 1], &i__1
, &i__2
, &MP
.r
[i3
- 1]);
663 mpadd(&y
[1], &MP
.r
[i3
- 1], &y
[1]);
664 if (MP
.r
[i3
- 1] != 0) goto L40
;
666 /* RESTORE T, CORRECT FOR ARGUMENT REDUCTION, AND EXIT */
670 mpmuli(&y
[1], &q
, &y
[1]);
672 /* CHECK THAT RELATIVE ERROR LESS THAN 0.01 UNLESS EXPONENT
673 * OF X IS LARGE (WHEN ATAN MIGHT NOT WORK)
679 if ((r__1
= ry
- atan(rx
), dabs(r__1
)) < dabs(ry
) * (float).01)
682 /* THE FOLLOWING MESSAGE MAY INDICATE THAT B**(T-1) IS TOO SMALL. */
685 FPRINTF(stderr
, "*** ERROR OCCURRED IN MPATAN, RESULT INCORRECT ***\n");
693 mpcdm(double *dx
, int *z
)
697 static int i
, k
, i2
, ib
, ie
, re
, tp
, rs
;
698 static double db
, dj
;
700 /* CONVERTS DOUBLE-PRECISION NUMBER DX TO MULTIPLE-PRECISION Z.
701 * SOME NUMBERS WILL NOT CONVERT EXACTLY ON MACHINES
702 * WITH BASE OTHER THAN TWO, FOUR OR SIXTEEN.
703 * THIS ROUTINE IS NOT CALLED BY ANY OTHER ROUTINE IN MP,
704 * SO MAY BE OMITTED IF DOUBLE-PRECISION IS NOT AVAILABLE.
705 * CHECK LEGALITY OF B, T, M AND MXR
708 --z
; /* Parameter adjustments */
715 if (*dx
< 0.) goto L20
;
716 else if (*dx
== 0) goto L10
;
719 /* IF DX = 0D0 RETURN 0 */
742 if (dj
< 1.) goto L60
;
744 /* INCREASE IE AND DIVIDE DJ BY 16. */
751 if (dj
>= .0625) goto L70
;
757 /* NOW DJ IS DY DIVIDED BY SUITABLE POWER OF 16
764 /* DB = DFLOAT(B) IS NOT ANSI STANDARD SO USE FLOAT AND DBLE */
766 db
= (double) ((float) MP
.b
);
768 /* CONVERSION LOOP (ASSUME DOUBLE-PRECISION OPS. EXACT) */
771 for (i
= 1; i
<= i__1
; ++i
) {
773 MP
.r
[i
- 1] = (int) dj
;
774 dj
-= (double) ((float) MP
.r
[i
- 1]);
777 /* NORMALIZE RESULT */
779 mpnzr(&rs
, &re
, &z
[1], &c__0
);
783 i__1
= MP
.b
* 7 * MP
.b
;
784 ib
= max(i__1
, 32767) / 16;
787 /* NOW MULTIPLY BY 16**IE */
789 if (ie
< 0) goto L90
;
790 else if (ie
== 0) goto L130
;
796 for (i
= 1; i
<= i__1
; ++i
) {
798 if (tp
<= ib
&& tp
!= MP
.b
&& i
< k
) continue;
799 mpdivi(&z
[1], &tp
, &z
[1]);
806 for (i
= 1; i
<= i__1
; ++i
) {
808 if (tp
<= ib
&& tp
!= MP
.b
&& i
< ie
) continue;
809 mpmuli(&z
[1], &tp
, &z
[1]);
819 mpchk(int *i
, int *j
)
823 /* CHECKS LEGALITY OF B, T, M AND MXR.
824 * THE CONDITION ON MXR (THE DIMENSION OF R IN COMMON) IS THAT
828 /* CHECK LEGALITY OF B, T AND M */
830 if (MP
.b
> 1) goto L40
;
833 FPRINTF(stderr
, "*** B = %d ILLEGAL IN CALL TO MPCHK.\nPERHAPS NOT SET BEFORE CALL TO AN MP ROUTINE ***\n", MP
.b
);
838 if (MP
.t
> 1) goto L60
;
841 FPRINTF(stderr
, "*** T = %d ILLEGAL IN CALL TO MPCHK.\nPERHAPS NOT SET BEFORE CALL TO AN MP ROUTINE ***\n", MP
.t
);
846 if (MP
.m
> MP
.t
) goto L80
;
849 FPRINTF(stderr
, "*** M .LE. T IN CALL TO MPCHK.\nPERHAPS NOT SET BEFORE CALL TO AN MP ROUTINE ***\n");
853 /* 8*B*B-1 SHOULD BE REPRESENTABLE, IF NOT WILL OVERFLOW
854 * AND MAY BECOME NEGATIVE, SO CHECK FOR THIS
858 ib
= (MP
.b
<< 2) * MP
.b
- 1;
859 if (ib
> 0 && (ib
<< 1) + 1 > 0) goto L100
;
862 FPRINTF(stderr
, "*** B TOO LARGE IN CALL TO MPCHK ***\n");
867 /* CHECK THAT SPACE IN COMMON IS SUFFICIENT */
871 if (MP
.mxr
>= mx
) return;
873 /* HERE COMMON IS TOO SMALL, SO GIVE ERROR MESSAGE. */
877 "*** MXR TOO SMALL OR NOT SET TO DIM(R) BEFORE CALL TO AN MP ROUTINE ***\n");
879 "*** MXR SHOULD BE AT LEAST %d*T + %d = %d ***\n*** ACTUALLY MXR = %d, AND T = %d ***\n",
880 *i
, *j
, mx
, MP
.mxr
, MP
.t
);
888 mpcim(int *ix
, int *z
)
894 /* CONVERTS INTEGER IX TO MULTIPLE-PRECISION Z.
895 * CHECK LEGALITY OF B, T, M AND MXR
898 --z
; /* Parameter adjustments */
903 else if (n
== 0) goto L10
;
918 /* SET EXPONENT TO T */
926 for (i
= 2; i
<= i__1
; ++i
) z
[i
+ 1] = 0;
932 /* NORMALIZE BY CALLING MPMUL2 */
934 mpmul2(&z
[1], &c__1
, &z
[1], &c__1
);
939 mpcmd(int *x
, double *dz
)
945 static double db
, dz2
;
947 /* CONVERTS MULTIPLE-PRECISION X TO DOUBLE-PRECISION DZ.
948 * ASSUMES X IS IN ALLOWABLE RANGE FOR DOUBLE-PRECISION
949 * NUMBERS. THERE IS SOME LOSS OF ACCURACY IF THE
951 * CHECK LEGALITY OF B, T, M AND MXR
954 --x
; /* Parameter adjustments */
958 if (x
[1] == 0) return;
960 /* DB = DFLOAT(B) IS NOT ANSI STANDARD, SO USE FLOAT AND DBLE */
962 db
= (double) ((float) MP
.b
);
964 for (i
= 1; i
<= i__1
; ++i
) {
965 *dz
= db
* *dz
+ (double) ((float) x
[i
+ 2]);
968 /* CHECK IF FULL DOUBLE-PRECISION ACCURACY ATTAINED */
972 /* TEST BELOW NOT ALWAYS EQUIVALENT TO - IF (DZ2.LE.DZ) GO TO 20,
973 * FOR EXAMPLE ON CYBER 76.
975 if (dz2
- *dz
<= 0.) goto L20
;
978 /* NOW ALLOW FOR EXPONENT */
982 *dz
*= mppow_di(&db
, &i__1
);
984 /* CHECK REASONABLENESS OF RESULT. */
986 if (*dz
<= 0.) goto L30
;
988 /* LHS SHOULD BE .LE. 0.5 BUT ALLOW FOR SOME ERROR IN DLOG */
990 if ((d__1
= (double) ((float) x
[2]) - (log(*dz
) / log((double)
991 ((float) MP
.b
)) + .5), C_abs(d__1
)) > .6) {
995 if (x
[1] < 0) *dz
= -(*dz
);
998 /* FOLLOWING MESSAGE INDICATES THAT X IS TOO LARGE OR SMALL -
999 * TRY USING MPCMDE INSTEAD.
1004 FPRINTF(stderr
, "*** FLOATING-POINT OVER/UNDER-FLOW IN MPCMD ***\n");
1012 mpcmf(int *x
, int *y
)
1017 static int x2
, il
, ip
, xs
;
1019 /* FOR MP X AND Y, RETURNS FRACTIONAL PART OF X IN Y,
1020 * I.E., Y = X - INTEGER PART OF X (TRUNCATED TOWARDS 0).
1023 --y
; /* Parameter adjustments */
1026 if (x
[1] != 0) goto L20
;
1028 /* RETURN 0 IF X = 0 */
1037 /* RETURN 0 IF EXPONENT SO LARGE THAT NO FRACTIONAL PART */
1039 if (x2
>= MP
.t
) goto L10
;
1041 /* IF EXPONENT NOT POSITIVE CAN RETURN X */
1043 if (x2
> 0) goto L30
;
1045 mpstr(&x
[1], &y
[1]);
1048 /* CLEAR ACCUMULATOR */
1052 for (i
= 1; i
<= i__1
; ++i
) MP
.r
[i
- 1] = 0;
1056 /* MOVE FRACTIONAL PART OF X TO ACCUMULATOR */
1059 for (i
= il
; i
<= i__1
; ++i
) MP
.r
[i
- 1] = x
[i
+ 2];
1061 for (i
= 1; i
<= 4; ++i
) {
1067 /* NORMALIZE RESULT AND RETURN */
1069 mpnzr(&xs
, &x2
, &y
[1], &c__1
);
1074 mpcmi(int *x
, int *iz
)
1078 static int i
, j
, k
, j1
, x2
, kx
, xs
, izs
;
1080 /* CONVERTS MULTIPLE-PRECISION X TO INTEGER IZ,
1081 * ASSUMING THAT X NOT TOO LARGE (ELSE USE MPCMIM).
1082 * X IS TRUNCATED TOWARDS ZERO.
1083 * IF INT(X)IS TOO LARGE TO BE REPRESENTED AS A SINGLE-
1084 * PRECISION INTEGER, IZ IS RETURNED AS ZERO. THE USER
1085 * MAY CHECK FOR THIS POSSIBILITY BY TESTING IF
1086 * ((X(1).NE.0).AND.(X(2).GT.0).AND.(IZ.EQ.0)) IS TRUE ON
1087 * RETURN FROM MPCMI.
1090 --x
; /* Parameter adjustments */
1094 if (xs
== 0) return;
1096 if (x
[2] <= 0) return;
1100 for (i
= 1; i
<= i__1
; ++i
) {
1103 if (i
<= MP
.t
) *iz
+= x
[i
+ 2];
1105 /* CHECK FOR SIGNS OF INTEGER OVERFLOW */
1107 if (*iz
<= 0 || *iz
<= izs
) goto L30
;
1110 /* CHECK THAT RESULT IS CORRECT (AN UNDETECTED OVERFLOW MAY
1116 for (i
= 1; i
<= i__1
; ++i
) {
1120 if (k
<= MP
.t
) kx
= x
[k
+ 2];
1121 if (kx
!= j
- MP
.b
* j1
) goto L30
;
1124 if (j
!= 0) goto L30
;
1126 /* RESULT CORRECT SO RESTORE SIGN AND RETURN */
1131 /* HERE OVERFLOW OCCURRED (OR X WAS UNNORMALIZED), SO
1141 mpcmim(int *x
, int *y
)
1143 int tmp
[MP_SIZE
]; /* Temporary store for the number. */
1144 int accuracy
; /* Temporary story for the accuracy. */
1145 int pointed
; /* Whether a decimal point has been given. */
1146 int toclear
; /* Indicates if display should be cleared. */
1147 char disp
[MAXLINE
]; /* Setup a string to store what would be displayed */
1148 enum num_type dtype
; /* Setup a temp display type variable */
1152 static int i
, il
, ll
;
1154 /* RETURNS Y = INTEGER PART OF X (TRUNCATED TOWARDS 0), FOR MP X AND Y.
1155 * USE IF Y TOO LARGE TO BE REPRESENTABLE AS A SINGLE-PRECISION INTEGER.
1156 * (ELSE COULD USE MPCMI).
1157 * CHECK LEGALITY OF B, T, M AND MXR
1160 --y
; /* Parameter adjustments */
1163 mpchk(&c__1
, &c__4
);
1164 mpstr(&x
[1], &y
[1]);
1172 /* IF EXPONENT LARGE ENOUGH RETURN Y = X */
1178 /* IF EXPONENT SMALL ENOUGH RETURN ZERO */
1187 /* SET FRACTION TO ZERO */
1191 for (i
= il
; i
<= i__1
; ++i
) {
1195 /* Fix for Sun bugtraq bug #4006391 - problem with Int function for numbers
1196 * like 4800 when internal representation in something like 4799.999999999.
1199 accuracy
= v
->accuracy
;
1201 pointed
= v
->pointed
;
1202 toclear
= v
->toclear
;
1205 v
->accuracy
= MAX_DIGITS
;
1207 STRCPY(disp
, make_number(tmp
, v
->base
, FALSE
));
1209 if (disp
[0] == '1') {
1213 v
->accuracy
= accuracy
;
1215 v
->pointed
= pointed
;
1216 v
->toclear
= toclear
;
1221 mpcmpi(int *x
, int *i
)
1225 /* COMPARES MP NUMBER X WITH INTEGER I, RETURNING
1229 * DIMENSION OF R IN COMMON AT LEAST 2T+6
1230 * CHECK LEGALITY OF B, T, M AND MXR
1233 --x
; /* Parameter adjustments */
1235 mpchk(&c__2
, &c__6
);
1237 /* CONVERT I TO MULTIPLE-PRECISION AND COMPARE */
1239 mpcim(i
, &MP
.r
[MP
.t
+ 4]);
1240 ret_val
= mpcomp(&x
[1], &MP
.r
[MP
.t
+ 4]);
1246 mpcmpr(int *x
, float *ri
)
1250 /* COMPARES MP NUMBER X WITH REAL NUMBER RI, RETURNING
1254 * DIMENSION OF R IN COMMON AT LEAST 2T+6
1255 * CHECK LEGALITY OF B, T, M AND MXR
1258 --x
; /* Parameter adjustments */
1260 mpchk(&c__2
, &c__6
);
1262 /* CONVERT RI TO MULTIPLE-PRECISION AND COMPARE */
1264 mpcrm(ri
, &MP
.r
[MP
.t
+ 4]);
1265 ret_val
= mpcomp(&x
[1], &MP
.r
[MP
.t
+ 4]);
1271 mpcmr(int *x
, float *rz
)
1277 static float rb
, rz2
;
1279 /* CONVERTS MULTIPLE-PRECISION X TO SINGLE-PRECISION RZ.
1280 * ASSUMES X IN ALLOWABLE RANGE. THERE IS SOME LOSS OF
1281 * ACCURACY IF THE EXPONENT IS LARGE.
1282 * CHECK LEGALITY OF B, T, M AND MXR
1285 --x
; /* Parameter adjustments */
1287 mpchk(&c__1
, &c__4
);
1289 if (x
[1] == 0) return;
1293 for (i
= 1; i
<= i__1
; ++i
) {
1294 *rz
= rb
* *rz
+ (float) x
[i
+ 2];
1297 /* CHECK IF FULL SINGLE-PRECISION ACCURACY ATTAINED */
1299 rz2
= *rz
+ (float) 1.0;
1300 if (rz2
<= *rz
) goto L20
;
1303 /* NOW ALLOW FOR EXPONENT */
1307 *rz
*= mppow_ri(&rb
, &i__1
);
1309 /* CHECK REASONABLENESS OF RESULT */
1311 if (*rz
<= (float)0.) goto L30
;
1313 /* LHS SHOULD BE .LE. 0.5, BUT ALLOW FOR SOME ERROR IN ALOG */
1315 if ((r__1
= (float) x
[2] - (log(*rz
) / log((float) MP
.b
) + (float).5),
1316 dabs(r__1
)) > (float).6) {
1320 if (x
[1] < 0) *rz
= -(double)(*rz
);
1323 /* FOLLOWING MESSAGE INDICATES THAT X IS TOO LARGE OR SMALL -
1324 * TRY USING MPCMRE INSTEAD.
1329 FPRINTF(stderr
, "*** FLOATING-POINT OVER/UNDER-FLOW IN MPCMR ***\n");
1337 mpcomp(int *x
, int *y
)
1339 int ret_val
, i__1
, i__2
;
1343 /* COMPARES THE MULTIPLE-PRECISION NUMBERS X AND Y,
1344 * RETURNING +1 IF X .GT. Y,
1346 * AND 0 IF X .EQ. Y.
1349 --y
; /* Parameter adjustments */
1352 if ((i__1
= x
[1] - y
[1]) < 0) goto L10
;
1353 else if (i__1
== 0) goto L30
;
1368 /* SIGN(X) = SIGN(Y), SEE IF ZERO */
1371 if (x
[1] != 0) goto L40
;
1378 /* HAVE TO COMPARE EXPONENTS AND FRACTIONS */
1383 for (i
= 2; i
<= i__1
; ++i
) {
1384 if ((i__2
= x
[i
] - y
[i
]) < 0) goto L60
;
1385 else if (i__2
== 0) continue;
1394 /* ABS(X) .LT. ABS(Y) */
1400 /* ABS(X) .GT. ABS(Y) */
1409 mpcos(int *x
, int *y
)
1413 /* RETURNS Y = COS(X) FOR MP X AND Y, USING MPSIN AND MPSIN1.
1414 * DIMENSION OF R IN COMMON AT LEAST 5T+12.
1417 --y
; /* Parameter adjustments */
1420 if (x
[1] != 0) goto L10
;
1424 mpcim(&c__1
, &y
[1]);
1427 /* CHECK LEGALITY OF B, T, M AND MXR */
1430 mpchk(&c__5
, &c__12
);
1433 /* SEE IF ABS(X) .LE. 1 */
1435 mpabs(&x
[1], &y
[1]);
1436 if (mpcmpi(&y
[1], &c__1
) <= 0) goto L20
;
1438 /* HERE ABS(X) .GT. 1 SO USE COS(X) = SIN(PI/2 - ABS(X)),
1439 * COMPUTING PI/2 WITH ONE GUARD DIGIT.
1443 mppi(&MP
.r
[i2
- 1]);
1444 mpdivi(&MP
.r
[i2
- 1], &c__2
, &MP
.r
[i2
- 1]);
1446 mpsub(&MP
.r
[i2
- 1], &y
[1], &y
[1]);
1447 mpsin(&y
[1], &y
[1]);
1450 /* HERE ABS(X) .LE. 1 SO USE POWER SERIES */
1453 mpsin1(&y
[1], &y
[1], &c__0
);
1458 mpcosh(int *x
, int *y
)
1462 /* RETURNS Y = COSH(X) FOR MP NUMBERS X AND Y, X NOT TOO LARGE.
1463 * USES MPEXP, DIMENSION OF R IN COMMON AT LEAST 5T+12
1466 --y
; /* Parameter adjustments */
1469 if (x
[1] != 0) goto L10
;
1473 mpcim(&c__1
, &y
[1]);
1476 /* CHECK LEGALITY OF B, T, M AND MXR */
1479 mpchk(&c__5
, &c__12
);
1480 i2
= (MP
.t
<< 2) + 11;
1481 mpabs(&x
[1], &MP
.r
[i2
- 1]);
1483 /* IF ABS(X) TOO LARGE MPEXP WILL PRINT ERROR MESSAGE
1484 * INCREASE M TO AVOID OVERFLOW WHEN COSH(X) REPRESENTABLE
1488 mpexp(&MP
.r
[i2
- 1], &MP
.r
[i2
- 1]);
1489 mprec(&MP
.r
[i2
- 1], &y
[1]);
1490 mpadd(&MP
.r
[i2
- 1], &y
[1], &y
[1]);
1492 /* RESTORE M. IF RESULT OVERFLOWS OR UNDERFLOWS, MPDIVI WILL
1497 mpdivi(&y
[1], &c__2
, &y
[1]);
1502 mpcqm(int *i
, int *j
, int *q
)
1506 /* CONVERTS THE RATIONAL NUMBER I/J TO MULTIPLE PRECISION Q. */
1508 --q
; /* Parameter adjustments */
1513 if (j1
< 0) goto L30
;
1514 else if (j1
== 0) goto L10
;
1519 FPRINTF(stderr
, "*** J = 0 IN CALL TO MPCQM ***\n");
1532 if (j1
!= 1) mpdivi(&q
[1], &j1
, &q
[1]);
1537 mpcrm(float *rx
, int *z
)
1541 static int i
, k
, i2
, ib
, ie
, re
, tp
, rs
;
1542 static float rb
, rj
;
1544 /* CONVERTS SINGLE-PRECISION NUMBER RX TO MULTIPLE-PRECISION Z.
1545 * SOME NUMBERS WILL NOT CONVERT EXACTLY ON MACHINES
1546 * WITH BASE OTHER THAN TWO, FOUR OR SIXTEEN.
1547 * CHECK LEGALITY OF B, T, M AND MXR
1550 --z
; /* Parameter adjustments */
1552 mpchk(&c__1
, &c__4
);
1557 if (*rx
< (float) 0.0) goto L20
;
1558 else if (*rx
== 0) goto L10
;
1561 /* IF RX = 0E0 RETURN 0 */
1571 rj
= -(double)(*rx
);
1584 if (rj
< (float)1.0) goto L60
;
1586 /* INCREASE IE AND DIVIDE RJ BY 16. */
1589 rj
*= (float) 0.0625;
1593 if (rj
>= (float).0625) goto L70
;
1599 /* NOW RJ IS DY DIVIDED BY SUITABLE POWER OF 16.
1607 /* CONVERSION LOOP (ASSUME SINGLE-PRECISION OPS. EXACT) */
1610 for (i
= 1; i
<= i__1
; ++i
) {
1612 MP
.r
[i
- 1] = (int) rj
;
1613 rj
-= (float) MP
.r
[i
- 1];
1616 /* NORMALIZE RESULT */
1618 mpnzr(&rs
, &re
, &z
[1], &c__0
);
1622 i__1
= MP
.b
* 7 * MP
.b
;
1623 ib
= max(i__1
, 32767) / 16;
1626 /* NOW MULTIPLY BY 16**IE */
1628 if (ie
< 0) goto L90
;
1629 else if (ie
== 0) goto L130
;
1635 for (i
= 1; i
<= i__1
; ++i
) {
1637 if (tp
<= ib
&& tp
!= MP
.b
&& i
< k
) continue;
1638 mpdivi(&z
[1], &tp
, &z
[1]);
1645 for (i
= 1; i
<= i__1
; ++i
) {
1647 if (tp
<= ib
&& tp
!= MP
.b
&& i
< ie
) continue;
1648 mpmuli(&z
[1], &tp
, &z
[1]);
1658 mpdiv(int *x
, int *y
, int *z
)
1660 static int i
, i2
, ie
, iz3
;
1662 /* SETS Z = X/Y, FOR MP X, Y AND Z.
1663 * DIMENSION OF R IN CALLING PROGRAM MUST BE AT LEAST 4T+10
1664 * (BUT Z(1) MAY BE R(3T+9)).
1665 * CHECK LEGALITY OF B, T, M AND MXR
1668 --z
; /* Parameter adjustments */
1672 mpchk(&c__4
, &c__10
);
1674 /* CHECK FOR DIVISION BY ZERO */
1676 if (y
[1] != 0) goto L20
;
1679 FPRINTF(stderr
, "*** ATTEMPTED DIVISION BY ZERO IN CALL TO MPDIV ***\n");
1686 /* SPACE USED BY MPREC IS 4T+10 WORDS, BUT CAN OVERLAP SLIGHTLY. */
1691 /* CHECK FOR X = 0 */
1693 if (x
[1] != 0) goto L30
;
1698 /* INCREASE M TO AVOID OVERFLOW IN MPREC */
1703 /* FORM RECIPROCAL OF Y */
1705 mprec(&y
[1], &MP
.r
[i2
- 1]);
1707 /* SET EXPONENT OF R(I2) TO ZERO TO AVOID OVERFLOW IN MPMUL */
1715 mpmul(&x
[1], &MP
.r
[i2
- 1], &z
[1]);
1717 mpext(&i
, &iz3
, &z
[1]);
1719 /* RESTORE M, CORRECT EXPONENT AND RETURN */
1723 if (z
[2] >= -MP
.m
) goto L40
;
1725 /* UNDERFLOW HERE */
1731 if (z
[2] <= MP
.m
) return;
1736 FPRINTF(stderr
, "*** OVERFLOW OCCURRED IN MPDIV ***\n");
1744 mpdivi(int *x
, int *iy
, int *z
)
1748 static int c
, i
, j
, k
, b2
, c2
, i2
, j1
, j2
, r1
;
1749 static int j11
, kh
, re
, iq
, ir
, rs
, iqj
;
1751 /* DIVIDES MP X BY THE SINGLE-PRECISION INTEGER IY GIVING MP Z.
1752 * THIS IS MUCH FASTER THAN DIVISION BY AN MP NUMBER.
1755 --z
; /* Parameter adjustments */
1760 if (j
< 0) goto L30
;
1761 else if (j
== 0) goto L10
;
1766 FPRINTF(stderr
, "*** ATTEMPTED DIVISION BY ZERO IN CALL TO MPDIVI ***\n");
1778 /* CHECK FOR ZERO DIVIDEND */
1780 if (rs
== 0) goto L120
;
1782 /* CHECK FOR DIVISION BY B */
1784 if (j
!= MP
.b
) goto L50
;
1785 mpstr(&x
[1], &z
[1]);
1786 if (re
<= -MP
.m
) goto L240
;
1791 /* CHECK FOR DIVISION BY 1 OR -1 */
1794 if (j
!= 1) goto L60
;
1795 mpstr(&x
[1], &z
[1]);
1804 /* IF J*B NOT REPRESENTABLE AS AN INTEGER HAVE TO SIMULATE
1805 * LONG DIVISION. ASSUME AT LEAST 16-BIT WORD.
1810 i__1
= MP
.b
<< 3, i__2
= 32767 / MP
.b
;
1811 b2
= max(i__1
,i__2
);
1812 if (j
>= b2
) goto L130
;
1814 /* LOOK FOR FIRST NONZERO DIGIT IN QUOTIENT */
1819 if (i
<= MP
.t
) c
+= x
[i
+ 2];
1821 if (r1
< 0) goto L210
;
1822 else if (r1
== 0) goto L70
;
1825 /* ADJUST EXPONENT AND GET T+4 DIGITS IN QUOTIENT */
1830 c
= MP
.b
* (c
- j
* r1
);
1832 if (i
>= MP
.t
) goto L100
;
1835 for (k
= 2; k
<= i__1
; ++k
) {
1838 MP
.r
[k
- 1] = c
/ j
;
1839 c
= MP
.b
* (c
- j
* MP
.r
[k
- 1]);
1841 if (c
< 0) goto L210
;
1846 for (k
= kh
; k
<= i__1
; ++k
) {
1847 MP
.r
[k
- 1] = c
/ j
;
1848 c
= MP
.b
* (c
- j
* MP
.r
[k
- 1]);
1850 if (c
< 0) goto L210
;
1852 /* NORMALIZE AND ROUND RESULT */
1855 mpnzr(&rs
, &re
, &z
[1], &c__0
);
1858 /* HERE NEED SIMULATED DOUBLE-PRECISION DIVISION */
1866 /* LOOK FOR FIRST NONZERO DIGIT */
1872 if (i
<= MP
.t
) c2
= x
[i
+ 2];
1873 if ((i__1
= c
- j1
) < 0) goto L140
;
1874 else if (i__1
== 0) goto L150
;
1878 if (c2
< j2
) goto L140
;
1880 /* COMPUTE T+4 QUOTIENT DIGITS */
1887 /* MAIN LOOP FOR LARGE ABS(IY) CASE */
1891 if (k
> i2
) goto L120
;
1894 /* GET APPROXIMATE QUOTIENT FIRST */
1899 /* NOW REDUCE SO OVERFLOW DOES NOT OCCUR */
1902 if (iq
< b2
) goto L190
;
1904 /* HERE IQ*B WOULD POSSIBLY OVERFLOW SO INCREASE IR */
1910 iq
= iq
* MP
.b
- ir
* j2
;
1911 if (iq
>= 0) goto L200
;
1913 /* HERE IQ NEGATIVE SO IR WAS TOO LARGE */
1919 if (i
<= MP
.t
) iq
+= x
[i
+ 2];
1922 /* R(K) = QUOTIENT, C = REMAINDER */
1924 MP
.r
[k
- 1] = iqj
+ ir
;
1926 if (c
>= 0) goto L170
;
1928 /* CARRY NEGATIVE SO OVERFLOW MUST HAVE OCCURRED */
1931 mpchk(&c__1
, &c__4
);
1934 FPRINTF(stderr
, "*** INTEGER OVERFLOW IN MPDIVI, B TOO LARGE ***\n");
1942 /* UNDERFLOW HERE */
1950 mpeq(int *x
, int *y
)
1954 /* RETURNS LOGICAL VALUE OF (X .EQ. Y) FOR MP X AND Y. */
1956 --y
; /* Parameter adjustments */
1959 ret_val
= mpcomp(&x
[1], &y
[1]) == 0;
1969 /* THIS ROUTINE IS CALLED WHEN AN ERROR CONDITION IS ENCOUNTERED, AND
1970 * AFTER A MESSAGE HAS BEEN WRITTEN TO STDERR.
1978 mpexp(int *x
, int *y
)
1983 static int i
, i2
, i3
, ie
, ix
, ts
, xs
, tss
;
1984 static float rx
, ry
, rlb
;
1986 /* RETURNS Y = EXP(X) FOR MP X AND Y.
1987 * EXP OF INTEGER AND FRACTIONAL PARTS OF X ARE COMPUTED
1988 * SEPARATELY. SEE ALSO COMMENTS IN MPEXP1.
1989 * TIME IS O(SQRT(T)M(T)).
1990 * DIMENSION OF R MUST BE AT LEAST 4T+10 IN CALLING PROGRAM
1991 * CHECK LEGALITY OF B, T, M AND MXR
1994 --y
; /* Parameter adjustments */
1997 mpchk(&c__4
, &c__10
);
1998 i2
= (MP
.t
<< 1) + 7;
2001 /* CHECK FOR X = 0 */
2003 if (x
[1] != 0) goto L10
;
2004 mpcim(&c__1
, &y
[1]);
2007 /* CHECK IF ABS(X) .LT. 1 */
2010 if (x
[2] > 0) goto L20
;
2012 /* USE MPEXP1 HERE */
2014 mpexp1(&x
[1], &y
[1]);
2015 mpaddi(&y
[1], &c__1
, &y
[1]);
2018 /* SEE IF ABS(X) SO LARGE THAT EXP(X) WILL CERTAINLY OVERFLOW
2019 * OR UNDERFLOW. 1.01 IS TO ALLOW FOR ERRORS IN ALOG.
2023 rlb
= log((float) MP
.b
) * (float)1.01;
2024 r__1
= -(double)((float) (MP
.m
+ 1)) * rlb
;
2025 if (mpcmpr(&x
[1], &r__1
) >= 0) goto L40
;
2027 /* UNDERFLOW SO CALL MPUNFL AND RETURN */
2034 r__1
= (float) MP
.m
* rlb
;
2035 if (mpcmpr(&x
[1], &r__1
) <= 0) goto L70
;
2041 FPRINTF(stderr
, "*** OVERFLOW IN SUBROUTINE MPEXP ***\n");
2047 /* NOW SAFE TO CONVERT X TO REAL */
2052 /* SAVE SIGN AND WORK WITH ABS(X) */
2055 mpabs(&x
[1], &MP
.r
[i3
- 1]);
2057 /* IF ABS(X) .GT. M POSSIBLE THAT INT(X) OVERFLOWS,
2061 if (dabs(rx
) > (float) MP
.m
) {
2062 mpdivi(&MP
.r
[i3
- 1], &c__32
, &MP
.r
[i3
- 1]);
2065 /* GET FRACTIONAL AND INTEGER PARTS OF ABS(X) */
2067 mpcmi(&MP
.r
[i3
- 1], &ix
);
2068 mpcmf(&MP
.r
[i3
- 1], &MP
.r
[i3
- 1]);
2070 /* ATTACH SIGN TO FRACTIONAL PART AND COMPUTE EXP OF IT */
2072 MP
.r
[i3
- 1] = xs
* MP
.r
[i3
- 1];
2073 mpexp1(&MP
.r
[i3
- 1], &y
[1]);
2074 mpaddi(&y
[1], &c__1
, &y
[1]);
2076 /* COMPUTE E-2 OR 1/E USING TWO EXTRA DIGITS IN CASE ABS(X) LARGE
2077 * (BUT ONLY ONE EXTRA DIGIT IF T .LT. 4)
2082 if (MP
.t
< 4) ts
= MP
.t
+ 1;
2087 mpcim(&xs
, &MP
.r
[i2
- 1]);
2090 /* LOOP FOR E COMPUTATION. DECREASE T IF POSSIBLE. */
2096 i__1
= ts
, i__2
= ts
+ 2 + MP
.r
[i2
];
2097 MP
.t
= min(i__1
,i__2
);
2098 if (MP
.t
<= 2) goto L90
;
2101 mpdivi(&MP
.r
[i2
- 1], &i__1
, &MP
.r
[i2
- 1]);
2103 mpadd2(&MP
.r
[i3
- 1], &MP
.r
[i2
- 1], &MP
.r
[i3
- 1], &
2104 MP
.r
[i2
- 1], &c__0
);
2105 if (MP
.r
[i2
- 1] != 0) goto L80
;
2107 /* RAISE E OR 1/E TO POWER IX */
2112 mpaddi(&MP
.r
[i3
- 1], &c__2
, &MP
.r
[i3
- 1]);
2114 mppwr(&MP
.r
[i3
- 1], &ix
, &MP
.r
[i3
- 1]);
2120 /* MULTIPLY EXPS OF INTEGER AND FRACTIONAL PARTS */
2122 mpmul(&y
[1], &MP
.r
[i3
- 1], &y
[1]);
2124 /* MUST CORRECT RESULT IF DIVIDED BY 32 ABOVE. */
2126 if (dabs(rx
) <= (float) MP
.m
|| y
[1] == 0) goto L110
;
2128 for (i
= 1; i
<= 5; ++i
) {
2130 /* SAVE EXPONENT TO AVOID OVERFLOW IN MPMUL */
2134 mpmul(&y
[1], &y
[1], &y
[1]);
2137 /* CHECK FOR UNDERFLOW AND OVERFLOW */
2139 if (y
[2] < -MP
.m
) goto L30
;
2140 if (y
[2] > MP
.m
) goto L50
;
2143 /* CHECK THAT RELATIVE ERROR LESS THAN 0.01 UNLESS ABS(X) LARGE
2144 * (WHEN EXP MIGHT OVERFLOW OR UNDERFLOW)
2148 if (dabs(rx
) > (float)10.0) return;
2151 if ((r__1
= ry
- exp(rx
), dabs(r__1
)) < ry
* (float)0.01) return;
2153 /* THE FOLLOWING MESSAGE MAY INDICATE THAT
2154 * B**(T-1) IS TOO SMALL, OR THAT M IS TOO SMALL SO THE
2155 * RESULT UNDERFLOWED.
2159 FPRINTF(stderr
, "*** ERROR OCCURRED IN MPEXP, RESULT INCORRECT ***\n");
2167 mpexp1(int *x
, int *y
)
2171 static int i
, q
, i2
, i3
, ib
, ic
, ts
;
2174 /* ASSUMES THAT X AND Y ARE MP NUMBERS, -1 .LT. X .LT. 1.
2175 * RETURNS Y = EXP(X) - 1 USING AN O(SQRT(T).M(T)) ALGORITHM
2176 * DESCRIBED IN - R. P. BRENT, THE COMPLEXITY OF MULTIPLE-
2177 * PRECISION ARITHMETIC (IN COMPLEXITY OF COMPUTATIONAL PROBLEM
2178 * SOLVING, UNIV. OF QUEENSLAND PRESS, BRISBANE, 1976, 126-165).
2179 * ASYMPTOTICALLY FASTER METHODS EXIST, BUT ARE NOT USEFUL
2180 * UNLESS T IS VERY LARGE. SEE COMMENTS TO MPATAN AND MPPIGL.
2181 * DIMENSION OF R IN CALLING PROGRAM MUST BE AT LEAST 3T+8
2182 * CHECK LEGALITY OF B, T, M AND MXR
2185 --y
; /* Parameter adjustments */
2188 mpchk(&c__3
, &c__8
);
2192 /* CHECK FOR X = 0 */
2194 if (x
[1] != 0) goto L20
;
2200 /* CHECK THAT ABS(X) .LT. 1 */
2203 if (x
[2] <= 0) goto L40
;
2206 FPRINTF(stderr
, "*** ABS(X) NOT LESS THAN 1 IN CALL TO MPEXP1 ***\n");
2213 mpstr(&x
[1], &MP
.r
[i2
- 1]);
2214 rlb
= log((float) MP
.b
);
2216 /* COMPUTE APPROXIMATELY OPTIMAL Q (AND DIVIDE X BY 2**Q) */
2218 q
= (int) (sqrt((float) MP
.t
* (float).48 * rlb
) + (float) x
[2] *
2223 if (q
<= 0) goto L60
;
2227 for (i
= 1; i
<= i__1
; ++i
) {
2229 if (ic
< ib
&& ic
!= MP
.b
&& i
< q
) continue;
2230 mpdivi(&MP
.r
[i2
- 1], &ic
, &MP
.r
[i2
- 1]);
2235 if (MP
.r
[i2
- 1] == 0) goto L10
;
2236 mpstr(&MP
.r
[i2
- 1], &y
[1]);
2237 mpstr(&MP
.r
[i2
- 1], &MP
.r
[i3
- 1]);
2241 /* SUM SERIES, REDUCING T WHERE POSSIBLE */
2244 MP
.t
= ts
+ 2 + MP
.r
[i3
] - y
[2];
2245 if (MP
.t
<= 2) goto L80
;
2247 MP
.t
= min(MP
.t
,ts
);
2248 mpmul(&MP
.r
[i2
- 1], &MP
.r
[i3
- 1], &MP
.r
[i3
- 1]);
2250 mpdivi(&MP
.r
[i3
- 1], &i
, &MP
.r
[i3
- 1]);
2252 mpadd2(&MP
.r
[i3
- 1], &y
[1], &y
[1], &y
[1], &c__0
);
2253 if (MP
.r
[i3
- 1] != 0) goto L70
;
2259 /* APPLY (X+1)**2 - 1 = X(2 + X) FOR Q ITERATIONS */
2262 for (i
= 1; i
<= i__1
; ++i
) {
2263 mpaddi(&y
[1], &c__2
, &MP
.r
[i2
- 1]);
2264 mpmul(&MP
.r
[i2
- 1], &y
[1], &y
[1]);
2270 mpext(int *i
, int *j
, int *x
)
2274 /* ROUTINE CALLED BY MPDIV AND MPSQRT TO ENSURE THAT
2275 * RESULTS ARE REPRESENTED EXACTLY IN T-2 DIGITS IF THEY
2276 * CAN BE. X IS AN MP NUMBER, I AND J ARE INTEGERS.
2279 --x
; /* Parameter adjustments */
2281 if (x
[1] == 0 || MP
.t
<= 2 || *i
== 0) return;
2283 /* COMPUTE MAXIMUM POSSIBLE ERROR IN THE LAST PLACE */
2285 q
= (*j
+ 1) / *i
+ 1;
2286 s
= MP
.b
* x
[MP
.t
+ 1] + x
[MP
.t
+ 2];
2287 if (s
> q
) goto L10
;
2289 /* SET LAST TWO DIGITS TO ZERO */
2296 if (s
+ q
< MP
.b
* MP
.b
) return;
2300 x
[MP
.t
+ 1] = MP
.b
- 1;
2303 /* NORMALIZE X (LAST DIGIT B IS OK IN MPMULI) */
2305 mpmuli(&x
[1], &c__1
, &x
[1]);
2310 mpgcd(int *k
, int *l
)
2312 static int i
, j
, is
, js
;
2314 /* RETURNS K = K/GCD AND L = L/GCD, WHERE GCD IS THE
2315 * GREATEST COMMON DIVISOR OF K AND L.
2316 * SAVE INPUT PARAMETERS IN LOCAL VARIABLES
2323 if (js
== 0) goto L30
;
2325 /* EUCLIDEAN ALGORITHM LOOP */
2329 if (is
== 0) goto L20
;
2331 if (js
!= 0) goto L10
;
2334 /* HERE JS IS THE GCD OF I AND J */
2341 /* IF J = 0 RETURN (1, 0) UNLESS I = 0, THEN (0, 0) */
2345 if (is
== 0) *k
= 0;
2351 mpge(int *x
, int *y
)
2355 /* RETURNS LOGICAL VALUE OF (X .GE. Y) FOR MP X AND Y. */
2357 --y
; /* Parameter adjustments */
2360 ret_val
= mpcomp(&x
[1], &y
[1]) >= 0;
2367 mpgt(int *x
, int *y
)
2371 /* RETURNS LOGICAL VALUE OF (X .GT. Y) FOR MP X AND Y. */
2373 --y
; /* Parameter adjustments */
2376 ret_val
= mpcomp(&x
[1], &y
[1]) > 0;
2383 mple(int *x
, int *y
)
2387 /* RETURNS LOGICAL VALUE OF (X .LE. Y) FOR MP X AND Y. */
2389 --y
; /* Parameter adjustments */
2392 ret_val
= mpcomp(&x
[1], &y
[1]) <= 0;
2399 mpln(int *x
, int *y
)
2403 static int e
, k
, i2
, i3
;
2404 static float rx
, rlx
;
2406 /* RETURNS Y = LN(X), FOR MP X AND Y, USING MPLNS.
2407 * RESTRICTION - INTEGER PART OF LN(X) MUST BE REPRESENTABLE
2408 * AS A SINGLE-PRECISION INTEGER. TIME IS O(SQRT(T).M(T)).
2409 * FOR SMALL INTEGER X, MPLNI IS FASTER.
2410 * ASYMPTOTICALLY FASTER METHODS EXIST (EG THE GAUSS-SALAMIN
2411 * METHOD, SEE MPLNGS), BUT ARE NOT USEFUL UNLESS T IS LARGE.
2412 * SEE COMMENTS TO MPATAN, MPEXP1 AND MPPIGL.
2413 * DIMENSION OF R IN CALLING PROGRAM MUST BE AT LEAST 6T+14.
2414 * CHECK LEGALITY OF B, T, M AND MXR
2417 --y
; /* Parameter adjustments */
2420 mpchk(&c__6
, &c__14
);
2421 i2
= (MP
.t
<< 2) + 11;
2424 /* CHECK THAT X IS POSITIVE */
2425 if (x
[1] > 0) goto L20
;
2428 FPRINTF(stderr
, "*** X NONPOSITIVE IN CALL TO MPLN ***\n");
2435 /* MOVE X TO LOCAL STORAGE */
2438 mpstr(&x
[1], &MP
.r
[i2
- 1]);
2442 /* LOOP TO GET APPROXIMATE LN(X) USING SINGLE-PRECISION */
2445 mpaddi(&MP
.r
[i2
- 1], &c_n1
, &MP
.r
[i3
- 1]);
2447 /* IF POSSIBLE GO TO CALL MPLNS */
2449 if (MP
.r
[i3
- 1] == 0 || MP
.r
[i3
] + 1 <= 0) goto L50
;
2451 /* REMOVE EXPONENT TO AVOID FLOATING-POINT OVERFLOW */
2455 mpcmr(&MP
.r
[i2
- 1], &rx
);
2457 /* RESTORE EXPONENT AND COMPUTE SINGLE-PRECISION LOG */
2460 rlx
= log(rx
) + (float) e
* log((float) MP
.b
);
2461 r__1
= -(double)rlx
;
2462 mpcrm(&r__1
, &MP
.r
[i3
- 1]);
2464 /* UPDATE Y AND COMPUTE ACCURATE EXP OF APPROXIMATE LOG */
2466 mpsub(&y
[1], &MP
.r
[i3
- 1], &y
[1]);
2467 mpexp(&MP
.r
[i3
- 1], &MP
.r
[i3
- 1]);
2469 /* COMPUTE RESIDUAL WHOSE LOG IS STILL TO BE FOUND */
2471 mpmul(&MP
.r
[i2
- 1], &MP
.r
[i3
- 1], &MP
.r
[i2
- 1]);
2473 /* MAKE SURE NOT LOOPING INDEFINITELY */
2475 if (k
< 10) goto L30
;
2478 FPRINTF(stderr
, "*** ERROR IN MPLN, ITERATION NOT CONVERGING ***\n");
2484 /* COMPUTE FINAL CORRECTION ACCURATELY USING MPLNS */
2487 mplns(&MP
.r
[i3
- 1], &MP
.r
[i3
- 1]);
2488 mpadd(&y
[1], &MP
.r
[i3
- 1], &y
[1]);
2493 mplns(int *x
, int *y
)
2497 static int i2
, i3
, i4
, ts
, it0
, ts2
, ts3
;
2499 /* RETURNS MP Y = LN(1+X) IF X IS AN MP NUMBER SATISFYING THE
2500 * CONDITION ABS(X) .LT. 1/B, ERROR OTHERWISE.
2501 * USES NEWTONS METHOD TO SOLVE THE EQUATION
2502 * EXP1(-Y) = X, THEN REVERSES SIGN OF Y.
2503 * (HERE EXP1(Y) = EXP(Y) - 1 IS COMPUTED USING MPEXP1).
2504 * TIME IS O(SQRT(T).M(T)) AS FOR MPEXP1, SPACE = 5T+12.
2505 * CHECK LEGALITY OF B, T, M AND MXR
2508 --y
; /* Parameter adjustments */
2511 mpchk(&c__5
, &c__12
);
2512 i2
= (MP
.t
<< 1) + 7;
2516 /* CHECK FOR X = 0 EXACTLY */
2518 if (x
[1] != 0) goto L10
;
2522 /* CHECK THAT ABS(X) .LT. 1/B */
2525 if (x
[2] + 1 <= 0) goto L30
;
2528 FPRINTF(stderr
, "*** ABS(X) .GE. 1/B IN CALL TO MPLNS ***\n");
2535 /* SAVE T AND GET STARTING APPROXIMATION TO -LN(1+X) */
2539 mpstr(&x
[1], &MP
.r
[i3
- 1]);
2540 mpdivi(&x
[1], &c__4
, &MP
.r
[i2
- 1]);
2541 mpaddq(&MP
.r
[i2
- 1], &c_n1
, &c__3
, &MP
.r
[i2
- 1]);
2542 mpmul(&x
[1], &MP
.r
[i2
- 1], &MP
.r
[i2
- 1]);
2543 mpaddq(&MP
.r
[i2
- 1], &c__1
, &c__2
, &MP
.r
[i2
- 1]);
2544 mpmul(&x
[1], &MP
.r
[i2
- 1], &MP
.r
[i2
- 1]);
2545 mpaddi(&MP
.r
[i2
- 1], &c_n1
, &MP
.r
[i2
- 1]);
2546 mpmul(&x
[1], &MP
.r
[i2
- 1], &y
[1]);
2548 /* START NEWTON ITERATION USING SMALL T, LATER INCREASE */
2552 i__1
= 5, i__2
= 13 - (MP
.b
<< 1);
2553 MP
.t
= max(i__1
,i__2
);
2554 if (MP
.t
> ts
) goto L80
;
2556 it0
= (MP
.t
+ 5) / 2;
2559 mpexp1(&y
[1], &MP
.r
[i4
- 1]);
2560 mpmul(&MP
.r
[i3
- 1], &MP
.r
[i4
- 1], &MP
.r
[i2
- 1]);
2561 mpadd(&MP
.r
[i4
- 1], &MP
.r
[i2
- 1], &MP
.r
[i4
- 1]);
2562 mpadd(&MP
.r
[i3
- 1], &MP
.r
[i4
- 1], &MP
.r
[i4
- 1]);
2563 mpsub(&y
[1], &MP
.r
[i4
- 1], &y
[1]);
2564 if (MP
.t
>= ts
) goto L60
;
2566 /* FOLLOWING LOOP COMPUTES NEXT VALUE OF T TO USE.
2567 * BECAUSE NEWTONS METHOD HAS 2ND ORDER CONVERGENCE,
2568 * WE CAN ALMOST DOUBLE T EACH TIME.
2576 MP
.t
= (MP
.t
+ it0
) / 2;
2577 if (MP
.t
> ts3
) goto L50
;
2582 /* CHECK THAT NEWTON ITERATION WAS CONVERGING AS EXPECTED */
2585 if (MP
.r
[i4
- 1] == 0 || MP
.r
[i4
] << 1 <= it0
- MP
.t
) {
2590 FPRINTF(stderr
, "*** ERROR OCCURRED IN MPLNS.\nNEWTON ITERATION NOT CONVERGING PROPERLY ***\n");
2595 /* REVERSE SIGN OF Y AND RETURN */
2604 mplt(int *x
, int *y
)
2608 /* RETURNS LOGICAL VALUE OF (X .LT. Y) FOR MP X AND Y. */
2610 --y
; /* Parameter adjustments */
2613 ret_val
= mpcomp(&x
[1], &y
[1]) < 0;
2626 /* SETS X TO THE LARGEST POSSIBLE POSITIVE MP NUMBER
2627 * CHECK LEGALITY OF B, T, M AND MXR
2630 --x
; /* Parameter adjustments */
2632 mpchk(&c__1
, &c__4
);
2635 /* SET FRACTION DIGITS TO B-1 */
2638 for (i
= 1; i
<= i__1
; ++i
) x
[i
+ 2] = it
;
2640 /* SET SIGN AND EXPONENT */
2648 mpmlp(int *u
, int *v
, int *w
, int *j
)
2654 /* PERFORMS INNER MULTIPLICATION LOOP FOR MPMUL
2655 * NOTE THAT CARRIES ARE NOT PROPAGATED IN INNER LOOP,
2656 * WHICH SAVES TIME AT THE EXPENSE OF SPACE.
2659 --v
; /* Parameter adjustments */
2663 for (i
= 1; i
<= i__1
; ++i
) u
[i
] += *w
* v
[i
];
2668 mpmul(int *x
, int *y
, int *z
)
2670 int i__1
, i__2
, i__3
, i__4
;
2672 static int c
, i
, j
, i2
, j1
, re
, ri
, xi
, rs
, i2p
;
2674 /* MULTIPLIES X AND Y, RETURNING RESULT IN Z, FOR MP X, Y AND Z.
2675 * THE SIMPLE O(T**2) ALGORITHM IS USED, WITH
2676 * FOUR GUARD DIGITS AND R*-ROUNDING.
2677 * ADVANTAGE IS TAKEN OF ZERO DIGITS IN X, BUT NOT IN Y.
2678 * ASYMPTOTICALLY FASTER ALGORITHMS ARE KNOWN (SEE KNUTH,
2679 * VOL. 2), BUT ARE DIFFICULT TO IMPLEMENT IN FORTRAN IN AN
2680 * EFFICIENT AND MACHINE-INDEPENDENT MANNER.
2681 * IN COMMENTS TO OTHER MP ROUTINES, M(T) IS THE TIME
2682 * TO PERFORM T-DIGIT MP MULTIPLICATION. THUS
2683 * M(T) = O(T**2) WITH THE PRESENT VERSION OF MPMUL,
2684 * BUT M(T) = O(T.LOG(T).LOG(LOG(T))) IS THEORETICALLY POSSIBLE.
2685 * CHECK LEGALITY OF B, T, M AND MXR
2688 --z
; /* Parameter adjustments */
2692 mpchk(&c__1
, &c__4
);
2696 /* FORM SIGN OF PRODUCT */
2699 if (rs
!= 0) goto L10
;
2701 /* SET RESULT TO ZERO */
2706 /* FORM EXPONENT OF PRODUCT */
2711 /* CLEAR ACCUMULATOR */
2714 for (i
= 1; i
<= i__1
; ++i
) MP
.r
[i
- 1] = 0;
2716 /* PERFORM MULTIPLICATION */
2720 for (i
= 1; i
<= i__1
; ++i
) {
2723 /* FOR SPEED, PUT THE NUMBER WITH MANY ZEROS FIRST */
2725 if (xi
== 0) continue;
2729 i__3
= MP
.t
, i__4
= i2
- i
;
2730 i__2
= min(i__3
,i__4
);
2731 mpmlp(&MP
.r
[i
], &y
[3], &xi
, &i__2
);
2733 if (c
> 0) continue;
2735 /* CHECK FOR LEGAL BASE B DIGIT */
2737 if (xi
< 0 || xi
>= MP
.b
) goto L90
;
2739 /* PROPAGATE CARRIES AT END AND EVERY EIGHTH TIME,
2740 * FASTER THAN DOING IT EVERY TIME.
2744 for (j
= 1; j
<= i__2
; ++j
) {
2746 ri
= MP
.r
[j1
- 1] + c
;
2747 if (ri
< 0) goto L70
;
2749 MP
.r
[j1
- 1] = ri
- MP
.b
* c
;
2751 if (c
!= 0) goto L90
;
2755 if (c
== 8) goto L60
;
2756 if (xi
< 0 || xi
>= MP
.b
) goto L90
;
2759 for (j
= 1; j
<= i__1
; ++j
) {
2761 ri
= MP
.r
[j1
- 1] + c
;
2762 if (ri
< 0) goto L70
;
2764 MP
.r
[j1
- 1] = ri
- MP
.b
* c
;
2766 if (c
!= 0) goto L90
;
2768 /* NORMALIZE AND ROUND RESULT */
2771 mpnzr(&rs
, &re
, &z
[1], &c__0
);
2776 FPRINTF(stderr
, "*** INTEGER OVERFLOW IN MPMUL, B TOO LARGE ***\n");
2783 FPRINTF(stderr
, "*** ILLEGAL BASE B DIGIT IN CALL TO MPMUL.\nPOSSIBLE OVERWRITING PROBLEM ***\n");
2793 mpmul2(int *x
, int *iy
, int *z
, int *trunc
)
2797 static int c
, i
, j
, c1
, c2
, j1
, j2
;
2798 static int t1
, t3
, t4
, ij
, re
, ri
, is
, ix
, rs
;
2800 /* MULTIPLIES MP X BY SINGLE-PRECISION INTEGER IY GIVING MP Z.
2801 * MULTIPLICATION BY 1 MAY BE USED TO NORMALIZE A NUMBER
2802 * EVEN IF SOME DIGITS ARE GREATER THAN B-1.
2803 * RESULT IS ROUNDED IF TRUNC.EQ.0, OTHERWISE TRUNCATED.
2806 --z
; /* Parameter adjustments */
2810 if (rs
== 0) goto L10
;
2812 if (j
< 0) goto L20
;
2813 else if (j
== 0) goto L10
;
2826 /* CHECK FOR MULTIPLICATION BY B */
2828 if (j
!= MP
.b
) goto L50
;
2829 if (x
[2] < MP
.m
) goto L40
;
2831 mpchk(&c__1
, &c__4
);
2834 FPRINTF(stderr
, "*** OVERFLOW OCCURRED IN MPMUL2 ***\n");
2841 mpstr(&x
[1], &z
[1]);
2846 /* SET EXPONENT TO EXPONENT(X) + 4 */
2851 /* FORM PRODUCT IN ACCUMULATOR */
2858 /* IF J*B NOT REPRESENTABLE AS AN INTEGER WE HAVE TO SIMULATE
2859 * DOUBLE-PRECISION MULTIPLICATION.
2864 i__1
= MP
.b
<< 3, i__2
= 32767 / MP
.b
;
2865 if (j
>= max(i__1
,i__2
)) goto L110
;
2868 for (ij
= 1; ij
<= i__1
; ++ij
) {
2870 ri
= j
* x
[i
+ 2] + c
;
2872 MP
.r
[i
+ 3] = ri
- MP
.b
* c
;
2875 /* CHECK FOR INTEGER OVERFLOW */
2877 if (ri
< 0) goto L130
;
2879 /* HAVE TO TREAT FIRST FOUR WORDS OF R SEPARATELY */
2881 for (ij
= 1; ij
<= 4; ++ij
) {
2885 MP
.r
[i
- 1] = ri
- MP
.b
* c
;
2887 if (c
== 0) goto L100
;
2889 /* HAVE TO SHIFT RIGHT HERE AS CARRY OFF END */
2893 for (ij
= 1; ij
<= i__1
; ++ij
) {
2895 MP
.r
[i
] = MP
.r
[i
- 1];
2899 MP
.r
[0] = ri
- MP
.b
* c
;
2901 if (c
< 0) goto L130
;
2902 else if (c
== 0) goto L100
;
2905 /* NORMALIZE AND ROUND OR TRUNCATE RESULT */
2908 mpnzr(&rs
, &re
, &z
[1], trunc
);
2911 /* HERE J IS TOO LARGE FOR SINGLE-PRECISION MULTIPLICATION */
2920 for (ij
= 1; ij
<= i__1
; ++ij
) {
2925 if (i
> 0) ix
= x
[i
+ 2];
2928 c
= j1
* ix
+ c1
+ is
;
2929 MP
.r
[i
+ 3] = ri
- MP
.b
* is
;
2932 if (c
< 0) goto L130
;
2933 else if (c
== 0) goto L100
;
2936 /* CAN ONLY GET HERE IF INTEGER OVERFLOW OCCURRED */
2939 mpchk(&c__1
, &c__4
);
2942 FPRINTF(stderr
, "*** INTEGER OVERFLOW IN MPMUL2, B TOO LARGE ***\n");
2951 mpmuli(int *x
, int *iy
, int *z
)
2954 /* MULTIPLIES MP X BY SINGLE-PRECISION INTEGER IY GIVING MP Z.
2955 * THIS IS FASTER THAN USING MPMUL. RESULT IS ROUNDED.
2956 * MULTIPLICATION BY 1 MAY BE USED TO NORMALIZE A NUMBER
2957 * EVEN IF THE LAST DIGIT IS B.
2960 --z
; /* Parameter adjustments */
2963 mpmul2(&x
[1], iy
, &z
[1], &c__0
);
2968 mpmulq(int *x
, int *i
, int *j
, int *y
)
2974 /* MULTIPLIES MP X BY I/J, GIVING MP Y */
2976 --y
; /* Parameter adjustments */
2979 if (*j
!= 0) goto L20
;
2980 mpchk(&c__1
, &c__4
);
2983 FPRINTF(stderr
, "*** ATTEMPTED DIVISION BY ZERO IN MPMULQ ***\n");
2990 if (*i
!= 0) goto L40
;
2996 /* REDUCE TO LOWEST TERMS */
3002 if (C_abs(is
) == 1) goto L50
;
3004 mpdivi(&x
[1], &js
, &y
[1]);
3005 mpmul2(&y
[1], &is
, &y
[1], &c__0
);
3012 mpdivi(&x
[1], &i__1
, &y
[1]);
3017 mpneg(int *x
, int *y
)
3020 /* SETS Y = -X FOR MP NUMBERS X AND Y */
3022 --y
; /* Parameter adjustments */
3025 mpstr(&x
[1], &y
[1]);
3031 mpnzr(int *rs
, int *re
, int *z
, int *trunc
)
3035 static int i
, j
, k
, b2
, i2
, is
, it
, i2m
, i2p
;
3037 /* ASSUMES LONG (I.E. (T+4)-DIGIT) FRACTION IN
3038 * R, SIGN = RS, EXPONENT = RE. NORMALIZES,
3039 * AND RETURNS MP RESULT IN Z. INTEGER ARGUMENTS RS AND RE
3040 * ARE NOT PRESERVED. R*-ROUNDING IS USED IF TRUNC.EQ.0
3043 --z
; /* Parameter adjustments */
3046 if (*rs
!= 0) goto L20
;
3048 /* STORE ZERO IN Z */
3054 /* CHECK THAT SIGN = +-1 */
3057 if (C_abs(*rs
) <= 1) goto L40
;
3060 FPRINTF(stderr
, "*** SIGN NOT 0, +1 OR -1 IN CALL TO MPNZR.\nPOSSIBLE OVERWRITING PROBLEM ***\n");
3066 /* LOOK FOR FIRST NONZERO DIGIT */
3070 for (i
= 1; i
<= i__1
; ++i
) {
3072 if (MP
.r
[i
- 1] > 0) goto L60
;
3080 if (is
== 0) goto L90
;
3087 for (j
= 1; j
<= i__1
; ++j
) {
3089 MP
.r
[j
- 1] = MP
.r
[k
- 1];
3093 for (j
= i2p
; j
<= i__1
; ++j
) MP
.r
[j
- 1] = 0;
3095 /* CHECK TO SEE IF TRUNCATION IS DESIRED */
3098 if (*trunc
!= 0) goto L150
;
3100 /* SEE IF ROUNDING NECESSARY
3101 * TREAT EVEN AND ODD BASES DIFFERENTLY
3105 if (b2
<< 1 != MP
.b
) goto L130
;
3107 /* B EVEN. ROUND IF R(T+1).GE.B2 UNLESS R(T) ODD AND ALL ZEROS
3111 if ((i__1
= MP
.r
[MP
.t
] - b2
) < 0) goto L150
;
3112 else if (i__1
== 0) goto L100
;
3116 if (MP
.r
[MP
.t
- 1] % 2 == 0) goto L110
;
3118 if (MP
.r
[MP
.t
+ 1] + MP
.r
[MP
.t
+ 2] + MP
.r
[MP
.t
+ 3] == 0) {
3126 for (j
= 1; j
<= i__1
; ++j
) {
3129 if (MP
.r
[i
- 1] < MP
.b
) goto L150
;
3133 /* EXCEPTIONAL CASE, ROUNDED UP TO .10000... */
3139 /* ODD BASE, ROUND IF R(T+1)... .GT. 1/2 */
3142 for (i
= 1; i
<= 4; ++i
) {
3144 if ((i__1
= MP
.r
[it
- 1] - b2
) < 0) goto L150
;
3145 else if (i__1
== 0) continue;
3149 /* CHECK FOR OVERFLOW */
3152 if (*re
<= MP
.m
) goto L170
;
3155 FPRINTF(stderr
, "*** OVERFLOW OCCURRED IN MPNZR ***\n");
3161 /* CHECK FOR UNDERFLOW */
3164 if (*re
< -MP
.m
) goto L190
;
3166 /* STORE RESULT IN Z */
3171 for (i
= 1; i
<= i__1
; ++i
) z
[i
+ 2] = MP
.r
[i
- 1];
3174 /* UNDERFLOW HERE */
3185 /* CALLED ON MULTIPLE-PRECISION OVERFLOW, IE WHEN THE
3186 * EXPONENT OF MP NUMBER X WOULD EXCEED M.
3187 * AT PRESENT EXECUTION IS TERMINATED WITH AN ERROR MESSAGE
3188 * AFTER CALLING MPMAXR(X), BUT IT WOULD BE POSSIBLE TO RETURN,
3189 * POSSIBLY UPDATING A COUNTER AND TERMINATING EXECUTION AFTER
3190 * A PRESET NUMBER OF OVERFLOWS. ACTION COULD EASILY BE DETERMINED
3191 * BY A FLAG IN LABELLED COMMON.
3192 * M MAY HAVE BEEN OVERWRITTEN, SO CHECK B, T, M ETC.
3195 --x
; /* Parameter adjustments */
3197 mpchk(&c__1
, &c__4
);
3199 /* SET X TO LARGEST POSSIBLE POSITIVE NUMBER */
3204 FPRINTF(stderr
, "*** CALL TO MPOVFL, MP OVERFLOW OCCURRED ***\n");
3207 /* TERMINATE EXECUTION BY CALLING MPERR */
3221 /* SETS MP X = PI TO THE AVAILABLE PRECISION.
3222 * USES PI/4 = 4.ARCTAN(1/5) - ARCTAN(1/239).
3224 * DIMENSION OF R MUST BE AT LEAST 3T+8
3225 * CHECK LEGALITY OF B, T, M AND MXR
3228 --x
; /* Parameter adjustments */
3230 mpchk(&c__3
, &c__8
);
3232 /* ALLOW SPACE FOR MPART1 */
3234 i2
= (MP
.t
<< 1) + 7;
3235 mpart1(&c__5
, &MP
.r
[i2
- 1]);
3236 mpmuli(&MP
.r
[i2
- 1], &c__4
, &MP
.r
[i2
- 1]);
3237 mpart1(&c__239
, &x
[1]);
3238 mpsub(&MP
.r
[i2
- 1], &x
[1], &x
[1]);
3239 mpmuli(&x
[1], &c__4
, &x
[1]);
3241 /* RETURN IF ERROR IS LESS THAN 0.01 */
3244 if ((r__1
= rx
- (float)3.1416, dabs(r__1
)) < (float) 0.01) return;
3246 /* FOLLOWING MESSAGE MAY INDICATE THAT B**(T-1) IS TOO SMALL */
3249 FPRINTF(stderr
, "*** ERROR OCCURRED IN MPPI, RESULT INCORRECT ***\n");
3257 mppwr(int *x
, int *n
, int *y
)
3259 static int i2
, n2
, ns
;
3261 /* RETURNS Y = X**N, FOR MP X AND Y, INTEGER N, WITH 0**0 = 1.
3262 * R MUST BE DIMENSIONED AT LEAST 4T+10 IN CALLING PROGRAM
3263 * (2T+6 IS ENOUGH IF N NONNEGATIVE).
3266 --y
; /* Parameter adjustments */
3271 if (n2
< 0) goto L20
;
3272 else if (n2
== 0) goto L10
;
3275 /* N = 0, RETURN Y = 1. */
3278 mpcim(&c__1
, &y
[1]);
3284 mpchk(&c__4
, &c__10
);
3286 if (x
[1] != 0) goto L60
;
3289 FPRINTF(stderr
, "*** ATTEMPT TO RAISE ZERO TO NEGATIVE POWER IN CALL TO SUBROUTINE MPPWR ***\n");
3298 mpchk(&c__2
, &c__6
);
3299 if (x
[1] != 0) goto L60
;
3301 /* X = 0, N .GT. 0, SO Y = 0 */
3310 mpstr(&x
[1], &y
[1]);
3312 /* IF N .LT. 0 FORM RECIPROCAL */
3314 if (*n
< 0) mprec(&y
[1], &y
[1]);
3315 mpstr(&y
[1], &MP
.r
[i2
- 1]);
3317 /* SET PRODUCT TERM TO ONE */
3319 mpcim(&c__1
, &y
[1]);
3321 /* MAIN LOOP, LOOK AT BITS OF N2 FROM RIGHT */
3326 if (n2
<< 1 != ns
) mpmul(&y
[1], &MP
.r
[i2
- 1], &y
[1]);
3327 if (n2
<= 0) return;
3329 mpmul(&MP
.r
[i2
- 1], &MP
.r
[i2
- 1], &MP
.r
[i2
- 1]);
3335 mppwr2(int *x
, int *y
, int *z
)
3339 /* RETURNS Z = X**Y FOR MP NUMBERS X, Y AND Z, WHERE X IS
3340 * POSITIVE (X .EQ. 0 ALLOWED IF Y .GT. 0). SLOWER THAN
3341 * MPPWR AND MPQPWR, SO USE THEM IF POSSIBLE.
3342 * DIMENSION OF R IN COMMON AT LEAST 7T+16
3343 * CHECK LEGALITY OF B, T, M AND MXR
3346 --z
; /* Parameter adjustments */
3350 mpchk(&c__7
, &c__16
);
3351 if (x
[1] < 0) goto L10
;
3352 else if (x
[1] == 0) goto L30
;
3356 show_error(_("Negative X and non-integer Y not supported"));
3359 /* HERE X IS ZERO, RETURN ZERO IF Y POSITIVE, OTHERWISE ERROR */
3362 if (y
[1] > 0) goto L60
;
3365 FPRINTF(stderr
, "*** X ZERO AND Y NONPOSITIVE IN CALL TO MPPWR2 ***\n");
3371 /* RETURN ZERO HERE */
3377 /* USUAL CASE HERE, X POSITIVE
3378 * USE MPLN AND MPEXP TO COMPUTE POWER
3383 mpln(&x
[1], &MP
.r
[i2
- 1]);
3384 mpmul(&y
[1], &MP
.r
[i2
- 1], &z
[1]);
3386 /* IF X**Y IS TOO LARGE, MPEXP WILL PRINT ERROR MESSAGE */
3388 mpexp(&z
[1], &z
[1]);
3393 mprec(int *x
, int *y
)
3396 /* Initialized data */
3398 static int it
[9] = { 0, 8, 6, 5, 4, 4, 4, 4, 4 };
3402 static int i2
, i3
, ex
, ts
, it0
, ts2
, ts3
;
3405 /* RETURNS Y = 1/X, FOR MP X AND Y.
3406 * MPROOT (X, -1, Y) HAS THE SAME EFFECT.
3407 * DIMENSION OF R MUST BE AT LEAST 4*T+10 IN CALLING PROGRAM
3408 * (BUT Y(1) MAY BE R(3T+9)).
3409 * NEWTONS METHOD IS USED, SO FINAL ONE OR TWO DIGITS MAY
3413 --y
; /* Parameter adjustments */
3416 /* CHECK LEGALITY OF B, T, M AND MXR */
3418 mpchk(&c__4
, &c__10
);
3420 /* MPADDI REQUIRES 2T+6 WORDS. */
3422 i2
= (MP
.t
<< 1) + 7;
3424 if (x
[1] != 0) goto L20
;
3427 FPRINTF(stderr
, "*** ATTEMPTED DIVISION BY ZERO IN CALL TO MPREC ***\n");
3437 /* TEMPORARILY INCREASE M TO AVOID OVERFLOW */
3441 /* SET EXPONENT TO ZERO SO RX NOT TOO LARGE OR SMALL. */
3446 /* USE SINGLE-PRECISION RECIPROCAL AS FIRST APPROXIMATION */
3448 r__1
= (float)1. / rx
;
3449 mpcrm(&r__1
, &MP
.r
[i2
- 1]);
3451 /* RESTORE EXPONENT */
3455 /* CORRECT EXPONENT OF FIRST APPROXIMATION */
3459 /* SAVE T (NUMBER OF DIGITS) */
3463 /* START WITH SMALL T TO SAVE TIME. ENSURE THAT B**(T-1) .GE. 100 */
3466 if (MP
.b
< 10) MP
.t
= it
[MP
.b
- 1];
3467 it0
= (MP
.t
+ 4) / 2;
3468 if (MP
.t
> ts
) goto L70
;
3470 /* MAIN ITERATION LOOP */
3473 mpmul(&x
[1], &MP
.r
[i2
- 1], &MP
.r
[i3
- 1]);
3474 mpaddi(&MP
.r
[i3
- 1], &c_n1
, &MP
.r
[i3
- 1]);
3476 /* TEMPORARILY REDUCE T */
3479 MP
.t
= (MP
.t
+ it0
) / 2;
3480 mpmul(&MP
.r
[i2
- 1], &MP
.r
[i3
- 1], &MP
.r
[i3
- 1]);
3485 mpsub(&MP
.r
[i2
- 1], &MP
.r
[i3
- 1], &MP
.r
[i2
- 1]);
3486 if (MP
.t
>= ts
) goto L50
;
3488 /* FOLLOWING LOOP ALMOST DOUBLES T (POSSIBLE
3489 * BECAUSE NEWTONS METHOD HAS 2ND ORDER CONVERGENCE).
3496 MP
.t
= (MP
.t
+ it0
) / 2;
3497 if (MP
.t
> ts3
) goto L40
;
3502 /* RETURN IF NEWTON ITERATION WAS CONVERGING */
3505 if (MP
.r
[i3
- 1] == 0 || (MP
.r
[i2
] - MP
.r
[i3
]) << 1 >= MP
.t
- it0
) {
3509 /* THE FOLLOWING MESSAGE MAY INDICATE THAT B**(T-1) IS TOO SMALL,
3510 * OR THAT THE STARTING APPROXIMATION IS NOT ACCURATE ENOUGH.
3514 FPRINTF(stderr
, "*** ERROR OCCURRED IN MPREC, NEWTON ITERATION NOT CONVERGING PROPERLY ***\n");
3519 /* MOVE RESULT TO Y AND RETURN AFTER RESTORING T */
3523 mpstr(&MP
.r
[i2
- 1], &y
[1]);
3525 /* RESTORE M AND CHECK FOR OVERFLOW (UNDERFLOW IMPOSSIBLE) */
3528 if (y
[2] <= MP
.m
) return;
3531 FPRINTF(stderr
, "*** OVERFLOW OCCURRED IN MPREC ***\n");
3539 mproot(int *x
, int *n
, int *y
)
3542 /* Initialized data */
3544 static int it
[9] = { 0, 8, 6, 5, 4, 4, 4, 4, 4 };
3549 static int i2
, i3
, ex
, np
, ts
, it0
, ts2
, ts3
, xes
;
3552 /* RETURNS Y = X**(1/N) FOR INTEGER N, ABS(N) .LE. MAX (B, 64).
3553 * AND MP NUMBERS X AND Y,
3554 * USING NEWTONS METHOD WITHOUT DIVISIONS. SPACE = 4T+10
3555 * (BUT Y(1) MAY BE R(3T+9))
3558 --y
; /* Parameter adjustments */
3561 /* CHECK LEGALITY OF B, T, M AND MXR */
3563 mpchk(&c__4
, &c__10
);
3564 if (*n
!= 1) goto L10
;
3565 mpstr(&x
[1], &y
[1]);
3569 i2
= (MP
.t
<< 1) + 7;
3571 if (*n
!= 0) goto L30
;
3574 FPRINTF(stderr
, "*** N = 0 IN CALL TO MPROOT ***\n");
3582 /* LOSS OF ACCURACY IF NP LARGE, SO ONLY ALLOW NP .LE. MAX (B, 64) */
3584 if (np
<= max(MP
.b
,64)) goto L60
;
3587 FPRINTF(stderr
, "*** ABS(N) TOO LARGE IN CALL TO MPROOT ***\n");
3595 /* LOOK AT SIGN OF X */
3598 if (x
[1] < 0) goto L90
;
3599 else if (x
[1] == 0) goto L70
;
3602 /* X = 0 HERE, RETURN 0 IF N POSITIVE, ERROR IF NEGATIVE */
3609 FPRINTF(stderr
, "*** X = 0 AND N NEGATIVE IN CALL TO MPROOT ***\n");
3614 /* X NEGATIVE HERE, SO ERROR IF N IS EVEN */
3617 if (np
% 2 != 0) goto L110
;
3620 FPRINTF(stderr
, "*** X NEGATIVE AND N EVEN IN CALL TO MPROOT ***\n");
3625 /* GET EXPONENT AND DIVIDE BY NP */
3631 /* REDUCE EXPONENT SO RX NOT TOO LARGE OR SMALL. */
3636 /* USE SINGLE-PRECISION ROOT FOR FIRST APPROXIMATION */
3638 r__1
= exp(((float) (np
* ex
- xes
) * log((float) MP
.b
) -
3639 log((dabs(rx
)))) / (float) np
);
3640 mpcrm(&r__1
, &MP
.r
[i2
- 1]);
3642 /* SIGN OF APPROXIMATION SAME AS THAT OF X */
3644 MP
.r
[i2
- 1] = x
[1];
3646 /* RESTORE EXPONENT */
3650 /* CORRECT EXPONENT OF FIRST APPROXIMATION */
3654 /* SAVE T (NUMBER OF DIGITS) */
3658 /* START WITH SMALL T TO SAVE TIME */
3662 /* ENSURE THAT B**(T-1) .GE. 100 */
3664 if (MP
.b
< 10) MP
.t
= it
[MP
.b
- 1];
3665 if (MP
.t
> ts
) goto L160
;
3667 /* IT0 IS A NECESSARY SAFETY FACTOR */
3669 it0
= (MP
.t
+ 4) / 2;
3671 /* MAIN ITERATION LOOP */
3674 mppwr(&MP
.r
[i2
- 1], &np
, &MP
.r
[i3
- 1]);
3675 mpmul(&x
[1], &MP
.r
[i3
- 1], &MP
.r
[i3
- 1]);
3676 mpaddi(&MP
.r
[i3
- 1], &c_n1
, &MP
.r
[i3
- 1]);
3678 /* TEMPORARILY REDUCE T */
3681 MP
.t
= (MP
.t
+ it0
) / 2;
3682 mpmul(&MP
.r
[i2
- 1], &MP
.r
[i3
- 1], &MP
.r
[i3
- 1]);
3683 mpdivi(&MP
.r
[i3
- 1], &np
, &MP
.r
[i3
- 1]);
3688 mpsub(&MP
.r
[i2
- 1], &MP
.r
[i3
- 1], &MP
.r
[i2
- 1]);
3690 /* FOLLOWING LOOP ALMOST DOUBLES T (POSSIBLE BECAUSE
3691 * NEWTONS METHOD HAS 2ND ORDER CONVERGENCE).
3694 if (MP
.t
>= ts
) goto L140
;
3699 MP
.t
= (MP
.t
+ it0
) / 2;
3700 if (MP
.t
> ts3
) goto L130
;
3705 /* NOW R(I2) IS X**(-1/NP)
3706 * CHECK THAT NEWTON ITERATION WAS CONVERGING
3710 if (MP
.r
[i3
- 1] == 0 || (MP
.r
[i2
] - MP
.r
[i3
]) << 1 >= MP
.t
- it0
) {
3714 /* THE FOLLOWING MESSAGE MAY INDICATE THAT B**(T-1) IS TOO SMALL,
3715 * OR THAT THE INITIAL APPROXIMATION OBTAINED USING ALOG AND EXP
3716 * IS NOT ACCURATE ENOUGH.
3720 FPRINTF(stderr
, "*** ERROR OCCURRED IN MPROOT, NEWTON ITERATION NOT CONVERGING PROPERLY ***\n");
3729 if (*n
< 0) goto L170
;
3732 mppwr(&MP
.r
[i2
- 1], &i__1
, &MP
.r
[i2
- 1]);
3733 mpmul(&x
[1], &MP
.r
[i2
- 1], &y
[1]);
3737 mpstr(&MP
.r
[i2
- 1], &y
[1]);
3742 mpset(int *idecpl
, int *itmax2
, int *maxdr
)
3746 static int i
, k
, w
, i2
, w2
, wn
;
3748 /* SETS BASE (B) AND NUMBER OF DIGITS (T) TO GIVE THE
3749 * EQUIVALENT OF AT LEAST IDECPL DECIMAL DIGITS.
3750 * IDECPL SHOULD BE POSITIVE.
3751 * ITMAX2 IS THE DIMENSION OF ARRAYS USED FOR MP NUMBERS,
3752 * SO AN ERROR OCCURS IF THE COMPUTED T EXCEEDS ITMAX2 - 2.
3754 * MXR = MAXDR (DIMENSION OF R IN COMMON, .GE. T+4), AND
3755 * M = (W-1)/4 (MAXIMUM ALLOWABLE EXPONENT),
3756 * WHERE W IS THE LARGEST INTEGER OF THE FORM 2**K-1 WHICH IS
3757 * REPRESENTABLE IN THE MACHINE, K .LE. 47
3758 * THE COMPUTED B AND T SATISFY THE CONDITIONS
3759 * (T-1)*LN(B)/LN(10) .GE. IDECPL AND 8*B*B-1 .LE. W .
3760 * APPROXIMATELY MINIMAL T AND MAXIMAL B SATISFYING
3761 * THESE CONDITIONS ARE CHOSEN.
3762 * PARAMETERS IDECPL, ITMAX2 AND MAXDR ARE INTEGERS.
3763 * BEWARE - MPSET WILL CAUSE AN INTEGER OVERFLOW TO OCCUR
3764 * ****** IF WORDLENGTH IS LESS THAN 48 BITS.
3765 * IF THIS IS NOT ALLOWABLE, CHANGE THE DETERMINATION
3766 * OF W (DO 30 ... TO 30 W = WN) OR SET B, T, M,
3767 * AND MXR WITHOUT CALLING MPSET.
3773 /* DETERMINE LARGE REPRESENTABLE INTEGER W OF FORM 2**K - 1 */
3778 /* ON CYBER 76 HAVE TO FIND K .LE. 47, SO ONLY LOOP
3779 * 47 TIMES AT MOST. IF GENUINE INTEGER WORDLENGTH
3780 * EXCEEDS 47 BITS THIS RESTRICTION CAN BE RELAXED.
3783 for (i
= 1; i
<= 47; ++i
) {
3785 /* INTEGER OVERFLOW WILL EVENTUALLY OCCUR HERE
3786 * IF WORDLENGTH .LT. 48 BITS
3792 /* APPARENTLY REDUNDANT TESTS MAY BE NECESSARY ON SOME
3793 * MACHINES, DEPENDING ON HOW INTEGER OVERFLOW IS HANDLED
3796 if (wn
<= w
|| wn
<= w2
|| wn
<= 0) goto L40
;
3801 /* SET MAXIMUM EXPONENT TO (W-1)/4 */
3805 if (*idecpl
> 0) goto L60
;
3808 FPRINTF(stderr
, "*** IDECPL .LE. 0 IN CALL TO MPSET ***\n");
3814 /* B IS THE LARGEST POWER OF 2 SUCH THAT (8*B*B-1) .LE. W */
3818 MP
.b
= pow_ii(&c__2
, &i__1
);
3820 /* 2E0 BELOW ENSURES AT LEAST ONE GUARD DIGIT */
3822 MP
.t
= (int) ((float) (*idecpl
) * log((float)10.) / log((float) MP
.b
) +
3825 /* SEE IF T TOO LARGE FOR DIMENSION STATEMENTS */
3828 if (i2
<= *itmax2
) goto L80
;
3832 "ITMAX2 TOO SMALL IN CALL TO MPSET ***\n*** INCREASE ITMAX2 AND DIMENSIONS OF MP ARRAYS TO AT LEAST %d ***\n",
3838 /* REDUCE TO MAXIMUM ALLOWED BY DIMENSION STATEMENTS */
3842 /* CHECK LEGALITY OF B, T, M AND MXR (AT LEAST T+4) */
3845 mpchk(&c__1
, &c__4
);
3850 mpsin(int *x
, int *y
)
3854 static int i2
, i3
, ie
, xs
;
3855 static float rx
, ry
;
3857 /* RETURNS Y = SIN(X) FOR MP X AND Y,
3858 * METHOD IS TO REDUCE X TO (-1, 1) AND USE MPSIN1, SO
3859 * TIME IS O(M(T)T/LOG(T)).
3860 * DIMENSION OF R IN CALLING PROGRAM MUST BE AT LEAST 5T+12
3861 * CHECK LEGALITY OF B, T, M AND MXR
3864 --y
; /* Parameter adjustments */
3867 mpchk(&c__5
, &c__12
);
3868 i2
= (MP
.t
<< 2) + 11;
3869 if (x
[1] != 0) goto L20
;
3878 if (ie
<= 2) mpcmr(&x
[1], &rx
);
3880 mpabs(&x
[1], &MP
.r
[i2
- 1]);
3882 /* USE MPSIN1 IF ABS(X) .LE. 1 */
3884 if (mpcmpi(&MP
.r
[i2
- 1], &c__1
) > 0) goto L30
;
3886 mpsin1(&MP
.r
[i2
- 1], &y
[1], &c__1
);
3889 /* FIND ABS(X) MODULO 2PI (IT WOULD SAVE TIME IF PI WERE
3890 * PRECOMPUTED AND SAVED IN COMMON).
3891 * FOR INCREASED ACCURACY COMPUTE PI/4 USING MPART1
3895 i3
= (MP
.t
<< 1) + 7;
3896 mpart1(&c__5
, &MP
.r
[i3
- 1]);
3897 mpmuli(&MP
.r
[i3
- 1], &c__4
, &MP
.r
[i3
- 1]);
3898 mpart1(&c__239
, &y
[1]);
3899 mpsub(&MP
.r
[i3
- 1], &y
[1], &y
[1]);
3900 mpdiv(&MP
.r
[i2
- 1], &y
[1], &MP
.r
[i2
- 1]);
3901 mpdivi(&MP
.r
[i2
- 1], &c__8
, &MP
.r
[i2
- 1]);
3902 mpcmf(&MP
.r
[i2
- 1], &MP
.r
[i2
- 1]);
3904 /* SUBTRACT 1/2, SAVE SIGN AND TAKE ABS */
3906 mpaddq(&MP
.r
[i2
- 1], &c_n1
, &c__2
, &MP
.r
[i2
- 1]);
3907 xs
= -xs
* MP
.r
[i2
- 1];
3908 if (xs
== 0) goto L10
;
3911 mpmuli(&MP
.r
[i2
- 1], &c__4
, &MP
.r
[i2
- 1]);
3913 /* IF NOT LESS THAN 1, SUBTRACT FROM 2 */
3916 mpaddi(&MP
.r
[i2
- 1], &c_n2
, &MP
.r
[i2
- 1]);
3919 if (MP
.r
[i2
- 1] == 0) goto L10
;
3922 mpmuli(&MP
.r
[i2
- 1], &c__2
, &MP
.r
[i2
- 1]);
3924 /* NOW REDUCED TO FIRST QUADRANT, IF LESS THAN PI/4 USE
3925 * POWER SERIES, ELSE COMPUTE COS OF COMPLEMENT
3928 if (MP
.r
[i2
] > 0) goto L40
;
3930 mpmul(&MP
.r
[i2
- 1], &y
[1], &MP
.r
[i2
- 1]);
3931 mpsin1(&MP
.r
[i2
- 1], &y
[1], &c__1
);
3935 mpaddi(&MP
.r
[i2
- 1], &c_n2
, &MP
.r
[i2
- 1]);
3936 mpmul(&MP
.r
[i2
- 1], &y
[1], &MP
.r
[i2
- 1]);
3937 mpsin1(&MP
.r
[i2
- 1], &y
[1], &c__0
);
3943 /* CHECK THAT ABSOLUTE ERROR LESS THAN 0.01 IF ABS(X) .LE. 100
3944 * (IF ABS(X) IS LARGE THEN SINGLE-PRECISION SIN INACCURATE)
3947 if (dabs(rx
) > (float)100.) return;
3950 if ((r__1
= ry
- sin(rx
), dabs(r__1
)) < (float) 0.01) return;
3952 /* THE FOLLOWING MESSAGE MAY INDICATE THAT
3953 * B**(T-1) IS TOO SMALL.
3957 FPRINTF(stderr
, "*** ERROR OCCURRED IN MPSIN, RESULT INCORRECT ***\n");
3965 mpsin1(int *x
, int *y
, int *is
)
3969 static int i
, b2
, i2
, i3
, ts
;
3971 /* COMPUTES Y = SIN(X) IF IS.NE.0, Y = COS(X) IF IS.EQ.0,
3972 * USING TAYLOR SERIES. ASSUMES ABS(X) .LE. 1.
3973 * X AND Y ARE MP NUMBERS, IS AN INTEGER.
3974 * TIME IS O(M(T)T/LOG(T)). THIS COULD BE REDUCED TO
3975 * O(SQRT(T)M(T)) AS IN MPEXP1, BUT NOT WORTHWHILE UNLESS
3976 * T IS VERY LARGE. ASYMPTOTICALLY FASTER METHODS ARE
3977 * DESCRIBED IN THE REFERENCES GIVEN IN COMMENTS
3978 * TO MPATAN AND MPPIGL.
3979 * DIMENSION OF R IN CALLING PROGRAM MUST BE AT LEAST 3T+8
3980 * CHECK LEGALITY OF B, T, M AND MXR
3983 --y
; /* Parameter adjustments */
3986 mpchk(&c__3
, &c__8
);
3987 if (x
[1] != 0) goto L20
;
3989 /* SIN(0) = 0, COS(0) = 1 */
3993 if (*is
== 0) mpcim(&c__1
, &y
[1]);
3999 b2
= max(MP
.b
,64) << 1;
4000 mpmul(&x
[1], &x
[1], &MP
.r
[i3
- 1]);
4001 if (mpcmpi(&MP
.r
[i3
- 1], &c__1
) <= 0) goto L40
;
4004 FPRINTF(stderr
, "*** ABS(X) .GT. 1 IN CALL TO MPSIN1 ***\n");
4011 if (*is
== 0) mpcim(&c__1
, &MP
.r
[i2
- 1]);
4012 if (*is
!= 0) mpstr(&x
[1], &MP
.r
[i2
- 1]);
4017 if (*is
== 0) goto L50
;
4019 mpstr(&MP
.r
[i2
- 1], &y
[1]);
4022 /* POWER SERIES LOOP. REDUCE T IF POSSIBLE */
4025 MP
.t
= MP
.r
[i2
] + ts
+ 2;
4026 if (MP
.t
<= 2) goto L80
;
4028 MP
.t
= min(MP
.t
,ts
);
4030 /* PUT R(I3) FIRST IN CASE ITS DIGITS ARE MAINLY ZERO */
4032 mpmul(&MP
.r
[i3
- 1], &MP
.r
[i2
- 1], &MP
.r
[i2
- 1]);
4034 /* IF I*(I+1) IS NOT REPRESENTABLE AS AN INTEGER, THE FOLLOWING
4035 * DIVISION BY I*(I+1) HAS TO BE SPLIT UP.
4038 if (i
> b2
) goto L60
;
4040 i__1
= -i
* (i
+ 1);
4041 mpdivi(&MP
.r
[i2
- 1], &i__1
, &MP
.r
[i2
- 1]);
4046 mpdivi(&MP
.r
[i2
- 1], &i__1
, &MP
.r
[i2
- 1]);
4048 mpdivi(&MP
.r
[i2
- 1], &i__1
, &MP
.r
[i2
- 1]);
4053 mpadd2(&MP
.r
[i2
- 1], &y
[1], &y
[1], &y
[1], &c__0
);
4054 if (MP
.r
[i2
- 1] != 0) goto L50
;
4058 if (*is
== 0) mpaddi(&y
[1], &c__1
, &y
[1]);
4063 mpsinh(int *x
, int *y
)
4067 static int i2
, i3
, xs
;
4069 /* RETURNS Y = SINH(X) FOR MP NUMBERS X AND Y, X NOT TOO LARGE.
4070 * METHOD IS TO USE MPEXP OR MPEXP1, SPACE = 5T+12
4071 * SAVE SIGN OF X AND CHECK FOR ZERO, SINH(0) = 0
4074 --y
; /* Parameter adjustments */
4078 if (xs
!= 0) goto L10
;
4083 /* CHECK LEGALITY OF B, T, M AND MXR */
4086 mpchk(&c__5
, &c__12
);
4087 i3
= (MP
.t
<< 2) + 11;
4089 /* WORK WITH ABS(X) */
4091 mpabs(&x
[1], &MP
.r
[i3
- 1]);
4092 if (MP
.r
[i3
] <= 0) goto L20
;
4094 /* HERE ABS(X) .GE. 1, IF TOO LARGE MPEXP GIVES ERROR MESSAGE
4095 * INCREASE M TO AVOID OVERFLOW IF SINH(X) REPRESENTABLE
4099 mpexp(&MP
.r
[i3
- 1], &MP
.r
[i3
- 1]);
4100 mprec(&MP
.r
[i3
- 1], &y
[1]);
4101 mpsub(&MP
.r
[i3
- 1], &y
[1], &y
[1]);
4103 /* RESTORE M. IF RESULT OVERFLOWS OR UNDERFLOWS, MPDIVI AT
4104 * STATEMENT 30 WILL ACT ACCORDINGLY.
4110 /* HERE ABS(X) .LT. 1 SO USE MPEXP1 TO AVOID CANCELLATION */
4113 i2
= i3
- (MP
.t
+ 2);
4114 mpexp1(&MP
.r
[i3
- 1], &MP
.r
[i2
- 1]);
4115 mpaddi(&MP
.r
[i2
- 1], &c__2
, &MP
.r
[i3
- 1]);
4116 mpmul(&MP
.r
[i3
- 1], &MP
.r
[i2
- 1], &y
[1]);
4117 mpaddi(&MP
.r
[i2
- 1], &c__1
, &MP
.r
[i3
- 1]);
4118 mpdiv(&y
[1], &MP
.r
[i3
- 1], &y
[1]);
4120 /* DIVIDE BY TWO AND RESTORE SIGN */
4124 mpdivi(&y
[1], &i__1
, &y
[1]);
4129 mpsqrt(int *x
, int *y
)
4131 static int i
, i2
, iy3
;
4133 /* RETURNS Y = SQRT(X), USING SUBROUTINE MPROOT IF X .GT. 0.
4134 * DIMENSION OF R IN CALLING PROGRAM MUST BE AT LEAST 4T+10
4135 * (BUT Y(1) MAY BE R(3T+9)). X AND Y ARE MP NUMBERS.
4136 * CHECK LEGALITY OF B, T, M AND MXR
4139 --y
; /* Parameter adjustments */
4142 mpchk(&c__4
, &c__10
);
4144 /* MPROOT NEEDS 4T+10 WORDS, BUT CAN OVERLAP SLIGHTLY. */
4147 if (x
[1] < 0) goto L10
;
4148 else if (x
[1] == 0) goto L30
;
4153 FPRINTF(stderr
, "*** X NEGATIVE IN CALL TO SUBROUTINE MPSQRT ***\n");
4163 mproot(&x
[1], &c_n2
, &MP
.r
[i2
- 1]);
4165 mpmul(&x
[1], &MP
.r
[i2
- 1], &y
[1]);
4167 mpext(&i
, &iy3
, &y
[1]);
4172 mpstr(int *x
, int *y
)
4176 static int i
, j
, t2
;
4178 /* SETS Y = X FOR MP X AND Y.
4179 * SEE IF X AND Y HAVE THE SAME ADDRESS (THEY OFTEN DO)
4182 --y
; /* Parameter adjustments */
4187 if (j
== x
[1]) goto L10
;
4189 /* HERE X(1) AND Y(1) MUST HAVE THE SAME ADDRESS */
4194 /* HERE X(1) AND Y(1) HAVE DIFFERENT ADDRESSES */
4199 /* NO NEED TO MOVE X(2), ... IF X(1) = 0 */
4205 for (i
= 2; i
<= i__1
; ++i
) y
[i
] = x
[i
];
4210 mpsub(int *x
, int *y
, int *z
)
4214 /* SUBTRACTS Y FROM X, FORMING RESULT IN Z, FOR MP X, Y AND Z.
4215 * FOUR GUARD DIGITS ARE USED, AND THEN R*-ROUNDING
4218 --z
; /* Parameter adjustments */
4223 mpadd2(&x
[1], &y
[1], &z
[1], y1
, &c__0
);
4228 mptanh(int *x
, int *y
)
4234 /* RETURNS Y = TANH(X) FOR MP NUMBERS X AND Y,
4235 * USING MPEXP OR MPEXP1, SPACE = 5T+12
4238 --y
; /* Parameter adjustments */
4241 if (x
[1] != 0) goto L10
;
4248 /* CHECK LEGALITY OF B, T, M AND MXR */
4251 mpchk(&c__5
, &c__12
);
4252 i2
= (MP
.t
<< 2) + 11;
4254 /* SAVE SIGN AND WORK WITH ABS(X) */
4257 mpabs(&x
[1], &MP
.r
[i2
- 1]);
4259 /* SEE IF ABS(X) SO LARGE THAT RESULT IS +-1 */
4261 r__1
= (float) MP
.t
* (float).5 * log((float) MP
.b
);
4262 mpcrm(&r__1
, &y
[1]);
4263 if (mpcomp(&MP
.r
[i2
- 1], &y
[1]) <= 0) goto L20
;
4265 /* HERE ABS(X) IS VERY LARGE */
4270 /* HERE ABS(X) NOT SO LARGE */
4273 mpmuli(&MP
.r
[i2
- 1], &c__2
, &MP
.r
[i2
- 1]);
4274 if (MP
.r
[i2
] <= 0) goto L30
;
4276 /* HERE ABS(X) .GE. 1/2 SO USE MPEXP */
4278 mpexp(&MP
.r
[i2
- 1], &MP
.r
[i2
- 1]);
4279 mpaddi(&MP
.r
[i2
- 1], &c_n1
, &y
[1]);
4280 mpaddi(&MP
.r
[i2
- 1], &c__1
, &MP
.r
[i2
- 1]);
4281 mpdiv(&y
[1], &MP
.r
[i2
- 1], &y
[1]);
4284 /* HERE ABS(X) .LT. 1/2, SO USE MPEXP1 TO AVOID CANCELLATION */
4287 mpexp1(&MP
.r
[i2
- 1], &MP
.r
[i2
- 1]);
4288 mpaddi(&MP
.r
[i2
- 1], &c__2
, &y
[1]);
4289 mpdiv(&MP
.r
[i2
- 1], &y
[1], &y
[1]);
4302 /* CALLED ON MULTIPLE-PRECISION UNDERFLOW, IE WHEN THE
4303 * EXPONENT OF MP NUMBER X WOULD BE LESS THAN -M.
4304 * SINCE M MAY HAVE BEEN OVERWRITTEN, CHECK B, T, M ETC.
4307 --x
; /* Parameter adjustments */
4309 mpchk(&c__1
, &c__4
);
4311 /* THE UNDERFLOWING NUMBER IS SET TO ZERO
4312 * AN ALTERNATIVE WOULD BE TO CALL MPMINR (X) AND RETURN,
4313 * POSSIBLY UPDATING A COUNTER AND TERMINATING EXECUTION
4314 * AFTER A PRESET NUMBER OF UNDERFLOWS. ACTION COULD EASILY
4315 * BE DETERMINED BY A FLAG IN LABELLED COMMON.
4323 mppow_di(double *ap
, int *bp
)
4334 if (x
== 0) return(pow
);
4339 if (n
& 01) pow
*= x
;
4340 if (n
>>= 1) x
*= x
;
4350 pow_ii(int *ap
, int *bp
)
4360 if (n
& 01) pow
*= x
;
4361 if (n
>>= 1) x
*= x
;
4371 mppow_ri(float *ap
, int *bp
)
4382 if (x
== 0) return(pow
);
4387 if (n
& 01) pow
*= x
;
4388 if (n
>>= 1) x
*= x
;