4 * Copyright (c) 1987-2007 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 #include "functions.h" /* FIXME: Only for show_error() */
47 #define C_abs(x) ((x) >= 0 ? (x) : -(x))
48 #define dabs(x) (double) C_abs(x)
49 #define min(a, b) ((a) <= (b) ? (a) : (b))
50 #define max(a, b) ((a) >= (b) ? (a) : (b))
53 int b
, t
, m
, mxr
, r
[MP_SIZE
];
56 /* Table of constant values */
64 static int c__12
= 12;
66 static int c__10
= 10;
67 static int c__32
= 32;
70 static int c__14
= 14;
72 static int c__239
= 239;
74 static int c__16
= 16;
76 static double mppow_di(double *, int *);
77 static double mppow_ri(float *, int *);
79 static int mpcmpi(int *, int *);
80 static int mpcmpr(int *, float *);
81 static int mpcomp(int *, int *);
82 static int pow_ii(int *, int *);
84 static void mpadd2(int *, int *, int *, int *, int *);
85 static void mpadd3(int *, int *, int *, int *, int *);
86 static void mpaddq(int *, int *, int *, int *);
87 static void mpart1(int *, int *);
88 static void mpchk(int *, int *);
89 static void mpcmr(int *, float *);
90 static void mpcqm(int *, int *, int *);
91 static void mpcrm(float *, int *);
92 static void mpexp1(int *, int *);
93 static void mpext(int *, int *, int *);
94 static void mpgcd(int *, int *);
95 static void mplns(int *, int *);
96 static void mpmaxr(int *);
97 static void mpmlp(int *, int *, int *, int *);
98 static void mpmul2(int *, int *, int *, int *);
99 static void mpmulq(int *, int *, int *, int *);
100 static void mpnzr(int *, int *, int *, int *);
101 static void mpovfl(int *);
102 static void mprec(int *, int *);
103 static void mproot(int *, int *, int *);
104 static void mpsin1(int *, int *, int *);
105 static void mpunfl(int *);
109 mpabs(int *x
, int *y
)
112 /* SETS Y = ABS(X) FOR MP NUMBERS X AND Y */
114 --y
; /* Parameter adjustments */
123 mpadd(int *x
, int *y
, int *z
)
126 /* ADDS X AND Y, FORMING RESULT IN Z, WHERE X, Y AND Z ARE MP
127 * NUMBERS. FOUR GUARD DIGITS ARE USED, AND THEN R*-ROUNDING.
130 --z
; /* Parameter adjustments */
134 mpadd2(&x
[1], &y
[1], &z
[1], &y
[1], &c__0
);
139 mpadd2(int *x
, int *y
, int *z
, int *y1
, int *trunc
)
144 static int ed
, re
, rs
, med
;
146 /* CALLED BY MPADD, MPSUB ETC.
147 * X, Y AND Z ARE MP NUMBERS, Y1 AND TRUNC ARE INTEGERS.
148 * TO FORCE CALL BY REFERENCE RATHER THAN VALUE/RESULT, Y1 IS
149 * DECLARED AS AN ARRAY, BUT ONLY Y1(1) IS EVER USED.
150 * SETS Z = X + Y1(1)*ABS(Y), WHERE Y1(1) = +- Y(1).
151 * IF TRUNC.EQ.0 R*-ROUNDING IS USED, OTHERWISE TRUNCATION.
152 * R*-ROUNDING IS DEFINED IN KUKI AND CODI, COMM. ACM
153 * 16(1973), 223. (SEE ALSO BRENT, IEEE TC-22(1973), 601.)
154 * CHECK FOR X OR Y ZERO
157 --y1
; /* Parameter adjustments */
162 if (x
[1] != 0) goto L20
;
164 /* X = 0 OR NEGLIGIBLE, SO RESULT = +-Y */
172 if (y1
[1] != 0) goto L40
;
174 /* Y = 0 OR NEGLIGIBLE, SO RESULT = X */
184 if (C_abs(s
) <= 1) goto L60
;
188 FPRINTF(stderr
, "*** SIGN NOT 0, +1 OR -1 IN MPADD2 CALL.\nPOSSIBLE OVERWRITING PROBLEM ***\n");
195 /* COMPARE EXPONENTS */
200 if (ed
< 0) goto L90
;
201 else if (ed
== 0) goto L70
;
204 /* EXPONENTS EQUAL SO COMPARE SIGNS, THEN FRACTIONS IF NEC. */
207 if (s
> 0) goto L100
;
210 for (j
= 1; j
<= i__1
; ++j
) {
211 if ((i__2
= x
[j
+ 2] - y
[j
+ 2]) < 0) goto L100
;
212 else if (i__2
== 0) continue;
221 /* HERE EXPONENT(Y) .GE. EXPONENT(X) */
224 if (med
> MP
.t
) goto L10
;
229 mpadd3(&x
[1], &y
[1], &s
, &med
, &re
);
231 /* NORMALIZE, ROUND OR TRUNCATE, AND RETURN */
234 mpnzr(&rs
, &re
, &z
[1], trunc
);
237 /* ABS(X) .GT. ABS(Y) */
240 if (med
> MP
.t
) goto L30
;
245 mpadd3(&y
[1], &x
[1], &s
, &med
, &re
);
251 mpadd3(int *x
, int *y
, int *s
, int *med
, int *re
)
255 static int c
, i
, j
, i2
, i2p
, ted
;
257 /* CALLED BY MPADD2, DOES INNER LOOPS OF ADDITION */
259 --y
; /* Parameter adjustments */
267 /* CLEAR GUARD DIGITS TO RIGHT OF X DIGITS */
270 if (i
<= ted
) goto L20
;
277 if (*s
< 0) goto L130
;
279 /* HERE DO ADDITION, EXPONENT(Y) .GE. EXPONENT(X) */
281 if (i
<= MP
.t
) goto L40
;
285 MP
.r
[i
- 1] = x
[j
+ 2];
287 if (i
> MP
.t
) goto L30
;
290 if (i
<= *med
) goto L60
;
293 c
= y
[i
+ 2] + x
[j
+ 2] + c
;
294 if (c
< MP
.b
) goto L50
;
296 /* CARRY GENERATED HERE */
298 MP
.r
[i
- 1] = c
- MP
.b
;
303 /* NO CARRY GENERATED HERE */
312 if (i
<= 0) goto L90
;
315 if (c
< MP
.b
) goto L70
;
326 /* NO CARRY POSSIBLE HERE */
331 MP
.r
[i
- 1] = y
[i
+ 2];
338 /* MUST SHIFT RIGHT HERE AS CARRY OFF END */
342 for (j
= 2; j
<= i__1
; ++j
) {
344 MP
.r
[i
] = MP
.r
[i
- 1];
350 /* HERE DO SUBTRACTION, ABS(Y) .GT. ABS(X) */
354 MP
.r
[i
- 1] = c
- x
[j
+ 2];
356 if (MP
.r
[i
- 1] >= 0) goto L120
;
358 /* BORROW GENERATED HERE */
367 if (i
> MP
.t
) goto L110
;
370 if (i
<= *med
) goto L160
;
373 c
= y
[i
+ 2] + c
- x
[j
+ 2];
374 if (c
>= 0) goto L150
;
376 /* BORROW GENERATED HERE */
378 MP
.r
[i
- 1] = c
+ MP
.b
;
383 /* NO BORROW GENERATED HERE */
395 if (c
>= 0) goto L70
;
397 MP
.r
[i
- 1] = c
+ MP
.b
;
405 mpaddi(int *x
, int *iy
, int *z
)
408 /* ADDS MULTIPLE-PRECISION X TO INTEGER IY
409 * GIVING MULTIPLE-PRECISION Z.
410 * DIMENSION OF R IN CALLING PROGRAM MUST BE
411 * AT LEAST 2T+6 (BUT Z(1) MAY BE R(T+5)).
412 * DIMENSION R(6) BECAUSE RALPH COMPILER ON UNIVAC 1100 COMPUTERS
413 * OBJECTS TO DIMENSION R(1).
414 * CHECK LEGALITY OF B, T, M AND MXR
417 --z
; /* Parameter adjustments */
421 mpcim(iy
, &MP
.r
[MP
.t
+ 4]);
422 mpadd(&x
[1], &MP
.r
[MP
.t
+ 4], &z
[1]);
427 mpaddq(int *x
, int *i
, int *j
, int *y
)
430 /* ADDS THE RATIONAL NUMBER I/J TO MP NUMBER X, MP RESULT IN Y
431 * DIMENSION OF R MUST BE AT LEAST 2T+6
432 * CHECK LEGALITY OF B, T, M AND MXR
435 --y
; /* Parameter adjustments */
439 mpcqm(i
, j
, &MP
.r
[MP
.t
+ 4]);
440 mpadd(&x
[1], &MP
.r
[MP
.t
+ 4], &y
[1]);
445 mpart1(int *n
, int *y
)
449 static int i
, b2
, i2
, id
, ts
;
451 /* COMPUTES MP Y = ARCTAN(1/N), ASSUMING INTEGER N .GT. 1.
452 * USES SERIES ARCTAN(X) = X - X**3/3 + X**5/5 - ...
453 * DIMENSION OF R IN CALLING PROGRAM MUST BE
455 * CHECK LEGALITY OF B, T, M AND MXR
458 --y
; /* Parameter adjustments */
461 if (*n
> 1) goto L20
;
464 FPRINTF(stderr
, "*** N .LE. 1 IN CALL TO MPART1 ***\n");
475 /* SET SUM TO X = 1/N */
477 mpcqm(&c__1
, n
, &y
[1]);
479 /* SET ADDITIVE TERM TO X */
481 mpstr(&y
[1], &MP
.r
[i2
- 1]);
485 /* ASSUME AT LEAST 16-BIT WORD. */
488 if (*n
< b2
) id
= b2
* 7 * b2
/ (*n
* *n
);
490 /* MAIN LOOP. FIRST REDUCE T IF POSSIBLE */
493 MP
.t
= ts
+ 2 + MP
.r
[i2
] - y
[2];
494 if (MP
.t
< 2) goto L60
;
498 /* IF (I+2)*N**2 IS NOT REPRESENTABLE AS AN INTEGER THE DIVISION
499 * FOLLOWING HAS TO BE PERFORMED IN SEVERAL STEPS.
502 if (i
>= id
) goto L40
;
505 i__2
= (i
+ 2) * *n
* *n
;
506 mpmulq(&MP
.r
[i2
- 1], &i__1
, &i__2
, &MP
.r
[i2
- 1]);
512 mpmulq(&MP
.r
[i2
- 1], &i__1
, &i__2
, &MP
.r
[i2
- 1]);
513 mpdivi(&MP
.r
[i2
- 1], n
, &MP
.r
[i2
- 1]);
514 mpdivi(&MP
.r
[i2
- 1], n
, &MP
.r
[i2
- 1]);
523 /* ADD TO SUM, USING MPADD2 (FASTER THAN MPADD) */
525 mpadd2(&MP
.r
[i2
- 1], &y
[1], &y
[1], &y
[1], &c__0
);
526 if (MP
.r
[i2
- 1] != 0) goto L30
;
534 mpasin(int *x
, int *y
)
540 /* RETURNS Y = ARCSIN(X), ASSUMING ABS(X) .LE. 1,
541 * FOR MP NUMBERS X AND Y.
542 * Y IS IN THE RANGE -PI/2 TO +PI/2.
543 * METHOD IS TO USE MPATAN, SO TIME IS O(M(T)T).
544 * DIMENSION OF R MUST BE AT LEAST 5T+12
545 * CHECK LEGALITY OF B, T, M AND MXR
548 --y
; /* Parameter adjustments */
551 mpchk(&c__5
, &c__12
);
552 i3
= (MP
.t
<< 2) + 11;
553 if (x
[1] == 0) goto L30
;
555 if (x
[2] <= 0) goto L40
;
557 /* HERE ABS(X) .GE. 1. SEE IF X = +-1 */
559 mpcim(&x
[1], &MP
.r
[i3
- 1]);
560 if (mpcomp(&x
[1], &MP
.r
[i3
- 1]) != 0) goto L10
;
562 /* X = +-1 SO RETURN +-PI/2 */
565 i__1
= MP
.r
[i3
- 1] << 1;
566 mpdivi(&y
[1], &i__1
, &y
[1]);
571 FPRINTF(stderr
, "*** ABS(X) .GT. 1 IN CALL TO MPASIN ***\n");
580 /* HERE ABS(X) .LT. 1 SO USE ARCTAN(X/SQRT(1 - X**2)) */
583 i2
= i3
- (MP
.t
+ 2);
584 mpcim(&c__1
, &MP
.r
[i2
- 1]);
585 mpstr(&MP
.r
[i2
- 1], &MP
.r
[i3
- 1]);
586 mpsub(&MP
.r
[i2
- 1], &x
[1], &MP
.r
[i2
- 1]);
587 mpadd(&MP
.r
[i3
- 1], &x
[1], &MP
.r
[i3
- 1]);
588 mpmul(&MP
.r
[i2
- 1], &MP
.r
[i3
- 1], &MP
.r
[i3
- 1]);
589 mproot(&MP
.r
[i3
- 1], &c_n2
, &MP
.r
[i3
- 1]);
590 mpmul(&x
[1], &MP
.r
[i3
- 1], &y
[1]);
591 mpatan(&y
[1], &y
[1]);
596 mpatan(int *x
, int *y
)
601 static int i
, q
, i2
, i3
, ie
, ts
;
604 /* RETURNS Y = ARCTAN(X) FOR MP X AND Y, USING AN O(T.M(T)) METHOD
605 * WHICH COULD EASILY BE MODIFIED TO AN O(SQRT(T)M(T))
606 * METHOD (AS IN MPEXP1). Y IS IN THE RANGE -PI/2 TO +PI/2.
607 * FOR AN ASYMPTOTICALLY FASTER METHOD, SEE - FAST MULTIPLE-
608 * PRECISION EVALUATION OF ELEMENTARY FUNCTIONS
609 * (BY R. P. BRENT), J. ACM 23 (1976), 242-251,
610 * AND THE COMMENTS IN MPPIGL.
611 * DIMENSION OF R IN CALLING PROGRAM MUST BE AT LEAST 5T+12
612 * CHECK LEGALITY OF B, T, M AND MXR
615 --y
; /* Parameter adjustments */
618 mpchk(&c__5
, &c__12
);
628 mpstr(&x
[1], &MP
.r
[i3
- 1]);
630 if (ie
<= 2) mpcmr(&x
[1], &rx
);
634 /* REDUCE ARGUMENT IF NECESSARY BEFORE USING SERIES */
637 if (MP
.r
[i3
] < 0) goto L30
;
639 if (MP
.r
[i3
] == 0 && (MP
.r
[i3
+ 1] + 1) << 1 <= MP
.b
)
643 mpmul(&MP
.r
[i3
- 1], &MP
.r
[i3
- 1], &y
[1]);
644 mpaddi(&y
[1], &c__1
, &y
[1]);
645 mpsqrt(&y
[1], &y
[1]);
646 mpaddi(&y
[1], &c__1
, &y
[1]);
647 mpdiv(&MP
.r
[i3
- 1], &y
[1], &MP
.r
[i3
- 1]);
650 /* USE POWER SERIES NOW ARGUMENT IN (-0.5, 0.5) */
653 mpstr(&MP
.r
[i3
- 1], &y
[1]);
654 mpmul(&MP
.r
[i3
- 1], &MP
.r
[i3
- 1], &MP
.r
[i2
- 1]);
658 /* SERIES LOOP. REDUCE T IF POSSIBLE. */
661 MP
.t
= ts
+ 2 + MP
.r
[i3
];
662 if (MP
.t
<= 2) goto L50
;
665 mpmul(&MP
.r
[i3
- 1], &MP
.r
[i2
- 1], &MP
.r
[i3
- 1]);
668 mpmulq(&MP
.r
[i3
- 1], &i__1
, &i__2
, &MP
.r
[i3
- 1]);
671 mpadd(&y
[1], &MP
.r
[i3
- 1], &y
[1]);
672 if (MP
.r
[i3
- 1] != 0) goto L40
;
674 /* RESTORE T, CORRECT FOR ARGUMENT REDUCTION, AND EXIT */
678 mpmuli(&y
[1], &q
, &y
[1]);
680 /* CHECK THAT RELATIVE ERROR LESS THAN 0.01 UNLESS EXPONENT
681 * OF X IS LARGE (WHEN ATAN MIGHT NOT WORK)
687 if ((r__1
= ry
- atan(rx
), dabs(r__1
)) < dabs(ry
) * (float).01)
690 /* THE FOLLOWING MESSAGE MAY INDICATE THAT B**(T-1) IS TOO SMALL. */
693 FPRINTF(stderr
, "*** ERROR OCCURRED IN MPATAN, RESULT INCORRECT ***\n");
701 mpcdm(double *dx
, int *z
)
705 static int i
, k
, i2
, ib
, ie
, re
, tp
, rs
;
706 static double db
, dj
;
708 /* CONVERTS DOUBLE-PRECISION NUMBER DX TO MULTIPLE-PRECISION Z.
709 * SOME NUMBERS WILL NOT CONVERT EXACTLY ON MACHINES
710 * WITH BASE OTHER THAN TWO, FOUR OR SIXTEEN.
711 * THIS ROUTINE IS NOT CALLED BY ANY OTHER ROUTINE IN MP,
712 * SO MAY BE OMITTED IF DOUBLE-PRECISION IS NOT AVAILABLE.
713 * CHECK LEGALITY OF B, T, M AND MXR
716 --z
; /* Parameter adjustments */
723 if (*dx
< 0.) goto L20
;
724 else if (*dx
== 0) goto L10
;
727 /* IF DX = 0D0 RETURN 0 */
750 if (dj
< 1.) goto L60
;
752 /* INCREASE IE AND DIVIDE DJ BY 16. */
759 if (dj
>= .0625) goto L70
;
765 /* NOW DJ IS DY DIVIDED BY SUITABLE POWER OF 16
772 /* DB = DFLOAT(B) IS NOT ANSI STANDARD SO USE FLOAT AND DBLE */
774 db
= (double) ((float) MP
.b
);
776 /* CONVERSION LOOP (ASSUME DOUBLE-PRECISION OPS. EXACT) */
779 for (i
= 1; i
<= i__1
; ++i
) {
781 MP
.r
[i
- 1] = (int) dj
;
782 dj
-= (double) ((float) MP
.r
[i
- 1]);
785 /* NORMALIZE RESULT */
787 mpnzr(&rs
, &re
, &z
[1], &c__0
);
791 i__1
= MP
.b
* 7 * MP
.b
;
792 ib
= max(i__1
, 32767) / 16;
795 /* NOW MULTIPLY BY 16**IE */
797 if (ie
< 0) goto L90
;
798 else if (ie
== 0) goto L130
;
804 for (i
= 1; i
<= i__1
; ++i
) {
806 if (tp
<= ib
&& tp
!= MP
.b
&& i
< k
) continue;
807 mpdivi(&z
[1], &tp
, &z
[1]);
814 for (i
= 1; i
<= i__1
; ++i
) {
816 if (tp
<= ib
&& tp
!= MP
.b
&& i
< ie
) continue;
817 mpmuli(&z
[1], &tp
, &z
[1]);
827 mpchk(int *i
, int *j
)
831 /* CHECKS LEGALITY OF B, T, M AND MXR.
832 * THE CONDITION ON MXR (THE DIMENSION OF R IN COMMON) IS THAT
836 /* CHECK LEGALITY OF B, T AND M */
838 if (MP
.b
> 1) goto L40
;
841 FPRINTF(stderr
, "*** B = %d ILLEGAL IN CALL TO MPCHK.\nPERHAPS NOT SET BEFORE CALL TO AN MP ROUTINE ***\n", MP
.b
);
846 if (MP
.t
> 1) goto L60
;
849 FPRINTF(stderr
, "*** T = %d ILLEGAL IN CALL TO MPCHK.\nPERHAPS NOT SET BEFORE CALL TO AN MP ROUTINE ***\n", MP
.t
);
854 if (MP
.m
> MP
.t
) goto L80
;
857 FPRINTF(stderr
, "*** M .LE. T IN CALL TO MPCHK.\nPERHAPS NOT SET BEFORE CALL TO AN MP ROUTINE ***\n");
861 /* 8*B*B-1 SHOULD BE REPRESENTABLE, IF NOT WILL OVERFLOW
862 * AND MAY BECOME NEGATIVE, SO CHECK FOR THIS
866 ib
= (MP
.b
<< 2) * MP
.b
- 1;
867 if (ib
> 0 && (ib
<< 1) + 1 > 0) goto L100
;
870 FPRINTF(stderr
, "*** B TOO LARGE IN CALL TO MPCHK ***\n");
875 /* CHECK THAT SPACE IN COMMON IS SUFFICIENT */
879 if (MP
.mxr
>= mx
) return;
881 /* HERE COMMON IS TOO SMALL, SO GIVE ERROR MESSAGE. */
885 "*** MXR TOO SMALL OR NOT SET TO DIM(R) BEFORE CALL TO AN MP ROUTINE ***\n");
887 "*** MXR SHOULD BE AT LEAST %d*T + %d = %d ***\n*** ACTUALLY MXR = %d, AND T = %d ***\n",
888 *i
, *j
, mx
, MP
.mxr
, MP
.t
);
896 mpcim(int *ix
, int *z
)
902 /* CONVERTS INTEGER IX TO MULTIPLE-PRECISION Z.
903 * CHECK LEGALITY OF B, T, M AND MXR
906 --z
; /* Parameter adjustments */
911 else if (n
== 0) goto L10
;
926 /* SET EXPONENT TO T */
934 for (i
= 2; i
<= i__1
; ++i
) z
[i
+ 1] = 0;
940 /* NORMALIZE BY CALLING MPMUL2 */
942 mpmul2(&z
[1], &c__1
, &z
[1], &c__1
);
947 mpcmd(int *x
, double *dz
)
953 static double db
, dz2
;
955 /* CONVERTS MULTIPLE-PRECISION X TO DOUBLE-PRECISION DZ.
956 * ASSUMES X IS IN ALLOWABLE RANGE FOR DOUBLE-PRECISION
957 * NUMBERS. THERE IS SOME LOSS OF ACCURACY IF THE
959 * CHECK LEGALITY OF B, T, M AND MXR
962 --x
; /* Parameter adjustments */
966 if (x
[1] == 0) return;
968 /* DB = DFLOAT(B) IS NOT ANSI STANDARD, SO USE FLOAT AND DBLE */
970 db
= (double) ((float) MP
.b
);
972 for (i
= 1; i
<= i__1
; ++i
) {
973 *dz
= db
* *dz
+ (double) ((float) x
[i
+ 2]);
976 /* CHECK IF FULL DOUBLE-PRECISION ACCURACY ATTAINED */
980 /* TEST BELOW NOT ALWAYS EQUIVALENT TO - IF (DZ2.LE.DZ) GO TO 20,
981 * FOR EXAMPLE ON CYBER 76.
983 if (dz2
- *dz
<= 0.) goto L20
;
986 /* NOW ALLOW FOR EXPONENT */
990 *dz
*= mppow_di(&db
, &i__1
);
992 /* CHECK REASONABLENESS OF RESULT. */
994 if (*dz
<= 0.) goto L30
;
996 /* LHS SHOULD BE .LE. 0.5 BUT ALLOW FOR SOME ERROR IN DLOG */
998 if ((d__1
= (double) ((float) x
[2]) - (log(*dz
) / log((double)
999 ((float) MP
.b
)) + .5), C_abs(d__1
)) > .6) {
1003 if (x
[1] < 0) *dz
= -(*dz
);
1006 /* FOLLOWING MESSAGE INDICATES THAT X IS TOO LARGE OR SMALL -
1007 * TRY USING MPCMDE INSTEAD.
1012 FPRINTF(stderr
, "*** FLOATING-POINT OVER/UNDER-FLOW IN MPCMD ***\n");
1020 mpcmf(int *x
, int *y
)
1025 static int x2
, il
, ip
, xs
;
1027 /* FOR MP X AND Y, RETURNS FRACTIONAL PART OF X IN Y,
1028 * I.E., Y = X - INTEGER PART OF X (TRUNCATED TOWARDS 0).
1031 --y
; /* Parameter adjustments */
1034 if (x
[1] != 0) goto L20
;
1036 /* RETURN 0 IF X = 0 */
1045 /* RETURN 0 IF EXPONENT SO LARGE THAT NO FRACTIONAL PART */
1047 if (x2
>= MP
.t
) goto L10
;
1049 /* IF EXPONENT NOT POSITIVE CAN RETURN X */
1051 if (x2
> 0) goto L30
;
1053 mpstr(&x
[1], &y
[1]);
1056 /* CLEAR ACCUMULATOR */
1060 for (i
= 1; i
<= i__1
; ++i
) MP
.r
[i
- 1] = 0;
1064 /* MOVE FRACTIONAL PART OF X TO ACCUMULATOR */
1067 for (i
= il
; i
<= i__1
; ++i
) MP
.r
[i
- 1] = x
[i
+ 2];
1069 for (i
= 1; i
<= 4; ++i
) {
1075 /* NORMALIZE RESULT AND RETURN */
1077 mpnzr(&xs
, &x2
, &y
[1], &c__1
);
1082 mpcmi(int *x
, int *iz
)
1086 static int i
, j
, k
, j1
, x2
, kx
, xs
, izs
;
1088 /* CONVERTS MULTIPLE-PRECISION X TO INTEGER IZ,
1089 * ASSUMING THAT X NOT TOO LARGE (ELSE USE MPCMIM).
1090 * X IS TRUNCATED TOWARDS ZERO.
1091 * IF INT(X)IS TOO LARGE TO BE REPRESENTED AS A SINGLE-
1092 * PRECISION INTEGER, IZ IS RETURNED AS ZERO. THE USER
1093 * MAY CHECK FOR THIS POSSIBILITY BY TESTING IF
1094 * ((X(1).NE.0).AND.(X(2).GT.0).AND.(IZ.EQ.0)) IS TRUE ON
1095 * RETURN FROM MPCMI.
1098 --x
; /* Parameter adjustments */
1102 if (xs
== 0) return;
1104 if (x
[2] <= 0) return;
1108 for (i
= 1; i
<= i__1
; ++i
) {
1111 if (i
<= MP
.t
) *iz
+= x
[i
+ 2];
1113 /* CHECK FOR SIGNS OF INTEGER OVERFLOW */
1115 if (*iz
<= 0 || *iz
<= izs
) goto L30
;
1118 /* CHECK THAT RESULT IS CORRECT (AN UNDETECTED OVERFLOW MAY
1124 for (i
= 1; i
<= i__1
; ++i
) {
1128 if (k
<= MP
.t
) kx
= x
[k
+ 2];
1129 if (kx
!= j
- MP
.b
* j1
) goto L30
;
1132 if (j
!= 0) goto L30
;
1134 /* RESULT CORRECT SO RESTORE SIGN AND RETURN */
1139 /* HERE OVERFLOW OCCURRED (OR X WAS UNNORMALIZED), SO
1149 mpcmim(int *x
, int *y
)
1151 int tmp
[MP_SIZE
]; /* Temporary store for the number. */
1152 int accuracy
; /* Temporary story for the accuracy. */
1153 int pointed
; /* Whether a decimal point has been given. */
1154 int toclear
; /* Indicates if display should be cleared. */
1155 char disp
[MAXLINE
]; /* Setup a string to store what would be displayed */
1156 enum num_type dtype
; /* Setup a temp display type variable */
1160 static int i
, il
, ll
;
1162 /* RETURNS Y = INTEGER PART OF X (TRUNCATED TOWARDS 0), FOR MP X AND Y.
1163 * USE IF Y TOO LARGE TO BE REPRESENTABLE AS A SINGLE-PRECISION INTEGER.
1164 * (ELSE COULD USE MPCMI).
1165 * CHECK LEGALITY OF B, T, M AND MXR
1168 --y
; /* Parameter adjustments */
1171 mpchk(&c__1
, &c__4
);
1172 mpstr(&x
[1], &y
[1]);
1180 /* IF EXPONENT LARGE ENOUGH RETURN Y = X */
1186 /* IF EXPONENT SMALL ENOUGH RETURN ZERO */
1195 /* SET FRACTION TO ZERO */
1199 for (i
= il
; i
<= i__1
; ++i
) {
1203 /* Fix for Sun bugtraq bug #4006391 - problem with Int function for numbers
1204 * like 4800 when internal representation in something like 4799.999999999.
1207 accuracy
= v
->accuracy
;
1209 pointed
= v
->pointed
;
1210 toclear
= v
->toclear
;
1213 v
->accuracy
= MAX_DIGITS
;
1215 STRCPY(disp
, make_number(tmp
, v
->base
, FALSE
));
1217 if (disp
[0] == '1') {
1221 v
->accuracy
= accuracy
;
1223 v
->pointed
= pointed
;
1224 v
->toclear
= toclear
;
1229 mpcmpi(int *x
, int *i
)
1233 /* COMPARES MP NUMBER X WITH INTEGER I, RETURNING
1237 * DIMENSION OF R IN COMMON AT LEAST 2T+6
1238 * CHECK LEGALITY OF B, T, M AND MXR
1241 --x
; /* Parameter adjustments */
1243 mpchk(&c__2
, &c__6
);
1245 /* CONVERT I TO MULTIPLE-PRECISION AND COMPARE */
1247 mpcim(i
, &MP
.r
[MP
.t
+ 4]);
1248 ret_val
= mpcomp(&x
[1], &MP
.r
[MP
.t
+ 4]);
1254 mpcmpr(int *x
, float *ri
)
1258 /* COMPARES MP NUMBER X WITH REAL NUMBER RI, RETURNING
1262 * DIMENSION OF R IN COMMON AT LEAST 2T+6
1263 * CHECK LEGALITY OF B, T, M AND MXR
1266 --x
; /* Parameter adjustments */
1268 mpchk(&c__2
, &c__6
);
1270 /* CONVERT RI TO MULTIPLE-PRECISION AND COMPARE */
1272 mpcrm(ri
, &MP
.r
[MP
.t
+ 4]);
1273 ret_val
= mpcomp(&x
[1], &MP
.r
[MP
.t
+ 4]);
1279 mpcmr(int *x
, float *rz
)
1285 static float rb
, rz2
;
1287 /* CONVERTS MULTIPLE-PRECISION X TO SINGLE-PRECISION RZ.
1288 * ASSUMES X IN ALLOWABLE RANGE. THERE IS SOME LOSS OF
1289 * ACCURACY IF THE EXPONENT IS LARGE.
1290 * CHECK LEGALITY OF B, T, M AND MXR
1293 --x
; /* Parameter adjustments */
1295 mpchk(&c__1
, &c__4
);
1297 if (x
[1] == 0) return;
1301 for (i
= 1; i
<= i__1
; ++i
) {
1302 *rz
= rb
* *rz
+ (float) x
[i
+ 2];
1305 /* CHECK IF FULL SINGLE-PRECISION ACCURACY ATTAINED */
1307 rz2
= *rz
+ (float) 1.0;
1308 if (rz2
<= *rz
) goto L20
;
1311 /* NOW ALLOW FOR EXPONENT */
1315 *rz
*= mppow_ri(&rb
, &i__1
);
1317 /* CHECK REASONABLENESS OF RESULT */
1319 if (*rz
<= (float)0.) goto L30
;
1321 /* LHS SHOULD BE .LE. 0.5, BUT ALLOW FOR SOME ERROR IN ALOG */
1323 if ((r__1
= (float) x
[2] - (log(*rz
) / log((float) MP
.b
) + (float).5),
1324 dabs(r__1
)) > (float).6) {
1328 if (x
[1] < 0) *rz
= -(double)(*rz
);
1331 /* FOLLOWING MESSAGE INDICATES THAT X IS TOO LARGE OR SMALL -
1332 * TRY USING MPCMRE INSTEAD.
1337 FPRINTF(stderr
, "*** FLOATING-POINT OVER/UNDER-FLOW IN MPCMR ***\n");
1345 mpcomp(int *x
, int *y
)
1347 int ret_val
, i__1
, i__2
;
1351 /* COMPARES THE MULTIPLE-PRECISION NUMBERS X AND Y,
1352 * RETURNING +1 IF X .GT. Y,
1354 * AND 0 IF X .EQ. Y.
1357 --y
; /* Parameter adjustments */
1360 if ((i__1
= x
[1] - y
[1]) < 0) goto L10
;
1361 else if (i__1
== 0) goto L30
;
1376 /* SIGN(X) = SIGN(Y), SEE IF ZERO */
1379 if (x
[1] != 0) goto L40
;
1386 /* HAVE TO COMPARE EXPONENTS AND FRACTIONS */
1391 for (i
= 2; i
<= i__1
; ++i
) {
1392 if ((i__2
= x
[i
] - y
[i
]) < 0) goto L60
;
1393 else if (i__2
== 0) continue;
1402 /* ABS(X) .LT. ABS(Y) */
1408 /* ABS(X) .GT. ABS(Y) */
1417 mpcos(int *x
, int *y
)
1421 /* RETURNS Y = COS(X) FOR MP X AND Y, USING MPSIN AND MPSIN1.
1422 * DIMENSION OF R IN COMMON AT LEAST 5T+12.
1425 --y
; /* Parameter adjustments */
1428 if (x
[1] != 0) goto L10
;
1432 mpcim(&c__1
, &y
[1]);
1435 /* CHECK LEGALITY OF B, T, M AND MXR */
1438 mpchk(&c__5
, &c__12
);
1441 /* SEE IF ABS(X) .LE. 1 */
1443 mpabs(&x
[1], &y
[1]);
1444 if (mpcmpi(&y
[1], &c__1
) <= 0) goto L20
;
1446 /* HERE ABS(X) .GT. 1 SO USE COS(X) = SIN(PI/2 - ABS(X)),
1447 * COMPUTING PI/2 WITH ONE GUARD DIGIT.
1451 mppi(&MP
.r
[i2
- 1]);
1452 mpdivi(&MP
.r
[i2
- 1], &c__2
, &MP
.r
[i2
- 1]);
1454 mpsub(&MP
.r
[i2
- 1], &y
[1], &y
[1]);
1455 mpsin(&y
[1], &y
[1]);
1458 /* HERE ABS(X) .LE. 1 SO USE POWER SERIES */
1461 mpsin1(&y
[1], &y
[1], &c__0
);
1466 mpcosh(int *x
, int *y
)
1470 /* RETURNS Y = COSH(X) FOR MP NUMBERS X AND Y, X NOT TOO LARGE.
1471 * USES MPEXP, DIMENSION OF R IN COMMON AT LEAST 5T+12
1474 --y
; /* Parameter adjustments */
1477 if (x
[1] != 0) goto L10
;
1481 mpcim(&c__1
, &y
[1]);
1484 /* CHECK LEGALITY OF B, T, M AND MXR */
1487 mpchk(&c__5
, &c__12
);
1488 i2
= (MP
.t
<< 2) + 11;
1489 mpabs(&x
[1], &MP
.r
[i2
- 1]);
1491 /* IF ABS(X) TOO LARGE MPEXP WILL PRINT ERROR MESSAGE
1492 * INCREASE M TO AVOID OVERFLOW WHEN COSH(X) REPRESENTABLE
1496 mpexp(&MP
.r
[i2
- 1], &MP
.r
[i2
- 1]);
1497 mprec(&MP
.r
[i2
- 1], &y
[1]);
1498 mpadd(&MP
.r
[i2
- 1], &y
[1], &y
[1]);
1500 /* RESTORE M. IF RESULT OVERFLOWS OR UNDERFLOWS, MPDIVI WILL
1505 mpdivi(&y
[1], &c__2
, &y
[1]);
1510 mpcqm(int *i
, int *j
, int *q
)
1514 /* CONVERTS THE RATIONAL NUMBER I/J TO MULTIPLE PRECISION Q. */
1516 --q
; /* Parameter adjustments */
1521 if (j1
< 0) goto L30
;
1522 else if (j1
== 0) goto L10
;
1527 FPRINTF(stderr
, "*** J = 0 IN CALL TO MPCQM ***\n");
1540 if (j1
!= 1) mpdivi(&q
[1], &j1
, &q
[1]);
1545 mpcrm(float *rx
, int *z
)
1549 static int i
, k
, i2
, ib
, ie
, re
, tp
, rs
;
1550 static float rb
, rj
;
1552 /* CONVERTS SINGLE-PRECISION NUMBER RX TO MULTIPLE-PRECISION Z.
1553 * SOME NUMBERS WILL NOT CONVERT EXACTLY ON MACHINES
1554 * WITH BASE OTHER THAN TWO, FOUR OR SIXTEEN.
1555 * CHECK LEGALITY OF B, T, M AND MXR
1558 --z
; /* Parameter adjustments */
1560 mpchk(&c__1
, &c__4
);
1565 if (*rx
< (float) 0.0) goto L20
;
1566 else if (*rx
== 0) goto L10
;
1569 /* IF RX = 0E0 RETURN 0 */
1579 rj
= -(double)(*rx
);
1592 if (rj
< (float)1.0) goto L60
;
1594 /* INCREASE IE AND DIVIDE RJ BY 16. */
1597 rj
*= (float) 0.0625;
1601 if (rj
>= (float).0625) goto L70
;
1607 /* NOW RJ IS DY DIVIDED BY SUITABLE POWER OF 16.
1615 /* CONVERSION LOOP (ASSUME SINGLE-PRECISION OPS. EXACT) */
1618 for (i
= 1; i
<= i__1
; ++i
) {
1620 MP
.r
[i
- 1] = (int) rj
;
1621 rj
-= (float) MP
.r
[i
- 1];
1624 /* NORMALIZE RESULT */
1626 mpnzr(&rs
, &re
, &z
[1], &c__0
);
1630 i__1
= MP
.b
* 7 * MP
.b
;
1631 ib
= max(i__1
, 32767) / 16;
1634 /* NOW MULTIPLY BY 16**IE */
1636 if (ie
< 0) goto L90
;
1637 else if (ie
== 0) goto L130
;
1643 for (i
= 1; i
<= i__1
; ++i
) {
1645 if (tp
<= ib
&& tp
!= MP
.b
&& i
< k
) continue;
1646 mpdivi(&z
[1], &tp
, &z
[1]);
1653 for (i
= 1; i
<= i__1
; ++i
) {
1655 if (tp
<= ib
&& tp
!= MP
.b
&& i
< ie
) continue;
1656 mpmuli(&z
[1], &tp
, &z
[1]);
1666 mpdiv(int *x
, int *y
, int *z
)
1668 static int i
, i2
, ie
, iz3
;
1670 /* SETS Z = X/Y, FOR MP X, Y AND Z.
1671 * DIMENSION OF R IN CALLING PROGRAM MUST BE AT LEAST 4T+10
1672 * (BUT Z(1) MAY BE R(3T+9)).
1673 * CHECK LEGALITY OF B, T, M AND MXR
1676 --z
; /* Parameter adjustments */
1680 mpchk(&c__4
, &c__10
);
1682 /* CHECK FOR DIVISION BY ZERO */
1684 if (y
[1] != 0) goto L20
;
1687 FPRINTF(stderr
, "*** ATTEMPTED DIVISION BY ZERO IN CALL TO MPDIV ***\n");
1694 /* SPACE USED BY MPREC IS 4T+10 WORDS, BUT CAN OVERLAP SLIGHTLY. */
1699 /* CHECK FOR X = 0 */
1701 if (x
[1] != 0) goto L30
;
1706 /* INCREASE M TO AVOID OVERFLOW IN MPREC */
1711 /* FORM RECIPROCAL OF Y */
1713 mprec(&y
[1], &MP
.r
[i2
- 1]);
1715 /* SET EXPONENT OF R(I2) TO ZERO TO AVOID OVERFLOW IN MPMUL */
1723 mpmul(&x
[1], &MP
.r
[i2
- 1], &z
[1]);
1725 mpext(&i
, &iz3
, &z
[1]);
1727 /* RESTORE M, CORRECT EXPONENT AND RETURN */
1731 if (z
[2] >= -MP
.m
) goto L40
;
1733 /* UNDERFLOW HERE */
1739 if (z
[2] <= MP
.m
) return;
1744 FPRINTF(stderr
, "*** OVERFLOW OCCURRED IN MPDIV ***\n");
1752 mpdivi(int *x
, int *iy
, int *z
)
1756 static int c
, i
, j
, k
, b2
, c2
, i2
, j1
, j2
, r1
;
1757 static int j11
, kh
, re
, iq
, ir
, rs
, iqj
;
1759 /* DIVIDES MP X BY THE SINGLE-PRECISION INTEGER IY GIVING MP Z.
1760 * THIS IS MUCH FASTER THAN DIVISION BY AN MP NUMBER.
1763 --z
; /* Parameter adjustments */
1768 if (j
< 0) goto L30
;
1769 else if (j
== 0) goto L10
;
1774 FPRINTF(stderr
, "*** ATTEMPTED DIVISION BY ZERO IN CALL TO MPDIVI ***\n");
1786 /* CHECK FOR ZERO DIVIDEND */
1788 if (rs
== 0) goto L120
;
1790 /* CHECK FOR DIVISION BY B */
1792 if (j
!= MP
.b
) goto L50
;
1793 mpstr(&x
[1], &z
[1]);
1794 if (re
<= -MP
.m
) goto L240
;
1799 /* CHECK FOR DIVISION BY 1 OR -1 */
1802 if (j
!= 1) goto L60
;
1803 mpstr(&x
[1], &z
[1]);
1812 /* IF J*B NOT REPRESENTABLE AS AN INTEGER HAVE TO SIMULATE
1813 * LONG DIVISION. ASSUME AT LEAST 16-BIT WORD.
1818 i__1
= MP
.b
<< 3, i__2
= 32767 / MP
.b
;
1819 b2
= max(i__1
,i__2
);
1820 if (j
>= b2
) goto L130
;
1822 /* LOOK FOR FIRST NONZERO DIGIT IN QUOTIENT */
1827 if (i
<= MP
.t
) c
+= x
[i
+ 2];
1829 if (r1
< 0) goto L210
;
1830 else if (r1
== 0) goto L70
;
1833 /* ADJUST EXPONENT AND GET T+4 DIGITS IN QUOTIENT */
1838 c
= MP
.b
* (c
- j
* r1
);
1840 if (i
>= MP
.t
) goto L100
;
1843 for (k
= 2; k
<= i__1
; ++k
) {
1846 MP
.r
[k
- 1] = c
/ j
;
1847 c
= MP
.b
* (c
- j
* MP
.r
[k
- 1]);
1849 if (c
< 0) goto L210
;
1854 for (k
= kh
; k
<= i__1
; ++k
) {
1855 MP
.r
[k
- 1] = c
/ j
;
1856 c
= MP
.b
* (c
- j
* MP
.r
[k
- 1]);
1858 if (c
< 0) goto L210
;
1860 /* NORMALIZE AND ROUND RESULT */
1863 mpnzr(&rs
, &re
, &z
[1], &c__0
);
1866 /* HERE NEED SIMULATED DOUBLE-PRECISION DIVISION */
1874 /* LOOK FOR FIRST NONZERO DIGIT */
1880 if (i
<= MP
.t
) c2
= x
[i
+ 2];
1881 if ((i__1
= c
- j1
) < 0) goto L140
;
1882 else if (i__1
== 0) goto L150
;
1886 if (c2
< j2
) goto L140
;
1888 /* COMPUTE T+4 QUOTIENT DIGITS */
1895 /* MAIN LOOP FOR LARGE ABS(IY) CASE */
1899 if (k
> i2
) goto L120
;
1902 /* GET APPROXIMATE QUOTIENT FIRST */
1907 /* NOW REDUCE SO OVERFLOW DOES NOT OCCUR */
1910 if (iq
< b2
) goto L190
;
1912 /* HERE IQ*B WOULD POSSIBLY OVERFLOW SO INCREASE IR */
1918 iq
= iq
* MP
.b
- ir
* j2
;
1919 if (iq
>= 0) goto L200
;
1921 /* HERE IQ NEGATIVE SO IR WAS TOO LARGE */
1927 if (i
<= MP
.t
) iq
+= x
[i
+ 2];
1930 /* R(K) = QUOTIENT, C = REMAINDER */
1932 MP
.r
[k
- 1] = iqj
+ ir
;
1934 if (c
>= 0) goto L170
;
1936 /* CARRY NEGATIVE SO OVERFLOW MUST HAVE OCCURRED */
1939 mpchk(&c__1
, &c__4
);
1942 FPRINTF(stderr
, "*** INTEGER OVERFLOW IN MPDIVI, B TOO LARGE ***\n");
1950 /* UNDERFLOW HERE */
1958 mpeq(int *x
, int *y
)
1962 /* RETURNS LOGICAL VALUE OF (X .EQ. Y) FOR MP X AND Y. */
1964 --y
; /* Parameter adjustments */
1967 ret_val
= mpcomp(&x
[1], &y
[1]) == 0;
1977 /* THIS ROUTINE IS CALLED WHEN AN ERROR CONDITION IS ENCOUNTERED, AND
1978 * AFTER A MESSAGE HAS BEEN WRITTEN TO STDERR.
1986 mpexp(int *x
, int *y
)
1991 static int i
, i2
, i3
, ie
, ix
, ts
, xs
, tss
;
1992 static float rx
, ry
, rlb
;
1994 /* RETURNS Y = EXP(X) FOR MP X AND Y.
1995 * EXP OF INTEGER AND FRACTIONAL PARTS OF X ARE COMPUTED
1996 * SEPARATELY. SEE ALSO COMMENTS IN MPEXP1.
1997 * TIME IS O(SQRT(T)M(T)).
1998 * DIMENSION OF R MUST BE AT LEAST 4T+10 IN CALLING PROGRAM
1999 * CHECK LEGALITY OF B, T, M AND MXR
2002 --y
; /* Parameter adjustments */
2005 mpchk(&c__4
, &c__10
);
2006 i2
= (MP
.t
<< 1) + 7;
2009 /* CHECK FOR X = 0 */
2011 if (x
[1] != 0) goto L10
;
2012 mpcim(&c__1
, &y
[1]);
2015 /* CHECK IF ABS(X) .LT. 1 */
2018 if (x
[2] > 0) goto L20
;
2020 /* USE MPEXP1 HERE */
2022 mpexp1(&x
[1], &y
[1]);
2023 mpaddi(&y
[1], &c__1
, &y
[1]);
2026 /* SEE IF ABS(X) SO LARGE THAT EXP(X) WILL CERTAINLY OVERFLOW
2027 * OR UNDERFLOW. 1.01 IS TO ALLOW FOR ERRORS IN ALOG.
2031 rlb
= log((float) MP
.b
) * (float)1.01;
2032 r__1
= -(double)((float) (MP
.m
+ 1)) * rlb
;
2033 if (mpcmpr(&x
[1], &r__1
) >= 0) goto L40
;
2035 /* UNDERFLOW SO CALL MPUNFL AND RETURN */
2042 r__1
= (float) MP
.m
* rlb
;
2043 if (mpcmpr(&x
[1], &r__1
) <= 0) goto L70
;
2049 FPRINTF(stderr
, "*** OVERFLOW IN SUBROUTINE MPEXP ***\n");
2055 /* NOW SAFE TO CONVERT X TO REAL */
2060 /* SAVE SIGN AND WORK WITH ABS(X) */
2063 mpabs(&x
[1], &MP
.r
[i3
- 1]);
2065 /* IF ABS(X) .GT. M POSSIBLE THAT INT(X) OVERFLOWS,
2069 if (dabs(rx
) > (float) MP
.m
) {
2070 mpdivi(&MP
.r
[i3
- 1], &c__32
, &MP
.r
[i3
- 1]);
2073 /* GET FRACTIONAL AND INTEGER PARTS OF ABS(X) */
2075 mpcmi(&MP
.r
[i3
- 1], &ix
);
2076 mpcmf(&MP
.r
[i3
- 1], &MP
.r
[i3
- 1]);
2078 /* ATTACH SIGN TO FRACTIONAL PART AND COMPUTE EXP OF IT */
2080 MP
.r
[i3
- 1] = xs
* MP
.r
[i3
- 1];
2081 mpexp1(&MP
.r
[i3
- 1], &y
[1]);
2082 mpaddi(&y
[1], &c__1
, &y
[1]);
2084 /* COMPUTE E-2 OR 1/E USING TWO EXTRA DIGITS IN CASE ABS(X) LARGE
2085 * (BUT ONLY ONE EXTRA DIGIT IF T .LT. 4)
2090 if (MP
.t
< 4) ts
= MP
.t
+ 1;
2095 mpcim(&xs
, &MP
.r
[i2
- 1]);
2098 /* LOOP FOR E COMPUTATION. DECREASE T IF POSSIBLE. */
2104 i__1
= ts
, i__2
= ts
+ 2 + MP
.r
[i2
];
2105 MP
.t
= min(i__1
,i__2
);
2106 if (MP
.t
<= 2) goto L90
;
2109 mpdivi(&MP
.r
[i2
- 1], &i__1
, &MP
.r
[i2
- 1]);
2111 mpadd2(&MP
.r
[i3
- 1], &MP
.r
[i2
- 1], &MP
.r
[i3
- 1], &
2112 MP
.r
[i2
- 1], &c__0
);
2113 if (MP
.r
[i2
- 1] != 0) goto L80
;
2115 /* RAISE E OR 1/E TO POWER IX */
2120 mpaddi(&MP
.r
[i3
- 1], &c__2
, &MP
.r
[i3
- 1]);
2122 mppwr(&MP
.r
[i3
- 1], &ix
, &MP
.r
[i3
- 1]);
2128 /* MULTIPLY EXPS OF INTEGER AND FRACTIONAL PARTS */
2130 mpmul(&y
[1], &MP
.r
[i3
- 1], &y
[1]);
2132 /* MUST CORRECT RESULT IF DIVIDED BY 32 ABOVE. */
2134 if (dabs(rx
) <= (float) MP
.m
|| y
[1] == 0) goto L110
;
2136 for (i
= 1; i
<= 5; ++i
) {
2138 /* SAVE EXPONENT TO AVOID OVERFLOW IN MPMUL */
2142 mpmul(&y
[1], &y
[1], &y
[1]);
2145 /* CHECK FOR UNDERFLOW AND OVERFLOW */
2147 if (y
[2] < -MP
.m
) goto L30
;
2148 if (y
[2] > MP
.m
) goto L50
;
2151 /* CHECK THAT RELATIVE ERROR LESS THAN 0.01 UNLESS ABS(X) LARGE
2152 * (WHEN EXP MIGHT OVERFLOW OR UNDERFLOW)
2156 if (dabs(rx
) > (float)10.0) return;
2159 if ((r__1
= ry
- exp(rx
), dabs(r__1
)) < ry
* (float)0.01) return;
2161 /* THE FOLLOWING MESSAGE MAY INDICATE THAT
2162 * B**(T-1) IS TOO SMALL, OR THAT M IS TOO SMALL SO THE
2163 * RESULT UNDERFLOWED.
2167 FPRINTF(stderr
, "*** ERROR OCCURRED IN MPEXP, RESULT INCORRECT ***\n");
2175 mpexp1(int *x
, int *y
)
2179 static int i
, q
, i2
, i3
, ib
, ic
, ts
;
2182 /* ASSUMES THAT X AND Y ARE MP NUMBERS, -1 .LT. X .LT. 1.
2183 * RETURNS Y = EXP(X) - 1 USING AN O(SQRT(T).M(T)) ALGORITHM
2184 * DESCRIBED IN - R. P. BRENT, THE COMPLEXITY OF MULTIPLE-
2185 * PRECISION ARITHMETIC (IN COMPLEXITY OF COMPUTATIONAL PROBLEM
2186 * SOLVING, UNIV. OF QUEENSLAND PRESS, BRISBANE, 1976, 126-165).
2187 * ASYMPTOTICALLY FASTER METHODS EXIST, BUT ARE NOT USEFUL
2188 * UNLESS T IS VERY LARGE. SEE COMMENTS TO MPATAN AND MPPIGL.
2189 * DIMENSION OF R IN CALLING PROGRAM MUST BE AT LEAST 3T+8
2190 * CHECK LEGALITY OF B, T, M AND MXR
2193 --y
; /* Parameter adjustments */
2196 mpchk(&c__3
, &c__8
);
2200 /* CHECK FOR X = 0 */
2202 if (x
[1] != 0) goto L20
;
2208 /* CHECK THAT ABS(X) .LT. 1 */
2211 if (x
[2] <= 0) goto L40
;
2214 FPRINTF(stderr
, "*** ABS(X) NOT LESS THAN 1 IN CALL TO MPEXP1 ***\n");
2221 mpstr(&x
[1], &MP
.r
[i2
- 1]);
2222 rlb
= log((float) MP
.b
);
2224 /* COMPUTE APPROXIMATELY OPTIMAL Q (AND DIVIDE X BY 2**Q) */
2226 q
= (int) (sqrt((float) MP
.t
* (float).48 * rlb
) + (float) x
[2] *
2231 if (q
<= 0) goto L60
;
2235 for (i
= 1; i
<= i__1
; ++i
) {
2237 if (ic
< ib
&& ic
!= MP
.b
&& i
< q
) continue;
2238 mpdivi(&MP
.r
[i2
- 1], &ic
, &MP
.r
[i2
- 1]);
2243 if (MP
.r
[i2
- 1] == 0) goto L10
;
2244 mpstr(&MP
.r
[i2
- 1], &y
[1]);
2245 mpstr(&MP
.r
[i2
- 1], &MP
.r
[i3
- 1]);
2249 /* SUM SERIES, REDUCING T WHERE POSSIBLE */
2252 MP
.t
= ts
+ 2 + MP
.r
[i3
] - y
[2];
2253 if (MP
.t
<= 2) goto L80
;
2255 MP
.t
= min(MP
.t
,ts
);
2256 mpmul(&MP
.r
[i2
- 1], &MP
.r
[i3
- 1], &MP
.r
[i3
- 1]);
2258 mpdivi(&MP
.r
[i3
- 1], &i
, &MP
.r
[i3
- 1]);
2260 mpadd2(&MP
.r
[i3
- 1], &y
[1], &y
[1], &y
[1], &c__0
);
2261 if (MP
.r
[i3
- 1] != 0) goto L70
;
2267 /* APPLY (X+1)**2 - 1 = X(2 + X) FOR Q ITERATIONS */
2270 for (i
= 1; i
<= i__1
; ++i
) {
2271 mpaddi(&y
[1], &c__2
, &MP
.r
[i2
- 1]);
2272 mpmul(&MP
.r
[i2
- 1], &y
[1], &y
[1]);
2278 mpext(int *i
, int *j
, int *x
)
2282 /* ROUTINE CALLED BY MPDIV AND MPSQRT TO ENSURE THAT
2283 * RESULTS ARE REPRESENTED EXACTLY IN T-2 DIGITS IF THEY
2284 * CAN BE. X IS AN MP NUMBER, I AND J ARE INTEGERS.
2287 --x
; /* Parameter adjustments */
2289 if (x
[1] == 0 || MP
.t
<= 2 || *i
== 0) return;
2291 /* COMPUTE MAXIMUM POSSIBLE ERROR IN THE LAST PLACE */
2293 q
= (*j
+ 1) / *i
+ 1;
2294 s
= MP
.b
* x
[MP
.t
+ 1] + x
[MP
.t
+ 2];
2295 if (s
> q
) goto L10
;
2297 /* SET LAST TWO DIGITS TO ZERO */
2304 if (s
+ q
< MP
.b
* MP
.b
) return;
2308 x
[MP
.t
+ 1] = MP
.b
- 1;
2311 /* NORMALIZE X (LAST DIGIT B IS OK IN MPMULI) */
2313 mpmuli(&x
[1], &c__1
, &x
[1]);
2318 mpgcd(int *k
, int *l
)
2320 static int i
, j
, is
, js
;
2322 /* RETURNS K = K/GCD AND L = L/GCD, WHERE GCD IS THE
2323 * GREATEST COMMON DIVISOR OF K AND L.
2324 * SAVE INPUT PARAMETERS IN LOCAL VARIABLES
2331 if (js
== 0) goto L30
;
2333 /* EUCLIDEAN ALGORITHM LOOP */
2337 if (is
== 0) goto L20
;
2339 if (js
!= 0) goto L10
;
2342 /* HERE JS IS THE GCD OF I AND J */
2349 /* IF J = 0 RETURN (1, 0) UNLESS I = 0, THEN (0, 0) */
2353 if (is
== 0) *k
= 0;
2359 mpge(int *x
, int *y
)
2363 /* RETURNS LOGICAL VALUE OF (X .GE. Y) FOR MP X AND Y. */
2365 --y
; /* Parameter adjustments */
2368 ret_val
= mpcomp(&x
[1], &y
[1]) >= 0;
2375 mpgt(int *x
, int *y
)
2379 /* RETURNS LOGICAL VALUE OF (X .GT. Y) FOR MP X AND Y. */
2381 --y
; /* Parameter adjustments */
2384 ret_val
= mpcomp(&x
[1], &y
[1]) > 0;
2391 mple(int *x
, int *y
)
2395 /* RETURNS LOGICAL VALUE OF (X .LE. Y) FOR MP X AND Y. */
2397 --y
; /* Parameter adjustments */
2400 ret_val
= mpcomp(&x
[1], &y
[1]) <= 0;
2407 mpln(int *x
, int *y
)
2411 static int e
, k
, i2
, i3
;
2412 static float rx
, rlx
;
2414 /* RETURNS Y = LN(X), FOR MP X AND Y, USING MPLNS.
2415 * RESTRICTION - INTEGER PART OF LN(X) MUST BE REPRESENTABLE
2416 * AS A SINGLE-PRECISION INTEGER. TIME IS O(SQRT(T).M(T)).
2417 * FOR SMALL INTEGER X, MPLNI IS FASTER.
2418 * ASYMPTOTICALLY FASTER METHODS EXIST (EG THE GAUSS-SALAMIN
2419 * METHOD, SEE MPLNGS), BUT ARE NOT USEFUL UNLESS T IS LARGE.
2420 * SEE COMMENTS TO MPATAN, MPEXP1 AND MPPIGL.
2421 * DIMENSION OF R IN CALLING PROGRAM MUST BE AT LEAST 6T+14.
2422 * CHECK LEGALITY OF B, T, M AND MXR
2425 --y
; /* Parameter adjustments */
2428 mpchk(&c__6
, &c__14
);
2429 i2
= (MP
.t
<< 2) + 11;
2432 /* CHECK THAT X IS POSITIVE */
2433 if (x
[1] > 0) goto L20
;
2436 FPRINTF(stderr
, "*** X NONPOSITIVE IN CALL TO MPLN ***\n");
2443 /* MOVE X TO LOCAL STORAGE */
2446 mpstr(&x
[1], &MP
.r
[i2
- 1]);
2450 /* LOOP TO GET APPROXIMATE LN(X) USING SINGLE-PRECISION */
2453 mpaddi(&MP
.r
[i2
- 1], &c_n1
, &MP
.r
[i3
- 1]);
2455 /* IF POSSIBLE GO TO CALL MPLNS */
2457 if (MP
.r
[i3
- 1] == 0 || MP
.r
[i3
] + 1 <= 0) goto L50
;
2459 /* REMOVE EXPONENT TO AVOID FLOATING-POINT OVERFLOW */
2463 mpcmr(&MP
.r
[i2
- 1], &rx
);
2465 /* RESTORE EXPONENT AND COMPUTE SINGLE-PRECISION LOG */
2468 rlx
= log(rx
) + (float) e
* log((float) MP
.b
);
2469 r__1
= -(double)rlx
;
2470 mpcrm(&r__1
, &MP
.r
[i3
- 1]);
2472 /* UPDATE Y AND COMPUTE ACCURATE EXP OF APPROXIMATE LOG */
2474 mpsub(&y
[1], &MP
.r
[i3
- 1], &y
[1]);
2475 mpexp(&MP
.r
[i3
- 1], &MP
.r
[i3
- 1]);
2477 /* COMPUTE RESIDUAL WHOSE LOG IS STILL TO BE FOUND */
2479 mpmul(&MP
.r
[i2
- 1], &MP
.r
[i3
- 1], &MP
.r
[i2
- 1]);
2481 /* MAKE SURE NOT LOOPING INDEFINITELY */
2483 if (k
< 10) goto L30
;
2486 FPRINTF(stderr
, "*** ERROR IN MPLN, ITERATION NOT CONVERGING ***\n");
2492 /* COMPUTE FINAL CORRECTION ACCURATELY USING MPLNS */
2495 mplns(&MP
.r
[i3
- 1], &MP
.r
[i3
- 1]);
2496 mpadd(&y
[1], &MP
.r
[i3
- 1], &y
[1]);
2501 mplns(int *x
, int *y
)
2505 static int i2
, i3
, i4
, ts
, it0
, ts2
, ts3
;
2507 /* RETURNS MP Y = LN(1+X) IF X IS AN MP NUMBER SATISFYING THE
2508 * CONDITION ABS(X) .LT. 1/B, ERROR OTHERWISE.
2509 * USES NEWTONS METHOD TO SOLVE THE EQUATION
2510 * EXP1(-Y) = X, THEN REVERSES SIGN OF Y.
2511 * (HERE EXP1(Y) = EXP(Y) - 1 IS COMPUTED USING MPEXP1).
2512 * TIME IS O(SQRT(T).M(T)) AS FOR MPEXP1, SPACE = 5T+12.
2513 * CHECK LEGALITY OF B, T, M AND MXR
2516 --y
; /* Parameter adjustments */
2519 mpchk(&c__5
, &c__12
);
2520 i2
= (MP
.t
<< 1) + 7;
2524 /* CHECK FOR X = 0 EXACTLY */
2526 if (x
[1] != 0) goto L10
;
2530 /* CHECK THAT ABS(X) .LT. 1/B */
2533 if (x
[2] + 1 <= 0) goto L30
;
2536 FPRINTF(stderr
, "*** ABS(X) .GE. 1/B IN CALL TO MPLNS ***\n");
2543 /* SAVE T AND GET STARTING APPROXIMATION TO -LN(1+X) */
2547 mpstr(&x
[1], &MP
.r
[i3
- 1]);
2548 mpdivi(&x
[1], &c__4
, &MP
.r
[i2
- 1]);
2549 mpaddq(&MP
.r
[i2
- 1], &c_n1
, &c__3
, &MP
.r
[i2
- 1]);
2550 mpmul(&x
[1], &MP
.r
[i2
- 1], &MP
.r
[i2
- 1]);
2551 mpaddq(&MP
.r
[i2
- 1], &c__1
, &c__2
, &MP
.r
[i2
- 1]);
2552 mpmul(&x
[1], &MP
.r
[i2
- 1], &MP
.r
[i2
- 1]);
2553 mpaddi(&MP
.r
[i2
- 1], &c_n1
, &MP
.r
[i2
- 1]);
2554 mpmul(&x
[1], &MP
.r
[i2
- 1], &y
[1]);
2556 /* START NEWTON ITERATION USING SMALL T, LATER INCREASE */
2560 i__1
= 5, i__2
= 13 - (MP
.b
<< 1);
2561 MP
.t
= max(i__1
,i__2
);
2562 if (MP
.t
> ts
) goto L80
;
2564 it0
= (MP
.t
+ 5) / 2;
2567 mpexp1(&y
[1], &MP
.r
[i4
- 1]);
2568 mpmul(&MP
.r
[i3
- 1], &MP
.r
[i4
- 1], &MP
.r
[i2
- 1]);
2569 mpadd(&MP
.r
[i4
- 1], &MP
.r
[i2
- 1], &MP
.r
[i4
- 1]);
2570 mpadd(&MP
.r
[i3
- 1], &MP
.r
[i4
- 1], &MP
.r
[i4
- 1]);
2571 mpsub(&y
[1], &MP
.r
[i4
- 1], &y
[1]);
2572 if (MP
.t
>= ts
) goto L60
;
2574 /* FOLLOWING LOOP COMPUTES NEXT VALUE OF T TO USE.
2575 * BECAUSE NEWTONS METHOD HAS 2ND ORDER CONVERGENCE,
2576 * WE CAN ALMOST DOUBLE T EACH TIME.
2584 MP
.t
= (MP
.t
+ it0
) / 2;
2585 if (MP
.t
> ts3
) goto L50
;
2590 /* CHECK THAT NEWTON ITERATION WAS CONVERGING AS EXPECTED */
2593 if (MP
.r
[i4
- 1] == 0 || MP
.r
[i4
] << 1 <= it0
- MP
.t
) {
2598 FPRINTF(stderr
, "*** ERROR OCCURRED IN MPLNS.\nNEWTON ITERATION NOT CONVERGING PROPERLY ***\n");
2603 /* REVERSE SIGN OF Y AND RETURN */
2612 mplt(int *x
, int *y
)
2616 /* RETURNS LOGICAL VALUE OF (X .LT. Y) FOR MP X AND Y. */
2618 --y
; /* Parameter adjustments */
2621 ret_val
= mpcomp(&x
[1], &y
[1]) < 0;
2634 /* SETS X TO THE LARGEST POSSIBLE POSITIVE MP NUMBER
2635 * CHECK LEGALITY OF B, T, M AND MXR
2638 --x
; /* Parameter adjustments */
2640 mpchk(&c__1
, &c__4
);
2643 /* SET FRACTION DIGITS TO B-1 */
2646 for (i
= 1; i
<= i__1
; ++i
) x
[i
+ 2] = it
;
2648 /* SET SIGN AND EXPONENT */
2656 mpmlp(int *u
, int *v
, int *w
, int *j
)
2662 /* PERFORMS INNER MULTIPLICATION LOOP FOR MPMUL
2663 * NOTE THAT CARRIES ARE NOT PROPAGATED IN INNER LOOP,
2664 * WHICH SAVES TIME AT THE EXPENSE OF SPACE.
2667 --v
; /* Parameter adjustments */
2671 for (i
= 1; i
<= i__1
; ++i
) u
[i
] += *w
* v
[i
];
2676 mpmul(int *x
, int *y
, int *z
)
2678 int i__1
, i__2
, i__3
, i__4
;
2680 static int c
, i
, j
, i2
, j1
, re
, ri
, xi
, rs
, i2p
;
2682 /* MULTIPLIES X AND Y, RETURNING RESULT IN Z, FOR MP X, Y AND Z.
2683 * THE SIMPLE O(T**2) ALGORITHM IS USED, WITH
2684 * FOUR GUARD DIGITS AND R*-ROUNDING.
2685 * ADVANTAGE IS TAKEN OF ZERO DIGITS IN X, BUT NOT IN Y.
2686 * ASYMPTOTICALLY FASTER ALGORITHMS ARE KNOWN (SEE KNUTH,
2687 * VOL. 2), BUT ARE DIFFICULT TO IMPLEMENT IN FORTRAN IN AN
2688 * EFFICIENT AND MACHINE-INDEPENDENT MANNER.
2689 * IN COMMENTS TO OTHER MP ROUTINES, M(T) IS THE TIME
2690 * TO PERFORM T-DIGIT MP MULTIPLICATION. THUS
2691 * M(T) = O(T**2) WITH THE PRESENT VERSION OF MPMUL,
2692 * BUT M(T) = O(T.LOG(T).LOG(LOG(T))) IS THEORETICALLY POSSIBLE.
2693 * CHECK LEGALITY OF B, T, M AND MXR
2696 --z
; /* Parameter adjustments */
2700 mpchk(&c__1
, &c__4
);
2704 /* FORM SIGN OF PRODUCT */
2707 if (rs
!= 0) goto L10
;
2709 /* SET RESULT TO ZERO */
2714 /* FORM EXPONENT OF PRODUCT */
2719 /* CLEAR ACCUMULATOR */
2722 for (i
= 1; i
<= i__1
; ++i
) MP
.r
[i
- 1] = 0;
2724 /* PERFORM MULTIPLICATION */
2728 for (i
= 1; i
<= i__1
; ++i
) {
2731 /* FOR SPEED, PUT THE NUMBER WITH MANY ZEROS FIRST */
2733 if (xi
== 0) continue;
2737 i__3
= MP
.t
, i__4
= i2
- i
;
2738 i__2
= min(i__3
,i__4
);
2739 mpmlp(&MP
.r
[i
], &y
[3], &xi
, &i__2
);
2741 if (c
> 0) continue;
2743 /* CHECK FOR LEGAL BASE B DIGIT */
2745 if (xi
< 0 || xi
>= MP
.b
) goto L90
;
2747 /* PROPAGATE CARRIES AT END AND EVERY EIGHTH TIME,
2748 * FASTER THAN DOING IT EVERY TIME.
2752 for (j
= 1; j
<= i__2
; ++j
) {
2754 ri
= MP
.r
[j1
- 1] + c
;
2755 if (ri
< 0) goto L70
;
2757 MP
.r
[j1
- 1] = ri
- MP
.b
* c
;
2759 if (c
!= 0) goto L90
;
2763 if (c
== 8) goto L60
;
2764 if (xi
< 0 || xi
>= MP
.b
) goto L90
;
2767 for (j
= 1; j
<= i__1
; ++j
) {
2769 ri
= MP
.r
[j1
- 1] + c
;
2770 if (ri
< 0) goto L70
;
2772 MP
.r
[j1
- 1] = ri
- MP
.b
* c
;
2774 if (c
!= 0) goto L90
;
2776 /* NORMALIZE AND ROUND RESULT */
2779 mpnzr(&rs
, &re
, &z
[1], &c__0
);
2784 FPRINTF(stderr
, "*** INTEGER OVERFLOW IN MPMUL, B TOO LARGE ***\n");
2791 FPRINTF(stderr
, "*** ILLEGAL BASE B DIGIT IN CALL TO MPMUL.\nPOSSIBLE OVERWRITING PROBLEM ***\n");
2801 mpmul2(int *x
, int *iy
, int *z
, int *trunc
)
2805 static int c
, i
, j
, c1
, c2
, j1
, j2
;
2806 static int t1
, t3
, t4
, ij
, re
, ri
, is
, ix
, rs
;
2808 /* MULTIPLIES MP X BY SINGLE-PRECISION INTEGER IY GIVING MP Z.
2809 * MULTIPLICATION BY 1 MAY BE USED TO NORMALIZE A NUMBER
2810 * EVEN IF SOME DIGITS ARE GREATER THAN B-1.
2811 * RESULT IS ROUNDED IF TRUNC.EQ.0, OTHERWISE TRUNCATED.
2814 --z
; /* Parameter adjustments */
2818 if (rs
== 0) goto L10
;
2820 if (j
< 0) goto L20
;
2821 else if (j
== 0) goto L10
;
2834 /* CHECK FOR MULTIPLICATION BY B */
2836 if (j
!= MP
.b
) goto L50
;
2837 if (x
[2] < MP
.m
) goto L40
;
2839 mpchk(&c__1
, &c__4
);
2842 FPRINTF(stderr
, "*** OVERFLOW OCCURRED IN MPMUL2 ***\n");
2849 mpstr(&x
[1], &z
[1]);
2854 /* SET EXPONENT TO EXPONENT(X) + 4 */
2859 /* FORM PRODUCT IN ACCUMULATOR */
2866 /* IF J*B NOT REPRESENTABLE AS AN INTEGER WE HAVE TO SIMULATE
2867 * DOUBLE-PRECISION MULTIPLICATION.
2872 i__1
= MP
.b
<< 3, i__2
= 32767 / MP
.b
;
2873 if (j
>= max(i__1
,i__2
)) goto L110
;
2876 for (ij
= 1; ij
<= i__1
; ++ij
) {
2878 ri
= j
* x
[i
+ 2] + c
;
2880 MP
.r
[i
+ 3] = ri
- MP
.b
* c
;
2883 /* CHECK FOR INTEGER OVERFLOW */
2885 if (ri
< 0) goto L130
;
2887 /* HAVE TO TREAT FIRST FOUR WORDS OF R SEPARATELY */
2889 for (ij
= 1; ij
<= 4; ++ij
) {
2893 MP
.r
[i
- 1] = ri
- MP
.b
* c
;
2895 if (c
== 0) goto L100
;
2897 /* HAVE TO SHIFT RIGHT HERE AS CARRY OFF END */
2901 for (ij
= 1; ij
<= i__1
; ++ij
) {
2903 MP
.r
[i
] = MP
.r
[i
- 1];
2907 MP
.r
[0] = ri
- MP
.b
* c
;
2909 if (c
< 0) goto L130
;
2910 else if (c
== 0) goto L100
;
2913 /* NORMALIZE AND ROUND OR TRUNCATE RESULT */
2916 mpnzr(&rs
, &re
, &z
[1], trunc
);
2919 /* HERE J IS TOO LARGE FOR SINGLE-PRECISION MULTIPLICATION */
2928 for (ij
= 1; ij
<= i__1
; ++ij
) {
2933 if (i
> 0) ix
= x
[i
+ 2];
2936 c
= j1
* ix
+ c1
+ is
;
2937 MP
.r
[i
+ 3] = ri
- MP
.b
* is
;
2940 if (c
< 0) goto L130
;
2941 else if (c
== 0) goto L100
;
2944 /* CAN ONLY GET HERE IF INTEGER OVERFLOW OCCURRED */
2947 mpchk(&c__1
, &c__4
);
2950 FPRINTF(stderr
, "*** INTEGER OVERFLOW IN MPMUL2, B TOO LARGE ***\n");
2959 mpmuli(int *x
, int *iy
, int *z
)
2962 /* MULTIPLIES MP X BY SINGLE-PRECISION INTEGER IY GIVING MP Z.
2963 * THIS IS FASTER THAN USING MPMUL. RESULT IS ROUNDED.
2964 * MULTIPLICATION BY 1 MAY BE USED TO NORMALIZE A NUMBER
2965 * EVEN IF THE LAST DIGIT IS B.
2968 --z
; /* Parameter adjustments */
2971 mpmul2(&x
[1], iy
, &z
[1], &c__0
);
2976 mpmulq(int *x
, int *i
, int *j
, int *y
)
2982 /* MULTIPLIES MP X BY I/J, GIVING MP Y */
2984 --y
; /* Parameter adjustments */
2987 if (*j
!= 0) goto L20
;
2988 mpchk(&c__1
, &c__4
);
2991 FPRINTF(stderr
, "*** ATTEMPTED DIVISION BY ZERO IN MPMULQ ***\n");
2998 if (*i
!= 0) goto L40
;
3004 /* REDUCE TO LOWEST TERMS */
3010 if (C_abs(is
) == 1) goto L50
;
3012 mpdivi(&x
[1], &js
, &y
[1]);
3013 mpmul2(&y
[1], &is
, &y
[1], &c__0
);
3020 mpdivi(&x
[1], &i__1
, &y
[1]);
3025 mpneg(int *x
, int *y
)
3028 /* SETS Y = -X FOR MP NUMBERS X AND Y */
3030 --y
; /* Parameter adjustments */
3033 mpstr(&x
[1], &y
[1]);
3039 mpnzr(int *rs
, int *re
, int *z
, int *trunc
)
3043 static int i
, j
, k
, b2
, i2
, is
, it
, i2m
, i2p
;
3045 /* ASSUMES LONG (I.E. (T+4)-DIGIT) FRACTION IN
3046 * R, SIGN = RS, EXPONENT = RE. NORMALIZES,
3047 * AND RETURNS MP RESULT IN Z. INTEGER ARGUMENTS RS AND RE
3048 * ARE NOT PRESERVED. R*-ROUNDING IS USED IF TRUNC.EQ.0
3051 --z
; /* Parameter adjustments */
3054 if (*rs
!= 0) goto L20
;
3056 /* STORE ZERO IN Z */
3062 /* CHECK THAT SIGN = +-1 */
3065 if (C_abs(*rs
) <= 1) goto L40
;
3068 FPRINTF(stderr
, "*** SIGN NOT 0, +1 OR -1 IN CALL TO MPNZR.\nPOSSIBLE OVERWRITING PROBLEM ***\n");
3074 /* LOOK FOR FIRST NONZERO DIGIT */
3078 for (i
= 1; i
<= i__1
; ++i
) {
3080 if (MP
.r
[i
- 1] > 0) goto L60
;
3088 if (is
== 0) goto L90
;
3095 for (j
= 1; j
<= i__1
; ++j
) {
3097 MP
.r
[j
- 1] = MP
.r
[k
- 1];
3101 for (j
= i2p
; j
<= i__1
; ++j
) MP
.r
[j
- 1] = 0;
3103 /* CHECK TO SEE IF TRUNCATION IS DESIRED */
3106 if (*trunc
!= 0) goto L150
;
3108 /* SEE IF ROUNDING NECESSARY
3109 * TREAT EVEN AND ODD BASES DIFFERENTLY
3113 if (b2
<< 1 != MP
.b
) goto L130
;
3115 /* B EVEN. ROUND IF R(T+1).GE.B2 UNLESS R(T) ODD AND ALL ZEROS
3119 if ((i__1
= MP
.r
[MP
.t
] - b2
) < 0) goto L150
;
3120 else if (i__1
== 0) goto L100
;
3124 if (MP
.r
[MP
.t
- 1] % 2 == 0) goto L110
;
3126 if (MP
.r
[MP
.t
+ 1] + MP
.r
[MP
.t
+ 2] + MP
.r
[MP
.t
+ 3] == 0) {
3134 for (j
= 1; j
<= i__1
; ++j
) {
3137 if (MP
.r
[i
- 1] < MP
.b
) goto L150
;
3141 /* EXCEPTIONAL CASE, ROUNDED UP TO .10000... */
3147 /* ODD BASE, ROUND IF R(T+1)... .GT. 1/2 */
3150 for (i
= 1; i
<= 4; ++i
) {
3152 if ((i__1
= MP
.r
[it
- 1] - b2
) < 0) goto L150
;
3153 else if (i__1
== 0) continue;
3157 /* CHECK FOR OVERFLOW */
3160 if (*re
<= MP
.m
) goto L170
;
3163 FPRINTF(stderr
, "*** OVERFLOW OCCURRED IN MPNZR ***\n");
3169 /* CHECK FOR UNDERFLOW */
3172 if (*re
< -MP
.m
) goto L190
;
3174 /* STORE RESULT IN Z */
3179 for (i
= 1; i
<= i__1
; ++i
) z
[i
+ 2] = MP
.r
[i
- 1];
3182 /* UNDERFLOW HERE */
3193 /* CALLED ON MULTIPLE-PRECISION OVERFLOW, IE WHEN THE
3194 * EXPONENT OF MP NUMBER X WOULD EXCEED M.
3195 * AT PRESENT EXECUTION IS TERMINATED WITH AN ERROR MESSAGE
3196 * AFTER CALLING MPMAXR(X), BUT IT WOULD BE POSSIBLE TO RETURN,
3197 * POSSIBLY UPDATING A COUNTER AND TERMINATING EXECUTION AFTER
3198 * A PRESET NUMBER OF OVERFLOWS. ACTION COULD EASILY BE DETERMINED
3199 * BY A FLAG IN LABELLED COMMON.
3200 * M MAY HAVE BEEN OVERWRITTEN, SO CHECK B, T, M ETC.
3203 --x
; /* Parameter adjustments */
3205 mpchk(&c__1
, &c__4
);
3207 /* SET X TO LARGEST POSSIBLE POSITIVE NUMBER */
3212 FPRINTF(stderr
, "*** CALL TO MPOVFL, MP OVERFLOW OCCURRED ***\n");
3215 /* TERMINATE EXECUTION BY CALLING MPERR */
3229 /* SETS MP X = PI TO THE AVAILABLE PRECISION.
3230 * USES PI/4 = 4.ARCTAN(1/5) - ARCTAN(1/239).
3232 * DIMENSION OF R MUST BE AT LEAST 3T+8
3233 * CHECK LEGALITY OF B, T, M AND MXR
3236 --x
; /* Parameter adjustments */
3238 mpchk(&c__3
, &c__8
);
3240 /* ALLOW SPACE FOR MPART1 */
3242 i2
= (MP
.t
<< 1) + 7;
3243 mpart1(&c__5
, &MP
.r
[i2
- 1]);
3244 mpmuli(&MP
.r
[i2
- 1], &c__4
, &MP
.r
[i2
- 1]);
3245 mpart1(&c__239
, &x
[1]);
3246 mpsub(&MP
.r
[i2
- 1], &x
[1], &x
[1]);
3247 mpmuli(&x
[1], &c__4
, &x
[1]);
3249 /* RETURN IF ERROR IS LESS THAN 0.01 */
3252 if ((r__1
= rx
- (float)3.1416, dabs(r__1
)) < (float) 0.01) return;
3254 /* FOLLOWING MESSAGE MAY INDICATE THAT B**(T-1) IS TOO SMALL */
3257 FPRINTF(stderr
, "*** ERROR OCCURRED IN MPPI, RESULT INCORRECT ***\n");
3265 mppwr(int *x
, int *n
, int *y
)
3267 static int i2
, n2
, ns
;
3269 /* RETURNS Y = X**N, FOR MP X AND Y, INTEGER N, WITH 0**0 = 1.
3270 * R MUST BE DIMENSIONED AT LEAST 4T+10 IN CALLING PROGRAM
3271 * (2T+6 IS ENOUGH IF N NONNEGATIVE).
3274 --y
; /* Parameter adjustments */
3279 if (n2
< 0) goto L20
;
3280 else if (n2
== 0) goto L10
;
3283 /* N = 0, RETURN Y = 1. */
3286 mpcim(&c__1
, &y
[1]);
3292 mpchk(&c__4
, &c__10
);
3294 if (x
[1] != 0) goto L60
;
3297 FPRINTF(stderr
, "*** ATTEMPT TO RAISE ZERO TO NEGATIVE POWER IN CALL TO SUBROUTINE MPPWR ***\n");
3306 mpchk(&c__2
, &c__6
);
3307 if (x
[1] != 0) goto L60
;
3309 /* X = 0, N .GT. 0, SO Y = 0 */
3318 mpstr(&x
[1], &y
[1]);
3320 /* IF N .LT. 0 FORM RECIPROCAL */
3322 if (*n
< 0) mprec(&y
[1], &y
[1]);
3323 mpstr(&y
[1], &MP
.r
[i2
- 1]);
3325 /* SET PRODUCT TERM TO ONE */
3327 mpcim(&c__1
, &y
[1]);
3329 /* MAIN LOOP, LOOK AT BITS OF N2 FROM RIGHT */
3334 if (n2
<< 1 != ns
) mpmul(&y
[1], &MP
.r
[i2
- 1], &y
[1]);
3335 if (n2
<= 0) return;
3337 mpmul(&MP
.r
[i2
- 1], &MP
.r
[i2
- 1], &MP
.r
[i2
- 1]);
3343 mppwr2(int *x
, int *y
, int *z
)
3347 /* RETURNS Z = X**Y FOR MP NUMBERS X, Y AND Z, WHERE X IS
3348 * POSITIVE (X .EQ. 0 ALLOWED IF Y .GT. 0). SLOWER THAN
3349 * MPPWR AND MPQPWR, SO USE THEM IF POSSIBLE.
3350 * DIMENSION OF R IN COMMON AT LEAST 7T+16
3351 * CHECK LEGALITY OF B, T, M AND MXR
3354 --z
; /* Parameter adjustments */
3358 mpchk(&c__7
, &c__16
);
3359 if (x
[1] < 0) goto L10
;
3360 else if (x
[1] == 0) goto L30
;
3364 show_error(_("Negative X and non-integer Y not supported"));
3367 /* HERE X IS ZERO, RETURN ZERO IF Y POSITIVE, OTHERWISE ERROR */
3370 if (y
[1] > 0) goto L60
;
3373 FPRINTF(stderr
, "*** X ZERO AND Y NONPOSITIVE IN CALL TO MPPWR2 ***\n");
3379 /* RETURN ZERO HERE */
3385 /* USUAL CASE HERE, X POSITIVE
3386 * USE MPLN AND MPEXP TO COMPUTE POWER
3391 mpln(&x
[1], &MP
.r
[i2
- 1]);
3392 mpmul(&y
[1], &MP
.r
[i2
- 1], &z
[1]);
3394 /* IF X**Y IS TOO LARGE, MPEXP WILL PRINT ERROR MESSAGE */
3396 mpexp(&z
[1], &z
[1]);
3401 mprec(int *x
, int *y
)
3404 /* Initialized data */
3406 static int it
[9] = { 0, 8, 6, 5, 4, 4, 4, 4, 4 };
3410 static int i2
, i3
, ex
, ts
, it0
, ts2
, ts3
;
3413 /* RETURNS Y = 1/X, FOR MP X AND Y.
3414 * MPROOT (X, -1, Y) HAS THE SAME EFFECT.
3415 * DIMENSION OF R MUST BE AT LEAST 4*T+10 IN CALLING PROGRAM
3416 * (BUT Y(1) MAY BE R(3T+9)).
3417 * NEWTONS METHOD IS USED, SO FINAL ONE OR TWO DIGITS MAY
3421 --y
; /* Parameter adjustments */
3424 /* CHECK LEGALITY OF B, T, M AND MXR */
3426 mpchk(&c__4
, &c__10
);
3428 /* MPADDI REQUIRES 2T+6 WORDS. */
3430 i2
= (MP
.t
<< 1) + 7;
3432 if (x
[1] != 0) goto L20
;
3435 FPRINTF(stderr
, "*** ATTEMPTED DIVISION BY ZERO IN CALL TO MPREC ***\n");
3445 /* TEMPORARILY INCREASE M TO AVOID OVERFLOW */
3449 /* SET EXPONENT TO ZERO SO RX NOT TOO LARGE OR SMALL. */
3454 /* USE SINGLE-PRECISION RECIPROCAL AS FIRST APPROXIMATION */
3456 r__1
= (float)1. / rx
;
3457 mpcrm(&r__1
, &MP
.r
[i2
- 1]);
3459 /* RESTORE EXPONENT */
3463 /* CORRECT EXPONENT OF FIRST APPROXIMATION */
3467 /* SAVE T (NUMBER OF DIGITS) */
3471 /* START WITH SMALL T TO SAVE TIME. ENSURE THAT B**(T-1) .GE. 100 */
3474 if (MP
.b
< 10) MP
.t
= it
[MP
.b
- 1];
3475 it0
= (MP
.t
+ 4) / 2;
3476 if (MP
.t
> ts
) goto L70
;
3478 /* MAIN ITERATION LOOP */
3481 mpmul(&x
[1], &MP
.r
[i2
- 1], &MP
.r
[i3
- 1]);
3482 mpaddi(&MP
.r
[i3
- 1], &c_n1
, &MP
.r
[i3
- 1]);
3484 /* TEMPORARILY REDUCE T */
3487 MP
.t
= (MP
.t
+ it0
) / 2;
3488 mpmul(&MP
.r
[i2
- 1], &MP
.r
[i3
- 1], &MP
.r
[i3
- 1]);
3493 mpsub(&MP
.r
[i2
- 1], &MP
.r
[i3
- 1], &MP
.r
[i2
- 1]);
3494 if (MP
.t
>= ts
) goto L50
;
3496 /* FOLLOWING LOOP ALMOST DOUBLES T (POSSIBLE
3497 * BECAUSE NEWTONS METHOD HAS 2ND ORDER CONVERGENCE).
3504 MP
.t
= (MP
.t
+ it0
) / 2;
3505 if (MP
.t
> ts3
) goto L40
;
3510 /* RETURN IF NEWTON ITERATION WAS CONVERGING */
3513 if (MP
.r
[i3
- 1] == 0 || (MP
.r
[i2
] - MP
.r
[i3
]) << 1 >= MP
.t
- it0
) {
3517 /* THE FOLLOWING MESSAGE MAY INDICATE THAT B**(T-1) IS TOO SMALL,
3518 * OR THAT THE STARTING APPROXIMATION IS NOT ACCURATE ENOUGH.
3522 FPRINTF(stderr
, "*** ERROR OCCURRED IN MPREC, NEWTON ITERATION NOT CONVERGING PROPERLY ***\n");
3527 /* MOVE RESULT TO Y AND RETURN AFTER RESTORING T */
3531 mpstr(&MP
.r
[i2
- 1], &y
[1]);
3533 /* RESTORE M AND CHECK FOR OVERFLOW (UNDERFLOW IMPOSSIBLE) */
3536 if (y
[2] <= MP
.m
) return;
3539 FPRINTF(stderr
, "*** OVERFLOW OCCURRED IN MPREC ***\n");
3547 mproot(int *x
, int *n
, int *y
)
3550 /* Initialized data */
3552 static int it
[9] = { 0, 8, 6, 5, 4, 4, 4, 4, 4 };
3557 static int i2
, i3
, ex
, np
, ts
, it0
, ts2
, ts3
, xes
;
3560 /* RETURNS Y = X**(1/N) FOR INTEGER N, ABS(N) .LE. MAX (B, 64).
3561 * AND MP NUMBERS X AND Y,
3562 * USING NEWTONS METHOD WITHOUT DIVISIONS. SPACE = 4T+10
3563 * (BUT Y(1) MAY BE R(3T+9))
3566 --y
; /* Parameter adjustments */
3569 /* CHECK LEGALITY OF B, T, M AND MXR */
3571 mpchk(&c__4
, &c__10
);
3572 if (*n
!= 1) goto L10
;
3573 mpstr(&x
[1], &y
[1]);
3577 i2
= (MP
.t
<< 1) + 7;
3579 if (*n
!= 0) goto L30
;
3582 FPRINTF(stderr
, "*** N = 0 IN CALL TO MPROOT ***\n");
3590 /* LOSS OF ACCURACY IF NP LARGE, SO ONLY ALLOW NP .LE. MAX (B, 64) */
3592 if (np
<= max(MP
.b
,64)) goto L60
;
3595 FPRINTF(stderr
, "*** ABS(N) TOO LARGE IN CALL TO MPROOT ***\n");
3603 /* LOOK AT SIGN OF X */
3606 if (x
[1] < 0) goto L90
;
3607 else if (x
[1] == 0) goto L70
;
3610 /* X = 0 HERE, RETURN 0 IF N POSITIVE, ERROR IF NEGATIVE */
3617 FPRINTF(stderr
, "*** X = 0 AND N NEGATIVE IN CALL TO MPROOT ***\n");
3622 /* X NEGATIVE HERE, SO ERROR IF N IS EVEN */
3625 if (np
% 2 != 0) goto L110
;
3628 FPRINTF(stderr
, "*** X NEGATIVE AND N EVEN IN CALL TO MPROOT ***\n");
3633 /* GET EXPONENT AND DIVIDE BY NP */
3639 /* REDUCE EXPONENT SO RX NOT TOO LARGE OR SMALL. */
3644 /* USE SINGLE-PRECISION ROOT FOR FIRST APPROXIMATION */
3646 r__1
= exp(((float) (np
* ex
- xes
) * log((float) MP
.b
) -
3647 log((dabs(rx
)))) / (float) np
);
3648 mpcrm(&r__1
, &MP
.r
[i2
- 1]);
3650 /* SIGN OF APPROXIMATION SAME AS THAT OF X */
3652 MP
.r
[i2
- 1] = x
[1];
3654 /* RESTORE EXPONENT */
3658 /* CORRECT EXPONENT OF FIRST APPROXIMATION */
3662 /* SAVE T (NUMBER OF DIGITS) */
3666 /* START WITH SMALL T TO SAVE TIME */
3670 /* ENSURE THAT B**(T-1) .GE. 100 */
3672 if (MP
.b
< 10) MP
.t
= it
[MP
.b
- 1];
3673 if (MP
.t
> ts
) goto L160
;
3675 /* IT0 IS A NECESSARY SAFETY FACTOR */
3677 it0
= (MP
.t
+ 4) / 2;
3679 /* MAIN ITERATION LOOP */
3682 mppwr(&MP
.r
[i2
- 1], &np
, &MP
.r
[i3
- 1]);
3683 mpmul(&x
[1], &MP
.r
[i3
- 1], &MP
.r
[i3
- 1]);
3684 mpaddi(&MP
.r
[i3
- 1], &c_n1
, &MP
.r
[i3
- 1]);
3686 /* TEMPORARILY REDUCE T */
3689 MP
.t
= (MP
.t
+ it0
) / 2;
3690 mpmul(&MP
.r
[i2
- 1], &MP
.r
[i3
- 1], &MP
.r
[i3
- 1]);
3691 mpdivi(&MP
.r
[i3
- 1], &np
, &MP
.r
[i3
- 1]);
3696 mpsub(&MP
.r
[i2
- 1], &MP
.r
[i3
- 1], &MP
.r
[i2
- 1]);
3698 /* FOLLOWING LOOP ALMOST DOUBLES T (POSSIBLE BECAUSE
3699 * NEWTONS METHOD HAS 2ND ORDER CONVERGENCE).
3702 if (MP
.t
>= ts
) goto L140
;
3707 MP
.t
= (MP
.t
+ it0
) / 2;
3708 if (MP
.t
> ts3
) goto L130
;
3713 /* NOW R(I2) IS X**(-1/NP)
3714 * CHECK THAT NEWTON ITERATION WAS CONVERGING
3718 if (MP
.r
[i3
- 1] == 0 || (MP
.r
[i2
] - MP
.r
[i3
]) << 1 >= MP
.t
- it0
) {
3722 /* THE FOLLOWING MESSAGE MAY INDICATE THAT B**(T-1) IS TOO SMALL,
3723 * OR THAT THE INITIAL APPROXIMATION OBTAINED USING ALOG AND EXP
3724 * IS NOT ACCURATE ENOUGH.
3728 FPRINTF(stderr
, "*** ERROR OCCURRED IN MPROOT, NEWTON ITERATION NOT CONVERGING PROPERLY ***\n");
3737 if (*n
< 0) goto L170
;
3740 mppwr(&MP
.r
[i2
- 1], &i__1
, &MP
.r
[i2
- 1]);
3741 mpmul(&x
[1], &MP
.r
[i2
- 1], &y
[1]);
3745 mpstr(&MP
.r
[i2
- 1], &y
[1]);
3750 mpset(int *idecpl
, int *itmax2
, int *maxdr
)
3754 static int i
, k
, w
, i2
, w2
, wn
;
3756 /* SETS BASE (B) AND NUMBER OF DIGITS (T) TO GIVE THE
3757 * EQUIVALENT OF AT LEAST IDECPL DECIMAL DIGITS.
3758 * IDECPL SHOULD BE POSITIVE.
3759 * ITMAX2 IS THE DIMENSION OF ARRAYS USED FOR MP NUMBERS,
3760 * SO AN ERROR OCCURS IF THE COMPUTED T EXCEEDS ITMAX2 - 2.
3762 * MXR = MAXDR (DIMENSION OF R IN COMMON, .GE. T+4), AND
3763 * M = (W-1)/4 (MAXIMUM ALLOWABLE EXPONENT),
3764 * WHERE W IS THE LARGEST INTEGER OF THE FORM 2**K-1 WHICH IS
3765 * REPRESENTABLE IN THE MACHINE, K .LE. 47
3766 * THE COMPUTED B AND T SATISFY THE CONDITIONS
3767 * (T-1)*LN(B)/LN(10) .GE. IDECPL AND 8*B*B-1 .LE. W .
3768 * APPROXIMATELY MINIMAL T AND MAXIMAL B SATISFYING
3769 * THESE CONDITIONS ARE CHOSEN.
3770 * PARAMETERS IDECPL, ITMAX2 AND MAXDR ARE INTEGERS.
3771 * BEWARE - MPSET WILL CAUSE AN INTEGER OVERFLOW TO OCCUR
3772 * ****** IF WORDLENGTH IS LESS THAN 48 BITS.
3773 * IF THIS IS NOT ALLOWABLE, CHANGE THE DETERMINATION
3774 * OF W (DO 30 ... TO 30 W = WN) OR SET B, T, M,
3775 * AND MXR WITHOUT CALLING MPSET.
3781 /* DETERMINE LARGE REPRESENTABLE INTEGER W OF FORM 2**K - 1 */
3786 /* ON CYBER 76 HAVE TO FIND K .LE. 47, SO ONLY LOOP
3787 * 47 TIMES AT MOST. IF GENUINE INTEGER WORDLENGTH
3788 * EXCEEDS 47 BITS THIS RESTRICTION CAN BE RELAXED.
3791 for (i
= 1; i
<= 47; ++i
) {
3793 /* INTEGER OVERFLOW WILL EVENTUALLY OCCUR HERE
3794 * IF WORDLENGTH .LT. 48 BITS
3800 /* APPARENTLY REDUNDANT TESTS MAY BE NECESSARY ON SOME
3801 * MACHINES, DEPENDING ON HOW INTEGER OVERFLOW IS HANDLED
3804 if (wn
<= w
|| wn
<= w2
|| wn
<= 0) goto L40
;
3809 /* SET MAXIMUM EXPONENT TO (W-1)/4 */
3813 if (*idecpl
> 0) goto L60
;
3816 FPRINTF(stderr
, "*** IDECPL .LE. 0 IN CALL TO MPSET ***\n");
3822 /* B IS THE LARGEST POWER OF 2 SUCH THAT (8*B*B-1) .LE. W */
3826 MP
.b
= pow_ii(&c__2
, &i__1
);
3828 /* 2E0 BELOW ENSURES AT LEAST ONE GUARD DIGIT */
3830 MP
.t
= (int) ((float) (*idecpl
) * log((float)10.) / log((float) MP
.b
) +
3833 /* SEE IF T TOO LARGE FOR DIMENSION STATEMENTS */
3836 if (i2
<= *itmax2
) goto L80
;
3840 "ITMAX2 TOO SMALL IN CALL TO MPSET ***\n*** INCREASE ITMAX2 AND DIMENSIONS OF MP ARRAYS TO AT LEAST %d ***\n",
3846 /* REDUCE TO MAXIMUM ALLOWED BY DIMENSION STATEMENTS */
3850 /* CHECK LEGALITY OF B, T, M AND MXR (AT LEAST T+4) */
3853 mpchk(&c__1
, &c__4
);
3858 mpsin(int *x
, int *y
)
3862 static int i2
, i3
, ie
, xs
;
3863 static float rx
, ry
;
3865 /* RETURNS Y = SIN(X) FOR MP X AND Y,
3866 * METHOD IS TO REDUCE X TO (-1, 1) AND USE MPSIN1, SO
3867 * TIME IS O(M(T)T/LOG(T)).
3868 * DIMENSION OF R IN CALLING PROGRAM MUST BE AT LEAST 5T+12
3869 * CHECK LEGALITY OF B, T, M AND MXR
3872 --y
; /* Parameter adjustments */
3875 mpchk(&c__5
, &c__12
);
3876 i2
= (MP
.t
<< 2) + 11;
3877 if (x
[1] != 0) goto L20
;
3886 if (ie
<= 2) mpcmr(&x
[1], &rx
);
3888 mpabs(&x
[1], &MP
.r
[i2
- 1]);
3890 /* USE MPSIN1 IF ABS(X) .LE. 1 */
3892 if (mpcmpi(&MP
.r
[i2
- 1], &c__1
) > 0) goto L30
;
3894 mpsin1(&MP
.r
[i2
- 1], &y
[1], &c__1
);
3897 /* FIND ABS(X) MODULO 2PI (IT WOULD SAVE TIME IF PI WERE
3898 * PRECOMPUTED AND SAVED IN COMMON).
3899 * FOR INCREASED ACCURACY COMPUTE PI/4 USING MPART1
3903 i3
= (MP
.t
<< 1) + 7;
3904 mpart1(&c__5
, &MP
.r
[i3
- 1]);
3905 mpmuli(&MP
.r
[i3
- 1], &c__4
, &MP
.r
[i3
- 1]);
3906 mpart1(&c__239
, &y
[1]);
3907 mpsub(&MP
.r
[i3
- 1], &y
[1], &y
[1]);
3908 mpdiv(&MP
.r
[i2
- 1], &y
[1], &MP
.r
[i2
- 1]);
3909 mpdivi(&MP
.r
[i2
- 1], &c__8
, &MP
.r
[i2
- 1]);
3910 mpcmf(&MP
.r
[i2
- 1], &MP
.r
[i2
- 1]);
3912 /* SUBTRACT 1/2, SAVE SIGN AND TAKE ABS */
3914 mpaddq(&MP
.r
[i2
- 1], &c_n1
, &c__2
, &MP
.r
[i2
- 1]);
3915 xs
= -xs
* MP
.r
[i2
- 1];
3916 if (xs
== 0) goto L10
;
3919 mpmuli(&MP
.r
[i2
- 1], &c__4
, &MP
.r
[i2
- 1]);
3921 /* IF NOT LESS THAN 1, SUBTRACT FROM 2 */
3924 mpaddi(&MP
.r
[i2
- 1], &c_n2
, &MP
.r
[i2
- 1]);
3927 if (MP
.r
[i2
- 1] == 0) goto L10
;
3930 mpmuli(&MP
.r
[i2
- 1], &c__2
, &MP
.r
[i2
- 1]);
3932 /* NOW REDUCED TO FIRST QUADRANT, IF LESS THAN PI/4 USE
3933 * POWER SERIES, ELSE COMPUTE COS OF COMPLEMENT
3936 if (MP
.r
[i2
] > 0) goto L40
;
3938 mpmul(&MP
.r
[i2
- 1], &y
[1], &MP
.r
[i2
- 1]);
3939 mpsin1(&MP
.r
[i2
- 1], &y
[1], &c__1
);
3943 mpaddi(&MP
.r
[i2
- 1], &c_n2
, &MP
.r
[i2
- 1]);
3944 mpmul(&MP
.r
[i2
- 1], &y
[1], &MP
.r
[i2
- 1]);
3945 mpsin1(&MP
.r
[i2
- 1], &y
[1], &c__0
);
3951 /* CHECK THAT ABSOLUTE ERROR LESS THAN 0.01 IF ABS(X) .LE. 100
3952 * (IF ABS(X) IS LARGE THEN SINGLE-PRECISION SIN INACCURATE)
3955 if (dabs(rx
) > (float)100.) return;
3958 if ((r__1
= ry
- sin(rx
), dabs(r__1
)) < (float) 0.01) return;
3960 /* THE FOLLOWING MESSAGE MAY INDICATE THAT
3961 * B**(T-1) IS TOO SMALL.
3965 FPRINTF(stderr
, "*** ERROR OCCURRED IN MPSIN, RESULT INCORRECT ***\n");
3973 mpsin1(int *x
, int *y
, int *is
)
3977 static int i
, b2
, i2
, i3
, ts
;
3979 /* COMPUTES Y = SIN(X) IF IS.NE.0, Y = COS(X) IF IS.EQ.0,
3980 * USING TAYLOR SERIES. ASSUMES ABS(X) .LE. 1.
3981 * X AND Y ARE MP NUMBERS, IS AN INTEGER.
3982 * TIME IS O(M(T)T/LOG(T)). THIS COULD BE REDUCED TO
3983 * O(SQRT(T)M(T)) AS IN MPEXP1, BUT NOT WORTHWHILE UNLESS
3984 * T IS VERY LARGE. ASYMPTOTICALLY FASTER METHODS ARE
3985 * DESCRIBED IN THE REFERENCES GIVEN IN COMMENTS
3986 * TO MPATAN AND MPPIGL.
3987 * DIMENSION OF R IN CALLING PROGRAM MUST BE AT LEAST 3T+8
3988 * CHECK LEGALITY OF B, T, M AND MXR
3991 --y
; /* Parameter adjustments */
3994 mpchk(&c__3
, &c__8
);
3995 if (x
[1] != 0) goto L20
;
3997 /* SIN(0) = 0, COS(0) = 1 */
4001 if (*is
== 0) mpcim(&c__1
, &y
[1]);
4007 b2
= max(MP
.b
,64) << 1;
4008 mpmul(&x
[1], &x
[1], &MP
.r
[i3
- 1]);
4009 if (mpcmpi(&MP
.r
[i3
- 1], &c__1
) <= 0) goto L40
;
4012 FPRINTF(stderr
, "*** ABS(X) .GT. 1 IN CALL TO MPSIN1 ***\n");
4019 if (*is
== 0) mpcim(&c__1
, &MP
.r
[i2
- 1]);
4020 if (*is
!= 0) mpstr(&x
[1], &MP
.r
[i2
- 1]);
4025 if (*is
== 0) goto L50
;
4027 mpstr(&MP
.r
[i2
- 1], &y
[1]);
4030 /* POWER SERIES LOOP. REDUCE T IF POSSIBLE */
4033 MP
.t
= MP
.r
[i2
] + ts
+ 2;
4034 if (MP
.t
<= 2) goto L80
;
4036 MP
.t
= min(MP
.t
,ts
);
4038 /* PUT R(I3) FIRST IN CASE ITS DIGITS ARE MAINLY ZERO */
4040 mpmul(&MP
.r
[i3
- 1], &MP
.r
[i2
- 1], &MP
.r
[i2
- 1]);
4042 /* IF I*(I+1) IS NOT REPRESENTABLE AS AN INTEGER, THE FOLLOWING
4043 * DIVISION BY I*(I+1) HAS TO BE SPLIT UP.
4046 if (i
> b2
) goto L60
;
4048 i__1
= -i
* (i
+ 1);
4049 mpdivi(&MP
.r
[i2
- 1], &i__1
, &MP
.r
[i2
- 1]);
4054 mpdivi(&MP
.r
[i2
- 1], &i__1
, &MP
.r
[i2
- 1]);
4056 mpdivi(&MP
.r
[i2
- 1], &i__1
, &MP
.r
[i2
- 1]);
4061 mpadd2(&MP
.r
[i2
- 1], &y
[1], &y
[1], &y
[1], &c__0
);
4062 if (MP
.r
[i2
- 1] != 0) goto L50
;
4066 if (*is
== 0) mpaddi(&y
[1], &c__1
, &y
[1]);
4071 mpsinh(int *x
, int *y
)
4075 static int i2
, i3
, xs
;
4077 /* RETURNS Y = SINH(X) FOR MP NUMBERS X AND Y, X NOT TOO LARGE.
4078 * METHOD IS TO USE MPEXP OR MPEXP1, SPACE = 5T+12
4079 * SAVE SIGN OF X AND CHECK FOR ZERO, SINH(0) = 0
4082 --y
; /* Parameter adjustments */
4086 if (xs
!= 0) goto L10
;
4091 /* CHECK LEGALITY OF B, T, M AND MXR */
4094 mpchk(&c__5
, &c__12
);
4095 i3
= (MP
.t
<< 2) + 11;
4097 /* WORK WITH ABS(X) */
4099 mpabs(&x
[1], &MP
.r
[i3
- 1]);
4100 if (MP
.r
[i3
] <= 0) goto L20
;
4102 /* HERE ABS(X) .GE. 1, IF TOO LARGE MPEXP GIVES ERROR MESSAGE
4103 * INCREASE M TO AVOID OVERFLOW IF SINH(X) REPRESENTABLE
4107 mpexp(&MP
.r
[i3
- 1], &MP
.r
[i3
- 1]);
4108 mprec(&MP
.r
[i3
- 1], &y
[1]);
4109 mpsub(&MP
.r
[i3
- 1], &y
[1], &y
[1]);
4111 /* RESTORE M. IF RESULT OVERFLOWS OR UNDERFLOWS, MPDIVI AT
4112 * STATEMENT 30 WILL ACT ACCORDINGLY.
4118 /* HERE ABS(X) .LT. 1 SO USE MPEXP1 TO AVOID CANCELLATION */
4121 i2
= i3
- (MP
.t
+ 2);
4122 mpexp1(&MP
.r
[i3
- 1], &MP
.r
[i2
- 1]);
4123 mpaddi(&MP
.r
[i2
- 1], &c__2
, &MP
.r
[i3
- 1]);
4124 mpmul(&MP
.r
[i3
- 1], &MP
.r
[i2
- 1], &y
[1]);
4125 mpaddi(&MP
.r
[i2
- 1], &c__1
, &MP
.r
[i3
- 1]);
4126 mpdiv(&y
[1], &MP
.r
[i3
- 1], &y
[1]);
4128 /* DIVIDE BY TWO AND RESTORE SIGN */
4132 mpdivi(&y
[1], &i__1
, &y
[1]);
4137 mpsqrt(int *x
, int *y
)
4139 static int i
, i2
, iy3
;
4141 /* RETURNS Y = SQRT(X), USING SUBROUTINE MPROOT IF X .GT. 0.
4142 * DIMENSION OF R IN CALLING PROGRAM MUST BE AT LEAST 4T+10
4143 * (BUT Y(1) MAY BE R(3T+9)). X AND Y ARE MP NUMBERS.
4144 * CHECK LEGALITY OF B, T, M AND MXR
4147 --y
; /* Parameter adjustments */
4150 mpchk(&c__4
, &c__10
);
4152 /* MPROOT NEEDS 4T+10 WORDS, BUT CAN OVERLAP SLIGHTLY. */
4155 if (x
[1] < 0) goto L10
;
4156 else if (x
[1] == 0) goto L30
;
4161 FPRINTF(stderr
, "*** X NEGATIVE IN CALL TO SUBROUTINE MPSQRT ***\n");
4171 mproot(&x
[1], &c_n2
, &MP
.r
[i2
- 1]);
4173 mpmul(&x
[1], &MP
.r
[i2
- 1], &y
[1]);
4175 mpext(&i
, &iy3
, &y
[1]);
4180 mpstr(int *x
, int *y
)
4184 static int i
, j
, t2
;
4186 /* SETS Y = X FOR MP X AND Y.
4187 * SEE IF X AND Y HAVE THE SAME ADDRESS (THEY OFTEN DO)
4190 --y
; /* Parameter adjustments */
4195 if (j
== x
[1]) goto L10
;
4197 /* HERE X(1) AND Y(1) MUST HAVE THE SAME ADDRESS */
4202 /* HERE X(1) AND Y(1) HAVE DIFFERENT ADDRESSES */
4207 /* NO NEED TO MOVE X(2), ... IF X(1) = 0 */
4213 for (i
= 2; i
<= i__1
; ++i
) y
[i
] = x
[i
];
4218 mpsub(int *x
, int *y
, int *z
)
4222 /* SUBTRACTS Y FROM X, FORMING RESULT IN Z, FOR MP X, Y AND Z.
4223 * FOUR GUARD DIGITS ARE USED, AND THEN R*-ROUNDING
4226 --z
; /* Parameter adjustments */
4231 mpadd2(&x
[1], &y
[1], &z
[1], y1
, &c__0
);
4236 mptanh(int *x
, int *y
)
4242 /* RETURNS Y = TANH(X) FOR MP NUMBERS X AND Y,
4243 * USING MPEXP OR MPEXP1, SPACE = 5T+12
4246 --y
; /* Parameter adjustments */
4249 if (x
[1] != 0) goto L10
;
4256 /* CHECK LEGALITY OF B, T, M AND MXR */
4259 mpchk(&c__5
, &c__12
);
4260 i2
= (MP
.t
<< 2) + 11;
4262 /* SAVE SIGN AND WORK WITH ABS(X) */
4265 mpabs(&x
[1], &MP
.r
[i2
- 1]);
4267 /* SEE IF ABS(X) SO LARGE THAT RESULT IS +-1 */
4269 r__1
= (float) MP
.t
* (float).5 * log((float) MP
.b
);
4270 mpcrm(&r__1
, &y
[1]);
4271 if (mpcomp(&MP
.r
[i2
- 1], &y
[1]) <= 0) goto L20
;
4273 /* HERE ABS(X) IS VERY LARGE */
4278 /* HERE ABS(X) NOT SO LARGE */
4281 mpmuli(&MP
.r
[i2
- 1], &c__2
, &MP
.r
[i2
- 1]);
4282 if (MP
.r
[i2
] <= 0) goto L30
;
4284 /* HERE ABS(X) .GE. 1/2 SO USE MPEXP */
4286 mpexp(&MP
.r
[i2
- 1], &MP
.r
[i2
- 1]);
4287 mpaddi(&MP
.r
[i2
- 1], &c_n1
, &y
[1]);
4288 mpaddi(&MP
.r
[i2
- 1], &c__1
, &MP
.r
[i2
- 1]);
4289 mpdiv(&y
[1], &MP
.r
[i2
- 1], &y
[1]);
4292 /* HERE ABS(X) .LT. 1/2, SO USE MPEXP1 TO AVOID CANCELLATION */
4295 mpexp1(&MP
.r
[i2
- 1], &MP
.r
[i2
- 1]);
4296 mpaddi(&MP
.r
[i2
- 1], &c__2
, &y
[1]);
4297 mpdiv(&MP
.r
[i2
- 1], &y
[1], &y
[1]);
4310 /* CALLED ON MULTIPLE-PRECISION UNDERFLOW, IE WHEN THE
4311 * EXPONENT OF MP NUMBER X WOULD BE LESS THAN -M.
4312 * SINCE M MAY HAVE BEEN OVERWRITTEN, CHECK B, T, M ETC.
4315 --x
; /* Parameter adjustments */
4317 mpchk(&c__1
, &c__4
);
4319 /* THE UNDERFLOWING NUMBER IS SET TO ZERO
4320 * AN ALTERNATIVE WOULD BE TO CALL MPMINR (X) AND RETURN,
4321 * POSSIBLY UPDATING A COUNTER AND TERMINATING EXECUTION
4322 * AFTER A PRESET NUMBER OF UNDERFLOWS. ACTION COULD EASILY
4323 * BE DETERMINED BY A FLAG IN LABELLED COMMON.
4331 mppow_di(double *ap
, int *bp
)
4342 if (x
== 0) return(pow
);
4347 if (n
& 01) pow
*= x
;
4348 if (n
>>= 1) x
*= x
;
4358 pow_ii(int *ap
, int *bp
)
4368 if (n
& 01) pow
*= x
;
4369 if (n
>>= 1) x
*= x
;
4379 mppow_ri(float *ap
, int *bp
)
4390 if (x
== 0) return(pow
);
4395 if (n
& 01) pow
*= x
;
4396 if (n
>>= 1) x
*= x
;