void __mplog(mp_no *x, mp_no *y, int p) { #include "mplog.h" int i,m; #if 0 int j,k,m1,m2,n; double a,b; #endif static const int mp[33] = {0,0,0,0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3, 4,4,4,4,4,4,4,4,4,4,4,4,4,4}; mp_no mpone = {0,{0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0}}; mp_no mpt1,mpt2; /* Choose m and initiate mpone */ m = mp[p]; mpone.e = 1; mpone.d[0]=mpone.d[1]=ONE; /* Perform m newton iterations to solve for y: exp(y)-x=0. */ /* The iterations formula is: y(n+1)=y(n)+(x*exp(-y(n))-1). */ __cpy(y,&mpt1,p); for (i=0; i<m; i++) { mpt1.d[0]=-mpt1.d[0]; __mpexp(&mpt1,&mpt2,p); __mul(x,&mpt2,&mpt1,p); __sub(&mpt1,&mpone,&mpt2,p); __add(y,&mpt2,&mpt1,p); __cpy(&mpt1,y,p); } return; }
void SECTION __mpsqrt (mp_no *x, mp_no *y, int p) { int i, m, ey; double dx, dy; static const mp_no mphalf = {0, {1.0, HALFRAD}}; static const mp_no mp3halfs = {1, {1.0, 1.0, HALFRAD}}; mp_no mpxn, mpz, mpu, mpt1, mpt2; ey = EX / 2; __cpy (x, &mpxn, p); mpxn.e -= (ey + ey); __mp_dbl (&mpxn, &dx, p); dy = fastiroot (dx); __dbl_mp (dy, &mpu, p); __mul (&mpxn, &mphalf, &mpz, p); m = __mpsqrt_mp[p]; for (i = 0; i < m; i++) { __sqr (&mpu, &mpt1, p); __mul (&mpt1, &mpz, &mpt2, p); __sub (&mp3halfs, &mpt2, &mpt1, p); __mul (&mpu, &mpt1, &mpt2, p); __cpy (&mpt2, &mpu, p); } __mul (&mpxn, &mpu, y, p); EY += ey; }
static void SECTION cc32(mp_no *x, mp_no *y, int p) { int i; double a; #if 0 double b; static const mp_no mpone = {1,{1.0,1.0}}; #endif mp_no mpt1,x2,gor,sum ,mpk={1,{1.0}}; #if 0 mp_no mpt2; #endif for (i=1;i<=p;i++) mpk.d[i]=0; __mul(x,x,&x2,p); mpk.d[1]=27.0; __mul(&oofac27,&mpk,&gor,p); __cpy(&gor,&sum,p); for (a=26.0;a>2.0;a-=2.0) { mpk.d[1]=a*(a-1.0); __mul(&gor,&mpk,&mpt1,p); __cpy(&mpt1,&gor,p); __mul(&x2,&sum,&mpt1,p); __sub(&gor,&mpt1,&sum,p); } __mul(&x2,&sum,y,p); }
void __inv(const mp_no *x, mp_no *y, int p) { int i; #if 0 int l; #endif double t; 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, 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4}; const mp_no mptwo = {1,{1.0,2.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0}}; __cpy(x,&z,p); 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++) { __cpy(y,&w,p); __mul(x,&w,y,p); __sub(&mptwo,y,&z,p); __mul(&w,&z,y,p); } 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) *X = 0 is not permissible. */ static void SECTION __inv (const mp_no *x, mp_no *y, int p) { long i; double t; 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, 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); t = 1 / t; __dbl_mp (t, y, p); EY -= EX; for (i = 0; i < np1[p]; i++) { __cpy (y, &w, p); __mul (x, &w, y, p); __sub (&__mptwo, y, &z, p); __mul (&w, &z, y, p); } }
static void add_magnitudes(const mp_no *x, const mp_no *y, mp_no *z, int p) { int i,j,k; EZ = EX; i=p; j=p+ EY - EX; k=p+1; if (j<1) {__cpy(x,z,p); return; } else Z[k] = ZERO; for (; j>0; i--,j--) { Z[k] += X[i] + Y[j]; if (Z[k] >= RADIX) { Z[k] -= RADIX; Z[--k] = ONE; } else Z[--k] = ZERO; } for (; i>0; i--) { Z[k] += X[i]; if (Z[k] >= RADIX) { Z[k] -= RADIX; Z[--k] = ONE; } else Z[--k] = ZERO; } if (Z[1] == ZERO) { for (i=1; i<=p; i++) Z[i] = Z[i+1]; } else EZ += ONE; }
/* 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 one ULP. */ void SECTION __sub (const mp_no *x, const mp_no *y, mp_no *z, int p) { int n; if (X[0] == 0) { __cpy (y, z, p); Z[0] = -Z[0]; return; } else if (Y[0] == 0) { __cpy (x, z, p); return; } 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]; } } 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] = 0; } }
Clustering::Cluster &Clustering::Cluster::operator=(const Clustering::Cluster &cluster) { if(*this == cluster) { return *this; } this->~Cluster(); __cpy(cluster.__points, cluster.__size); return *this; }
Cluster& Cluster::operator=(const Cluster & other){ if(this != &other){ //delete & copy __size = other.__size; __del(); __cpy(other.__points); } return *this; }
void __add(const mp_no *x, const mp_no *y, mp_no *z, int p) { int n; if (X[0] == ZERO) {__cpy(y,z,p); return; } else if (Y[0] == ZERO) {__cpy(x,z,p); return; } 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]; } } 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; }
void __c32(mp_no *x, mp_no *y, mp_no *z, int p) { static const mp_no mpt={1,{1.0,2.0}}, one={1,{1.0,1.0}}; mp_no u,t,t1,t2,c,s; int i; __cpy(x,&u,p); u.e=u.e-1; cc32(&u,&c,p); ss32(&u,&s,p); for (i=0;i<24;i++) { __mul(&c,&s,&t,p); __sub(&s,&t,&t1,p); __add(&t1,&t1,&s,p); __sub(&mpt,&c,&t1,p); __mul(&t1,&c,&t2,p); __add(&t2,&t2,&c,p); } __sub(&one,&c,y,p); __cpy(&s,z,p); }
void SECTION __c32(mp_no *x, mp_no *y, mp_no *z, int p) { mp_no u,t,t1,t2,c,s; int i; __cpy(x,&u,p); u.e=u.e-1; cc32(&u,&c,p); ss32(&u,&s,p); for (i=0;i<24;i++) { __mul(&c,&s,&t,p); __sub(&s,&t,&t1,p); __add(&t1,&t1,&s,p); __sub(&mptwo,&c,&t1,p); __mul(&t1,&c,&t2,p); __add(&t2,&t2,&c,p); } __sub(&mpone,&c,y,p); __cpy(&s,z,p); }
Cluster::Cluster(const Cluster &C1) : centroid(C1.__dimensionality,C1){ __id = C1.__id; __dimensionality = C1.__dimensionality; __size = C1.getSize(); if(C1.__points != nullptr){ __cpy(C1.__points); } else{ __points = nullptr; } }
static void SECTION ss32(mp_no *x, mp_no *y, int p) { int i; double a; mp_no mpt1,x2,gor,sum ,mpk={1,{1.0}}; for (i=1;i<=p;i++) mpk.d[i]=0; __sqr(x,&x2,p); __cpy(&oofac27,&gor,p); __cpy(&gor,&sum,p); for (a=27.0;a>1.0;a-=2.0) { mpk.d[1]=a*(a-1.0); __mul(&gor,&mpk,&mpt1,p); __cpy(&mpt1,&gor,p); __mul(&x2,&sum,&mpt1,p); __sub(&gor,&mpt1,&sum,p); } __mul(x,&sum,y,p); }
Cluster::Cluster(const Cluster &other) { if (other.__points == nullptr) { __size = other.__size; __points = nullptr; return; } __size = other.__size; __cpy(other.__points); }
static void sub_magnitudes(const mp_no *x, const mp_no *y, mp_no *z, int p) { int i,j,k; EZ = EX; if (EX == EY) { i=j=k=p; Z[k] = Z[k+1] = ZERO; } else { j= EX - EY; if (j > p) {__cpy(x,z,p); return; } 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--) { Z[k] += (X[i] - Y[j]); if (Z[k] < ZERO) { Z[k] += RADIX; Z[--k] = MONE; } else Z[--k] = ZERO; } for (; i>0; i--) { Z[k] += X[i]; if (Z[k] < ZERO) { Z[k] += RADIX; Z[--k] = MONE; } else Z[--k] = ZERO; } for (i=1; Z[i] == ZERO; i++) ; EZ = EZ - i + 1; for (k=1; i <= p+1; ) Z[k++] = Z[i++]; for (; k <= p; ) Z[k++] = ZERO; return; }
Cluster& Cluster::operator=(const Cluster & other){ if(__dimensionality != other.__dimensionality){ throw DimensionalityMismatchEx(__dimensionality,other.__dimensionality); } if(this != &other){ //delete & copy __id = other.__id; __size = other.__size; __del(); if(other.__points != nullptr){ __cpy(other.__points); } else{ __points = nullptr; } } return *this; }
void SECTION __mpatan(mp_no *x, mp_no *y, int p) { int i,m,n; double dx; mp_no mpone = {0,{0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0}}, mptwo = {0,{0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0}}, mptwoim1 = {0,{0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0}}; mp_no mps,mpsm,mpt,mpt1,mpt2,mpt3; /* Choose m and initiate mpone, mptwo & mptwoim1 */ if (EX>0) m=7; else if (EX<0) m=0; else { __mp_dbl(x,&dx,p); dx=ABS(dx); for (m=6; m>0; m--) {if (dx>__atan_xm[m].d) break;} } mpone.e = mptwo.e = mptwoim1.e = 1; mpone.d[0] = mpone.d[1] = mptwo.d[0] = mptwoim1.d[0] = ONE; mptwo.d[1] = TWO; /* Reduce x m times */ __mul(x,x,&mpsm,p); if (m==0) __cpy(x,&mps,p); else { for (i=0; i<m; i++) { __add(&mpone,&mpsm,&mpt1,p); __mpsqrt(&mpt1,&mpt2,p); __add(&mpt2,&mpt2,&mpt1,p); __add(&mptwo,&mpsm,&mpt2,p); __add(&mpt1,&mpt2,&mpt3,p); __dvd(&mpsm,&mpt3,&mpt1,p); __cpy(&mpt1,&mpsm,p); } __mpsqrt(&mpsm,&mps,p); mps.d[0] = X[0]; } /* Evaluate a truncated power series for Atan(s) */ n=__atan_np[p]; mptwoim1.d[1] = __atan_twonm1[p].d; __dvd(&mpsm,&mptwoim1,&mpt,p); for (i=n-1; i>1; i--) { mptwoim1.d[1] -= TWO; __dvd(&mpsm,&mptwoim1,&mpt1,p); __mul(&mpsm,&mpt,&mpt2,p); __sub(&mpt1,&mpt2,&mpt,p); } __mul(&mps,&mpt,&mpt1,p); __sub(&mps,&mpt1,&mpt,p); /* Compute Atan(x) */ mptwoim1.d[1] = __atan_twom[m].d; __mul(&mptwoim1,&mpt,y,p); return; }
Clustering::Cluster::Cluster(const Clustering::Cluster &cluster) { __cpy(cluster.__points, cluster.__size); }
void __mpexp(mp_no *x, mp_no *y, int p) { int i,j,k,m,m1,m2,n; Double a,b; static const int np[33] = {0,0,0,0,3,3,4,4,5,4,4,5,5,5,6,6,6,6,6,6, 6,6,6,6,7,7,7,7,8,8,8,8,8}; static const int m1p[33]= {0,0,0,0,17,23,23,28,27,38,42,39,43,47,43,47,50,54, 57,60,64,67,71,74,68,71,74,77,70,73,76,78,81}; static const int m1np[7][18] = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, { 0, 0, 0, 0,36,48,60,72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, { 0, 0, 0, 0,24,32,40,48,56,64,72, 0, 0, 0, 0, 0, 0, 0}, { 0, 0, 0, 0,17,23,29,35,41,47,53,59,65, 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0, 0,23,28,33,38,42,47,52,57,62,66, 0, 0}, { 0, 0, 0, 0, 0, 0, 0, 0,27, 0, 0,39,43,47,51,55,59,63}, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,43,47,50,54}}; mp_no mpone = {0,{0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0}}; mp_no mpk = {0,{0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0}}; mp_no mps,mpak,mpt1,mpt2; /* Choose m,n and compute a=2**(-m) */ n = np[p]; m1 = m1p[p]; a = twomm1[p].d(); for (i=0; i<EX; i++) a *= RADIXI; for ( ; i>EX; i--) a *= RADIX; b = X[1]*RADIXI; m2 = 24*EX; for (; b<HALF; m2--) { a *= TWO; b *= TWO; } if (b == HALF) { for (i=2; i<=p; i++) { if (X[i]!=ZERO) break; } if (i==p+1) { m2--; a *= TWO; } } if ((m=m1+m2) <= 0) { m=0; a=ONE; for (i=n-1; i>0; i--,n--) { if (m1np[i][p]+m2>0) break; } } /* Compute s=x*2**(-m). Put result in mps */ __dbl_mp(a,&mpt1,p); __mul(x,&mpt1,&mps,p); /* Evaluate the polynomial. Put result in mpt2 */ mpone.e=1; mpone.d(0)=ONE; mpone.d(1)=ONE; mpk.e = 1; mpk.d(0) = ONE; mpk.d(1)=nn[n].d(); __dvd(&mps,&mpk,&mpt1,p); __add(&mpone,&mpt1,&mpak,p); for (k=n-1; k>1; k--) { __mul(&mps,&mpak,&mpt1,p); mpk.d(1)=nn[k].d(); __dvd(&mpt1,&mpk,&mpt2,p); __add(&mpone,&mpt2,&mpak,p); } __mul(&mps,&mpak,&mpt1,p); __add(&mpone,&mpt1,&mpt2,p); /* Raise polynomial value to the power of 2**m. Put result in y */ for (k=0,j=0; k<m; ) { __mul(&mpt2,&mpt2,&mpt1,p); k++; if (k==m) { j=1; break; } __mul(&mpt1,&mpt1,&mpt2,p); k++; } if (j) __cpy(&mpt1,y,p); else __cpy(&mpt2,y,p); return; }
/* Add magnitudes of *X and *Y assuming that abs (*X) >= abs (*Y) > 0. The 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, truncated. */ static void SECTION add_magnitudes (const mp_no *x, const mp_no *y, mp_no *z, int p) { long i, j, k; long p2 = p; mantissa_t zk; EZ = EX; i = p2; j = p2 + EY - EX; k = p2 + 1; if (__glibc_unlikely (j < 1)) { __cpy (x, z, p); return; } zk = 0; for (; j > 0; i--, j--) { zk += X[i] + Y[j]; if (zk >= RADIX) { Z[k--] = zk - RADIX; zk = 1; } else { Z[k--] = zk; zk = 0; } } for (; i > 0; i--) { zk += X[i]; if (zk >= RADIX) { Z[k--] = zk - RADIX; zk = 1; } else { Z[k--] = zk; zk = 0; } } if (zk == 0) { for (i = 1; i <= p2; i++) Z[i] = Z[i + 1]; } else { Z[1] = zk; EZ += 1; } }
/* 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 and Z or Y and Z. One guard digit is used. The error is less than one ULP. */ static void SECTION sub_magnitudes (const mp_no *x, const mp_no *y, mp_no *z, int p) { long i, j, k; long p2 = p; mantissa_t zk; EZ = EX; i = p2; j = p2 + EY - EX; k = p2; /* Y is too small compared to X, copy X over to the result. */ if (__glibc_unlikely (j < 1)) { __cpy (x, z, p); return; } /* The relevant least significant digit in Y is non-zero, so we factor it in to enhance accuracy. */ if (j < p2 && Y[j + 1] > 0) { Z[k + 1] = RADIX - Y[j + 1]; zk = -1; } else zk = Z[k + 1] = 0; /* Subtract and borrow. */ for (; j > 0; i--, j--) { zk += (X[i] - Y[j]); if (zk < 0) { Z[k--] = zk + RADIX; zk = -1; } else { Z[k--] = zk; zk = 0; } } /* We're done with digits from Y, so it's just digits in X. */ for (; i > 0; i--) { zk += X[i]; if (zk < 0) { Z[k--] = zk + RADIX; zk = -1; } else { Z[k--] = zk; zk = 0; } } /* Normalize. */ for (i = 1; Z[i] == 0; i++) ; EZ = EZ - i + 1; for (k = 1; i <= p2 + 1; ) Z[k++] = Z[i++]; for (; k <= p2; ) Z[k++] = 0; }
/* Multi-Precision exponential function subroutine (for p >= 4, 2**(-55) <= abs(x) <= 1024). */ void SECTION __mpexp (mp_no *x, mp_no *y, int p) { int i, j, k, m, m1, m2, n; mantissa_t b; static const int np[33] = { 0, 0, 0, 0, 3, 3, 4, 4, 5, 4, 4, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8 }; static const int m1p[33] = { 0, 0, 0, 0, 17, 23, 23, 28, 27, 38, 42, 39, 43, 47, 43, 47, 50, 54, 57, 60, 64, 67, 71, 74, 68, 71, 74, 77, 70, 73, 76, 78, 81 }; static const int m1np[7][18] = { {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 36, 48, 60, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 24, 32, 40, 48, 56, 64, 72, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 17, 23, 29, 35, 41, 47, 53, 59, 65, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 23, 28, 33, 38, 42, 47, 52, 57, 62, 66, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 27, 0, 0, 39, 43, 47, 51, 55, 59, 63}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 47, 50, 54} }; mp_no mps, mpk, mpt1, mpt2; /* Choose m,n and compute a=2**(-m). */ n = np[p]; m1 = m1p[p]; b = X[1]; m2 = 24 * EX; for (; b < HALFRAD; m2--) b *= 2; if (b == HALFRAD) { for (i = 2; i <= p; i++) { if (X[i] != 0) break; } if (i == p + 1) m2--; } m = m1 + m2; if (__glibc_unlikely (m <= 0)) { /* The m1np array which is used to determine if we can reduce the polynomial expansion iterations, has only 18 elements. Besides, numbers smaller than those required by p >= 18 should not come here at all since the fast phase of exp returns 1.0 for anything less than 2^-55. */ assert (p < 18); m = 0; for (i = n - 1; i > 0; i--, n--) if (m1np[i][p] + m2 > 0) break; } /* Compute s=x*2**(-m). Put result in mps. This is the range-reduced input that we will use to compute e^s. For the final result, simply raise it to 2^m. */ __pow_mp (-m, &mpt1, p); __mul (x, &mpt1, &mps, p); /* Compute the Taylor series for e^s: 1 + x/1! + x^2/2! + x^3/3! ... for N iterations. We compute this as: e^x = 1 + (x * n!/1! + x^2 * n!/2! + x^3 * n!/3!) / n! = 1 + (x * (n!/1! + x * (n!/2! + x * (n!/3! + x ...)))) / n! k! is computed on the fly as KF and at the end of the polynomial loop, KF is n!, which can be used directly. */ __cpy (&mps, &mpt2, p); double kf = 1.0; /* Evaluate the rest. The result will be in mpt2. */ for (k = n - 1; k > 0; k--) { /* n! / k! = n * (n - 1) ... * (n - k + 1) */ kf *= k + 1; __dbl_mp (kf, &mpk, p); __add (&mpt2, &mpk, &mpt1, p); __mul (&mps, &mpt1, &mpt2, p); } __dbl_mp (kf, &mpk, p); __dvd (&mpt2, &mpk, &mpt1, p); __add (&__mpone, &mpt1, &mpt2, p); /* Raise polynomial value to the power of 2**m. Put result in y. */ for (k = 0, j = 0; k < m;) { __sqr (&mpt2, &mpt1, p); k++; if (k == m) { j = 1; break; } __sqr (&mpt1, &mpt2, p); k++; } if (j) __cpy (&mpt1, y, p); else __cpy (&mpt2, y, p); return; }
Cluster::Cluster(const Cluster & p) : __size(p.__size){ __cpy(p.__points); }