gcalctool r2328 - in trunk: . gcalctool



Author: rancell
Date: Mon Dec  8 14:26:46 2008
New Revision: 2328
URL: http://svn.gnome.org/viewvc/gcalctool?rev=2328&view=rev

Log:
Rewrote mp<->str functions and fixed up some exponential stuff

Modified:
   trunk/ChangeLog
   trunk/gcalctool/ce_tokeniser.l
   trunk/gcalctool/display.c
   trunk/gcalctool/functions.c
   trunk/gcalctool/mp-binary.c
   trunk/gcalctool/mp-convert.c
   trunk/gcalctool/mp.c
   trunk/gcalctool/mp.h
   trunk/gcalctool/register.c
   trunk/gcalctool/unittest.c

Modified: trunk/gcalctool/ce_tokeniser.l
==============================================================================
--- trunk/gcalctool/ce_tokeniser.l	(original)
+++ trunk/gcalctool/ce_tokeniser.l	Mon Dec  8 14:26:46 2008
@@ -44,8 +44,7 @@
 OCT     [0-7]
 DEC	[0-9]
 HEX     [0-9]|[A-F]|[a-f]
-EXP     "e+"|"e-"|"E+"|"E-"
-NEP     "e"
+EXP     "e"|"e+"|"e-"|"E"|"E+"|"E-"
 HEX_NUM {HEX}+|{HEX}*{DECIMAL}{HEX}*
 DEC_NUM{DEC}+|{DEC}*{DECIMAL}{DEC}*
 OCT_NUM{OCT}+|{OCT}*{DECIMAL}{OCT}*

Modified: trunk/gcalctool/display.c
==============================================================================
--- trunk/gcalctool/display.c	(original)
+++ trunk/gcalctool/display.c	Mon Dec  8 14:26:46 2008
@@ -642,7 +642,7 @@
         }
     }
  
-    mp_cast_to_string(fixed, MAX_DIGITS, MPmant, base, v->accuracy, MAX_DIGITS-6);
+    mp_cast_to_string(fixed, MAX_DIGITS, MPmant, basevals[base], v->accuracy);
     len = strlen(fixed);
     for (i = 0; i < len; i++) {
         *optr++ = fixed[i];
@@ -713,6 +713,6 @@
         (v->dtype == FIX && val != 0.0 && (val > max_fix[base]))) {
         make_eng_sci(target, target_len, MPnumber, base);
     } else {
-        mp_cast_to_string(target, target_len, MPnumber, base, v->accuracy, MAX_DIGITS);
+        mp_cast_to_string(target, target_len, MPnumber, basevals[base], v->accuracy);
     }
 }

Modified: trunk/gcalctool/functions.c
==============================================================================
--- trunk/gcalctool/functions.c	(original)
+++ trunk/gcalctool/functions.c	Mon Dec  8 14:26:46 2008
@@ -259,9 +259,6 @@
 {
     int ret, MP[MP_SIZE];
 
-    v->dtype = n;
-    set_resource(R_DISPLAY, Rdstr[(int) v->dtype]);
-
     ret = display_is_usable_number(&v->display, MP);
     if (ret) {
         ui_set_statusbar(_("No sane value to convert"),
@@ -269,9 +266,12 @@
     } else {
         mp_set_from_mp(MP, display_get_answer(&v->display));
         display_set_string(&v->display, "Ans", -1);
-        ui_make_registers();
     }
     clear_undo_history();
+   
+    v->dtype = n;
+    set_resource(R_DISPLAY, Rdstr[(int) v->dtype]);
+    ui_make_registers();
 
     display_set_cursor(&v->display, -1);
     display_refresh(&v->display);

Modified: trunk/gcalctool/mp-binary.c
==============================================================================
--- trunk/gcalctool/mp-binary.c	(original)
+++ trunk/gcalctool/mp-binary.c	Mon Dec  8 14:26:46 2008
@@ -20,13 +20,13 @@
 {
     char text1[MAX_DIGITS], text2[MAX_DIGITS], text_out[MAX_DIGITS];
     int offset1, offset2, offset_out;
-    
-    mp_cast_to_string(text1, MAX_DIGITS, s1, HEX, MAX_DIGITS, MAX_DIGITS);
-    mp_cast_to_string(text2, MAX_DIGITS, s2, HEX, MAX_DIGITS, MAX_DIGITS);
+   
+    mp_cast_to_string(text1, MAX_DIGITS, s1, 16, 0);
+    mp_cast_to_string(text2, MAX_DIGITS, s2, 16, 0);
     offset1 = strlen(text1) - 1;
     offset2 = strlen(text2) - 1;
     offset_out = offset1 > offset2 ? offset1 : offset2;
-    
+   
     /* Be at least 32 bits wide so inverse operations make sense */
     if (offset_out < 7)
         offset_out = 7;
@@ -45,7 +45,7 @@
         }
         text_out[offset_out] = digits[bitwise_operator(v1, v2)];
     }
-    
+   
     mp_set_from_string(text_out, 16, t);
 }
 
@@ -90,7 +90,7 @@
 {
     int dummy[MP_SIZE];
     mp_set_from_integer(0, dummy);
-    mp_bitwise(s1, dummy, mp_bitwise_not, t);    
+    mp_bitwise(s1, dummy, mp_bitwise_not, t);
 }
 
 
@@ -101,7 +101,7 @@
     size_t len, offset;
     
     /* Convert to a hexadecimal string and use last 8 characters */
-    mp_cast_to_string(text, MAX_DIGITS, s1, HEX, MAX_DIGITS, MAX_DIGITS);
+    mp_cast_to_string(text, MAX_DIGITS, s1, 16, 0);
     len = strlen(text);
     offset = len > 8 ? len - 8: 0;
     mp_set_from_string(text + offset, 16, t1);
@@ -115,7 +115,7 @@
     size_t len, offset;
     
     /* Convert to a hexadecimal string and use last 4 characters */
-    mp_cast_to_string(text, MAX_DIGITS, s1, HEX, MAX_DIGITS, MAX_DIGITS);
+    mp_cast_to_string(text, MAX_DIGITS, s1, 16, 0);
     len = strlen(text);
     offset = len > 4 ? len - 4: 0;
     mp_set_from_string(text + offset, 16, t1);

Modified: trunk/gcalctool/mp-convert.c
==============================================================================
--- trunk/gcalctool/mp-convert.c	(original)
+++ trunk/gcalctool/mp-convert.c	Mon Dec  8 14:26:46 2008
@@ -21,6 +21,7 @@
 
 #include <stdlib.h>
 #include <string.h>
+#include <ctype.h>
 #include <math.h>
 #include <assert.h>
 
@@ -478,88 +479,112 @@
 /* Convert MP number to fixed number string in the given base to the
  * maximum number of digits specified.
  */
-// FIXME: Rewrite
 void
-mp_cast_to_string(char *target, int target_len, const int *MPnumber, int base, int accuracy, int cmax)
+mp_cast_to_string(char *target, int target_len, const int *MPnumber, int base, int accuracy)
 {
     static char digits[] = "0123456789ABCDEF";
-    char *optr;
-    int MP1base[MP_SIZE], MP1[MP_SIZE], MP2[MP_SIZE], MPval[MP_SIZE];
-    int ndig;                   /* Total number of digits to generate. */
-    int ddig;                   /* Number of digits to left of decimal sep. */
-    int dval, i;
- 
+    char *optr, *start, *end, *last_non_zero;
+    int number[MP_SIZE], integer_component[MP_SIZE], fractional_component[MP_SIZE], MPbase[MP_SIZE], temp[MP_SIZE];
+   
     optr = target;
-    mp_abs(MPnumber, MPval);
-    mp_set_from_integer(0, MP1);
-    if (mp_is_less_than(MPnumber, MP1)) {
+
+    /* Insert sign */
+    if (mp_is_negative(MPnumber)) {
         *optr++ = '-';
+        mp_abs(MPnumber, number);
+    } else  {
+        mp_set_from_mp(MPnumber, number);	
     }
-
-    mp_set_from_integer(basevals[base], MP1base);
-
-    mppwr(MP1base, accuracy, MP1);
-    mp_set_from_string("0.5", 10, MP2);
-    mpdiv(MP2, MP1, MP1);
-    mp_add(MPval, MP1, MPval);
-
-    mp_set_from_integer(1, MP2);
-    if (mp_is_less_than(MPval, MP2)) {
-        ddig = 0;
-        *optr++ = '0';
-        cmax--;
-    } else {
-        for (ddig = 0; mp_is_greater_equal(MPval, MP2); ddig++) {
-            mpdiv(MPval, MP1base, MPval);
-        }
+   
+    /* Add rounding factor */
+    mp_set_from_integer(base, MPbase);
+    mppwr(MPbase, -(accuracy+1), temp);
+    mpmuli(temp, base, temp);
+    mpdivi(temp, 2, temp);
+    mp_add(number, temp, number);
+
+    /* Split into integer and fractional component */
+    mpcmim(number, integer_component);
+    mpcmf(number, fractional_component);  
+
+    /* Write out the integer component least significant digit to most */
+    start = optr;
+    mp_set_from_mp(integer_component, temp);
+    do {
+        int t[MP_SIZE], t2[MP_SIZE], t3[MP_SIZE];
+       
+        mpdivi(temp, base, t);
+        mpcmim(t, t);
+        mpmuli(t, base, t2);
+       
+        mp_subtract(temp, t2, t3);
+        mpcmim(t3, t3);
+        *optr++ = digits[mp_cast_to_int(t3)];
+       
+        mp_set_from_mp(t, temp);
+    } while (!mp_is_zero(temp));
+    end = optr - 1;
+   
+    /* Reverse digits */
+    while(start < end) {
+        char t;
+        t = *start;
+        *start = *end;
+        *end = t;
+        start++;
+        end--;
     }
- 
-    ndig = (ddig + accuracy) < (--cmax) ? (ddig + accuracy) : (--cmax);
-
-    while (ndig-- > 0) {
-        if (ddig-- == 0) {
-            for (i = 0; i < strlen(v->radix); i++)
-                *optr++ = v->radix[i];
-        }
-        mpmul(MPval, MP1base, MPval);
-        dval = mp_cast_to_int(MPval);
-
-        if (dval > basevals[base]-1) {
-            dval = basevals[base]-1;
-        }
-
-        *optr++ = digits[dval];
-        dval = -dval;
-        mp_add_integer(MPval, dval, MPval);
-    }    
-    *optr++ = '\0';
-
-    /* Strip off trailing zeroes */
-    if (!v->show_zeroes) {
-        for (i = strlen(target) - 1; i > 1 && target[i] == '0'; i--) {
-            target[i] = '\0';
-        }
-        
-        /* If no fractional part discard radix */
-        if (strlen(target) >= strlen(v->radix) && strcmp(target + strlen(target) - strlen(v->radix), v->radix) == 0) {
-            target[strlen(target) - strlen(v->radix)] = '\0';
-        }
+   
+    /* Stop if there is no fractional component or not showing fractional part */
+    if ((mp_is_zero(fractional_component) && !v->show_zeroes) || accuracy == 0) {
+        *optr = '\0';
+        return;
     }
+   
+    last_non_zero = optr;
+    *optr++ = '.';
+   
+    /* Write out the fractional component */
+    mp_set_from_mp(fractional_component, temp);
+    do {
+        int d;
+        int digit[MP_SIZE];
+
+        mpmuli(temp, base, temp);
+        mpcmim(temp, digit);
+        d = mp_cast_to_int(digit);
+       
+        *optr++ = digits[d];
+        if(d != 0)
+	   last_non_zero = optr;
+        mp_subtract(temp, digit, temp);
+        accuracy--;
+    } while (!mp_is_zero(temp) && accuracy > 0);
+
+    /* Strip trailing zeroes */
+    if (!v->show_zeroes)
+       optr = last_non_zero;
+
+    *optr = '\0';
 }
 
 
 static int
-char_val(char chr)
+char_val(char chr, int base)
 {
+    int value;
     if (chr >= '0' && chr <= '9') {
-        return(chr - '0');
+        value = chr - '0';
     } else if (chr >= 'a' && chr <= 'f') {
-        return(chr - 'a' + 10);
+        value = chr - 'a' + 10;
     } else if (chr >= 'A' && chr <= 'F') {
-        return(chr - 'A' + 10);
+        value = chr - 'A' + 10;
     } else {
-        return(-1);
+        return -1;
     }
+    if (value >= base)
+       return -1;
+    return value;
 }
 
 
@@ -569,17 +594,13 @@
 mp_set_from_string(const char *str, int base, int *MPval)
 {
     const char *optr;
-    int MP1[MP_SIZE], MP2[MP_SIZE], MPbase[MP_SIZE];
-    int i, inum;
+    int inum;
     int negate = 0;
 
-    mp_set_from_integer(0, MPval);
-    mp_set_from_integer(base, MPbase);
-
     optr = str;
 
-    /* Remove any initial spaces or tabs. */
-    while (*optr == ' ' || *optr == '\t') {
+    /* Remove leading whitespace */
+    while (isspace(*optr)) {
         optr++;
     }
 
@@ -589,48 +610,65 @@
         optr++;
     }
 
-    while ((inum = char_val(*optr)) >= 0) {
-        mpmul(MPval, MPbase, MPval);
+    /* Convert integer part */
+    mp_set_from_integer(0, MPval);
+    while ((inum = char_val(*optr, base)) >= 0) {
+        mpmuli(MPval, base, MPval);
         mp_add_integer(MPval, inum, MPval);
         optr++;
     }
-
+   
+    /* Convert fractional part */
     if (*optr == '.' || *optr == *v->radix) {
+        int numerator[MP_SIZE], denominator[MP_SIZE];
+       
         optr++;
-        for (i = 1; (inum = char_val(*optr)) >= 0; i++) {
-            mppwr(MPbase, i, MP1);
-            mp_set_from_integer(inum, MP2);
-            mpdiv(MP2, MP1, MP1);
-            mp_add(MPval, MP1, MPval);
+
+        mp_set_from_integer(0, numerator);
+        mp_set_from_integer(1, denominator);
+        while ((inum = char_val(*optr, base)) >= 0) {
+	    mpmuli(denominator, base, denominator);
+	    mpmuli(numerator, base, numerator);
+	    mp_add_integer(numerator, inum, numerator);
             optr++;
         }
+        mpdiv(numerator, denominator, numerator);
+        mp_add(MPval, numerator, MPval);
     }
    
+    /* Convert exponential part */
     if (*optr == 'e' || *optr == 'E') {
         int negate = 0;
-        int MPexponent[MP_SIZE], temp1[MP_SIZE], temp2[MP_SIZE];
-        optr++;
+        int MPbase[MP_SIZE], MPexponent[MP_SIZE], temp[MP_SIZE];
+
+        optr++;       
+
+        /* Get sign */
         if (*optr == '-') {
 	    negate = 1;
 	    optr++;
+	} else if (*optr == '+') {
+	    optr++;
 	}
+
+        /* Get magnitude */
         mp_set_from_integer(0, MPexponent);
-        while ((inum = char_val(*optr)) >= 0) {
-            mpmul(MPval, MPbase, MPval);
-            mp_add_integer(MPval, inum, MPval);
+        while ((inum = char_val(*optr, base)) >= 0) {
+            mpmuli(MPexponent, base, MPexponent);
+            mp_add_integer(MPexponent, inum, MPexponent);
             optr++;
         }
-        if (negate == 1) {
+        if (negate) {
             mp_invert_sign(MPexponent, MPexponent);
         }
-       
-        mppwr2(MPbase, MPexponent, temp1);
-        mpmul(MPval, temp1, temp2);
-        mp_set_from_mp(temp2, MPval);
+
+        mp_set_from_integer(base, MPbase);       
+        mppwr2(MPbase, MPexponent, temp);
+        mpmul(MPval, temp, MPval);
     }
 
     /* Strip trailing whitespace */
-    while (*optr == ' ') {
+    while (isspace(*optr)) {
         optr++;
     }
    

Modified: trunk/gcalctool/mp.c
==============================================================================
--- trunk/gcalctool/mp.c	(original)
+++ trunk/gcalctool/mp.c	Mon Dec  8 14:26:46 2008
@@ -456,10 +456,7 @@
 void
 mpcmim(const int *x, int *y)
 {
-    int tmp[MP_SIZE];     /* Temporary store for the number. */
-    char disp[MAXLINE];   /* Setup a string to store what would be displayed */
-
-    int i, il, ll;
+    int i, il;
 
     mpchk(1, 4);
     mp_set_from_mp(x, y);
@@ -468,7 +465,6 @@
     }
 
     il = y[1] + 1;
-    ll = il;
 
     /* IF EXPONENT LARGE ENOUGH RETURN Y = X */
     if (il > MP.t) {
@@ -485,13 +481,6 @@
     for (i = il; i <= MP.t; ++i) {
         y[i + 1] = 0;
     }
-
-    // FIXME: Won't this have completely different behaviour depending on base?
-    mpcmf(x, tmp);
-    mp_cast_to_string(disp, MAXLINE, tmp, v->base, MAX_DIGITS, MAX_DIGITS);
-    if (disp[0] == '1') {
-        y[ll]++;
-    }
 }
 
 /*  COMPARES MP NUMBER X WITH REAL NUMBER RI, RETURNING
@@ -1149,6 +1138,22 @@
 
 
 int
+mp_is_zero(const int *x)
+{
+    return x[0] == 0;
+}
+
+
+int 
+mp_is_negative(const int *x)
+{
+    int zero[MP_SIZE];
+    mp_set_from_integer(0, zero);
+    return mp_is_less_than(x, zero);
+}
+
+
+int
 mp_is_greater_equal(const int *x, const int *y)
 {
     /* RETURNS LOGICAL VALUE OF (X >= Y) FOR MP X AND Y. */

Modified: trunk/gcalctool/mp.h
==============================================================================
--- trunk/gcalctool/mp.h	(original)
+++ trunk/gcalctool/mp.h	Mon Dec  8 14:26:46 2008
@@ -53,6 +53,9 @@
 
 int mp_compare_mp_to_mp(const int *x, const int *y);
 
+int mp_is_zero(const int *x);
+int mp_is_negative(const int *x);
+
 /* return true if parameter is integer */
 int mp_is_integer(int MPnum[MP_SIZE]);
 
@@ -105,7 +108,7 @@
 float  mp_cast_to_float(const int *);
 double mp_cast_to_double(const int *);
 int    mp_cast_to_int(const int *);
-void   mp_cast_to_string(char *, int, const int *, int, int, int);
+void   mp_cast_to_string(char *, int, const int *, int, int);
 
 /* mp-trigonometric.c */
 void mp_acos(const int *x, int *z);

Modified: trunk/gcalctool/register.c
==============================================================================
--- trunk/gcalctool/register.c	(original)
+++ trunk/gcalctool/register.c	Mon Dec  8 14:26:46 2008
@@ -144,7 +144,7 @@
 
     /* NOTE: Constants are written out with no thousands separator and with a
        radix character of ".". */
-    mp_cast_to_string(text, MAX_LOCALIZED, value, DEC, MAX_DIGITS, MAX_DIGITS);
+    mp_cast_to_string(text, MAX_LOCALIZED, value, 10, MAX_DIGITS);
     SNPRINTF(key, MAXLINE, "constant%1dvalue", index);
     set_resource(key, text);
 }

Modified: trunk/gcalctool/unittest.c
==============================================================================
--- trunk/gcalctool/unittest.c	(original)
+++ trunk/gcalctool/unittest.c	Mon Dec  8 14:26:46 2008
@@ -43,7 +43,7 @@
         return;
     }
     
-    mp_cast_to_string(result_str, MAXLINE, result, DEC, 100, 100);
+    mp_cast_to_string(result_str, MAXLINE, result, basevals[v->base], 100);
     if(strcmp(result_str, expected) != 0)
         printf("FAIL: '%s' -> '%s', expected '%s'\n", expression, result_str, expected);
     else
@@ -66,9 +66,9 @@
     test("1.00", "1", 0);
     test("1.01", "1.01", 0);
     test("pi", "3.141592654", 0);
+    test("1e3", "1000", 0);
     test("1e+3", "1000", 0);
     test("1e-3", "0.001", 0);
-    test("1e9", "1000000000", 0);
 
     test("0+0", "0", 0);
     test("1+1", "2", 0);
@@ -162,11 +162,12 @@
     v->ttype = GRAD;
     test("Sin(100)", "1", 0);
 
+    v->base = HEX;
     test("3 And 5", "1", 0);
     test("3 Or 5", "7", 0);
     test("3 Xor 5", "6", 0);
-    test("3 Xnor 5", "4294967289", 0);
-    test("~ 122", "4294967173", 0);
+    test("3 Xnor 5", "FFFFFFF9", 0);
+    test("~7A", "FFFFFF85", 0);
 }
 
 



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