gcalctool r2326 - trunk/gcalctool
- From: rancell svn gnome org
- To: svn-commits-list gnome org
- Subject: gcalctool r2326 - trunk/gcalctool
- Date: Tue, 2 Dec 2008 17:21:44 +0000 (UTC)
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]