[gcalctool/gcalctool-newui2] ...



commit 073970ccaac2cc1a0f2104354f830fbdb49cc7e9
Author: Robert Ancell <robert ancell gmail com>
Date:   Fri Jul 17 17:22:17 2009 +1000

    ...

 src/mp-convert.c         |   64 +++++------------------
 src/mp-equation-parser.y |    2 +-
 src/mp-equation.c        |    2 +-
 src/mp-trigonometric.c   |   50 +-----------------
 src/mp.c                 |  126 ++++++++++++++-------------------------------
 src/unittest.c           |   40 +++++++++------
 6 files changed, 82 insertions(+), 202 deletions(-)
---
diff --git a/src/mp-convert.c b/src/mp-convert.c
index 93a8d88..d03577e 100644
--- a/src/mp-convert.c
+++ b/src/mp-convert.c
@@ -28,9 +28,6 @@
 #include "mp.h"
 #include "mp-internal.h"
 
-/*  SETS Y = X FOR MP X AND Y.
- *  SEE IF X AND Y HAVE THE SAME ADDRESS (THEY OFTEN DO)
- */
 void
 mp_set_from_mp(const MPNumber *x, MPNumber *z)
 {
@@ -38,11 +35,7 @@ mp_set_from_mp(const MPNumber *x, MPNumber *z)
         memcpy(z, x, sizeof(MPNumber));
 }
 
-/*  CONVERTS SINGLE-PRECISION NUMBER RX TO MULTIPLE-PRECISION Z.
- *  SOME NUMBERS WILL NOT CONVERT EXACTLY ON MACHINES
- *  WITH BASE OTHER THAN TWO, FOUR OR SIXTEEN.
- *  CHECK LEGALITY OF B, T, M AND MXR
- */
+
 void
 mp_set_from_float(float rx, MPNumber *z)
 {
@@ -122,19 +115,7 @@ mp_set_from_float(float rx, MPNumber *z)
     return;
 }
 
-void
-mp_set_from_random(MPNumber *z)
-{
-    mp_set_from_double(drand48(), z);
-}
 
-/*  CONVERTS DOUBLE-PRECISION NUMBER DX TO MULTIPLE-PRECISION Z.
- *  SOME NUMBERS WILL NOT CONVERT EXACTLY ON MACHINES
- *  WITH BASE OTHER THAN TWO, FOUR OR SIXTEEN.
- *  THIS ROUTINE IS NOT CALLED BY ANY OTHER ROUTINE IN MP,
- *  SO MAY BE OMITTED IF DOUBLE-PRECISION IS NOT AVAILABLE.
- *  CHECK LEGALITY OF B, T, M AND MXR
- */
 void
 mp_set_from_double(double dx, MPNumber *z)
 {
@@ -209,9 +190,6 @@ mp_set_from_double(double dx, MPNumber *z)
 }
 
 
-/*  CONVERTS INTEGER IX TO MULTIPLE-PRECISION Z.
- *  CHECK LEGALITY OF B, T, M AND MXR
- */
 void
 mp_set_from_integer(int x, MPNumber *z)
 {
@@ -238,7 +216,7 @@ mp_set_from_integer(int x, MPNumber *z)
     }
 }
 
-/* CONVERTS THE RATIONAL NUMBER I/J TO MULTIPLE PRECISION Q. */
+
 void
 mp_set_from_fraction(int i, int j, MPNumber *z)
 {
@@ -260,16 +238,14 @@ mp_set_from_fraction(int i, int j, MPNumber *z)
         mp_divide_integer(z, j, z);
 }
 
-/*  CONVERTS MULTIPLE-PRECISION X TO INTEGER, AND
- *  RETURNS RESULT.
- *  ASSUMING THAT X NOT TOO LARGE (ELSE USE MP_INTEGER_COMPONENT)
- *  X IS TRUNCATED TOWARDS ZERO.
- *  IF INT(X)IS TOO LARGE TO BE REPRESENTED AS A SINGLE-
- *  PRECISION INTEGER, IZ IS RETURNED AS ZERO.  THE USER
- *  MAY CHECK FOR THIS POSSIBILITY BY TESTING IF
- *  ((X(1).NE.0).AND.(X(2).GT.0).AND.(IZ.EQ.0)) IS TRUE ON
- *  RETURN FROM MP_CAST_TO_INST.
- */
+
+void
+mp_set_from_random(MPNumber *z)
+{
+    mp_set_from_double(drand48(), z);
+}
+
+
 int
 mp_cast_to_int(const MPNumber *x)
 {
@@ -320,6 +296,7 @@ mp_cast_to_int(const MPNumber *x)
      */
 }
 
+
 static double
 mppow_ri(float ap, int bp)
 {
@@ -348,11 +325,7 @@ mppow_ri(float ap, int bp)
     return pow;
 }
 
-/*  CONVERTS MULTIPLE-PRECISION X TO SINGLE-PRECISION.
- *  ASSUMES X IN ALLOWABLE RANGE.  THERE IS SOME LOSS OF
- *  ACCURACY IF THE EXPONENT IS LARGE.
- *  CHECK LEGALITY OF B, T, M AND MXR
- */
+
 float
 mp_cast_to_float(const MPNumber *x)
 {
@@ -391,6 +364,7 @@ mp_cast_to_float(const MPNumber *x)
     return rz;
 }
 
+
 static double
 mppow_di(double ap, int bp)
 {
@@ -412,13 +386,7 @@ mppow_di(double ap, int bp)
     return(pow);
 }
 
-/*  CONVERTS MULTIPLE-PRECISION X TO DOUBLE-PRECISION,
- *  AND RETURNS RESULT.
- *  ASSUMES X IS IN ALLOWABLE RANGE FOR DOUBLE-PRECISION
- *  NUMBERS.   THERE IS SOME LOSS OF ACCURACY IF THE
- *  EXPONENT IS LARGE.
- *  CHECK LEGALITY OF B, T, M AND MXR
- */
+
 double
 mp_cast_to_double(const MPNumber *x)
 {
@@ -466,9 +434,6 @@ mp_cast_to_double(const MPNumber *x)
 }
 
 
-/* Convert MP number to fixed number string in the given base to the
- * maximum number of digits specified.
- */
 void
 mp_cast_to_string(const MPNumber *x, int base, int accuracy, int trim_zeroes, char *buffer, int buffer_length)
 {
@@ -630,7 +595,6 @@ char_val(char **c, int base)
 }
 
 
-/* Convert string into an MP number */
 void
 mp_set_from_string(const char *str, MPNumber *z)
 {
diff --git a/src/mp-equation-parser.y b/src/mp-equation-parser.y
index 66aee9f..f8cc342 100644
--- a/src/mp-equation-parser.y
+++ b/src/mp-equation-parser.y
@@ -102,11 +102,11 @@ static void do_mod(yyscan_t yyscanner, const MPNumber *x, const MPNumber *y, MPN
 %left tNOT
 %left tROOT tROOT3 tROOT4
 %left <name> tVARIABLE tFUNCTION
-%right '^' tINVERSE '!'
 %right <integer> tSUBNUM tSUPNUM
 %left BOOLEAN_OPERATOR
 %left PERCENTAGE
 %left UNARY_MINUS
+%right '^' tINVERSE '!'
 
 %type <int_t> exp function
 %start statement
diff --git a/src/mp-equation.c b/src/mp-equation.c
index 0cbe134..0890ce2 100644
--- a/src/mp-equation.c
+++ b/src/mp-equation.c
@@ -39,7 +39,7 @@ get_variable(MPEquationParserState *state, const char *name, MPNumber *z)
     lower_name = strdup(name);
     for (c = lower_name; *c; c++)
         *c = tolower(*c);
-    
+
     if (lower_name[0] == 'r')
         mp_set_from_mp(register_get_value(atoi(name+1)), z);
     else if (strcmp(lower_name, "ans") == 0)
diff --git a/src/mp-trigonometric.c b/src/mp-trigonometric.c
index 29e4ed2..ad98c36 100644
--- a/src/mp-trigonometric.c
+++ b/src/mp-trigonometric.c
@@ -28,11 +28,6 @@
 #include "mp.h"
 #include "mp-internal.h"
 
-/*  COMPARES MP NUMBER X WITH INTEGER I, RETURNING
- *      +1 IF X  >  I,
- *       0 IF X == I,
- *      -1 IF X  <  I
- */
 static int
 mp_compare_mp_to_int(const MPNumber *x, int i)
 {
@@ -102,8 +97,8 @@ convert_from_radians(const MPNumber *x, MPAngleUnit unit, MPNumber *z)
 }
 
 
-/*  COMPUTES Z = SIN(X) IF DO_SIN != 0, Z = COS(X) IF DO_SIN == 0,
- *  USING TAYLOR SERIES.   ASSUMES ABS(X) <= 1.
+/* z = sin(x) -1 >= x >= 1, do_sin = 1
+ * z = cos(x) -1 >= x >= 1, do_sin = 0
  */
 static void
 mpsin1(const MPNumber *x, MPNumber *z, int do_sin)
@@ -135,6 +130,7 @@ mpsin1(const MPNumber *x, MPNumber *z, int do_sin)
         i = 2;
     }
 
+    /* Taylor series */
     /* POWER SERIES LOOP.  REDUCE T IF POSSIBLE */
     b2 = max(MP_BASE, 64) << 1;
     do {
@@ -161,12 +157,6 @@ mpsin1(const MPNumber *x, MPNumber *z, int do_sin)
 }
 
 
-/*  RETURNS Z = SIN(X) FOR MP X AND Z,
- *  METHOD IS TO REDUCE X TO (-1, 1) AND USE MPSIN1, SO
- *  TIME IS O(M(T)T/LOG(T)).
- *  DIMENSION OF R IN CALLING PROGRAM MUST BE AT LEAST 5T+12
- *  CHECK LEGALITY OF B, T, M AND MXR
- */
 void
 mp_sin(const MPNumber *x, MPAngleUnit unit, MPNumber *z)
 {
@@ -252,9 +242,6 @@ mp_sin(const MPNumber *x, MPAngleUnit unit, MPNumber *z)
 }
 
 
-/*  RETURNS Z = COS(X) FOR MP X AND Z, USING MP_SIN AND MPSIN1.
- *  DIMENSION OF R IN COMMON AT LEAST 5T+12.
- */
 void
 mp_cos(const MPNumber *xi, MPAngleUnit unit, MPNumber *z)
 {
@@ -301,13 +288,6 @@ mp_tan(const MPNumber *x, MPAngleUnit unit, MPNumber *z)
 }
 
 
-/*  RETURNS Z = ARCSIN(X), ASSUMING ABS(X) <= 1,
- *  FOR MP NUMBERS X AND Z.
- *  Z IS IN THE RANGE -PI/2 TO +PI/2.
- *  METHOD IS TO USE MP_ATAN, SO TIME IS O(M(T)T).
- *  DIMENSION OF R MUST BE AT LEAST 5T+12
- *  CHECK LEGALITY OF B, T, M AND MXR
- */
 void
 mp_asin(const MPNumber *x, MPAngleUnit unit, MPNumber *z)
 {
@@ -345,20 +325,6 @@ mp_asin(const MPNumber *x, MPAngleUnit unit, MPNumber *z)
 }
 
 
-/*  MP precision arc cosine.
- *
- *  1. If (x < -1  or x > 1) then report DOMAIN error and return 0.
- *
- *  2. If (x == 0) then acos(x) = PI/2.
- *
- *  3. If (x == 1) then acos(x) = 0
- *
- *  4. If (x == -1) then acos(x) = PI.
- *
- *  5. If (0 < x < 1) then  acos(x) = atan(sqrt(1-x^2) / x)
- *
- *  6. If (-1 < x < 0) then acos(x) = atan(sqrt(1-x^2) / x) + PI
- */
 void
 mp_acos(const MPNumber *x, MPAngleUnit unit, MPNumber *z)
 {
@@ -395,16 +361,6 @@ mp_acos(const MPNumber *x, MPAngleUnit unit, MPNumber *z)
 }
 
 
-/*  RETURNS Z = ARCTAN(X) FOR MP X AND Z, USING AN O(T.M(T)) METHOD
- *  WHICH COULD EASILY BE MODIFIED TO AN O(SQRT(T)M(T))
- *  METHOD (AS IN MPEXP). Z IS IN THE RANGE -PI/2 TO +PI/2.
- *  FOR AN ASYMPTOTICALLY FASTER METHOD, SEE - FAST MULTIPLE-
- *  PRECISION EVALUATION OF ELEMENTARY FUNCTIONS
- *  (BY R. P. BRENT), J. ACM 23 (1976), 242-251,
- *  AND THE COMMENTS IN MPPIGL.
- *  DIMENSION OF R IN CALLING PROGRAM MUST BE AT LEAST 5T+12
- *  CHECK LEGALITY OF B, T, M AND MXR
- */
 void
 mp_atan(const MPNumber *x, MPAngleUnit unit, MPNumber *z)
 {
diff --git a/src/mp.c b/src/mp.c
index 84eb531..6f6e566 100644
--- a/src/mp.c
+++ b/src/mp.c
@@ -299,9 +299,6 @@ mp_add2(const MPNumber *x, const MPNumber *y, int y_sign, MPNumber *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)
 {
@@ -328,6 +325,13 @@ mp_add_fraction(const MPNumber *x, int i, int j, MPNumber *y)
 
 
 void
+mp_subtract(const MPNumber *x, const MPNumber *y, MPNumber *z)
+{
+    mp_add2(x, y, -y->sign, z);
+}
+
+
+void
 mp_fractional_component(const MPNumber *x, MPNumber *z)
 {
     int i, shift;
@@ -695,7 +699,7 @@ mpexp(const MPNumber *x, MPNumber *z)
         return;
     }
 
-    /* CHECK THAT ABS(X) < 1 */
+    /* Only defined for |x| < 1 */
     if (x->exponent > 0) {
         mperr("*** ABS(X) NOT LESS THAN 1 IN CALL TO MPEXP ***");
         mp_set_from_integer(0, z);
@@ -751,13 +755,6 @@ mpexp(const MPNumber *x, MPNumber *z)
 }
 
 
-/*  RETURNS Z = EXP(X) FOR MP X AND Z.
- *  EXP OF INTEGER AND FRACTIONAL PARTS OF X ARE COMPUTED
- *  SEPARATELY.  SEE ALSO COMMENTS IN MPEXP.
- *  TIME IS O(SQRT(T)M(T)).
- *  DIMENSION OF R MUST BE AT LEAST 4T+10 IN CALLING PROGRAM
- *  CHECK LEGALITY OF B, T, M AND MXR
- */
 void
 mp_epowy(const MPNumber *x, MPNumber *z)
 {
@@ -943,8 +940,6 @@ mp_is_less_equal(const MPNumber *x, const MPNumber *y)
  *  CONDITION ABS(X) < 1/B, ERROR OTHERWISE.
  *  USES NEWTONS METHOD TO SOLVE THE EQUATION
  *  EXP1(-Y) = X, THEN REVERSES SIGN OF Y.
- *  TIME IS O(SQRT(T).M(T)) AS FOR MPEXP, SPACE = 5T+12.
- *  CHECK LEGALITY OF B, T, M AND MXR
  */
 static void
 mplns(const MPNumber *x, MPNumber *z)
@@ -965,7 +960,7 @@ mplns(const MPNumber *x, MPNumber *z)
         return;
     }
 
-    /* GET STARTING APPROXIMATION TO -LN(1+X) */
+    /* Get starting approximation -ln(1+x) ~= -x + x^2/2 - x^3/3 + x^4/4 */
     mp_set_from_mp(x, &t2);
     mp_divide_integer(x, 4, &t1);
     mp_add_fraction(&t1, -1, 3, &t1);
@@ -1025,7 +1020,7 @@ mp_ln(const MPNumber *x, MPNumber *z)
     float rx, rlx;
     MPNumber t1, t2;
     
-    /* ln(-x) -> error */
+    /* ln(-x) invalid */
     if (x->sign <= 0) {
         mperr("*** X NONPOSITIVE IN CALL TO MP_LN ***");
         mp_set_from_integer(0, z);
@@ -1113,13 +1108,9 @@ mp_is_less_than(const MPNumber *x, const MPNumber *y)
 void
 mp_multiply(const MPNumber *x, const MPNumber *y, MPNumber *z)
 {
-    int c, i, j, i2, xi;
+    int c, i, j, xi;
     MPNumber r;
 
-    i2 = MP_T + 4;
-    
-    memset(&r, 0, sizeof(MPNumber));
-    
     /* x*0 = 0*y = 0 */
     if (x->sign == 0 || y->sign == 0) {
         mp_set_from_integer(0, z);
@@ -1128,6 +1119,7 @@ mp_multiply(const MPNumber *x, const MPNumber *y, MPNumber *z)
     
     z->sign = x->sign * y->sign;
     z->exponent = x->exponent + y->exponent;
+    memset(&r, 0, sizeof(MPNumber));
     
     /* PERFORM MULTIPLICATION */
     c = 8;
@@ -1139,7 +1131,7 @@ mp_multiply(const MPNumber *x, const MPNumber *y, MPNumber *z)
             continue;
 
         /* Computing MIN */
-        for (j = 0; j < min(MP_T, i2 - i - 1); j++)
+        for (j = 0; j < min(MP_T, MP_T + 3 - i); j++)
             r.fraction[i+j+1] += xi * y->fraction[j];
         c--;
         if (c > 0)
@@ -1155,7 +1147,7 @@ mp_multiply(const MPNumber *x, const MPNumber *y, MPNumber *z)
         /*  PROPAGATE CARRIES AT END AND EVERY EIGHTH TIME,
          *  FASTER THAN DOING IT EVERY TIME.
          */
-        for (j = i2 - 1; j >= 0; j--) {
+        for (j = MP_T + 3; j >= 0; j--) {
             int ri = r.fraction[j] + c;
             if (ri < 0) {
                 mperr("*** INTEGER OVERFLOW IN MP_MULTIPLY, B TOO LARGE ***");
@@ -1181,7 +1173,7 @@ mp_multiply(const MPNumber *x, const MPNumber *y, MPNumber *z)
         }
     
         c = 0;
-        for (j = i2 - 1; j >= 0; j--) {
+        for (j = MP_T + 3; j >= 0; j--) {
             int ri = r.fraction[j] + c;
             if (ri < 0) {
                 mperr("*** INTEGER OVERFLOW IN MP_MULTIPLY, B TOO LARGE ***");
@@ -1381,12 +1373,9 @@ mp_multiply_integer(const MPNumber *x, int y, MPNumber *z)
 }
 
 
-/* MULTIPLIES MP X BY I/J, GIVING MP Y */
 void
 mp_multiply_fraction(const MPNumber *x, int numerator, int denominator, MPNumber *z)
 {
-    int is, js;
-
     if (denominator == 0) {
         mperr("*** ATTEMPTED DIVISION BY ZERO IN MP_MULTIPLY_FRACTION ***");
         mp_set_from_integer(0, z);
@@ -1398,32 +1387,21 @@ mp_multiply_fraction(const MPNumber *x, int numerator, int denominator, MPNumber
         return;
     }
 
-    /* REDUCE TO LOWEST TERMS */
-    is = numerator;
-    js = denominator;
-    mpgcd(&is, &js);
-    if (abs(is) == 1) {
-        /* HERE IS = +-1 */
-        mp_divide_integer(x, is * js, z);
-    } else {
-        mp_divide_integer(x, js, z);
-        mp_multiply_integer(z, is, z);
-    }
+    /* Reduce to lowest terms */
+    mpgcd(&numerator, &denominator);
+    mp_divide_integer(x, denominator, z);
+    mp_multiply_integer(z, numerator, z);
 }
 
 
-/* SETS Y = -X FOR MP NUMBERS X AND Y */
 void
-mp_invert_sign(const MPNumber *x, MPNumber *y)
+mp_invert_sign(const MPNumber *x, MPNumber *z)
 {
-    mp_set_from_mp(x, y);
-    y->sign = -y->sign;
+    mp_set_from_mp(x, z);
+    z->sign = -z->sign;
 }
 
-/*  ASSUMES LONG (I.E. (T+4)-DIGIT) FRACTION IN R.  NORMALIZES,
- *  AND RETURNS MP RESULT IN Z.  INTEGER ARGUMENTS REG_EXP IS
- *  NOT PRESERVED. R*-ROUNDING IS USED IF TRUNC == 0
- */
+
 // FIXME: Is r->fraction large enough?  It seems to be in practise but it may be MP_T+4 instead of MP_T
 // FIXME: There is some sort of stack corruption/use of unitialised variables here.  Some functions are
 // using stack variables as x otherwise there are corruption errors. e.g. "Cos(45) - 1/Sqrt(2) = -0"
@@ -1556,15 +1534,12 @@ mp_pwr(const MPNumber *x, const MPNumber *y, MPNumber *z)
 void
 mp_reciprocal(const MPNumber *x, MPNumber *z)
 {
-    /* Initialized data */
-    static int it[9] = { 0, 8, 6, 5, 4, 4, 4, 4, 4 };
-
     MPNumber tmp_x, t1, t2;
-
     int ex, it0, t;
     float rx;
+    static int it[9] = { 0, 8, 6, 5, 4, 4, 4, 4, 4 };
 
-    /* MP_ADD_INTEGER REQUIRES 2T+6 WORDS. */
+    /* 1/x invalid */
     if (x->sign == 0) {
         mperr("*** ATTEMPTED DIVISION BY ZERO IN CALL TO MP_RECIPROCAL ***");
         mp_set_from_integer(0, z);
@@ -1630,28 +1605,22 @@ mp_reciprocal(const MPNumber *x, MPNumber *z)
 }
 
 
-/*  RETURNS Z = X^(1/N) FOR INTEGER N, ABS(N) <= MAX (B, 64).
- *  AND MP NUMBERS X AND Z,
- *  USING NEWTONS METHOD WITHOUT DIVISIONS.   SPACE = 4T+10
- *  (BUT Z.EXP MAY BE R(3T+9))
- */
 void
 mp_root(const MPNumber *x, int n, MPNumber *z)
 {
-    /* Initialized data */
-    static const int it[9] = { 0, 8, 6, 5, 4, 4, 4, 4, 4 };
-
     float r__1;
-
     int ex, np, it0, t;
     float rx;
     MPNumber t1, t2;
+    static const int it[9] = { 0, 8, 6, 5, 4, 4, 4, 4, 4 };
 
+    /* x^(1/1) = x */
     if (n == 1) {
         mp_set_from_mp(x, z);
         return;
     }
 
+    /* x^(1/0) invalid */
     if (n == 0) {
         mperr("*** N == 0 IN CALL TO MP_ROOT ***");
         mp_set_from_integer(0, z);
@@ -1687,10 +1656,10 @@ mp_root(const MPNumber *x, int n, MPNumber *z)
 
     /* REDUCE EXPONENT SO RX NOT TOO LARGE OR SMALL. */
     {
-      MPNumber tmp_x;
-      mp_set_from_mp(x, &tmp_x);
-      tmp_x.exponent = 0;
-      rx = mp_cast_to_float(&tmp_x);
+        MPNumber tmp_x;
+        mp_set_from_mp(x, &tmp_x);
+        tmp_x.exponent = 0;
+        rx = mp_cast_to_float(&tmp_x);
     }
 
     /* USE SINGLE-PRECISION ROOT FOR FIRST APPROXIMATION */
@@ -1763,24 +1732,17 @@ mp_root(const MPNumber *x, int n, MPNumber *z)
 }
 
 
-/*  RETURNS Z = SQRT(X), USING SUBROUTINE MP_ROOT IF X > 0.
- *  DIMENSION OF R IN CALLING PROGRAM MUST BE AT LEAST 4T+10
- *  (BUT Z.EXP MAY BE R(3T+9)).  X AND Z ARE MP NUMBERS.
- *  CHECK LEGALITY OF B, T, M AND MXR
- */
 void
 mp_sqrt(const MPNumber *x, MPNumber *z)
 {
-    int i, i2;
-    MPNumber t;
-
-    /* MP_ROOT NEEDS 4T+10 WORDS, BUT CAN OVERLAP SLIGHTLY. */
-    i2 = MP_T * 3 + 9;
-    if (x->sign < 0) {
+    if (x->sign < 0)
         mperr("*** X NEGATIVE IN CALL TO SUBROUTINE MP_SQRT ***");
-    } else if (x->sign == 0) {
+    else if (x->sign == 0)
         mp_set_from_integer(0, z);
-    } else {
+    else {
+        int i;
+        MPNumber t;
+
         mp_root(x, -2, &t);
         i = t.fraction[0];
         mp_multiply(x, &t, z);
@@ -1788,15 +1750,6 @@ mp_sqrt(const MPNumber *x, MPNumber *z)
     }
 }
 
-/*  SUBTRACTS Y FROM X, FORMING RESULT IN Z, FOR MP X, Y AND Z.
- *  FOUR GUARD DIGITS ARE USED, AND THEN R*-ROUNDING
- */
-void
-mp_subtract(const MPNumber *x, const MPNumber *y, MPNumber *z)
-{
-    mp_add2(x, y, -y->sign, z);
-}
-
 
 void
 mp_factorial(const MPNumber *x, MPNumber *z)
@@ -1832,9 +1785,8 @@ mp_modulus_divide(const MPNumber *x, const MPNumber *y, MPNumber *z)
     mp_subtract(x, &t2, z);
 
     mp_set_from_integer(0, &t1);
-    if ((mp_is_less_than(y, &t1) && mp_is_greater_than(z, &t1)) || mp_is_less_than(z, &t1)) {
+    if ((mp_is_less_than(y, &t1) && mp_is_greater_than(z, &t1)) || mp_is_less_than(z, &t1))
         mp_add(z, y, z);
-    }
 }
 
 
diff --git a/src/unittest.c b/src/unittest.c
index bbf3bc5..b93b376 100644
--- a/src/unittest.c
+++ b/src/unittest.c
@@ -136,6 +136,10 @@ test_parser()
     test("1½", "1.5", 0);
     test("1.00", "1", 0);
     test("1.01", "1.01", 0);
+
+    test("١٢٣٤٥٦٧٨٩٠", "1234567890", 0);
+    test("Û±Û²Û³Û´ÛµÛ¶Û·Û¸Û¹Û°", "1234567890", 0);
+
     //test("2A", "2000000000000000", 0);
     test("2T", "2000000000000", 0);
     test("2G", "2000000000", 0);
@@ -164,9 +168,12 @@ test_parser()
     //test("2n3", "0.0000000023", 0); // FIXME: Need to print out significant figures, not decimal places
     //test("2p3", "0.0000000000023", 0); // FIXME: Need to print out significant figures, not decimal places
     //test("2f3", "0.0000000000000023", 0); // FIXME: Need to print out significant figures, not decimal places
+
+    test("2Ã?10^3", "2000", 0);
+    test("2Ã?10^â??3", "0.002", 0);
+
     test("Ï?", "3.141592654", 0);
     test("e", "2.718281828", 0);
-
     test("2Ï?", "6.283185307", 0);
     test("2e", "5.436563657", 0);
     //test("2Ï?²", "19.739208802", 0);
@@ -176,9 +183,6 @@ test_parser()
     test("Ï?e", "8.539734223", 0);
     test("eÏ?", "8.539734223", 0);
     //test("2Ï?e", "17.079468445", 0);
-    
-    test("١٢٣٤٥٦٧٨٩٠", "1234567890", 0);
-    test("Û±Û²Û³Û´ÛµÛ¶Û·Û¸Û¹Û°", "1234567890", 0);
 
     test("0+0", "0", 0);
     test("1+1", "2", 0);
@@ -189,39 +193,42 @@ test_parser()
     test("2-3", "â??1", 0);
     test("2â??3", "â??1", 0);
     test("3â??2", "1", 0);
-    test("1â??0.9â??0.1", "0", 0);
     test("40000â??0.001", "39999.999", 0);
     test("0.001â??40000", "â??39999.999", 0);
-    test("40000000â??40000000", "0", 0);
     test("2*3", "6", 0);
     test("2Ã?3", "6", 0);
     test("â??2Ã?3", "â??6", 0);
     test("2Ã?â??3", "â??6", 0);
     test("â??2Ã?â??3", "6", 0);
-    
-    test("2Ã?10^3", "2000", 0);
-    test("2Ã?10^â??3", "0.002", 0);
-
     test("6/3", "2", 0);
     test("6÷3", "2", 0);
     test("1÷2", "0.5", 0);
     test("â??6÷3", "â??2", 0);
     test("6÷â??3", "â??2", 0);
     test("â??6÷â??3", "2", 0);
+    test("(â??3)÷(â??6)", "0.5", 0);
     test("2÷2", "1", 0);
     test("1203÷1", "1203", 0);
     test("â??0÷32352.689", "0", 0);
     test("1÷4", "0.25", 0);
-    test("(â??3)÷(â??6)", "0.5", 0);
     test("1÷3", "0.333333333", 0);
     test("2÷3", "0.666666667", 0);
     test("1÷0", "", -20001);
     test("0÷0", "", -20001);
+    
+    /* Precision */
+    test("1000000000000000â??1000000000000000", "0", 0);
+    test("1000000000000000÷1000000000000000", "1", 0);
+    test("1000000000000000Ã?0.000000000000001", "1", 0);    
 
+    /* Order of operations */
+    test("1â??0.9â??0.1", "0", 0);
     test("1+2Ã?3", "7", 0);
     test("1+(2Ã?3)", "7", 0);
     test("(1+2)Ã?3", "9", 0);
+    test("(1+2Ã?3)", "7", 0);
     
+    /* Percentage */
     test("100%", "1", 0);
     test("1%", "0.01", 0);
     test("100+1%", "101", 0);
@@ -229,16 +236,17 @@ test_parser()
     test("100Ã?1%", "1", 0);
     test("100÷1%", "10000", 0);
 
+    /* Factorial */
     test("0!", "1", 0);
     test("1!", "1", 0);
     test("5!", "120", 0);
     test("69!", "171122452428141311372468338881272839092270544893520369393648040923257279754140647424000000000000000", 0);
     test("0.1!", "", -20001);
-    test("â??1!", "", -20001);
-    test("0â??1!", "â??1", 0);    
+    test("â??1!", "â??1", 0);
     test("(â??1)!", "", -20001);
     test("â??(1!)", "â??1", 0);
 
+    /* Powers */
     test("2²", "4", 0);
     test("2³", "8", 0);
     test("2¹�", "1024", 0);
@@ -249,7 +257,7 @@ test_parser()
     //test("2â?»", "", -20001); // FIXME: Maybe an error in bison?
     test("2^â??1", "0.5", 0);
     test("2^(â??1)", "0.5", 0);
-    test("â??10^2", "100", 0);
+    test("â??10^2", "â??100", 0);
     test("(â??10)^2", "100", 0);
     test("â??(10^2)", "â??100", 0);
     test("2^100", "1267650600228229401496703205376", 0);
@@ -270,8 +278,8 @@ test_parser()
     test("Sqrt(2)", "1.414213562", 0);
     test("4^0.5", "2", 0);
     test("2^0.5", "1.414213562", 0);
-    test("â??4^0.5", "", -20001);
-    test("â??8^(1÷3)", "â??2", 0);
+    test("(â??4)^0.5", "", -20001);
+    test("(â??8)^(1÷3)", "â??2", 0);
     
     test("0 mod 7", "0", 0);
     test("6 mod 7", "6", 0);



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