📄 i8.c
字号:
/* i8.c */
#include <stdio.h>
#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);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -