void iaddg(int i, giant g) /* Giant g becomes g + (int)i. */ { int w, j = 0, carry = 0, size = abs(g->sign); giant tmp; if (isZero(g)) { itog(i, g); } else if (g->sign < 0) { tmp = popg(); itog(i, tmp); addg(tmp, g); pushg(1); return; } else { w = g->n[0] + i; do { g->n[j] = (unsigned short)(w & 65535L); carry = w >> 16; w = g->n[++j] + carry; } while ((carry != 0) && (j < size)); } if (carry) { ++g->sign; g->n[size] = (unsigned short)carry; } }
void make_recip(giant d, giant r) /* r becomes the steady-state reciprocal * 2^(2b)/d, where b = bit-length of d-1. */ { int b; giant tmp, tmp2; if (isZero(d) || (d->sign < 0)) { exit(SIGN); } tmp = popg(); tmp2 = popg(); itog(1, r); subg(r, d); b = bitlen(d); addg(r, d); gshiftleft(b, r); gtog(r, tmp2); while (1) { gtog(r, tmp); squareg(tmp); gshiftright(b, tmp); mulg(d, tmp); gshiftright(b, tmp); addg(r, r); subg(tmp, r); if (gcompg(r, tmp2) <= 0) break; gtog(r, tmp2); } itog(1, tmp); gshiftleft(2 * b, tmp); gtog(r, tmp2); mulg(d, tmp2); subg(tmp2, tmp); itog(1, tmp2); while (tmp->sign < 0) { subg(tmp2, r); addg(d, tmp); } pushg(2); }
void grammarsquareg(giant a) /* a := a^2. */ { unsigned int cur_term; unsigned int prod, carry = 0, temp; unsigned int asize = abs(a->sign), max = asize * 2 - 1; unsigned short *ptr = a->n, *ptr1, *ptr2; giant scratch; if (asize == 0) { itog(0, a); return; } scratch = popg(); asize--; temp = *ptr; temp *= temp; scratch->n[0] = temp; carry = temp >> 16; for (cur_term = 1; cur_term < max; cur_term++) { ptr1 = ptr2 = ptr; if (cur_term <= asize) { ptr2 += cur_term; } else { ptr1 += cur_term - asize; ptr2 += asize; } prod = carry & 0xFFFF; carry >>= 16; while (ptr1 < ptr2) { temp = *ptr1++ * *ptr2--; prod += (temp << 1) & 0xFFFF; carry += (temp >> 15); } if (ptr1 == ptr2) { temp = *ptr1; temp *= temp; prod += temp & 0xFFFF; carry += (temp >> 16); } carry += prod >> 16; scratch->n[cur_term] = (unsigned short)(prod); }
void powermodg(giant x, giant n, giant g) /* x becomes x^n (mod g). */ { int len, pos; giant scratch2 = popg(); gtog(x, scratch2); itog(1, x); len = bitlen(n); pos = 0; while (1) { if (bitval(n, pos++)) { mulg(scratch2, x); modg(g, x); } if (pos >= len) break; squareg(scratch2); modg(g, scratch2); } pushg(1); }
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"); }