www.pudn.com > calc.rar > i1.c
/* program "i1.c" */ /* * A translation into C of the pascal program ARITHMETIC, addition, * subtraction, multiplication and exponentiation. * from "SCIENTIFIC PASCAL" by H. FLANDERS pp. 342-357. */ #include#include #include #include "integer.h" #include "fun.h" int MAX(int i, int j) { return(i >= j ? i: j); } int MIN(int i, int j) { return(i <= j ? i: j); } MPI *MAXMPI(MPI *I, MPI *J) { return(COMPAREI(I, J) >= 0 ? COPYI(I): COPYI(J)); } MPI *MINMPI(MPI *I, MPI *J) { return(COMPAREI(I, J) <= 0 ? COPYI(I): COPYI(J)); } int RSV(MPI *Aptr, MPI *Bptr) { /* * relative sizes of absolute values of MPI'S *Aptr and *Bptr. * 1 if |*Aptr| > |*Bptr| * RSV(Aptr, Bptr) = 0 if |*Aptr| = |*Bptr| * -1 if |*Aptr| < |*Bptr| */ unsigned int j; if (Aptr->D > Bptr->D) return (1); else if (Aptr->D < Bptr->D) return (-1); else { j = Aptr->D; while ((Aptr->V[j] == Bptr->V[j]) && j) j-- ; if (Aptr->V[j] > Bptr->V[j]) return (1); else if (Aptr->V[j] < Bptr->V[j]) return (-1); else return (0); } } MPI *ADD0I(MPI *Aptr, MPI *Bptr) /* * input: Aptr and Bptr are pointers to non-negative MPI'S. * output: *Eptr = *Aptr + *Bptr. */ { unsigned int j, m, n; unsigned long c, t; MPI *Eptr; MPI *tmp; m = (unsigned int)MIN((int) Aptr->D, (int) Bptr->D); n = (unsigned int)MAX((int) Aptr->D, (int) Bptr->D); c = 0; Eptr = BUILDMPI(n + 1); for (j = 0; j <= m; j++) { t = Aptr->V[j] + Bptr->V[j] + c; Eptr->V[j] = t & (R0 - 1); c = t >> T0; } if (Aptr->D > Bptr->D) { for (j = 1 + m; j <= Aptr->D; j++) { t = Aptr->V[j] + c; Eptr->V[j] = t & (R0 - 1); c = t >> T0; } } if (Aptr->D < Bptr->D) { for (j = 1 + m; j <= Bptr->D; j++) { t = Bptr->V[j] + c; Eptr->V[j] = t & (R0 - 1); c = t >> T0; } } if (c) { tmp = BANK_REALLOC(Eptr, n + 1); FREEMPI(Eptr); Eptr = tmp; Eptr->V[n + 1] = c; } Eptr->S = MAX(Aptr->S, Bptr->S); return Eptr; } MPI *ADD0_I(MPI *Aptr, unsigned long b) /* * input: Aptr is a pointer to a non-negative MPI. * b is a non-negative integer < R0. * output: *Eptr = *Aptr + b. */ { unsigned int j, n; unsigned long c, t; MPI *Eptr, *tmp; if (b >= R0) { fprintf(stderr, "in ADD0_I, %lu >= R0\n", b); exit(1); } if (b == 0) return COPYI(Aptr); n = Aptr->D; Eptr = BUILDMPI(n + 1); c = b; for (j = 0; j <= n; j++) { t = Aptr->V[j] + c; Eptr->V[j] = t & (R0 - 1); c = t >> T0; } if (c) { tmp = Eptr; Eptr = BANK_REALLOC(Eptr, n + 1); FREEMPI(tmp); Eptr->V[n + 1] = c; } Eptr->S = b ? 1 : Aptr->S; return Eptr; } MPI *SUB0I(MPI *Aptr, MPI *Bptr) /* * input: Aptr, Bptr, pointers to non-negative MPI'S, *Aptr >= *Bptr. * output: MPI *Eptr = *Aptr - *Bptr. */ { int k; unsigned int d, e, j, m, n; unsigned long c, t; MPI *Eptr, *tmptr; if (Bptr->S == 0) return COPYI(Aptr); n = Aptr->D; Eptr = BUILDMPI(n + 1); m = Bptr->D; c = 1; /* c = 1: no borrow, c = 0: a borrow */ for (j = 0; j <= m; j++) { t = Aptr->V[j] - Bptr->V[j] + R0 + c - 1; Eptr->V[j] = t & (R0 - 1); c = t >> T0; } if (n > m) { for (j = m + 1; j <= n; j++) { t = Aptr->V[j] + R0 + c - 1; Eptr->V[j] = t & (R0 - 1); c = t >> T0; } } /* finding Eptr->S and Eptr->D */ Eptr->S = 0; d = 0; k = n; while (k >= 0) { if (Eptr->V[k] != 0) { Eptr->S = 1; d = k; k = -1; } else k-- ; } e = n - d; if (e) { tmptr = BANK_REALLOC(Eptr, d); FREEMPI(Eptr); Eptr = tmptr; } return Eptr; } MPI *SUB0_I(MPI *Aptr, unsigned long b) /* * input: Aptr a pointer to a non-negative MPI. b a non-negative integer, * b < R0, *Aptr >= b; output: *Eptr = *Aptr - b. */ { unsigned int e, j, n; unsigned long c, t; MPI *Eptr, *tmp; if (b >= R0) { fprintf(stderr, "in SUB0_I, %lu >= R0\n", b); exit(1); } if (b == 0) return COPYI(Aptr); n = Aptr->D; Eptr = BUILDMPI(n + 1); c = 1; /* c = 1: no borrow, c = 0: a borrow. */ t = Aptr->V[0] - b + R0; Eptr->V[0] = t & (R0 - 1); c = t >> T0; for (j = 1; j <= n; j++) { t = Aptr->V[j] + R0 + c - 1; Eptr->V[j] = t & (R0 - 1); c = t >> T0; } if (Aptr->D) Eptr->S = 1; else Eptr->S = Eptr->V[0] ? 1 : 0; e = Eptr->V[n]; if (e == 0 && n ) { tmp = Eptr; Eptr = BANK_REALLOC(Eptr, n - 1); FREEMPI(tmp); } return Eptr; } MPI *ADDI(MPI *Aptr, MPI *Bptr) /* * input: Aptr and Bptr, pointers to MPI'S. * output: MPI *Eptr = *Aptr + *Bptr. */ { MPI *Eptr; if (Aptr->S == Bptr->S) { Eptr = ADD0I(Aptr, Bptr); Eptr->S = Aptr->S; } else { switch (RSV(Aptr, Bptr)) { case -1: { Eptr = SUB0I(Bptr, Aptr); Eptr->S = Bptr->S; break; } case 0: { Eptr = ZEROI(); break; } default: /* case 1: */ { Eptr = SUB0I(Aptr, Bptr); Eptr->S = Aptr->S; } } } return Eptr; } MPI *SUBI(MPI *Aptr, MPI *Bptr) /* * input: Aptr and Bptr, pointers to MPI'S. * output: MPI *Eptr = *Aptr - *Bptr. */ { MPI *Eptr; Bptr->S = -Bptr->S; Eptr = ADDI(Aptr, Bptr); Bptr->S = -Bptr->S; return Eptr; } MPI *BANK_REALLOC(MPI *Aptr, unsigned int degree) /* * Reallocs using the memory bank. The original MPI is Aptr, and the new one * has the given degree. */ { int size; MPI *Bptr; #ifdef _WIN32 unsigned int k; #endif if(Aptr->D <= degree) size = Aptr->D; else size = degree; Bptr = BUILDMPI(1 + degree); #ifdef _WIN32 for (k = 0; k <= size; k++) Bptr->V[k] = Aptr->V[k]; #else /* bcopy((char *)(Aptr->V), (char *)(Bptr->V), (1 + size) * sizeof(unsigned long)); */ Bptr->V = (USL *)memcpy((char *)(Bptr->V), (char *)(Aptr->V), (1 + size) * sizeof(unsigned long)); #endif Bptr->S = Aptr->S; return Bptr; } MPI *MULTI(MPI *Aptr, MPI *Bptr) /* * input: Aptr and Bptr, pointers to MPI'S. * output: MPI *Eptr = *Aptr * *Bptr. */ { register unsigned int j, bk, k, m, n; unsigned long c = 0, t; int e; MPI *Eptr, *tmp; e = Aptr->S * Bptr->S; if (e == 0) return ZEROI(); m = Aptr->D; n = Bptr->D; /* if (m < 1000 && n < 1000) { */ Eptr = BUILDMPI(m + n + 2); for (k = 0; k <= m; k++) Eptr->V[k] = 0; for (k = 0; k <= n; k++) { bk = Bptr->V[k]; if (bk != 0) { c = 0; for (j = 0; j <= m; j++) { t = Aptr->V[j] * bk + Eptr->V[j + k] + c; /* t < R0 * R0 = 2 ^ O32 */ Eptr->V[j + k] = t & (R0 - 1); c = t >> T0; /* c < R0 */ } Eptr->V[m + k + 1] = c; } else Eptr->V[m + k + 1] = 0; } if (c == 0) { tmp = BANK_REALLOC(Eptr, m + n); FREEMPI(Eptr); Eptr = tmp; } /* } */ /* else if (m < R0 && n < R0) Eptr = FFM(Aptr, Bptr, 3);*/ /* Fast Fourier Transform, 3 primes*/ /* else Eptr = FFM(Aptr, Bptr, 4);*/ /* Fast Fourier Transform, 4 primes*/ Eptr->S = e; return Eptr; } MPI *MULT_I(MPI *Aptr, long b) /* * input: Aptr is a pointer to an MPI, Aptr->D < K0. * b is an integer, |b| < R0. output: *Eptr = *Aptr * b. */ { unsigned int j, n; unsigned long a, c = 0, t; MPI *Eptr; MPI *tmp; if (abs(b) >= R0) { fprintf(stderr, "in MULT_I, %ld >= R0\n", b); exit(1); } if (b == 0 || Aptr->S == 0) return ZEROI(); n = Aptr->D; Eptr = BUILDMPI(n + 1); Eptr->S = b > 0 ? Aptr->S : - Aptr->S; a = b > 0 ? b : -b; for (j = 0; j <= n; j++) { t = Aptr->V[j] * a + c; Eptr->V[j] = t & ((USL)R0 - 1); c = t >> T0; } if (c) { tmp = BANK_REALLOC(Eptr, n + 1); FREEMPI(Eptr); Eptr = tmp; Eptr->V[n + 1] = c; } return Eptr; } MPI *POWERI(MPI *Aptr, unsigned n) /* * *Eptr = (*Aptr) ^ n, where 0 <= n < R0 * R0. */ { MPI *Btmp, *Ctmp, *Eptr; Eptr = ONEI(); if (n == 0) return Eptr; Btmp = COPYI(Aptr); while (1) { if (n & 1) { Ctmp = Eptr; Eptr = MULTI(Ctmp, Btmp); FREEMPI(Ctmp); if (n == 1) { FREEMPI(Btmp); return Eptr; } } Ctmp = Btmp; Btmp = MULTI(Ctmp, Ctmp); FREEMPI(Ctmp); n = n >> 1; } } MPI *POWER_I(long a, unsigned n) /* * n is a non-negative integer, n < R0 * R0. * a is an integer, |a| < R0. * *Eptr = a ^ n. */ { MPI *Eptr, *Btmp, *Ctmp; if (abs(a) >= R0) { fprintf(stderr, "in POWER_I, %ld >= R0\n", a); exit(1); } if (a == 0) return ZEROI(); if (n == 0) return ONEI(); Eptr = ONEI(); Btmp = BUILDMPI(1); Btmp->S = a > 0 ? 1 : -1; Btmp->V[0] = a > 0 ? a : -a; while (1) { if (n & 1) { Ctmp = Eptr; Eptr = MULTI(Ctmp, Btmp); FREEMPI(Ctmp); if (n == 1) { FREEMPI(Btmp); return Eptr; } } Ctmp = Btmp; Btmp = MULTI(Ctmp, Ctmp); FREEMPI(Ctmp); n = n >> 1; } } MPI *MULTI3(MPI *A, MPI *B, MPI *C) /* * Returns A * B * C. */ { MPI *Tmp1, *Tmp2; Tmp1 = MULTI(A, B); Tmp2 = MULTI(Tmp1, C); FREEMPI(Tmp1); return (Tmp2); } unsigned long MULT32(USL x, USL y) /* * Returns [x*y/2^32]. */ { MPI *X, *Y, *Z; USL t; X = CHANGE(x); Y = CHANGE(y); FREEMPI(X); FREEMPI(Y); Z = MULTI(X, Y); if (Z->D <= 1) t = 0; else if (Z->D == 2) t = Z->V[2]; else t = ((Z->V[3]) << 16) + Z->V[2]; FREEMPI(Z); return (t); } MPI *MULTABC(MPI *A, MPI *B, MPI *C) /* * Returns A + B * C. */ { MPI *Temp1, *Temp2; Temp1 = MULTI(B, C); Temp2 = ADDI(A, Temp1); FREEMPI(Temp1); return (Temp2); } MPI *SHIFTLB(MPI *U) /* * Multiplies U by R0. */ { MPI *T; unsigned int n, i; n = U->D + 1; T = BUILDMPI(n + 1); T->S = U->S; for (i = 1; i <= n; i++) T->V[i] = U->V[i - 1]; T->V[0] = 0; return (T); } MPI *MULT_II(MPI *Aptr, USL b) /* * output: MPI *Eptr = *Aptr * b, where b is an USL. */ { register unsigned int j, bk, k, m, n; unsigned long c = 0, t; int e; MPI *Eptr, *Bptr, *tmp; e = Aptr->S; if (e == 0) return ZEROI(); m = Aptr->D; Bptr = CHANGE(b); n = Bptr->D; Eptr = BUILDMPI(m + n + 2); for (k = 0; k <= m; k++) Eptr->V[k] = 0; for (k = 0; k <= n; k++) { bk = Bptr->V[k]; if (bk != 0) { c = 0; for (j = 0; j <= m; j++) { t = Aptr->V[j] * bk + Eptr->V[j + k] + c; /* t < R0 * R0 = 2 ^ O32 */ Eptr->V[j + k] = t & (R0 - 1); c = t >> T0; /* c < R0 */ } Eptr->V[m + k + 1] = c; } else Eptr->V[m + k + 1] = 0; } if (c == 0) { tmp = BANK_REALLOC(Eptr, m + n); FREEMPI(Eptr); Eptr = tmp; } Eptr->S = e; FREEMPI(Bptr); return Eptr; } int COMPAREI(MPI *Aptr, MPI *Bptr) /* * returns 1 if Aptr > Bptr, 0 if Aptr = Bptr, -1 if Aptr < Bptr. */ { MPI *Temp; int t; Temp = SUBI(Aptr, Bptr); t = Temp->S; FREEMPI(Temp); return (t); } int QSORTCOMPAREI(const void *Aptr, const void *Bptr) /* * returns 1 if Aptr > Bptr, 0 if Aptr = Bptr, -1 if Aptr < Bptr. */ { MPI *Temp; int t; Temp = SUBI(*(MPI **) Aptr, *(MPI **) Bptr); t = Temp->S; FREEMPI(Temp); return (t); } void QSORTMPI(MPI *A[], USI m, USI n) /* * Sorts the array of MPI's A[m],A[m+1],...,A[n] into * increasing order. */ { USI t; t = n - m + 1; printf("before qsort...t=%d\n",t); qsort((char*)(A + m), t, sizeof(MPI *), QSORTCOMPAREI); printf("after qsort\n"); return; } void QSORTMPI0(MPI *A[], USI m, USI n) /* * Sorts the array of non-negative MPI's A[m],A[m+1],...,A[n] into * increasing order. */ { USI t; t = n - m + 1; qsort((char*)(A + m), t, sizeof(MPI *), QSORTRSV); return; } int QSORTRSV(const void *Aptr, const void *Bptr) { /* * relative sizes of absolute values of MPI'S **Aptr and **Bptr. * 1 if |**Aptr| > |**Bptr| * RSV(Aptr, Bptr) = 0 if |**Aptr| = |**Bptr| * -1 if |**Aptr| < |**Bptr| * for use in QSORTMPI0(). */ unsigned int j; if (( *(MPI **) Aptr)->D > ( *(MPI **) Bptr)->D) return (1); else if (( *(MPI **) Aptr)->D < ( *(MPI **) Bptr)->D) return (-1); else { j = ( *(MPI **) Aptr)->D; while ((( *(MPI **) Aptr)->V[j] == ( *(MPI **) Bptr)->V[j]) && j) j-- ; if (( *(MPI **) Aptr)->V[j] > ( *(MPI **) Bptr)->V[j]) return (1); else if (( *(MPI **) Aptr)->V[j] < ( *(MPI **) Bptr)->V[j]) return (-1); else return (0); } } void QSORTMATI(MPMATI *Mptr, USI r, USI s) /* * Sorts the rows of *Mptr in increasing order of length. * Based on Kochan, p.142-143, Programming in ANSI C. */ { USI i, j, m; MPI **TEMP, *temp, **R; m = Mptr->R; R = (MPI **)mmalloc(m * sizeof(MPI *)); for (i = r; i <= s; i++) R[i] = DOTRI(Mptr, i, i); if (s > r) { for (i = r; i < s - 1; i++) for (j = i + 1; j <= s; j++) { if (RSV(R[i], R[j]) == 1) { temp = R[i]; R[i] = R[j]; R[j] = temp; TEMP = Mptr->V[i]; Mptr->V[i] = Mptr->V[j]; Mptr->V[j] = TEMP; } } } for (i = r; i <= s; i++) FREEMPI(R[i]); ffree((char *)R, m * sizeof(MPI *)); } /* Returns respectively positive, zero, negative if MPI is positive, zero * or negative */ int SIGNI(MPI *I) { if (I == NULL) return 0; else return I->S; }