2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these libraries and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $XConsortium: mp.c /main/3 1995/11/01 12:42:08 rswiston $ */
26 * Contains the actual math functions. *
28 * (c) Copyright 1993, 1994 Hewlett-Packard Company *
29 * (c) Copyright 1993, 1994 International Business Machines Corp. *
30 * (c) Copyright 1993, 1994 Sun Microsystems, Inc. *
31 * (c) Copyright 1993, 1994 Novell, Inc. *
34 /* This maths library is based on the MP multi-precision floating-point
35 * arithmetic package originally written in FORTRAN by Richard Brent,
36 * Computer Centre, Australian National University in the 1970's.
38 * It has been converted from FORTRAN into C using the freely available
39 * f2c translator, available via netlib on research.att.com.
41 * The subsequently converted C code has then been tidied up, mainly to
42 * remove any dependencies on the libI77 and libF77 support libraries.
44 * FOR A GENERAL DESCRIPTION OF THE PHILOSOPHY AND DESIGN OF MP,
45 * SEE - R. P. BRENT, A FORTRAN MULTIPLE-PRECISION ARITHMETIC
46 * PACKAGE, ACM TRANS. MATH. SOFTWARE 4 (MARCH 1978), 57-70.
47 * SOME ADDITIONAL DETAILS ARE GIVEN IN THE SAME ISSUE, 71-81.
48 * FOR DETAILS OF THE IMPLEMENTATION, CALLING SEQUENCES ETC. SEE
58 int b, t, m, mxr, r[MP_SIZE] ;
61 /* Table of constant values */
69 static int c__12 = 12 ;
70 static int c_n2 = -2 ;
71 static int c__10 = 10 ;
72 static int c__32 = 32 ;
75 static int c__14 = 14 ;
76 static int c_n1 = -1 ;
77 static int c__239 = 239 ;
79 static int c__16 = 16 ;
81 extern char *mpstrs[] ; /* MP errors (visible with -D option). */
82 extern char *vstrs[] ; /* Various strings. */
84 extern Vars v ; /* Calctool variables and options. */
91 /* SETS Y = ABS(X) FOR MP NUMBERS X AND Y */
93 --y ; /* Parameter adjustments */
103 mpadd(int *x, int *y, int *z)
106 /* ADDS X AND Y, FORMING RESULT IN Z, WHERE X, Y AND Z ARE MP
107 * NUMBERS. FOUR GUARD DIGITS ARE USED, AND THEN R*-ROUNDING.
110 --z ; /* Parameter adjustments */
114 mpadd2(&x[1], &y[1], &z[1], &y[1], &c__0) ;
120 mpadd2(int *x, int *y, int *z, int *y1, int *trunc)
125 static int ed, re, rs, med ;
127 /* CALLED BY MPADD, MPSUB ETC.
128 * X, Y AND Z ARE MP NUMBERS, Y1 AND TRUNC ARE INTEGERS.
129 * TO FORCE CALL BY REFERENCE RATHER THAN VALUE/RESULT, Y1 IS
130 * DECLARED AS AN ARRAY, BUT ONLY Y1(1) IS EVER USED.
131 * SETS Z = X + Y1(1)*ABS(Y), WHERE Y1(1) = +- Y(1).
132 * IF TRUNC.EQ.0 R*-ROUNDING IS USED, OTHERWISE TRUNCATION.
133 * R*-ROUNDING IS DEFINED IN KUKI AND CODI, COMM. ACM
134 * 16(1973), 223. (SEE ALSO BRENT, IEEE TC-22(1973), 601.)
135 * CHECK FOR X OR Y ZERO
138 --y1 ; /* Parameter adjustments */
143 if (x[1] != 0) goto L20 ;
145 /* X = 0 OR NEGLIGIBLE, SO RESULT = +-Y */
148 mpstr(&y[1], &z[1]) ;
153 if (y1[1] != 0) goto L40 ;
155 /* Y = 0 OR NEGLIGIBLE, SO RESULT = X */
158 mpstr(&x[1], &z[1]) ;
165 if (C_abs(s) <= 1) goto L60 ;
167 mpchk(&c__1, &c__4) ;
170 _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_ADD2A]) ;
171 _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_ADD2B]) ;
178 /* COMPARE EXPONENTS */
183 if (ed < 0) goto L90 ;
184 else if (ed == 0) goto L70 ;
187 /* EXPONENTS EQUAL SO COMPARE SIGNS, THEN FRACTIONS IF NEC. */
190 if (s > 0) goto L100 ;
193 for (j = 1; j <= i__1; ++j)
195 if ((i__2 = x[j + 2] - y[j + 2]) < 0) goto L100 ;
196 else if (i__2 == 0) continue ;
205 /* HERE EXPONENT(Y) .GE. EXPONENT(X) */
208 if (med > MP.t) goto L10 ;
213 mpadd3(&x[1], &y[1], &s, &med, &re) ;
215 /* NORMALIZE, ROUND OR TRUNCATE, AND RETURN */
218 mpnzr(&rs, &re, &z[1], trunc) ;
221 /* ABS(X) .GT. ABS(Y) */
224 if (med > MP.t) goto L30 ;
229 mpadd3(&y[1], &x[1], &s, &med, &re) ;
235 mpadd3(int *x, int *y, int *s, int *med, int *re)
239 static int c, i, j, i2, i2p, ted ;
241 /* CALLED BY MPADD2, DOES INNER LOOPS OF ADDITION */
243 --y ; /* Parameter adjustments */
251 /* CLEAR GUARD DIGITS TO RIGHT OF X DIGITS */
254 if (i <= ted) goto L20 ;
261 if (*s < 0) goto L130 ;
263 /* HERE DO ADDITION, EXPONENT(Y) .GE. EXPONENT(X) */
265 if (i <= MP.t) goto L40 ;
269 MP.r[i - 1] = x[j + 2] ;
271 if (i > MP.t) goto L30 ;
274 if (i <= *med) goto L60 ;
277 c = y[i + 2] + x[j + 2] + c ;
278 if (c < MP.b) goto L50 ;
280 /* CARRY GENERATED HERE */
282 MP.r[i - 1] = c - MP.b ;
287 /* NO CARRY GENERATED HERE */
296 if (i <= 0) goto L90 ;
299 if (c < MP.b) goto L70 ;
310 /* NO CARRY POSSIBLE HERE */
315 MP.r[i - 1] = y[i + 2] ;
322 /* MUST SHIFT RIGHT HERE AS CARRY OFF END */
326 for (j = 2 ; j <= i__1 ; ++j)
329 MP.r[i] = MP.r[i - 1] ;
335 /* HERE DO SUBTRACTION, ABS(Y) .GT. ABS(X) */
339 MP.r[i - 1] = c - x[j + 2] ;
341 if (MP.r[i - 1] >= 0) goto L120 ;
343 /* BORROW GENERATED HERE */
346 MP.r[i - 1] += MP.b ;
352 if (i > MP.t) goto L110 ;
355 if (i <= *med) goto L160 ;
358 c = y[i + 2] + c - x[j + 2] ;
359 if (c >= 0) goto L150 ;
361 /* BORROW GENERATED HERE */
363 MP.r[i - 1] = c + MP.b ;
368 /* NO BORROW GENERATED HERE */
380 if (c >= 0) goto L70 ;
382 MP.r[i - 1] = c + MP.b ;
390 mpaddi(int *x, int *iy, int *z)
393 /* ADDS MULTIPLE-PRECISION X TO INTEGER IY
394 * GIVING MULTIPLE-PRECISION Z.
395 * DIMENSION OF R IN CALLING PROGRAM MUST BE
396 * AT LEAST 2T+6 (BUT Z(1) MAY BE R(T+5)).
397 * DIMENSION R(6) BECAUSE RALPH COMPILER ON UNIVAC 1100 COMPUTERS
398 * OBJECTS TO DIMENSION R(1).
399 * CHECK LEGALITY OF B, T, M AND MXR
402 --z ; /* Parameter adjustments */
405 mpchk(&c__2, &c__6) ;
406 mpcim(iy, &MP.r[MP.t + 4]) ;
407 mpadd(&x[1], &MP.r[MP.t + 4], &z[1]) ;
413 mpaddq(int *x, int *i, int *j, int *y)
416 /* ADDS THE RATIONAL NUMBER I/J TO MP NUMBER X, MP RESULT IN Y
417 * DIMENSION OF R MUST BE AT LEAST 2T+6
418 * CHECK LEGALITY OF B, T, M AND MXR
421 --y ; /* Parameter adjustments */
424 mpchk(&c__2, &c__6) ;
425 mpcqm(i, j, &MP.r[MP.t + 4]) ;
426 mpadd(&x[1], &MP.r[MP.t + 4], &y[1]) ;
432 mpart1(int *n, int *y)
436 static int i, b2, i2, id, ts ;
438 /* COMPUTES MP Y = ARCTAN(1/N), ASSUMING INTEGER N .GT. 1.
439 * USES SERIES ARCTAN(X) = X - X**3/3 + X**5/5 - ...
440 * DIMENSION OF R IN CALLING PROGRAM MUST BE
442 * CHECK LEGALITY OF B, T, M AND MXR
445 --y ; /* Parameter adjustments */
447 mpchk(&c__2, &c__6) ;
448 if (*n > 1) goto L20 ;
450 if (v->MPerrors) _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_PART1]) ;
460 /* SET SUM TO X = 1/N */
462 mpcqm(&c__1, n, &y[1]) ;
464 /* SET ADDITIVE TERM TO X */
466 mpstr(&y[1], &MP.r[i2 - 1]) ;
470 /* ASSUME AT LEAST 16-BIT WORD. */
473 if (*n < b2) id = b2 * 7 * b2 / (*n * *n) ;
475 /* MAIN LOOP. FIRST REDUCE T IF POSSIBLE */
478 MP.t = ts + 2 + MP.r[i2] - y[2] ;
479 if (MP.t < 2) goto L60 ;
481 MP.t = min(MP.t,ts) ;
483 /* IF (I+2)*N**2 IS NOT REPRESENTABLE AS AN INTEGER THE DIVISION
484 * FOLLOWING HAS TO BE PERFORMED IN SEVERAL STEPS.
487 if (i >= id) goto L40 ;
490 i__2 = (i + 2) * *n * *n ;
491 mpmulq(&MP.r[i2 - 1], &i__1, &i__2, &MP.r[i2 - 1]) ;
497 mpmulq(&MP.r[i2 - 1], &i__1, &i__2, &MP.r[i2 - 1]) ;
498 mpdivi(&MP.r[i2 - 1], n, &MP.r[i2 - 1]) ;
499 mpdivi(&MP.r[i2 - 1], n, &MP.r[i2 - 1]) ;
508 /* ADD TO SUM, USING MPADD2 (FASTER THAN MPADD) */
510 mpadd2(&MP.r[i2 - 1], &y[1], &y[1], &y[1], &c__0) ;
511 if (MP.r[i2 - 1] != 0) goto L30 ;
520 mpasin(int *x, int *y)
526 /* RETURNS Y = ARCSIN(X), ASSUMING ABS(X) .LE. 1,
527 * FOR MP NUMBERS X AND Y.
528 * Y IS IN THE RANGE -PI/2 TO +PI/2.
529 * METHOD IS TO USE MPATAN, SO TIME IS O(M(T)T).
530 * DIMENSION OF R MUST BE AT LEAST 5T+12
531 * CHECK LEGALITY OF B, T, M AND MXR
534 --y ; /* Parameter adjustments */
537 mpchk(&c__5, &c__12) ;
538 i3 = (MP.t << 2) + 11 ;
539 if (x[1] == 0) goto L30 ;
541 if (x[2] <= 0) goto L40 ;
543 /* HERE ABS(X) .GE. 1. SEE IF X = +-1 */
545 mpcim(&x[1], &MP.r[i3 - 1]) ;
546 if (mpcomp(&x[1], &MP.r[i3 - 1]) != 0) goto L10 ;
548 /* X = +-1 SO RETURN +-PI/2 */
551 i__1 = MP.r[i3 - 1] << 1 ;
552 mpdivi(&y[1], &i__1, &y[1]) ;
556 if (v->MPerrors) _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_ASIN]) ;
564 /* HERE ABS(X) .LT. 1 SO USE ARCTAN(X/SQRT(1 - X**2)) */
567 i2 = i3 - (MP.t + 2) ;
568 mpcim(&c__1, &MP.r[i2 - 1]) ;
569 mpstr(&MP.r[i2 - 1], &MP.r[i3 - 1]) ;
570 mpsub(&MP.r[i2 - 1], &x[1], &MP.r[i2 - 1]) ;
571 mpadd(&MP.r[i3 - 1], &x[1], &MP.r[i3 - 1]) ;
572 mpmul(&MP.r[i2 - 1], &MP.r[i3 - 1], &MP.r[i3 - 1]) ;
573 mproot(&MP.r[i3 - 1], &c_n2, &MP.r[i3 - 1]) ;
574 mpmul(&x[1], &MP.r[i3 - 1], &y[1]) ;
575 mpatan(&y[1], &y[1]) ;
581 mpatan(int *x, int *y)
586 static int i, q, i2, i3, ie, ts ;
587 static float rx, ry ;
589 /* RETURNS Y = ARCTAN(X) FOR MP X AND Y, USING AN O(T.M(T)) METHOD
590 * WHICH COULD EASILY BE MODIFIED TO AN O(SQRT(T)M(T))
591 * METHOD (AS IN MPEXP1). Y IS IN THE RANGE -PI/2 TO +PI/2.
592 * FOR AN ASYMPTOTICALLY FASTER METHOD, SEE - FAST MULTIPLE-
593 * PRECISION EVALUATION OF ELEMENTARY FUNCTIONS
594 * (BY R. P. BRENT), J. ACM 23 (1976), 242-251,
595 * AND THE COMMENTS IN MPPIGL.
596 * DIMENSION OF R IN CALLING PROGRAM MUST BE AT LEAST 5T+12
597 * CHECK LEGALITY OF B, T, M AND MXR
600 --y ; /* Parameter adjustments */
603 mpchk(&c__5, &c__12) ;
613 mpstr(&x[1], &MP.r[i3 - 1]) ;
615 if (ie <= 2) mpcmr(&x[1], &rx) ;
619 /* REDUCE ARGUMENT IF NECESSARY BEFORE USING SERIES */
622 if (MP.r[i3] < 0) goto L30 ;
624 if (MP.r[i3] == 0 && (MP.r[i3 + 1] + 1) << 1 <= MP.b)
628 mpmul(&MP.r[i3 - 1], &MP.r[i3 - 1], &y[1]) ;
629 mpaddi(&y[1], &c__1, &y[1]) ;
630 mpsqrt(&y[1], &y[1]) ;
631 mpaddi(&y[1], &c__1, &y[1]) ;
632 mpdiv(&MP.r[i3 - 1], &y[1], &MP.r[i3 - 1]) ;
635 /* USE POWER SERIES NOW ARGUMENT IN (-0.5, 0.5) */
638 mpstr(&MP.r[i3 - 1], &y[1]) ;
639 mpmul(&MP.r[i3 - 1], &MP.r[i3 - 1], &MP.r[i2 - 1]) ;
643 /* SERIES LOOP. REDUCE T IF POSSIBLE. */
646 MP.t = ts + 2 + MP.r[i3] ;
647 if (MP.t <= 2) goto L50 ;
649 MP.t = min(MP.t,ts) ;
650 mpmul(&MP.r[i3 - 1], &MP.r[i2 - 1], &MP.r[i3 - 1]) ;
653 mpmulq(&MP.r[i3 - 1], &i__1, &i__2, &MP.r[i3 - 1]) ;
656 mpadd(&y[1], &MP.r[i3 - 1], &y[1]) ;
657 if (MP.r[i3 - 1] != 0) goto L40 ;
659 /* RESTORE T, CORRECT FOR ARGUMENT REDUCTION, AND EXIT */
663 mpmuli(&y[1], &q, &y[1]) ;
665 /* CHECK THAT RELATIVE ERROR LESS THAN 0.01 UNLESS EXPONENT
666 * OF X IS LARGE (WHEN ATAN MIGHT NOT WORK)
672 if ((r__1 = ry - atan(rx), dabs(r__1)) < dabs(ry) * (float).01)
675 /* THE FOLLOWING MESSAGE MAY INDICATE THAT B**(T-1) IS TOO SMALL. */
677 if (v->MPerrors) _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_ATAN]) ;
685 mpcdm(double *dx, int *z)
689 static int i, k, i2, ib, ie, re, tp, rs ;
690 static double db, dj ;
692 /* CONVERTS DOUBLE-PRECISION NUMBER DX TO MULTIPLE-PRECISION Z.
693 * SOME NUMBERS WILL NOT CONVERT EXACTLY ON MACHINES
694 * WITH BASE OTHER THAN TWO, FOUR OR SIXTEEN.
695 * THIS ROUTINE IS NOT CALLED BY ANY OTHER ROUTINE IN MP,
696 * SO MAY BE OMITTED IF DOUBLE-PRECISION IS NOT AVAILABLE.
697 * CHECK LEGALITY OF B, T, M AND MXR
700 --z ; /* Parameter adjustments */
702 mpchk(&c__1, &c__4) ;
707 if (*dx < 0.) goto L20 ;
708 else if (*dx == 0) goto L10 ;
711 /* IF DX = 0D0 RETURN 0 */
734 if (dj < 1.) goto L60 ;
736 /* INCREASE IE AND DIVIDE DJ BY 16. */
743 if (dj >= .0625) goto L70 ;
749 /* NOW DJ IS DY DIVIDED BY SUITABLE POWER OF 16
756 /* DB = DFLOAT(B) IS NOT ANSI STANDARD SO USE FLOAT AND DBLE */
758 db = (double) ((float) MP.b) ;
760 /* CONVERSION LOOP (ASSUME DOUBLE-PRECISION OPS. EXACT) */
763 for (i = 1; i <= i__1; ++i)
766 MP.r[i - 1] = (int) dj ;
767 dj -= (double) ((float) MP.r[i - 1]) ;
770 /* NORMALIZE RESULT */
772 mpnzr(&rs, &re, &z[1], &c__0) ;
776 i__1 = MP.b * 7 * MP.b ;
777 ib = max(i__1, 32767) / 16 ;
780 /* NOW MULTIPLY BY 16**IE */
782 if (ie < 0) goto L90 ;
783 else if (ie == 0) goto L130 ;
789 for (i = 1; i <= i__1; ++i)
792 if (tp <= ib && tp != MP.b && i < k) continue ;
793 mpdivi(&z[1], &tp, &z[1]) ;
800 for (i = 1; i <= i__1; ++i)
803 if (tp <= ib && tp != MP.b && i < ie) continue ;
804 mpmuli(&z[1], &tp, &z[1]) ;
814 mpchk(int *i, int *j)
818 /* CHECKS LEGALITY OF B, T, M AND MXR.
819 * THE CONDITION ON MXR (THE DIMENSION OF R IN COMMON) IS THAT
823 /* CHECK LEGALITY OF B, T AND M */
825 if (MP.b > 1) goto L40 ;
829 _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_CHKC]) ;
830 _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_CHKD]) ;
835 if (MP.t > 1) goto L60 ;
839 _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_CHKE]) ;
840 _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_CHKF]) ;
845 if (MP.m > MP.t) goto L80 ;
849 _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_CHKG]) ;
850 _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_CHKH]) ;
854 /* 8*B*B-1 SHOULD BE REPRESENTABLE, IF NOT WILL OVERFLOW
855 * AND MAY BECOME NEGATIVE, SO CHECK FOR THIS
859 ib = (MP.b << 2) * MP.b - 1 ;
860 if (ib > 0 && (ib << 1) + 1 > 0) goto L100 ;
863 _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_CHKI]) ;
867 /* CHECK THAT SPACE IN COMMON IS SUFFICIENT */
870 mx = *i * MP.t + *j ;
871 if (MP.mxr >= mx) return ;
873 /* HERE COMMON IS TOO SMALL, SO GIVE ERROR MESSAGE. */
879 _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_CHKJ]) ;
880 _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_CHKL]) ;
881 msg = (char *) XtMalloc(strlen( mpstrs[(int) MP_CHKM]) + 200);
882 sprintf(msg, mpstrs[(int) MP_CHKM], *i, *j, mx) ;
883 _DtSimpleError (v->appname, DtWarning, NULL, msg);
884 sprintf(msg, mpstrs[(int) MP_CHKN], MP.mxr, MP.t) ;
885 _DtSimpleError (v->appname, DtWarning, NULL, msg);
895 mpcim(int *ix, int *z)
901 /* CONVERTS INTEGER IX TO MULTIPLE-PRECISION Z.
902 * CHECK LEGALITY OF B, T, M AND MXR
905 --z ; /* Parameter adjustments */
907 mpchk(&c__1, &c__4) ;
909 if (n < 0) goto L20 ;
910 else if (n == 0) goto L10 ;
925 /* SET EXPONENT TO T */
933 for (i = 2; i <= i__1; ++i) z[i + 1] = 0 ;
939 /* NORMALIZE BY CALLING MPMUL2 */
941 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 */
964 mpchk(&c__1, &c__4) ;
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)
974 *dz = db * *dz + (double) ((float) x[i + 2]) ;
977 /* CHECK IF FULL DOUBLE-PRECISION ACCURACY ATTAINED */
981 /* TEST BELOW NOT ALWAYS EQUIVALENT TO - IF (DZ2.LE.DZ) GO TO 20,
982 * FOR EXAMPLE ON CYBER 76.
984 if (dz2 - *dz <= 0.) goto L20 ;
987 /* NOW ALLOW FOR EXPONENT */
991 *dz *= mppow_di(&db, &i__1) ;
993 /* CHECK REASONABLENESS OF RESULT. */
995 if (*dz <= 0.) goto L30 ;
997 /* LHS SHOULD BE .LE. 0.5 BUT ALLOW FOR SOME ERROR IN DLOG */
999 if ((d__1 = (double) ((float) x[2]) - (log(*dz) / log((double)
1000 ((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.
1011 if (v->MPerrors) _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_CMD]) ;
1019 mpcmf(int *x, int *y)
1024 static int x2, il, ip, xs ;
1026 /* FOR MP X AND Y, RETURNS FRACTIONAL PART OF X IN Y,
1027 * I.E., Y = X - INTEGER PART OF X (TRUNCATED TOWARDS 0).
1030 --y ; /* Parameter adjustments */
1033 if (x[1] != 0) goto L20 ;
1035 /* RETURN 0 IF X = 0 */
1044 /* RETURN 0 IF EXPONENT SO LARGE THAT NO FRACTIONAL PART */
1046 if (x2 >= MP.t) goto L10 ;
1048 /* IF EXPONENT NOT POSITIVE CAN RETURN X */
1050 if (x2 > 0) goto L30 ;
1052 mpstr(&x[1], &y[1]) ;
1055 /* CLEAR ACCUMULATOR */
1059 for (i = 1; i <= i__1; ++i) MP.r[i - 1] = 0 ;
1063 /* MOVE FRACTIONAL PART OF X TO ACCUMULATOR */
1066 for (i = il; i <= i__1; ++i) MP.r[i - 1] = x[i + 2] ;
1068 for (i = 1; i <= 4; ++i)
1075 /* NORMALIZE RESULT AND RETURN */
1077 mpnzr(&xs, &x2, &y[1], &c__1) ;
1083 mpcmi(int *x, int *iz)
1087 static int i, j, k, j1, x2, kx, xs, izs ;
1089 /* CONVERTS MULTIPLE-PRECISION X TO INTEGER IZ,
1090 * ASSUMING THAT X NOT TOO LARGE (ELSE USE MPCMIM).
1091 * X IS TRUNCATED TOWARDS ZERO.
1092 * IF INT(X)IS TOO LARGE TO BE REPRESENTED AS A SINGLE-
1093 * PRECISION INTEGER, IZ IS RETURNED AS ZERO. THE USER
1094 * MAY CHECK FOR THIS POSSIBILITY BY TESTING IF
1095 * ((X(1).NE.0).AND.(X(2).GT.0).AND.(IZ.EQ.0)) IS TRUE ON
1096 * RETURN FROM MPCMI.
1099 --x ; /* Parameter adjustments */
1103 if (xs == 0) return ;
1105 if (x[2] <= 0) return ;
1109 for (i = 1; i <= i__1; ++i)
1113 if (i <= MP.t) *iz += x[i + 2] ;
1115 /* CHECK FOR SIGNS OF INTEGER OVERFLOW */
1117 if (*iz <= 0 || *iz <= izs) goto L30 ;
1120 /* CHECK THAT RESULT IS CORRECT (AN UNDETECTED OVERFLOW MAY
1126 for (i = 1; i <= i__1; ++i)
1131 if (k <= MP.t) kx = x[k + 2] ;
1132 if (kx != j - MP.b * j1) goto L30 ;
1135 if (j != 0) goto L30 ;
1137 /* RESULT CORRECT SO RESTORE SIGN AND RETURN */
1142 /* HERE OVERFLOW OCCURRED (OR X WAS UNNORMALIZED), SO
1153 mpcmim(int *x, int *y)
1159 /* RETURNS Y = INTEGER PART OF X (TRUNCATED TOWARDS 0), FOR MP X AND Y.
1160 * USE IF Y TOO LARGE TO BE REPRESENTABLE AS A SINGLE-PRECISION INTEGER.
1161 * (ELSE COULD USE MPCMI).
1162 * CHECK LEGALITY OF B, T, M AND MXR
1165 --y ; /* Parameter adjustments */
1168 mpchk(&c__1, &c__4) ;
1169 mpstr(&x[1], &y[1]) ;
1170 if (y[1] == 0) return ;
1174 /* IF EXPONENT LARGE ENOUGH RETURN Y = X */
1176 if (il > MP.t) return ;
1178 /* IF EXPONENT SMALL ENOUGH RETURN ZERO */
1180 if (il > 1) goto L10 ;
1185 /* SET FRACTION TO ZERO */
1189 for (i = il; i <= i__1; ++i) y[i + 2] = 0 ;
1195 mpcmpi(int *x, int *i)
1199 /* COMPARES MP NUMBER X WITH INTEGER I, RETURNING
1203 * DIMENSION OF R IN COMMON AT LEAST 2T+6
1204 * CHECK LEGALITY OF B, T, M AND MXR
1207 --x ; /* Parameter adjustments */
1209 mpchk(&c__2, &c__6) ;
1211 /* CONVERT I TO MULTIPLE-PRECISION AND COMPARE */
1213 mpcim(i, &MP.r[MP.t + 4]) ;
1214 ret_val = mpcomp(&x[1], &MP.r[MP.t + 4]) ;
1220 mpcmpr(int *x, float *ri)
1224 /* COMPARES MP NUMBER X WITH REAL NUMBER RI, RETURNING
1228 * DIMENSION OF R IN COMMON AT LEAST 2T+6
1229 * CHECK LEGALITY OF B, T, M AND MXR
1232 --x ; /* Parameter adjustments */
1234 mpchk(&c__2, &c__6) ;
1236 /* CONVERT RI TO MULTIPLE-PRECISION AND COMPARE */
1238 mpcrm(ri, &MP.r[MP.t + 4]) ;
1239 ret_val = mpcomp(&x[1], &MP.r[MP.t + 4]) ;
1245 mpcmr(int *x, float *rz)
1251 static float rb, rz2 ;
1253 /* CONVERTS MULTIPLE-PRECISION X TO SINGLE-PRECISION RZ.
1254 * ASSUMES X IN ALLOWABLE RANGE. THERE IS SOME LOSS OF
1255 * ACCURACY IF THE EXPONENT IS LARGE.
1256 * CHECK LEGALITY OF B, T, M AND MXR
1259 --x ; /* Parameter adjustments */
1261 mpchk(&c__1, &c__4) ;
1263 if (x[1] == 0) return ;
1267 for (i = 1; i <= i__1; ++i)
1269 *rz = rb * *rz + (float) x[i + 2] ;
1272 /* CHECK IF FULL SINGLE-PRECISION ACCURACY ATTAINED */
1274 rz2 = *rz + (float) 1.0 ;
1275 if (rz2 <= *rz) goto L20 ;
1278 /* NOW ALLOW FOR EXPONENT */
1282 *rz *= mppow_ri(&rb, &i__1) ;
1284 /* CHECK REASONABLENESS OF RESULT */
1286 if (*rz <= (float)0.) goto L30 ;
1288 /* LHS SHOULD BE .LE. 0.5, BUT ALLOW FOR SOME ERROR IN ALOG */
1290 if ((r__1 = (float) x[2] - (log(*rz) / log((float) MP.b) + (float).5),
1291 dabs(r__1)) > (float).6)
1294 if (x[1] < 0) *rz = -(double)(*rz) ;
1297 /* FOLLOWING MESSAGE INDICATES THAT X IS TOO LARGE OR SMALL -
1298 * TRY USING MPCMRE INSTEAD.
1302 if (v->MPerrors) _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_CMR]) ;
1310 mpcomp(int *x, int *y)
1312 int ret_val, i__1, i__2 ;
1316 /* COMPARES THE MULTIPLE-PRECISION NUMBERS X AND Y,
1317 * RETURNING +1 IF X .GT. Y,
1319 * AND 0 IF X .EQ. Y.
1322 --y ; /* Parameter adjustments */
1325 if ((i__1 = x[1] - y[1]) < 0) goto L10 ;
1326 else if (i__1 == 0) goto L30 ;
1341 /* SIGN(X) = SIGN(Y), SEE IF ZERO */
1344 if (x[1] != 0) goto L40 ;
1351 /* HAVE TO COMPARE EXPONENTS AND FRACTIONS */
1356 for (i = 2; i <= i__1; ++i)
1358 if ((i__2 = x[i] - y[i]) < 0) goto L60 ;
1359 else if (i__2 == 0) continue ;
1368 /* ABS(X) .LT. ABS(Y) */
1374 /* ABS(X) .GT. ABS(Y) */
1383 mpcos(int *x, int *y)
1387 /* RETURNS Y = COS(X) FOR MP X AND Y, USING MPSIN AND MPSIN1.
1388 * DIMENSION OF R IN COMMON AT LEAST 5T+12.
1391 --y ; /* Parameter adjustments */
1394 if (x[1] != 0) goto L10 ;
1398 mpcim(&c__1, &y[1]) ;
1401 /* CHECK LEGALITY OF B, T, M AND MXR */
1404 mpchk(&c__5, &c__12) ;
1405 i2 = MP.t * 3 + 12 ;
1407 /* SEE IF ABS(X) .LE. 1 */
1409 mpabs(&x[1], &y[1]) ;
1410 if (mpcmpi(&y[1], &c__1) <= 0) goto L20 ;
1412 /* HERE ABS(X) .GT. 1 SO USE COS(X) = SIN(PI/2 - ABS(X)),
1413 * COMPUTING PI/2 WITH ONE GUARD DIGIT.
1417 mppi(&MP.r[i2 - 1]) ;
1418 mpdivi(&MP.r[i2 - 1], &c__2, &MP.r[i2 - 1]) ;
1420 mpsub(&MP.r[i2 - 1], &y[1], &y[1]) ;
1421 mpsin(&y[1], &y[1]) ;
1424 /* HERE ABS(X) .LE. 1 SO USE POWER SERIES */
1427 mpsin1(&y[1], &y[1], &c__0) ;
1433 mpcosh(int *x, int *y)
1437 /* RETURNS Y = COSH(X) FOR MP NUMBERS X AND Y, X NOT TOO LARGE.
1438 * USES MPEXP, DIMENSION OF R IN COMMON AT LEAST 5T+12
1441 --y ; /* Parameter adjustments */
1444 if (x[1] != 0) goto L10 ;
1448 mpcim(&c__1, &y[1]) ;
1451 /* CHECK LEGALITY OF B, T, M AND MXR */
1454 mpchk(&c__5, &c__12) ;
1455 i2 = (MP.t << 2) + 11 ;
1456 mpabs(&x[1], &MP.r[i2 - 1]) ;
1458 /* IF ABS(X) TOO LARGE MPEXP WILL PRINT ERROR MESSAGE
1459 * INCREASE M TO AVOID OVERFLOW WHEN COSH(X) REPRESENTABLE
1463 mpexp(&MP.r[i2 - 1], &MP.r[i2 - 1]) ;
1464 mprec(&MP.r[i2 - 1], &y[1]) ;
1465 mpadd(&MP.r[i2 - 1], &y[1], &y[1]) ;
1467 /* RESTORE M. IF RESULT OVERFLOWS OR UNDERFLOWS, MPDIVI WILL
1472 mpdivi(&y[1], &c__2, &y[1]) ;
1478 mpcqm(int *i, int *j, int *q)
1482 /* CONVERTS THE RATIONAL NUMBER I/J TO MULTIPLE PRECISION Q. */
1484 --q ; /* Parameter adjustments */
1489 if (j1 < 0) goto L30 ;
1490 else if (j1 == 0) goto L10 ;
1494 if (v->MPerrors) _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_CQM]) ;
1506 if (j1 != 1) mpdivi(&q[1], &j1, &q[1]) ;
1512 mpcrm(float *rx, int *z)
1516 static int i, k, i2, ib, ie, re, tp, rs ;
1517 static float rb, rj ;
1519 /* CONVERTS SINGLE-PRECISION NUMBER RX TO MULTIPLE-PRECISION Z.
1520 * SOME NUMBERS WILL NOT CONVERT EXACTLY ON MACHINES
1521 * WITH BASE OTHER THAN TWO, FOUR OR SIXTEEN.
1522 * CHECK LEGALITY OF B, T, M AND MXR
1525 --z ; /* Parameter adjustments */
1527 mpchk(&c__1, &c__4) ;
1532 if (*rx < (float) 0.0) goto L20 ;
1533 else if (*rx == 0) goto L10 ;
1536 /* IF RX = 0E0 RETURN 0 */
1546 rj = -(double)(*rx) ;
1559 if (rj < (float)1.0) goto L60 ;
1561 /* INCREASE IE AND DIVIDE RJ BY 16. */
1564 rj *= (float) 0.0625 ;
1568 if (rj >= (float).0625) goto L70 ;
1574 /* NOW RJ IS DY DIVIDED BY SUITABLE POWER OF 16.
1582 /* CONVERSION LOOP (ASSUME SINGLE-PRECISION OPS. EXACT) */
1585 for (i = 1; i <= i__1; ++i)
1588 MP.r[i - 1] = (int) rj ;
1589 rj -= (float) MP.r[i - 1] ;
1592 /* NORMALIZE RESULT */
1594 mpnzr(&rs, &re, &z[1], &c__0) ;
1598 i__1 = MP.b * 7 * MP.b ;
1599 ib = max(i__1, 32767) / 16 ;
1602 /* NOW MULTIPLY BY 16**IE */
1604 if (ie < 0) goto L90 ;
1605 else if (ie == 0) goto L130 ;
1611 for (i = 1; i <= i__1; ++i)
1614 if (tp <= ib && tp != MP.b && i < k) continue ;
1615 mpdivi(&z[1], &tp, &z[1]) ;
1622 for (i = 1; i <= i__1; ++i)
1625 if (tp <= ib && tp != MP.b && i < ie) continue ;
1626 mpmuli(&z[1], &tp, &z[1]) ;
1636 mpdiv(int *x, int *y, int *z)
1638 static int i, i2, ie, iz3 ;
1640 /* SETS Z = X/Y, FOR MP X, Y AND Z.
1641 * DIMENSION OF R IN CALLING PROGRAM MUST BE AT LEAST 4T+10
1642 * (BUT Z(1) MAY BE R(3T+9)).
1643 * CHECK LEGALITY OF B, T, M AND MXR
1646 --z ; /* Parameter adjustments */
1650 mpchk(&c__4, &c__10) ;
1652 /* CHECK FOR DIVISION BY ZERO */
1654 if (y[1] != 0) goto L20 ;
1656 if (v->MPerrors) _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_DIVA]) ;
1662 /* SPACE USED BY MPREC IS 4T+10 WORDS, BUT CAN OVERLAP SLIGHTLY. */
1667 /* CHECK FOR X = 0 */
1669 if (x[1] != 0) goto L30 ;
1674 /* INCREASE M TO AVOID OVERFLOW IN MPREC */
1679 /* FORM RECIPROCAL OF Y */
1681 mprec(&y[1], &MP.r[i2 - 1]) ;
1683 /* SET EXPONENT OF R(I2) TO ZERO TO AVOID OVERFLOW IN MPMUL */
1691 mpmul(&x[1], &MP.r[i2 - 1], &z[1]) ;
1693 mpext(&i, &iz3, &z[1]) ;
1695 /* RESTORE M, CORRECT EXPONENT AND RETURN */
1699 if (z[2] >= -MP.m) goto L40 ;
1701 /* UNDERFLOW HERE */
1707 if (z[2] <= MP.m) return ;
1711 if (v->MPerrors) _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_DIVB]) ;
1719 mpdivi(int *x, int *iy, int*z)
1723 static int c, i, j, k, b2, c2, i2, j1, j2, r1 ;
1724 static int j11, kh, re, iq, ir, rs, iqj ;
1726 /* DIVIDES MP X BY THE SINGLE-PRECISION INTEGER IY GIVING MP Z.
1727 * THIS IS MUCH FASTER THAN DIVISION BY AN MP NUMBER.
1730 --z ; /* Parameter adjustments */
1735 if (j < 0) goto L30 ;
1736 else if (j == 0) goto L10 ;
1740 if (v->MPerrors) _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_DIVIA]) ;
1751 /* CHECK FOR ZERO DIVIDEND */
1753 if (rs == 0) goto L120 ;
1755 /* CHECK FOR DIVISION BY B */
1757 if (j != MP.b) goto L50 ;
1758 mpstr(&x[1], &z[1]) ;
1759 if (re <= -MP.m) goto L240 ;
1764 /* CHECK FOR DIVISION BY 1 OR -1 */
1767 if (j != 1) goto L60 ;
1768 mpstr(&x[1], &z[1]) ;
1777 /* IF J*B NOT REPRESENTABLE AS AN INTEGER HAVE TO SIMULATE
1778 * LONG DIVISION. ASSUME AT LEAST 16-BIT WORD.
1783 i__1 = MP.b << 3, i__2 = 32767 / MP.b ;
1784 b2 = max(i__1,i__2) ;
1785 if (j >= b2) goto L130 ;
1787 /* LOOK FOR FIRST NONZERO DIGIT IN QUOTIENT */
1792 if (i <= MP.t) c += x[i + 2] ;
1794 if (r1 < 0) goto L210 ;
1795 else if (r1 == 0) goto L70 ;
1798 /* ADJUST EXPONENT AND GET T+4 DIGITS IN QUOTIENT */
1803 c = MP.b * (c - j * r1) ;
1805 if (i >= MP.t) goto L100 ;
1808 for (k = 2; k <= i__1; ++k)
1812 MP.r[k - 1] = c / j ;
1813 c = MP.b * (c - j * MP.r[k - 1]) ;
1815 if (c < 0) goto L210 ;
1820 for (k = kh; k <= i__1; ++k)
1822 MP.r[k - 1] = c / j ;
1823 c = MP.b * (c - j * MP.r[k - 1]) ;
1825 if (c < 0) goto L210 ;
1827 /* NORMALIZE AND ROUND RESULT */
1830 mpnzr(&rs, &re, &z[1], &c__0) ;
1833 /* HERE NEED SIMULATED DOUBLE-PRECISION DIVISION */
1838 j2 = j - j1 * MP.b ;
1841 /* LOOK FOR FIRST NONZERO DIGIT */
1847 if (i <= MP.t) c2 = x[i + 2] ;
1848 if ((i__1 = c - j1) < 0) goto L140 ;
1849 else if (i__1 == 0) goto L150 ;
1853 if (c2 < j2) goto L140 ;
1855 /* COMPUTE T+4 QUOTIENT DIGITS */
1862 /* MAIN LOOP FOR LARGE ABS(IY) CASE */
1866 if (k > i2) goto L120 ;
1869 /* GET APPROXIMATE QUOTIENT FIRST */
1874 /* NOW REDUCE SO OVERFLOW DOES NOT OCCUR */
1877 if (iq < b2) goto L190 ;
1879 /* HERE IQ*B WOULD POSSIBLY OVERFLOW SO INCREASE IR */
1885 iq = iq * MP.b - ir * j2 ;
1886 if (iq >= 0) goto L200 ;
1888 /* HERE IQ NEGATIVE SO IR WAS TOO LARGE */
1894 if (i <= MP.t) iq += x[i + 2] ;
1897 /* R(K) = QUOTIENT, C = REMAINDER */
1899 MP.r[k - 1] = iqj + ir ;
1901 if (c >= 0) goto L170 ;
1903 /* CARRY NEGATIVE SO OVERFLOW MUST HAVE OCCURRED */
1906 mpchk(&c__1, &c__4) ;
1908 if (v->MPerrors) _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_DIVIB]) ;
1915 /* UNDERFLOW HERE */
1924 mpeq(int *x, int *y)
1928 /* RETURNS LOGICAL VALUE OF (X .EQ. Y) FOR MP X AND Y. */
1930 --y ; /* Parameter adjustments */
1933 ret_val = mpcomp(&x[1], &y[1]) == 0 ;
1942 /* THIS ROUTINE IS CALLED WHEN AN ERROR CONDITION IS ENCOUNTERED, AND
1943 * AFTER A MESSAGE HAS BEEN WRITTEN TO STDERR.
1946 doerr(vstrs[(int) V_ERROR]) ;
1951 mpexp(int *x, int *y)
1956 static int i, i2, i3, ie, ix, ts, xs, tss ;
1957 static float rx, ry, rlb ;
1959 /* RETURNS Y = EXP(X) FOR MP X AND Y.
1960 * EXP OF INTEGER AND FRACTIONAL PARTS OF X ARE COMPUTED
1961 * SEPARATELY. SEE ALSO COMMENTS IN MPEXP1.
1962 * TIME IS O(SQRT(T)M(T)).
1963 * DIMENSION OF R MUST BE AT LEAST 4T+10 IN CALLING PROGRAM
1964 * CHECK LEGALITY OF B, T, M AND MXR
1967 --y ; /* Parameter adjustments */
1970 mpchk(&c__4, &c__10) ;
1971 i2 = (MP.t << 1) + 7 ;
1972 i3 = i2 + MP.t + 2 ;
1974 /* CHECK FOR X = 0 */
1976 if (x[1] != 0) goto L10 ;
1977 mpcim(&c__1, &y[1]) ;
1980 /* CHECK IF ABS(X) .LT. 1 */
1983 if (x[2] > 0) goto L20 ;
1985 /* USE MPEXP1 HERE */
1987 mpexp1(&x[1], &y[1]) ;
1988 mpaddi(&y[1], &c__1, &y[1]) ;
1991 /* SEE IF ABS(X) SO LARGE THAT EXP(X) WILL CERTAINLY OVERFLOW
1992 * OR UNDERFLOW. 1.01 IS TO ALLOW FOR ERRORS IN ALOG.
1996 rlb = log((float) MP.b) * (float)1.01 ;
1997 r__1 = -(double)((float) (MP.m + 1)) * rlb ;
1998 if (mpcmpr(&x[1], &r__1) >= 0) goto L40 ;
2000 /* UNDERFLOW SO CALL MPUNFL AND RETURN */
2007 r__1 = (float) MP.m * rlb ;
2008 if (mpcmpr(&x[1], &r__1) <= 0) goto L70 ;
2013 if (v->MPerrors) _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_EXPA]) ;
2018 /* NOW SAFE TO CONVERT X TO REAL */
2023 /* SAVE SIGN AND WORK WITH ABS(X) */
2026 mpabs(&x[1], &MP.r[i3 - 1]) ;
2028 /* IF ABS(X) .GT. M POSSIBLE THAT INT(X) OVERFLOWS,
2032 if (dabs(rx) > (float) MP.m)
2033 mpdivi(&MP.r[i3 - 1], &c__32, &MP.r[i3 - 1]) ;
2035 /* GET FRACTIONAL AND INTEGER PARTS OF ABS(X) */
2037 mpcmi(&MP.r[i3 - 1], &ix) ;
2038 mpcmf(&MP.r[i3 - 1], &MP.r[i3 - 1]) ;
2040 /* ATTACH SIGN TO FRACTIONAL PART AND COMPUTE EXP OF IT */
2042 MP.r[i3 - 1] = xs * MP.r[i3 - 1] ;
2043 mpexp1(&MP.r[i3 - 1], &y[1]) ;
2044 mpaddi(&y[1], &c__1, &y[1]) ;
2046 /* COMPUTE E-2 OR 1/E USING TWO EXTRA DIGITS IN CASE ABS(X) LARGE
2047 * (BUT ONLY ONE EXTRA DIGIT IF T .LT. 4)
2052 if (MP.t < 4) ts = MP.t + 1 ;
2055 i3 = i2 + MP.t + 2 ;
2057 mpcim(&xs, &MP.r[i2 - 1]) ;
2060 /* LOOP FOR E COMPUTATION. DECREASE T IF POSSIBLE. */
2066 i__1 = ts, i__2 = ts + 2 + MP.r[i2] ;
2067 MP.t = min(i__1,i__2) ;
2068 if (MP.t <= 2) goto L90 ;
2071 mpdivi(&MP.r[i2 - 1], &i__1, &MP.r[i2 - 1]) ;
2073 mpadd2(&MP.r[i3 - 1], &MP.r[i2 - 1], &MP.r[i3 - 1], &
2074 MP.r[i2 - 1], &c__0) ;
2075 if (MP.r[i2 - 1] != 0) goto L80 ;
2077 /* RAISE E OR 1/E TO POWER IX */
2082 mpaddi(&MP.r[i3 - 1], &c__2, &MP.r[i3 - 1]) ;
2083 mppwr(&MP.r[i3 - 1], &ix, &MP.r[i3 - 1]) ;
2089 /* MULTIPLY EXPS OF INTEGER AND FRACTIONAL PARTS */
2091 mpmul(&y[1], &MP.r[i3 - 1], &y[1]) ;
2093 /* MUST CORRECT RESULT IF DIVIDED BY 32 ABOVE. */
2095 if (dabs(rx) <= (float) MP.m || y[1] == 0) goto L110 ;
2097 for (i = 1; i <= 5; ++i)
2100 /* SAVE EXPONENT TO AVOID OVERFLOW IN MPMUL */
2104 mpmul(&y[1], &y[1], &y[1]) ;
2107 /* CHECK FOR UNDERFLOW AND OVERFLOW */
2109 if (y[2] < -MP.m) goto L30 ;
2110 if (y[2] > MP.m) goto L50 ;
2113 /* CHECK THAT RELATIVE ERROR LESS THAN 0.01 UNLESS ABS(X) LARGE
2114 * (WHEN EXP MIGHT OVERFLOW OR UNDERFLOW)
2118 if (dabs(rx) > (float)10.0) return ;
2121 if ((r__1 = ry - exp(rx), dabs(r__1)) < ry * (float)0.01) return ;
2123 /* THE FOLLOWING MESSAGE MAY INDICATE THAT
2124 * B**(T-1) IS TOO SMALL, OR THAT M IS TOO SMALL SO THE
2125 * RESULT UNDERFLOWED.
2128 if (v->MPerrors) _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_EXPB]) ;
2136 mpexp1(int *x, int *y)
2140 static int i, q, i2, i3, ib, ic, ts ;
2143 /* ASSUMES THAT X AND Y ARE MP NUMBERS, -1 .LT. X .LT. 1.
2144 * RETURNS Y = EXP(X) - 1 USING AN O(SQRT(T).M(T)) ALGORITHM
2145 * DESCRIBED IN - R. P. BRENT, THE COMPLEXITY OF MULTIPLE-
2146 * PRECISION ARITHMETIC (IN COMPLEXITY OF COMPUTATIONAL PROBLEM
2147 * SOLVING, UNIV. OF QUEENSLAND PRESS, BRISBANE, 1976, 126-165).
2148 * ASYMPTOTICALLY FASTER METHODS EXIST, BUT ARE NOT USEFUL
2149 * UNLESS T IS VERY LARGE. SEE COMMENTS TO MPATAN AND MPPIGL.
2150 * DIMENSION OF R IN CALLING PROGRAM MUST BE AT LEAST 3T+8
2151 * CHECK LEGALITY OF B, T, M AND MXR
2154 --y ; /* Parameter adjustments */
2157 mpchk(&c__3, &c__8) ;
2159 i3 = i2 + MP.t + 2 ;
2161 /* CHECK FOR X = 0 */
2163 if (x[1] != 0) goto L20 ;
2169 /* CHECK THAT ABS(X) .LT. 1 */
2172 if (x[2] <= 0) goto L40 ;
2174 if (v->MPerrors) _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_EXP1]) ;
2180 mpstr(&x[1], &MP.r[i2 - 1]) ;
2181 rlb = log((float) MP.b) ;
2183 /* COMPUTE APPROXIMATELY OPTIMAL Q (AND DIVIDE X BY 2**Q) */
2185 q = (int) (sqrt((float) MP.t * (float).48 * rlb) + (float) x[2] *
2186 (float)1.44 * rlb) ;
2190 if (q <= 0) goto L60 ;
2194 for (i = 1; i <= i__1; ++i)
2197 if (ic < ib && ic != MP.b && i < q) continue ;
2198 mpdivi(&MP.r[i2 - 1], &ic, &MP.r[i2 - 1]) ;
2203 if (MP.r[i2 - 1] == 0) goto L10 ;
2204 mpstr(&MP.r[i2 - 1], &y[1]) ;
2205 mpstr(&MP.r[i2 - 1], &MP.r[i3 - 1]) ;
2209 /* SUM SERIES, REDUCING T WHERE POSSIBLE */
2212 MP.t = ts + 2 + MP.r[i3] - y[2] ;
2213 if (MP.t <= 2) goto L80 ;
2215 MP.t = min(MP.t,ts) ;
2216 mpmul(&MP.r[i2 - 1], &MP.r[i3 - 1], &MP.r[i3 - 1]) ;
2218 mpdivi(&MP.r[i3 - 1], &i, &MP.r[i3 - 1]) ;
2220 mpadd2(&MP.r[i3 - 1], &y[1], &y[1], &y[1], &c__0) ;
2221 if (MP.r[i3 - 1] != 0) goto L70 ;
2225 if (q <= 0) return ;
2227 /* APPLY (X+1)**2 - 1 = X(2 + X) FOR Q ITERATIONS */
2230 for (i = 1; i <= i__1; ++i)
2232 mpaddi(&y[1], &c__2, &MP.r[i2 - 1]) ;
2233 mpmul(&MP.r[i2 - 1], &y[1], &y[1]) ;
2240 mpext(int *i, int *j, int *x)
2244 /* ROUTINE CALLED BY MPDIV AND MPSQRT TO ENSURE THAT
2245 * RESULTS ARE REPRESENTED EXACTLY IN T-2 DIGITS IF THEY
2246 * CAN BE. X IS AN MP NUMBER, I AND J ARE INTEGERS.
2249 --x ; /* Parameter adjustments */
2251 if (x[1] == 0 || MP.t <= 2 || *i == 0) return ;
2253 /* COMPUTE MAXIMUM POSSIBLE ERROR IN THE LAST PLACE */
2255 q = (*j + 1) / *i + 1 ;
2256 s = MP.b * x[MP.t + 1] + x[MP.t + 2] ;
2257 if (s > q) goto L10 ;
2259 /* SET LAST TWO DIGITS TO ZERO */
2266 if (s + q < MP.b * MP.b) return ;
2270 x[MP.t + 1] = MP.b - 1 ;
2271 x[MP.t + 2] = MP.b ;
2273 /* NORMALIZE X (LAST DIGIT B IS OK IN MPMULI) */
2275 mpmuli(&x[1], &c__1, &x[1]) ;
2281 mpgcd(int *k, int *l)
2283 static int i, j, is, js ;
2285 /* RETURNS K = K/GCD AND L = L/GCD, WHERE GCD IS THE
2286 * GREATEST COMMON DIVISOR OF K AND L.
2287 * SAVE INPUT PARAMETERS IN LOCAL VARIABLES
2294 if (js == 0) goto L30 ;
2296 /* EUCLIDEAN ALGORITHM LOOP */
2300 if (is == 0) goto L20 ;
2302 if (js != 0) goto L10 ;
2305 /* HERE JS IS THE GCD OF I AND J */
2312 /* IF J = 0 RETURN (1, 0) UNLESS I = 0, THEN (0, 0) */
2316 if (is == 0) *k = 0 ;
2323 mpge(int *x, int *y)
2327 /* RETURNS LOGICAL VALUE OF (X .GE. Y) FOR MP X AND Y. */
2329 --y ; /* Parameter adjustments */
2332 ret_val = mpcomp(&x[1], &y[1]) >= 0 ;
2338 mpgt(int *x, int *y)
2342 /* RETURNS LOGICAL VALUE OF (X .GT. Y) FOR MP X AND Y. */
2344 --y ; /* Parameter adjustments */
2347 ret_val = mpcomp(&x[1], &y[1]) > 0 ;
2353 mple(int *x, int *y)
2357 /* RETURNS LOGICAL VALUE OF (X .LE. Y) FOR MP X AND Y. */
2359 --y ; /* Parameter adjustments */
2362 ret_val = mpcomp(&x[1], &y[1]) <= 0 ;
2368 mpln(int *x, int *y)
2372 static int e, k, i2, i3 ;
2373 static float rx, rlx ;
2375 /* RETURNS Y = LN(X), FOR MP X AND Y, USING MPLNS.
2376 * RESTRICTION - INTEGER PART OF LN(X) MUST BE REPRESENTABLE
2377 * AS A SINGLE-PRECISION INTEGER. TIME IS O(SQRT(T).M(T)).
2378 * FOR SMALL INTEGER X, MPLNI IS FASTER.
2379 * ASYMPTOTICALLY FASTER METHODS EXIST (EG THE GAUSS-SALAMIN
2380 * METHOD, SEE MPLNGS), BUT ARE NOT USEFUL UNLESS T IS LARGE.
2381 * SEE COMMENTS TO MPATAN, MPEXP1 AND MPPIGL.
2382 * DIMENSION OF R IN CALLING PROGRAM MUST BE AT LEAST 6T+14.
2383 * CHECK LEGALITY OF B, T, M AND MXR
2386 --y ; /* Parameter adjustments */
2389 mpchk(&c__6, &c__14) ;
2390 i2 = (MP.t << 2) + 11 ;
2391 i3 = i2 + MP.t + 2 ;
2393 /* CHECK THAT X IS POSITIVE */
2394 if (x[1] > 0) goto L20 ;
2396 if (v->MPerrors) _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_LNA]) ;
2402 /* MOVE X TO LOCAL STORAGE */
2405 mpstr(&x[1], &MP.r[i2 - 1]) ;
2409 /* LOOP TO GET APPROXIMATE LN(X) USING SINGLE-PRECISION */
2412 mpaddi(&MP.r[i2 - 1], &c_n1, &MP.r[i3 - 1]) ;
2414 /* IF POSSIBLE GO TO CALL MPLNS */
2416 if (MP.r[i3 - 1] == 0 || MP.r[i3] + 1 <= 0) goto L50 ;
2418 /* REMOVE EXPONENT TO AVOID FLOATING-POINT OVERFLOW */
2422 mpcmr(&MP.r[i2 - 1], &rx) ;
2424 /* RESTORE EXPONENT AND COMPUTE SINGLE-PRECISION LOG */
2427 rlx = log(rx) + (float) e * log((float) MP.b) ;
2428 r__1 = -(double)rlx ;
2429 mpcrm(&r__1, &MP.r[i3 - 1]) ;
2431 /* UPDATE Y AND COMPUTE ACCURATE EXP OF APPROXIMATE LOG */
2433 mpsub(&y[1], &MP.r[i3 - 1], &y[1]) ;
2434 mpexp(&MP.r[i3 - 1], &MP.r[i3 - 1]) ;
2436 /* COMPUTE RESIDUAL WHOSE LOG IS STILL TO BE FOUND */
2438 mpmul(&MP.r[i2 - 1], &MP.r[i3 - 1], &MP.r[i2 - 1]) ;
2440 /* MAKE SURE NOT LOOPING INDEFINITELY */
2442 if (k < 10) goto L30 ;
2444 if (v->MPerrors) _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_LNB]) ;
2449 /* COMPUTE FINAL CORRECTION ACCURATELY USING MPLNS */
2452 mplns(&MP.r[i3 - 1], &MP.r[i3 - 1]) ;
2453 mpadd(&y[1], &MP.r[i3 - 1], &y[1]) ;
2459 mplns(int *x, int *y)
2463 static int i2, i3, i4, ts, it0, ts2, ts3 ;
2465 /* RETURNS MP Y = LN(1+X) IF X IS AN MP NUMBER SATISFYING THE
2466 * CONDITION ABS(X) .LT. 1/B, ERROR OTHERWISE.
2467 * USES NEWTONS METHOD TO SOLVE THE EQUATION
2468 * EXP1(-Y) = X, THEN REVERSES SIGN OF Y.
2469 * (HERE EXP1(Y) = EXP(Y) - 1 IS COMPUTED USING MPEXP1).
2470 * TIME IS O(SQRT(T).M(T)) AS FOR MPEXP1, SPACE = 5T+12.
2471 * CHECK LEGALITY OF B, T, M AND MXR
2474 --y ; /* Parameter adjustments */
2477 mpchk(&c__5, &c__12) ;
2478 i2 = (MP.t << 1) + 7 ;
2479 i3 = i2 + MP.t + 2 ;
2480 i4 = i3 + MP.t + 2 ;
2482 /* CHECK FOR X = 0 EXACTLY */
2484 if (x[1] != 0) goto L10 ;
2488 /* CHECK THAT ABS(X) .LT. 1/B */
2491 if (x[2] + 1 <= 0) goto L30 ;
2493 if (v->MPerrors) _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_LNSA]) ;
2499 /* SAVE T AND GET STARTING APPROXIMATION TO -LN(1+X) */
2503 mpstr(&x[1], &MP.r[i3 - 1]) ;
2504 mpdivi(&x[1], &c__4, &MP.r[i2 - 1]) ;
2505 mpaddq(&MP.r[i2 - 1], &c_n1, &c__3, &MP.r[i2 - 1]) ;
2506 mpmul(&x[1], &MP.r[i2 - 1], &MP.r[i2 - 1]) ;
2507 mpaddq(&MP.r[i2 - 1], &c__1, &c__2, &MP.r[i2 - 1]) ;
2508 mpmul(&x[1], &MP.r[i2 - 1], &MP.r[i2 - 1]) ;
2509 mpaddi(&MP.r[i2 - 1], &c_n1, &MP.r[i2 - 1]) ;
2510 mpmul(&x[1], &MP.r[i2 - 1], &y[1]) ;
2512 /* START NEWTON ITERATION USING SMALL T, LATER INCREASE */
2516 i__1 = 5, i__2 = 13 - (MP.b << 1) ;
2517 MP.t = max(i__1,i__2) ;
2518 if (MP.t > ts) goto L80 ;
2520 it0 = (MP.t + 5) / 2 ;
2523 mpexp1(&y[1], &MP.r[i4 - 1]) ;
2524 mpmul(&MP.r[i3 - 1], &MP.r[i4 - 1], &MP.r[i2 - 1]) ;
2525 mpadd(&MP.r[i4 - 1], &MP.r[i2 - 1], &MP.r[i4 - 1]) ;
2526 mpadd(&MP.r[i3 - 1], &MP.r[i4 - 1], &MP.r[i4 - 1]) ;
2527 mpsub(&y[1], &MP.r[i4 - 1], &y[1]) ;
2528 if (MP.t >= ts) goto L60 ;
2530 /* FOLLOWING LOOP COMPUTES NEXT VALUE OF T TO USE.
2531 * BECAUSE NEWTONS METHOD HAS 2ND ORDER CONVERGENCE,
2532 * WE CAN ALMOST DOUBLE T EACH TIME.
2540 MP.t = (MP.t + it0) / 2 ;
2541 if (MP.t > ts3) goto L50 ;
2546 /* CHECK THAT NEWTON ITERATION WAS CONVERGING AS EXPECTED */
2549 if (MP.r[i4 - 1] == 0 || MP.r[i4] << 1 <= it0 - MP.t)
2554 _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_LNSB]) ;
2555 _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_LNSC]) ;
2560 /* REVERSE SIGN OF Y AND RETURN */
2570 mplt(int *x, int *y)
2574 /* RETURNS LOGICAL VALUE OF (X .LT. Y) FOR MP X AND Y. */
2576 --y ; /* Parameter adjustments */
2579 ret_val = mpcomp(&x[1], &y[1]) < 0 ;
2591 /* SETS X TO THE LARGEST POSSIBLE POSITIVE MP NUMBER
2592 * CHECK LEGALITY OF B, T, M AND MXR
2595 --x ; /* Parameter adjustments */
2597 mpchk(&c__1, &c__4) ;
2600 /* SET FRACTION DIGITS TO B-1 */
2603 for (i = 1; i <= i__1; ++i) x[i + 2] = it ;
2605 /* SET SIGN AND EXPONENT */
2614 mpmlp(int *u, int *v, int *w, int *j)
2620 /* PERFORMS INNER MULTIPLICATION LOOP FOR MPMUL
2621 * NOTE THAT CARRIES ARE NOT PROPAGATED IN INNER LOOP,
2622 * WHICH SAVES TIME AT THE EXPENSE OF SPACE.
2625 --v ; /* Parameter adjustments */
2629 for (i = 1; i <= i__1; ++i) u[i] += *w * v[i] ;
2635 mpmul(int *x, int *y, int *z)
2637 int i__1, i__2, i__3, i__4 ;
2639 static int c, i, j, i2, j1, re, ri, xi, rs, i2p ;
2641 /* MULTIPLIES X AND Y, RETURNING RESULT IN Z, FOR MP X, Y AND Z.
2642 * THE SIMPLE O(T**2) ALGORITHM IS USED, WITH
2643 * FOUR GUARD DIGITS AND R*-ROUNDING.
2644 * ADVANTAGE IS TAKEN OF ZERO DIGITS IN X, BUT NOT IN Y.
2645 * ASYMPTOTICALLY FASTER ALGORITHMS ARE KNOWN (SEE KNUTH,
2646 * VOL. 2), BUT ARE DIFFICULT TO IMPLEMENT IN FORTRAN IN AN
2647 * EFFICIENT AND MACHINE-INDEPENDENT MANNER.
2648 * IN COMMENTS TO OTHER MP ROUTINES, M(T) IS THE TIME
2649 * TO PERFORM T-DIGIT MP MULTIPLICATION. THUS
2650 * M(T) = O(T**2) WITH THE PRESENT VERSION OF MPMUL,
2651 * BUT M(T) = O(T.LOG(T).LOG(LOG(T))) IS THEORETICALLY POSSIBLE.
2652 * CHECK LEGALITY OF B, T, M AND MXR
2655 --z ; /* Parameter adjustments */
2659 mpchk(&c__1, &c__4) ;
2663 /* FORM SIGN OF PRODUCT */
2666 if (rs != 0) goto L10 ;
2668 /* SET RESULT TO ZERO */
2673 /* FORM EXPONENT OF PRODUCT */
2678 /* CLEAR ACCUMULATOR */
2681 for (i = 1; i <= i__1; ++i) MP.r[i - 1] = 0 ;
2683 /* PERFORM MULTIPLICATION */
2687 for (i = 1; i <= i__1; ++i)
2691 /* FOR SPEED, PUT THE NUMBER WITH MANY ZEROS FIRST */
2693 if (xi == 0) continue ;
2697 i__3 = MP.t, i__4 = i2 - i ;
2698 i__2 = min(i__3,i__4) ;
2699 mpmlp(&MP.r[i], &y[3], &xi, &i__2) ;
2701 if (c > 0) continue ;
2703 /* CHECK FOR LEGAL BASE B DIGIT */
2705 if (xi < 0 || xi >= MP.b) goto L90 ;
2707 /* PROPAGATE CARRIES AT END AND EVERY EIGHTH TIME,
2708 * FASTER THAN DOING IT EVERY TIME.
2712 for (j = 1; j <= i__2; ++j)
2715 ri = MP.r[j1 - 1] + c ;
2716 if (ri < 0) goto L70 ;
2718 MP.r[j1 - 1] = ri - MP.b * c ;
2720 if (c != 0) goto L90 ;
2724 if (c == 8) goto L60 ;
2725 if (xi < 0 || xi >= MP.b) goto L90 ;
2728 for (j = 1; j <= i__1; ++j)
2731 ri = MP.r[j1 - 1] + c ;
2732 if (ri < 0) goto L70 ;
2734 MP.r[j1 - 1] = ri - MP.b * c ;
2736 if (c != 0) goto L90 ;
2738 /* NORMALIZE AND ROUND RESULT */
2741 mpnzr(&rs, &re, &z[1], &c__0) ;
2745 if (v->MPerrors) _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_MULA]) ;
2752 _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_MULB]) ;
2753 _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_MULC]) ;
2764 mpmul2(int *x, int *iy, int *z, int *trunc)
2768 static int c, i, j, c1, c2, j1, j2 ;
2769 static int t1, t3, t4, ij, re, ri, is, ix, rs ;
2771 /* MULTIPLIES MP X BY SINGLE-PRECISION INTEGER IY GIVING MP Z.
2772 * MULTIPLICATION BY 1 MAY BE USED TO NORMALIZE A NUMBER
2773 * EVEN IF SOME DIGITS ARE GREATER THAN B-1.
2774 * RESULT IS ROUNDED IF TRUNC.EQ.0, OTHERWISE TRUNCATED.
2777 --z ; /* Parameter adjustments */
2781 if (rs == 0) goto L10 ;
2783 if (j < 0) goto L20 ;
2784 else if (j == 0) goto L10 ;
2797 /* CHECK FOR MULTIPLICATION BY B */
2799 if (j != MP.b) goto L50 ;
2800 if (x[2] < MP.m) goto L40 ;
2802 mpchk(&c__1, &c__4) ;
2804 if (v->MPerrors) _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_MUL2A]) ;
2810 mpstr(&x[1], &z[1]) ;
2815 /* SET EXPONENT TO EXPONENT(X) + 4 */
2820 /* FORM PRODUCT IN ACCUMULATOR */
2827 /* IF J*B NOT REPRESENTABLE AS AN INTEGER WE HAVE TO SIMULATE
2828 * DOUBLE-PRECISION MULTIPLICATION.
2833 i__1 = MP.b << 3, i__2 = 32767 / MP.b ;
2834 if (j >= max(i__1,i__2)) goto L110 ;
2837 for (ij = 1; ij <= i__1; ++ij)
2840 ri = j * x[i + 2] + c ;
2842 MP.r[i + 3] = ri - MP.b * c ;
2845 /* CHECK FOR INTEGER OVERFLOW */
2847 if (ri < 0) goto L130 ;
2849 /* HAVE TO TREAT FIRST FOUR WORDS OF R SEPARATELY */
2851 for (ij = 1; ij <= 4; ++ij)
2856 MP.r[i - 1] = ri - MP.b * c ;
2858 if (c == 0) goto L100 ;
2860 /* HAVE TO SHIFT RIGHT HERE AS CARRY OFF END */
2864 for (ij = 1; ij <= i__1; ++ij)
2867 MP.r[i] = MP.r[i - 1] ;
2871 MP.r[0] = ri - MP.b * c ;
2873 if (c < 0) goto L130 ;
2874 else if (c == 0) goto L100 ;
2877 /* NORMALIZE AND ROUND OR TRUNCATE RESULT */
2880 mpnzr(&rs, &re, &z[1], trunc) ;
2883 /* HERE J IS TOO LARGE FOR SINGLE-PRECISION MULTIPLICATION */
2887 j2 = j - j1 * MP.b ;
2892 for (ij = 1; ij <= i__1; ++ij)
2895 c2 = c - MP.b * c1 ;
2898 if (i > 0) ix = x[i + 2] ;
2901 c = j1 * ix + c1 + is ;
2902 MP.r[i + 3] = ri - MP.b * is ;
2905 if (c < 0) goto L130 ;
2906 else if (c == 0) goto L100 ;
2909 /* CAN ONLY GET HERE IF INTEGER OVERFLOW OCCURRED */
2912 mpchk(&c__1, &c__4) ;
2914 if (v->MPerrors) _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_MUL2B]) ;
2922 mpmuli(int *x, int *iy, int *z)
2925 /* MULTIPLIES MP X BY SINGLE-PRECISION INTEGER IY GIVING MP Z.
2926 * THIS IS FASTER THAN USING MPMUL. RESULT IS ROUNDED.
2927 * MULTIPLICATION BY 1 MAY BE USED TO NORMALIZE A NUMBER
2928 * EVEN IF THE LAST DIGIT IS B.
2931 --z ; /* Parameter adjustments */
2934 mpmul2(&x[1], iy, &z[1], &c__0) ;
2940 mpmulq(int *x, int *i, int *j, int *y)
2946 /* MULTIPLIES MP X BY I/J, GIVING MP Y */
2948 --y ; /* Parameter adjustments */
2951 if (*j != 0) goto L20 ;
2952 mpchk(&c__1, &c__4) ;
2954 if (v->MPerrors) _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_MULQ]) ;
2960 if (*i != 0) goto L40 ;
2966 /* REDUCE TO LOWEST TERMS */
2972 if (C_abs(is) == 1) goto L50 ;
2974 mpdivi(&x[1], &js, &y[1]) ;
2975 mpmul2(&y[1], &is, &y[1], &c__0) ;
2982 mpdivi(&x[1], &i__1, &y[1]) ;
2988 mpneg(int *x, int *y)
2991 /* SETS Y = -X FOR MP NUMBERS X AND Y */
2993 --y ; /* Parameter adjustments */
2996 mpstr(&x[1], &y[1]) ;
3003 mpnzr(int *rs, int *re, int *z, int *trunc)
3007 static int i, j, k, b2, i2, is, it, i2m, i2p ;
3009 /* ASSUMES LONG (I.E. (T+4)-DIGIT) FRACTION IN
3010 * R, SIGN = RS, EXPONENT = RE. NORMALIZES,
3011 * AND RETURNS MP RESULT IN Z. INTEGER ARGUMENTS RS AND RE
3012 * ARE NOT PRESERVED. R*-ROUNDING IS USED IF TRUNC.EQ.0
3015 --z ; /* Parameter adjustments */
3018 if (*rs != 0) goto L20 ;
3020 /* STORE ZERO IN Z */
3026 /* CHECK THAT SIGN = +-1 */
3029 if (C_abs(*rs) <= 1) goto L40 ;
3033 _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_NZRA]) ;
3034 _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_NZRB]) ;
3040 /* LOOK FOR FIRST NONZERO DIGIT */
3044 for (i = 1; i <= i__1; ++i)
3047 if (MP.r[i - 1] > 0) goto L60 ;
3055 if (is == 0) goto L90 ;
3062 for (j = 1; j <= i__1; ++j)
3065 MP.r[j - 1] = MP.r[k - 1] ;
3069 for (j = i2p; j <= i__1; ++j) MP.r[j - 1] = 0 ;
3071 /* CHECK TO SEE IF TRUNCATION IS DESIRED */
3074 if (*trunc != 0) goto L150 ;
3076 /* SEE IF ROUNDING NECESSARY
3077 * TREAT EVEN AND ODD BASES DIFFERENTLY
3081 if (b2 << 1 != MP.b) goto L130 ;
3083 /* B EVEN. ROUND IF R(T+1).GE.B2 UNLESS R(T) ODD AND ALL ZEROS
3087 if ((i__1 = MP.r[MP.t] - b2) < 0) goto L150 ;
3088 else if (i__1 == 0) goto L100 ;
3092 if (MP.r[MP.t - 1] % 2 == 0) goto L110 ;
3094 if (MP.r[MP.t + 1] + MP.r[MP.t + 2] +
3095 MP.r[MP.t + 3] == 0)
3102 for (j = 1; j <= i__1; ++j)
3106 if (MP.r[i - 1] < MP.b) goto L150 ;
3110 /* EXCEPTIONAL CASE, ROUNDED UP TO .10000... */
3116 /* ODD BASE, ROUND IF R(T+1)... .GT. 1/2 */
3119 for (i = 1; i <= 4; ++i)
3122 if ((i__1 = MP.r[it - 1] - b2) < 0) goto L150 ;
3123 else if (i__1 == 0) continue ;
3127 /* CHECK FOR OVERFLOW */
3130 if (*re <= MP.m) goto L170 ;
3132 if (v->MPerrors) _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_NZRC]) ;
3137 /* CHECK FOR UNDERFLOW */
3140 if (*re < -MP.m) goto L190 ;
3142 /* STORE RESULT IN Z */
3147 for (i = 1; i <= i__1; ++i) z[i + 2] = MP.r[i - 1] ;
3150 /* UNDERFLOW HERE */
3162 /* CALLED ON MULTIPLE-PRECISION OVERFLOW, IE WHEN THE
3163 * EXPONENT OF MP NUMBER X WOULD EXCEED M.
3164 * AT PRESENT EXECUTION IS TERMINATED WITH AN ERROR MESSAGE
3165 * AFTER CALLING MPMAXR(X), BUT IT WOULD BE POSSIBLE TO RETURN,
3166 * POSSIBLY UPDATING A COUNTER AND TERMINATING EXECUTION AFTER
3167 * A PRESET NUMBER OF OVERFLOWS. ACTION COULD EASILY BE DETERMINED
3168 * BY A FLAG IN LABELLED COMMON.
3169 * M MAY HAVE BEEN OVERWRITTEN, SO CHECK B, T, M ETC.
3172 --x ; /* Parameter adjustments */
3174 mpchk(&c__1, &c__4) ;
3176 /* SET X TO LARGEST POSSIBLE POSITIVE NUMBER */
3180 if (v->MPerrors) _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_OVFL]) ;
3182 /* TERMINATE EXECUTION BY CALLING MPERR */
3197 /* SETS MP X = PI TO THE AVAILABLE PRECISION.
3198 * USES PI/4 = 4.ARCTAN(1/5) - ARCTAN(1/239).
3200 * DIMENSION OF R MUST BE AT LEAST 3T+8
3201 * CHECK LEGALITY OF B, T, M AND MXR
3204 --x ; /* Parameter adjustments */
3206 mpchk(&c__3, &c__8) ;
3208 /* ALLOW SPACE FOR MPART1 */
3210 i2 = (MP.t << 1) + 7 ;
3211 mpart1(&c__5, &MP.r[i2 - 1]) ;
3212 mpmuli(&MP.r[i2 - 1], &c__4, &MP.r[i2 - 1]) ;
3213 mpart1(&c__239, &x[1]) ;
3214 mpsub(&MP.r[i2 - 1], &x[1], &x[1]) ;
3215 mpmuli(&x[1], &c__4, &x[1]) ;
3217 /* RETURN IF ERROR IS LESS THAN 0.01 */
3220 if ((r__1 = rx - (float)3.1416, dabs(r__1)) < (float) 0.01) return ;
3222 /* FOLLOWING MESSAGE MAY INDICATE THAT B**(T-1) IS TOO SMALL */
3224 if (v->MPerrors) _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_PI]) ;
3232 mppwr(int *x, int *n, int *y)
3234 static int i2, n2, ns ;
3236 /* RETURNS Y = X**N, FOR MP X AND Y, INTEGER N, WITH 0**0 = 1.
3237 * R MUST BE DIMENSIONED AT LEAST 4T+10 IN CALLING PROGRAM
3238 * (2T+6 IS ENOUGH IF N NONNEGATIVE).
3241 --y ; /* Parameter adjustments */
3246 if (n2 < 0) goto L20 ;
3247 else if (n2 == 0) goto L10 ;
3250 /* N = 0, RETURN Y = 1. */
3253 mpcim(&c__1, &y[1]) ;
3259 mpchk(&c__4, &c__10) ;
3261 if (x[1] != 0) goto L60 ;
3265 _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_PWRA]) ;
3266 _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_PWRB]) ;
3275 mpchk(&c__2, &c__6) ;
3276 if (x[1] != 0) goto L60 ;
3278 /* X = 0, N .GT. 0, SO Y = 0 */
3287 mpstr(&x[1], &y[1]) ;
3289 /* IF N .LT. 0 FORM RECIPROCAL */
3291 if (*n < 0) mprec(&y[1], &y[1]) ;
3292 mpstr(&y[1], &MP.r[i2 - 1]) ;
3294 /* SET PRODUCT TERM TO ONE */
3296 mpcim(&c__1, &y[1]) ;
3298 /* MAIN LOOP, LOOK AT BITS OF N2 FROM RIGHT */
3303 if (n2 << 1 != ns) mpmul(&y[1], &MP.r[i2 - 1], &y[1]) ;
3304 if (n2 <= 0) return ;
3306 mpmul(&MP.r[i2 - 1], &MP.r[i2 - 1], &MP.r[i2 - 1]) ;
3312 mppwr2(int *x, int *y, int *z)
3316 /* RETURNS Z = X**Y FOR MP NUMBERS X, Y AND Z, WHERE X IS
3317 * POSITIVE (X .EQ. 0 ALLOWED IF Y .GT. 0). SLOWER THAN
3318 * MPPWR AND MPQPWR, SO USE THEM IF POSSIBLE.
3319 * DIMENSION OF R IN COMMON AT LEAST 7T+16
3320 * CHECK LEGALITY OF B, T, M AND MXR
3323 --z ; /* Parameter adjustments */
3327 mpchk(&c__7, &c__16) ;
3328 if (x[1] < 0) goto L10 ;
3329 else if (x[1] == 0) goto L30 ;
3333 if (v->MPerrors) _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_PWR2A]) ;
3337 /* HERE X IS ZERO, RETURN ZERO IF Y POSITIVE, OTHERWISE ERROR */
3340 if (y[1] > 0) goto L60 ;
3342 if (v->MPerrors) _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_PWR2B]) ;
3347 /* RETURN ZERO HERE */
3353 /* USUAL CASE HERE, X POSITIVE
3354 * USE MPLN AND MPEXP TO COMPUTE POWER
3358 i2 = MP.t * 6 + 15 ;
3359 mpln(&x[1], &MP.r[i2 - 1]) ;
3360 mpmul(&y[1], &MP.r[i2 - 1], &z[1]) ;
3362 /* IF X**Y IS TOO LARGE, MPEXP WILL PRINT ERROR MESSAGE */
3364 mpexp(&z[1], &z[1]) ;
3370 mprec(int *x, int *y)
3373 /* Initialized data */
3375 static int it[9] = { 0, 8, 6, 5, 4, 4, 4, 4, 4 } ;
3379 static int i2, i3, ex, ts, it0, ts2, ts3 ;
3382 /* RETURNS Y = 1/X, FOR MP X AND Y.
3383 * MPROOT (X, -1, Y) HAS THE SAME EFFECT.
3384 * DIMENSION OF R MUST BE AT LEAST 4*T+10 IN CALLING PROGRAM
3385 * (BUT Y(1) MAY BE R(3T+9)).
3386 * NEWTONS METHOD IS USED, SO FINAL ONE OR TWO DIGITS MAY
3390 --y ; /* Parameter adjustments */
3393 /* CHECK LEGALITY OF B, T, M AND MXR */
3395 mpchk(&c__4, &c__10) ;
3397 /* MPADDI REQUIRES 2T+6 WORDS. */
3399 i2 = (MP.t << 1) + 7 ;
3400 i3 = i2 + MP.t + 2 ;
3401 if (x[1] != 0) goto L20 ;
3403 if (v->MPerrors) _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_RECA]) ;
3412 /* TEMPORARILY INCREASE M TO AVOID OVERFLOW */
3416 /* SET EXPONENT TO ZERO SO RX NOT TOO LARGE OR SMALL. */
3421 /* USE SINGLE-PRECISION RECIPROCAL AS FIRST APPROXIMATION */
3423 r__1 = (float)1. / rx ;
3424 mpcrm(&r__1, &MP.r[i2 - 1]) ;
3426 /* RESTORE EXPONENT */
3430 /* CORRECT EXPONENT OF FIRST APPROXIMATION */
3434 /* SAVE T (NUMBER OF DIGITS) */
3438 /* START WITH SMALL T TO SAVE TIME. ENSURE THAT B**(T-1) .GE. 100 */
3441 if (MP.b < 10) MP.t = it[MP.b - 1] ;
3442 it0 = (MP.t + 4) / 2 ;
3443 if (MP.t > ts) goto L70 ;
3445 /* MAIN ITERATION LOOP */
3448 mpmul(&x[1], &MP.r[i2 - 1], &MP.r[i3 - 1]) ;
3449 mpaddi(&MP.r[i3 - 1], &c_n1, &MP.r[i3 - 1]) ;
3451 /* TEMPORARILY REDUCE T */
3454 MP.t = (MP.t + it0) / 2 ;
3455 mpmul(&MP.r[i2 - 1], &MP.r[i3 - 1], &MP.r[i3 - 1]) ;
3460 mpsub(&MP.r[i2 - 1], &MP.r[i3 - 1], &MP.r[i2 - 1]) ;
3461 if (MP.t >= ts) goto L50 ;
3463 /* FOLLOWING LOOP ALMOST DOUBLES T (POSSIBLE
3464 * BECAUSE NEWTONS METHOD HAS 2ND ORDER CONVERGENCE).
3471 MP.t = (MP.t + it0) / 2 ;
3472 if (MP.t > ts3) goto L40 ;
3474 MP.t = min(ts,ts2) ;
3477 /* RETURN IF NEWTON ITERATION WAS CONVERGING */
3480 if (MP.r[i3 - 1] == 0 || (MP.r[i2] - MP.r[i3]) << 1 >=
3484 /* THE FOLLOWING MESSAGE MAY INDICATE THAT B**(T-1) IS TOO SMALL,
3485 * OR THAT THE STARTING APPROXIMATION IS NOT ACCURATE ENOUGH.
3490 _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_RECB]) ;
3491 _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_RECC]) ;
3496 /* MOVE RESULT TO Y AND RETURN AFTER RESTORING T */
3500 mpstr(&MP.r[i2 - 1], &y[1]) ;
3502 /* RESTORE M AND CHECK FOR OVERFLOW (UNDERFLOW IMPOSSIBLE) */
3505 if (y[2] <= MP.m) return ;
3507 if (v->MPerrors) _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_RECD]) ;
3515 mproot(int *x, int *n, int *y)
3518 /* Initialized data */
3520 static int it[9] = { 0, 8, 6, 5, 4, 4, 4, 4, 4 } ;
3525 static int i2, i3, ex, np, ts, it0, ts2, ts3, xes ;
3528 /* RETURNS Y = X**(1/N) FOR INTEGER N, ABS(N) .LE. MAX (B, 64).
3529 * AND MP NUMBERS X AND Y,
3530 * USING NEWTONS METHOD WITHOUT DIVISIONS. SPACE = 4T+10
3531 * (BUT Y(1) MAY BE R(3T+9))
3534 --y ; /* Parameter adjustments */
3537 /* CHECK LEGALITY OF B, T, M AND MXR */
3539 mpchk(&c__4, &c__10) ;
3540 if (*n != 1) goto L10 ;
3541 mpstr(&x[1], &y[1]) ;
3545 i2 = (MP.t << 1) + 7 ;
3546 i3 = i2 + MP.t + 2 ;
3547 if (*n != 0) goto L30 ;
3549 if (v->MPerrors) _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_ROOTA]) ;
3556 /* LOSS OF ACCURACY IF NP LARGE, SO ONLY ALLOW NP .LE. MAX (B, 64) */
3558 if (np <= max(MP.b,64)) goto L60 ;
3560 if (v->MPerrors) _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_ROOTB]) ;
3567 /* LOOK AT SIGN OF X */
3570 if (x[1] < 0) goto L90 ;
3571 else if (x[1] == 0) goto L70 ;
3574 /* X = 0 HERE, RETURN 0 IF N POSITIVE, ERROR IF NEGATIVE */
3578 if (*n > 0) return ;
3580 if (v->MPerrors) _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_ROOTC]) ;
3584 /* X NEGATIVE HERE, SO ERROR IF N IS EVEN */
3587 if (np % 2 != 0) goto L110 ;
3589 if (v->MPerrors) _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_ROOTD]) ;
3593 /* GET EXPONENT AND DIVIDE BY NP */
3599 /* REDUCE EXPONENT SO RX NOT TOO LARGE OR SMALL. */
3604 /* USE SINGLE-PRECISION ROOT FOR FIRST APPROXIMATION */
3606 r__1 = exp(((float) (np * ex - xes) * log((float) MP.b) - log((dabs(
3607 rx)))) / (float) np) ;
3608 mpcrm(&r__1, &MP.r[i2 - 1]) ;
3610 /* SIGN OF APPROXIMATION SAME AS THAT OF X */
3612 MP.r[i2 - 1] = x[1] ;
3614 /* RESTORE EXPONENT */
3618 /* CORRECT EXPONENT OF FIRST APPROXIMATION */
3622 /* SAVE T (NUMBER OF DIGITS) */
3626 /* START WITH SMALL T TO SAVE TIME */
3630 /* ENSURE THAT B**(T-1) .GE. 100 */
3632 if (MP.b < 10) MP.t = it[MP.b - 1] ;
3633 if (MP.t > ts) goto L160 ;
3635 /* IT0 IS A NECESSARY SAFETY FACTOR */
3637 it0 = (MP.t + 4) / 2 ;
3639 /* MAIN ITERATION LOOP */
3642 mppwr(&MP.r[i2 - 1], &np, &MP.r[i3 - 1]) ;
3643 mpmul(&x[1], &MP.r[i3 - 1], &MP.r[i3 - 1]) ;
3644 mpaddi(&MP.r[i3 - 1], &c_n1, &MP.r[i3 - 1]) ;
3646 /* TEMPORARILY REDUCE T */
3649 MP.t = (MP.t + it0) / 2 ;
3650 mpmul(&MP.r[i2 - 1], &MP.r[i3 - 1], &MP.r[i3 - 1]) ;
3651 mpdivi(&MP.r[i3 - 1], &np, &MP.r[i3 - 1]) ;
3656 mpsub(&MP.r[i2 - 1], &MP.r[i3 - 1], &MP.r[i2 - 1]) ;
3658 /* FOLLOWING LOOP ALMOST DOUBLES T (POSSIBLE BECAUSE
3659 * NEWTONS METHOD HAS 2ND ORDER CONVERGENCE).
3662 if (MP.t >= ts) goto L140 ;
3667 MP.t = (MP.t + it0) / 2 ;
3668 if (MP.t > ts3) goto L130 ;
3670 MP.t = min(ts,ts2) ;
3673 /* NOW R(I2) IS X**(-1/NP)
3674 * CHECK THAT NEWTON ITERATION WAS CONVERGING
3678 if (MP.r[i3 - 1] == 0 || (MP.r[i2] - MP.r[i3]) << 1 >=
3682 /* THE FOLLOWING MESSAGE MAY INDICATE THAT B**(T-1) IS TOO SMALL,
3683 * OR THAT THE INITIAL APPROXIMATION OBTAINED USING ALOG AND EXP
3684 * IS NOT ACCURATE ENOUGH.
3689 _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_ROOTE]) ;
3690 _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_ROOTF]) ;
3699 if (*n < 0) goto L170 ;
3702 mppwr(&MP.r[i2 - 1], &i__1, &MP.r[i2 - 1]) ;
3703 mpmul(&x[1], &MP.r[i2 - 1], &y[1]) ;
3707 mpstr(&MP.r[i2 - 1], &y[1]) ;
3713 mpset(int *idecpl, int *itmax2, int *maxdr)
3717 static int i, k, w, i2, w2, wn ;
3719 /* SETS BASE (B) AND NUMBER OF DIGITS (T) TO GIVE THE
3720 * EQUIVALENT OF AT LEAST IDECPL DECIMAL DIGITS.
3721 * IDECPL SHOULD BE POSITIVE.
3722 * ITMAX2 IS THE DIMENSION OF ARRAYS USED FOR MP NUMBERS,
3723 * SO AN ERROR OCCURS IF THE COMPUTED T EXCEEDS ITMAX2 - 2.
3725 * MXR = MAXDR (DIMENSION OF R IN COMMON, .GE. T+4), AND
3726 * M = (W-1)/4 (MAXIMUM ALLOWABLE EXPONENT),
3727 * WHERE W IS THE LARGEST INTEGER OF THE FORM 2**K-1 WHICH IS
3728 * REPRESENTABLE IN THE MACHINE, K .LE. 47
3729 * THE COMPUTED B AND T SATISFY THE CONDITIONS
3730 * (T-1)*LN(B)/LN(10) .GE. IDECPL AND 8*B*B-1 .LE. W .
3731 * APPROXIMATELY MINIMAL T AND MAXIMAL B SATISFYING
3732 * THESE CONDITIONS ARE CHOSEN.
3733 * PARAMETERS IDECPL, ITMAX2 AND MAXDR ARE INTEGERS.
3734 * BEWARE - MPSET WILL CAUSE AN INTEGER OVERFLOW TO OCCUR
3735 * ****** IF WORDLENGTH IS LESS THAN 48 BITS.
3736 * IF THIS IS NOT ALLOWABLE, CHANGE THE DETERMINATION
3737 * OF W (DO 30 ... TO 30 W = WN) OR SET B, T, M,
3738 * AND MXR WITHOUT CALLING MPSET.
3744 /* DETERMINE LARGE REPRESENTABLE INTEGER W OF FORM 2**K - 1 */
3749 /* ON CYBER 76 HAVE TO FIND K .LE. 47, SO ONLY LOOP
3750 * 47 TIMES AT MOST. IF GENUINE INTEGER WORDLENGTH
3751 * EXCEEDS 47 BITS THIS RESTRICTION CAN BE RELAXED.
3754 for (i = 1; i <= 47; ++i)
3757 /* INTEGER OVERFLOW WILL EVENTUALLY OCCUR HERE
3758 * IF WORDLENGTH .LT. 48 BITS
3764 /* APPARENTLY REDUNDANT TESTS MAY BE NECESSARY ON SOME
3765 * MACHINES, DEPENDING ON HOW INTEGER OVERFLOW IS HANDLED
3768 if (wn <= w || wn <= w2 || wn <= 0) goto L40 ;
3773 /* SET MAXIMUM EXPONENT TO (W-1)/4 */
3777 if (*idecpl > 0) goto L60 ;
3779 if (v->MPerrors) _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_SETB]) ;
3784 /* B IS THE LARGEST POWER OF 2 SUCH THAT (8*B*B-1) .LE. W */
3787 i__1 = (k - 3) / 2 ;
3788 MP.b = pow_ii(&c__2, &i__1) ;
3790 /* 2E0 BELOW ENSURES AT LEAST ONE GUARD DIGIT */
3792 MP.t = (int) ((float) (*idecpl) * log((float)10.) / log((float)
3793 MP.b) + (float)2.0) ;
3795 /* SEE IF T TOO LARGE FOR DIMENSION STATEMENTS */
3798 if (i2 <= *itmax2) goto L80 ;
3804 _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_SETC]) ;
3805 _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_SETD]) ;
3806 msg = (char *) XtMalloc(strlen( mpstrs[(int) MP_SETE]) + 200);
3807 sprintf(msg, mpstrs[(int) MP_SETE], i2) ;
3808 _DtSimpleError (v->appname, DtWarning, NULL, msg);
3814 /* REDUCE TO MAXIMUM ALLOWED BY DIMENSION STATEMENTS */
3816 MP.t = *itmax2 - 2 ;
3818 /* CHECK LEGALITY OF B, T, M AND MXR (AT LEAST T+4) */
3821 mpchk(&c__1, &c__4) ;
3827 mpsin(int *x, int *y)
3831 static int i2, i3, ie, xs ;
3832 static float rx, ry ;
3834 /* RETURNS Y = SIN(X) FOR MP X AND Y,
3835 * METHOD IS TO REDUCE X TO (-1, 1) AND USE MPSIN1, SO
3836 * TIME IS O(M(T)T/LOG(T)).
3837 * DIMENSION OF R IN CALLING PROGRAM MUST BE AT LEAST 5T+12
3838 * CHECK LEGALITY OF B, T, M AND MXR
3841 --y ; /* Parameter adjustments */
3844 mpchk(&c__5, &c__12) ;
3845 i2 = (MP.t << 2) + 11 ;
3846 if (x[1] != 0) goto L20 ;
3855 if (ie <= 2) mpcmr(&x[1], &rx) ;
3857 mpabs(&x[1], &MP.r[i2 - 1]) ;
3859 /* USE MPSIN1 IF ABS(X) .LE. 1 */
3861 if (mpcmpi(&MP.r[i2 - 1], &c__1) > 0) goto L30 ;
3863 mpsin1(&MP.r[i2 - 1], &y[1], &c__1) ;
3866 /* FIND ABS(X) MODULO 2PI (IT WOULD SAVE TIME IF PI WERE
3867 * PRECOMPUTED AND SAVED IN COMMON).
3868 * FOR INCREASED ACCURACY COMPUTE PI/4 USING MPART1
3872 i3 = (MP.t << 1) + 7 ;
3873 mpart1(&c__5, &MP.r[i3 - 1]) ;
3874 mpmuli(&MP.r[i3 - 1], &c__4, &MP.r[i3 - 1]) ;
3875 mpart1(&c__239, &y[1]) ;
3876 mpsub(&MP.r[i3 - 1], &y[1], &y[1]) ;
3877 mpdiv(&MP.r[i2 - 1], &y[1], &MP.r[i2 - 1]) ;
3878 mpdivi(&MP.r[i2 - 1], &c__8, &MP.r[i2 - 1]) ;
3879 mpcmf(&MP.r[i2 - 1], &MP.r[i2 - 1]) ;
3881 /* SUBTRACT 1/2, SAVE SIGN AND TAKE ABS */
3883 mpaddq(&MP.r[i2 - 1], &c_n1, &c__2, &MP.r[i2 - 1]) ;
3884 xs = -xs * MP.r[i2 - 1] ;
3885 if (xs == 0) goto L10 ;
3888 mpmuli(&MP.r[i2 - 1], &c__4, &MP.r[i2 - 1]) ;
3890 /* IF NOT LESS THAN 1, SUBTRACT FROM 2 */
3893 mpaddi(&MP.r[i2 - 1], &c_n2, &MP.r[i2 - 1]) ;
3895 if (MP.r[i2 - 1] == 0) goto L10 ;
3898 mpmuli(&MP.r[i2 - 1], &c__2, &MP.r[i2 - 1]) ;
3900 /* NOW REDUCED TO FIRST QUADRANT, IF LESS THAN PI/4 USE
3901 * POWER SERIES, ELSE COMPUTE COS OF COMPLEMENT
3904 if (MP.r[i2] > 0) goto L40 ;
3906 mpmul(&MP.r[i2 - 1], &y[1], &MP.r[i2 - 1]) ;
3907 mpsin1(&MP.r[i2 - 1], &y[1], &c__1) ;
3911 mpaddi(&MP.r[i2 - 1], &c_n2, &MP.r[i2 - 1]) ;
3912 mpmul(&MP.r[i2 - 1], &y[1], &MP.r[i2 - 1]) ;
3913 mpsin1(&MP.r[i2 - 1], &y[1], &c__0) ;
3917 if (ie > 2) return ;
3919 /* CHECK THAT ABSOLUTE ERROR LESS THAN 0.01 IF ABS(X) .LE. 100
3920 * (IF ABS(X) IS LARGE THEN SINGLE-PRECISION SIN INACCURATE)
3923 if (dabs(rx) > (float)100.) return ;
3926 if ((r__1 = ry - sin(rx), dabs(r__1)) < (float) 0.01) return ;
3928 /* THE FOLLOWING MESSAGE MAY INDICATE THAT
3929 * B**(T-1) IS TOO SMALL.
3932 if (v->MPerrors) _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_SIN]) ;
3940 mpsin1(int *x, int *y, int *is)
3944 static int i, b2, i2, i3, ts ;
3946 /* COMPUTES Y = SIN(X) IF IS.NE.0, Y = COS(X) IF IS.EQ.0,
3947 * USING TAYLOR SERIES. ASSUMES ABS(X) .LE. 1.
3948 * X AND Y ARE MP NUMBERS, IS AN INTEGER.
3949 * TIME IS O(M(T)T/LOG(T)). THIS COULD BE REDUCED TO
3950 * O(SQRT(T)M(T)) AS IN MPEXP1, BUT NOT WORTHWHILE UNLESS
3951 * T IS VERY LARGE. ASYMPTOTICALLY FASTER METHODS ARE
3952 * DESCRIBED IN THE REFERENCES GIVEN IN COMMENTS
3953 * TO MPATAN AND MPPIGL.
3954 * DIMENSION OF R IN CALLING PROGRAM MUST BE AT LEAST 3T+8
3955 * CHECK LEGALITY OF B, T, M AND MXR
3958 --y ; /* Parameter adjustments */
3961 mpchk(&c__3, &c__8) ;
3962 if (x[1] != 0) goto L20 ;
3964 /* SIN(0) = 0, COS(0) = 1 */
3968 if (*is == 0) mpcim(&c__1, &y[1]) ;
3973 i3 = i2 + MP.t + 2 ;
3974 b2 = max(MP.b,64) << 1 ;
3975 mpmul(&x[1], &x[1], &MP.r[i3 - 1]) ;
3976 if (mpcmpi(&MP.r[i3 - 1], &c__1) <= 0) goto L40 ;
3978 if (v->MPerrors) _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_SIN1]) ;
3984 if (*is == 0) mpcim(&c__1, &MP.r[i2 - 1]) ;
3985 if (*is != 0) mpstr(&x[1], &MP.r[i2 - 1]) ;
3990 if (*is == 0) goto L50 ;
3992 mpstr(&MP.r[i2 - 1], &y[1]) ;
3995 /* POWER SERIES LOOP. REDUCE T IF POSSIBLE */
3998 MP.t = MP.r[i2] + ts + 2 ;
3999 if (MP.t <= 2) goto L80 ;
4001 MP.t = min(MP.t,ts) ;
4003 /* PUT R(I3) FIRST IN CASE ITS DIGITS ARE MAINLY ZERO */
4005 mpmul(&MP.r[i3 - 1], &MP.r[i2 - 1], &MP.r[i2 - 1]) ;
4007 /* IF I*(I+1) IS NOT REPRESENTABLE AS AN INTEGER, THE FOLLOWING
4008 * DIVISION BY I*(I+1) HAS TO BE SPLIT UP.
4011 if (i > b2) goto L60 ;
4013 i__1 = -i * (i + 1) ;
4014 mpdivi(&MP.r[i2 - 1], &i__1, &MP.r[i2 - 1]) ;
4019 mpdivi(&MP.r[i2 - 1], &i__1, &MP.r[i2 - 1]) ;
4021 mpdivi(&MP.r[i2 - 1], &i__1, &MP.r[i2 - 1]) ;
4026 mpadd2(&MP.r[i2 - 1], &y[1], &y[1], &y[1], &c__0) ;
4027 if (MP.r[i2 - 1] != 0) goto L50 ;
4031 if (*is == 0) mpaddi(&y[1], &c__1, &y[1]) ;
4037 mpsinh(int *x, int *y)
4041 static int i2, i3, xs ;
4043 /* RETURNS Y = SINH(X) FOR MP NUMBERS X AND Y, X NOT TOO LARGE.
4044 * METHOD IS TO USE MPEXP OR MPEXP1, SPACE = 5T+12
4045 * SAVE SIGN OF X AND CHECK FOR ZERO, SINH(0) = 0
4048 --y ; /* Parameter adjustments */
4052 if (xs != 0) goto L10 ;
4057 /* CHECK LEGALITY OF B, T, M AND MXR */
4060 mpchk(&c__5, &c__12) ;
4061 i3 = (MP.t << 2) + 11 ;
4063 /* WORK WITH ABS(X) */
4065 mpabs(&x[1], &MP.r[i3 - 1]) ;
4066 if (MP.r[i3] <= 0) goto L20 ;
4068 /* HERE ABS(X) .GE. 1, IF TOO LARGE MPEXP GIVES ERROR MESSAGE
4069 * INCREASE M TO AVOID OVERFLOW IF SINH(X) REPRESENTABLE
4073 mpexp(&MP.r[i3 - 1], &MP.r[i3 - 1]) ;
4074 mprec(&MP.r[i3 - 1], &y[1]) ;
4075 mpsub(&MP.r[i3 - 1], &y[1], &y[1]) ;
4077 /* RESTORE M. IF RESULT OVERFLOWS OR UNDERFLOWS, MPDIVI AT
4078 * STATEMENT 30 WILL ACT ACCORDINGLY.
4084 /* HERE ABS(X) .LT. 1 SO USE MPEXP1 TO AVOID CANCELLATION */
4087 i2 = i3 - (MP.t + 2) ;
4088 mpexp1(&MP.r[i3 - 1], &MP.r[i2 - 1]) ;
4089 mpaddi(&MP.r[i2 - 1], &c__2, &MP.r[i3 - 1]) ;
4090 mpmul(&MP.r[i3 - 1], &MP.r[i2 - 1], &y[1]) ;
4091 mpaddi(&MP.r[i2 - 1], &c__1, &MP.r[i3 - 1]) ;
4092 mpdiv(&y[1], &MP.r[i3 - 1], &y[1]) ;
4094 /* DIVIDE BY TWO AND RESTORE SIGN */
4098 mpdivi(&y[1], &i__1, &y[1]) ;
4104 mpsqrt(int *x, int *y)
4106 static int i, i2, iy3 ;
4108 /* RETURNS Y = SQRT(X), USING SUBROUTINE MPROOT IF X .GT. 0.
4109 * DIMENSION OF R IN CALLING PROGRAM MUST BE AT LEAST 4T+10
4110 * (BUT Y(1) MAY BE R(3T+9)). X AND Y ARE MP NUMBERS.
4111 * CHECK LEGALITY OF B, T, M AND MXR
4114 --y ; /* Parameter adjustments */
4117 mpchk(&c__4, &c__10) ;
4119 /* MPROOT NEEDS 4T+10 WORDS, BUT CAN OVERLAP SLIGHTLY. */
4122 if (x[1] < 0) goto L10 ;
4123 else if (x[1] == 0) goto L30 ;
4127 if (v->MPerrors) _DtSimpleError (v->appname, DtWarning, NULL, mpstrs[(int) MP_SQRT]) ;
4136 mproot(&x[1], &c_n2, &MP.r[i2 - 1]) ;
4138 mpmul(&x[1], &MP.r[i2 - 1], &y[1]) ;
4140 mpext(&i, &iy3, &y[1]) ;
4146 mpstr(int *x, int *y)
4150 static int i, j, t2 ;
4152 /* SETS Y = X FOR MP X AND Y.
4153 * SEE IF X AND Y HAVE THE SAME ADDRESS (THEY OFTEN DO)
4156 --y ; /* Parameter adjustments */
4161 if (j == x[1]) goto L10 ;
4163 /* HERE X(1) AND Y(1) MUST HAVE THE SAME ADDRESS */
4168 /* HERE X(1) AND Y(1) HAVE DIFFERENT ADDRESSES */
4173 /* NO NEED TO MOVE X(2), ... IF X(1) = 0 */
4175 if (j == 0) return ;
4179 for (i = 2; i <= i__1; ++i) y[i] = x[i] ;
4185 mpsub(int *x, int *y, int *z)
4189 /* SUBTRACTS Y FROM X, FORMING RESULT IN Z, FOR MP X, Y AND Z.
4190 * FOUR GUARD DIGITS ARE USED, AND THEN R*-ROUNDING
4193 --z ; /* Parameter adjustments */
4198 mpadd2(&x[1], &y[1], &z[1], y1, &c__0) ;
4204 mptanh(int *x, int *y)
4210 /* RETURNS Y = TANH(X) FOR MP NUMBERS X AND Y,
4211 * USING MPEXP OR MPEXP1, SPACE = 5T+12
4214 --y ; /* Parameter adjustments */
4217 if (x[1] != 0) goto L10 ;
4224 /* CHECK LEGALITY OF B, T, M AND MXR */
4227 mpchk(&c__5, &c__12) ;
4228 i2 = (MP.t << 2) + 11 ;
4230 /* SAVE SIGN AND WORK WITH ABS(X) */
4233 mpabs(&x[1], &MP.r[i2 - 1]) ;
4235 /* SEE IF ABS(X) SO LARGE THAT RESULT IS +-1 */
4237 r__1 = (float) MP.t * (float).5 * log((float) MP.b) ;
4238 mpcrm(&r__1, &y[1]) ;
4239 if (mpcomp(&MP.r[i2 - 1], &y[1]) <= 0) goto L20 ;
4241 /* HERE ABS(X) IS VERY LARGE */
4246 /* HERE ABS(X) NOT SO LARGE */
4249 mpmuli(&MP.r[i2 - 1], &c__2, &MP.r[i2 - 1]) ;
4250 if (MP.r[i2] <= 0) goto L30 ;
4252 /* HERE ABS(X) .GE. 1/2 SO USE MPEXP */
4254 mpexp(&MP.r[i2 - 1], &MP.r[i2 - 1]) ;
4255 mpaddi(&MP.r[i2 - 1], &c_n1, &y[1]) ;
4256 mpaddi(&MP.r[i2 - 1], &c__1, &MP.r[i2 - 1]) ;
4257 mpdiv(&y[1], &MP.r[i2 - 1], &y[1]) ;
4260 /* HERE ABS(X) .LT. 1/2, SO USE MPEXP1 TO AVOID CANCELLATION */
4263 mpexp1(&MP.r[i2 - 1], &MP.r[i2 - 1]) ;
4264 mpaddi(&MP.r[i2 - 1], &c__2, &y[1]) ;
4265 mpdiv(&MP.r[i2 - 1], &y[1], &y[1]) ;
4279 /* CALLED ON MULTIPLE-PRECISION UNDERFLOW, IE WHEN THE
4280 * EXPONENT OF MP NUMBER X WOULD BE LESS THAN -M.
4281 * SINCE M MAY HAVE BEEN OVERWRITTEN, CHECK B, T, M ETC.
4284 --x ; /* Parameter adjustments */
4286 mpchk(&c__1, &c__4) ;
4288 /* THE UNDERFLOWING NUMBER IS SET TO ZERO
4289 * AN ALTERNATIVE WOULD BE TO CALL MPMINR (X) AND RETURN,
4290 * POSSIBLY UPDATING A COUNTER AND TERMINATING EXECUTION
4291 * AFTER A PRESET NUMBER OF UNDERFLOWS. ACTION COULD EASILY
4292 * BE DETERMINED BY A FLAG IN LABELLED COMMON.
4301 mppow_di(double *ap, int *bp)
4314 if (x == 0) return(pow) ;
4320 if (n & 01) pow *= x;
4321 if (n >>= 1) x *= x ;
4330 pow_ii(int *ap, int *bp)
4341 if (n & 01) pow *= x ;
4342 if (n >>= 1) x *= x ;
4350 mppow_ri(float *ap, int *bp)
4363 if (x == 0) return(pow) ;
4369 if (n & 01) pow *= x ;
4370 if (n >>= 1) x *= x ;