www.pudn.com > calc.rar > i8.c
/* i8.c */ #include#include "integer.h" #include "fun.h" MPI *APPROXN(MPI *Aptr, unsigned int m) /* * *Eptr = 2 ^ (1 + [i / m]), (where i + 1 is the number of binary digits in the positive MPI *Aptr) is the initial approximation to the integer part of the m-th root of *Aptr. (*Aptr)^(1/m) < *Eptr <= 2*(*Aptr)^(1/m). */ { MPI *Eptr; unsigned int i = 0; i = BINARYB(Aptr) - 1; Eptr = POWER_I(2L, 1 + (i / m)); return (Eptr); } MPI *NEWTON(MPI *Aptr, unsigned int m, MPI *Fptr) /* * Returns the integer part of the mth root of *Aptr, where m is * an unsigned integer, 1 < m < R0. * The method is Newton's, using the integer part function, with initial * approximation *Fptr > (*Aptr)^(1/m). */ { MPI *X, *Y, *Z, *Temp, *Temp1; X = COPYI(Fptr); while (1) { Y = COPYI(X); Z = POWERI(X, m - 1); Temp = INT0(Aptr, Z); FREEMPI(Z); Z = MULT_I(X, m - 1); Temp1 = ADD0I(Temp, Z); FREEMPI(X); FREEMPI(Temp); X = INT0_(Temp1, m); FREEMPI(Temp1); FREEMPI(Z); if (RSV(Y, X) != 1) { FREEMPI(X); return (Y); } FREEMPI(Y); } } MPI *BABY_MTHROOT(MPI *Aptr, unsigned int m) /* * *Eptr is the integer part of the mth root of *Aptr, where m is * an unsigned integer, 1 < m < R0. * The method is Newton's, using the integer part function, with initial * approximation provided by APPROXN(), for "small" *Aptr. */ { MPI *X, *Eptr; X = APPROXN(Aptr, m); Eptr = NEWTON(Aptr, m, X); FREEMPI(X); return (Eptr); } MPI *BIG_MTHROOT(MPI *Aptr, unsigned int m) /* * *Eptr, the integer part of the mth root of the positive MPI *Aptr, * 1 < m < R0, is obtained by Newton's method, using the integer part function. */ { MPI *a, *X, *Eptr, *Temp; unsigned int i, n, r, t; n = Aptr->D; if (n < m) { Eptr = BABY_MTHROOT(Aptr, m); return (Eptr); } else { r = n / m; a = BUILDMPI((n % m) + 1); /* a = [*Aptr/R0^(m*r)] */ a->S = 1; t = r * m; for (i = 0; i <= a->D; i++) a->V[i] = Aptr->V[i + t]; X = BABY_MTHROOT(a, m); FREEMPI(a); Temp = X; X = ADD0_I(X, (USL)1); FREEMPI(Temp); Temp = X; X = BUILDMPI(Temp->D + r + 1); /* X = X* R0^r */ X->S = 1; for (i = X->D; i >= r; i--) X->V[i] = Temp->V[i - r]; FREEMPI(Temp); INTSETUL(X->V, (USL)r, (USL)0); /* sets the first r array elements to 0 */ Eptr = NEWTON(Aptr, m, X); /* X is the initial approximation */ FREEMPI(X); return (Eptr); } } void MTHROOT(MPI *Aptr, MPI *Bptr, unsigned int m, unsigned int r) /* * *Aptr and *Bptr are positive MPI'S. * the mthroot of *Aptr/(*Bptr) is computed to r decimal places, r >= 0; * m, r are integers, 0 < m * r < R0 * R0. */ { MPI *D, *E, *F, *G, *Y, *Temp; unsigned int i, l; E = POWER_I(10L, r * m); Temp = E; E = MULTI(E, Aptr); FREEMPI(Temp); Temp = E; E = INT0(E, Bptr); FREEMPI(Temp); if (E->S == 0) { FREEMPI(E); if (r == 0) { printf("%uthroot of ", m); PRINTI(Aptr); printf("/"); PRINTI(Bptr); printf(" = 0\n"); return; } else { printf("%uthroot of ", m); PRINTI(Aptr); printf("/"); PRINTI(Bptr); printf(" = 0."); for (i = 1; i <= r; i++) printf("0"); printf("\n"); return; } } Y = BIG_MTHROOT(E, m); FREEMPI(E); F = POWER_I(10L, r); G = MOD0(Y, F); D = INT0(Y, F); FREEMPI(F); FREEMPI(Y); printf("%uthroot of ", m); PRINTI(Aptr); printf("/"); PRINTI(Bptr); printf(" = "); PRINTI(D); FREEMPI(D); if (r == 0) { FREEMPI(G); printf("\n"); return; } printf("."); l = LENGTHI(G); /* the number of decimal digits in G */ for (i = 1; i <= r - l; i++) printf("0"); PRINTI(G); printf("\n"); FREEMPI(G); return; } MPR *MTHROOTR(MPR *Nptr, unsigned int m, unsigned int r) /* * *Nptr is a positive MPR. * the mthroot of *Nptr is computed to r decimal places, r >= 0 . * m, r are integers, 0 < m * r < R0 * R0 . */ { MPI *Tmp0I, *Tmp1I, *Tmp2I; MPR *Tmp1R; Tmp0I = POWER_I(10L, r); Tmp1I = POWERI(Tmp0I, m); Tmp2I = MULTI(Tmp1I, Nptr->N); Tmp1R = RATIOI(Tmp2I, Nptr->D); FREEMPI(Tmp1I); FREEMPI(Tmp2I); Tmp1I = INTI(Tmp1R->N, Tmp1R->D); FREEMPR(Tmp1R); if (EQZEROI(Tmp1I)) { FREEMPI(Tmp1I); FREEMPI(Tmp0I); return (ZEROR()); } Tmp2I = BIG_MTHROOT(Tmp1I, m); FREEMPI(Tmp1I); Tmp1R = RATIOI(Tmp2I, Tmp0I); FREEMPI(Tmp0I); FREEMPI(Tmp2I); return (Tmp1R); } MPI *PI(unsigned int r) { MPI *PI, *X, *X1, *Y, *U, *V; MPI *Tmp, *Tmp0I, *Tmp1I, *Tmp2I, *Tmp3I, *Tmp4I, *Tmp5I; Tmp0I = POWER_I(10L, r); Tmp1I = POWERI(Tmp0I, 2);/* 10^2r */ Tmp2I = POWERI(Tmp1I, 2);/* 10^4r */ Tmp3I = POWERI(Tmp2I, 2);/* 10^8r */ Tmp = MULT_I(Tmp2I, 2L); X = BIG_MTHROOT(Tmp, 2); FREEMPI(Tmp); Tmp4I = MULT_I(Tmp1I, 2L); PI = ADD0I(Tmp4I, X); FREEMPI(Tmp4I); Tmp4I = MULT_I(Tmp3I, 2L); Y = BIG_MTHROOT(Tmp4I, 4); FREEMPI(Tmp3I); FREEMPI(Tmp4I); while (1) { Tmp4I = ADD0I(X, Tmp1I); Tmp = X; X = MULTI(Tmp0I, Tmp4I); FREEMPI(Tmp); Tmp3I = BIG_MTHROOT(X, 2); X1 = MULT_I(Tmp3I, 2L); Tmp = X; X = INT0(X, X1); FREEMPI(Tmp); FREEMPI(X1); U = MULTI(X, Y); Tmp = U; U = ADD0I(U, Tmp2I); printf(" U = "); PRINTI(U); printf("\n"); FREEMPI(Tmp); Tmp5I = ADD0I(Y, Tmp1I); V = MULTI(Tmp3I, Tmp5I); Tmp = V; V = MULTI(V, Tmp0I); FREEMPI(Tmp); Tmp = Y; Y = INT0(U, V); printf(" V = "); PRINTI(V); printf("\n"); FREEMPI(U); FREEMPI(V); printf(" Y = "); PRINTI(Y); printf("\n"); if (EQUALI(Tmp1I, Y)) { FREEMPI(Tmp0I); FREEMPI(Tmp1I); FREEMPI(Tmp2I); FREEMPI(Tmp3I); FREEMPI(Tmp4I); FREEMPI(Tmp5I); return (PI); } Tmp = PI; PI = MULTI(PI, Tmp4I); FREEMPI(Tmp); Tmp = PI; PI = INT0(PI, Tmp5I); FREEMPI(Tmp4I); FREEMPI(Tmp5I); } } MPR *PII(unsigned int r) /* * From " A very rapidly convergent product expansion for pi," Bit 23 (1983) * 538-540, by J.M. Borwein and P.B. Borwein. The algorithm delivers pi * to 2^r decimals. */ { MPR * Tmp1, * Tmp2, * Tmp3, * Tmp4, * Tmp5, * Tmp6, * Tmp7, *Tmp8; MPR *X, *Y, *PI, *ONE, *TWO, *Tmp, *TEST, *SS, *TEN, *Tmp9; MPI *S, *TmpI; unsigned int s; S = POWER_I(2L, r); s = CONVERTI(S); FREEMPI(S); SS = BUILDMPR(); SS->N = POWER_I(10L, s + 1); SS->D = ONEI(); ONE = ONER(); TWO = BUILDMPR(); TWO->N = CHANGE((USL)2); TWO->D = ONEI(); TEN = BUILDMPR(); TEN->N = CHANGE((USL)10); TEN->D = ONEI(); X = MTHROOTR(TWO, 2, s + 1); PI = ADDR(TWO, X); Tmp1 = MTHROOTR(X, 2, s + 1); Tmp2 = INVERSER(Tmp1); Tmp3 = ADDR(Tmp1, Tmp2); Tmp = X; X = RATIOR(Tmp3, TWO); printf("X = "); PRINTDR(s, X); printf("\n"); FREEMPR(Tmp); FREEMPR(Tmp1); FREEMPR(Tmp2); FREEMPR(Tmp3); Y = MTHROOTR(TWO, 4, s + 1); while (1) { Tmp1 = MTHROOTR(X, 2, s + 1); Tmp2 = INVERSER(Tmp1); Tmp3 = ADDR(Tmp1, Tmp2); Tmp4 = RATIOR(Tmp3, TWO); Tmp5 = MULTR(Y, Tmp1); Tmp6 = ADDR(Tmp5, Tmp2); Tmp7 = ADDR(Y, ONE); Tmp8 = ADDR(X, ONE); Tmp = PI; PI = MULTR(Tmp8, PI); FREEMPR(Tmp); Tmp = PI; PI = RATIOR(PI, Tmp7); FREEMPR(Tmp); Tmp = X; X = Tmp4; FREEMPR(Tmp); printf("X = "); PRINTDR(s, X); printf("\n"); Tmp = Y; Y = RATIOR(Tmp6, Tmp7); FREEMPR(Tmp); printf("Y = "); PRINTDR(s, Y); printf("\n"); TEST = SUBR(Y, ONE); Tmp = TEST; Tmp9 = MULTR(SS, TEN); TEST = MULTR(Tmp9, TEST); FREEMPR(Tmp); TmpI = INT0(TEST->N, TEST->D); FREEMPR(TEST); if (TmpI->S == 0) { printf("Y - 1 = "); PRINTDR(s, Y); printf("\n"); FREEMPR(Tmp1); FREEMPR(Tmp2); FREEMPR(Tmp3); FREEMPR(Tmp5); FREEMPR(Tmp6); FREEMPR(Tmp7); FREEMPR(Tmp8); FREEMPR(Tmp9); FREEMPI(TmpI); FREEMPR(ONE); FREEMPR(TWO); FREEMPR(TEN); FREEMPR(SS); FREEMPR(X); FREEMPR(Y); return (PI); } FREEMPR(Tmp1); FREEMPR(Tmp2); FREEMPR(Tmp3); FREEMPR(Tmp5); FREEMPR(Tmp6); FREEMPR(Tmp7); FREEMPR(Tmp8); FREEMPR(Tmp9); FREEMPI(TmpI); } }