gcalctool r2328 - in trunk: . gcalctool
- From: rancell svn gnome org
- To: svn-commits-list gnome org
- Subject: gcalctool r2328 - in trunk: . gcalctool
- Date: Mon, 8 Dec 2008 14:26:47 +0000 (UTC)
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]