[gcalctool] General tidyups



commit 41b31f5bdc615160b60483408a04d038cd225fb7
Author: Robert Ancell <robert ancell gmail com>
Date:   Tue May 19 14:53:40 2009 +0200

    General tidyups
---
 src/mp.c |  636 ++++++++++++++++++++++++++++++-------------------------------
 1 files changed, 313 insertions(+), 323 deletions(-)

diff --git a/src/mp.c b/src/mp.c
index afe5d50..8ea8330 100644
--- a/src/mp.c
+++ b/src/mp.c
@@ -31,15 +31,121 @@
 // FIXME: MP.t and MP.m modified inside functions, needs to be fixed to be thread safe
 
 static int mp_compare_mp_to_float(const MPNumber *, float);
-static int pow_ii(int, int);
 
-static void mpadd2(const MPNumber *, const MPNumber *, MPNumber *, int, int);
-static int  mpadd3(const MPNumber *, const MPNumber *, int *, int, int);
-static void mpext(int, int, MPNumber *);
-static void mplns(const MPNumber *, MPNumber *);
-static void mpmaxr(MPNumber *);
-static void mpovfl(MPNumber *, const char *);
-static void mpunfl(MPNumber *);
+/*  SETS X TO THE LARGEST POSSIBLE POSITIVE MP NUMBER
+ *  CHECK LEGALITY OF B, T, M AND MXR
+ */
+static void
+mpmaxr(MPNumber *x)
+{
+    int i, it;
+
+    mpchk();
+    it = MP.b - 1;
+
+    /* SET FRACTION DIGITS TO B-1 */
+    for (i = 0; i < MP.t; i++)
+        x->fraction[i] = it;
+
+    /* SET SIGN AND EXPONENT */
+    x->sign = 1;
+    x->exponent = MP.m;
+}
+
+
+/*  CALLED ON MULTIPLE-PRECISION OVERFLOW, IE WHEN THE
+ *  EXPONENT OF MP NUMBER X WOULD EXCEED M.
+ *  AT PRESENT EXECUTION IS TERMINATED WITH AN ERROR MESSAGE
+ *  AFTER CALLING MPMAXR(X), BUT IT WOULD BE POSSIBLE TO RETURN,
+ *  POSSIBLY UPDATING A COUNTER AND TERMINATING EXECUTION AFTER
+ *  A PRESET NUMBER OF OVERFLOWS.  ACTION COULD EASILY BE DETERMINED
+ *  BY A FLAG IN LABELLED COMMON.
+ *  M MAY HAVE BEEN OVERWRITTEN, SO CHECK B, T, M ETC.
+ */
+static void
+mpovfl(MPNumber *x, const char *error)
+{
+    fprintf(stderr, "%s\n", error);
+    
+    mpchk();
+
+    /* SET X TO LARGEST POSSIBLE POSITIVE NUMBER */
+    mpmaxr(x);
+
+    /* TERMINATE EXECUTION BY CALLING MPERR */
+    mperr("*** CALL TO MPOVFL, MP OVERFLOW OCCURRED ***");
+}
+
+
+/*  CALLED ON MULTIPLE-PRECISION UNDERFLOW, IE WHEN THE
+ *  EXPONENT OF MP NUMBER X WOULD BE LESS THAN -M.
+ *  SINCE M MAY HAVE BEEN OVERWRITTEN, CHECK B, T, M ETC.
+ */
+static void
+mpunfl(MPNumber *x)
+{
+    mpchk();
+
+    /*  THE UNDERFLOWING NUMBER IS SET TO ZERO
+     *  AN ALTERNATIVE WOULD BE TO CALL MPMINR (X) AND RETURN,
+     *  POSSIBLY UPDATING A COUNTER AND TERMINATING EXECUTION
+     *  AFTER A PRESET NUMBER OF UNDERFLOWS.  ACTION COULD EASILY
+     *  BE DETERMINED BY A FLAG IN LABELLED COMMON.
+     */
+    x->sign = 0;
+}
+
+
+static int
+pow_ii(int x, int n)
+{
+    int pow = 1;
+
+    if (n > 0) {
+        for (;;) { 
+            if (n & 01) pow *= x;
+            if (n >>= 1) x *= x;
+            else break;
+        }
+    }
+
+    return(pow);
+}
+
+
+/*  ROUTINE CALLED BY MP_DIVIDE AND MP_SQRT TO ENSURE THAT
+ *  RESULTS ARE REPRESENTED EXACTLY IN T-2 DIGITS IF THEY
+ *  CAN BE.  X IS AN MP NUMBER, I AND J ARE INTEGERS.
+ */
+static void
+mpext(int i, int j, MPNumber *x)
+{
+    int q, s;
+
+    if (x->sign == 0 || MP.t <= 2 || i == 0)
+        return;
+
+    /* COMPUTE MAXIMUM POSSIBLE ERROR IN THE LAST PLACE */
+    q = (j + 1) / i + 1;
+    s = MP.b * x->fraction[MP.t - 2] + x->fraction[MP.t - 1];
+
+    /* SET LAST TWO DIGITS TO ZERO */    
+    if (s <= q) {
+        x->fraction[MP.t - 2] = 0;
+        x->fraction[MP.t - 1] = 0;
+        return;
+    }
+
+    if (s + q < MP.b * MP.b)
+        return;
+
+    /* ROUND UP HERE */
+    x->fraction[MP.t - 2] = MP.b - 1;
+    x->fraction[MP.t - 1] = MP.b;
+
+    /* NORMALIZE X (LAST DIGIT B IS OK IN MP_MULTIPLY_INTEGER) */
+    mp_multiply_integer(x, 1, x);
+}
 
 
 /*  SETS BASE (B) AND NUMBER OF DIGITS (T) TO GIVE THE
@@ -119,6 +225,22 @@ mp_init(int accuracy)
 }
 
 
+/*  CHECKS LEGALITY OF B, T, M AND MXR.
+ *  THE CONDITION ON MXR (THE DIMENSION OF R IN COMMON) IS THAT
+ *  MXR >= (I*T + J)
+ */
+// FIXME: MP.t is changed around calls to add/subtract/multiply/divide - it should not be global
+void
+mpchk()
+{
+    /* CHECK LEGALITY OF T AND M */
+    if (MP.t <= 1)
+        mperr("*** T = %d ILLEGAL IN CALL TO MPCHK, PERHAPS NOT SET BEFORE CALL TO AN MP ROUTINE ***", MP.t);
+    if (MP.m <= MP.t)
+        mperr("*** M <= T IN CALL TO MPCHK, PERHAPS NOT SET BEFORE CALL TO AN MP ROUTINE ***");
+}
+
+
 /* SETS Y = ABS(X) FOR MP NUMBERS X AND Y */
 void
 mp_abs(const MPNumber *x, MPNumber *z)
@@ -128,114 +250,11 @@ mp_abs(const MPNumber *x, MPNumber *z)
         z->sign = -z->sign;
 }
 
-/*  ADDS X AND Y, FORMING RESULT IN Z, WHERE X, Y AND Z ARE MP
- *  NUMBERS.  FOUR GUARD DIGITS ARE USED, AND THEN R*-ROUNDING.
- */
-void
-mp_add(const MPNumber *x, const MPNumber *y, MPNumber *z)
-{
-    mpadd2(x, y, z, y->sign, 0);
-}
-
-/*  CALLED BY MP_ADD, MP_SUBTRACT ETC.
- *  X, Y AND Z ARE MP NUMBERS, Y_SIGN AND TRUNC ARE INTEGERS.
- *  SETS Z = X + Y_SIGN*ABS(Y), WHERE Y_SIGN = +- y->sign.
- *  IF TRUNC == 0 R*-ROUNDING IS USED, OTHERWISE TRUNCATION.
- *  R*-ROUNDING IS DEFINED IN KUKI AND CODI, COMM. ACM
- *  16(1973), 223.  (SEE ALSO BRENT, IEEE TC-22(1973), 601.)
- *  CHECK FOR X OR Y ZERO
- */
-static void
-mpadd2(const MPNumber *x, const MPNumber *y, MPNumber *z, int y_sign, int trunc)
-{
-    int sign_prod;
-    int exp_diff, med;
-    int x_largest = 0;
-    MPNumber zt; // Use stack variable because of mp_normalize brokeness
-
-    /* X = 0 OR NEGLIGIBLE, SO RESULT = +-Y */
-    if (x->sign == 0) {
-        mp_set_from_mp(y, z);
-        z->sign = y_sign;
-        return;
-    }
-
-    /* Y = 0 OR NEGLIGIBLE, SO RESULT = X */    
-    if (y_sign == 0 || y->sign == 0) {
-        mp_set_from_mp(x, z);
-        return;
-    }
-
-    /* COMPARE SIGNS */
-    sign_prod = y_sign * x->sign;
-    if (abs(sign_prod) > 1) {
-        mpchk();
-        mperr("*** SIGN NOT 0, +1 OR -1 IN MPADD2 CALL, POSSIBLE OVERWRITING PROBLEM ***");
-        z->sign = 0;
-        return;
-    }
-
-    /* COMPARE EXPONENTS */
-    exp_diff = x->exponent - y->exponent;
-    med = abs(exp_diff);
-    if (exp_diff < 0) {
-        /* HERE EXPONENT(Y)  >  EXPONENT(X) */
-        if (med > MP.t) {
-            /* 'y' so much larger than 'x' that 'x+-y = y'.  Warning: still true with rounding??  */
-            mp_set_from_mp(y, z);
-            z->sign = y_sign;
-            return;
-        }
-        x_largest = 0;
-    } else if (exp_diff > 0) {
-        /* HERE EXPONENT(X)  >  EXPONENT(Y) */
-        if (med > MP.t) {
-            /* 'x' so much larger than 'y' that 'x+-y = x'.  Warning: still true with rounding??  */
-            mp_set_from_mp(x, z);
-            return;
-        }
-        x_largest = 1;
-    } else {
-        /* EXPONENTS EQUAL SO COMPARE SIGNS, THEN FRACTIONS IF NEC. */
-        if (sign_prod < 0) {
-            /* Signs are not equal.  find out which mantissa is larger. */
-            int j;
-            for (j = 0; j < MP.t; j++) {
-                int i = x->fraction[j] - y->fraction[j];
-                if (i == 0)
-                    continue;
-                if (i < 0)
-                    x_largest = 0;
-                else if (i > 0)
-                    x_largest = 1;
-                break;
-            }
-            
-            /* Both mantissas equal, so result is zero. */
-            if (j >= MP.t) {
-                z->sign = 0;
-                return;
-            }
-        }
-    }
-
-    /* NORMALIZE, ROUND OR TRUNCATE, AND RETURN */
-    if (x_largest) {
-        zt.sign = x->sign;
-        zt.exponent = x->exponent + mpadd3(y, x, zt.fraction, sign_prod, med);
-    } else {
-        zt.sign = y_sign;
-        zt.exponent = y->exponent + mpadd3(x, y, zt.fraction, sign_prod, med);
-    }
-    mp_normalize(&zt, trunc);
-    mp_set_from_mp(&zt, z);
-}
-
 
 /* CALLED BY MPADD2, DOES INNER LOOPS OF ADDITION */
 /* return value is amount by which exponent needs to be increased. */
 static int
-mpadd3(const MPNumber *x, const MPNumber *y, int *r, int s, int med)
+mp_add3(const MPNumber *x, const MPNumber *y, int *r, int s, int med)
 {
     int i, c;
     
@@ -340,6 +359,104 @@ mpadd3(const MPNumber *x, const MPNumber *y, int *r, int s, int med)
 }
 
 
+/* z = x + y_sign * abs(y) */
+static void
+mp_add2(const MPNumber *x, const MPNumber *y, int y_sign, MPNumber *z)
+{
+    int sign_prod;
+    int exp_diff, med;
+    int x_largest = 0;
+    MPNumber zt; // Use stack variable because of mp_normalize brokeness
+
+    /* X = 0 OR NEGLIGIBLE, SO RESULT = +-Y */
+    if (x->sign == 0) {
+        mp_set_from_mp(y, z);
+        z->sign = y_sign;
+        return;
+    }
+
+    /* Y = 0 OR NEGLIGIBLE, SO RESULT = X */    
+    if (y->sign == 0 || y->sign == 0) {
+        mp_set_from_mp(x, z);
+        return;
+    }
+
+    /* COMPARE SIGNS */
+    sign_prod = y_sign * x->sign;
+    if (abs(sign_prod) > 1) {
+        mpchk();
+        mperr("*** SIGN NOT 0, +1 OR -1 IN MP_ADD2 CALL, POSSIBLE OVERWRITING PROBLEM ***");
+        z->sign = 0;
+        return;
+    }
+
+    /* COMPARE EXPONENTS */
+    exp_diff = x->exponent - y->exponent;
+    med = abs(exp_diff);
+    if (exp_diff < 0) {
+        /* HERE EXPONENT(Y)  >  EXPONENT(X) */
+        if (med > MP.t) {
+            /* 'y' so much larger than 'x' that 'x+-y = y'.  Warning: still true with rounding??  */
+            mp_set_from_mp(y, z);
+            z->sign = y_sign;
+            return;
+        }
+        x_largest = 0;
+    } else if (exp_diff > 0) {
+        /* HERE EXPONENT(X)  >  EXPONENT(Y) */
+        if (med > MP.t) {
+            /* 'x' so much larger than 'y' that 'x+-y = x'.  Warning: still true with rounding??  */
+            mp_set_from_mp(x, z);
+            return;
+        }
+        x_largest = 1;
+    } else {
+        /* EXPONENTS EQUAL SO COMPARE SIGNS, THEN FRACTIONS IF NEC. */
+        if (sign_prod < 0) {
+            /* Signs are not equal.  find out which mantissa is larger. */
+            int j;
+            for (j = 0; j < MP.t; j++) {
+                int i = x->fraction[j] - y->fraction[j];
+                if (i == 0)
+                    continue;
+                if (i < 0)
+                    x_largest = 0;
+                else if (i > 0)
+                    x_largest = 1;
+                break;
+            }
+            
+            /* Both mantissas equal, so result is zero. */
+            if (j >= MP.t) {
+                z->sign = 0;
+                return;
+            }
+        }
+    }
+
+    /* NORMALIZE, ROUND OR TRUNCATE, AND RETURN */
+    if (x_largest) {
+        zt.sign = x->sign;
+        zt.exponent = x->exponent + mp_add3(y, x, zt.fraction, sign_prod, med);
+    } else {
+        zt.sign = y_sign;
+        zt.exponent = y->exponent + mp_add3(x, y, zt.fraction, sign_prod, med);
+    }
+    mp_normalize(&zt, 0);
+    mp_set_from_mp(&zt, z);   
+}
+
+
+/*  ADDS X AND Y, FORMING RESULT IN Z, WHERE X, Y AND Z ARE MP
+ *  NUMBERS.  FOUR GUARD DIGITS ARE USED, AND THEN R*-ROUNDING.
+ */
+void
+mp_add(const MPNumber *x, const MPNumber *y, MPNumber *z)
+{
+    mp_add2(x, y, y->sign, z);
+}
+
+
 /*  ADDS MULTIPLE-PRECISION X TO INTEGER Y
  *  GIVING MULTIPLE-PRECISION Z.
  *  DIMENSION OF R IN CALLING PROGRAM MUST BE
@@ -372,21 +489,6 @@ mp_add_fraction(const MPNumber *x, int i, int j, MPNumber *y)
 }
 
 
-/*  CHECKS LEGALITY OF B, T, M AND MXR.
- *  THE CONDITION ON MXR (THE DIMENSION OF R IN COMMON) IS THAT
- *  MXR >= (I*T + J)
- */
-// FIXME: MP.t is changed around calls to add/subtract/multiply/divide - it should not be global
-void
-mpchk()
-{
-    /* CHECK LEGALITY OF T AND M */
-    if (MP.t <= 1)
-        mperr("*** T = %d ILLEGAL IN CALL TO MPCHK, PERHAPS NOT SET BEFORE CALL TO AN MP ROUTINE ***", MP.t);
-    if (MP.m <= MP.t)
-        mperr("*** M <= T IN CALL TO MPCHK, PERHAPS NOT SET BEFORE CALL TO AN MP ROUTINE ***");
-}
-
 /*  FOR MP X AND Y, RETURNS FRACTIONAL PART OF X IN Y,
  *  I.E., Y = X - INTEGER PART OF X (TRUNCATED TOWARDS 0).
  */
@@ -1026,41 +1128,6 @@ mpexp1(const MPNumber *x, MPNumber *y)
 }
 
 
-/*  ROUTINE CALLED BY MP_DIVIDE AND MP_SQRT TO ENSURE THAT
- *  RESULTS ARE REPRESENTED EXACTLY IN T-2 DIGITS IF THEY
- *  CAN BE.  X IS AN MP NUMBER, I AND J ARE INTEGERS.
- */
-static void
-mpext(int i, int j, MPNumber *x)
-{
-    int q, s;
-
-    if (x->sign == 0 || MP.t <= 2 || i == 0)
-        return;
-
-    /* COMPUTE MAXIMUM POSSIBLE ERROR IN THE LAST PLACE */
-    q = (j + 1) / i + 1;
-    s = MP.b * x->fraction[MP.t - 2] + x->fraction[MP.t - 1];
-
-    /* SET LAST TWO DIGITS TO ZERO */    
-    if (s <= q) {
-        x->fraction[MP.t - 2] = 0;
-        x->fraction[MP.t - 1] = 0;
-        return;
-    }
-
-    if (s + q < MP.b * MP.b)
-        return;
-
-    /* ROUND UP HERE */
-    x->fraction[MP.t - 2] = MP.b - 1;
-    x->fraction[MP.t - 1] = MP.b;
-
-    /* NORMALIZE X (LAST DIGIT B IS OK IN MP_MULTIPLY_INTEGER) */
-    mp_multiply_integer(x, 1, x);
-}
-
-
 /*  RETURNS K = K/GCD AND L = L/GCD, WHERE GCD IS THE
  *  GREATEST COMMON DIVISOR OF K AND L.
  *  SAVE INPUT PARAMETERS IN LOCAL VARIABLES
@@ -1138,93 +1205,6 @@ mp_is_less_equal(const MPNumber *x, const MPNumber *y)
 }
 
 
-/*  RETURNS Y = LN(X), FOR MP X AND Y, USING MPLNS.
- *  RESTRICTION - INTEGER PART OF LN(X) MUST BE REPRESENTABLE
- *  AS A SINGLE-PRECISION INTEGER.  TIME IS O(SQRT(T).M(T)).
- *  FOR SMALL INTEGER X, MPLNI IS FASTER.
- *  ASYMPTOTICALLY FASTER METHODS EXIST (EG THE GAUSS-SALAMIN
- *  METHOD, SEE MPLNGS), BUT ARE NOT USEFUL UNLESS T IS LARGE.
- *  SEE COMMENTS TO MP_ATAN, MPEXP1 AND MPPIGL.
- *  DIMENSION OF R IN CALLING PROGRAM MUST BE AT LEAST 6T+14.
- *  CHECK LEGALITY OF B, T, M AND MXR
- */
-void
-mp_ln(const MPNumber *x, MPNumber *z)
-{
-    int e, k;
-    float rx, rlx;
-    MPNumber t1, t2;
-    
-    mpchk();
-
-    /* CHECK THAT X IS POSITIVE */
-    if (x->sign <= 0) {
-        mperr("*** X NONPOSITIVE IN CALL TO MP_LN ***");
-        z->sign = 0;
-        return;
-    }
-
-    /* MOVE X TO LOCAL STORAGE */
-    mp_set_from_mp(x, &t1);
-    z->sign = 0;
-    k = 0;
-
-    /* LOOP TO GET APPROXIMATE LN(X) USING SINGLE-PRECISION */
-    while(1)
-    {
-        mp_add_integer(&t1, -1, &t2);
-
-        /* IF POSSIBLE GO TO CALL MPLNS */
-        if (t2.sign == 0 || t2.exponent + 1 <= 0) {
-            /* COMPUTE FINAL CORRECTION ACCURATELY USING MPLNS */
-            mplns(&t2, &t2);
-            mp_add(z, &t2, z);
-            return;
-        }
-
-        /* REMOVE EXPONENT TO AVOID FLOATING-POINT OVERFLOW */
-        e = t1.exponent;
-        t1.exponent = 0;
-        rx = mp_cast_to_float(&t1);
-
-        /* RESTORE EXPONENT AND COMPUTE SINGLE-PRECISION LOG */
-        t1.exponent = e;
-        rlx = log(rx) + (float) e * log((float) MP.b);
-        mp_set_from_float(-(double)rlx, &t2);
-
-        /* UPDATE Z AND COMPUTE ACCURATE EXP OF APPROXIMATE LOG */
-        mp_subtract(z, &t2, z);
-        mp_epowy(&t2, &t2);
-
-        /* COMPUTE RESIDUAL WHOSE LOG IS STILL TO BE FOUND */
-        mp_multiply(&t1, &t2, &t1);
-        
-        /* MAKE SURE NOT LOOPING INDEFINITELY */
-        ++k;
-        if (k >= 10) {
-            mperr("*** ERROR IN MP_LN, ITERATION NOT CONVERGING ***");
-            return;
-        }
-    }
-}
-
-
-/*  MP precision common log.
- *
- *  1. log10(x) = log10(e) * log(x)
- */
-void
-mp_logarithm(int n, MPNumber *x, MPNumber *z)
-{
-    MPNumber t1, t2;
-
-    mp_set_from_integer(n, &t1);
-    mp_ln(&t1, &t1);
-    mp_ln(x, &t2);
-    mp_divide(&t2, &t1, z);
-}
-
-
 /*  RETURNS MP Y = LN(1+X) IF X IS AN MP NUMBER SATISFYING THE
  *  CONDITION ABS(X) < 1/B, ERROR OTHERWISE.
  *  USES NEWTONS METHOD TO SOLVE THE EQUATION
@@ -1309,32 +1289,98 @@ mplns(const MPNumber *x, MPNumber *y)
 }
 
 
-/* RETURNS LOGICAL VALUE OF (X < Y) FOR MP X AND Y. */
-int
-mp_is_less_than(const MPNumber *x, const MPNumber *y)
+/*  RETURNS Y = LN(X), FOR MP X AND Y, USING MPLNS.
+ *  RESTRICTION - INTEGER PART OF LN(X) MUST BE REPRESENTABLE
+ *  AS A SINGLE-PRECISION INTEGER.  TIME IS O(SQRT(T).M(T)).
+ *  FOR SMALL INTEGER X, MPLNI IS FASTER.
+ *  ASYMPTOTICALLY FASTER METHODS EXIST (EG THE GAUSS-SALAMIN
+ *  METHOD, SEE MPLNGS), BUT ARE NOT USEFUL UNLESS T IS LARGE.
+ *  SEE COMMENTS TO MP_ATAN, MPEXP1 AND MPPIGL.
+ *  DIMENSION OF R IN CALLING PROGRAM MUST BE AT LEAST 6T+14.
+ *  CHECK LEGALITY OF B, T, M AND MXR
+ */
+void
+mp_ln(const MPNumber *x, MPNumber *z)
 {
-    return (mp_compare_mp_to_mp(x, y) < 0);
+    int e, k;
+    float rx, rlx;
+    MPNumber t1, t2;
+    
+    mpchk();
+
+    /* CHECK THAT X IS POSITIVE */
+    if (x->sign <= 0) {
+        mperr("*** X NONPOSITIVE IN CALL TO MP_LN ***");
+        z->sign = 0;
+        return;
+    }
+
+    /* MOVE X TO LOCAL STORAGE */
+    mp_set_from_mp(x, &t1);
+    z->sign = 0;
+    k = 0;
+
+    /* LOOP TO GET APPROXIMATE LN(X) USING SINGLE-PRECISION */
+    while(1)
+    {
+        mp_add_integer(&t1, -1, &t2);
+
+        /* IF POSSIBLE GO TO CALL MPLNS */
+        if (t2.sign == 0 || t2.exponent + 1 <= 0) {
+            /* COMPUTE FINAL CORRECTION ACCURATELY USING MPLNS */
+            mplns(&t2, &t2);
+            mp_add(z, &t2, z);
+            return;
+        }
+
+        /* REMOVE EXPONENT TO AVOID FLOATING-POINT OVERFLOW */
+        e = t1.exponent;
+        t1.exponent = 0;
+        rx = mp_cast_to_float(&t1);
+
+        /* RESTORE EXPONENT AND COMPUTE SINGLE-PRECISION LOG */
+        t1.exponent = e;
+        rlx = log(rx) + (float) e * log((float) MP.b);
+        mp_set_from_float(-(double)rlx, &t2);
+
+        /* UPDATE Z AND COMPUTE ACCURATE EXP OF APPROXIMATE LOG */
+        mp_subtract(z, &t2, z);
+        mp_epowy(&t2, &t2);
+
+        /* COMPUTE RESIDUAL WHOSE LOG IS STILL TO BE FOUND */
+        mp_multiply(&t1, &t2, &t1);
+        
+        /* MAKE SURE NOT LOOPING INDEFINITELY */
+        ++k;
+        if (k >= 10) {
+            mperr("*** ERROR IN MP_LN, ITERATION NOT CONVERGING ***");
+            return;
+        }
+    }
 }
 
 
-/*  SETS X TO THE LARGEST POSSIBLE POSITIVE MP NUMBER
- *  CHECK LEGALITY OF B, T, M AND MXR
+/*  MP precision common log.
+ *
+ *  1. log10(x) = log10(e) * log(x)
  */
-static void
-mpmaxr(MPNumber *x)
+void
+mp_logarithm(int n, MPNumber *x, MPNumber *z)
 {
-    int i, it;
+    MPNumber t1, t2;
 
-    mpchk();
-    it = MP.b - 1;
+    mp_set_from_integer(n, &t1);
+    mp_ln(&t1, &t1);
+    mp_ln(x, &t2);
+    mp_divide(&t2, &t1, z);
+}
 
-    /* SET FRACTION DIGITS TO B-1 */
-    for (i = 0; i < MP.t; i++)
-        x->fraction[i] = it;
 
-    /* SET SIGN AND EXPONENT */
-    x->sign = 1;
-    x->exponent = MP.m;
+/* RETURNS LOGICAL VALUE OF (X < Y) FOR MP X AND Y. */
+int
+mp_is_less_than(const MPNumber *x, const MPNumber *y)
+{
+    return (mp_compare_mp_to_mp(x, y) < 0);
 }
 
 
@@ -1735,29 +1781,6 @@ mp_normalize(MPNumber *x, int trunc)
 }
 
 
-/*  CALLED ON MULTIPLE-PRECISION OVERFLOW, IE WHEN THE
- *  EXPONENT OF MP NUMBER X WOULD EXCEED M.
- *  AT PRESENT EXECUTION IS TERMINATED WITH AN ERROR MESSAGE
- *  AFTER CALLING MPMAXR(X), BUT IT WOULD BE POSSIBLE TO RETURN,
- *  POSSIBLY UPDATING A COUNTER AND TERMINATING EXECUTION AFTER
- *  A PRESET NUMBER OF OVERFLOWS.  ACTION COULD EASILY BE DETERMINED
- *  BY A FLAG IN LABELLED COMMON.
- *  M MAY HAVE BEEN OVERWRITTEN, SO CHECK B, T, M ETC.
- */
-static void
-mpovfl(MPNumber *x, const char *error)
-{
-    fprintf(stderr, "%s\n", error);
-    
-    mpchk();
-
-    /* SET X TO LARGEST POSSIBLE POSITIVE NUMBER */
-    mpmaxr(x);
-
-    /* TERMINATE EXECUTION BY CALLING MPERR */
-    mperr("*** CALL TO MPOVFL, MP OVERFLOW OCCURRED ***");
-}
-
 /*  RETURNS Y = X**N, FOR MP X AND Y, INTEGER N, WITH 0**0 = 1.
  *  R MUST BE DIMENSIONED AT LEAST 4T+10 IN CALLING PROGRAM
  *  (2T+6 IS ENOUGH IF N NONNEGATIVE).
@@ -2146,42 +2169,9 @@ mp_sqrt(const MPNumber *x, MPNumber *z)
 void
 mp_subtract(const MPNumber *x, const MPNumber *y, MPNumber *z)
 {
-    mpadd2(x, y, z, -y->sign, 0);
+    mp_add2(x, y, -y->sign, z);
 }
 
-/*  CALLED ON MULTIPLE-PRECISION UNDERFLOW, IE WHEN THE
- *  EXPONENT OF MP NUMBER X WOULD BE LESS THAN -M.
- *  SINCE M MAY HAVE BEEN OVERWRITTEN, CHECK B, T, M ETC.
- */
-static void
-mpunfl(MPNumber *x)
-{
-    mpchk();
-
-    /*  THE UNDERFLOWING NUMBER IS SET TO ZERO
-     *  AN ALTERNATIVE WOULD BE TO CALL MPMINR (X) AND RETURN,
-     *  POSSIBLY UPDATING A COUNTER AND TERMINATING EXECUTION
-     *  AFTER A PRESET NUMBER OF UNDERFLOWS.  ACTION COULD EASILY
-     *  BE DETERMINED BY A FLAG IN LABELLED COMMON.
-     */
-    x->sign = 0;
-}
-
-static int
-pow_ii(int x, int n)
-{
-    int pow = 1;
-
-    if (n > 0) {
-        for (;;) { 
-            if (n & 01) pow *= x;
-            if (n >>= 1) x *= x;
-            else break;
-        }
-    }
-
-    return(pow);
-}
 
 void
 mp_factorial(const MPNumber *x, MPNumber *z)



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]