www.pudn.com > calc.rar > log.c
#include "integer.h" #include#include #include #include "fun.h" #include "stack.h" #ifdef _WIN32 #include "unistd_DOS.h" #else #include #endif void INTLOG(Stack s) /* This performs variant 0 of Shank's log_b(a), * working as in bc scale 2r, but doing it in integers. * See http://www.maths.uq.edu.au/~krm/log.pdf * We print out the partial quotients n[0],...,n[r-1] if a>b, * n[0],...,n[r] if a a[1]=b. * The output is not guaranteed to be correct, but seems certain to be so. * See D. Shanks, "A logarithm algorithm", Math. Tables and Other Aids to * Computation 8, (1954). 60--64. */ { USI j; USL i, r, rr, n; MPI *AA, *BB, *C, *TMP1, *TMP2; MPI *A = stackPop(s); MPI *B = stackPop(s); MPI *R = stackPop(s); MPI *N = stackPop(s); i = 0; j = 2; rr = CONVERTI(R); FREEMPI(R); n = CONVERTI(N); FREEMPI(N); if (RSV(A, B) == -1) rr++; r = rr + rr; C = POWER_I(10, r); AA = MULTI(A, C); if (n){ printf("A[0] = "); PRINTI(AA); printf("\n"); } BB = MULTI(B, C); if (n){ printf("A[1] = "); PRINTI(BB); printf("\n"); } while (rr){ if (RSV(AA, BB) >= 0){ TMP1 = MULTI(AA, C); TMP2 = AA; AA = INT(TMP1, BB); FREEMPI(TMP1); FREEMPI(TMP2); i++; } else{ if (n){ printf("n[%u]=%lu, A[%u]=", j - 2, i, j); PRINTI(AA); } else printf("n[%u]=%lu", j - 2, i); printf("\n"); j++; TMP1 = BB; BB = AA; AA = TMP1; rr--; i = 0; /* reset the partial quotient count */ } } FREEMPI(AA); FREEMPI(BB); FREEMPI(A); FREEMPI(B); FREEMPI(C); return; } void LOG_(Stack s) /* This performs Shank's log a to base b algorithm, working in effect with * scale 2r, but doing it in integers. * We work with scale = 2r and believe that this is sufficient to correctly * output partial quotients a[0],...,a[s], where s=r-1 if n>b, but r if n = 0){ TMP1 = MULTI(AA, C); TMP2 = AA; AA = INT(TMP1, BB); FREEMPI(TMP1); FREEMPI(TMP2); i++; TMP1 = PN; PN = ADDI(PN, PP); FREEMPI(TMP1); TMP1 = QN; QN = ADDI(QN, QP); FREEMPI(TMP1); if(EQUALI(BB, C)){ PRINTI(A); FPRINTI(outfile, A); printf("^"); fprintf(outfile, "^"); PRINTI(PP); FPRINTI(outfile, PP); printf("="); fprintf(outfile, "="); PRINTI(B); FPRINTI(outfile, B); printf("^"); fprintf(outfile, "^"); PRINTI(QP); FPRINTI(outfile, QP); printf("\n"); fprintf(outfile, "\n"); FREEMPI(AA); FREEMPI(BB); FREEMPI(A); FREEMPI(B); FREEMPI(C); FREEMPI(PN); FREEMPI(PP); FREEMPI(QP); FREEMPI(QN); return; } } else{ if (n){ printf("n[%u]=%lu, A[%u]=", j - 2, i, j); PRINTI(AA); } else printf("n[%u]=%lu", j - 2, i); fprintf(outfile, "n[%u]=%lu, A[%u]=", j - 2, i, j); FPRINTI(outfile, AA); j++; TMP1 = BB; BB = AA; AA = TMP1; TMP1 = PN; PN = PP; PP = TMP1; TMP1 = QN; QN = QP; QP = TMP1; printf(", p[%u]/q[%u]=", j - 3, j - 3); PRINTI(QP); printf("/"); PRINTI(PP); fprintf(outfile, ", p[%u]/q[%u]=", j - 3, j - 3); FPRINTI(outfile, QP); fprintf(outfile, "/"); FPRINTI(outfile, PP); printf("\n"); fprintf(outfile, "\n"); rr--; i = 0; /* reset the partial quotient count */ } } printf("The log of "); fprintf(outfile, "The log of "); PRINTI(A); FPRINTI(outfile, A); printf(" to base "); fprintf(outfile, " to base "); PRINTI(B); FPRINTI(outfile, B); if (j == 3){ printf(" has integer part "); fprintf(outfile, " has integer part "); PRINTI(QP); FPRINTI(outfile, QP); printf("\n"); fprintf(outfile, "\n"); FREEMPI(AA); FREEMPI(BB); FREEMPI(A); FREEMPI(B); FREEMPI(C); FREEMPI(PN); FREEMPI(PP); FREEMPI(QP); FREEMPI(QN); fclose(outfile); return; } printf(" equals "); fprintf(outfile, " equals "); if (PN->S){ fclose(outfile); tt = COMPARE_DIGITS(QP, PP, QN, PN, 10); outfile = fopen(buff, "a"); if (tt == -1){ X = MULTI(QP, PN); Y = MULTI(PP, QN); printf(" has integer part "); fprintf(outfile, " has integer part "); if (RSV(X, Y)< 0) Z = INTI(QP, PP); else Z = INTI(QN, PN); PRINTI(Z); FPRINTI(outfile, Z); FREEMPI(Z); FREEMPI(X); FREEMPI(Y); printf("\n"); fprintf(outfile, "\n"); FREEMPI(AA); FREEMPI(BB); FREEMPI(A); FREEMPI(B); FREEMPI(C); FREEMPI(PN); FREEMPI(PP); FREEMPI(QP); FREEMPI(QN); fclose(outfile); return; } else{ printf(" truncated to %u decimal places\n", tt); fprintf(outfile, " truncated to %u decimal places\n", tt); } } FREEMPI(AA); FREEMPI(BB); FREEMPI(A); FREEMPI(B); FREEMPI(C); FREEMPI(PN); FREEMPI(PP); FREEMPI(QP); FREEMPI(QN); fclose(outfile); return; } int COMPARE_DIGITS(MPI *M, MPI *N, MPI *U, MPI *V, USL b) /* m,n,u,v are positive integers, b is the base. * We compare the base b expansions. If the integer parts * of m/n and u/v are equal, we go on to compare the expansions * after the decimal point. We print out the t common decimals and * the number t. */ { USI i, o; MPI *R, *S, *T, *P, *RR, *PP; MPI *MM, *UU, *TMP1; char buff[20]; FILE *outfile; R = INTI(M, N); RR = INTI(U, V); strcpy(buff, "log.out"); outfile = fopen(buff, "a"); if (EQUALI(R, RR)){ /* integer parts are equal */ PRINTI(R); FPRINTI(outfile, R); } else{ FREEMPI(R); FREEMPI(RR); fclose(outfile); return(-1); } TMP1 = MULTI(R, N); MM = SUBI(M, TMP1); FREEMPI(TMP1); TMP1 = MULTI(RR, V); UU = SUBI(U, TMP1); FREEMPI(TMP1); i = 0; P = MULT_I(MM, b); FREEMPI(MM); PP = MULT_I(UU, b); FREEMPI(UU); S = INT(P, N); /* the first decimal digit of {m/n} */ T = INT(PP, V);/* the first decimal digit of {u/v} */ FREEMPI(R); FREEMPI(RR); R = MOD(P, N); RR = MOD(PP, V); FREEMPI(P); FREEMPI(PP); printf("."); fprintf(outfile, "."); o = EQUALI(S, T); while(o){ PRINTI(S); FPRINTI(outfile, S); FREEMPI(S); FREEMPI(T); P = MULT_I(R, b); PP = MULT_I(RR, b); FREEMPI(R); FREEMPI(RR); R = MOD(P, N); RR = MOD(PP, V); S = INT(P, N); /* the first decimal digit of {m/n} */ T = INT(PP, V);/* the first decimal digit of {u/v} */ o = EQUALI(S, T); FREEMPI(P); FREEMPI(PP); i++; } FREEMPI(S); FREEMPI(T); FREEMPI(R); FREEMPI(RR); printf("\n"); fprintf(outfile, "\n"); fclose(outfile); return (i); /* the no. of common decimal digits after the decimal point */ } void INTLOG1(Stack s) /* This performs variant 1 of Shank's log_b(a), * See http://www.maths.uq.edu.au/~krm/log.pdf */ { USI j; USL i, r, rr, n; MPI *AA, *BB, *C, *TMP1, *TMP2, *E, *F; MPI *A = stackPop(s); MPI *B = stackPop(s); MPI *R = stackPop(s); MPI *N = stackPop(s); i = 0; j = 2; rr = CONVERTI(R); FREEMPI(R); n = CONVERTI(N); FREEMPI(N); if (RSV(A, B) == -1) rr++; r = rr + rr; C = POWER_I(10, r); F = POWER_I(10, rr + 2); E = ADD0I(C, F); FREEMPI(F); AA = MULTI(A, C); if (n){ printf("A[0] = "); PRINTI(AA); printf("\n"); } BB = MULTI(B, C); if (n){ printf("A[1] = "); PRINTI(BB); printf("\n"); } while (RSV(BB, E)>= 0){ if (RSV(AA, BB) >= 0){ TMP1 = MULTI(AA, C); TMP2 = AA; AA = INT(TMP1, BB); FREEMPI(TMP1); FREEMPI(TMP2); i++; } else{ if (n){ printf("n[%u]=%lu, A[%u]=", j - 2, i, j); PRINTI(AA); } else printf("n[%u]=%lu", j - 2, i); printf("\n"); j++; TMP1 = BB; BB = AA; AA = TMP1; /*rr--;*/ i = 0; /* reset the partial quotient count */ } } FREEMPI(AA); FREEMPI(BB); FREEMPI(A); FREEMPI(B); FREEMPI(C); FREEMPI(E); return; } void INTLOG2(Stack s) /* This performs variant 2 of Shank's log_b(a), * See http://www.maths.uq.edu.au/~krm/log.pdf */ { USI j; USL d, i, r, rr, n; MPI *AA, *BB, *C, *TMP1, *TMP2, *E, *F; MPI *U, *X, *Y, *Z; MPI *A = stackPop(s); MPI *B = stackPop(s); MPI *R = stackPop(s); MPI *N = stackPop(s); i = 0; j = 2; rr = CONVERTI(R); FREEMPI(R); n = CONVERTI(N); FREEMPI(N); if (RSV(A, B) == -1) rr++; r = rr + rr; C = POWER_I(10, r); F = POWER_I(10, rr + 2); E = ADD0I(C, F); FREEMPI(F); AA = MULTI(A, C); if (n){ printf("A[0] = "); PRINTI(AA); printf("\n"); } BB = MULTI(B, C); if (n){ printf("A[1] = "); PRINTI(BB); printf("\n"); } while (RSV(BB, E)>= 0){ Y = ONEI(); X = COPYI(AA); while(1){ U = INT0(X, Y); TMP1 = X; TMP2 = Y; X = MULTI(C, X); Y = MULTI(BB, Y); FREEMPI(TMP1); FREEMPI(TMP2); Z = MULTI(C, Y); d = RSV(Z, X); FREEMPI(Z); if (d == 1) break; i++; FREEMPI(U); } FREEMPI(X); FREEMPI(Y); FREEMPI(AA); AA = COPYI(U); FREEMPI(U); if (n){ printf("n[%u]=%lu, A[%u]=", j - 2, i, j); PRINTI(AA); } else printf("n[%u]=%lu", j - 2, i); printf("\n"); j++; TMP1 = BB; BB = AA; AA = TMP1; i = 0; /* reset the partial quotient count */ } FREEMPI(AA); FREEMPI(BB); FREEMPI(A); FREEMPI(B); FREEMPI(C); FREEMPI(E); return; } void LOG1(Stack s) /* This performs variant 1 of Shank's log a to base b algorithm, working in * effect with scale 2r, but doing it in integers. */ { USI j; int tt; USL i, r, rr, n; MPI *AA, *BB, *C, *TMP1, *TMP2; MPI *PN, *QP, *QN, *PP, *X, *Y, *Z; MPI *E, *F; char buff[20]; FILE *outfile; MPI *A = stackPop(s); MPI *B = stackPop(s); MPI *D = stackPop(s); MPI *R = stackPop(s); MPI *N = stackPop(s); i = 0; j = 2; PN = ONEI(); QP = ONEI(); QN = ZEROI(); PP = ZEROI(); rr = CONVERTI(R); FREEMPI(R); n = CONVERTI(N); FREEMPI(N); if (RSV(A, B) == -1) rr++; r = rr + rr; C = POWERI(D, r); F = POWERI(D, rr + 2); FREEMPI(D); E = ADD0I(C, F); FREEMPI(F); AA = MULTI(A, C); printf("Partial Quotient, Convergent\n"); printf("----------------------------\n"); if (n){ printf("A[0] = "); PRINTI(AA); printf("\n"); } strcpy(buff, "log1.out"); if(access(buff, R_OK) == 0) unlink(buff); outfile = fopen(buff, "w"); fprintf(outfile, "A[0] = "); FPRINTI(outfile, AA); fprintf(outfile, "\n"); BB = MULTI(B, C); if (n){ printf("A[1] = "); PRINTI(BB); printf("\n"); } fprintf(outfile, "A[1] = "); FPRINTI(outfile, BB); fprintf(outfile, "\n"); while (RSV(BB, E) >= 0){ if (RSV(AA, BB) >= 0){ TMP1 = MULTI(AA, C); TMP2 = AA; AA = INT(TMP1, BB); FREEMPI(TMP1); FREEMPI(TMP2); i++; TMP1 = PN; PN = ADDI(PN, PP); FREEMPI(TMP1); TMP1 = QN; QN = ADDI(QN, QP); FREEMPI(TMP1); if(EQUALI(BB, C)){ PRINTI(A); FPRINTI(outfile, A); printf("^"); fprintf(outfile, "^"); PRINTI(PP); FPRINTI(outfile, PP); printf("="); fprintf(outfile, "="); PRINTI(B); FPRINTI(outfile, B); printf("^"); fprintf(outfile, "^"); PRINTI(QP); FPRINTI(outfile, QP); printf("\n"); fprintf(outfile, "\n"); FREEMPI(AA); FREEMPI(BB); FREEMPI(A); FREEMPI(B); FREEMPI(C); FREEMPI(PN); FREEMPI(PP); FREEMPI(QP); FREEMPI(QN); return; } } else{ if (n){ printf("n[%u]=%lu, A[%u]=", j - 2, i, j); PRINTI(AA); } else printf("n[%u]=%lu", j - 2, i); fprintf(outfile, "n[%u]=%lu, A[%u]=", j - 2, i, j); FPRINTI(outfile, AA); j++; TMP1 = BB; BB = AA; AA = TMP1; TMP1 = PN; PN = PP; PP = TMP1; TMP1 = QN; QN = QP; QP = TMP1; printf(", p[%u]/q[%u]=", j - 3, j - 3); PRINTI(QP); printf("/"); PRINTI(PP); fprintf(outfile, ", p[%u]/q[%u]=", j - 3, j - 3); FPRINTI(outfile, QP); fprintf(outfile, "/"); FPRINTI(outfile, PP); printf("\n"); fprintf(outfile, "\n"); /* rr--; */ i = 0; /* reset the partial quotient count */ } } printf("The log of "); fprintf(outfile, "The log of "); PRINTI(A); FPRINTI(outfile, A); printf(" to base "); fprintf(outfile, " to base "); PRINTI(B); FPRINTI(outfile, B); if (j == 3){ printf(" has integer part "); fprintf(outfile, " has integer part "); PRINTI(QP); FPRINTI(outfile, QP); printf("\n"); fprintf(outfile, "\n"); FREEMPI(AA); FREEMPI(BB); FREEMPI(A); FREEMPI(B); FREEMPI(C); FREEMPI(PN); FREEMPI(PP); FREEMPI(QP); FREEMPI(QN); fclose(outfile); return; } printf(" equals "); fprintf(outfile, " equals "); if (PN->S){ fclose(outfile); tt = COMPARE_DIGITS(QP, PP, QN, PN, 10); outfile = fopen(buff, "a"); if (tt == -1){ X = MULTI(QP, PN); Y = MULTI(PP, QN); printf(" has integer part "); fprintf(outfile, " has integer part "); if (RSV(X, Y)< 0) Z = INTI(QP, PP); else Z = INTI(QN, PN); PRINTI(Z); FPRINTI(outfile, Z); FREEMPI(Z); FREEMPI(X); FREEMPI(Y); printf("\n"); fprintf(outfile, "\n"); FREEMPI(AA); FREEMPI(BB); FREEMPI(A); FREEMPI(B); FREEMPI(C); FREEMPI(PN); FREEMPI(PP); FREEMPI(QP); FREEMPI(QN); fclose(outfile); return; } else{ printf(" truncated to %u decimal places\n", tt); fprintf(outfile, " truncated to %u decimal places\n", tt); } } FREEMPI(AA); FREEMPI(BB); FREEMPI(A); FREEMPI(B); FREEMPI(C); FREEMPI(PN); FREEMPI(PP); FREEMPI(QP); FREEMPI(QN); FREEMPI(E); fclose(outfile); return; } void LOGG(Stack S) /* This performs variant 1 of Shank's log_b(a), * See http://www.maths.uq.edu.au/~krm/log.pdf */ { USL i, j, n, nn, r, rr, s, ss; MPI *A, *B, *C, *AA, *BB, *CC, *TMP1, *TMP2; MPI *X = stackPop(S); MPI *Y = stackPop(S); MPI *D = stackPop(S); MPI *R = stackPop(S); MPI *RR = stackPop(S); i = 0; j = 0; s = 2; ss = 2; r = CONVERTI(R); rr = CONVERTI(RR); FREEMPI(R); FREEMPI(RR); if(r >= rr){ FREEMPI(X); FREEMPI(Y); FREEMPI(D); execerror("arg 4 >= arg5", ""); } C = POWERI(D, (USI)r); A = MULTI(X, C); B = MULTI(Y, C); CC = POWERI(D, (USI)rr); AA = MULTI(X, CC); BB = MULTI(Y, CC); FREEMPI(D); FREEMPI(X); FREEMPI(Y); while (RSV(B, C) >= 0 && RSV(BB, CC) >= 0){ while (RSV(A, B) >= 0){ TMP1 = MULTI(A, C); TMP2 = A; A = INT(TMP1, B); FREEMPI(TMP1); FREEMPI(TMP2); i++; } n = i; printf("n=%lu\n", n); s++; TMP1 = B; B = A; A = TMP1; i = 0; /* reset the partial quotient count */ printf("AA="); PRINTI(AA); printf("\n"); printf("BB="); PRINTI(BB); printf("\n"); while (RSV(AA, BB) >= 0){ TMP1 = MULTI(AA, CC); TMP2 = AA; AA = INT(TMP1, BB); FREEMPI(TMP1); FREEMPI(TMP2); j++; printf("AA="); PRINTI(AA); printf("\n"); printf("BB="); PRINTI(BB); printf("\n"); } nn = j; printf("nn=%lu\n", nn); ss++; TMP1 = BB; BB = AA; AA = TMP1; j = 0; /* reset the partial quotient count */ if (n != nn){ printf("%lu != %lu\n", n, nn); printf("breaking\n"); break; } printf("n[%lu]=%lu\n", s - 3, n); } FREEMPI(A); FREEMPI(B); FREEMPI(AA); FREEMPI(BB); FREEMPI(C); FREEMPI(CC); return; } void LOGGG(Stack S) /* This performs variant 1 of Shank's log_b(a), * See http://www.maths.uq.edu.au/~krm/log.pdf */ { int tt; USL e, i, j, n, nn, r, rr, s, ss; MPI *A, *B, *C, *AA, *BB, *CC, *TMP1, *TMP2; MPI *PN, *QP, *QN, *PP, *X, *Y, *Z, *QNN, *PNN; char buff[20]; FILE *outfile; MPI *XX = stackPop(S); MPI *YY = stackPop(S); MPI *D = stackPop(S); MPI *R = stackPop(S); MPI *RR = stackPop(S); MPI *E = stackPop(S); i = 0; j = 0; e = CONVERTI(E); FREEMPI(E); PN = ONEI(); QP = ONEI(); QN = ZEROI(); PP = ZEROI(); PNN = ONEI(); QNN = ZEROI(); s = 2; ss = 2; r = CONVERTI(R); rr = CONVERTI(RR); FREEMPI(R); FREEMPI(RR); if(r >= rr){ FREEMPI(XX); FREEMPI(YY); FREEMPI(D); FREEMPI(E); execerror("arg 4 >= arg5", ""); } C = POWERI(D, (USI)r); A = MULTI(XX, C); B = MULTI(YY, C); CC = POWERI(D, (USI)rr); AA = MULTI(XX, CC); BB = MULTI(YY, CC); FREEMPI(D); strcpy(buff, "log.out"); outfile = fopen(buff, "w"); while (RSV(B, C) > 0 && RSV(BB, CC) > 0){ if (e){ FREEMPI(PNN); FREEMPI(QNN); PNN = COPYI(PN); QNN = COPYI(QN); } while (RSV(A, B) >= 0){ TMP1 = MULTI(A, C); TMP2 = A; A = INT(TMP1, B); FREEMPI(TMP1); FREEMPI(TMP2); i++; if (e){ TMP1 = PN; PN = ADDI(PN, PP); FREEMPI(TMP1); TMP1 = QN; QN = ADDI(QN, QP); FREEMPI(TMP1); } } n = i; s++; TMP1 = B; B = A; A = TMP1; i = 0; /* reset the partial quotient count */ while (RSV(AA, BB) >= 0){ TMP1 = MULTI(AA, CC); TMP2 = AA; AA = INT(TMP1, BB); FREEMPI(TMP1); FREEMPI(TMP2); j++; } nn = j; ss++; TMP1 = BB; BB = AA; AA = TMP1; j = 0; /* reset the partial quotient count */ if (n != nn){ /* printf("%lu != %lu\n", n, nn); printf("breaking\n");*/ break; } if (e){ printf("n[%lu]=%lu:", s - 3, n); fprintf(outfile, "n[%lu]=%lu:", s - 3, n); } else{ printf("n[%lu]=%lu\n", s - 3, n); fprintf(outfile, "n[%lu]=%lu\n", s - 3, n); } if (e){ TMP1 = PN; PN = PP; PP = TMP1; TMP1 = QN; QN = QP; QP = TMP1; if(EQUALI(B, C)){ /* tricky-needed if B=C is reached and n !=nn is not encountered */ FREEMPI(PNN); FREEMPI(QNN); PNN = COPYI(PN); QNN = COPYI(QN); } printf("p[%lu]/q[%lu]=", s - 3, s - 3); PRINTI(QP); printf("/"); PRINTI(PP); fprintf(outfile, "p[%lu]/q[%lu]=", s - 3, s - 3); FPRINTI(outfile, QP); fprintf(outfile, "/"); FPRINTI(outfile, PP); printf("\n"); fprintf(outfile, "\n"); } } if(e){ printf("The log of "); fprintf(outfile, "The log of "); PRINTI(XX); FPRINTI(outfile, XX); printf(" to base "); fprintf(outfile, " to base "); PRINTI(YY); FPRINTI(outfile, YY); FREEMPI(XX); FREEMPI(YY); if (s == 3){ printf(" has integer part "); fprintf(outfile, " has integer part "); PRINTI(QP); FPRINTI(outfile, QP); printf("\n"); fprintf(outfile, "\n"); FREEMPI(AA); FREEMPI(BB); FREEMPI(A); FREEMPI(B); FREEMPI(C); FREEMPI(PN); FREEMPI(PP); FREEMPI(QP); FREEMPI(QN); FREEMPI(PNN); FREEMPI(QNN); fclose(outfile); return; } printf(" equals "); fprintf(outfile, " equals "); if (PN->S){ fclose(outfile); tt = COMPARE_DIGITS(QP, PP, QNN, PNN, 10); outfile = fopen(buff, "a"); if (tt == -1){ X = MULTI(QP, PN); Y = MULTI(PP, QN); printf(" has integer part "); fprintf(outfile, " has integer part "); if (RSV(X, Y)< 0) Z = INTI(QP, PP); else Z = INTI(QN, PN); PRINTI(Z); FPRINTI(outfile, Z); FREEMPI(Z); FREEMPI(X); FREEMPI(Y); printf("\n"); fprintf(outfile, "\n"); FREEMPI(AA); FREEMPI(BB); FREEMPI(A); FREEMPI(B); FREEMPI(C); FREEMPI(CC); FREEMPI(PN); FREEMPI(PP); FREEMPI(QP); FREEMPI(QN); FREEMPI(QNN); FREEMPI(PNN); fclose(outfile); return; } else{ printf(" truncated to %u decimal places\n", tt); fprintf(outfile, " truncated to %u decimal places\n", tt); } } } FREEMPI(A); FREEMPI(B); FREEMPI(AA); FREEMPI(BB); FREEMPI(C); FREEMPI(CC); FREEMPI(PN); FREEMPI(PP); FREEMPI(QP); FREEMPI(QN); FREEMPI(XX); FREEMPI(YY); FREEMPI(QNN); FREEMPI(PNN); fclose(outfile); return; } void SHANKSLOG(Stack s) /* This performs Shank's log_b(a), * See http://www.maths.uq.edu.au/~krm/log.pdf * See D. Shanks, "A logarithm algorithm", Math. Tables and Other Aids to * Computation 8, (1954). 60--64. * We print the a[i] for i <= n, to d decimal places. */ { USL i, n; USI j, d; MPR *AA, *BB, *TMP1; MPI *A = stackPop(s); MPI *B = stackPop(s); MPI *D = stackPop(s); MPI *N = stackPop(s); i = 0; j = 2; d = (USI)CONVERTI(D); FREEMPI(D); n = CONVERTI(N); FREEMPI(N); printf("a[0] = "); PRINTI(A); printf("\n"); printf("a[1] = "); PRINTI(B); printf("\n"); AA = BUILDMPR(); AA->N = COPYI(A); AA->D = ONEI(); FREEMPI(A); BB = BUILDMPR(); BB->N = COPYI(B); BB->D = ONEI(); FREEMPI(B); while (j <= n){ printf("Starting AA "); PRINTDR(d, AA); printf("; BB to "); PRINTDR(d, BB); printf("\n"); while (COMPARER(AA, BB) >=0){ TMP1 = AA; AA = RATIOR(AA, BB); printf("decreasing AA to "); PRINTDR(d, AA); printf("; BB="); PRINTDR(d, BB); printf("\n"); FREEMPR(TMP1); i++; } printf("n[%u]=%lu, A[%u]=", j - 2, i, j); PRINTDR(d, AA); printf("\n"); j++; TMP1 = BB; BB = AA; AA = TMP1; i = 0; /* reset the partial quotient count */ } FREEMPR(AA); FREEMPR(BB); return; } void LOG(MPI *A, MPI *B, MPI *D, MPI *R, MPIA *M, MPI **L) /* Returns an array M[] of L positive integers that are hopefully * partial quotients of log(A)/log(B), using C=D^R. * Here A > B > 1, D > 1, R >= 1 * Uses an algorithm in http://www.numbertheory.org/pdfs/log.pdf */ { USL i, ii, r, s; USI l, flag=1; MPI *AA, *BB, *AAA, *BBB, *C, *TMP1, *TMP2, *I; MPIA P, Q; char buff[20]; FILE *outfile; P= NULL; Q= NULL; s = 0; r = CONVERTI(R); C = POWERI(D, r); AA = MULTI(A, C); BB = MULTI(B, C); AAA = COPYI(AA); BBB = COPYI(BB); *M = BUILDMPIA(); i = ii = 0; strcpy(buff, "log.out"); outfile = fopen(buff, "w"); fprintf(outfile, "Output from log("); FPRINTI(outfile, A); fprintf(outfile, ","); FPRINTI(outfile, B); fprintf(outfile, ","); FPRINTI(outfile, D); fprintf(outfile, ","); FPRINTI(outfile, R); fprintf(outfile, ")\n"); while (RSV(BB, C) > 0 && RSV(BBB, C) > 0){ i = 0; while (RSV(AA, BB) >= 0){ TMP1 = MULTI(AA, C); TMP2 = AA; AA = INT(TMP1, BB); FREEMPI(TMP1); FREEMPI(TMP2); i++; } TMP1 = BB; BB = AA; AA = TMP1; ii = 0; while (RSV(AAA, BBB) >= 0){ TMP1 = MULTI(AAA, C); TMP2 = AAA; AAA = CEILINGI(TMP1, BBB); FREEMPI(TMP1); FREEMPI(TMP2); ii++; } TMP1 = BBB; BBB = AAA; AAA = TMP1; if(!EQUALI(BB, BBB)) flag = 0; if (i == ii){ I = CHANGEI(i); ADD_TO_MPIA(*M, I, s); /* fprintf(outfile, "m[%lu]=%lu\n", s, i);*/ fprintf(outfile, "%lu", i); /*for use in Latexing*/ if((s+1)%20!=0) fprintf(outfile, "&"); else fprintf(outfile, "\\\\\n"); FREEMPI(I); } else{ printf("M[%lu]=%lu != %lu=M'[%lu]\n", s,i,ii, s); fprintf(outfile, "M[%lu]=%lu != %lu=M'[%lu]\n", s,i,ii, s); flag = 0; break; } s++; } *L = CHANGE(s); if(flag && EQUALI(BB, C) && EQUALI(BBB, C)){ printf("log("); PRINTI(A); printf(")"); printf("/log("); PRINTI(B); printf(")"); printf(" is likely to be the rational number "); l = (*M)->size; CONVERGENTS(*M, &P, &Q); PRINTI(P->A[l-1]); printf("/"); PRINTI(Q->A[l-1]); printf("\n"); FREEMPIA(P); FREEMPIA(Q); } FREEMPI(C); FREEMPI(AA); FREEMPI(AAA); FREEMPI(BB); FREEMPI(BBB); fclose(outfile); } MPI *LOGX(MPI *A, MPI *B, MPI *D, MPI *R, MPIA *M, MPI **L) { MPI *TMP = ONEI(); int s; s = COMPAREI(B, TMP); if (s <= 0){ printf("B <= 1\n"); FREEMPI(TMP); M = NULL; return NULL; } s = COMPAREI(D, TMP); if (s <= 0){ printf("D <= 1\n"); FREEMPI(TMP); M = NULL; return NULL; } s = COMPAREI(A, B); if (s <= 0){ printf("A <= B\n"); FREEMPI(TMP); M = NULL; return NULL; } s = COMPAREI(R, TMP); if (s < 0){ printf("R < 1\n"); FREEMPI(TMP); M = NULL; return NULL; } FREEMPI(TMP); LOG(A, B, D, R, M, L); return ONEI(); } void TESTLOG1(MPI *A, MPI *B, MPI *D, MPI *R) /* This is similar to LOG, but is for use in TESTLOG2 */ { USL i, ii, r, s; MPI *AA, *BB, *AAA, *BBB, *C, *TMP1, *TMP2; char buff[20]; FILE *outfile; s = 0; r = CONVERTI(R); C = POWERI(D, r); AA = MULTI(A, C); BB = MULTI(B, C); AAA = COPYI(AA); BBB = COPYI(BB); i = ii = 0; strcpy(buff, "testlog.out"); outfile = fopen(buff, "a"); while (RSV(BB, C) > 0 && RSV(BBB, C) > 0){ i = 0; while (RSV(AA, BB) >= 0){ TMP1 = MULTI(AA, C); TMP2 = AA; AA = INT(TMP1, BB); FREEMPI(TMP1); FREEMPI(TMP2); i++; } TMP1 = BB; BB = AA; AA = TMP1; ii = 0; while (RSV(AAA, BBB) >= 0){ TMP1 = MULTI(AAA, C); TMP2 = AAA; AAA = CEILINGI(TMP1, BBB); FREEMPI(TMP1); FREEMPI(TMP2); ii++; } TMP1 = BBB; BBB = AAA; AAA = TMP1; if (i == ii){ printf("%lu,", i); fflush(stdout); fprintf(outfile, "%lu,", i); } else break; s++; } printf("\n"); fprintf(outfile,"\n"); FREEMPI(C); FREEMPI(AA); FREEMPI(AAA); FREEMPI(BB); FREEMPI(BBB); fclose(outfile); } void TESTLOG(MPI *A, MPI *B, MPI *D, MPI *M, MPI *N) /* runs TESTLOG1(A,B,D,R) for R=M,...,N. */ { USL r, m, n; MPI *R; char buff[20]; FILE *outfile; strcpy(buff, "testlog.out"); outfile = fopen(buff, "w"); m = CONVERTI(M); n = CONVERTI(N); for (r = m; r <= n; r++){ R = CHANGE(r); TESTLOG1(A, B, D, R); FREEMPI(R); } fclose(outfile); } MPI *TESTLOGX(MPI *A, MPI *B, MPI *D, MPI *M, MPI *N) { MPI *TMP = ONEI(); int s; s = COMPAREI(B, TMP); if (s <= 0){ printf("B <= 1\n"); FREEMPI(TMP); M = NULL; return NULL; } s = COMPAREI(D, TMP); if (s <= 0){ printf("D <= 1\n"); FREEMPI(TMP); M = NULL; return NULL; } s = COMPAREI(A, B); if (s <= 0){ printf("A <= B\n"); FREEMPI(TMP); M = NULL; return NULL; } s = COMPAREI(M, TMP); if (s < 0){ printf("M < 1\n"); FREEMPI(TMP); M = NULL; return NULL; } s = COMPAREI(M, TMP); if (s < 0){ printf("M < 1\n"); FREEMPI(TMP); M = NULL; return NULL; } s = COMPAREI(N, M); if (s < 0){ printf("N < M\n"); FREEMPI(TMP); M = NULL; return NULL; } FREEMPI(TMP); TESTLOG(A, B, D, M, N); return ONEI(); }