void auxmulg(giant a, giant b) /* Optimized general multiply, b becomes a*b. Modes are: * AUTO_MUL: switch according to empirical speed criteria. * GRAMMAR_MUL: force grammar-school algorithm. * KARAT_MUL: force Karatsuba divide-conquer method. * FFT_MUL: force floating point FFT method. */ { float grammartime; int square = (a == b); int sizea, sizeb; switch (mulmode) { case GRAMMAR_MUL: if (square) grammarsquareg(b); else grammarmulg(a, b); break; case FFT_MUL: if (square) FFTsquareg(b); else FFTmulg(a, b); break; case KARAT_MUL: if (square) karatsquareg(b); else karatmulg(a, b); break; case AUTO_MUL: sizea = abs(a->sign); sizeb = abs(b->sign); if ((sizea > KARAT_BREAK) && (sizea <= FFT_BREAK) && (sizeb > KARAT_BREAK) && (sizeb <= FFT_BREAK)) { if (square) karatsquareg(b); else karatmulg(a, b); } else { grammartime = (float)sizea; grammartime *= (float)sizeb; if (grammartime < FFT_BREAK * FFT_BREAK) { if (square) grammarsquareg(b); else grammarmulg(a, b); } else { if (square) FFTsquareg(b); else FFTmulg(a, b); } } break; } }
void FFTmulg(giant y, giant x) { /* x becomes y*x. */ int lambda, sizex = abs(x->sign), sizey = abs(y->sign); int finalsign = gsign(x)*gsign(y); register int L; if ((sizex <= 4) || (sizey <= 4)) { grammarmulg(y, x); return; } L = lpt(sizex + sizey, &lambda); if (!z) z = (double *)malloc(MAX_SHORTS * sizeof(double)); if (!z2) z2 = (double *)malloc(MAX_SHORTS * sizeof(double)); giant_to_double(x, sizex, z, L); giant_to_double(y, sizey, z2, L); fft_real_to_hermitian(z, L); fft_real_to_hermitian(z2, L); mul_hermitian(z2, z, L); fftinv_hermitian_to_real(z, L); addsignal(x, z, L); x->sign = finalsign * abs(x->sign); }
void FFTsquareg(giant x) { int j, size = abs(x->sign); register int L; if (size < 4) { grammarmulg(x, x); return; } L = lpt(size + size, &j); if (!z) z = (double *)malloc(MAX_SHORTS * sizeof(double)); giant_to_double(x, size, z, L); fft_real_to_hermitian(z, L); square_hermitian(z, L); fftinv_hermitian_to_real(z, L); addsignal(x, z, L); x->sign = abs(x->sign); }
void main( void ) { giant x = newgiant(INFINITY), y = newgiant(INFINITY), p = newgiant(INFINITY), r = newgiant(100); int j; printf("Give two integers x, y on separate lines:\n"); gin(x); gin(y); gtog(y, p); /* p := y */ mulg(x, p); printf("y * x = "); gout(p); gtog(y, p); subg(x, p); printf("y - x = "); gout(p); gtog(y, p); addg(x, p); printf("y + x = "); gout(p); gtog(y, p); divg(x, p); printf("y div x = "); gout(p); gtog(y, p); modg(x, p); printf("y mod x = "); gout(p); gtog(y, p); gcdg(x, p); printf("GCD(x, y) = "); gout(p); /* Next, test which of x, y is greater. */ if (gcompg(x, y) < 0 ) printf("y is greater\n"); else if (gcompg(x,y) == 0) printf("x, y equal\n"); else printf("x is greater\n"); /* Next, we see how a giant struct is comprised. * We make a random, bipolar number of about 100 * digits in base 65536. */ for (j=0; j < 100; j++) { /* Fill 100 digits randomly. */ r->n[j] = (unsigned short)rand(); } r->sign = 100 * (1 - 2*(rand()%2)); /* Next, don't forget to check for leading zero digits, * even though such are unlikely. */ j = abs(r->sign) - 1; while ((r->n[j] == 0) && (j > 0)) { --j; } r->sign = (j+1) * ((r->sign > 0) ? 1: -1); printf("The random number: "); gout(r); /* Next, compare a large-FFT multiply with a standard, * grammar-school multiply. */ itog(1, x); gshiftleft(65536, x); iaddg(1, x); itog(5, y); gshiftleft(30000, y); itog(1, p); subg(p, y); /* Now we multiply (2^65536 + 1)*(5*(2^30000) - 1). */ gtog(y, p); mulg(x, p); /* Actually invokes FFT method because bit lengths of x, y are sufficiently large. */ printf("High digit of (2^65536 + 1)*(5*(2^30000) - 1) via FFT mul: %d\n", (int) p->n[abs(p->sign)-1]); fflush(stdout); gtog(y, p); grammarmulg(x, p); /* Grammar-school method. */ printf("High digit via grammar-school mul: %d\n", (int) p->n[abs(p->sign)-1]); fflush(stdout); /* Next, perform Fermat test for pseudoprimality. */ printf("Give prime candidate p:\n"); gin(p); gtog(p, y); itog(1, x); subg(x, y); itog(2, x); powermodg(x, y, p); if (isone(x)) printf("p is probably prime.\n"); else printf("p is composite.\n"); }