[gcalctool/gcalctool-newui2] ...



commit 3eda079425fa15a1762c1219ae5a9a6c64e04787
Author: Robert Ancell <robert ancell gmail com>
Date:   Thu Jul 16 13:47:55 2009 +1000

    ...

 data/gcalctool.ui |    1 +
 src/mp-convert.c  |    4 +-
 src/mp-equation.c |    1 -
 src/mp-internal.h |    2 +-
 src/mp.c          |  360 ++++++++++++++++++++++++----------------------------
 5 files changed, 170 insertions(+), 198 deletions(-)
---
diff --git a/data/gcalctool.ui b/data/gcalctool.ui
index 789cd2f..c74cf77 100644
--- a/data/gcalctool.ui
+++ b/data/gcalctool.ui
@@ -4,6 +4,7 @@
   <!-- interface-naming-policy toplevel-contextual -->
   <object class="GtkWindow" id="calc_window">
     <property name="events">GDK_BUTTON_PRESS_MASK</property>
+    <property name="role">gcalctool</property>
     <accel-groups>
       <group name="accelgroup1"/>
     </accel-groups>
diff --git a/src/mp-convert.c b/src/mp-convert.c
index 71a96ae..93a8d88 100644
--- a/src/mp-convert.c
+++ b/src/mp-convert.c
@@ -93,7 +93,7 @@ mp_set_from_float(float rx, MPNumber *z)
     }
 
     /* NORMALIZE RESULT */
-    mp_normalize(z, 0);
+    mp_normalize(z);
 
     /* Computing MAX */
     ib = max(MP_BASE * 7 * MP_BASE, 32767) / 16;
@@ -179,7 +179,7 @@ mp_set_from_double(double dx, MPNumber *z)
     }
 
     /* NORMALIZE RESULT */
-    mp_normalize(z, 0);
+    mp_normalize(z);
 
     /* Computing MAX */
     ib = max(MP_BASE * 7 * MP_BASE, 32767) / 16;
diff --git a/src/mp-equation.c b/src/mp-equation.c
index 22293ca..0cbe134 100644
--- a/src/mp-equation.c
+++ b/src/mp-equation.c
@@ -104,7 +104,6 @@ get_function(MPEquationParserState *state, const char *name, const MPNumber *x,
         int base;
         
         base = sub_atoi(lower_name + 3);
-        printf("%d\n", base);
         if (base < 0)
             result = 0;
         else
diff --git a/src/mp-internal.h b/src/mp-internal.h
index d289c1a..5fd6e03 100644
--- a/src/mp-internal.h
+++ b/src/mp-internal.h
@@ -43,6 +43,6 @@
 
 void mperr(const char *format, ...) __attribute__((format(printf, 1, 2)));
 void mpgcd(int *, int *);
-void mp_normalize(MPNumber *, int trunc);
+void mp_normalize(MPNumber *);
 
 #endif /* MP_INTERNAL_H */
diff --git a/src/mp.c b/src/mp.c
index 1fdfced..84eb531 100644
--- a/src/mp.c
+++ b/src/mp.c
@@ -294,7 +294,7 @@ mp_add2(const MPNumber *x, const MPNumber *y, int y_sign, MPNumber *z)
         zt.sign = y_sign;
         zt.exponent = y->exponent + mp_add3(x, y, zt.fraction, sign_prod, med);
     }
-    mp_normalize(&zt, 0);
+    mp_normalize(&zt);
     mp_set_from_mp(&zt, z);
 }
 
@@ -385,60 +385,50 @@ mp_integer_component(const MPNumber *x, MPNumber *z)
 }
 
 
-/*  COMPARES THE MULTIPLE-PRECISION NUMBERS X AND Y,
- *  RETURNING +1 IF X  >  Y,
- *            -1 IF X  <  Y,
- *  AND        0 IF X  == Y.
- */
 int
 mp_compare_mp_to_mp(const MPNumber *x, const MPNumber *y)
 {
-    int i, i2;
-
-    if (x->sign < y->sign) 
-        return -1;
-    if (x->sign > y->sign)
-        return 1;
+    int i;
 
-    /* SIGN(X) == SIGN(Y), SEE IF ZERO */
+    if (x->sign != y->sign) {
+        if (x->sign > y->sign) 
+            return 1;
+        else
+            return -1;
+    }
+    
+    /* x = y = 0 */
     if (x->sign == 0)
-        return 0;  /* X == Y == 0 */
+        return 0;
 
-    /* HAVE TO COMPARE EXPONENTS AND FRACTIONS */
-    i2 = x->exponent - y->exponent;
-    if (i2 < 0) {
-        /* ABS(X)  <  ABS(Y) */
-        return -x->sign;
-    }
-    if (i2 > 0) {
-        /* ABS(X)  >  ABS(Y) */
-        return x->sign;
-    }
-    for (i = 0; i < MP_T; i++) {
-        i2 = x->fraction[i] - y->fraction[i];
-        if (i2 < 0) {
-            /* ABS(X)  <  ABS(Y) */
+    /* See if numbers are of different magnitude */
+    if (x->exponent != y->exponent) {
+        if (x->exponent > y->exponent)
+            return x->sign;
+        else
             return -x->sign;
-        }
-        if (i2 > 0) {
-            /* ABS(X)  >  ABS(Y) */
+    }
+
+    /* Compare fractions */
+    for (i = 0; i < MP_SIZE; i++) {
+        if (x->fraction[i] == y->fraction[i])
+            continue;
+
+        if (x->fraction[i] > y->fraction[i])
             return x->sign;
-        }
+        else
+            return -x->sign;
     }
 
-    /* NUMBERS EQUAL */
+    /* x = y */
     return 0;
 }
 
-/*  SETS Z = X/Y, FOR MP X, Y AND Z.
- *  DIMENSION OF R IN CALLING PROGRAM MUST BE AT LEAST 4T+10
- *  (BUT Z(1) MAY BE R(3T+9)).
- *  CHECK LEGALITY OF B, T, M AND MXR
- */
+
 void
 mp_divide(const MPNumber *x, const MPNumber *y, MPNumber *z)
 {
-    int i, ie, iz3;
+    int i, ie;
     MPNumber t;
 
     /* x/0 */
@@ -464,71 +454,77 @@ mp_divide(const MPNumber *x, const MPNumber *y, MPNumber *z)
 
     /* MULTIPLY BY X */
     mp_multiply(x, &t, z);
-    iz3 = z->fraction[0];
-    mpext(i, iz3, z);
+    mpext(i, z->fraction[0], z);
 
     z->exponent += ie;
 }
 
 
-/*  DIVIDES MP X BY THE SINGLE-PRECISION INTEGER IY GIVING MP Z.
- *  THIS IS MUCH FASTER THAN DIVISION BY AN MP NUMBER.
- */
 void
-mp_divide_integer(const MPNumber *x, int iy, MPNumber *z)
+mp_divide_integer(const MPNumber *x, int y, MPNumber *z)
 {
     int i__1;
     int c, i, k, b2, c2, i2, j1, j2, r1;
     int j11, kh, iq, ir, iqj;
 
-    if (iy == 0) {
+    /* x/0 */
+    if (y == 0) {
         mperr("*** ATTEMPTED DIVISION BY ZERO IN CALL TO MP_DIVIDE_INTEGER ***");
         mp_set_from_integer(0, z);
         return;
     }
-
-    z->sign = x->sign;
-    if (iy < 0) {
-        iy = -iy;
-        z->sign = -z->sign;
-    }
-    if (z->sign == 0)
+    
+    /* 0/y = 0 */
+    if (x->sign == 0) {
+        mp_set_from_integer(0, z);
         return;
-    z->exponent = x->exponent;
+    }
 
-    /* CHECK FOR DIVISION BY B */
-    if (iy == MP_BASE) {
+    /* Division by -1 or 1 just changes sign */
+    if (y == 1 || y == -1) {
         mp_set_from_mp(x, z);
-        z->exponent--;
+        z->sign *= y;
         return;
     }
 
-    /* CHECK FOR DIVISION BY 1 OR -1 */
-    if (iy == 1) {
-        int s = z->sign;
+    /* If dividing by base then can optimise */
+    if (y % MP_BASE == 0) {
         mp_set_from_mp(x, z);
-        z->sign = s;
+        if (y < 0) {
+            z->sign = -z->sign;
+            z->exponent -= -y / MP_BASE;
+        }
+        else
+            z->exponent -= y / MP_BASE;
         return;
     }
 
+    if (y < 0) {
+        y = -y;
+        z->sign = -x->sign;
+    }
+    else
+        z->sign = x->sign;
+    z->exponent = x->exponent;
+
     c = 0;
     i2 = MP_T + 4;
     i = 0;
 
-    /*  IF IY*B NOT REPRESENTABLE AS AN INTEGER HAVE TO SIMULATE
+    /*  IF y*B NOT REPRESENTABLE AS AN INTEGER HAVE TO SIMULATE
      *  LONG DIVISION.  ASSUME AT LEAST 16-BIT WORD.
      */
 
     /* Computing MAX */
     b2 = max(MP_BASE << 3, 32767 / MP_BASE);
-    if (iy < b2) {
+    if (y < b2) {
         /* LOOK FOR FIRST NONZERO DIGIT IN QUOTIENT */
         do {
             c = MP_BASE * c;
             if (i < MP_T)
                 c += x->fraction[i];
             i++;
-            r1 = c / iy;
+            r1 = c / y;
             if (r1 < 0)
                 goto L210;
         } while(r1 == 0);
@@ -536,14 +532,14 @@ mp_divide_integer(const MPNumber *x, int iy, MPNumber *z)
         /* ADJUST EXPONENT AND GET T+4 DIGITS IN QUOTIENT */
         z->exponent += 1 - i;
         z->fraction[0] = r1;
-        c = MP_BASE * (c - iy * r1);
+        c = MP_BASE * (c - y * r1);
         kh = 1;
         if (i < MP_T) {
             kh = MP_T + 1 - i;
             for (k = 1; k < kh; k++) {
                 c += x->fraction[i];
-                z->fraction[k] = c / iy;
-                c = MP_BASE * (c - iy * z->fraction[k]);
+                z->fraction[k] = c / y;
+                c = MP_BASE * (c - y * z->fraction[k]);
                 i++;
             }
             if (c < 0)
@@ -551,24 +547,24 @@ mp_divide_integer(const MPNumber *x, int iy, MPNumber *z)
         }
         
         for (k = kh; k < i2; k++) {
-            z->fraction[k] = c / iy;
-            c = MP_BASE * (c - iy * z->fraction[k]);
+            z->fraction[k] = c / y;
+            c = MP_BASE * (c - y * z->fraction[k]);
         }
         if (c < 0)
             goto L210;
         
         /* NORMALIZE AND ROUND RESULT */
-        mp_normalize(z, 0);
+        mp_normalize(z);
 
         return;
     }
     
     /* HERE NEED SIMULATED DOUBLE-PRECISION DIVISION */
-    j1 = iy / MP_BASE;
+    j1 = y / MP_BASE;
 
     /* LOOK FOR FIRST NONZERO DIGIT */
     c2 = 0;
-    j2 = iy - j1 * MP_BASE;
+    j2 = y - j1 * MP_BASE;
     do {
         c = MP_BASE * c + c2;
         i__1 = c - j1;
@@ -581,7 +577,7 @@ mp_divide_integer(const MPNumber *x, int iy, MPNumber *z)
     i--;
     k = 1;
 
-    /* MAIN LOOP FOR LARGE ABS(IY) CASE */
+    /* MAIN LOOP FOR LARGE ABS(y) CASE */
     j11 = j1 + 1;
     while(1) {
         /* GET APPROXIMATE QUOTIENT FIRST */
@@ -599,24 +595,24 @@ mp_divide_integer(const MPNumber *x, int iy, MPNumber *z)
         if (iq < 0) {
             /* HERE IQ NEGATIVE SO IR WAS TOO LARGE */
             ir--;
-            iq += iy;
+            iq += y;
         }
 
         if (i < MP_T)
             iq += x->fraction[i];
         i++;
-        iqj = iq / iy;
+        iqj = iq / y;
 
         /* R(K) = QUOTIENT, C = REMAINDER */
         z->fraction[k - 1] = iqj + ir;
-        c = iq - iy * iqj;
+        c = iq - y * iqj;
         
         if (c < 0)
             goto L210;
         
         ++k;
         if (k > i2) {
-            mp_normalize(z, 0);
+            mp_normalize(z);
             return;
         }
     }
@@ -925,24 +921,21 @@ mp_is_negative(const MPNumber *x)
 int
 mp_is_greater_equal(const MPNumber *x, const MPNumber *y)
 {
-    /* RETURNS LOGICAL VALUE OF (X >= Y) FOR MP X AND Y. */
-    return (mp_compare_mp_to_mp(x, y) >= 0);
+    return mp_compare_mp_to_mp(x, y) >= 0;
 }
 
 
 int
 mp_is_greater_than(const MPNumber *x, const MPNumber *y)
 {
-    /* RETURNS LOGICAL VALUE OF (X > Y) FOR MP X AND Y. */
-    return (mp_compare_mp_to_mp(x, y) > 0);
+    return mp_compare_mp_to_mp(x, y) > 0;
 }
 
 
 int
 mp_is_less_equal(const MPNumber *x, const MPNumber *y)
 {
-    /* RETURNS LOGICAL VALUE OF (X <= Y) FOR MP X AND Y. */
-    return (mp_compare_mp_to_mp(x, y) <= 0);
+    return mp_compare_mp_to_mp(x, y) <= 0;
 }
 
 
@@ -960,7 +953,7 @@ mplns(const MPNumber *x, MPNumber *z)
     MPNumber t1, t2, t3;
     
     /* ln(1) = 0 */
-    if (x->sign == 0)  {
+    if (x->sign == 0) {
         mp_set_from_integer(0, z);
         return;
     }
@@ -1025,16 +1018,6 @@ mplns(const MPNumber *x, MPNumber *z)
 }
 
 
-/*  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, MPEXP 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)
 {
@@ -1042,7 +1025,7 @@ mp_ln(const MPNumber *x, MPNumber *z)
     float rx, rlx;
     MPNumber t1, t2;
     
-    /* CHECK THAT X IS POSITIVE */
+    /* ln(-x) -> error */
     if (x->sign <= 0) {
         mperr("*** X NONPOSITIVE IN CALL TO MP_LN ***");
         mp_set_from_integer(0, z);
@@ -1107,11 +1090,10 @@ mp_logarithm(int n, const MPNumber *x, MPNumber *z)
 }
 
 
-/* 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);
+    return mp_compare_mp_to_mp(x, y) < 0;
 }
 
 
@@ -1138,12 +1120,13 @@ mp_multiply(const MPNumber *x, const MPNumber *y, MPNumber *z)
     
     memset(&r, 0, sizeof(MPNumber));
     
-    /* FORM SIGN OF PRODUCT */
-    z->sign = x->sign * y->sign;
-    if (z->sign == 0)
+    /* x*0 = 0*y = 0 */
+    if (x->sign == 0 || y->sign == 0) {
+        mp_set_from_integer(0, z);
         return;
-
-    /* FORM EXPONENT OF PRODUCT */
+    }
+    
+    z->sign = x->sign * y->sign;
     z->exponent = x->exponent + y->exponent;
     
     /* PERFORM MULTIPLICATION */
@@ -1220,7 +1203,7 @@ mp_multiply(const MPNumber *x, const MPNumber *y, MPNumber *z)
     // FIXME: Use stack variable because of mp_normalize brokeness
     for (i = 0; i < MP_SIZE; i++)
         z->fraction[i] = r.fraction[i];
-    mp_normalize(z, 0);
+    mp_normalize(z);
 }
 
 
@@ -1276,37 +1259,44 @@ mp_multiply_new(const MPNumber *x, const MPNumber *y, MPNumber *z)
 }
 
 
-/*  MULTIPLIES MP X BY SINGLE-PRECISION INTEGER IY GIVING MP Z.
- *  MULTIPLICATION BY 1 MAY BE USED TO NORMALIZE A NUMBER
- *  EVEN IF SOME DIGITS ARE GREATER THAN B-1.
- *  RESULT IS ROUNDED IF TRUNC == 0, OTHERWISE TRUNCATED.
- */
-static void
-mpmul2(const MPNumber *x, int iy, MPNumber *z, int trunc)
+void
+mp_multiply_integer(const MPNumber *x, int y, MPNumber *z)
 {
     int c, i, c1, c2, j1, j2;
     int t1, t3, t4, ij, ri = 0, is, ix;
     
-    z->sign = x->sign;
-    if (z->sign == 0 || iy == 0) {
+    /* x*0 = 0*y = 0 */
+    if (x->sign == 0 || y == 0) {
         mp_set_from_integer(0, z);
         return;
     }
 
-    if (iy < 0) {
-        iy = -iy;
-        z->sign = -z->sign;
-
-        /* CHECK FOR MULTIPLICATION BY B */
-        if (iy == MP_BASE) {
-            mp_set_from_mp(x, z);
-            z->sign = z->sign;
-            z->exponent = x->exponent + 1;
-            return;
+    /* x*1 = x, x*-1 = -x */
+    // FIXME: Why is this not working?
+    /*if (y == 1 || y == -1) {
+        mp_set_from_mp(x, z);
+        z->sign *= y;
+        return;
+    }*/
+    
+    /* If multiplying by base then can optimise */
+    if (y % MP_BASE == 0) {
+        mp_set_from_mp(x, z);
+        if (y < 0) {
+            z->sign = -z->sign;
+            z->exponent += -y / MP_BASE;
         }
+        else
+            z->exponent += y / MP_BASE;    
+        return;
     }
 
-    /* SET EXPONENT TO EXPONENT(X) + 4 */
+    if (y < 0) {
+        y = -y;
+        z->sign = -x->sign;
+    }
+    else
+        z->sign = x->sign;
     z->exponent = x->exponent + 4;
 
     /* FORM PRODUCT IN ACCUMULATOR */
@@ -1315,15 +1305,15 @@ mpmul2(const MPNumber *x, int iy, MPNumber *z, int trunc)
     t3 = MP_T + 3;
     t4 = MP_T + 4;
 
-    /*  IF IY*B NOT REPRESENTABLE AS AN INTEGER WE HAVE TO SIMULATE
+    /*  IF y*B NOT REPRESENTABLE AS AN INTEGER WE HAVE TO SIMULATE
      *  DOUBLE-PRECISION MULTIPLICATION.
      */
 
     /* Computing MAX */
-    if (iy >= max(MP_BASE << 3, 32767 / MP_BASE)) {
+    if (y >= max(MP_BASE << 3, 32767 / MP_BASE)) {
         /* HERE J IS TOO LARGE FOR SINGLE-PRECISION MULTIPLICATION */
-        j1 = iy / MP_BASE;
-        j2 = iy - j1 * MP_BASE;
+        j1 = y / MP_BASE;
+        j2 = y - j1 * MP_BASE;
 
         /* FORM PRODUCT */
         for (ij = 1; ij <= t4; ++ij) {
@@ -1343,14 +1333,14 @@ mpmul2(const MPNumber *x, int iy, MPNumber *z, int trunc)
     {
         for (ij = 1; ij <= MP_T; ++ij) {
             i = t1 - ij;
-            ri = iy * x->fraction[i - 1] + c;
+            ri = y * x->fraction[i - 1] + c;
             c = ri / MP_BASE;
             z->fraction[i + 3] = ri - MP_BASE * c;
         }
 
         /* CHECK FOR INTEGER OVERFLOW */
         if (ri < 0) {
-            mperr("*** INTEGER OVERFLOW IN MPMUL2, B TOO LARGE ***");
+            mperr("*** INTEGER OVERFLOW IN mp_multiply_integer, B TOO LARGE ***");
             mp_set_from_integer(0, z);
             return;
         }
@@ -1369,12 +1359,12 @@ mpmul2(const MPNumber *x, int iy, MPNumber *z, int trunc)
         /* NORMALIZE AND ROUND OR TRUNCATE RESULT */
         if (c == 0)
         {
-            mp_normalize(z, trunc);
+            mp_normalize(z);
             return;
         }
         
         if (c < 0) {
-            mperr("*** INTEGER OVERFLOW IN MPMUL2, B TOO LARGE ***");
+            mperr("*** INTEGER OVERFLOW IN mp_multiply_integer, B TOO LARGE ***");
             mp_set_from_integer(0, z);
             return;
         }
@@ -1391,18 +1381,6 @@ mpmul2(const MPNumber *x, int iy, MPNumber *z, int trunc)
 }
 
 
-/*  MULTIPLIES MP X BY SINGLE-PRECISION INTEGER IY GIVING MP Z.
- *  THIS IS FASTER THAN USING MP_MULTIPLY.  RESULT IS ROUNDED.
- *  MULTIPLICATION BY 1 MAY BE USED TO NORMALIZE A NUMBER
- *  EVEN IF THE LAST DIGIT IS B.
- */
-void
-mp_multiply_integer(const MPNumber *x, int iy, MPNumber *z)
-{
-    mpmul2(x, iy, z, 0);
-}
-
-
 /* MULTIPLIES MP X BY I/J, GIVING MP Y */
 void
 mp_multiply_fraction(const MPNumber *x, int numerator, int denominator, MPNumber *z)
@@ -1451,7 +1429,7 @@ mp_invert_sign(const MPNumber *x, MPNumber *y)
 // using stack variables as x otherwise there are corruption errors. e.g. "Cos(45) - 1/Sqrt(2) = -0"
 // (try in scientific mode)
 void
-mp_normalize(MPNumber *x, int trunc)
+mp_normalize(MPNumber *x)
 {
     int i__1, i, j, b2, i2, i2m, round;
 
@@ -1485,58 +1463,53 @@ mp_normalize(MPNumber *x, int trunc)
             x->fraction[j] = 0;
     }
 
-    /* CHECK TO SEE IF TRUNCATION IS DESIRED */
-    if (trunc == 0) {
-        /*  SEE IF ROUNDING NECESSARY
-         *  TREAT EVEN AND ODD BASES DIFFERENTLY
-         */
-        b2 = MP_BASE / 2;
-        if (b2 << 1 != MP_BASE) {
-            round = 0;
-            /* ODD BASE, ROUND IF R(T+1)... > 1/2 */
-            for (i = 0; i < 4; i++) {
-                i__1 = x->fraction[MP_T + i] - b2;
-                if (i__1 < 0)
-                    break;
-                else if (i__1 == 0)
-                    continue;
-                else {
-                    round = 1;
-                    break;
-                }
-            }
-        }
-        else {
-            /*  B EVEN.  ROUND IF R(T+1) >= B2 UNLESS R(T) ODD AND ALL ZEROS
-             *  AFTER R(T+2).
-             */
-            round = 1;
-            i__1 = x->fraction[MP_T] - b2;
+    /*  SEE IF ROUNDING NECESSARY
+     *  TREAT EVEN AND ODD BASES DIFFERENTLY
+     */
+    b2 = MP_BASE / 2;
+    if (b2 << 1 != MP_BASE) {
+        round = 0;
+        /* ODD BASE, ROUND IF R(T+1)... > 1/2 */
+        for (i = 0; i < 4; i++) {
+            i__1 = x->fraction[MP_T + i] - b2;
             if (i__1 < 0)
-                round = 0;
-            else if (i__1 == 0) {
-                if (x->fraction[MP_T - 1] % 2 != 0) {
-                    if (x->fraction[MP_T + 1] + x->fraction[MP_T + 2] + x->fraction[MP_T + 3] == 0) {
-                        round = 0;
-                    }
-                }
+                break;
+            else if (i__1 == 0)
+                continue;
+            else {
+                round = 1;
+                break;
             }
         }
-
-        /* ROUND */
-        if (round) {
-            for (j = MP_T - 1; j >= 0; j--) {
-                ++x->fraction[j];
-                if (x->fraction[j] < MP_BASE)
-                    break;
-                x->fraction[j] = 0;
+    }
+    else {
+        /*  B EVEN.  ROUND IF R(T+1) >= B2 UNLESS R(T) ODD AND ALL ZEROS
+         *  AFTER R(T+2).
+         */
+        round = 1;
+        i__1 = x->fraction[MP_T] - b2;
+        if (i__1 < 0)
+            round = 0;
+        else if (i__1 == 0) {
+            if (x->fraction[MP_T - 1] % 2 != 0) {
+                if (x->fraction[MP_T + 1] + x->fraction[MP_T + 2] + x->fraction[MP_T + 3] == 0)
+                    round = 0;
             }
+        }
+    }
 
-            /* EXCEPTIONAL CASE, ROUNDED UP TO .10000... */
-            if (j < 0) {
-                x->exponent++;
-                x->fraction[0] = 1;
-            }
+    /* ROUND */
+    if (round) {
+        for (j = MP_T - 1; j >= 0; j--) {
+            ++x->fraction[j];
+            if (x->fraction[j] < MP_BASE)
+                break;
+            x->fraction[j] = 0;
+        }
+        /* EXCEPTIONAL CASE, ROUNDED UP TO .10000... */
+        if (j < 0) {
+            x->exponent++;
+            x->fraction[0] = 1;
         }
     }
 }
@@ -1798,7 +1771,7 @@ mp_root(const MPNumber *x, int n, MPNumber *z)
 void
 mp_sqrt(const MPNumber *x, MPNumber *z)
 {
-    int i, i2, iy3;
+    int i, i2;
     MPNumber t;
 
     /* MP_ROOT NEEDS 4T+10 WORDS, BUT CAN OVERLAP SLIGHTLY. */
@@ -1811,8 +1784,7 @@ mp_sqrt(const MPNumber *x, MPNumber *z)
         mp_root(x, -2, &t);
         i = t.fraction[0];
         mp_multiply(x, &t, z);
-        iy3 = z->fraction[0];
-        mpext(i, iy3, z);
+        mpext(i, z->fraction[0], z);
     }
 }
 



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