static void popg(mpz_t val, unsigned char *face, int s) { if(s>=4) { s>>=1; popg(val, face, s); popg(val, face+s, s); popg(val, face+s*48, s); popg(val, face+s*49, s); } else {
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 modg_via_recip(giant d, giant r, giant n) /* This is the fastest mod of the present collection. * n := n % d, where r is the precalculated * steady-state reciprocal of d. */ { int s = (bitlen(r) - 1), sign = n->sign; giant tmp, tmp2; if (isZero(d) || (d->sign < 0)) { exit(SIGN); } tmp = popg(); tmp2 = popg(); n->sign = abs(n->sign); while (1) { gtog(n, tmp); gshiftright(s - 1, tmp); mulg(r, tmp); gshiftright(s + 1, tmp); mulg(d, tmp); subg(tmp, n); if (gcompg(n, d) >= 0) subg(d, n); if (gcompg(n, d) < 0) break; } if (sign >= 0) goto done; if (isZero(n)) goto done; negg(n); addg(d, n); done: pushg(2); return; }
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 grammarmulg(giant a, giant b) /* b becomes a*b. */ { int i, j; unsigned int prod, carry = 0; int asize = abs(a->sign), bsize = abs(b->sign); unsigned short *aptr, *bptr, *destptr; unsigned short mult; giant scratch = popg(); for (i = 0; i < asize + bsize; ++i) { scratch->n[i] = 0; } bptr = &(b->n[0]); for (i = 0; i < bsize; ++i) { mult = *(bptr++); if (mult) { carry = 0; aptr = &(a->n[0]); destptr = &(scratch->n[i]); for (j = 0; j < asize; ++j) { prod = *(aptr++) * mult + *destptr + carry; *(destptr++) = (unsigned short)(prod & 0xffff); carry = prod >> 16; } *destptr = (unsigned short)carry; } } bsize += asize; if (!carry) --bsize; scratch->sign = gsign(a)*gsign(b)*bsize; gtog(scratch, b); pushg(1); }
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); }