Update comments in mpa.c

Fixed comment style and clearer wording in some cases.
This commit is contained in:
Siddhesh Poyarekar 2013-01-09 19:07:15 +05:30
parent 3a235abb5a
commit 950c99ca90
4 changed files with 190 additions and 207 deletions

View File

@ -1,3 +1,48 @@
2013-01-09 Siddhesh Poyarekar <siddhesh@redhat.com>
* sysdeps/ieee754/dbl-64/mpa.c (mcr): Reword comment.
(__acr): Likewise.
(__cpy): Likewise.
(norm): Likewise.
(denorm): Likewise.
(__mp_dbl): Likewise.
(__dbl_mp): Likewise.
(add_magnitudes): Likewise.
(sub_magnitudes): Likewise.
(__add): Likewise.
(__sub): Likewise.
(__mul): Likewise.
(__inv): Likewise.
(__dvd): Likewise.
* sysdeps/powerpc/powerpc32/power4/fpu/mpa.c (mcr): Likewise.
(__acr): Likewise.
(__cpy): Likewise.
(norm): Likewise.
(denorm): Likewise.
(__mp_dbl): Likewise.
(__dbl_mp): Likewise.
(add_magnitudes): Likewise.
(sub_magnitudes): Likewise.
(__add): Likewise.
(__sub): Likewise.
(__mul): Likewise.
(__inv): Likewise.
(__dvd): Likewise.
* sysdeps/powerpc/powerpc64/power4/fpu/mpa.c (mcr): Likewise.
(__acr): Likewise.
(__cpy): Likewise.
(norm): Likewise.
(denorm): Likewise.
(__mp_dbl): Likewise.
(__dbl_mp): Likewise.
(add_magnitudes): Likewise.
(sub_magnitudes): Likewise.
(__add): Likewise.
(__sub): Likewise.
(__mul): Likewise.
(__inv): Likewise.
(__dvd): Likewise.
2013-01-08 Joseph Myers <joseph@codesourcery.com> 2013-01-08 Joseph Myers <joseph@codesourcery.com>
* io/sys/stat.h [__GNUC__ && __GNUC__ >= 2 && * io/sys/stat.h [__GNUC__ && __GNUC__ >= 2 &&

View File

@ -45,7 +45,7 @@
#include "endian.h" #include "endian.h"
#include "mpa.h" #include "mpa.h"
#include "mpa2.h" #include "mpa2.h"
#include <sys/param.h> /* For MIN() */ #include <sys/param.h>
#ifndef SECTION #ifndef SECTION
# define SECTION # define SECTION
@ -57,10 +57,8 @@ const mp_no mptwo = {1, {1.0, 2.0}};
#endif #endif
#ifndef NO___ACR #ifndef NO___ACR
/* mcr() compares the sizes of the mantissas of two multiple precision */ /* Compare mantissa of two multiple precision numbers regardless of the sign
/* numbers. Mantissas are compared regardless of the signs of the */ and exponent of the numbers. */
/* numbers, even if x->d[0] or y->d[0] are zero. Exponents are also */
/* disregarded. */
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;
@ -71,8 +69,7 @@ mcr(const mp_no *x, const mp_no *y, int p) {
return 0; return 0;
} }
/* Compare the absolute values of two multiple precision numbers. */
/* acr() compares 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;
@ -92,19 +89,18 @@ __acr(const mp_no *x, const mp_no *y, int p) {
} }
#endif #endif
#ifndef NO___CPY #ifndef NO___CPY
/* Copy a multiple precision number. Set *y=*x. x=y is permissible. */ /* Copy multiple precision number X into Y. They could be the same
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
@ -154,8 +150,8 @@ static void norm(const mp_no *x, double *y, int p)
#undef R #undef R
} }
/* Convert a multiple precision number *x into a double precision */ /* Convert a multiple precision number *X into a double precision
/* number *y, denormalized 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;
@ -198,9 +194,8 @@ static void denorm(const mp_no *x, double *y, int p)
#undef R #undef R
} }
/* Convert a multiple precision number *x into a double precision number *y. */ /* Convert multiple precision number *X into double precision number *Y. The
/* The result is correctly rounded to the nearest/even. *x is left unchanged */ 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; }
@ -212,11 +207,8 @@ void __mp_dbl(const mp_no *x, double *y, int p) {
} }
#endif #endif
/* Get the multiple precision equivalent of X into *Y. If the precision is too
/* dbl_mp() converts a double precision number x into a multiple precision */ small, the result is truncated. */
/* number *y. If the precision p is too small the result is truncated. x is */
/* left unchanged. */
void void
SECTION SECTION
__dbl_mp(double x, mp_no *y, int p) { __dbl_mp(double x, mp_no *y, int p) {
@ -224,16 +216,16 @@ __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) {Y[0] = ZERO; return; }
else if (x > ZERO) Y[0] = ONE; else if (x > ZERO) Y[0] = ONE;
else {Y[0] = MONE; x=-x; } else {Y[0] = MONE; x=-x; }
/* Exponent */ /* Exponent. */
for (EY=ONE; x >= RADIX; EY += ONE) x *= RADIXI; for (EY=ONE; x >= RADIX; EY += ONE) x *= RADIXI;
for ( ; x < ONE; EY -= ONE) x *= RADIX; 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; u = (x + TWO52) - TWO52;
@ -242,13 +234,10 @@ __dbl_mp(double x, mp_no *y, int p) {
for ( ; i<=p; i++) Y[i] = ZERO; for ( ; i<=p; i++) Y[i] = ZERO;
} }
/* Add magnitudes of *X and *Y assuming that abs (*X) >= abs (*Y) > 0. The
/* add_magnitudes() adds the magnitudes of *x & *y assuming that */ sign of the sum *Z is not changed. X and Y may overlap but not X and Z or
/* abs(*x) >= abs(*y) > 0. */ Y and Z. No guard digit is used. The result equals the exact sum,
/* The sign of the sum *z is undefined. x&y may overlap but not x&z or y&z. */ truncated. */
/* No guard digit is used. The result equals the exact sum, truncated. */
/* *x & *y are left unchanged. */
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) {
@ -286,13 +275,10 @@ add_magnitudes(const mp_no *x, const mp_no *y, mp_no *z, int p) {
else EZ += ONE; else EZ += ONE;
} }
/* Subtract the magnitudes of *X and *Y assuming that abs (*x) > abs (*y) > 0.
/* sub_magnitudes() subtracts the magnitudes of *x & *y assuming that */ The sign of the difference *Z is not changed. X and Y may overlap but not X
/* abs(*x) > abs(*y) > 0. */ and Z or Y and Z. One guard digit is used. The error is less than one
/* The sign of the difference *z is undefined. x&y may overlap but not x&z */ ULP. */
/* or y&z. One guard digit is used. The error is less than one ulp. */
/* *x & *y are left unchanged. */
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) {
@ -344,11 +330,9 @@ sub_magnitudes(const mp_no *x, const mp_no *y, mp_no *z, int p) {
Z[k++] = ZERO; Z[k++] = ZERO;
} }
/* Add *X and *Y and store the result in *Z. X and Y may overlap, but not X
/* Add two multiple precision numbers. Set *z = *x + *y. x&y may overlap */ and Z or Y and Z. One guard digit is used. The error is less than one
/* but not x&z or y&z. One guard digit is used. The error is less than */ ULP. */
/* one ulp. *x & *y are left unchanged. */
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) {
@ -369,11 +353,9 @@ __add(const mp_no *x, const mp_no *y, mp_no *z, int p) {
} }
} }
/* Subtract *Y from *X and return the result in *Z. X and Y may overlap but
/* Subtract two multiple precision numbers. *z is set to *x - *y. x&y may */ not X and Z or Y and Z. One guard digit is used. The error is less than
/* overlap but not x&z or y&z. One guard digit is used. The error is */ one ULP. */
/* less than one ulp. *x & *y are left unchanged. */
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) {
@ -394,12 +376,9 @@ __sub(const mp_no *x, const mp_no *y, mp_no *z, int p) {
} }
} }
/* Multiply *X and *Y and store result in *Z. X and Y may overlap but not X
/* Multiply two multiple precision numbers. *z is set to *x * *y. x&y */ and Z or Y and Z. For P in [1, 2, 3], the exact result is truncated to P
/* may overlap but not x&z or y&z. In case p=1,2,3 the exact result is */ digits. In case P > 3 the error is bounded by 1.001 ULP. */
/* truncated to p digits. In case p>3 the error is bounded by 1.001 ulp. */
/* *x & *y are left unchanged. */
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) {
@ -414,7 +393,7 @@ __mul(const mp_no *x, const mp_no *y, mp_no *z, int p) {
return; return;
} }
/* Multiply, add and carry */ /* Multiply, add and carry. */
k2 = (__glibc_unlikely (p < 3)) ? p + p : p + 3; k2 = (__glibc_unlikely (p < 3)) ? p + p : p + 3;
Z[k2] = ZERO; Z[k2] = ZERO;
@ -454,12 +433,12 @@ __mul(const mp_no *x, const mp_no *y, mp_no *z, int p) {
Z[0] = X[0] * Y[0]; Z[0] = X[0] * Y[0];
} }
/* Invert *X and store in *Y. Relative error bound:
- For P = 2: 1.001 * R ^ (1 - P)
- For P = 3: 1.063 * R ^ (1 - P)
- For P > 3: 2.001 * R ^ (1 - P)
/* Invert a multiple precision number. Set *y = 1 / *x. */ *X = 0 is not permissible. */
/* Relative error bound = 1.001*r**(1-p) for p=2, 1.063*r**(1-p) for p=3, */
/* 2.001*r**(1-p) for p>3. */
/* *x=0 is not permissible. *x is left unchanged. */
static static
SECTION SECTION
void __inv(const mp_no *x, mp_no *y, int p) { void __inv(const mp_no *x, mp_no *y, int p) {
@ -480,12 +459,13 @@ void __inv(const mp_no *x, mp_no *y, int p) {
} }
} }
/* Divide *X by *Y and store result in *Z. X and Y may overlap but not X and Z
or Y and Z. Relative error bound:
- For P = 2: 2.001 * R ^ (1 - P)
- For P = 3: 2.063 * R ^ (1 - P)
- For P > 3: 3.001 * R ^ (1 - P)
/* Divide one multiple precision number by another.Set *z = *x / *y. *x & *y */ *X = 0 is not permissible. */
/* are left unchanged. x&y may overlap but not x&z or y&z. */
/* Relative error bound = 2.001*r**(1-p) for p=2, 2.063*r**(1-p) for p=3 */
/* and 3.001*r**(1-p) for p>3. *y=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) {

View File

@ -44,15 +44,13 @@
#include "endian.h" #include "endian.h"
#include "mpa.h" #include "mpa.h"
#include "mpa2.h" #include "mpa2.h"
#include <sys/param.h> /* For MIN() */ #include <sys/param.h>
const mp_no mpone = {1, {1.0, 1.0}}; const mp_no mpone = {1, {1.0, 1.0}};
const mp_no mptwo = {1, {1.0, 2.0}}; const mp_no mptwo = {1, {1.0, 2.0}};
/* mcr() compares the sizes of the mantissas of two multiple precision */ /* Compare mantissa of two multiple precision numbers regardless of the sign
/* numbers. Mantissas are compared regardless of the signs of the */ and exponent of the numbers. */
/* numbers, even if x->d[0] or y->d[0] are zero. Exponents are also */
/* disregarded. */
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;
@ -63,9 +61,7 @@ static int mcr(const mp_no *x, const mp_no *y, int p) {
return 0; return 0;
} }
/* Compare the absolute values of two multiple precision numbers. */
/* acr() compares 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;
@ -83,8 +79,8 @@ int __acr(const mp_no *x, const mp_no *y, int p) {
return i; return i;
} }
/* Copy multiple precision number X into Y. They could be the same
/* Copy a multiple precision number. Set *y=*x. x=y is permissible. */ 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;
@ -94,9 +90,8 @@ void __cpy(const mp_no *x, mp_no *y, int p) {
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
@ -147,8 +142,8 @@ static void norm(const mp_no *x, double *y, int p)
#undef R #undef R
} }
/* Convert a multiple precision number *x into a double precision */ /* Convert a multiple precision number *X into a double precision
/* number *y, denormalized 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;
@ -194,9 +189,8 @@ static void denorm(const mp_no *x, double *y, int p)
#undef R #undef R
} }
/* Convert a multiple precision number *x into a double precision number *y. */ /* Convert multiple precision number *X into double precision number *Y. The
/* The result is correctly rounded to the nearest/even. *x is left unchanged */ 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; }
@ -206,27 +200,24 @@ void __mp_dbl(const mp_no *x, double *y, int 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
/* dbl_mp() converts a double precision number x into a multiple precision */ small, the result is truncated. */
/* number *y. If the precision p is too small the result is truncated. x is */
/* left unchanged. */
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) {Y[0] = ZERO; return; }
else if (x > ZERO) Y[0] = ONE; else if (x > ZERO) Y[0] = ONE;
else {Y[0] = MONE; x=-x; } else {Y[0] = MONE; x=-x; }
/* Exponent */ /* Exponent. */
for (EY=ONE; x >= RADIX; EY += ONE) x *= RADIXI; for (EY=ONE; x >= RADIX; EY += ONE) x *= RADIXI;
for ( ; x < ONE; EY -= ONE) x *= RADIX; 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; u = (x + TWO52) - TWO52;
@ -236,13 +227,10 @@ void __dbl_mp(double x, mp_no *y, int p) {
return; return;
} }
/* Add magnitudes of *X and *Y assuming that abs (*X) >= abs (*Y) > 0. The
/* add_magnitudes() adds the magnitudes of *x & *y assuming that */ sign of the sum *Z is not changed. X and Y may overlap but not X and Z or
/* abs(*x) >= abs(*y) > 0. */ Y and Z. No guard digit is used. The result equals the exact sum,
/* The sign of the sum *z is undefined. x&y may overlap but not x&z or y&z. */ truncated. */
/* No guard digit is used. The result equals the exact sum, truncated. */
/* *x & *y are left unchanged. */
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;
@ -279,13 +267,10 @@ static void add_magnitudes(const mp_no *x, const mp_no *y, mp_no *z, int p) {
else EZ += ONE; else EZ += ONE;
} }
/* Subtract the magnitudes of *X and *Y assuming that abs (*x) > abs (*y) > 0.
/* sub_magnitudes() subtracts the magnitudes of *x & *y assuming that */ The sign of the difference *Z is not changed. X and Y may overlap but not X
/* abs(*x) > abs(*y) > 0. */ and Z or Y and Z. One guard digit is used. The error is less than one
/* The sign of the difference *z is undefined. x&y may overlap but not x&z */ ULP. */
/* or y&z. One guard digit is used. The error is less than one ulp. */
/* *x & *y are left unchanged. */
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;
@ -338,11 +323,9 @@ static void sub_magnitudes(const mp_no *x, const mp_no *y, mp_no *z, int p) {
return; return;
} }
/* Add *X and *Y and store the result in *Z. X and Y may overlap, but not X
/* Add two multiple precision numbers. Set *z = *x + *y. x&y may overlap */ and Z or Y and Z. One guard digit is used. The error is less than one
/* but not x&z or y&z. One guard digit is used. The error is less than */ ULP. */
/* one ulp. *x & *y are left unchanged. */
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;
@ -362,11 +345,9 @@ void __add(const mp_no *x, const mp_no *y, mp_no *z, int p) {
return; return;
} }
/* Subtract *Y from *X and return the result in *Z. X and Y may overlap but
/* Subtract two multiple precision numbers. *z is set to *x - *y. x&y may */ not X and Z or Y and Z. One guard digit is used. The error is less than
/* overlap but not x&z or y&z. One guard digit is used. The error is */ one ULP. */
/* less than one ulp. *x & *y are left unchanged. */
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;
@ -386,12 +367,9 @@ void __sub(const mp_no *x, const mp_no *y, mp_no *z, int p) {
return; return;
} }
/* Multiply *X and *Y and store result in *Z. X and Y may overlap but not X
/* Multiply two multiple precision numbers. *z is set to *x * *y. x&y */ and Z or Y and Z. For P in [1, 2, 3], the exact result is truncated to P
/* may overlap but not x&z or y&z. In case p=1,2,3 the exact result is */ digits. In case P > 3 the error is bounded by 1.001 ULP. */
/* truncated to p digits. In case p>3 the error is bounded by 1.001 ulp. */
/* *x & *y are left unchanged. */
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;
@ -409,12 +387,12 @@ void __mul(const mp_no *x, const mp_no *y, mp_no *z, int p) {
if (k > p2) {i1=k-p2; i2=p2+1; } if (k > p2) {i1=k-p2; i2=p2+1; }
else {i1=1; i2=k; } 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 */ /* Make sure we have at least 2 iterations. */
if (((i2 - i1) & 1L) == 1L) if (((i2 - i1) & 1L) == 1L)
{ {
/* Handle the odd iterations case. */ /* Handle the odd iterations case. */
@ -429,7 +407,7 @@ void __mul(const mp_no *x, const mp_no *y, mp_no *z, int p) {
zk += x->d[i]*y->d[j]; zk += x->d[i]*y->d[j];
zk2 += x->d[i+1]*y->d[j-1]; zk2 += x->d[i+1]*y->d[j-1];
} }
zk += zk2; /* final sum. */ zk += zk2; /* Final sum. */
} }
else else
{ {
@ -460,12 +438,12 @@ void __mul(const mp_no *x, const mp_no *y, mp_no *z, int p) {
return; return;
} }
/* Invert *X and store in *Y. Relative error bound:
- For P = 2: 1.001 * R ^ (1 - P)
- For P = 3: 1.063 * R ^ (1 - P)
- For P > 3: 2.001 * R ^ (1 - P)
/* Invert a multiple precision number. Set *y = 1 / *x. */ *X = 0 is not permissible. */
/* Relative error bound = 1.001*r**(1-p) for p=2, 1.063*r**(1-p) for p=3, */
/* 2.001*r**(1-p) for p>3. */
/* *x=0 is not permissible. *x is left unchanged. */
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;
@ -489,12 +467,13 @@ void __inv(const mp_no *x, mp_no *y, int p) {
return; return;
} }
/* Divide *X by *Y and store result in *Z. X and Y may overlap but not X and Z
or Y and Z. Relative error bound:
- For P = 2: 2.001 * R ^ (1 - P)
- For P = 3: 2.063 * R ^ (1 - P)
- For P > 3: 3.001 * R ^ (1 - P)
/* Divide one multiple precision number by another.Set *z = *x / *y. *x & *y */ *X = 0 is not permissible. */
/* are left unchanged. x&y may overlap but not x&z or y&z. */
/* Relative error bound = 2.001*r**(1-p) for p=2, 2.063*r**(1-p) for p=3 */
/* and 3.001*r**(1-p) for p>3. *y=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;

View File

@ -44,15 +44,13 @@
#include "endian.h" #include "endian.h"
#include "mpa.h" #include "mpa.h"
#include "mpa2.h" #include "mpa2.h"
#include <sys/param.h> /* For MIN() */ #include <sys/param.h>
const mp_no mpone = {1, {1.0, 1.0}}; const mp_no mpone = {1, {1.0, 1.0}};
const mp_no mptwo = {1, {1.0, 2.0}}; const mp_no mptwo = {1, {1.0, 2.0}};
/* mcr() compares the sizes of the mantissas of two multiple precision */ /* Compare mantissa of two multiple precision numbers regardless of the sign
/* numbers. Mantissas are compared regardless of the signs of the */ and exponent of the numbers. */
/* numbers, even if x->d[0] or y->d[0] are zero. Exponents are also */
/* disregarded. */
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;
@ -63,9 +61,7 @@ static int mcr(const mp_no *x, const mp_no *y, int p) {
return 0; return 0;
} }
/* Compare the absolute values of two multiple precision numbers. */
/* acr() compares 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;
@ -83,8 +79,8 @@ int __acr(const mp_no *x, const mp_no *y, int p) {
return i; return i;
} }
/* Copy multiple precision number X into Y. They could be the same
/* Copy a multiple precision number. Set *y=*x. x=y is permissible. */ 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;
@ -94,9 +90,8 @@ void __cpy(const mp_no *x, mp_no *y, int p) {
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
@ -147,8 +142,8 @@ static void norm(const mp_no *x, double *y, int p)
#undef R #undef R
} }
/* Convert a multiple precision number *x into a double precision */ /* Convert a multiple precision number *X into a double precision
/* number *y, denormalized 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;
@ -194,9 +189,8 @@ static void denorm(const mp_no *x, double *y, int p)
#undef R #undef R
} }
/* Convert a multiple precision number *x into a double precision number *y. */ /* Convert multiple precision number *X into double precision number *Y. The
/* The result is correctly rounded to the nearest/even. *x is left unchanged */ 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; }
@ -206,27 +200,24 @@ void __mp_dbl(const mp_no *x, double *y, int 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
/* dbl_mp() converts a double precision number x into a multiple precision */ small, the result is truncated. */
/* number *y. If the precision p is too small the result is truncated. x is */
/* left unchanged. */
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) {Y[0] = ZERO; return; }
else if (x > ZERO) Y[0] = ONE; else if (x > ZERO) Y[0] = ONE;
else {Y[0] = MONE; x=-x; } else {Y[0] = MONE; x=-x; }
/* Exponent */ /* Exponent. */
for (EY=ONE; x >= RADIX; EY += ONE) x *= RADIXI; for (EY=ONE; x >= RADIX; EY += ONE) x *= RADIXI;
for ( ; x < ONE; EY -= ONE) x *= RADIX; 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; u = (x + TWO52) - TWO52;
@ -236,13 +227,10 @@ void __dbl_mp(double x, mp_no *y, int p) {
return; return;
} }
/* Add magnitudes of *X and *Y assuming that abs (*X) >= abs (*Y) > 0. The
/* add_magnitudes() adds the magnitudes of *x & *y assuming that */ sign of the sum *Z is not changed. X and Y may overlap but not X and Z or
/* abs(*x) >= abs(*y) > 0. */ Y and Z. No guard digit is used. The result equals the exact sum,
/* The sign of the sum *z is undefined. x&y may overlap but not x&z or y&z. */ truncated. */
/* No guard digit is used. The result equals the exact sum, truncated. */
/* *x & *y are left unchanged. */
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;
@ -279,13 +267,10 @@ static void add_magnitudes(const mp_no *x, const mp_no *y, mp_no *z, int p) {
else EZ += ONE; else EZ += ONE;
} }
/* Subtract the magnitudes of *X and *Y assuming that abs (*x) > abs (*y) > 0.
/* sub_magnitudes() subtracts the magnitudes of *x & *y assuming that */ The sign of the difference *Z is not changed. X and Y may overlap but not X
/* abs(*x) > abs(*y) > 0. */ and Z or Y and Z. One guard digit is used. The error is less than one
/* The sign of the difference *z is undefined. x&y may overlap but not x&z */ ULP. */
/* or y&z. One guard digit is used. The error is less than one ulp. */
/* *x & *y are left unchanged. */
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;
@ -338,11 +323,9 @@ static void sub_magnitudes(const mp_no *x, const mp_no *y, mp_no *z, int p) {
return; return;
} }
/* Add *X and *Y and store the result in *Z. X and Y may overlap, but not X
/* Add two multiple precision numbers. Set *z = *x + *y. x&y may overlap */ and Z or Y and Z. One guard digit is used. The error is less than one
/* but not x&z or y&z. One guard digit is used. The error is less than */ ULP. */
/* one ulp. *x & *y are left unchanged. */
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;
@ -362,11 +345,9 @@ void __add(const mp_no *x, const mp_no *y, mp_no *z, int p) {
return; return;
} }
/* Subtract *Y from *X and return the result in *Z. X and Y may overlap but
/* Subtract two multiple precision numbers. *z is set to *x - *y. x&y may */ not X and Z or Y and Z. One guard digit is used. The error is less than
/* overlap but not x&z or y&z. One guard digit is used. The error is */ one ULP. */
/* less than one ulp. *x & *y are left unchanged. */
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;
@ -386,12 +367,9 @@ void __sub(const mp_no *x, const mp_no *y, mp_no *z, int p) {
return; return;
} }
/* Multiply *X and *Y and store result in *Z. X and Y may overlap but not X
/* Multiply two multiple precision numbers. *z is set to *x * *y. x&y */ and Z or Y and Z. For P in [1, 2, 3], the exact result is truncated to P
/* may overlap but not x&z or y&z. In case p=1,2,3 the exact result is */ digits. In case P > 3 the error is bounded by 1.001 ULP. */
/* truncated to p digits. In case p>3 the error is bounded by 1.001 ulp. */
/* *x & *y are left unchanged. */
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;
@ -409,12 +387,12 @@ void __mul(const mp_no *x, const mp_no *y, mp_no *z, int p) {
if (k > p2) {i1=k-p2; i2=p2+1; } if (k > p2) {i1=k-p2; i2=p2+1; }
else {i1=1; i2=k; } 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 */ /* Make sure we have at least 2 iterations. */
if (((i2 - i1) & 1L) == 1L) if (((i2 - i1) & 1L) == 1L)
{ {
/* Handle the odd iterations case. */ /* Handle the odd iterations case. */
@ -429,7 +407,7 @@ void __mul(const mp_no *x, const mp_no *y, mp_no *z, int p) {
zk += x->d[i]*y->d[j]; zk += x->d[i]*y->d[j];
zk2 += x->d[i+1]*y->d[j-1]; zk2 += x->d[i+1]*y->d[j-1];
} }
zk += zk2; /* final sum. */ zk += zk2; /* Final sum. */
} }
else else
{ {
@ -460,12 +438,12 @@ void __mul(const mp_no *x, const mp_no *y, mp_no *z, int p) {
return; return;
} }
/* Invert *X and store in *Y. Relative error bound:
- For P = 2: 1.001 * R ^ (1 - P)
- For P = 3: 1.063 * R ^ (1 - P)
- For P > 3: 2.001 * R ^ (1 - P)
/* Invert a multiple precision number. Set *y = 1 / *x. */ *X = 0 is not permissible. */
/* Relative error bound = 1.001*r**(1-p) for p=2, 1.063*r**(1-p) for p=3, */
/* 2.001*r**(1-p) for p>3. */
/* *x=0 is not permissible. *x is left unchanged. */
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;
@ -489,12 +467,13 @@ void __inv(const mp_no *x, mp_no *y, int p) {
return; return;
} }
/* Divide *X by *Y and store result in *Z. X and Y may overlap but not X and Z
or Y and Z. Relative error bound:
- For P = 2: 2.001 * R ^ (1 - P)
- For P = 3: 2.063 * R ^ (1 - P)
- For P > 3: 3.001 * R ^ (1 - P)
/* Divide one multiple precision number by another.Set *z = *x / *y. *x & *y */ *X = 0 is not permissible. */
/* are left unchanged. x&y may overlap but not x&z or y&z. */
/* Relative error bound = 2.001*r**(1-p) for p=2, 2.063*r**(1-p) for p=3 */
/* and 3.001*r**(1-p) for p>3. *y=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;