gcalctool r2326 - trunk/gcalctool



Author: rancell
Date: Tue Dec  2 17:21:43 2008
New Revision: 2326
URL: http://svn.gnome.org/viewvc/gcalctool?rev=2326&view=rev

Log:
Simplify MP functions


Modified:
   trunk/gcalctool/ce_tokeniser.l
   trunk/gcalctool/display.c
   trunk/gcalctool/display.h
   trunk/gcalctool/functions.c
   trunk/gcalctool/get.c
   trunk/gcalctool/gtk.c
   trunk/gcalctool/mp-boolean.c
   trunk/gcalctool/mp-convert.c
   trunk/gcalctool/mp-trigonometric.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	Tue Dec  2 17:21:43 2008
@@ -106,28 +106,28 @@
 {BIN_NUM} {
 if (v->base != BIN) REJECT;
 if (strlen(yytext) > MAX_DIGITS) parser_state.error = -PARSER_ERR_TOO_LONG_NUMBER;
-MPstr_to_num(yytext, basevals[v->base], celval.int_t);
+mp_set_from_string(yytext, basevals[v->base], celval.int_t);
 return tNUMBER;
 }
 
 {OCT_NUM} {
 if (v->base != OCT) REJECT;
 if (strlen(yytext) > MAX_DIGITS) parser_state.error = -PARSER_ERR_TOO_LONG_NUMBER;
-MPstr_to_num(yytext, basevals[v->base], celval.int_t);
+mp_set_from_string(yytext, basevals[v->base], celval.int_t);
 return tNUMBER;
 }
 
 {DEC_NUM} {
 if (v->base != DEC) REJECT;
 if (strlen(yytext) > MAX_DIGITS) parser_state.error = -PARSER_ERR_TOO_LONG_NUMBER;
-MPstr_to_num(yytext, basevals[v->base], celval.int_t);
+mp_set_from_string(yytext, basevals[v->base], celval.int_t);
 return tNUMBER;
 }
 
 {HEX_NUM} {
 if (v->base != HEX) REJECT;
 if (strlen(yytext) > MAX_DIGITS) parser_state.error = -PARSER_ERR_TOO_LONG_NUMBER;
-MPstr_to_num(yytext, basevals[v->base], celval.int_t);
+mp_set_from_string(yytext, basevals[v->base], celval.int_t);
 return tNUMBER;
 }
 

Modified: trunk/gcalctool/display.c
==============================================================================
--- trunk/gcalctool/display.c	(original)
+++ trunk/gcalctool/display.c	Tue Dec  2 17:21:43 2008
@@ -215,7 +215,7 @@
         text = "0";
     }
     else if (display_is_result(display)) {
-        mp_cast_to_number(buf, MAX_DISPLAY, display_get_answer(display), v->base, FALSE);
+        display_make_number(buf, MAX_DISPLAY, display_get_answer(display), v->base, FALSE);
         text = buf;
     }
     
@@ -237,7 +237,7 @@
         text = "0";
     }
     else if (display_is_result(display)) {
-        mp_cast_to_number(buf, MAX_DISPLAY, display_get_answer(display), v->base, FALSE);
+        display_make_number(buf, MAX_DISPLAY, display_get_answer(display), v->base, FALSE);
         text = buf;
     }
     
@@ -263,12 +263,11 @@
 }
 
 void
-display_set_number(GCDisplay *display, int *MPval)
+display_set_number(GCDisplay *display, const int *MPval)
 {
-    if (!v->error) {
-        mp_cast_to_number(display->display, MAX_DISPLAY, MPval, v->base, FALSE);
-        ui_set_display(display->display, -1);
-    }
+   char text[MAX_DISPLAY];
+   display_make_number(text, MAX_DISPLAY, MPval, v->base, FALSE);
+   display_set_string(display, text, -1);
 }
 
 void
@@ -411,6 +410,15 @@
 }
 
 void
+display_insert_number(GCDisplay *display, const int value[MP_SIZE])
+{
+    char text[MAX_DISPLAY];
+    display_make_number(text, MAX_DISPLAY, value, v->base, FALSE);
+    display_insert(display, text);
+}
+
+
+void
 display_backspace(GCDisplay *display)
 {
     char buf[MAX_DISPLAY] = "", buf2[MAX_DISPLAY], *t;
@@ -422,7 +430,7 @@
     /* If cursor is at end of the line then delete the last character preserving accuracy */
     if (cursor < 0) {
         if (exp_has_postfix(e->expression, "Ans")) {
-            mp_cast_to_number(buf, MAX_DISPLAY, e->ans, v->base, FALSE);
+            display_make_number(buf, MAX_DISPLAY, e->ans, v->base, FALSE);
             t = str_replace(e->expression, "Ans", buf);
             free(e->expression);
             e->expression = t;
@@ -431,7 +439,7 @@
                 SNPRINTF(buf, MAX_DISPLAY, "R%d", i);
                 if (exp_has_postfix(e->expression, buf)) {
                     register_get(i, MP_reg);
-                    mp_cast_to_number(buf2, MAX_DISPLAY, MP_reg, v->base, FALSE);
+                    display_make_number(buf2, MAX_DISPLAY, MP_reg, v->base, FALSE);
                     /* Remove "Rx" postfix and replace with backspaced number */
                     SNPRINTF(buf, MAX_DISPLAY, "%.*s%s", strlen(e->expression) - 2, e->expression - 3, buf2);
                     display_set_string(display, buf, cursor - 1);
@@ -488,14 +496,14 @@
     e = get_state(display);
     if (display_is_empty(display)) {
         mp_set_from_integer(0, MP_reg);
-        mp_cast_to_number(x, MAX_LOCALIZED, MP_reg, v->base, FALSE);
+        display_make_number(x, MAX_LOCALIZED, MP_reg, v->base, FALSE);
         str = x;
     } else {           
         str = strdup(e->expression);
     }
         
     /* Substitute answer register */
-    mp_cast_to_number(ans, MAX_LOCALIZED, e->ans, v->base, TRUE);
+    display_make_number(ans, MAX_LOCALIZED, e->ans, v->base, TRUE);
     localize_expression(localized, ans, MAX_LOCALIZED, &cursor);
     str = str_replace(str, "Ans", localized);
 
@@ -503,7 +511,7 @@
     for (i = 0; i < 10; i++) {
         SNPRINTF(reg, 3, "R%d", i);
         register_get(i, MP_reg);
-        mp_cast_to_number(xx, MAX_LOCALIZED, MP_reg, v->base, FALSE);
+        display_make_number(xx, MAX_LOCALIZED, MP_reg, v->base, FALSE);
         t = str_replace(str, reg, xx);
         free(str);
         str = t;
@@ -574,3 +582,137 @@
     
     return errorCode;
 }
+
+
+/* Convert engineering or scientific number in the given base. */
+void
+make_eng_sci(char *target, int target_len, const int *MPnumber, int base)
+{
+    static char digits[] = "0123456789ABCDEF";   
+    char fixed[MAX_DIGITS], *optr;
+    int MP1[MP_SIZE], MPatmp[MP_SIZE], MPval[MP_SIZE];
+    int MP1base[MP_SIZE], MP3base[MP_SIZE], MP10base[MP_SIZE];
+    int i, dval, len;
+    int MPmant[MP_SIZE];        /* Mantissa. */
+    int ddig;                   /* Number of digits in exponent. */
+    int eng = 0;                /* Set if this is an engineering number. */
+    int exp = 0;                /* Exponent */
+    
+    if (v->dtype == ENG) {
+        eng = 1;
+    }
+    optr = target;
+    mp_abs(MPnumber, MPval);
+    mp_set_from_integer(0, MP1);
+    if (mp_is_less_than(MPnumber, MP1)) {
+        *optr++ = '-';
+    }
+    mp_set_from_mp(MPval, MPmant);
+
+    mp_set_from_integer(basevals[base], MP1base);
+    mppwr(MP1base, 3, MP3base);
+
+    mppwr(MP1base, 10, MP10base);
+
+    mp_set_from_integer(1, MP1);
+    mpdiv(MP1, MP10base, MPatmp);
+
+    mp_set_from_integer(0, MP1);
+    if (!mp_is_equal(MPmant, MP1)) {
+        while (!eng && mp_is_greater_equal(MPmant, MP10base)) {
+            exp += 10;
+            mpmul(MPmant, MPatmp, MPmant);
+        }
+ 
+        while ((!eng &&  mp_is_greater_equal(MPmant, MP1base)) ||
+                (eng && (mp_is_greater_equal(MPmant, MP3base) || exp % 3 != 0))) {
+            exp += 1;
+            mpdiv(MPmant, MP1base, MPmant);
+        }
+ 
+        while (!eng && mp_is_less_than(MPmant, MPatmp)) {
+            exp -= 10;
+            mpmul(MPmant, MP10base, MPmant);
+        }
+ 
+        mp_set_from_integer(1, MP1);
+        while (mp_is_less_than(MPmant, MP1) || (eng && exp % 3 != 0)) {
+            exp -= 1;
+            mpmul(MPmant, MP1base, MPmant);
+        }
+    }
+ 
+    mp_cast_to_string(fixed, MAX_DIGITS, MPmant, base, v->accuracy, MAX_DIGITS-6);
+    len = strlen(fixed);
+    for (i = 0; i < len; i++) {
+        *optr++ = fixed[i];
+    }
+ 
+    *optr++ = 'e';
+ 
+    if (exp < 0) {
+        exp = -exp;
+        *optr++ = '-';
+    } else {
+        *optr++ = '+';
+    }
+ 
+    mp_set_from_string("0.5", 10, MP1);
+    mp_add_integer(MP1, exp, MPval);
+    mp_set_from_integer(1, MP1);
+    for (ddig = 0; mp_is_greater_equal(MPval, MP1); ddig++) {
+        mpdiv(MPval, MP1base, MPval);
+    }
+ 
+    if (ddig == 0) {
+        *optr++ = '0';
+    }
+ 
+    while (ddig-- > 0) {
+        mpmul(MPval, MP1base, MPval);
+        dval = mp_cast_to_int(MPval);
+        *optr++ = digits[dval];
+        dval = -dval;
+        mp_add_integer(MPval, dval, MPval);
+    }
+    *optr++    = '\0';
+}
+
+
+/* Convert MP number to character string in the given base. */
+void
+display_make_number(char *target, int target_len, const int *MPnumber, int base, int ignoreError)
+{
+    static double max_fix[MAXBASES] = {
+       1.298074214e+33,    /* Binary. */
+       2.037035976e+90,    /* Octal. */
+       1.000000000e+100,   /* Decimal */
+       2.582249878e+120    /* Hexadecimal. */
+    };
+
+    double val;
+    
+    /*  NOTE: display_make_number can currently set v->error when converting to a double.
+     *        This is to provide the same look&feel as V3 even though gcalctool
+     *        now does internal arithmetic to "infinite" precision.
+     *
+     *  XXX:  Needs to be improved. Shouldn't need to convert to a double in
+     *        order to do these tests.
+     */
+
+    double number = mp_cast_to_double(MPnumber);
+
+    val = fabs(number);
+    if (v->error && !ignoreError) {
+        STRNCPY(target, _("Error"), target_len - 1);
+        return;
+    }
+    // FIXME: Do this based on the number of digits, not actual values
+    if ((v->dtype == ENG) ||
+        (v->dtype == SCI) ||
+        (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);
+    }
+}

Modified: trunk/gcalctool/display.h
==============================================================================
--- trunk/gcalctool/display.h	(original)
+++ trunk/gcalctool/display.h	Tue Dec  2 17:21:43 2008
@@ -46,7 +46,6 @@
 
 typedef struct
 {
-    char display[MAX_DISPLAY];  /* Current calculator display. */
     GCDisplayHistory h;         /* History of expression mode states */
 } GCDisplay;
 
@@ -62,7 +61,7 @@
 int *display_get_answer(GCDisplay *);
 int display_get_cursor(GCDisplay *);
 
-void display_set_number(GCDisplay *, int *);
+void display_set_number(GCDisplay *, const int *);
 void display_set_string(GCDisplay *, const char *, int);
 void display_set_cursor(GCDisplay *, int);
 void display_set_error(GCDisplay *, const char *);
@@ -74,6 +73,7 @@
 gboolean display_is_undo_step(GCDisplay *display);
 
 void display_insert(GCDisplay *, const char *);
+void display_insert_number(GCDisplay *display, const int *);
 void display_backspace(GCDisplay *);
 void display_delete(GCDisplay *);
 void display_surround(GCDisplay *, const char *, const char *);
@@ -84,4 +84,6 @@
 
 int display_solve(GCDisplay *, int *);
 
+void display_make_number(char *target, int target_len, const int *MPnumber, int base, int ignoreError);
+
 #endif /* DISPLAY_H */

Modified: trunk/gcalctool/functions.c
==============================================================================
--- trunk/gcalctool/functions.c	(original)
+++ trunk/gcalctool/functions.c	Tue Dec  2 17:21:43 2008
@@ -334,7 +334,7 @@
         case FN_CLEAR_ENTRY:
             display_clear(&v->display);
             ui_set_error_state(FALSE);
-            MPstr_to_num("0", 10, ans);
+            mp_set_from_string("0", 10, ans);
             break;
 
         case FN_SHIFT:
@@ -376,8 +376,7 @@
             break;
 
         case FN_CONSTANT:
-            mp_cast_to_number(buf, MAXLINE, constant_get_value(arg), v->base, FALSE);
-            display_insert(&v->display, buf);
+            display_insert_number(&v->display, constant_get_value(arg));
             break;
 
         case FN_BACKSPACE:
@@ -403,13 +402,10 @@
 
                 bit_value ^= (1LL << (63 - arg));
     
-                /* FIXME: Convert to since we don't support setting MP numbers from 64 bit integers */
+                /* FIXME: Convert to string since we don't support setting MP numbers from 64 bit integers */
                 SNPRINTF(buf, MAX_DISPLAY, "%llu", bit_value);
-                MPstr_to_num(buf, 10, MP);
-
-                /* FIXME: Set as string as display_set_number doesn't store correctly */
-                mp_cast_to_number(buf, MAX_DISPLAY, MP, v->base, FALSE);
-                display_set_string(&v->display, buf, -1);
+                mp_set_from_string(buf, 10, MP);
+                display_set_number(&v->display, MP);
             }
             break;
 

Modified: trunk/gcalctool/get.c
==============================================================================
--- trunk/gcalctool/get.c	(original)
+++ trunk/gcalctool/get.c	Tue Dec  2 17:21:43 2008
@@ -252,7 +252,7 @@
         SNPRINTF(key, MAXLINE, "register%d", i);
         if (get_str_resource(key, str)) {
             int temp[MP_SIZE];
-            MPstr_to_num(str, 10, temp);
+            mp_set_from_string(str, 10, temp);
             register_set(i, temp);
         }
     }

Modified: trunk/gcalctool/gtk.c
==============================================================================
--- trunk/gcalctool/gtk.c	(original)
+++ trunk/gcalctool/gtk.c	Tue Dec  2 17:21:43 2008
@@ -534,9 +534,8 @@
     int *ans;
 
     ans = display_get_answer(&v->display);
-    MPstr_to_num("0", 10, ans);
+    mp_set_from_integer(0, ans);
     display_clear(&v->display);
-    display_set_number(&v->display, ans);
 }
 
 
@@ -1389,7 +1388,7 @@
 {
     GdkScreen *screen;
     GError *error = NULL;
-   
+
     screen = gtk_widget_get_screen (GTK_WIDGET (X->kframe));
     gtk_show_uri (screen, "ghelp:gcalctool", gtk_get_current_event_time (), &error);
  
@@ -1505,7 +1504,7 @@
         }
         entry = glade_xml_get_widget(X->financial,
                                      finc_dialog_fields[dialog][i]);
-        MPstr_to_num(gtk_entry_get_text(GTK_ENTRY(entry)), 10, arg[i]);
+        mp_set_from_string(gtk_entry_get_text(GTK_ENTRY(entry)), 10, arg[i]);
         gtk_entry_set_text(GTK_ENTRY(entry), "0");
     }
     gtk_widget_grab_focus(glade_xml_get_widget(X->financial, 
@@ -1562,7 +1561,7 @@
     int i;
 
     for (i = 0; i < MAX_CONSTANTS; i++) {
-        mp_cast_to_number(value, MAXLINE, constant_get_value(i), DEC, TRUE);
+        display_make_number(value, MAXLINE, constant_get_value(i), DEC, TRUE);
         SNPRINTF(mline, MAXLINE, 
                  "<span weight=\"bold\">%s_%1d:</span> %s [%s]", _("C"), i, 
                  value, 
@@ -1617,7 +1616,7 @@
                                    COLUMN_NUMBER, &number,
                                    COLUMN_VALUE, &value,
                                    COLUMN_DESCRIPTION, &description, -1);
-                MPstr_to_num(value, 10, temp);
+                mp_set_from_string(value, 10, temp);
                 constant_set(number, description, temp);
             } while (gtk_tree_model_iter_next(X->constants_model, &iter));
         }
@@ -1685,7 +1684,7 @@
     for (i = 0; i < MAX_CONSTANTS; i++) {
         gtk_list_store_append(model, &iter);
         
-        mp_cast_to_number(constant, MAXLINE, constant_get_value(i), DEC, TRUE);
+        display_make_number(constant, MAXLINE, constant_get_value(i), DEC, TRUE);
         gtk_list_store_set(model, &iter,
                            COLUMN_NUMBER, i,
                            COLUMN_EDITABLE, TRUE,
@@ -1733,12 +1732,12 @@
         int temp[MP_SIZE];
         
         register_get(n, temp);
-        mp_cast_to_number(mval, MAXLINE, temp, v->base, TRUE);
+        display_make_number(mval, MAXLINE, temp, v->base, TRUE);
         gtk_entry_set_width_chars(GTK_ENTRY(X->regs[n]), strlen(mval));
         gtk_entry_set_text(GTK_ENTRY(X->regs[n]), mval);
 
         SNPRINTF(key, MAXLINE, "register%d", n);
-        mp_cast_to_number(value, MAXLINE, temp, DEC, TRUE);
+        display_make_number(value, MAXLINE, temp, DEC, TRUE);
         set_resource(key, value);
     }
 }
@@ -1816,7 +1815,7 @@
     for (i = 0; i < MAX_REGISTERS; i++) {
         int temp[MP_SIZE];
         register_get(i, temp);
-        mp_cast_to_number(value, MAXLINE, temp, v->base, TRUE);
+        display_make_number(value, MAXLINE, temp, v->base, TRUE);
         SNPRINTF(mstr, MAXLINE, "<span weight=\"bold\">%s_%d:</span>    %s",
         /* Translators: R is the short form of register used inter alia in popup menus */
                 _("R"), i, value);

Modified: trunk/gcalctool/mp-boolean.c
==============================================================================
--- trunk/gcalctool/mp-boolean.c	(original)
+++ trunk/gcalctool/mp-boolean.c	Tue Dec  2 17:21:43 2008
@@ -21,8 +21,8 @@
     char text1[MAX_DIGITS], text2[MAX_DIGITS], text_out[MAX_DIGITS];
     int offset1, offset2, offset_out;
     
-    mp_cast_to_fixed(text1, MAX_DIGITS, s1, HEX, MAX_DIGITS, MAX_DIGITS);
-    mp_cast_to_fixed(text2, MAX_DIGITS, s2, HEX, MAX_DIGITS, MAX_DIGITS);
+    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);
     offset1 = strlen(text1) - 1;
     offset2 = strlen(text2) - 1;
     offset_out = offset1 > offset2 ? offset1 : offset2;
@@ -46,7 +46,7 @@
         text_out[offset_out] = digits[bitwise_operator(v1, v2)];
     }
     
-    MPstr_to_num(text_out, 16, t);
+    mp_set_from_string(text_out, 16, t);
 }
 
 
@@ -101,10 +101,10 @@
     size_t len, offset;
     
     /* Convert to a hexadecimal string and use last 8 characters */
-    mp_cast_to_fixed(text, MAX_DIGITS, s1, HEX, MAX_DIGITS, MAX_DIGITS);
+    mp_cast_to_string(text, MAX_DIGITS, s1, HEX, MAX_DIGITS, MAX_DIGITS);
     len = strlen(text);
     offset = len > 8 ? len - 8: 0;
-    MPstr_to_num(text + offset, 16, t1);
+    mp_set_from_string(text + offset, 16, t1);
 }
 
 
@@ -115,10 +115,10 @@
     size_t len, offset;
     
     /* Convert to a hexadecimal string and use last 4 characters */
-    mp_cast_to_fixed(text, MAX_DIGITS, s1, HEX, MAX_DIGITS, MAX_DIGITS);
+    mp_cast_to_string(text, MAX_DIGITS, s1, HEX, MAX_DIGITS, MAX_DIGITS);
     len = strlen(text);
     offset = len > 4 ? len - 4: 0;
-    MPstr_to_num(text + offset, 16, t1);
+    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	Tue Dec  2 17:21:43 2008
@@ -30,15 +30,6 @@
 // FIXME: Needed for v->radix
 #include "calctool.h"
 
-static char digits[] = "0123456789ABCDEF";
-
-static double max_fix[MAXBASES] = {
-    1.298074214e+33,    /* Binary. */
-    2.037035976e+90,    /* Octal. */
-    1.000000000e+100,   /* Decimal */
-    2.582249878e+120    /* Hexadecimal. */
-};
-
 /*  SETS Y = X FOR MP X AND Y.
  *  SEE IF X AND Y HAVE THE SAME ADDRESS (THEY OFTEN DO)
  */
@@ -483,136 +474,15 @@
     }
 }
 
-static int
-char_val(char chr)
-{
-    if (chr >= '0' && chr <= '9') {
-        return(chr - '0');
-    } else if (chr >= 'a' && chr <= 'f') {
-        return(chr - 'a' + 10);
-    } else if (chr >= 'A' && chr <= 'F') {
-        return(chr - 'A' + 10);
-    } else {
-        return(-1);
-    }
-}
-
-/* Convert string into an MP number, in the given base
- */
-void
-MPstr_to_num(const char *str, int base, int *MPval)
-{
-    const char *optr;
-    int MP1[MP_SIZE], MP2[MP_SIZE], MPbase[MP_SIZE];
-    int i, inum;
-    int exp      = 0;
-    int exp_sign = 1;
-    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') {
-        optr++;
-    }
-
-    /* Check if this is a negative number. */
-    if (*optr == '-') {
-        negate = 1;
-        optr++;
-    }
-
-    while ((inum = char_val(*optr)) >= 0) {
-        mpmul(MPval, MPbase, MPval);
-        mp_add_integer(MPval, inum, MPval);
-        optr++;
-    }
-
-    if (*optr == '.' || *optr == *v->radix) {
-        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);
-            optr++;
-        }
-    }
-
-    while (*optr == ' ') {
-        optr++;
-    }
- 
-    if (*optr != '\0') {
-        if (*optr == '-') {
-            exp_sign = -1;
-        }
- 
-        while ((inum = char_val(*++optr)) >= 0) {
-            exp = exp * basevals[(int) base] + inum;
-        }
-    }
-    exp *= exp_sign;
-
-    if (negate == 1) {
-        mp_invert_sign(MPval, MPval);
-    }
-}
-
-static void 
-calc_xtimestenpowx(int s1[MP_SIZE], int s2[MP_SIZE], int t1[MP_SIZE])
-{
-    int MP1[MP_SIZE], MP2[MP_SIZE];
-
-    mp_set_from_integer(10, MP2);
-    mppwr2(MP2, s2, MP1);
-    mpmul(s1, MP1, t1);
-}
-
-void
-mp_set_from_string(const char *number, int base, int t[MP_SIZE])
-{
-    int i;
-    char *a = NULL;
-    char *b = NULL;
-
-    int MP_a[MP_SIZE];
-    int MP_b[MP_SIZE];
-
-    assert(number);
-    a = strdup(number);
-    assert(a);
-
-    for (i = 0; !((a[i] == 'e') || (a[i] == 'E')); i++) {
-        assert(a[i]);
-    }
-
-    a[i] = 0;
-    b = &a[i+2];
-
-    MPstr_to_num(a, base, MP_a);
-    MPstr_to_num(b, base, MP_b);
-    if (a[i+1] == '-') {
-        int MP_c[MP_SIZE];
-        mp_invert_sign(MP_b, MP_c);
-        calc_xtimestenpowx(MP_a, MP_c, t);
-    } else {
-        calc_xtimestenpowx(MP_a, MP_b, t);
-    }
-
-    free(a);
-}
-
 
 /* Convert MP number to fixed number string in the given base to the
  * maximum number of digits specified.
  */
+// FIXME: Rewrite
 void
-mp_cast_to_fixed(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, int cmax)
 {
+    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. */
@@ -629,7 +499,7 @@
     mp_set_from_integer(basevals[base], MP1base);
 
     mppwr(MP1base, accuracy, MP1);
-    MPstr_to_num("0.5", 10, MP2);
+    mp_set_from_string("0.5", 10, MP2);
     mpdiv(MP2, MP1, MP1);
     mp_add(MPval, MP1, MPval);
 
@@ -678,127 +548,97 @@
 }
 
 
-/* Convert engineering or scientific number in the given base. */
-void
-make_eng_sci(char *target, int target_len, const int *MPnumber, int base)
+static int
+char_val(char chr)
 {
-    char fixed[MAX_DIGITS], *optr;
-    int MP1[MP_SIZE], MPatmp[MP_SIZE], MPval[MP_SIZE];
-    int MP1base[MP_SIZE], MP3base[MP_SIZE], MP10base[MP_SIZE];
-    int i, dval, len;
-    int MPmant[MP_SIZE];        /* Mantissa. */
-    int ddig;                   /* Number of digits in exponent. */
-    int eng = 0;                /* Set if this is an engineering number. */
-    int exp = 0;                /* Exponent */
-    
-    if (v->dtype == ENG) {
-        eng = 1;
-    }
-    optr = target;
-    mp_abs(MPnumber, MPval);
-    mp_set_from_integer(0, MP1);
-    if (mp_is_less_than(MPnumber, MP1)) {
-        *optr++ = '-';
+    if (chr >= '0' && chr <= '9') {
+        return(chr - '0');
+    } else if (chr >= 'a' && chr <= 'f') {
+        return(chr - 'a' + 10);
+    } else if (chr >= 'A' && chr <= 'F') {
+        return(chr - 'A' + 10);
+    } else {
+        return(-1);
     }
-    mp_set_from_mp(MPval, MPmant);
+}
 
-    mp_set_from_integer(basevals[base], MP1base);
-    mppwr(MP1base, 3, MP3base);
 
-    mppwr(MP1base, 10, MP10base);
+/* Convert string into an MP number, in the given base
+ */
+void
+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 negate = 0;
+
+    mp_set_from_integer(0, MPval);
+    mp_set_from_integer(base, MPbase);
 
-    mp_set_from_integer(1, MP1);
-    mpdiv(MP1, MP10base, MPatmp);
+    optr = str;
 
-    mp_set_from_integer(0, MP1);
-    if (!mp_is_equal(MPmant, MP1)) {
-        while (!eng && mp_is_greater_equal(MPmant, MP10base)) {
-            exp += 10;
-            mpmul(MPmant, MPatmp, MPmant);
-        }
- 
-        while ((!eng &&  mp_is_greater_equal(MPmant, MP1base)) ||
-                (eng && (mp_is_greater_equal(MPmant, MP3base) || exp % 3 != 0))) {
-            exp += 1;
-            mpdiv(MPmant, MP1base, MPmant);
-        }
- 
-        while (!eng && mp_is_less_than(MPmant, MPatmp)) {
-            exp -= 10;
-            mpmul(MPmant, MP10base, MPmant);
-        }
- 
-        mp_set_from_integer(1, MP1);
-        while (mp_is_less_than(MPmant, MP1) || (eng && exp % 3 != 0)) {
-            exp -= 1;
-            mpmul(MPmant, MP1base, MPmant);
-        }
-    }
- 
-    mp_cast_to_fixed(fixed, MAX_DIGITS, MPmant, base, v->accuracy, MAX_DIGITS-6);
-    len = strlen(fixed);
-    for (i = 0; i < len; i++) {
-        *optr++ = fixed[i];
+    /* Remove any initial spaces or tabs. */
+    while (*optr == ' ' || *optr == '\t') {
+        optr++;
     }
- 
-    *optr++ = 'e';
- 
-    if (exp < 0) {
-        exp = -exp;
-        *optr++ = '-';
-    } else {
-        *optr++ = '+';
+
+    /* Check if this is a negative number. */
+    if (*optr == '-') {
+        negate = 1;
+        optr++;
     }
- 
-    MPstr_to_num("0.5", 10, MP1);
-    mp_add_integer(MP1, exp, MPval);
-    mp_set_from_integer(1, MP1);
-    for (ddig = 0; mp_is_greater_equal(MPval, MP1); ddig++) {
-        mpdiv(MPval, MP1base, MPval);
+
+    while ((inum = char_val(*optr)) >= 0) {
+        mpmul(MPval, MPbase, MPval);
+        mp_add_integer(MPval, inum, MPval);
+        optr++;
     }
- 
-    if (ddig == 0) {
-        *optr++ = '0';
+
+    if (*optr == '.' || *optr == *v->radix) {
+        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);
+            optr++;
+        }
     }
- 
-    while (ddig-- > 0) {
-        mpmul(MPval, MP1base, MPval);
-        dval = mp_cast_to_int(MPval);
-        *optr++ = digits[dval];
-        dval = -dval;
-        mp_add_integer(MPval, dval, MPval);
+   
+    if (*optr == 'e' || *optr == 'E') {
+        int negate = 0;
+        int MPexponent[MP_SIZE], temp1[MP_SIZE], temp2[MP_SIZE];
+        optr++;
+        if (*optr == '-') {
+	    negate = 1;
+	    optr++;
+	}
+        mp_set_from_integer(0, MPexponent);
+        while ((inum = char_val(*optr)) >= 0) {
+            mpmul(MPval, MPbase, MPval);
+            mp_add_integer(MPval, inum, MPval);
+            optr++;
+        }
+        if (negate == 1) {
+            mp_invert_sign(MPexponent, MPexponent);
+        }
+       
+        mppwr2(MPbase, MPexponent, temp1);
+        mpmul(MPval, temp1, temp2);
+        mp_set_from_mp(temp2, MPval);
     }
-    *optr++    = '\0';
-}
-
 
-/* Convert MP number to character string in the given base. */
-void
-mp_cast_to_number(char *target, int target_len, const int *MPnumber, int base, int ignoreError)
-{
-    double val;
-    
-    /*  NOTE: mp_cast_to_number can currently set v->error when converting to a double.
-     *        This is to provide the same look&feel as V3 even though gcalctool
-     *        now does internal arithmetic to "infinite" precision.
-     *
-     *  XXX:  Needs to be improved. Shouldn't need to convert to a double in
-     *        order to do these tests.
-     */
-
-    double number = mp_cast_to_double(MPnumber);
-
-    val = fabs(number);
-    if (v->error && !ignoreError) {
-        STRNCPY(target, _("Error"), target_len - 1);
-        return;
+    /* Strip trailing whitespace */
+    while (*optr == ' ') {
+        optr++;
     }
-    // FIXME: Do this based on the number of digits, not actual values
-    if ((v->dtype == ENG) ||
-        (v->dtype == SCI) ||
-        (v->dtype == FIX && val != 0.0 && (val > max_fix[base]))) {
-        make_eng_sci(target, target_len, MPnumber, base);
-    } else {
-        mp_cast_to_fixed(target, target_len, MPnumber, base, v->accuracy, MAX_DIGITS);
+   
+    if (*optr != '\0') {
+       // FIXME: Error decoding
+    }
+ 
+    if (negate == 1) {
+        mp_invert_sign(MPval, MPval);
     }
 }

Modified: trunk/gcalctool/mp-trigonometric.c
==============================================================================
--- trunk/gcalctool/mp-trigonometric.c	(original)
+++ trunk/gcalctool/mp-trigonometric.c	Tue Dec  2 17:21:43 2008
@@ -366,7 +366,7 @@
         mp_subtract(MP1, x, MP3);
         mpdiv(MP2, MP3, MP3);
         mpln(MP3, MP3);
-        MPstr_to_num("0.5", 10, MP1);
+        mp_set_from_string("0.5", 10, MP1);
         mpmul(MP1, MP3, z);
     }
 }

Modified: trunk/gcalctool/mp.c
==============================================================================
--- trunk/gcalctool/mp.c	(original)
+++ trunk/gcalctool/mp.c	Tue Dec  2 17:21:43 2008
@@ -488,7 +488,7 @@
 
     // FIXME: Won't this have completely different behaviour depending on base?
     mpcmf(x, tmp);
-    mp_cast_to_fixed(disp, MAXLINE, tmp, v->base, MAX_DIGITS, MAX_DIGITS);
+    mp_cast_to_string(disp, MAXLINE, tmp, v->base, MAX_DIGITS, MAX_DIGITS);
     if (disp[0] == '1') {
         y[ll]++;
     }
@@ -2398,7 +2398,7 @@
     mpcmim(MPval, MP1);
     mp_set_from_integer(0, MP2);
     if (mp_is_equal(MPval, MP1)
-        && mp_is_greater_equal(MPval, MP2)) {   /* Only positive integers. */
+	&& mp_is_greater_equal(MPval, MP2)) {   /* Only positive integers. */
         if (mp_is_equal(MP1, MP2)) {    /* Special case for 0! */
             mp_set_from_integer(1, MPres);
             return;
@@ -2426,8 +2426,8 @@
 
 int
 mp_modulus_divide(int op1[MP_SIZE], 
-                  int op2[MP_SIZE], 
-                  int result[MP_SIZE])
+		  int op2[MP_SIZE], 
+		  int result[MP_SIZE])
 {
     int MP1[MP_SIZE], MP2[MP_SIZE];
 
@@ -2442,8 +2442,8 @@
 
     mp_set_from_integer(0, MP1);
     if ((mp_is_less_than(op2, MP1)
-         && mp_is_greater_than(result, MP1)) ||
-        mp_is_less_than(result, MP1)) { 
+	 && mp_is_greater_than(result, MP1)) ||
+	mp_is_less_than(result, MP1)) { 
         mp_add(result, op2, result);
     }
 
@@ -2483,7 +2483,7 @@
 {
     int MP1[MP_SIZE];
 
-    MPstr_to_num("0.01", 10, MP1);
+    mp_set_from_string("0.01", 10, MP1);
     mpmul(s1, MP1, t1);
 }
 

Modified: trunk/gcalctool/mp.h
==============================================================================
--- trunk/gcalctool/mp.h	(original)
+++ trunk/gcalctool/mp.h	Tue Dec  2 17:21:43 2008
@@ -101,14 +101,11 @@
 void   mp_set_from_integer(int, int *);
 void   mp_set_from_fraction(int, int, int *);
 void   mp_set_from_random(int t[MP_SIZE]);
+void   mp_set_from_string(const char *number, int base, int t[MP_SIZE]);
 float  mp_cast_to_float(const int *);
 double mp_cast_to_double(const int *);
 int    mp_cast_to_int(const int *);
-// FIXME: These should be merged together
-void   MPstr_to_num(const char *, int, int *);
-void   mp_set_from_string(const char *number, int base, int t[MP_SIZE]); 
-void   mp_cast_to_fixed(char *, int, const int *, int, int, int);
-void   mp_cast_to_number(char *, int, const int *, int, int);
+void   mp_cast_to_string(char *, int, const int *, 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	Tue Dec  2 17:21:43 2008
@@ -80,13 +80,13 @@
         }
 
         if (nline && vline) {
-            MPstr_to_num(vline, 10, value);
+            mp_set_from_string(vline, 10, value);
             constant_set(i, nline, value);
             g_free(nline);
             g_free(vline);
         }
         else {
-            MPstr_to_num(default_constants[i][1], 10, value);
+            mp_set_from_string(default_constants[i][1], 10, value);
             constant_set(i, default_constants[i][0], value);
         }
     }
@@ -134,7 +134,7 @@
 
 void constant_set(int index, const char *name, int value[MP_SIZE])
 {
-    char key[MAXLINE], temp[MAX_LOCALIZED];
+    char key[MAXLINE], text[MAX_LOCALIZED];
 
     STRNCPY(constant_names[index], name, MAXLINE - 1);
     mp_set_from_mp(value, constant_values[index]);
@@ -144,9 +144,9 @@
 
     /* NOTE: Constants are written out with no thousands separator and with a
        radix character of ".". */
-    mp_cast_to_number(temp, MAX_LOCALIZED, value, DEC, TRUE);   
+    mp_cast_to_string(text, MAX_LOCALIZED, value, DEC, MAX_DIGITS, MAX_DIGITS);
     SNPRINTF(key, MAXLINE, "constant%1dvalue", index);
-    set_resource(key, temp);
+    set_resource(key, text);
 }
 
 

Modified: trunk/gcalctool/unittest.c
==============================================================================
--- trunk/gcalctool/unittest.c	(original)
+++ trunk/gcalctool/unittest.c	Tue Dec  2 17:21:43 2008
@@ -43,7 +43,7 @@
         return;
     }
     
-    mp_cast_to_fixed(result_str, MAXLINE, result, DEC, 100, 100);
+    mp_cast_to_string(result_str, MAXLINE, result, DEC, 100, 100);
     if(strcmp(result_str, expected) != 0)
         printf("FAIL: '%s' -> '%s', expected '%s'\n", expression, result_str, expected);
     else



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