[gcalctool] Simplify MP loops
- From: Robert Ancell <rancell src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gcalctool] Simplify MP loops
- Date: Mon, 17 May 2010 06:44:36 +0000 (UTC)
commit 6554f3d2186565e1618692e669d007a917308ad4
Author: Robert Ancell <robert ancell gmail com>
Date: Sat May 15 11:50:40 2010 +0200
Simplify MP loops
src/mp.c | 123 +++++++++++++++++++++++++++++++-------------------------------
1 files changed, 62 insertions(+), 61 deletions(-)
---
diff --git a/src/mp.c b/src/mp.c
index 331ea9b..320c3b2 100644
--- a/src/mp.c
+++ b/src/mp.c
@@ -603,9 +603,7 @@ mp_divide(const MPNumber *x, const MPNumber *y, MPNumber *z)
void
mp_divide_integer(const MPNumber *x, int64_t y, MPNumber *z)
{
- int i__1;
- int c, i, k, b2, c2, i2, j1, j2, r1;
- int j11, kh, iq, ir, iqj;
+ int c, i, k, b2, c2, j1, j2;
/* x/0 */
if (y == 0) {
@@ -650,7 +648,6 @@ mp_divide_integer(const MPNumber *x, int64_t y, MPNumber *z)
z->exponent = x->exponent;
c = 0;
- i2 = MP_T + 4;
i = 0;
/* IF y*B NOT REPRESENTABLE AS AN INTEGER HAVE TO SIMULATE
@@ -660,6 +657,8 @@ mp_divide_integer(const MPNumber *x, int64_t y, MPNumber *z)
/* Computing MAX */
b2 = max(MP_BASE << 3, 32767 / MP_BASE);
if (y < b2) {
+ int kh, r1;
+
/* LOOK FOR FIRST NONZERO DIGIT IN QUOTIENT */
do {
c = MP_BASE * c;
@@ -669,7 +668,7 @@ mp_divide_integer(const MPNumber *x, int64_t y, MPNumber *z)
r1 = c / y;
if (r1 < 0)
goto L210;
- } while(r1 == 0);
+ } while (r1 == 0);
/* ADJUST EXPONENT AND GET T+4 DIGITS IN QUOTIENT */
z->exponent += 1 - i;
@@ -688,7 +687,7 @@ mp_divide_integer(const MPNumber *x, int64_t y, MPNumber *z)
goto L210;
}
- for (k = kh; k < i2; k++) {
+ for (k = kh; k < MP_T + 4; k++) {
z->fraction[k] = c / y;
c = MP_BASE * (c - y * z->fraction[k]);
}
@@ -703,16 +702,15 @@ mp_divide_integer(const MPNumber *x, int64_t y, MPNumber *z)
/* HERE NEED SIMULATED DOUBLE-PRECISION DIVISION */
j1 = y / MP_BASE;
+ j2 = y - j1 * MP_BASE;
/* LOOK FOR FIRST NONZERO DIGIT */
c2 = 0;
- j2 = y - j1 * MP_BASE;
do {
c = MP_BASE * c + c2;
- i__1 = c - j1;
c2 = i < MP_T ? x->fraction[i] : 0;
i++;
- } while (i__1 < 0 || (i__1 == 0 && c2 < j2));
+ } while (c < j1 || (c == j1 && c2 < j2));
/* COMPUTE T+4 QUOTIENT DIGITS */
z->exponent += 1 - i;
@@ -720,10 +718,11 @@ mp_divide_integer(const MPNumber *x, int64_t y, MPNumber *z)
k = 1;
/* MAIN LOOP FOR LARGE ABS(y) CASE */
- j11 = j1 + 1;
- while(1) {
+ while (true) {
+ int ir, iq, iqj;
+
/* GET APPROXIMATE QUOTIENT FIRST */
- ir = c / j11;
+ ir = c / (j1 + 1);
/* NOW REDUCE SO OVERFLOW DOES NOT OCCUR */
iq = c - ir * j1;
@@ -753,7 +752,7 @@ mp_divide_integer(const MPNumber *x, int64_t y, MPNumber *z)
goto L210;
++k;
- if (k > i2) {
+ if (k > MP_T + 4) {
mp_normalize(z);
if (mp_is_complex(x)) {
@@ -1277,7 +1276,7 @@ mp_is_less_than(const MPNumber *x, const MPNumber *y)
static void
mp_multiply_real(const MPNumber *x, const MPNumber *y, MPNumber *z)
{
- int c, i, j, xi;
+ int c, i, xi;
MPNumber r;
/* x*0 = 0*y = 0 */
@@ -1293,6 +1292,8 @@ mp_multiply_real(const MPNumber *x, const MPNumber *y, MPNumber *z)
/* PERFORM MULTIPLICATION */
c = 8;
for (i = 0; i < MP_T; i++) {
+ int j;
+
xi = x->fraction[i];
/* FOR SPEED, PUT THE NUMBER WITH MANY ZEROS FIRST */
@@ -1342,15 +1343,15 @@ mp_multiply_real(const MPNumber *x, const MPNumber *y, MPNumber *z)
}
c = 0;
- for (j = MP_T + 3; j >= 0; j--) {
- int ri = r.fraction[j] + c;
+ for (i = MP_T + 3; i >= 0; i--) {
+ int ri = r.fraction[i] + c;
if (ri < 0) {
mperr("*** INTEGER OVERFLOW IN MP_MULTIPLY, B TOO LARGE ***");
mp_set_from_integer(0, z);
return;
}
c = ri / MP_BASE;
- r.fraction[j] = ri - MP_BASE * c;
+ r.fraction[i] = ri - MP_BASE * c;
}
if (c != 0) {
@@ -1405,8 +1406,7 @@ mp_multiply(const MPNumber *x, const MPNumber *y, MPNumber *z)
void
mp_multiply_integer(const MPNumber *x, int64_t y, MPNumber *z)
{
- int c, i, c1, c2, j1, j2;
- int t1, t3, t4, ij, ri = 0, is, ix;
+ int c, i;
/* x*0 = 0*y = 0 */
if (mp_is_zero(x) || y == 0) {
@@ -1418,12 +1418,14 @@ mp_multiply_integer(const MPNumber *x, int64_t y, MPNumber *z)
// FIXME: Why is this not working?
/*if (y == 1 || y == -1) {
mp_set_from_mp(x, z);
- z->sign *= y;
+ if (y < 0)
+ mp_invert_sign(z, z);
return;
}*/
/* If multiplying by base then can optimise */
- if (y % MP_BASE == 0) {
+ // FIXME: Very unlikely and doesn't support complex numbers
+ /*if (y % MP_BASE == 0) {
mp_set_from_mp(x, z);
if (y < 0) {
z->sign = -z->sign;
@@ -1432,8 +1434,9 @@ mp_multiply_integer(const MPNumber *x, int64_t y, MPNumber *z)
else
z->exponent += y / MP_BASE;
return;
- }
+ }*/
+ //FIXME: breaks: mp_set_from_integer(0, z);
if (y < 0) {
y = -y;
z->sign = -x->sign;
@@ -1444,9 +1447,6 @@ mp_multiply_integer(const MPNumber *x, int64_t y, MPNumber *z)
/* FORM PRODUCT IN ACCUMULATOR */
c = 0;
- t1 = MP_T + 1;
- t3 = MP_T + 3;
- t4 = MP_T + 4;
/* IF y*B NOT REPRESENTABLE AS AN INTEGER WE HAVE TO SIMULATE
* DOUBLE-PRECISION MULTIPLICATION.
@@ -1454,31 +1454,36 @@ mp_multiply_integer(const MPNumber *x, int64_t y, MPNumber *z)
/* Computing MAX */
if (y >= max(MP_BASE << 3, 32767 / MP_BASE)) {
+ int j1, j2;
+
/* HERE J IS TOO LARGE FOR SINGLE-PRECISION MULTIPLICATION */
j1 = y / MP_BASE;
j2 = y - j1 * MP_BASE;
/* FORM PRODUCT */
- for (ij = 1; ij <= t4; ++ij) {
+ for (i = MP_T + 3; i >= 0; i--) {
+ int c1, c2, is, ix, t;
+
c1 = c / MP_BASE;
c2 = c - MP_BASE * c1;
- i = t1 - ij;
ix = 0;
- if (i > 0)
- ix = x->fraction[i - 1];
- ri = j2 * ix + c2;
- is = ri / MP_BASE;
+ if (i > 3)
+ ix = x->fraction[i - 4];
+
+ t = j2 * ix + c2;
+ is = t / MP_BASE;
c = j1 * ix + c1 + is;
- z->fraction[i + 3] = ri - MP_BASE * is;
+ z->fraction[i] = t - MP_BASE * is;
}
}
else
{
- for (ij = 1; ij <= MP_T; ++ij) {
- i = t1 - ij;
- ri = y * x->fraction[i - 1] + c;
+ int ri = 0;
+
+ for (i = MP_T + 3; i >= 4; i--) {
+ ri = y * x->fraction[i - 4] + c;
c = ri / MP_BASE;
- z->fraction[i + 3] = ri - MP_BASE * c;
+ z->fraction[i] = ri - MP_BASE * c;
}
/* CHECK FOR INTEGER OVERFLOW */
@@ -1489,39 +1494,35 @@ mp_multiply_integer(const MPNumber *x, int64_t y, MPNumber *z)
}
/* HAVE TO TREAT FIRST FOUR WORDS OF R SEPARATELY */
- for (ij = 1; ij <= 4; ++ij) {
- i = 5 - ij;
- ri = c;
- c = ri / MP_BASE;
- z->fraction[i - 1] = ri - MP_BASE * c;
+ for (i = 3; i >= 0; i--) {
+ int t;
+
+ t = c;
+ c = t / MP_BASE;
+ z->fraction[i] = t - MP_BASE * c;
}
}
/* HAVE TO SHIFT RIGHT HERE AS CARRY OFF END */
- while(1) {
- /* NORMALIZE AND ROUND OR TRUNCATE RESULT */
- if (c == 0)
- {
- mp_normalize(z);
- return;
- }
-
- if (c < 0) {
- mperr("*** INTEGER OVERFLOW IN mp_multiply_integer, B TOO LARGE ***");
- mp_set_from_integer(0, z);
- return;
- }
+ while (c != 0) {
+ int t;
- for (ij = 1; ij <= t3; ++ij) {
- i = t4 - ij;
+ for (i = MP_T + 3; i >= 1; i--)
z->fraction[i] = z->fraction[i - 1];
- }
- ri = c;
- c = ri / MP_BASE;
- z->fraction[0] = ri - MP_BASE * c;
+ t = c;
+ c = t / MP_BASE;
+ z->fraction[0] = t - MP_BASE * c;
z->exponent++;
}
-
+
+ if (c < 0) {
+ mperr("*** INTEGER OVERFLOW IN mp_multiply_integer, B TOO LARGE ***");
+ mp_set_from_integer(0, z);
+ return;
+ }
+
+ mp_normalize(z);
+
if (mp_is_complex(x)) {
MPNumber im_z;
mp_imaginary_component(x, &im_z);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]