Fix code formatting in mpa.c

This includes the overridden mpa.c in power4.
This commit is contained in:
Siddhesh Poyarekar 2013-01-14 21:31:25 +05:30
parent e34ab70550
commit 1066a53440
4 changed files with 1487 additions and 718 deletions

View File

@ -1,5 +1,9 @@
2013-01-14 Siddhesh Poyarekar <siddhesh@redhat.com> 2013-01-14 Siddhesh Poyarekar <siddhesh@redhat.com>
* sysdeps/ieee754/dbl-64/mpa.c: Fix formatting.
* sysdeps/powerpc/powerpc32/power4/fpu/mpa.c: Likewise.
* sysdeps/powerpc/powerpc64/power4/fpu/mpa.c: Likewise.
* sysdeps/powerpc/powerpc32/power4/fpu/mpa.c (__inv): Remove * sysdeps/powerpc/powerpc32/power4/fpu/mpa.c (__inv): Remove
local variable MPTWO. local variable MPTWO.
* sysdeps/powerpc/powerpc64/power4/fpu/mpa.c (__inv): * sysdeps/powerpc/powerpc64/power4/fpu/mpa.c (__inv):

View File

@ -60,30 +60,45 @@ const mp_no mptwo = {1, {1.0, 2.0}};
/* Compare mantissa of two multiple precision numbers regardless of the sign /* Compare mantissa of two multiple precision numbers regardless of the sign
and exponent of the numbers. */ and exponent of the numbers. */
static int static int
mcr(const mp_no *x, const mp_no *y, int p) { mcr (const mp_no *x, const mp_no *y, int p)
{
int i; int i;
for (i=1; i<=p; i++) { for (i = 1; i <= p; i++)
if (X[i] == Y[i]) continue; {
else if (X[i] > Y[i]) return 1; if (X[i] == Y[i])
else return -1; } continue;
else if (X[i] > Y[i])
return 1;
else
return -1;
}
return 0; return 0;
} }
/* Compare the absolute values of two multiple precision numbers. */ /* Compare the absolute values of two multiple precision numbers. */
int int
__acr(const mp_no *x, const mp_no *y, int p) { __acr (const mp_no *x, const mp_no *y, int p)
{
int i; int i;
if (X[0] == ZERO) { if (X[0] == ZERO)
if (Y[0] == ZERO) i= 0; {
else i=-1; if (Y[0] == ZERO)
} i = 0;
else if (Y[0] == ZERO) i= 1; else
else { i = -1;
if (EX > EY) i= 1; }
else if (EX < EY) i=-1; else if (Y[0] == ZERO)
else i= mcr(x,y,p); i = 1;
} else
{
if (EX > EY)
i = 1;
else if (EX < EY)
i = -1;
else
i = mcr (x, y, p);
}
return i; return i;
} }
@ -92,59 +107,86 @@ __acr(const mp_no *x, const mp_no *y, int p) {
#ifndef NO___CPY #ifndef NO___CPY
/* Copy multiple precision number X into Y. They could be the same /* Copy multiple precision number X into Y. They could be the same
number. */ number. */
void __cpy(const mp_no *x, mp_no *y, int p) { void
__cpy (const mp_no *x, mp_no *y, int p)
{
EY = EX; EY = EX;
for (int i=0; i <= p; i++) Y[i] = X[i]; for (int i = 0; i <= p; i++)
Y[i] = X[i];
} }
#endif #endif
#ifndef NO___MP_DBL #ifndef NO___MP_DBL
/* Convert a multiple precision number *X into a double precision /* Convert a multiple precision number *X into a double precision
number *Y, normalized case (|x| >= 2**(-1022))). */ number *Y, normalized case (|x| >= 2**(-1022))). */
static void norm(const mp_no *x, double *y, int p) static void
norm (const mp_no *x, double *y, int p)
{ {
#define R RADIXI #define R RADIXI
int i; int i;
double a,c,u,v,z[5]; double a, c, u, v, z[5];
if (p<5) { if (p < 5)
if (p==1) c = X[1]; {
else if (p==2) c = X[1] + R* X[2]; if (p == 1)
else if (p==3) c = X[1] + R*(X[2] + R* X[3]); c = X[1];
else if (p==4) c =(X[1] + R* X[2]) + R*R*(X[3] + R*X[4]); else if (p == 2)
} c = X[1] + R * X[2];
else { else if (p == 3)
for (a=ONE, z[1]=X[1]; z[1] < TWO23; ) c = X[1] + R * (X[2] + R * X[3]);
{a *= TWO; z[1] *= TWO; } else if (p == 4)
c = (X[1] + R * X[2]) + R * R * (X[3] + R * X[4]);
for (i=2; i<5; i++) {
z[i] = X[i]*a;
u = (z[i] + CUTTER)-CUTTER;
if (u > z[i]) u -= RADIX;
z[i] -= u;
z[i-1] += u*RADIXI;
} }
else
u = (z[3] + TWO71) - TWO71; {
if (u > z[3]) u -= TWO19; for (a = ONE, z[1] = X[1]; z[1] < TWO23;)
v = z[3]-u; {
a *= TWO;
if (v == TWO18) { z[1] *= TWO;
if (z[4] == ZERO) {
for (i=5; i <= p; i++) {
if (X[i] == ZERO) continue;
else {z[3] += ONE; break; }
} }
}
else z[3] += ONE;
}
c = (z[1] + R *(z[2] + R * z[3]))/a; for (i = 2; i < 5; i++)
} {
z[i] = X[i] * a;
u = (z[i] + CUTTER) - CUTTER;
if (u > z[i])
u -= RADIX;
z[i] -= u;
z[i - 1] += u * RADIXI;
}
u = (z[3] + TWO71) - TWO71;
if (u > z[3])
u -= TWO19;
v = z[3] - u;
if (v == TWO18)
{
if (z[4] == ZERO)
{
for (i = 5; i <= p; i++)
{
if (X[i] == ZERO)
continue;
else
{
z[3] += ONE;
break;
}
}
}
else
z[3] += ONE;
}
c = (z[1] + R * (z[2] + R * z[3])) / a;
}
c *= X[0]; c *= X[0];
for (i=1; i<EX; i++) c *= RADIX; for (i = 1; i < EX; i++)
for (i=1; i>EX; i--) c *= RADIXI; c *= RADIX;
for (i = 1; i > EX; i--)
c *= RADIXI;
*y = c; *y = c;
#undef R #undef R
@ -152,58 +194,129 @@ static void norm(const mp_no *x, double *y, int p)
/* Convert a multiple precision number *X into a double precision /* Convert a multiple precision number *X into a double precision
number *Y, Denormal case (|x| < 2**(-1022))). */ number *Y, Denormal case (|x| < 2**(-1022))). */
static void denorm(const mp_no *x, double *y, int p) static void
denorm (const mp_no *x, double *y, int p)
{ {
int i,k; int i, k;
double c,u,z[5]; double c, u, z[5];
#define R RADIXI #define R RADIXI
if (EX<-44 || (EX==-44 && X[1]<TWO5)) if (EX < -44 || (EX == -44 && X[1] < TWO5))
{ *y=ZERO; return; } {
*y = ZERO;
return;
}
if (p==1) { if (p == 1)
if (EX==-42) {z[1]=X[1]+TWO10; z[2]=ZERO; z[3]=ZERO; k=3;} {
else if (EX==-43) {z[1]= TWO10; z[2]=X[1]; z[3]=ZERO; k=2;} if (EX == -42)
else {z[1]= TWO10; z[2]=ZERO; z[3]=X[1]; k=1;} {
} z[1] = X[1] + TWO10;
else if (p==2) { z[2] = ZERO;
if (EX==-42) {z[1]=X[1]+TWO10; z[2]=X[2]; z[3]=ZERO; k=3;} z[3] = ZERO;
else if (EX==-43) {z[1]= TWO10; z[2]=X[1]; z[3]=X[2]; k=2;} k = 3;
else {z[1]= TWO10; z[2]=ZERO; z[3]=X[1]; k=1;} }
} else if (EX == -43)
else { {
if (EX==-42) {z[1]=X[1]+TWO10; z[2]=X[2]; k=3;} z[1] = TWO10;
else if (EX==-43) {z[1]= TWO10; z[2]=X[1]; k=2;} z[2] = X[1];
else {z[1]= TWO10; z[2]=ZERO; k=1;} z[3] = ZERO;
z[3] = X[k]; k = 2;
} }
else
{
z[1] = TWO10;
z[2] = ZERO;
z[3] = X[1];
k = 1;
}
}
else if (p == 2)
{
if (EX == -42)
{
z[1] = X[1] + TWO10;
z[2] = X[2];
z[3] = ZERO;
k = 3;
}
else if (EX == -43)
{
z[1] = TWO10;
z[2] = X[1];
z[3] = X[2];
k = 2;
}
else
{
z[1] = TWO10;
z[2] = ZERO;
z[3] = X[1];
k = 1;
}
}
else
{
if (EX == -42)
{
z[1] = X[1] + TWO10;
z[2] = X[2];
k = 3;
}
else if (EX == -43)
{
z[1] = TWO10;
z[2] = X[1];
k = 2;
}
else
{
z[1] = TWO10;
z[2] = ZERO;
k = 1;
}
z[3] = X[k];
}
u = (z[3] + TWO57) - TWO57; u = (z[3] + TWO57) - TWO57;
if (u > z[3]) u -= TWO5; if (u > z[3])
u -= TWO5;
if (u==z[3]) { if (u == z[3])
for (i=k+1; i <= p; i++) { {
if (X[i] == ZERO) continue; for (i = k + 1; i <= p; i++)
else {z[3] += ONE; break; } {
if (X[i] == ZERO)
continue;
else
{
z[3] += ONE;
break;
}
}
} }
}
c = X[0]*((z[1] + R*(z[2] + R*z[3])) - TWO10); c = X[0] * ((z[1] + R * (z[2] + R * z[3])) - TWO10);
*y = c*TWOM1032; *y = c * TWOM1032;
#undef R #undef R
} }
/* Convert multiple precision number *X into double precision number *Y. The /* Convert multiple precision number *X into double precision number *Y. The
result is correctly rounded to the nearest/even. */ result is correctly rounded to the nearest/even. */
void __mp_dbl(const mp_no *x, double *y, int p) { void
__mp_dbl (const mp_no *x, double *y, int p)
if (X[0] == ZERO) {*y = ZERO; return; } {
if (X[0] == ZERO)
{
*y = ZERO;
return;
}
if (__glibc_likely (EX > -42 || (EX == -42 && X[1] >= TWO10))) if (__glibc_likely (EX > -42 || (EX == -42 && X[1] >= TWO10)))
norm(x,y,p); norm (x, y, p);
else else
denorm(x,y,p); denorm (x, y, p);
} }
#endif #endif
@ -211,27 +324,44 @@ void __mp_dbl(const mp_no *x, double *y, int p) {
small, the result is truncated. */ small, the result is truncated. */
void void
SECTION SECTION
__dbl_mp(double x, mp_no *y, int p) { __dbl_mp (double x, mp_no *y, int p)
{
int i,n; int i, n;
double u; double u;
/* Sign. */ /* Sign. */
if (x == ZERO) {Y[0] = ZERO; return; } if (x == ZERO)
else if (x > ZERO) Y[0] = ONE; {
else {Y[0] = MONE; x=-x; } Y[0] = ZERO;
return;
}
else if (x > ZERO)
Y[0] = ONE;
else
{
Y[0] = MONE;
x = -x;
}
/* Exponent. */ /* Exponent. */
for (EY=ONE; x >= RADIX; EY += ONE) x *= RADIXI; for (EY = ONE; x >= RADIX; EY += ONE)
for ( ; x < ONE; EY -= ONE) x *= RADIX; x *= RADIXI;
for (; x < ONE; EY -= ONE)
x *= RADIX;
/* Digits. */ /* Digits. */
n=MIN(p,4); n = MIN (p, 4);
for (i=1; i<=n; i++) { for (i = 1; i <= n; i++)
u = (x + TWO52) - TWO52; {
if (u>x) u -= ONE; u = (x + TWO52) - TWO52;
Y[i] = u; x -= u; x *= RADIX; } if (u > x)
for ( ; i<=p; i++) Y[i] = ZERO; u -= ONE;
Y[i] = u;
x -= u;
x *= RADIX;
}
for (; i <= p; i++)
Y[i] = ZERO;
} }
/* Add magnitudes of *X and *Y assuming that abs (*X) >= abs (*Y) > 0. The /* Add magnitudes of *X and *Y assuming that abs (*X) >= abs (*Y) > 0. The
@ -240,39 +370,55 @@ __dbl_mp(double x, mp_no *y, int p) {
truncated. */ truncated. */
static void static void
SECTION SECTION
add_magnitudes(const mp_no *x, const mp_no *y, mp_no *z, int p) { add_magnitudes (const mp_no *x, const mp_no *y, mp_no *z, int p)
{
int i,j,k; int i, j, k;
EZ = EX; EZ = EX;
i=p; j=p+ EY - EX; k=p+1; i = p;
j = p + EY - EX;
k = p + 1;
if (j<1) if (j < 1)
{__cpy(x,z,p); return; } {
else Z[k] = ZERO; __cpy (x, z, p);
return;
}
else
Z[k] = ZERO;
for (; j>0; i--,j--) { for (; j > 0; i--, j--)
Z[k] += X[i] + Y[j]; {
if (Z[k] >= RADIX) { Z[k] += X[i] + Y[j];
Z[k] -= RADIX; if (Z[k] >= RADIX)
Z[--k] = ONE; } {
else Z[k] -= RADIX;
Z[--k] = ZERO; Z[--k] = ONE;
} }
else
Z[--k] = ZERO;
}
for (; i>0; i--) { for (; i > 0; i--)
Z[k] += X[i]; {
if (Z[k] >= RADIX) { Z[k] += X[i];
Z[k] -= RADIX; if (Z[k] >= RADIX)
Z[--k] = ONE; } {
else Z[k] -= RADIX;
Z[--k] = ZERO; Z[--k] = ONE;
} }
else
Z[--k] = ZERO;
}
if (Z[1] == ZERO) { if (Z[1] == ZERO)
for (i=1; i<=p; i++) Z[i] = Z[i+1]; } {
else EZ += ONE; for (i = 1; i <= p; i++)
Z[i] = Z[i + 1];
}
else
EZ += ONE;
} }
/* Subtract the magnitudes of *X and *Y assuming that abs (*x) > abs (*y) > 0. /* Subtract the magnitudes of *X and *Y assuming that abs (*x) > abs (*y) > 0.
@ -281,52 +427,73 @@ add_magnitudes(const mp_no *x, const mp_no *y, mp_no *z, int p) {
ULP. */ ULP. */
static void static void
SECTION SECTION
sub_magnitudes(const mp_no *x, const mp_no *y, mp_no *z, int p) { sub_magnitudes (const mp_no *x, const mp_no *y, mp_no *z, int p)
{
int i,j,k; int i, j, k;
EZ = EX; EZ = EX;
if (EX == EY) { if (EX == EY)
i=j=k=p; {
Z[k] = Z[k+1] = ZERO; } i = j = k = p;
else { Z[k] = Z[k + 1] = ZERO;
j= EX - EY; }
if (j > p) {__cpy(x,z,p); return; } else
else { {
i=p; j=p+1-j; k=p; j = EX - EY;
if (Y[j] > ZERO) { if (j > p)
Z[k+1] = RADIX - Y[j--]; {
Z[k] = MONE; } __cpy (x, z, p);
else { return;
Z[k+1] = ZERO; }
Z[k] = ZERO; j--;} else
{
i = p;
j = p + 1 - j;
k = p;
if (Y[j] > ZERO)
{
Z[k + 1] = RADIX - Y[j--];
Z[k] = MONE;
}
else
{
Z[k + 1] = ZERO;
Z[k] = ZERO;
j--;
}
}
} }
}
for (; j>0; i--,j--) { for (; j > 0; i--, j--)
Z[k] += (X[i] - Y[j]); {
if (Z[k] < ZERO) { Z[k] += (X[i] - Y[j]);
Z[k] += RADIX; if (Z[k] < ZERO)
Z[--k] = MONE; } {
else Z[k] += RADIX;
Z[--k] = ZERO; Z[--k] = MONE;
} }
else
Z[--k] = ZERO;
}
for (; i>0; i--) { for (; i > 0; i--)
Z[k] += X[i]; {
if (Z[k] < ZERO) { Z[k] += X[i];
Z[k] += RADIX; if (Z[k] < ZERO)
Z[--k] = MONE; } {
else Z[k] += RADIX;
Z[--k] = ZERO; Z[--k] = MONE;
} }
else
Z[--k] = ZERO;
}
for (i=1; Z[i] == ZERO; i++) ; for (i = 1; Z[i] == ZERO; i++);
EZ = EZ - i + 1; EZ = EZ - i + 1;
for (k=1; i <= p+1; ) for (k = 1; i <= p + 1;)
Z[k++] = Z[i++]; Z[k++] = Z[i++];
for (; k <= p; ) for (; k <= p;)
Z[k++] = ZERO; Z[k++] = ZERO;
} }
@ -335,22 +502,49 @@ sub_magnitudes(const mp_no *x, const mp_no *y, mp_no *z, int p) {
ULP. */ ULP. */
void void
SECTION SECTION
__add(const mp_no *x, const mp_no *y, mp_no *z, int p) { __add (const mp_no *x, const mp_no *y, mp_no *z, int p)
{
int n; int n;
if (X[0] == ZERO) {__cpy(y,z,p); return; } if (X[0] == ZERO)
else if (Y[0] == ZERO) {__cpy(x,z,p); return; } {
__cpy (y, z, p);
return;
}
else if (Y[0] == ZERO)
{
__cpy (x, z, p);
return;
}
if (X[0] == Y[0]) { if (X[0] == Y[0])
if (__acr(x,y,p) > 0) {add_magnitudes(x,y,z,p); Z[0] = X[0]; } {
else {add_magnitudes(y,x,z,p); Z[0] = Y[0]; } if (__acr (x, y, p) > 0)
} {
else { add_magnitudes (x, y, z, p);
if ((n=__acr(x,y,p)) == 1) {sub_magnitudes(x,y,z,p); Z[0] = X[0]; } Z[0] = X[0];
else if (n == -1) {sub_magnitudes(y,x,z,p); Z[0] = Y[0]; } }
else Z[0] = ZERO; else
} {
add_magnitudes (y, x, z, p);
Z[0] = Y[0];
}
}
else
{
if ((n = __acr (x, y, p)) == 1)
{
sub_magnitudes (x, y, z, p);
Z[0] = X[0];
}
else if (n == -1)
{
sub_magnitudes (y, x, z, p);
Z[0] = Y[0];
}
else
Z[0] = ZERO;
}
} }
/* Subtract *Y from *X and return the result in *Z. X and Y may overlap but /* Subtract *Y from *X and return the result in *Z. X and Y may overlap but
@ -358,22 +552,50 @@ __add(const mp_no *x, const mp_no *y, mp_no *z, int p) {
one ULP. */ one ULP. */
void void
SECTION SECTION
__sub(const mp_no *x, const mp_no *y, mp_no *z, int p) { __sub (const mp_no *x, const mp_no *y, mp_no *z, int p)
{
int n; int n;
if (X[0] == ZERO) {__cpy(y,z,p); Z[0] = -Z[0]; return; } if (X[0] == ZERO)
else if (Y[0] == ZERO) {__cpy(x,z,p); return; } {
__cpy (y, z, p);
Z[0] = -Z[0];
return;
}
else if (Y[0] == ZERO)
{
__cpy (x, z, p);
return;
}
if (X[0] != Y[0]) { if (X[0] != Y[0])
if (__acr(x,y,p) > 0) {add_magnitudes(x,y,z,p); Z[0] = X[0]; } {
else {add_magnitudes(y,x,z,p); Z[0] = -Y[0]; } if (__acr (x, y, p) > 0)
} {
else { add_magnitudes (x, y, z, p);
if ((n=__acr(x,y,p)) == 1) {sub_magnitudes(x,y,z,p); Z[0] = X[0]; } Z[0] = X[0];
else if (n == -1) {sub_magnitudes(y,x,z,p); Z[0] = -Y[0]; } }
else Z[0] = ZERO; else
} {
add_magnitudes (y, x, z, p);
Z[0] = -Y[0];
}
}
else
{
if ((n = __acr (x, y, p)) == 1)
{
sub_magnitudes (x, y, z, p);
Z[0] = X[0];
}
else if (n == -1)
{
sub_magnitudes (y, x, z, p);
Z[0] = -Y[0];
}
else
Z[0] = ZERO;
}
} }
/* Multiply *X and *Y and store result in *Z. X and Y may overlap but not X /* Multiply *X and *Y and store result in *Z. X and Y may overlap but not X
@ -381,15 +603,15 @@ __sub(const mp_no *x, const mp_no *y, mp_no *z, int p) {
digits. In case P > 3 the error is bounded by 1.001 ULP. */ digits. In case P > 3 the error is bounded by 1.001 ULP. */
void void
SECTION SECTION
__mul(const mp_no *x, const mp_no *y, mp_no *z, int p) { __mul (const mp_no *x, const mp_no *y, mp_no *z, int p)
{
int i, j, k, k2; int i, j, k, k2;
double u; double u;
/* Is z=0? */ /* Is z=0? */
if (__glibc_unlikely (X[0] * Y[0] == ZERO)) if (__glibc_unlikely (X[0] * Y[0] == ZERO))
{ {
Z[0]=ZERO; Z[0] = ZERO;
return; return;
} }
@ -397,7 +619,7 @@ __mul(const mp_no *x, const mp_no *y, mp_no *z, int p) {
k2 = (__glibc_unlikely (p < 3)) ? p + p : p + 3; k2 = (__glibc_unlikely (p < 3)) ? p + p : p + 3;
Z[k2] = ZERO; Z[k2] = ZERO;
for (k = k2; k > p; ) for (k = k2; k > p;)
{ {
for (i = k - p, j = p; i < p + 1; i++, j--) for (i = k - p, j = p; i < p + 1; i++, j--)
Z[k] += X[i] * Y[j]; Z[k] += X[i] * Y[j];
@ -411,7 +633,7 @@ __mul(const mp_no *x, const mp_no *y, mp_no *z, int p) {
while (k > 1) while (k > 1)
{ {
for (i = 1,j = k - 1; i < k; i++, j--) for (i = 1, j = k - 1; i < k; i++, j--)
Z[k] += X[i] * Y[j]; Z[k] += X[i] * Y[j];
u = (Z[k] + CUTTER) - CUTTER; u = (Z[k] + CUTTER) - CUTTER;
@ -426,7 +648,7 @@ __mul(const mp_no *x, const mp_no *y, mp_no *z, int p) {
if (__glibc_unlikely (Z[1] == ZERO)) if (__glibc_unlikely (Z[1] == ZERO))
{ {
for (i = 1; i <= p; i++) for (i = 1; i <= p; i++)
Z[i] = Z[i+1]; Z[i] = Z[i + 1];
EZ--; EZ--;
} }
@ -439,24 +661,32 @@ __mul(const mp_no *x, const mp_no *y, mp_no *z, int p) {
- For P > 3: 2.001 * R ^ (1 - P) - For P > 3: 2.001 * R ^ (1 - P)
*X = 0 is not permissible. */ *X = 0 is not permissible. */
static static void
SECTION SECTION
void __inv(const mp_no *x, mp_no *y, int p) { __inv (const mp_no *x, mp_no *y, int p)
{
int i; int i;
double t; double t;
mp_no z,w; mp_no z, w;
static const int np1[] = {0,0,0,0,1,2,2,2,2,3,3,3,3,3,3,3,3,3, static const int np1[] =
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4}; { 0, 0, 0, 0, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
};
__cpy(x,&z,p); z.e=0; __mp_dbl(&z,&t,p); __cpy (x, &z, p);
t=ONE/t; __dbl_mp(t,y,p); EY -= EX; z.e = 0;
__mp_dbl (&z, &t, p);
t = ONE / t;
__dbl_mp (t, y, p);
EY -= EX;
for (i=0; i<np1[p]; i++) { for (i = 0; i < np1[p]; i++)
__cpy(y,&w,p); {
__mul(x,&w,y,p); __cpy (y, &w, p);
__sub(&mptwo,y,&z,p); __mul (x, &w, y, p);
__mul(&w,&z,y,p); __sub (&mptwo, y, &z, p);
} __mul (&w, &z, y, p);
}
} }
/* Divide *X by *Y and store result in *Z. X and Y may overlap but not X and Z /* Divide *X by *Y and store result in *Z. X and Y may overlap but not X and Z
@ -468,10 +698,15 @@ void __inv(const mp_no *x, mp_no *y, int p) {
*X = 0 is not permissible. */ *X = 0 is not permissible. */
void void
SECTION SECTION
__dvd(const mp_no *x, const mp_no *y, mp_no *z, int p) { __dvd (const mp_no *x, const mp_no *y, mp_no *z, int p)
{
mp_no w; mp_no w;
if (X[0] == ZERO) Z[0] = ZERO; if (X[0] == ZERO)
else {__inv(y,&w,p); __mul(x,&w,z,p);} Z[0] = ZERO;
else
{
__inv (y, &w, p);
__mul (x, &w, z, p);
}
} }

View File

@ -51,91 +51,135 @@ const mp_no mptwo = {1, {1.0, 2.0}};
/* Compare mantissa of two multiple precision numbers regardless of the sign /* Compare mantissa of two multiple precision numbers regardless of the sign
and exponent of the numbers. */ and exponent of the numbers. */
static int mcr(const mp_no *x, const mp_no *y, int p) { static int
mcr (const mp_no *x, const mp_no *y, int p)
{
long i; long i;
long p2 = p; long p2 = p;
for (i=1; i<=p2; i++) { for (i = 1; i <= p2; i++)
if (X[i] == Y[i]) continue; {
else if (X[i] > Y[i]) return 1; if (X[i] == Y[i])
else return -1; } continue;
else if (X[i] > Y[i])
return 1;
else
return -1;
}
return 0; return 0;
} }
/* Compare the absolute values of two multiple precision numbers. */ /* Compare the absolute values of two multiple precision numbers. */
int __acr(const mp_no *x, const mp_no *y, int p) { int
__acr (const mp_no *x, const mp_no *y, int p)
{
long i; long i;
if (X[0] == ZERO) { if (X[0] == ZERO)
if (Y[0] == ZERO) i= 0; {
else i=-1; if (Y[0] == ZERO)
} i = 0;
else if (Y[0] == ZERO) i= 1; else
else { i = -1;
if (EX > EY) i= 1; }
else if (EX < EY) i=-1; else if (Y[0] == ZERO)
else i= mcr(x,y,p); i = 1;
} else
{
if (EX > EY)
i = 1;
else if (EX < EY)
i = -1;
else
i = mcr (x, y, p);
}
return i; return i;
} }
/* Copy multiple precision number X into Y. They could be the same /* Copy multiple precision number X into Y. They could be the same
number. */ number. */
void __cpy(const mp_no *x, mp_no *y, int p) { void
__cpy (const mp_no *x, mp_no *y, int p)
{
long i; long i;
EY = EX; EY = EX;
for (i=0; i <= p; i++) Y[i] = X[i]; for (i = 0; i <= p; i++)
Y[i] = X[i];
return; return;
} }
/* Convert a multiple precision number *X into a double precision /* Convert a multiple precision number *X into a double precision
number *Y, normalized case (|x| >= 2**(-1022))). */ number *Y, normalized case (|x| >= 2**(-1022))). */
static void norm(const mp_no *x, double *y, int p) static void
norm (const mp_no *x, double *y, int p)
{ {
#define R RADIXI #define R RADIXI
long i; long i;
double a,c,u,v,z[5]; double a, c, u, v, z[5];
if (p<5) { if (p < 5)
if (p==1) c = X[1]; {
else if (p==2) c = X[1] + R* X[2]; if (p == 1)
else if (p==3) c = X[1] + R*(X[2] + R* X[3]); c = X[1];
else if (p==4) c =(X[1] + R* X[2]) + R*R*(X[3] + R*X[4]); else if (p == 2)
} c = X[1] + R * X[2];
else { else if (p == 3)
for (a=ONE, z[1]=X[1]; z[1] < TWO23; ) c = X[1] + R * (X[2] + R * X[3]);
{a *= TWO; z[1] *= TWO; } else if (p == 4)
c = (X[1] + R * X[2]) + R * R * (X[3] + R * X[4]);
for (i=2; i<5; i++) {
z[i] = X[i]*a;
u = (z[i] + CUTTER)-CUTTER;
if (u > z[i]) u -= RADIX;
z[i] -= u;
z[i-1] += u*RADIXI;
} }
else
{
for (a = ONE, z[1] = X[1]; z[1] < TWO23;)
{
a *= TWO;
z[1] *= TWO;
}
u = (z[3] + TWO71) - TWO71; for (i = 2; i < 5; i++)
if (u > z[3]) u -= TWO19; {
v = z[3]-u; z[i] = X[i] * a;
u = (z[i] + CUTTER) - CUTTER;
if (u > z[i])
u -= RADIX;
z[i] -= u;
z[i - 1] += u * RADIXI;
}
if (v == TWO18) { u = (z[3] + TWO71) - TWO71;
if (z[4] == ZERO) { if (u > z[3])
for (i=5; i <= p; i++) { u -= TWO19;
if (X[i] == ZERO) continue; v = z[3] - u;
else {z[3] += ONE; break; }
} if (v == TWO18)
} {
else z[3] += ONE; if (z[4] == ZERO)
{
for (i = 5; i <= p; i++)
{
if (X[i] == ZERO)
continue;
else
{
z[3] += ONE;
break;
}
}
}
else
z[3] += ONE;
}
c = (z[1] + R * (z[2] + R * z[3])) / a;
} }
c = (z[1] + R *(z[2] + R * z[3]))/a;
}
c *= X[0]; c *= X[0];
for (i=1; i<EX; i++) c *= RADIX; for (i = 1; i < EX; i++)
for (i=1; i>EX; i--) c *= RADIXI; c *= RADIX;
for (i = 1; i > EX; i--)
c *= RADIXI;
*y = c; *y = c;
return; return;
@ -144,46 +188,112 @@ static void norm(const mp_no *x, double *y, int p)
/* Convert a multiple precision number *X into a double precision /* Convert a multiple precision number *X into a double precision
number *Y, Denormal case (|x| < 2**(-1022))). */ number *Y, Denormal case (|x| < 2**(-1022))). */
static void denorm(const mp_no *x, double *y, int p) static void
denorm (const mp_no *x, double *y, int p)
{ {
long i,k; long i, k;
long p2 = p; long p2 = p;
double c,u,z[5]; double c, u, z[5];
#define R RADIXI #define R RADIXI
if (EX<-44 || (EX==-44 && X[1]<TWO5)) if (EX < -44 || (EX == -44 && X[1] < TWO5))
{ *y=ZERO; return; } {
*y = ZERO;
return;
}
if (p2==1) { if (p2 == 1)
if (EX==-42) {z[1]=X[1]+TWO10; z[2]=ZERO; z[3]=ZERO; k=3;} {
else if (EX==-43) {z[1]= TWO10; z[2]=X[1]; z[3]=ZERO; k=2;} if (EX == -42)
else {z[1]= TWO10; z[2]=ZERO; z[3]=X[1]; k=1;} {
} z[1] = X[1] + TWO10;
else if (p2==2) { z[2] = ZERO;
if (EX==-42) {z[1]=X[1]+TWO10; z[2]=X[2]; z[3]=ZERO; k=3;} z[3] = ZERO;
else if (EX==-43) {z[1]= TWO10; z[2]=X[1]; z[3]=X[2]; k=2;} k = 3;
else {z[1]= TWO10; z[2]=ZERO; z[3]=X[1]; k=1;} }
} else if (EX == -43)
else { {
if (EX==-42) {z[1]=X[1]+TWO10; z[2]=X[2]; k=3;} z[1] = TWO10;
else if (EX==-43) {z[1]= TWO10; z[2]=X[1]; k=2;} z[2] = X[1];
else {z[1]= TWO10; z[2]=ZERO; k=1;} z[3] = ZERO;
z[3] = X[k]; k = 2;
} }
else
{
z[1] = TWO10;
z[2] = ZERO;
z[3] = X[1];
k = 1;
}
}
else if (p2 == 2)
{
if (EX == -42)
{
z[1] = X[1] + TWO10;
z[2] = X[2];
z[3] = ZERO;
k = 3;
}
else if (EX == -43)
{
z[1] = TWO10;
z[2] = X[1];
z[3] = X[2];
k = 2;
}
else
{
z[1] = TWO10;
z[2] = ZERO;
z[3] = X[1];
k = 1;
}
}
else
{
if (EX == -42)
{
z[1] = X[1] + TWO10;
z[2] = X[2];
k = 3;
}
else if (EX == -43)
{
z[1] = TWO10;
z[2] = X[1];
k = 2;
}
else
{
z[1] = TWO10;
z[2] = ZERO;
k = 1;
}
z[3] = X[k];
}
u = (z[3] + TWO57) - TWO57; u = (z[3] + TWO57) - TWO57;
if (u > z[3]) u -= TWO5; if (u > z[3])
u -= TWO5;
if (u==z[3]) { if (u == z[3])
for (i=k+1; i <= p2; i++) { {
if (X[i] == ZERO) continue; for (i = k + 1; i <= p2; i++)
else {z[3] += ONE; break; } {
if (X[i] == ZERO)
continue;
else
{
z[3] += ONE;
break;
}
}
} }
}
c = X[0]*((z[1] + R*(z[2] + R*z[3])) - TWO10); c = X[0] * ((z[1] + R * (z[2] + R * z[3])) - TWO10);
*y = c*TWOM1032; *y = c * TWOM1032;
return; return;
#undef R #undef R
@ -191,39 +301,65 @@ static void denorm(const mp_no *x, double *y, int p)
/* Convert multiple precision number *X into double precision number *Y. The /* Convert multiple precision number *X into double precision number *Y. The
result is correctly rounded to the nearest/even. */ result is correctly rounded to the nearest/even. */
void __mp_dbl(const mp_no *x, double *y, int p) { void
__mp_dbl (const mp_no *x, double *y, int p)
{
if (X[0] == ZERO)
{
*y = ZERO;
return;
}
if (X[0] == ZERO) {*y = ZERO; return; } if (EX > -42)
norm (x, y, p);
if (EX> -42) norm(x,y,p); else if (EX == -42 && X[1] >= TWO10)
else if (EX==-42 && X[1]>=TWO10) norm(x,y,p); norm (x, y, p);
else denorm(x,y,p); else
denorm (x, y, p);
} }
/* Get the multiple precision equivalent of X into *Y. If the precision is too /* Get the multiple precision equivalent of X into *Y. If the precision is too
small, the result is truncated. */ small, the result is truncated. */
void __dbl_mp(double x, mp_no *y, int p) { void
__dbl_mp (double x, mp_no *y, int p)
long i,n; {
long i, n;
long p2 = p; long p2 = p;
double u; double u;
/* Sign. */ /* Sign. */
if (x == ZERO) {Y[0] = ZERO; return; } if (x == ZERO)
else if (x > ZERO) Y[0] = ONE; {
else {Y[0] = MONE; x=-x; } Y[0] = ZERO;
return;
}
else if (x > ZERO)
Y[0] = ONE;
else
{
Y[0] = MONE;
x = -x;
}
/* Exponent. */ /* Exponent. */
for (EY=ONE; x >= RADIX; EY += ONE) x *= RADIXI; for (EY = ONE; x >= RADIX; EY += ONE)
for ( ; x < ONE; EY -= ONE) x *= RADIX; x *= RADIXI;
for (; x < ONE; EY -= ONE)
x *= RADIX;
/* Digits. */ /* Digits. */
n=MIN(p2,4); n = MIN (p2, 4);
for (i=1; i<=n; i++) { for (i = 1; i <= n; i++)
u = (x + TWO52) - TWO52; {
if (u>x) u -= ONE; u = (x + TWO52) - TWO52;
Y[i] = u; x -= u; x *= RADIX; } if (u > x)
for ( ; i<=p2; i++) Y[i] = ZERO; u -= ONE;
Y[i] = u;
x -= u;
x *= RADIX;
}
for (; i <= p2; i++)
Y[i] = ZERO;
return; return;
} }
@ -231,93 +367,132 @@ void __dbl_mp(double x, mp_no *y, int p) {
sign of the sum *Z is not changed. X and Y may overlap but not X and Z or sign of the sum *Z is not changed. X and Y may overlap but not X and Z or
Y and Z. No guard digit is used. The result equals the exact sum, Y and Z. No guard digit is used. The result equals the exact sum,
truncated. */ truncated. */
static void add_magnitudes(const mp_no *x, const mp_no *y, mp_no *z, int p) { static void
add_magnitudes (const mp_no *x, const mp_no *y, mp_no *z, int p)
long i,j,k; {
long i, j, k;
long p2 = p; long p2 = p;
EZ = EX; EZ = EX;
i=p2; j=p2+ EY - EX; k=p2+1; i = p2;
j = p2 + EY - EX;
k = p2 + 1;
if (j<1) if (j < 1)
{__cpy(x,z,p); return; } {
else Z[k] = ZERO; __cpy (x, z, p);
return;
}
else
Z[k] = ZERO;
for (; j>0; i--,j--) { for (; j > 0; i--, j--)
Z[k] += X[i] + Y[j]; {
if (Z[k] >= RADIX) { Z[k] += X[i] + Y[j];
Z[k] -= RADIX; if (Z[k] >= RADIX)
Z[--k] = ONE; } {
else Z[k] -= RADIX;
Z[--k] = ZERO; Z[--k] = ONE;
} }
else
Z[--k] = ZERO;
}
for (; i>0; i--) { for (; i > 0; i--)
Z[k] += X[i]; {
if (Z[k] >= RADIX) { Z[k] += X[i];
Z[k] -= RADIX; if (Z[k] >= RADIX)
Z[--k] = ONE; } {
else Z[k] -= RADIX;
Z[--k] = ZERO; Z[--k] = ONE;
} }
else
Z[--k] = ZERO;
}
if (Z[1] == ZERO) { if (Z[1] == ZERO)
for (i=1; i<=p2; i++) Z[i] = Z[i+1]; } {
else EZ += ONE; for (i = 1; i <= p2; i++)
Z[i] = Z[i + 1];
}
else
EZ += ONE;
} }
/* Subtract the magnitudes of *X and *Y assuming that abs (*x) > abs (*y) > 0. /* Subtract the magnitudes of *X and *Y assuming that abs (*x) > abs (*y) > 0.
The sign of the difference *Z is not changed. X and Y may overlap but not X The sign of the difference *Z is not changed. X and Y may overlap but not X
and Z or Y and Z. One guard digit is used. The error is less than one and Z or Y and Z. One guard digit is used. The error is less than one
ULP. */ ULP. */
static void sub_magnitudes(const mp_no *x, const mp_no *y, mp_no *z, int p) { static void
sub_magnitudes (const mp_no *x, const mp_no *y, mp_no *z, int p)
long i,j,k; {
long i, j, k;
long p2 = p; long p2 = p;
EZ = EX; EZ = EX;
if (EX == EY) { if (EX == EY)
i=j=k=p2; {
Z[k] = Z[k+1] = ZERO; } i = j = k = p2;
else { Z[k] = Z[k + 1] = ZERO;
j= EX - EY; }
if (j > p2) {__cpy(x,z,p); return; } else
else { {
i=p2; j=p2+1-j; k=p2; j = EX - EY;
if (Y[j] > ZERO) { if (j > p2)
Z[k+1] = RADIX - Y[j--]; {
Z[k] = MONE; } __cpy (x, z, p);
else { return;
Z[k+1] = ZERO; }
Z[k] = ZERO; j--;} else
{
i = p2;
j = p2 + 1 - j;
k = p2;
if (Y[j] > ZERO)
{
Z[k + 1] = RADIX - Y[j--];
Z[k] = MONE;
}
else
{
Z[k + 1] = ZERO;
Z[k] = ZERO;
j--;
}
}
} }
}
for (; j>0; i--,j--) { for (; j > 0; i--, j--)
Z[k] += (X[i] - Y[j]); {
if (Z[k] < ZERO) { Z[k] += (X[i] - Y[j]);
Z[k] += RADIX; if (Z[k] < ZERO)
Z[--k] = MONE; } {
else Z[k] += RADIX;
Z[--k] = ZERO; Z[--k] = MONE;
} }
else
Z[--k] = ZERO;
}
for (; i>0; i--) { for (; i > 0; i--)
Z[k] += X[i]; {
if (Z[k] < ZERO) { Z[k] += X[i];
Z[k] += RADIX; if (Z[k] < ZERO)
Z[--k] = MONE; } {
else Z[k] += RADIX;
Z[--k] = ZERO; Z[--k] = MONE;
} }
else
Z[--k] = ZERO;
}
for (i=1; Z[i] == ZERO; i++) ; for (i = 1; Z[i] == ZERO; i++);
EZ = EZ - i + 1; EZ = EZ - i + 1;
for (k=1; i <= p2+1; ) for (k = 1; i <= p2 + 1;)
Z[k++] = Z[i++]; Z[k++] = Z[i++];
for (; k <= p2; ) for (; k <= p2;)
Z[k++] = ZERO; Z[k++] = ZERO;
return; return;
@ -326,111 +501,186 @@ static void sub_magnitudes(const mp_no *x, const mp_no *y, mp_no *z, int p) {
/* Add *X and *Y and store the result in *Z. X and Y may overlap, but not X /* Add *X and *Y and store the result in *Z. X and Y may overlap, but not X
and Z or Y and Z. One guard digit is used. The error is less than one and Z or Y and Z. One guard digit is used. The error is less than one
ULP. */ ULP. */
void __add(const mp_no *x, const mp_no *y, mp_no *z, int p) { void
__add (const mp_no *x, const mp_no *y, mp_no *z, int p)
{
int n; int n;
if (X[0] == ZERO) {__cpy(y,z,p); return; } if (X[0] == ZERO)
else if (Y[0] == ZERO) {__cpy(x,z,p); return; } {
__cpy (y, z, p);
return;
}
else if (Y[0] == ZERO)
{
__cpy (x, z, p);
return;
}
if (X[0] == Y[0]) { if (X[0] == Y[0])
if (__acr(x,y,p) > 0) {add_magnitudes(x,y,z,p); Z[0] = X[0]; } {
else {add_magnitudes(y,x,z,p); Z[0] = Y[0]; } if (__acr (x, y, p) > 0)
} {
else { add_magnitudes (x, y, z, p);
if ((n=__acr(x,y,p)) == 1) {sub_magnitudes(x,y,z,p); Z[0] = X[0]; } Z[0] = X[0];
else if (n == -1) {sub_magnitudes(y,x,z,p); Z[0] = Y[0]; } }
else Z[0] = ZERO; else
} {
add_magnitudes (y, x, z, p);
Z[0] = Y[0];
}
}
else
{
if ((n = __acr (x, y, p)) == 1)
{
sub_magnitudes (x, y, z, p);
Z[0] = X[0];
}
else if (n == -1)
{
sub_magnitudes (y, x, z, p);
Z[0] = Y[0];
}
else
Z[0] = ZERO;
}
return; return;
} }
/* Subtract *Y from *X and return the result in *Z. X and Y may overlap but /* Subtract *Y from *X and return the result in *Z. X and Y may overlap but
not X and Z or Y and Z. One guard digit is used. The error is less than not X and Z or Y and Z. One guard digit is used. The error is less than
one ULP. */ one ULP. */
void __sub(const mp_no *x, const mp_no *y, mp_no *z, int p) { void
__sub (const mp_no *x, const mp_no *y, mp_no *z, int p)
{
int n; int n;
if (X[0] == ZERO) {__cpy(y,z,p); Z[0] = -Z[0]; return; } if (X[0] == ZERO)
else if (Y[0] == ZERO) {__cpy(x,z,p); return; } {
__cpy (y, z, p);
Z[0] = -Z[0];
return;
}
else if (Y[0] == ZERO)
{
__cpy (x, z, p);
return;
}
if (X[0] != Y[0]) { if (X[0] != Y[0])
if (__acr(x,y,p) > 0) {add_magnitudes(x,y,z,p); Z[0] = X[0]; } {
else {add_magnitudes(y,x,z,p); Z[0] = -Y[0]; } if (__acr (x, y, p) > 0)
} {
else { add_magnitudes (x, y, z, p);
if ((n=__acr(x,y,p)) == 1) {sub_magnitudes(x,y,z,p); Z[0] = X[0]; } Z[0] = X[0];
else if (n == -1) {sub_magnitudes(y,x,z,p); Z[0] = -Y[0]; } }
else Z[0] = ZERO; else
} {
add_magnitudes (y, x, z, p);
Z[0] = -Y[0];
}
}
else
{
if ((n = __acr (x, y, p)) == 1)
{
sub_magnitudes (x, y, z, p);
Z[0] = X[0];
}
else if (n == -1)
{
sub_magnitudes (y, x, z, p);
Z[0] = -Y[0];
}
else
Z[0] = ZERO;
}
return; return;
} }
/* Multiply *X and *Y and store result in *Z. X and Y may overlap but not X /* Multiply *X and *Y and store result in *Z. X and Y may overlap but not X
and Z or Y and Z. For P in [1, 2, 3], the exact result is truncated to P and Z or Y and Z. For P in [1, 2, 3], the exact result is truncated to P
digits. In case P > 3 the error is bounded by 1.001 ULP. */ digits. In case P > 3 the error is bounded by 1.001 ULP. */
void __mul(const mp_no *x, const mp_no *y, mp_no *z, int p) { void
__mul (const mp_no *x, const mp_no *y, mp_no *z, int p)
{
long i, i1, i2, j, k, k2; long i, i1, i2, j, k, k2;
long p2 = p; long p2 = p;
double u, zk, zk2; double u, zk, zk2;
/* Is z=0? */ /* Is z=0? */
if (X[0]*Y[0]==ZERO) if (X[0] * Y[0] == ZERO)
{ Z[0]=ZERO; return; } {
Z[0] = ZERO;
return;
}
/* Multiply, add and carry */ /* Multiply, add and carry */
k2 = (p2<3) ? p2+p2 : p2+3; k2 = (p2 < 3) ? p2 + p2 : p2 + 3;
zk = Z[k2]=ZERO; zk = Z[k2] = ZERO;
for (k=k2; k>1; ) { for (k = k2; k > 1;)
if (k > p2) {i1=k-p2; i2=p2+1; } {
else {i1=1; i2=k; } if (k > p2)
{
i1 = k - p2;
i2 = p2 + 1;
}
else
{
i1 = 1;
i2 = k;
}
#if 1 #if 1
/* Rearrange this inner loop to allow the fmadd instructions to be /* Rearrange this inner loop to allow the fmadd instructions to be
independent and execute in parallel on processors that have independent and execute in parallel on processors that have
dual symmetrical FP pipelines. */ dual symmetrical FP pipelines. */
if (i1 < (i2-1)) if (i1 < (i2 - 1))
{
/* Make sure we have at least 2 iterations. */
if (((i2 - i1) & 1L) == 1L)
{ {
/* Handle the odd iterations case. */ /* Make sure we have at least 2 iterations. */
zk2 = x->d[i2-1]*y->d[i1]; if (((i2 - i1) & 1L) == 1L)
{
/* Handle the odd iterations case. */
zk2 = x->d[i2 - 1] * y->d[i1];
}
else
zk2 = 0.0;
/* Do two multiply/adds per loop iteration, using independent
accumulators; zk and zk2. */
for (i = i1, j = i2 - 1; i < i2 - 1; i += 2, j -= 2)
{
zk += x->d[i] * y->d[j];
zk2 += x->d[i + 1] * y->d[j - 1];
}
zk += zk2; /* Final sum. */
} }
else else
zk2 = 0.0;
/* Do two multiply/adds per loop iteration, using independent
accumulators; zk and zk2. */
for (i=i1,j=i2-1; i<i2-1; i+=2,j-=2)
{ {
zk += x->d[i]*y->d[j]; /* Special case when iterations is 1. */
zk2 += x->d[i+1]*y->d[j-1]; zk += x->d[i1] * y->d[i1];
} }
zk += zk2; /* Final sum. */
}
else
{
/* Special case when iterations is 1. */
zk += x->d[i1]*y->d[i1];
}
#else #else
/* The original code. */ /* The original code. */
for (i=i1,j=i2-1; i<i2; i++,j--) zk += X[i]*Y[j]; for (i = i1, j = i2 - 1; i < i2; i++, j--)
zk += X[i] * Y[j];
#endif #endif
u = (zk + CUTTER)-CUTTER; u = (zk + CUTTER) - CUTTER;
if (u > zk) u -= RADIX; if (u > zk)
Z[k] = zk - u; u -= RADIX;
zk = u*RADIXI; Z[k] = zk - u;
--k; zk = u * RADIXI;
} --k;
}
Z[k] = zk; Z[k] = zk;
/* Is there a carry beyond the most significant digit? */ /* Is there a carry beyond the most significant digit? */
if (Z[1] == ZERO) { if (Z[1] == ZERO)
for (i=1; i<=p2; i++) Z[i]=Z[i+1]; {
EZ = EX + EY - 1; } for (i = 1; i <= p2; i++)
Z[i] = Z[i + 1];
EZ = EX + EY - 1;
}
else else
EZ = EX + EY; EZ = EX + EY;
@ -444,22 +694,31 @@ void __mul(const mp_no *x, const mp_no *y, mp_no *z, int p) {
- For P > 3: 2.001 * R ^ (1 - P) - For P > 3: 2.001 * R ^ (1 - P)
*X = 0 is not permissible. */ *X = 0 is not permissible. */
void __inv(const mp_no *x, mp_no *y, int p) { void
__inv (const mp_no *x, mp_no *y, int p)
{
long i; long i;
double t; double t;
mp_no z,w; mp_no z, w;
static const int np1[] = {0,0,0,0,1,2,2,2,2,3,3,3,3,3,3,3,3,3, static const int np1[] =
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4}; { 0, 0, 0, 0, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
};
__cpy(x,&z,p); z.e=0; __mp_dbl(&z,&t,p); __cpy (x, &z, p);
t=ONE/t; __dbl_mp(t,y,p); EY -= EX; z.e = 0;
__mp_dbl (&z, &t, p);
t = ONE / t;
__dbl_mp (t, y, p);
EY -= EX;
for (i=0; i<np1[p]; i++) { for (i = 0; i < np1[p]; i++)
__cpy(y,&w,p); {
__mul(x,&w,y,p); __cpy (y, &w, p);
__sub(&mptwo,y,&z,p); __mul (x, &w, y, p);
__mul(&w,&z,y,p); __sub (&mptwo, y, &z, p);
} __mul (&w, &z, y, p);
}
return; return;
} }
@ -470,11 +729,17 @@ void __inv(const mp_no *x, mp_no *y, int p) {
- For P > 3: 3.001 * R ^ (1 - P) - For P > 3: 3.001 * R ^ (1 - P)
*X = 0 is not permissible. */ *X = 0 is not permissible. */
void __dvd(const mp_no *x, const mp_no *y, mp_no *z, int p) { void
__dvd (const mp_no *x, const mp_no *y, mp_no *z, int p)
{
mp_no w; mp_no w;
if (X[0] == ZERO) Z[0] = ZERO; if (X[0] == ZERO)
else {__inv(y,&w,p); __mul(x,&w,z,p);} Z[0] = ZERO;
else
{
__inv (y, &w, p);
__mul (x, &w, z, p);
}
return; return;
} }

View File

@ -51,91 +51,135 @@ const mp_no mptwo = {1, {1.0, 2.0}};
/* Compare mantissa of two multiple precision numbers regardless of the sign /* Compare mantissa of two multiple precision numbers regardless of the sign
and exponent of the numbers. */ and exponent of the numbers. */
static int mcr(const mp_no *x, const mp_no *y, int p) { static int
mcr (const mp_no *x, const mp_no *y, int p)
{
long i; long i;
long p2 = p; long p2 = p;
for (i=1; i<=p2; i++) { for (i = 1; i <= p2; i++)
if (X[i] == Y[i]) continue; {
else if (X[i] > Y[i]) return 1; if (X[i] == Y[i])
else return -1; } continue;
else if (X[i] > Y[i])
return 1;
else
return -1;
}
return 0; return 0;
} }
/* Compare the absolute values of two multiple precision numbers. */ /* Compare the absolute values of two multiple precision numbers. */
int __acr(const mp_no *x, const mp_no *y, int p) { int
__acr (const mp_no *x, const mp_no *y, int p)
{
long i; long i;
if (X[0] == ZERO) { if (X[0] == ZERO)
if (Y[0] == ZERO) i= 0; {
else i=-1; if (Y[0] == ZERO)
} i = 0;
else if (Y[0] == ZERO) i= 1; else
else { i = -1;
if (EX > EY) i= 1; }
else if (EX < EY) i=-1; else if (Y[0] == ZERO)
else i= mcr(x,y,p); i = 1;
} else
{
if (EX > EY)
i = 1;
else if (EX < EY)
i = -1;
else
i = mcr (x, y, p);
}
return i; return i;
} }
/* Copy multiple precision number X into Y. They could be the same /* Copy multiple precision number X into Y. They could be the same
number. */ number. */
void __cpy(const mp_no *x, mp_no *y, int p) { void
__cpy (const mp_no *x, mp_no *y, int p)
{
long i; long i;
EY = EX; EY = EX;
for (i=0; i <= p; i++) Y[i] = X[i]; for (i = 0; i <= p; i++)
Y[i] = X[i];
return; return;
} }
/* Convert a multiple precision number *X into a double precision /* Convert a multiple precision number *X into a double precision
number *Y, normalized case (|x| >= 2**(-1022))). */ number *Y, normalized case (|x| >= 2**(-1022))). */
static void norm(const mp_no *x, double *y, int p) static void
norm (const mp_no *x, double *y, int p)
{ {
#define R RADIXI #define R RADIXI
long i; long i;
double a,c,u,v,z[5]; double a, c, u, v, z[5];
if (p<5) { if (p < 5)
if (p==1) c = X[1]; {
else if (p==2) c = X[1] + R* X[2]; if (p == 1)
else if (p==3) c = X[1] + R*(X[2] + R* X[3]); c = X[1];
else if (p==4) c =(X[1] + R* X[2]) + R*R*(X[3] + R*X[4]); else if (p == 2)
} c = X[1] + R * X[2];
else { else if (p == 3)
for (a=ONE, z[1]=X[1]; z[1] < TWO23; ) c = X[1] + R * (X[2] + R * X[3]);
{a *= TWO; z[1] *= TWO; } else if (p == 4)
c = (X[1] + R * X[2]) + R * R * (X[3] + R * X[4]);
for (i=2; i<5; i++) {
z[i] = X[i]*a;
u = (z[i] + CUTTER)-CUTTER;
if (u > z[i]) u -= RADIX;
z[i] -= u;
z[i-1] += u*RADIXI;
} }
else
{
for (a = ONE, z[1] = X[1]; z[1] < TWO23;)
{
a *= TWO;
z[1] *= TWO;
}
u = (z[3] + TWO71) - TWO71; for (i = 2; i < 5; i++)
if (u > z[3]) u -= TWO19; {
v = z[3]-u; z[i] = X[i] * a;
u = (z[i] + CUTTER) - CUTTER;
if (u > z[i])
u -= RADIX;
z[i] -= u;
z[i - 1] += u * RADIXI;
}
if (v == TWO18) { u = (z[3] + TWO71) - TWO71;
if (z[4] == ZERO) { if (u > z[3])
for (i=5; i <= p; i++) { u -= TWO19;
if (X[i] == ZERO) continue; v = z[3] - u;
else {z[3] += ONE; break; }
} if (v == TWO18)
} {
else z[3] += ONE; if (z[4] == ZERO)
{
for (i = 5; i <= p; i++)
{
if (X[i] == ZERO)
continue;
else
{
z[3] += ONE;
break;
}
}
}
else
z[3] += ONE;
}
c = (z[1] + R * (z[2] + R * z[3])) / a;
} }
c = (z[1] + R *(z[2] + R * z[3]))/a;
}
c *= X[0]; c *= X[0];
for (i=1; i<EX; i++) c *= RADIX; for (i = 1; i < EX; i++)
for (i=1; i>EX; i--) c *= RADIXI; c *= RADIX;
for (i = 1; i > EX; i--)
c *= RADIXI;
*y = c; *y = c;
return; return;
@ -144,46 +188,112 @@ static void norm(const mp_no *x, double *y, int p)
/* Convert a multiple precision number *X into a double precision /* Convert a multiple precision number *X into a double precision
number *Y, Denormal case (|x| < 2**(-1022))). */ number *Y, Denormal case (|x| < 2**(-1022))). */
static void denorm(const mp_no *x, double *y, int p) static void
denorm (const mp_no *x, double *y, int p)
{ {
long i,k; long i, k;
long p2 = p; long p2 = p;
double c,u,z[5]; double c, u, z[5];
#define R RADIXI #define R RADIXI
if (EX<-44 || (EX==-44 && X[1]<TWO5)) if (EX < -44 || (EX == -44 && X[1] < TWO5))
{ *y=ZERO; return; } {
*y = ZERO;
return;
}
if (p2==1) { if (p2 == 1)
if (EX==-42) {z[1]=X[1]+TWO10; z[2]=ZERO; z[3]=ZERO; k=3;} {
else if (EX==-43) {z[1]= TWO10; z[2]=X[1]; z[3]=ZERO; k=2;} if (EX == -42)
else {z[1]= TWO10; z[2]=ZERO; z[3]=X[1]; k=1;} {
} z[1] = X[1] + TWO10;
else if (p2==2) { z[2] = ZERO;
if (EX==-42) {z[1]=X[1]+TWO10; z[2]=X[2]; z[3]=ZERO; k=3;} z[3] = ZERO;
else if (EX==-43) {z[1]= TWO10; z[2]=X[1]; z[3]=X[2]; k=2;} k = 3;
else {z[1]= TWO10; z[2]=ZERO; z[3]=X[1]; k=1;} }
} else if (EX == -43)
else { {
if (EX==-42) {z[1]=X[1]+TWO10; z[2]=X[2]; k=3;} z[1] = TWO10;
else if (EX==-43) {z[1]= TWO10; z[2]=X[1]; k=2;} z[2] = X[1];
else {z[1]= TWO10; z[2]=ZERO; k=1;} z[3] = ZERO;
z[3] = X[k]; k = 2;
} }
else
{
z[1] = TWO10;
z[2] = ZERO;
z[3] = X[1];
k = 1;
}
}
else if (p2 == 2)
{
if (EX == -42)
{
z[1] = X[1] + TWO10;
z[2] = X[2];
z[3] = ZERO;
k = 3;
}
else if (EX == -43)
{
z[1] = TWO10;
z[2] = X[1];
z[3] = X[2];
k = 2;
}
else
{
z[1] = TWO10;
z[2] = ZERO;
z[3] = X[1];
k = 1;
}
}
else
{
if (EX == -42)
{
z[1] = X[1] + TWO10;
z[2] = X[2];
k = 3;
}
else if (EX == -43)
{
z[1] = TWO10;
z[2] = X[1];
k = 2;
}
else
{
z[1] = TWO10;
z[2] = ZERO;
k = 1;
}
z[3] = X[k];
}
u = (z[3] + TWO57) - TWO57; u = (z[3] + TWO57) - TWO57;
if (u > z[3]) u -= TWO5; if (u > z[3])
u -= TWO5;
if (u==z[3]) { if (u == z[3])
for (i=k+1; i <= p2; i++) { {
if (X[i] == ZERO) continue; for (i = k + 1; i <= p2; i++)
else {z[3] += ONE; break; } {
if (X[i] == ZERO)
continue;
else
{
z[3] += ONE;
break;
}
}
} }
}
c = X[0]*((z[1] + R*(z[2] + R*z[3])) - TWO10); c = X[0] * ((z[1] + R * (z[2] + R * z[3])) - TWO10);
*y = c*TWOM1032; *y = c * TWOM1032;
return; return;
#undef R #undef R
@ -191,39 +301,65 @@ static void denorm(const mp_no *x, double *y, int p)
/* Convert multiple precision number *X into double precision number *Y. The /* Convert multiple precision number *X into double precision number *Y. The
result is correctly rounded to the nearest/even. */ result is correctly rounded to the nearest/even. */
void __mp_dbl(const mp_no *x, double *y, int p) { void
__mp_dbl (const mp_no *x, double *y, int p)
{
if (X[0] == ZERO)
{
*y = ZERO;
return;
}
if (X[0] == ZERO) {*y = ZERO; return; } if (EX > -42)
norm (x, y, p);
if (EX> -42) norm(x,y,p); else if (EX == -42 && X[1] >= TWO10)
else if (EX==-42 && X[1]>=TWO10) norm(x,y,p); norm (x, y, p);
else denorm(x,y,p); else
denorm (x, y, p);
} }
/* Get the multiple precision equivalent of X into *Y. If the precision is too /* Get the multiple precision equivalent of X into *Y. If the precision is too
small, the result is truncated. */ small, the result is truncated. */
void __dbl_mp(double x, mp_no *y, int p) { void
__dbl_mp (double x, mp_no *y, int p)
long i,n; {
long i, n;
long p2 = p; long p2 = p;
double u; double u;
/* Sign. */ /* Sign. */
if (x == ZERO) {Y[0] = ZERO; return; } if (x == ZERO)
else if (x > ZERO) Y[0] = ONE; {
else {Y[0] = MONE; x=-x; } Y[0] = ZERO;
return;
}
else if (x > ZERO)
Y[0] = ONE;
else
{
Y[0] = MONE;
x = -x;
}
/* Exponent. */ /* Exponent. */
for (EY=ONE; x >= RADIX; EY += ONE) x *= RADIXI; for (EY = ONE; x >= RADIX; EY += ONE)
for ( ; x < ONE; EY -= ONE) x *= RADIX; x *= RADIXI;
for (; x < ONE; EY -= ONE)
x *= RADIX;
/* Digits. */ /* Digits. */
n=MIN(p2,4); n = MIN (p2, 4);
for (i=1; i<=n; i++) { for (i = 1; i <= n; i++)
u = (x + TWO52) - TWO52; {
if (u>x) u -= ONE; u = (x + TWO52) - TWO52;
Y[i] = u; x -= u; x *= RADIX; } if (u > x)
for ( ; i<=p2; i++) Y[i] = ZERO; u -= ONE;
Y[i] = u;
x -= u;
x *= RADIX;
}
for (; i <= p2; i++)
Y[i] = ZERO;
return; return;
} }
@ -231,93 +367,132 @@ void __dbl_mp(double x, mp_no *y, int p) {
sign of the sum *Z is not changed. X and Y may overlap but not X and Z or sign of the sum *Z is not changed. X and Y may overlap but not X and Z or
Y and Z. No guard digit is used. The result equals the exact sum, Y and Z. No guard digit is used. The result equals the exact sum,
truncated. */ truncated. */
static void add_magnitudes(const mp_no *x, const mp_no *y, mp_no *z, int p) { static void
add_magnitudes (const mp_no *x, const mp_no *y, mp_no *z, int p)
long i,j,k; {
long i, j, k;
long p2 = p; long p2 = p;
EZ = EX; EZ = EX;
i=p2; j=p2+ EY - EX; k=p2+1; i = p2;
j = p2 + EY - EX;
k = p2 + 1;
if (j<1) if (j < 1)
{__cpy(x,z,p); return; } {
else Z[k] = ZERO; __cpy (x, z, p);
return;
}
else
Z[k] = ZERO;
for (; j>0; i--,j--) { for (; j > 0; i--, j--)
Z[k] += X[i] + Y[j]; {
if (Z[k] >= RADIX) { Z[k] += X[i] + Y[j];
Z[k] -= RADIX; if (Z[k] >= RADIX)
Z[--k] = ONE; } {
else Z[k] -= RADIX;
Z[--k] = ZERO; Z[--k] = ONE;
} }
else
Z[--k] = ZERO;
}
for (; i>0; i--) { for (; i > 0; i--)
Z[k] += X[i]; {
if (Z[k] >= RADIX) { Z[k] += X[i];
Z[k] -= RADIX; if (Z[k] >= RADIX)
Z[--k] = ONE; } {
else Z[k] -= RADIX;
Z[--k] = ZERO; Z[--k] = ONE;
} }
else
Z[--k] = ZERO;
}
if (Z[1] == ZERO) { if (Z[1] == ZERO)
for (i=1; i<=p2; i++) Z[i] = Z[i+1]; } {
else EZ += ONE; for (i = 1; i <= p2; i++)
Z[i] = Z[i + 1];
}
else
EZ += ONE;
} }
/* Subtract the magnitudes of *X and *Y assuming that abs (*x) > abs (*y) > 0. /* Subtract the magnitudes of *X and *Y assuming that abs (*x) > abs (*y) > 0.
The sign of the difference *Z is not changed. X and Y may overlap but not X The sign of the difference *Z is not changed. X and Y may overlap but not X
and Z or Y and Z. One guard digit is used. The error is less than one and Z or Y and Z. One guard digit is used. The error is less than one
ULP. */ ULP. */
static void sub_magnitudes(const mp_no *x, const mp_no *y, mp_no *z, int p) { static void
sub_magnitudes (const mp_no *x, const mp_no *y, mp_no *z, int p)
long i,j,k; {
long i, j, k;
long p2 = p; long p2 = p;
EZ = EX; EZ = EX;
if (EX == EY) { if (EX == EY)
i=j=k=p2; {
Z[k] = Z[k+1] = ZERO; } i = j = k = p2;
else { Z[k] = Z[k + 1] = ZERO;
j= EX - EY; }
if (j > p2) {__cpy(x,z,p); return; } else
else { {
i=p2; j=p2+1-j; k=p2; j = EX - EY;
if (Y[j] > ZERO) { if (j > p2)
Z[k+1] = RADIX - Y[j--]; {
Z[k] = MONE; } __cpy (x, z, p);
else { return;
Z[k+1] = ZERO; }
Z[k] = ZERO; j--;} else
{
i = p2;
j = p2 + 1 - j;
k = p2;
if (Y[j] > ZERO)
{
Z[k + 1] = RADIX - Y[j--];
Z[k] = MONE;
}
else
{
Z[k + 1] = ZERO;
Z[k] = ZERO;
j--;
}
}
} }
}
for (; j>0; i--,j--) { for (; j > 0; i--, j--)
Z[k] += (X[i] - Y[j]); {
if (Z[k] < ZERO) { Z[k] += (X[i] - Y[j]);
Z[k] += RADIX; if (Z[k] < ZERO)
Z[--k] = MONE; } {
else Z[k] += RADIX;
Z[--k] = ZERO; Z[--k] = MONE;
} }
else
Z[--k] = ZERO;
}
for (; i>0; i--) { for (; i > 0; i--)
Z[k] += X[i]; {
if (Z[k] < ZERO) { Z[k] += X[i];
Z[k] += RADIX; if (Z[k] < ZERO)
Z[--k] = MONE; } {
else Z[k] += RADIX;
Z[--k] = ZERO; Z[--k] = MONE;
} }
else
Z[--k] = ZERO;
}
for (i=1; Z[i] == ZERO; i++) ; for (i = 1; Z[i] == ZERO; i++);
EZ = EZ - i + 1; EZ = EZ - i + 1;
for (k=1; i <= p2+1; ) for (k = 1; i <= p2 + 1;)
Z[k++] = Z[i++]; Z[k++] = Z[i++];
for (; k <= p2; ) for (; k <= p2;)
Z[k++] = ZERO; Z[k++] = ZERO;
return; return;
@ -326,111 +501,186 @@ static void sub_magnitudes(const mp_no *x, const mp_no *y, mp_no *z, int p) {
/* Add *X and *Y and store the result in *Z. X and Y may overlap, but not X /* Add *X and *Y and store the result in *Z. X and Y may overlap, but not X
and Z or Y and Z. One guard digit is used. The error is less than one and Z or Y and Z. One guard digit is used. The error is less than one
ULP. */ ULP. */
void __add(const mp_no *x, const mp_no *y, mp_no *z, int p) { void
__add (const mp_no *x, const mp_no *y, mp_no *z, int p)
{
int n; int n;
if (X[0] == ZERO) {__cpy(y,z,p); return; } if (X[0] == ZERO)
else if (Y[0] == ZERO) {__cpy(x,z,p); return; } {
__cpy (y, z, p);
return;
}
else if (Y[0] == ZERO)
{
__cpy (x, z, p);
return;
}
if (X[0] == Y[0]) { if (X[0] == Y[0])
if (__acr(x,y,p) > 0) {add_magnitudes(x,y,z,p); Z[0] = X[0]; } {
else {add_magnitudes(y,x,z,p); Z[0] = Y[0]; } if (__acr (x, y, p) > 0)
} {
else { add_magnitudes (x, y, z, p);
if ((n=__acr(x,y,p)) == 1) {sub_magnitudes(x,y,z,p); Z[0] = X[0]; } Z[0] = X[0];
else if (n == -1) {sub_magnitudes(y,x,z,p); Z[0] = Y[0]; } }
else Z[0] = ZERO; else
} {
add_magnitudes (y, x, z, p);
Z[0] = Y[0];
}
}
else
{
if ((n = __acr (x, y, p)) == 1)
{
sub_magnitudes (x, y, z, p);
Z[0] = X[0];
}
else if (n == -1)
{
sub_magnitudes (y, x, z, p);
Z[0] = Y[0];
}
else
Z[0] = ZERO;
}
return; return;
} }
/* Subtract *Y from *X and return the result in *Z. X and Y may overlap but /* Subtract *Y from *X and return the result in *Z. X and Y may overlap but
not X and Z or Y and Z. One guard digit is used. The error is less than not X and Z or Y and Z. One guard digit is used. The error is less than
one ULP. */ one ULP. */
void __sub(const mp_no *x, const mp_no *y, mp_no *z, int p) { void
__sub (const mp_no *x, const mp_no *y, mp_no *z, int p)
{
int n; int n;
if (X[0] == ZERO) {__cpy(y,z,p); Z[0] = -Z[0]; return; } if (X[0] == ZERO)
else if (Y[0] == ZERO) {__cpy(x,z,p); return; } {
__cpy (y, z, p);
Z[0] = -Z[0];
return;
}
else if (Y[0] == ZERO)
{
__cpy (x, z, p);
return;
}
if (X[0] != Y[0]) { if (X[0] != Y[0])
if (__acr(x,y,p) > 0) {add_magnitudes(x,y,z,p); Z[0] = X[0]; } {
else {add_magnitudes(y,x,z,p); Z[0] = -Y[0]; } if (__acr (x, y, p) > 0)
} {
else { add_magnitudes (x, y, z, p);
if ((n=__acr(x,y,p)) == 1) {sub_magnitudes(x,y,z,p); Z[0] = X[0]; } Z[0] = X[0];
else if (n == -1) {sub_magnitudes(y,x,z,p); Z[0] = -Y[0]; } }
else Z[0] = ZERO; else
} {
add_magnitudes (y, x, z, p);
Z[0] = -Y[0];
}
}
else
{
if ((n = __acr (x, y, p)) == 1)
{
sub_magnitudes (x, y, z, p);
Z[0] = X[0];
}
else if (n == -1)
{
sub_magnitudes (y, x, z, p);
Z[0] = -Y[0];
}
else
Z[0] = ZERO;
}
return; return;
} }
/* Multiply *X and *Y and store result in *Z. X and Y may overlap but not X /* Multiply *X and *Y and store result in *Z. X and Y may overlap but not X
and Z or Y and Z. For P in [1, 2, 3], the exact result is truncated to P and Z or Y and Z. For P in [1, 2, 3], the exact result is truncated to P
digits. In case P > 3 the error is bounded by 1.001 ULP. */ digits. In case P > 3 the error is bounded by 1.001 ULP. */
void __mul(const mp_no *x, const mp_no *y, mp_no *z, int p) { void
__mul (const mp_no *x, const mp_no *y, mp_no *z, int p)
{
long i, i1, i2, j, k, k2; long i, i1, i2, j, k, k2;
long p2 = p; long p2 = p;
double u, zk, zk2; double u, zk, zk2;
/* Is z=0? */ /* Is z=0? */
if (X[0]*Y[0]==ZERO) if (X[0] * Y[0] == ZERO)
{ Z[0]=ZERO; return; } {
Z[0] = ZERO;
return;
}
/* Multiply, add and carry */ /* Multiply, add and carry */
k2 = (p2<3) ? p2+p2 : p2+3; k2 = (p2 < 3) ? p2 + p2 : p2 + 3;
zk = Z[k2]=ZERO; zk = Z[k2] = ZERO;
for (k=k2; k>1; ) { for (k = k2; k > 1;)
if (k > p2) {i1=k-p2; i2=p2+1; } {
else {i1=1; i2=k; } if (k > p2)
{
i1 = k - p2;
i2 = p2 + 1;
}
else
{
i1 = 1;
i2 = k;
}
#if 1 #if 1
/* Rearrange this inner loop to allow the fmadd instructions to be /* Rearrange this inner loop to allow the fmadd instructions to be
independent and execute in parallel on processors that have independent and execute in parallel on processors that have
dual symmetrical FP pipelines. */ dual symmetrical FP pipelines. */
if (i1 < (i2-1)) if (i1 < (i2 - 1))
{
/* Make sure we have at least 2 iterations. */
if (((i2 - i1) & 1L) == 1L)
{ {
/* Handle the odd iterations case. */ /* Make sure we have at least 2 iterations. */
zk2 = x->d[i2-1]*y->d[i1]; if (((i2 - i1) & 1L) == 1L)
{
/* Handle the odd iterations case. */
zk2 = x->d[i2 - 1] * y->d[i1];
}
else
zk2 = 0.0;
/* Do two multiply/adds per loop iteration, using independent
accumulators; zk and zk2. */
for (i = i1, j = i2 - 1; i < i2 - 1; i += 2, j -= 2)
{
zk += x->d[i] * y->d[j];
zk2 += x->d[i + 1] * y->d[j - 1];
}
zk += zk2; /* Final sum. */
} }
else else
zk2 = 0.0;
/* Do two multiply/adds per loop iteration, using independent
accumulators; zk and zk2. */
for (i=i1,j=i2-1; i<i2-1; i+=2,j-=2)
{ {
zk += x->d[i]*y->d[j]; /* Special case when iterations is 1. */
zk2 += x->d[i+1]*y->d[j-1]; zk += x->d[i1] * y->d[i1];
} }
zk += zk2; /* Final sum. */
}
else
{
/* Special case when iterations is 1. */
zk += x->d[i1]*y->d[i1];
}
#else #else
/* The original code. */ /* The original code. */
for (i=i1,j=i2-1; i<i2; i++,j--) zk += X[i]*Y[j]; for (i = i1, j = i2 - 1; i < i2; i++, j--)
zk += X[i] * Y[j];
#endif #endif
u = (zk + CUTTER)-CUTTER; u = (zk + CUTTER) - CUTTER;
if (u > zk) u -= RADIX; if (u > zk)
Z[k] = zk - u; u -= RADIX;
zk = u*RADIXI; Z[k] = zk - u;
--k; zk = u * RADIXI;
} --k;
}
Z[k] = zk; Z[k] = zk;
/* Is there a carry beyond the most significant digit? */ /* Is there a carry beyond the most significant digit? */
if (Z[1] == ZERO) { if (Z[1] == ZERO)
for (i=1; i<=p2; i++) Z[i]=Z[i+1]; {
EZ = EX + EY - 1; } for (i = 1; i <= p2; i++)
Z[i] = Z[i + 1];
EZ = EX + EY - 1;
}
else else
EZ = EX + EY; EZ = EX + EY;
@ -444,22 +694,31 @@ void __mul(const mp_no *x, const mp_no *y, mp_no *z, int p) {
- For P > 3: 2.001 * R ^ (1 - P) - For P > 3: 2.001 * R ^ (1 - P)
*X = 0 is not permissible. */ *X = 0 is not permissible. */
void __inv(const mp_no *x, mp_no *y, int p) { void
__inv (const mp_no *x, mp_no *y, int p)
{
long i; long i;
double t; double t;
mp_no z,w; mp_no z, w;
static const int np1[] = {0,0,0,0,1,2,2,2,2,3,3,3,3,3,3,3,3,3, static const int np1[] =
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4}; { 0, 0, 0, 0, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
};
__cpy(x,&z,p); z.e=0; __mp_dbl(&z,&t,p); __cpy (x, &z, p);
t=ONE/t; __dbl_mp(t,y,p); EY -= EX; z.e = 0;
__mp_dbl (&z, &t, p);
t = ONE / t;
__dbl_mp (t, y, p);
EY -= EX;
for (i=0; i<np1[p]; i++) { for (i = 0; i < np1[p]; i++)
__cpy(y,&w,p); {
__mul(x,&w,y,p); __cpy (y, &w, p);
__sub(&mptwo,y,&z,p); __mul (x, &w, y, p);
__mul(&w,&z,y,p); __sub (&mptwo, y, &z, p);
} __mul (&w, &z, y, p);
}
return; return;
} }
@ -470,11 +729,17 @@ void __inv(const mp_no *x, mp_no *y, int p) {
- For P > 3: 3.001 * R ^ (1 - P) - For P > 3: 3.001 * R ^ (1 - P)
*X = 0 is not permissible. */ *X = 0 is not permissible. */
void __dvd(const mp_no *x, const mp_no *y, mp_no *z, int p) { void
__dvd (const mp_no *x, const mp_no *y, mp_no *z, int p)
{
mp_no w; mp_no w;
if (X[0] == ZERO) Z[0] = ZERO; if (X[0] == ZERO)
else {__inv(y,&w,p); __mul(x,&w,z,p);} Z[0] = ZERO;
else
{
__inv (y, &w, p);
__mul (x, &w, z, p);
}
return; return;
} }