[gcalctool] Split MPNumber structure into sign,exponent,fraction
- From: Robert Ancell <rancell src gnome org>
- To: svn-commits-list gnome org
- Subject: [gcalctool] Split MPNumber structure into sign,exponent,fraction
- Date: Tue, 5 May 2009 20:59:31 -0400 (EDT)
commit 73293c9b89c41ff19dcd58a47831f262a367a0b0
Author: Robert Ancell <robert ancell gmail com>
Date: Wed May 6 10:59:05 2009 +1000
Split MPNumber structure into sign,exponent,fraction
---
gcalctool/calctool.c | 2 +-
gcalctool/mp-convert.c | 52 +++---
gcalctool/mp-trigonometric.c | 92 ++++----
gcalctool/mp.c | 509 +++++++++++++++++++++---------------------
gcalctool/mp.h | 10 +-
gcalctool/unittest.c | 2 +
6 files changed, 334 insertions(+), 333 deletions(-)
diff --git a/gcalctool/calctool.c b/gcalctool/calctool.c
index c47706e..f9f365f 100644
--- a/gcalctool/calctool.c
+++ b/gcalctool/calctool.c
@@ -268,7 +268,7 @@ main(int argc, char **argv)
register_init();
display_init(&v->display);
ui_init(&argc, &argv);
-
+
get_options(argc, argv);
ui_load();
diff --git a/gcalctool/mp-convert.c b/gcalctool/mp-convert.c
index 51c0545..dcf1c18 100644
--- a/gcalctool/mp-convert.c
+++ b/gcalctool/mp-convert.c
@@ -42,8 +42,8 @@ mp_set_from_mp(const MPNumber *x, MPNumber *y)
return;
/* NO NEED TO COPY X[1],X[2],... IF X[0] == 0 */
- if (x->data[0] == 0) {
- y->data[0] = 0;
+ if (x->sign == 0) {
+ y->sign = 0;
return;
}
@@ -73,7 +73,7 @@ mp_set_from_float(float rx, MPNumber *z)
rj = rx;
} else {
/* IF RX = 0E0 RETURN 0 */
- z->data[0] = 0;
+ z->sign = 0;
return;
}
@@ -163,7 +163,7 @@ mp_set_from_double(double dx, MPNumber *z)
rs = 1;
dj = dx;
} else {
- z->data[0] = 0;
+ z->sign = 0;
return;
}
@@ -228,25 +228,25 @@ mp_set_from_integer(int ix, MPNumber *z)
mpchk(1, 4);
if (ix == 0) {
- z->data[0] = 0;
+ z->sign = 0;
return;
}
if (ix < 0) {
ix = -ix;
- z->data[0] = -1;
+ z->sign = -1;
}
else
- z->data[0] = 1;
+ z->sign = 1;
/* SET EXPONENT TO T */
- z->data[1] = MP.t;
+ z->exponent = MP.t;
/* CLEAR FRACTION */
- memset(&z->data[2], 0, (MP.t-1)*sizeof(int));
+ memset(z->fraction, 0, (MP.t-1)*sizeof(int));
/* INSERT IX */
- z->data[MP.t + 1] = ix;
+ z->fraction[MP.t - 1] = ix;
/* NORMALIZE BY CALLING MPMUL2 */
mpmul2(z, 1, z, 1);
@@ -260,7 +260,7 @@ mp_set_from_fraction(int i, int j, MPNumber *q)
if (j == 0) {
mperr("*** J == 0 IN CALL TO MP_SET_FROM_FRACTION ***\n");
- q->data[0] = 0;
+ q->sign = 0;
return;
}
@@ -288,17 +288,17 @@ mp_cast_to_int(const MPNumber *x)
{
int i, j, k, j1, x2, kx, xs, izs, ret_val = 0;
- xs = x->data[0];
+ xs = x->sign;
/* RETURN 0 IF X = 0 OR IF NUMBER FRACTION */
- if (xs == 0 || x->data[1] <= 0)
+ if (xs == 0 || x->exponent <= 0)
return 0;
- x2 = x->data[1];
+ x2 = x->exponent;
for (i = 1; i <= x2; ++i) {
izs = ret_val;
ret_val = MP.b * ret_val;
if (i <= MP.t)
- ret_val += x->data[i + 1];
+ ret_val += x->fraction[i - 1];
/* CHECK FOR SIGNS OF INTEGER OVERFLOW */
if (ret_val <= 0 || ret_val <= izs)
@@ -314,7 +314,7 @@ mp_cast_to_int(const MPNumber *x)
k = x2 + 1 - i;
kx = 0;
if (k <= MP.t)
- kx = x->data[k + 1];
+ kx = x->fraction[k - 1];
if (kx != j - MP.b * j1)
return 0;
j = j1;
@@ -367,12 +367,12 @@ mp_cast_to_float(const MPNumber *x)
float rb, rz2;
mpchk(1, 4);
- if (x->data[0] == 0)
+ if (x->sign == 0)
return 0.0;
rb = (float) MP.b;
for (i = 1; i <= MP.t; ++i) {
- rz = rb * rz + (float) x->data[i + 1];
+ rz = rb * rz + (float) x->fraction[i - 1];
tm = i;
/* CHECK IF FULL SINGLE-PRECISION ACCURACY ATTAINED */
@@ -382,12 +382,12 @@ mp_cast_to_float(const MPNumber *x)
}
/* NOW ALLOW FOR EXPONENT */
- rz *= mppow_ri(rb, x->data[1] - tm);
+ rz *= mppow_ri(rb, x->exponent - tm);
/* CHECK REASONABLENESS OF RESULT */
/* LHS SHOULD BE <= 0.5, BUT ALLOW FOR SOME ERROR IN ALOG */
if (rz <= (float)0. ||
- fabs((float) x->data[1] - (log(rz) / log((float) MP.b) + (float).5)) > (float).6) {
+ fabs((float) x->exponent - (log(rz) / log((float) MP.b) + (float).5)) > (float).6) {
/* FOLLOWING MESSAGE INDICATES THAT X IS TOO LARGE OR SMALL -
* TRY USING MPCMRE INSTEAD.
*/
@@ -395,7 +395,7 @@ mp_cast_to_float(const MPNumber *x)
return 0.0;
}
- if (x->data[0] < 0)
+ if (x->sign < 0)
rz = -(double)(rz);
return rz;
}
@@ -435,12 +435,12 @@ mp_cast_to_double(const MPNumber *x)
double d__1, db, dz2, ret_val = 0.0;
mpchk(1, 4);
- if (x->data[0] == 0)
+ if (x->sign == 0)
return 0.0;
db = (double) MP.b;
for (i = 1; i <= MP.t; ++i) {
- ret_val = db * ret_val + (double) x->data[i + 1];
+ ret_val = db * ret_val + (double) x->fraction[i - 1];
tm = i;
/* CHECK IF FULL DOUBLE-PRECISION ACCURACY ATTAINED */
@@ -454,12 +454,12 @@ mp_cast_to_double(const MPNumber *x)
}
/* NOW ALLOW FOR EXPONENT */
- ret_val *= mppow_di(db, x->data[1] - tm);
+ ret_val *= mppow_di(db, x->exponent - tm);
/* CHECK REASONABLENESS OF RESULT. */
/* LHS SHOULD BE .LE. 0.5 BUT ALLOW FOR SOME ERROR IN DLOG */
if (ret_val <= 0. ||
- ((d__1 = (double) ((float) x->data[1]) - (log(ret_val) / log((double)
+ ((d__1 = (double) ((float) x->exponent) - (log(ret_val) / log((double)
((float) MP.b)) + .5), abs(d__1)) > .6)) {
/* FOLLOWING MESSAGE INDICATES THAT X IS TOO LARGE OR SMALL -
* TRY USING MPCMDE INSTEAD.
@@ -469,7 +469,7 @@ mp_cast_to_double(const MPNumber *x)
}
else
{
- if (x->data[0] < 0)
+ if (x->sign < 0)
ret_val = -ret_val;
return ret_val;
}
diff --git a/gcalctool/mp-trigonometric.c b/gcalctool/mp-trigonometric.c
index fa6abdf..0cacaa8 100644
--- a/gcalctool/mp-trigonometric.c
+++ b/gcalctool/mp-trigonometric.c
@@ -67,8 +67,8 @@ mpsin1(const MPNumber *x, MPNumber *z, int do_sin)
mpchk(3, 8);
/* SIN(0) = 0, COS(0) = 1 */
- if (x->data[0] == 0) {
- z->data[0] = 0;
+ if (x->sign == 0) {
+ z->sign = 0;
if (do_sin == 0)
mp_set_from_integer(1, z);
return;
@@ -85,7 +85,7 @@ mpsin1(const MPNumber *x, MPNumber *z, int do_sin)
if (do_sin != 0)
mp_set_from_mp(x, &t1);
- z->data[0] = 0;
+ z->sign = 0;
i = 1;
ts = MP.t;
if (do_sin != 0) {
@@ -95,7 +95,7 @@ mpsin1(const MPNumber *x, MPNumber *z, int do_sin)
/* POWER SERIES LOOP. REDUCE T IF POSSIBLE */
do {
- MP.t = t1.data[1] + ts + 2;
+ MP.t = t1.exponent + ts + 2;
if (MP.t <= 2)
break;
@@ -117,7 +117,7 @@ mpsin1(const MPNumber *x, MPNumber *z, int do_sin)
i += 2;
MP.t = ts;
mp_add(&t1, z, z);
- } while(t1.data[0] != 0);
+ } while(t1.sign != 0);
MP.t = ts;
if (do_sin == 0)
@@ -151,11 +151,11 @@ mp_acos(const MPNumber *x, MPNumber *z)
if (mp_is_greater_than(x, &MP1) || mp_is_less_than(x, &MPn1)) {
mperr("Error");
- z->data[0] = 0;
- } else if (x->data[0] == 0) {
+ z->sign = 0;
+ } else if (x->sign == 0) {
mpdivi(&MPpi, 2, z);
} else if (mp_is_equal(x, &MP1)) {
- z->data[0] = 0;
+ z->sign = 0;
} else if (mp_is_equal(x, &MPn1)) {
mp_set_from_mp(&MPpi, z);
} else {
@@ -164,7 +164,7 @@ mp_acos(const MPNumber *x, MPNumber *z)
mp_sqrt(&MP2, &MP2);
mpdiv(&MP2, x, &MP2);
mp_atan(&MP2, &MPy);
- if (x->data[0] > 0) {
+ if (x->sign > 0) {
mp_set_from_mp(&MPy, z);
} else {
mp_add(&MPy, &MPpi, z);
@@ -211,12 +211,12 @@ mp_asin(const MPNumber *x, MPNumber *z)
MPNumber t1, t2;
mpchk(5, 12);
- if (x->data[0] == 0) {
- z->data[0] = 0;
+ if (x->sign == 0) {
+ z->sign = 0;
return;
}
- if (x->data[1] <= 0) {
+ if (x->exponent <= 0) {
/* HERE ABS(X) < 1, SO USE ARCTAN(X/SQRT(1 - X^2)) */
mp_set_from_integer(1, &t1);
mp_set_from_mp(&t1, &t2);
@@ -230,14 +230,14 @@ mp_asin(const MPNumber *x, MPNumber *z)
}
/* HERE ABS(X) >= 1. SEE IF X == +-1 */
- mp_set_from_integer(x->data[0], &t2);
+ mp_set_from_integer(x->sign, &t2);
if (!mp_is_equal(x, &t2)) {
mperr("*** ABS(X) > 1 IN CALL TO MP_ASIN ***");
}
/* X == +-1 SO RETURN +-PI/2 */
mp_get_pi(z);
- mpdivi(z, t2.data[0] << 1, z);
+ mpdivi(z, t2.sign << 1, z);
}
@@ -276,21 +276,21 @@ mp_atan(const MPNumber *x, MPNumber *z)
MPNumber t1, t2;
mpchk(5, 12);
- if (x->data[0] == 0) {
- z->data[0] = 0;
+ if (x->sign == 0) {
+ z->sign = 0;
return;
}
mp_set_from_mp(x, &t2);
- if (abs(x->data[1]) <= 2)
+ if (abs(x->exponent) <= 2)
rx = mp_cast_to_float(x);
q = 1;
/* REDUCE ARGUMENT IF NECESSARY BEFORE USING SERIES */
- while (t2.data[1] >= 0)
+ while (t2.exponent >= 0)
{
- if (t2.data[1] == 0 && (t2.data[2] + 1) << 1 <= MP.b)
+ if (t2.exponent == 0 && (t2.fraction[0] + 1) << 1 <= MP.b)
break;
q <<= 1;
@@ -308,14 +308,14 @@ mp_atan(const MPNumber *x, MPNumber *z)
ts = MP.t;
/* SERIES LOOP. REDUCE T IF POSSIBLE. */
- while ((MP.t = ts + 2 + t2.data[1]) > 1) {
+ while ((MP.t = ts + 2 + t2.exponent) > 1) {
MP.t = min(MP.t,ts);
mpmul(&t2, &t1, &t2);
mpmulq(&t2, -i, i + 2, &t2);
i += 2;
MP.t = ts;
mp_add(z, &t2, z);
- if (t2.data[0] == 0) break;
+ if (t2.sign == 0) break;
}
/* RESTORE T, CORRECT FOR ARGUMENT REDUCTION, AND EXIT */
@@ -325,7 +325,7 @@ mp_atan(const MPNumber *x, MPNumber *z)
/* CHECK THAT RELATIVE ERROR LESS THAN 0.01 UNLESS EXPONENT
* OF X IS LARGE (WHEN ATAN MIGHT NOT WORK)
*/
- if (abs(x->data[1]) > 2)
+ if (abs(x->exponent) > 2)
return;
ry = mp_cast_to_float(z);
@@ -354,7 +354,7 @@ mp_atanh(const MPNumber *x, MPNumber *z)
if (mp_is_greater_equal(x, &MP1) || mp_is_less_equal(x, &MPn1)) {
mperr("Error");
- z->data[0] = 0;
+ z->sign = 0;
} else {
mp_add(&MP1, x, &MP2);
mp_subtract(&MP1, x, &MP3);
@@ -375,7 +375,7 @@ mp_cos(const MPNumber *x, MPNumber *z)
MPNumber t;
/* COS(0) = 1 */
- if (x->data[0] == 0) {
+ if (x->sign == 0) {
mp_set_from_integer(1, z);
return;
}
@@ -409,7 +409,7 @@ mp_cosh(const MPNumber *x, MPNumber *z)
MPNumber t;
/* COSH(0) == 1 */
- if (x->data[0] == 0) {
+ if (x->sign == 0) {
mp_set_from_integer(1, z);
return;
}
@@ -449,13 +449,13 @@ mp_sin(const MPNumber *x, MPNumber *z)
mpchk(5, 12);
- if (x->data[0] == 0) {
- z->data[0] = 0;
+ if (x->sign == 0) {
+ z->sign = 0;
return;
}
- xs = x->data[0];
- ie = abs(x->data[1]);
+ xs = x->sign;
+ ie = abs(x->exponent);
if (ie <= 2)
rx = mp_cast_to_float(x);
@@ -481,31 +481,31 @@ mp_sin(const MPNumber *x, MPNumber *z)
/* SUBTRACT 1/2, SAVE SIGN AND TAKE ABS */
mp_add_fraction(&t1, -1, 2, &t1);
- xs = -xs * t1.data[0];
+ xs = -xs * t1.sign;
if (xs == 0) {
- z->data[0] = 0;
+ z->sign = 0;
return;
}
- t1.data[0] = 1;
+ t1.sign = 1;
mpmuli(&t1, 4, &t1);
/* IF NOT LESS THAN 1, SUBTRACT FROM 2 */
- if (t1.data[1] > 0)
+ if (t1.exponent > 0)
mp_add_integer(&t1, -2, &t1);
- if (t1.data[0] == 0) {
- z->data[0] = 0;
+ if (t1.sign == 0) {
+ z->sign = 0;
return;
}
- t1.data[0] = 1;
+ t1.sign = 1;
mpmuli(&t1, 2, &t1);
/* NOW REDUCED TO FIRST QUADRANT, IF LESS THAN PI/4 USE
* POWER SERIES, ELSE COMPUTE COS OF COMPLEMENT
*/
- if (t1.data[1] > 0) {
+ if (t1.exponent > 0) {
mp_add_integer(&t1, -2, &t1);
mpmul(&t1, z, &t1);
mpsin1(&t1, z, 0);
@@ -515,7 +515,7 @@ mp_sin(const MPNumber *x, MPNumber *z)
}
}
- z->data[0] = xs;
+ z->sign = xs;
if (ie > 2)
return;
@@ -546,9 +546,9 @@ mp_sinh(const MPNumber *x, MPNumber *z)
int xs;
MPNumber t1, t2;
- xs = x->data[0];
+ xs = x->sign;
if (xs == 0) {
- z->data[0] = 0;
+ z->sign = 0;
return;
}
@@ -559,7 +559,7 @@ mp_sinh(const MPNumber *x, MPNumber *z)
mp_abs(x, &t2);
/* HERE ABS(X) < 1 SO USE MPEXP1 TO AVOID CANCELLATION */
- if (t2.data[1] <= 0) {
+ if (t2.exponent <= 0) {
mpexp1(&t2, &t1);
mp_add_integer(&t1, 2, &t2);
mpmul(&t2, &t1, z);
@@ -614,8 +614,8 @@ mp_tanh(const MPNumber *x, MPNumber *z)
MPNumber t;
/* TANH(0) = 0 */
- if (x->data[0] == 0) {
- z->data[0] = 0;
+ if (x->sign == 0) {
+ z->sign = 0;
return;
}
@@ -623,7 +623,7 @@ mp_tanh(const MPNumber *x, MPNumber *z)
mpchk(5, 12);
/* SAVE SIGN AND WORK WITH ABS(X) */
- xs = x->data[0];
+ xs = x->sign;
mp_abs(x, &t);
/* SEE IF ABS(X) SO LARGE THAT RESULT IS +-1 */
@@ -637,7 +637,7 @@ mp_tanh(const MPNumber *x, MPNumber *z)
/* HERE ABS(X) NOT SO LARGE */
mpmuli(&t, 2, &t);
- if (t.data[1] > 0) {
+ if (t.exponent > 0) {
/* HERE ABS(X) >= 1/2 SO USE MPEXP */
mpexp(&t, &t);
mp_add_integer(&t, -1, z);
@@ -651,5 +651,5 @@ mp_tanh(const MPNumber *x, MPNumber *z)
}
/* RESTORE SIGN */
- z->data[0] = xs * z->data[0];
+ z->sign = xs * z->sign;
}
diff --git a/gcalctool/mp.c b/gcalctool/mp.c
index 5a94728..cf8d6d7 100644
--- a/gcalctool/mp.c
+++ b/gcalctool/mp.c
@@ -55,7 +55,7 @@ void
mp_abs(const MPNumber *x, MPNumber *y)
{
mp_set_from_mp(x, y);
- y->data[0] = abs(y->data[0]);
+ y->sign = abs(y->sign);
}
@@ -66,12 +66,12 @@ mp_abs(const MPNumber *x, MPNumber *y)
void
mp_add(const MPNumber *x, const MPNumber *y, MPNumber *z)
{
- mpadd2(x, y, z, y->data[0], 0);
+ mpadd2(x, y, z, y->sign, 0);
}
/* CALLED BY MP_ADD, MP_SUBTRACT ETC.
* X, Y AND Z ARE MP NUMBERS, Y_SIGN AND TRUNC ARE INTEGERS.
- * SETS Z = X + Y_SIGN*ABS(Y), WHERE Y_SIGN = +- y->data[0].
+ * SETS Z = X + Y_SIGN*ABS(Y), WHERE Y_SIGN = +- y->sign.
* IF TRUNC == 0 R*-ROUNDING IS USED, OTHERWISE TRUNCATION.
* R*-ROUNDING IS DEFINED IN KUKI AND CODI, COMM. ACM
* 16(1973), 223. (SEE ALSO BRENT, IEEE TC-22(1973), 601.)
@@ -84,29 +84,29 @@ mpadd2(const MPNumber *x, const MPNumber *y, MPNumber *z, int y_sign, int trunc)
int exp_diff, exp_result, med;
/* X = 0 OR NEGLIGIBLE, SO RESULT = +-Y */
- if (x->data[0] == 0) {
+ if (x->sign == 0) {
mp_set_from_mp(y, z);
- z->data[0] = y_sign;
+ z->sign = y_sign;
return;
}
/* Y = 0 OR NEGLIGIBLE, SO RESULT = X */
- if (y_sign == 0 || y->data[0] == 0) {
+ if (y_sign == 0 || y->sign == 0) {
mp_set_from_mp(x, z);
return;
}
/* COMPARE SIGNS */
- sign_prod = y_sign * x->data[0];
+ sign_prod = y_sign * x->sign;
if (abs(sign_prod) > 1) {
mpchk(1, 4);
mperr("*** SIGN NOT 0, +1 OR -1 IN MPADD2 CALL, POSSIBLE OVERWRITING PROBLEM ***");
- z->data[0] = 0;
+ z->sign = 0;
return;
}
/* COMPARE EXPONENTS */
- exp_diff = x->data[1] - y->data[1];
+ exp_diff = x->exponent - y->exponent;
med = abs(exp_diff);
if (exp_diff < 0) {
/* HERE EXPONENT(Y) > EXPONENT(X) */
@@ -114,7 +114,7 @@ mpadd2(const MPNumber *x, const MPNumber *y, MPNumber *z, int y_sign, int trunc)
/* 'y' so much larger than 'x' that 'x+-y = y'. Warning:
still true with rounding?? */
mp_set_from_mp(y, z);
- z->data[0] = y_sign;
+ z->sign = y_sign;
return;
}
goto L10;
@@ -133,8 +133,8 @@ mpadd2(const MPNumber *x, const MPNumber *y, MPNumber *z, int y_sign, int trunc)
/* signs are not equal. find out which mantissa is
larger. */
int j;
- for (j = 2; j <= MP.t + 1; j++) {
- int i = x->data[j] - y->data[j];
+ for (j = 0; j <= MP.t - 1; j++) {
+ int i = x->fraction[j] - y->fraction[j];
if (i < 0)
goto L10;
else if (i > 0)
@@ -142,21 +142,21 @@ mpadd2(const MPNumber *x, const MPNumber *y, MPNumber *z, int y_sign, int trunc)
}
/* both mantissas equal, so result is zero. */
- z->data[0] = 0;
+ z->sign = 0;
return;
}
}
L10:
- exp_result = y->data[1] + mpadd3(x, y, sign_prod, med);
+ exp_result = y->exponent + mpadd3(x, y, sign_prod, med);
/* NORMALIZE, ROUND OR TRUNCATE, AND RETURN */
mp_get_normalized_register(y_sign, &exp_result, z, trunc);
return;
L20:
- exp_result = x->data[1] + mpadd3(y, x, sign_prod, med);
+ exp_result = x->exponent + mpadd3(y, x, sign_prod, med);
/* NORMALIZE, ROUND OR TRUNCATE, AND RETURN */
- mp_get_normalized_register(x->data[0], &exp_result, z, trunc);
+ mp_get_normalized_register(x->sign, &exp_result, z, trunc);
return;
}
@@ -166,115 +166,107 @@ L20:
static int
mpadd3(const MPNumber *x, const MPNumber *y, int s, int med)
{
- int c, i, j, i2, i2p, ted;
+ int i, c;
- ted = MP.t + med;
- i2 = MP.t + 4;
- i = i2;
- c = 0;
-
/* CLEAR GUARD DIGITS TO RIGHT OF X DIGITS */
- while(i > ted) {
- MP.r[i - 1] = 0;
- --i;
+ for(i = 3; i >= med; i--) {
+ MP.r[MP.t + i] = 0;
}
if (s >= 0) {
/* HERE DO ADDITION, EXPONENT(Y) >= EXPONENT(X) */
- while (i > MP.t) {
- j = i - med;
- MP.r[i - 1] = x->data[j + 1];
- i--;
+ for (i = MP.t + 3; i >= MP.t; i--) {
+ MP.r[i] = x->fraction[i - med];
}
- while (i > med) {
- j = i - med;
- c = y->data[i + 1] + x->data[j + 1] + c;
+ c = 0;
+ for (; i >= med; i--) {
+ c = y->fraction[i] + x->fraction[i - med] + c;
if (c < MP.b) {
/* NO CARRY GENERATED HERE */
- MP.r[i - 1] = c;
+ MP.r[i] = c;
c = 0;
} else {
/* CARRY GENERATED HERE */
- MP.r[i - 1] = c - MP.b;
+ MP.r[i] = c - MP.b;
c = 1;
}
- i--;
}
- while (i > 0)
+ for (; i >= 0; i--)
{
- c = y->data[i + 1] + c;
+ c = y->fraction[i] + c;
if (c < MP.b) {
- MP.r[i - 1] = c;
+ MP.r[i] = c;
i--;
/* NO CARRY POSSIBLE HERE */
- for (; i > 0; i--)
- MP.r[i - 1] = y->data[i + 1];
+ for (; i >= 0; i--)
+ MP.r[i] = y->fraction[i];
return 0;
}
- MP.r[i - 1] = 0;
+ MP.r[i] = 0;
c = 1;
- --i;
}
/* MUST SHIFT RIGHT HERE AS CARRY OFF END */
if (c != 0) {
- i2p = i2 + 1;
- for (j = 2; j <= i2; ++j) {
- i = i2p - j;
+ int j;
+
+ for (j = 2; j <= MP.t + 4; j++) {
+ i = MP.t + 5 - j;
MP.r[i] = MP.r[i - 1];
}
MP.r[0] = 1;
return 1;
}
+
return 0;
}
-
- while (i > MP.t) {
+
+ c = 0;
+ for (i = MP.t + med - 1; i >= MP.t; i--) {
/* HERE DO SUBTRACTION, ABS(Y) > ABS(X) */
- j = i - med;
- MP.r[i - 1] = c - x->data[j + 1];
+ MP.r[i] = c - x->fraction[i - med];
c = 0;
/* BORROW GENERATED HERE */
- if (MP.r[i - 1] < 0) {
+ if (MP.r[i] < 0) {
c = -1;
- MP.r[i - 1] += MP.b;
+ MP.r[i] += MP.b;
}
- --i;
}
- for(; i > med; i--) {
- j = i - med;
- c = y->data[i + 1] + c - x->data[j + 1];
+ for(; i >= med; i--) {
+ c = y->fraction[i] + c - x->fraction[i - med];
if (c >= 0) {
/* NO BORROW GENERATED HERE */
- MP.r[i - 1] = c;
+ MP.r[i] = c;
c = 0;
} else {
/* BORROW GENERATED HERE */
- MP.r[i - 1] = c + MP.b;
+ MP.r[i] = c + MP.b;
c = -1;
}
}
- for (; i > 0; i--) {
- c = y->data[i + 1] + c;
+ for (; i >= 0; i--) {
+ c = y->fraction[i] + c;
+
if (c >= 0) {
- MP.r[i - 1] = c;
+ MP.r[i] = c;
i--;
/* NO CARRY POSSIBLE HERE */
- for (; i > 0; i--)
- MP.r[i - 1] = y->data[i + 1];
+ for (; i >= 0; i--)
+ MP.r[i] = y->fraction[i];
+
return 0;
}
- MP.r[i - 1] = c + MP.b;
+ MP.r[i] = c + MP.b;
c = -1;
}
return 0;
@@ -328,7 +320,7 @@ mp_atan1N(int n, MPNumber *z)
mpchk(2, 6);
if (n <= 1) {
mperr("*** N <= 1 IN CALL TO MP_ATAN1N ***");
- z->data[0] = 0;
+ z->sign = 0;
return;
}
@@ -348,7 +340,7 @@ mp_atan1N(int n, MPNumber *z)
id = b2 * 7 * b2 / (n * n);
/* MAIN LOOP. FIRST REDUCE T IF POSSIBLE */
- while ((MP.t = ts + 2 + t.data[1] - z->data[1]) > 1) {
+ while ((MP.t = ts + 2 + t.exponent - z->exponent) > 1) {
MP.t = min(MP.t,ts);
@@ -371,7 +363,7 @@ mp_atan1N(int n, MPNumber *z)
/* ADD TO SUM */
mp_add(&t, z, z);
- if (t.data[0] == 0) break;
+ if (t.sign == 0) break;
}
MP.t = ts;
}
@@ -415,30 +407,30 @@ mpcmf(const MPNumber *x, MPNumber *y)
/* RETURN 0 IF X = 0
OR IF EXPONENT SO LARGE THAT NO FRACTIONAL PART */
- if (x->data[0] == 0 || x->data[1] >= MP.t) {
- y->data[0] = 0;
+ if (x->sign == 0 || x->exponent >= MP.t) {
+ y->sign = 0;
return;
}
/* IF EXPONENT NOT POSITIVE CAN RETURN X */
- if (x->data[1] <= 0) {
+ if (x->exponent <= 0) {
mp_set_from_mp(x, y);
return;
}
/* CLEAR ACCUMULATOR */
- offset_exp = x->data[1];
+ offset_exp = x->exponent;
memset(MP.r, 0, offset_exp*sizeof(int));
/* MOVE FRACTIONAL PART OF X TO ACCUMULATOR */
- memcpy (MP.r + offset_exp, x->data + (offset_exp + 2),
+ memcpy (MP.r + offset_exp, x->fraction + offset_exp,
(MP.t - offset_exp)*sizeof(int));
memset(MP.r + MP.t, 0, 4*sizeof(int));
/* NORMALIZE RESULT AND RETURN */
- mp_get_normalized_register(x->data[0], &offset_exp, y, 1);
+ mp_get_normalized_register(x->sign, &offset_exp, y, 1);
}
/* RETURNS Y = INTEGER PART OF X (TRUNCATED TOWARDS 0), FOR MP X AND Y.
@@ -449,30 +441,28 @@ mpcmf(const MPNumber *x, MPNumber *y)
void
mpcmim(const MPNumber *x, MPNumber *y)
{
- int i, il;
+ int i;
mpchk(1, 4);
mp_set_from_mp(x, y);
- if (y->data[0] == 0) {
+ if (y->sign == 0) {
return;
}
- il = y->data[1] + 1;
-
/* IF EXPONENT LARGE ENOUGH RETURN Y = X */
- if (il > MP.t) {
+ if (y->exponent >= MP.t) {
return;
}
/* IF EXPONENT SMALL ENOUGH RETURN ZERO */
- if (il <= 1) {
- y->data[0] = 0;
+ if (y->exponent <= 0) {
+ y->sign = 0;
return;
}
/* SET FRACTION TO ZERO */
- for (i = il; i <= MP.t; ++i) {
- y->data[i + 1] = 0;
+ for (i = y->exponent; i < MP.t; i++) {
+ y->fraction[i] = 0;
}
}
@@ -502,28 +492,36 @@ mp_compare_mp_to_float(const MPNumber *x, float ri)
int
mp_compare_mp_to_mp(const MPNumber *x, const MPNumber *y)
{
- int i, t2;
+ int i, i2;
- if (x->data[0] < y->data[0])
+ if (x->sign < y->sign)
return -1;
- if (x->data[0] > y->data[0])
+ if (x->sign > y->sign)
return 1;
/* SIGN(X) == SIGN(Y), SEE IF ZERO */
- if (x->data[0] == 0)
+ if (x->sign == 0)
return 0; /* X == Y == 0 */
/* HAVE TO COMPARE EXPONENTS AND FRACTIONS */
- t2 = MP.t + 2;
- for (i = 2; i <= t2; ++i) {
- int i2 = x->data[i-1] - y->data[i-1];
+ i2 = x->exponent - y->exponent;
+ if (i2 < 0) {
+ /* ABS(X) < ABS(Y) */
+ return -x->sign;
+ }
+ if (i2 > 0) {
+ /* ABS(X) > ABS(Y) */
+ return x->sign;
+ }
+ for (i = 0; i < MP.t; i++) {
+ i2 = x->fraction[i] - y->fraction[i];
if (i2 < 0) {
/* ABS(X) < ABS(Y) */
- return -x->data[0];
+ return -x->sign;
}
if (i2 > 0) {
/* ABS(X) > ABS(Y) */
- return x->data[0];
+ return x->sign;
}
}
@@ -545,15 +543,15 @@ mpdiv(const MPNumber *x, const MPNumber *y, MPNumber *z)
mpchk(4, 10);
/* CHECK FOR DIVISION BY ZERO */
- if (y->data[0] == 0) {
+ if (y->sign == 0) {
mperr("*** ATTEMPTED DIVISION BY ZERO IN CALL TO MPDIV ***");
- z->data[0] = 0;
+ z->sign = 0;
return;
}
/* CHECK FOR X = 0 */
- if (x->data[0] == 0) {
- z->data[0] = 0;
+ if (x->sign == 0) {
+ z->sign = 0;
return;
}
@@ -564,23 +562,23 @@ mpdiv(const MPNumber *x, const MPNumber *y, MPNumber *z)
mp_reciprocal(y, &t);
/* SET EXPONENT OF R(I2) TO ZERO TO AVOID OVERFLOW IN MPMUL */
- ie = t.data[1];
- t.data[1] = 0;
- i = t.data[2];
+ ie = t.exponent;
+ t.exponent = 0;
+ i = t.fraction[0];
/* MULTIPLY BY X */
mpmul(x, &t, z);
- iz3 = z->data[2];
+ iz3 = z->fraction[0];
mpext(i, iz3, z);
/* RESTORE M, CORRECT EXPONENT AND RETURN */
MP.m += -2;
- z->data[1] += ie;
- if (z->data[1] < -MP.m) {
+ z->exponent += ie;
+ if (z->exponent < -MP.m) {
/* UNDERFLOW HERE */
mpunfl(z);
}
- else if (z->data[1] > MP.m) {
+ else if (z->exponent > MP.m) {
/* OVERFLOW HERE */
mpovfl(z, "*** OVERFLOW OCCURRED IN MPDIV ***");
}
@@ -597,11 +595,11 @@ mpdivi(const MPNumber *x, int iy, MPNumber *z)
int c, i, k, b2, c2, i2, j1, j2, r1;
int j11, kh, re, iq, ir, rs, iqj;
- rs = x->data[0];
+ rs = x->sign;
if (iy == 0) {
mperr("*** ATTEMPTED DIVISION BY ZERO IN CALL TO MPDIVI ***");
- z->data[0] = 0;
+ z->sign = 0;
return;
}
@@ -610,7 +608,7 @@ mpdivi(const MPNumber *x, int iy, MPNumber *z)
rs = -rs;
}
- re = x->data[1];
+ re = x->exponent;
/* CHECK FOR ZERO DIVIDEND */
if (rs == 0) {
@@ -626,15 +624,15 @@ mpdivi(const MPNumber *x, int iy, MPNumber *z)
mpunfl(z);
return;
}
- z->data[0] = rs;
- z->data[1] = re - 1;
+ z->sign = rs;
+ z->exponent = re - 1;
return;
}
/* CHECK FOR DIVISION BY 1 OR -1 */
if (iy == 1) {
mp_set_from_mp(x, z);
- z->data[0] = rs;
+ z->sign = rs;
return;
}
@@ -654,7 +652,7 @@ mpdivi(const MPNumber *x, int iy, MPNumber *z)
++i;
c = MP.b * c;
if (i <= MP.t)
- c += x->data[i + 1];
+ c += x->fraction[i - 1];
r1 = c / iy;
if (r1 < 0)
goto L210;
@@ -669,7 +667,7 @@ mpdivi(const MPNumber *x, int iy, MPNumber *z)
kh = MP.t + 1 - i;
for (k = 2; k <= kh; ++k) {
++i;
- c += x->data[i + 1];
+ c += x->fraction[i - 1];
MP.r[k - 1] = c / iy;
c = MP.b * (c - iy * MP.r[k - 1]);
}
@@ -678,15 +676,16 @@ mpdivi(const MPNumber *x, int iy, MPNumber *z)
++kh;
}
- for (k = kh; k <= i2; ++k) {
- MP.r[k - 1] = c / iy;
- c = MP.b * (c - iy * MP.r[k - 1]);
+ for (k = kh - 1; k < i2; k++) {
+ MP.r[k] = c / iy;
+ c = MP.b * (c - iy * MP.r[k]);
}
if (c < 0)
goto L210;
/* NORMALIZE AND ROUND RESULT */
mp_get_normalized_register(rs, &re, z, 0);
+
return;
}
@@ -698,11 +697,13 @@ mpdivi(const MPNumber *x, int iy, MPNumber *z)
/* LOOK FOR FIRST NONZERO DIGIT */
while(1) {
- ++i;
+ i++;
c = MP.b * c + c2;
c2 = 0;
- if (i <= MP.t) c2 = x->data[i + 1];
- if ((i__1 = c - j1) < 0)
+ if (i <= MP.t)
+ c2 = x->fraction[i - 1];
+ i__1 = c - j1;
+ if (i__1 < 0)
continue;
else if (i__1 == 0) {
if (c2 < j2)
@@ -736,7 +737,7 @@ mpdivi(const MPNumber *x, int iy, MPNumber *z)
}
if (i <= MP.t)
- iq += x->data[i + 1];
+ iq += x->fraction[i - 1];
iqj = iq / iy;
/* R(K) = QUOTIENT, C = REMAINDER */
@@ -758,7 +759,7 @@ L210:
/* CARRY NEGATIVE SO OVERFLOW MUST HAVE OCCURRED */
mpchk(1, 4);
mperr("*** INTEGER OVERFLOW IN MPDIVI, B TOO LARGE ***");
- z->data[0] = 0;
+ z->sign = 0;
}
@@ -836,13 +837,13 @@ mpexp(const MPNumber *x, MPNumber *y)
mpchk(4, 10);
/* CHECK FOR X == 0 */
- if (x->data[0] == 0) {
+ if (x->sign == 0) {
mp_set_from_integer(1, y);
return;
}
/* CHECK IF ABS(X) < 1 */
- if (x->data[1] <= 0) {
+ if (x->exponent <= 0) {
/* USE MPEXP1 HERE */
mpexp1(x, y);
mp_add_integer(y, 1, y);
@@ -869,7 +870,7 @@ mpexp(const MPNumber *x, MPNumber *y)
rx = mp_cast_to_float(x);
/* SAVE SIGN AND WORK WITH ABS(X) */
- xs = x->data[0];
+ xs = x->sign;
mp_abs(x, &t2);
/* IF ABS(X) > M POSSIBLE THAT INT(X) OVERFLOWS,
@@ -884,7 +885,7 @@ mpexp(const MPNumber *x, MPNumber *y)
mpcmf(&t2, &t2);
/* ATTACH SIGN TO FRACTIONAL PART AND COMPUTE EXP OF IT */
- t2.data[0] *= xs;
+ t2.sign *= xs;
mpexp1(&t2, y);
mp_add_integer(y, 1, y);
@@ -896,21 +897,21 @@ mpexp(const MPNumber *x, MPNumber *y)
if (MP.t < 4)
ts = MP.t + 1;
MP.t = ts;
- t2.data[0] = 0;
+ t2.sign = 0;
mp_set_from_integer(xs, &t1);
i = 1;
/* LOOP FOR E COMPUTATION. DECREASE T IF POSSIBLE. */
/* Computing MIN */
do {
- MP.t = min(ts, ts + 2 + t1.data[1]);
+ MP.t = min(ts, ts + 2 + t1.exponent);
if (MP.t <= 2)
break;
++i;
mpdivi(&t1, i * xs, &t1);
MP.t = ts;
mp_add(&t2, &t1, &t2);
- } while (t1.data[0] != 0);
+ } while (t1.sign != 0);
/* RAISE E OR 1/E TO POWER IX */
MP.t = ts;
@@ -926,20 +927,20 @@ mpexp(const MPNumber *x, MPNumber *y)
mpmul(y, &t2, y);
/* MUST CORRECT RESULT IF DIVIDED BY 32 ABOVE. */
- if (fabs(rx) > (float) MP.m && y->data[0] != 0) {
+ if (fabs(rx) > (float) MP.m && y->sign != 0) {
for (i = 1; i <= 5; ++i) {
/* SAVE EXPONENT TO AVOID OVERFLOW IN MPMUL */
- ie = y->data[1];
- y->data[1] = 0;
+ ie = y->exponent;
+ y->exponent = 0;
mpmul(y, y, y);
- y->data[1] += ie << 1;
+ y->exponent += ie << 1;
/* CHECK FOR UNDERFLOW AND OVERFLOW */
- if (y->data[1] < -MP.m) {
+ if (y->exponent < -MP.m) {
mpunfl(y);
return;
}
- if (y->data[1] > MP.m) {
+ if (y->exponent > MP.m) {
mpovfl(y, "*** OVERFLOW IN SUBROUTINE MPEXP ***");
return;
}
@@ -984,15 +985,15 @@ mpexp1(const MPNumber *x, MPNumber *y)
mpchk(3, 8);
/* CHECK FOR X = 0 */
- if (x->data[0] == 0) {
- y->data[0] = 0;
+ if (x->sign == 0) {
+ y->sign = 0;
return;
}
/* CHECK THAT ABS(X) < 1 */
- if (x->data[1] > 0) {
+ if (x->exponent > 0) {
mperr("*** ABS(X) NOT LESS THAN 1 IN CALL TO MPEXP1 ***");
- y->data[0] = 0;
+ y->sign = 0;
return;
}
@@ -1000,7 +1001,7 @@ mpexp1(const MPNumber *x, MPNumber *y)
rlb = log((float) MP.b);
/* COMPUTE APPROXIMATELY OPTIMAL Q (AND DIVIDE X BY 2**Q) */
- q = (int) (sqrt((float) MP.t * (float).48 * rlb) + (float) x->data[1] *
+ q = (int) (sqrt((float) MP.t * (float).48 * rlb) + (float) x->exponent *
(float)1.44 * rlb);
/* HALVE Q TIMES */
@@ -1016,8 +1017,8 @@ mpexp1(const MPNumber *x, MPNumber *y)
}
}
- if (t1.data[0] == 0) {
- y->data[0] = 0;
+ if (t1.sign == 0) {
+ y->sign = 0;
return;
}
mp_set_from_mp(&t1, y);
@@ -1027,7 +1028,7 @@ mpexp1(const MPNumber *x, MPNumber *y)
/* SUM SERIES, REDUCING T WHERE POSSIBLE */
do {
- MP.t = ts + 2 + t2.data[1] - y->data[1];
+ MP.t = ts + 2 + t2.exponent - y->exponent;
if (MP.t <= 2)
break;
@@ -1037,7 +1038,7 @@ mpexp1(const MPNumber *x, MPNumber *y)
mpdivi(&t2, i, &t2);
MP.t = ts;
mp_add(&t2, y, y);
- } while (t2.data[0] != 0);
+ } while (t2.sign != 0);
MP.t = ts;
if (q <= 0)
@@ -1060,17 +1061,17 @@ mpext(int i, int j, MPNumber *x)
{
int q, s;
- if (x->data[0] == 0 || MP.t <= 2 || i == 0)
+ if (x->sign == 0 || MP.t <= 2 || i == 0)
return;
/* COMPUTE MAXIMUM POSSIBLE ERROR IN THE LAST PLACE */
q = (j + 1) / i + 1;
- s = MP.b * x->data[MP.t] + x->data[MP.t + 1];
+ s = MP.b * x->fraction[MP.t - 2] + x->fraction[MP.t - 1];
/* SET LAST TWO DIGITS TO ZERO */
if (s <= q) {
- x->data[MP.t] = 0;
- x->data[MP.t + 1] = 0;
+ x->fraction[MP.t - 2] = 0;
+ x->fraction[MP.t - 1] = 0;
return;
}
@@ -1078,8 +1079,8 @@ mpext(int i, int j, MPNumber *x)
return;
/* ROUND UP HERE */
- x->data[MP.t] = MP.b - 1;
- x->data[MP.t + 1] = MP.b;
+ x->fraction[MP.t - 2] = MP.b - 1;
+ x->fraction[MP.t - 1] = MP.b;
/* NORMALIZE X (LAST DIGIT B IS OK IN MPMULI) */
mpmuli(x, 1, x);
@@ -1126,7 +1127,7 @@ mpgcd(int *k, int *l)
int
mp_is_zero(const MPNumber *x)
{
- return x->data[0] == 0;
+ return x->sign == 0;
}
@@ -1183,15 +1184,15 @@ mpln(MPNumber *x, MPNumber *y)
mpchk(6, 14);
/* CHECK THAT X IS POSITIVE */
- if (x->data[0] <= 0) {
+ if (x->sign <= 0) {
mperr("*** X NONPOSITIVE IN CALL TO MPLN ***");
- y->data[0] = 0;
+ y->sign = 0;
return;
}
/* MOVE X TO LOCAL STORAGE */
mp_set_from_mp(x, &t1);
- y->data[0] = 0;
+ y->sign = 0;
k = 0;
/* LOOP TO GET APPROXIMATE LN(X) USING SINGLE-PRECISION */
@@ -1200,7 +1201,7 @@ mpln(MPNumber *x, MPNumber *y)
mp_add_integer(&t1, -1, &t2);
/* IF POSSIBLE GO TO CALL MPLNS */
- if (t2.data[0] == 0 || t2.data[1] + 1 <= 0) {
+ if (t2.sign == 0 || t2.exponent + 1 <= 0) {
/* COMPUTE FINAL CORRECTION ACCURATELY USING MPLNS */
mplns(&t2, &t2);
mp_add(y, &t2, y);
@@ -1208,12 +1209,12 @@ mpln(MPNumber *x, MPNumber *y)
}
/* REMOVE EXPONENT TO AVOID FLOATING-POINT OVERFLOW */
- e = t1.data[1];
- t1.data[1] = 0;
+ e = t1.exponent;
+ t1.exponent = 0;
rx = mp_cast_to_float(&t1);
/* RESTORE EXPONENT AND COMPUTE SINGLE-PRECISION LOG */
- t1.data[1] = e;
+ t1.exponent = e;
rlx = log(rx) + (float) e * log((float) MP.b);
mp_set_from_float(-(double)rlx, &t2);
@@ -1267,15 +1268,15 @@ mplns(const MPNumber *x, MPNumber *y)
mpchk(5, 12);
/* CHECK FOR X = 0 EXACTLY */
- if (x->data[0] == 0) {
- y->data[0] = 0;
+ if (x->sign == 0) {
+ y->sign = 0;
return;
}
/* CHECK THAT ABS(X) < 1/B */
- if (x->data[1] + 1 > 0) {
+ if (x->exponent + 1 > 0) {
mperr("*** ABS(X) >= 1/B IN CALL TO MPLNS ***");
- y->data[0] = 0;
+ y->sign = 0;
return;
}
@@ -1324,13 +1325,13 @@ mplns(const MPNumber *x, MPNumber *y)
}
/* CHECK THAT NEWTON ITERATION WAS CONVERGING AS EXPECTED */
- if (t3.data[0] != 0 && t3.data[1] << 1 > it0 - MP.t) {
+ if (t3.sign != 0 && t3.exponent << 1 > it0 - MP.t) {
mperr("*** ERROR OCCURRED IN MPLNS, NEWTON ITERATION NOT CONVERGING PROPERLY ***");
}
}
/* REVERSE SIGN OF Y AND RETURN */
- y->data[0] = -y->data[0];
+ y->sign = -y->sign;
MP.t = ts;
}
@@ -1356,11 +1357,11 @@ mpmaxr(MPNumber *x)
/* SET FRACTION DIGITS TO B-1 */
for (i = 1; i <= MP.t; i++)
- x->data[i + 1] = it;
+ x->fraction[i - 1] = it;
/* SET SIGN AND EXPONENT */
- x->data[0] = 1;
- x->data[1] = MP.m;
+ x->sign = 1;
+ x->exponent = MP.m;
}
@@ -1402,32 +1403,32 @@ mpmul(const MPNumber *x, const MPNumber *y, MPNumber *z)
i2p = i2 + 1;
/* FORM SIGN OF PRODUCT */
- rs = x->data[0] * y->data[0];
+ rs = x->sign * y->sign;
if (rs == 0) {
/* SET RESULT TO ZERO */
- z->data[0] = 0;
+ z->sign = 0;
return;
}
/* FORM EXPONENT OF PRODUCT */
- re = x->data[1] + y->data[1];
+ re = x->exponent + y->exponent;
/* CLEAR ACCUMULATOR */
- for (i = 1; i <= i2; ++i)
- MP.r[i - 1] = 0;
+ for (i = 0; i < i2; i++)
+ MP.r[i] = 0;
/* PERFORM MULTIPLICATION */
c = 8;
i__1 = MP.t;
for (i = 1; i <= i__1; ++i) {
- xi = x->data[i + 1];
+ xi = x->fraction[i - 1];
/* FOR SPEED, PUT THE NUMBER WITH MANY ZEROS FIRST */
if (xi == 0)
continue;
/* Computing MIN */
- mpmlp(&MP.r[i], &y->data[2], xi, min(MP.t, i2 - i));
+ mpmlp(&MP.r[i], y->fraction, xi, min(MP.t, i2 - i));
--c;
if (c > 0)
continue;
@@ -1435,7 +1436,7 @@ mpmul(const MPNumber *x, const MPNumber *y, MPNumber *z)
/* CHECK FOR LEGAL BASE B DIGIT */
if (xi < 0 || xi >= MP.b) {
mperr("*** ILLEGAL BASE B DIGIT IN CALL TO MPMUL, POSSIBLE OVERWRITING PROBLEM ***");
- z->data[0] = 0;
+ z->sign = 0;
return;
}
@@ -1447,7 +1448,7 @@ mpmul(const MPNumber *x, const MPNumber *y, MPNumber *z)
ri = MP.r[j1 - 1] + c;
if (ri < 0) {
mperr("*** INTEGER OVERFLOW IN MPMUL, B TOO LARGE ***");
- z->data[0] = 0;
+ z->sign = 0;
return;
}
c = ri / MP.b;
@@ -1455,7 +1456,7 @@ mpmul(const MPNumber *x, const MPNumber *y, MPNumber *z)
}
if (c != 0) {
mperr("*** ILLEGAL BASE B DIGIT IN CALL TO MPMUL, POSSIBLE OVERWRITING PROBLEM ***");
- z->data[0] = 0;
+ z->sign = 0;
return;
}
c = 8;
@@ -1464,7 +1465,7 @@ mpmul(const MPNumber *x, const MPNumber *y, MPNumber *z)
if (c != 8) {
if (xi < 0 || xi >= MP.b) {
mperr("*** ILLEGAL BASE B DIGIT IN CALL TO MPMUL, POSSIBLE OVERWRITING PROBLEM ***");
- z->data[0] = 0;
+ z->sign = 0;
return;
}
@@ -1474,7 +1475,7 @@ mpmul(const MPNumber *x, const MPNumber *y, MPNumber *z)
ri = MP.r[j1 - 1] + c;
if (ri < 0) {
mperr("*** INTEGER OVERFLOW IN MPMUL, B TOO LARGE ***");
- z->data[0] = 0;
+ z->sign = 0;
return;
}
c = ri / MP.b;
@@ -1483,7 +1484,7 @@ mpmul(const MPNumber *x, const MPNumber *y, MPNumber *z)
if (c != 0) {
mperr("*** ILLEGAL BASE B DIGIT IN CALL TO MPMUL, POSSIBLE OVERWRITING PROBLEM ***");
- z->data[0] = 0;
+ z->sign = 0;
return;
}
}
@@ -1504,9 +1505,9 @@ mpmul2(MPNumber *x, int iy, MPNumber *z, int trunc)
int c, i, c1, c2, j1, j2;
int t1, t3, t4, ij, re, ri = 0, is, ix, rs;
- rs = x->data[0];
+ rs = x->sign;
if (rs == 0 || iy == 0) {
- z->data[0] = 0;
+ z->sign = 0;
return;
}
@@ -1516,10 +1517,10 @@ mpmul2(MPNumber *x, int iy, MPNumber *z, int trunc)
/* CHECK FOR MULTIPLICATION BY B */
if (iy == MP.b) {
- if (x->data[1] < MP.m) {
+ if (x->exponent < MP.m) {
mp_set_from_mp(x, z);
- z->data[0] = rs;
- z->data[1] = x->data[1] + 1;
+ z->sign = rs;
+ z->exponent = x->exponent + 1;
}
else {
mpchk(1, 4);
@@ -1530,7 +1531,7 @@ mpmul2(MPNumber *x, int iy, MPNumber *z, int trunc)
}
/* SET EXPONENT TO EXPONENT(X) + 4 */
- re = x->data[1] + 4;
+ re = x->exponent + 4;
/* FORM PRODUCT IN ACCUMULATOR */
c = 0;
@@ -1555,7 +1556,7 @@ mpmul2(MPNumber *x, int iy, MPNumber *z, int trunc)
i = t1 - ij;
ix = 0;
if (i > 0)
- ix = x->data[i + 1];
+ ix = x->fraction[i - 1];
ri = j2 * ix + c2;
is = ri / MP.b;
c = j1 * ix + c1 + is;
@@ -1566,7 +1567,7 @@ mpmul2(MPNumber *x, int iy, MPNumber *z, int trunc)
{
for (ij = 1; ij <= MP.t; ++ij) {
i = t1 - ij;
- ri = iy * x->data[i + 1] + c;
+ ri = iy * x->fraction[i - 1] + c;
c = ri / MP.b;
MP.r[i + 3] = ri - MP.b * c;
}
@@ -1575,7 +1576,7 @@ mpmul2(MPNumber *x, int iy, MPNumber *z, int trunc)
if (ri < 0) {
mpchk(1, 4);
mperr("*** INTEGER OVERFLOW IN MPMUL2, B TOO LARGE ***");
- z->data[0] = 0;
+ z->sign = 0;
return;
}
@@ -1600,7 +1601,7 @@ mpmul2(MPNumber *x, int iy, MPNumber *z, int trunc)
if (c < 0) {
mpchk(1, 4);
mperr("*** INTEGER OVERFLOW IN MPMUL2, B TOO LARGE ***");
- z->data[0] = 0;
+ z->sign = 0;
return;
}
@@ -1639,12 +1640,12 @@ mpmulq(MPNumber *x, int i, int j, MPNumber *y)
if (j == 0) {
mpchk(1, 4);
mperr("*** ATTEMPTED DIVISION BY ZERO IN MPMULQ ***");
- y->data[0] = 0;
+ y->sign = 0;
return;
}
if (i == 0) {
- y->data[0] = 0;
+ y->sign = 0;
return;
}
@@ -1667,7 +1668,7 @@ void
mp_invert_sign(const MPNumber *x, MPNumber *y)
{
mp_set_from_mp(x, y);
- y->data[0] = -y->data[0];
+ y->sign = -y->sign;
}
@@ -1681,47 +1682,43 @@ mp_get_normalized_register(int reg_sign, int *reg_exp, MPNumber *z, int trunc)
{
int i__1;
- int i, j, k, b2, i2, is, it, i2m, i2p;
+ int i, j, b2, i2, i2m;
int round;
i2 = MP.t + 4;
if (reg_sign == 0) {
/* STORE ZERO IN Z */
- z->data[0] = 0;
+ z->sign = 0;
return;
}
/* CHECK THAT SIGN = +-1 */
if (abs(reg_sign) > 1) {
mperr("*** SIGN NOT 0, +1 OR -1 IN CALL TO MP_GET_NORMALIZED_REGISTER, POSSIBLE OVERWRITING PROBLEM ***");
- z->data[0] = 0;
+ z->sign = 0;
return;
}
/* LOOK FOR FIRST NONZERO DIGIT */
- for (i = 1; i <= i2; ++i) {
- is = i - 1;
- if (MP.r[i - 1] > 0)
+ for (i = 0; i < i2; i++) {
+ if (MP.r[i] > 0)
break;
}
/* FRACTION ZERO */
- if (i > i2) {
- z->data[0] = 0;
+ if (i >= i2) {
+ z->sign = 0;
return;
}
- if (is != 0) {
+ if (i != 0) {
/* NORMALIZE */
- *reg_exp -= is;
- i2m = i2 - is;
- for (j = 1; j <= i2m; ++j) {
- k = j + is;
- MP.r[j - 1] = MP.r[k - 1];
- }
- i2p = i2m + 1;
- for (j = i2p; j <= i2; ++j)
- MP.r[j - 1] = 0;
+ *reg_exp -= i;
+ i2m = i2 - i;
+ for (j = 0; j < i2m; j++)
+ MP.r[j] = MP.r[j + i];
+ for (; j < i2; j++)
+ MP.r[j] = 0;
}
/* CHECK TO SEE IF TRUNCATION IS DESIRED */
@@ -1733,9 +1730,9 @@ mp_get_normalized_register(int reg_sign, int *reg_exp, MPNumber *z, int trunc)
if (b2 << 1 != MP.b) {
round = 0;
/* ODD BASE, ROUND IF R(T+1)... > 1/2 */
- for (i = 1; i <= 4; ++i) {
- it = MP.t + i;
- if ((i__1 = MP.r[it - 1] - b2) < 0)
+ for (i = 0; i < 4; i++) {
+ i__1 = MP.r[MP.t + i] - b2;
+ if (i__1 < 0)
break;
else if (i__1 == 0)
continue;
@@ -1750,7 +1747,8 @@ mp_get_normalized_register(int reg_sign, int *reg_exp, MPNumber *z, int trunc)
* AFTER R(T+2).
*/
round = 1;
- if ((i__1 = MP.r[MP.t] - b2) < 0)
+ i__1 = MP.r[MP.t] - b2;
+ if (i__1 < 0)
round = 0;
else if (i__1 == 0) {
if (MP.r[MP.t - 1] % 2 != 0) {
@@ -1763,16 +1761,15 @@ mp_get_normalized_register(int reg_sign, int *reg_exp, MPNumber *z, int trunc)
/* ROUND */
if (round) {
- for (j = 1; j <= MP.t; ++j) {
- i = MP.t + 1 - j;
- ++MP.r[i - 1];
- if (MP.r[i - 1] < MP.b)
+ for (j = MP.t - 1; j >= 0; j--) {
+ ++MP.r[j];
+ if (MP.r[j] < MP.b)
break;
- MP.r[i - 1] = 0;
+ MP.r[j] = 0;
}
/* EXCEPTIONAL CASE, ROUNDED UP TO .10000... */
- if (j > MP.t) {
+ if (j < 0) {
++(*reg_exp);
MP.r[0] = 1;
}
@@ -1792,10 +1789,10 @@ mp_get_normalized_register(int reg_sign, int *reg_exp, MPNumber *z, int trunc)
}
/* STORE RESULT IN Z */
- z->data[0] = reg_sign;
- z->data[1] = *reg_exp;
- for (i = 1; i <= MP.t; ++i)
- z->data[i + 1] = MP.r[i - 1];
+ z->sign = reg_sign;
+ z->exponent = *reg_exp;
+ for (i = 0; i < MP.t; i++)
+ z->fraction[i] = MP.r[i];
}
@@ -1869,9 +1866,9 @@ mppwr(const MPNumber *x, int n, MPNumber *y)
/* N < 0 */
mpchk(4, 10);
n2 = -n2;
- if (x->data[0] == 0) {
+ if (x->sign == 0) {
mperr("*** ATTEMPT TO RAISE ZERO TO NEGATIVE POWER IN CALL TO SUBROUTINE MPPWR ***");
- y->data[0] = 0;
+ y->sign = 0;
return;
}
} else if (n2 == 0) {
@@ -1881,8 +1878,8 @@ mppwr(const MPNumber *x, int n, MPNumber *y)
} else {
/* N > 0 */
mpchk(2, 6);
- if (x->data[0] == 0) {
- y->data[0] = 0;
+ if (x->sign == 0) {
+ y->sign = 0;
return;
}
}
@@ -1925,17 +1922,17 @@ mppwr2(MPNumber *x, MPNumber *y, MPNumber *z)
mpchk(7, 16);
- if (x->data[0] < 0) {
+ if (x->sign < 0) {
mperr(_("Negative X and non-integer Y not supported"));
- z->data[0] = 0;
+ z->sign = 0;
}
- else if (x->data[0] == 0)
+ else if (x->sign == 0)
{
/* HERE X IS ZERO, RETURN ZERO IF Y POSITIVE, OTHERWISE ERROR */
- if (y->data[0] <= 0) {
+ if (y->sign <= 0) {
mperr("*** X ZERO AND Y NONPOSITIVE IN CALL TO MPPWR2 ***");
}
- z->data[0] = 0;
+ z->sign = 0;
}
else {
/* USUAL CASE HERE, X POSITIVE
@@ -1972,13 +1969,13 @@ mp_reciprocal(const MPNumber *x, MPNumber *z)
mpchk(4, 10);
/* MP_ADD_INTEGER REQUIRES 2T+6 WORDS. */
- if (x->data[0] == 0) {
+ if (x->sign == 0) {
mperr("*** ATTEMPTED DIVISION BY ZERO IN CALL TO MP_RECIPROCAL ***");
- z->data[0] = 0;
+ z->sign = 0;
return;
}
- ex = x->data[1];
+ ex = x->exponent;
/* TEMPORARILY INCREASE M TO AVOID OVERFLOW */
MP.m += 2;
@@ -1986,14 +1983,14 @@ mp_reciprocal(const MPNumber *x, MPNumber *z)
/* SET EXPONENT TO ZERO SO RX NOT TOO LARGE OR SMALL. */
/* work-around to avoid touching X */
mp_set_from_mp(x, &tmp_x);
- tmp_x.data[1] = 0;
+ tmp_x.exponent = 0;
rx = mp_cast_to_float(&tmp_x);
/* USE SINGLE-PRECISION RECIPROCAL AS FIRST APPROXIMATION */
mp_set_from_float((float)1. / rx, &t1);
/* CORRECT EXPONENT OF FIRST APPROXIMATION */
- t1.data[1] -= ex;
+ t1.exponent -= ex;
/* SAVE T (NUMBER OF DIGITS) */
ts = MP.t;
@@ -2035,7 +2032,7 @@ mp_reciprocal(const MPNumber *x, MPNumber *z)
}
/* RETURN IF NEWTON ITERATION WAS CONVERGING */
- if (t2.data[0] != 0 && (t1.data[1] - t2.data[1]) << 1 < MP.t - it0) {
+ if (t2.sign != 0 && (t1.exponent - t2.exponent) << 1 < MP.t - it0) {
/* THE FOLLOWING MESSAGE MAY INDICATE THAT B**(T-1) IS TOO SMALL,
* OR THAT THE STARTING APPROXIMATION IS NOT ACCURATE ENOUGH.
*/
@@ -2049,7 +2046,7 @@ mp_reciprocal(const MPNumber *x, MPNumber *z)
/* RESTORE M AND CHECK FOR OVERFLOW (UNDERFLOW IMPOSSIBLE) */
MP.m += -2;
- if (z->data[1] <= MP.m)
+ if (z->exponent <= MP.m)
return;
mpovfl(z, "*** OVERFLOW OCCURRED IN MP_RECIPROCAL ***");
@@ -2083,7 +2080,7 @@ mp_root(const MPNumber *x, int n, MPNumber *z)
if (n == 0) {
mperr("*** N == 0 IN CALL TO MP_ROOT ***");
- z->data[0] = 0;
+ z->sign = 0;
return;
}
@@ -2092,49 +2089,49 @@ mp_root(const MPNumber *x, int n, MPNumber *z)
/* LOSS OF ACCURACY IF NP LARGE, SO ONLY ALLOW NP <= MAX (B, 64) */
if (np > max(MP.b, 64)) {
mperr("*** ABS(N) TOO LARGE IN CALL TO MP_ROOT ***");
- z->data[0] = 0;
+ z->sign = 0;
return;
}
/* LOOK AT SIGN OF X */
- if (x->data[0] == 0) {
+ if (x->sign == 0) {
/* X == 0 HERE, RETURN 0 IF N POSITIVE, ERROR IF NEGATIVE */
- z->data[0] = 0;
+ z->sign = 0;
if (n > 0)
return;
mperr("*** X == 0 AND N NEGATIVE IN CALL TO MP_ROOT ***");
- z->data[0] = 0;
+ z->sign = 0;
return;
}
- if (x->data[0] < 0 && np % 2 == 0) {
+ if (x->sign < 0 && np % 2 == 0) {
mperr("*** X NEGATIVE AND N EVEN IN CALL TO MP_ROOT ***");
- z->data[0] = 0;
+ z->sign = 0;
return;
}
/* DIVIDE EXPONENT BY NP */
- ex = x->data[1] / np;
+ ex = x->exponent / np;
/* REDUCE EXPONENT SO RX NOT TOO LARGE OR SMALL. */
{
MPNumber tmp_x;
mp_set_from_mp(x, &tmp_x);
- tmp_x.data[1] = 0;
+ tmp_x.exponent = 0;
rx = mp_cast_to_float(&tmp_x);
}
/* USE SINGLE-PRECISION ROOT FOR FIRST APPROXIMATION */
- r__1 = exp(((float) (np * ex - x->data[1]) * log((float) MP.b) -
+ r__1 = exp(((float) (np * ex - x->exponent) * log((float) MP.b) -
log((fabs(rx)))) / (float) np);
mp_set_from_float(r__1, &t1);
/* SIGN OF APPROXIMATION SAME AS THAT OF X */
- t1.data[0] = x->data[0];
+ t1.sign = x->sign;
/* CORRECT EXPONENT OF FIRST APPROXIMATION */
- t1.data[1] -= ex;
+ t1.exponent -= ex;
/* SAVE T (NUMBER OF DIGITS) */
ts = MP.t;
@@ -2184,7 +2181,7 @@ mp_root(const MPNumber *x, int n, MPNumber *z)
/* NOW R(I2) IS X**(-1/NP)
* CHECK THAT NEWTON ITERATION WAS CONVERGING
*/
- if (t2.data[0] != 0 && (t1.data[1] - t2.data[1]) << 1 < MP.t - it0) {
+ if (t2.sign != 0 && (t1.exponent - t2.exponent) << 1 < MP.t - it0) {
/* THE FOLLOWING MESSAGE MAY INDICATE THAT B**(T-1) IS TOO SMALL,
* OR THAT THE INITIAL APPROXIMATION OBTAINED USING ALOG AND EXP
* IS NOT ACCURATE ENOUGH.
@@ -2298,15 +2295,15 @@ mp_sqrt(const MPNumber *x, MPNumber *z)
/* MP_ROOT NEEDS 4T+10 WORDS, BUT CAN OVERLAP SLIGHTLY. */
i2 = MP.t * 3 + 9;
- if (x->data[0] < 0) {
+ if (x->sign < 0) {
mperr("*** X NEGATIVE IN CALL TO SUBROUTINE MP_SQRT ***");
- } else if (x->data[0] == 0) {
- z->data[0] = 0;
+ } else if (x->sign == 0) {
+ z->sign = 0;
} else {
mp_root(x, -2, &t);
- i = t.data[2];
+ i = t.fraction[0];
mpmul(x, &t, z);
- iy3 = z->data[2];
+ iy3 = z->fraction[0];
mpext(i, iy3, z);
}
}
@@ -2317,7 +2314,7 @@ mp_sqrt(const MPNumber *x, MPNumber *z)
void
mp_subtract(const MPNumber *x, const MPNumber *y, MPNumber *z)
{
- mpadd2(x, y, z, -y->data[0], 0);
+ mpadd2(x, y, z, -y->sign, 0);
}
/* CALLED ON MULTIPLE-PRECISION UNDERFLOW, IE WHEN THE
@@ -2335,7 +2332,7 @@ mpunfl(MPNumber *x)
* AFTER A PRESET NUMBER OF UNDERFLOWS. ACTION COULD EASILY
* BE DETERMINED BY A FLAG IN LABELLED COMMON.
*/
- x->data[0] = 0;
+ x->sign = 0;
}
static int
diff --git a/gcalctool/mp.h b/gcalctool/mp.h
index 8ec4b7e..baf5f9e 100644
--- a/gcalctool/mp.h
+++ b/gcalctool/mp.h
@@ -44,11 +44,13 @@
typedef struct
{
- /* data[0] = sign (0, -1 or +1)
- * data[1] = exponent (to base MP.b)
- * data[2..MP.t+2] = normalized fraction.
+ /* sign (0, -1 or +1)
+ * exponent (to base MP.b)
+ * fraction = normalized fraction.
*/
- int data[MP_SIZE];
+ int sign;
+ int exponent;
+ int fraction[MP_SIZE-2]; // Size MP.t?
} MPNumber;
/* If we're not using GNU C, elide __attribute__ */
diff --git a/gcalctool/unittest.c b/gcalctool/unittest.c
index 2e06127..6d1d5aa 100644
--- a/gcalctool/unittest.c
+++ b/gcalctool/unittest.c
@@ -54,6 +54,8 @@ test(char *expression, char *expected, int expected_error)
void
test_parser()
{
+ v->base = DEC;
+
test("0", "0", 0);
test("1", "1", 0);
test("+1", "1", 0);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]