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 gmersennemod( int n, giant g ) /* g := g (mod 2^n - 1) */ { int the_sign; giant scratch3 = borrowGiant(g->capacity); giant scratch4 = borrowGiant(1); if ((the_sign = gsign(g)) < 0) absg(g); while (bitlen(g) > n) { gtog(g,scratch3); gshiftright(n,scratch3); addg(scratch3,g); gshiftleft(n,scratch3); subg(scratch3,g); } if(isZero(g)) goto out; int_to_giant(1,scratch3); gshiftleft(n,scratch3); int_to_giant(1,scratch4); subg(scratch4,scratch3); if(gcompg(g,scratch3) >= 0) subg(scratch3,g); if (the_sign < 0) { g->sign = -g->sign; addg(scratch3,g); } out: returnGiant(scratch3); returnGiant(scratch4); }
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 gshiftleft(int bits, giant g) /* shift g left bits bits. Equivalent to g = g*2^bits. */ { int rem = bits & 15, crem = 16 - rem, words = bits >> 4; int size = abs(g->sign), j, k, sign = gsign(g); unsigned short carry, dat; if (!bits) return; if (!size) return; if (bits < 0) { gshiftright(-bits, g); return; } if (size + words + 1 > current_max_size) { error = OVFLOW; exit(error); } if (rem == 0) { memmove(g->n + words, g->n, size * sizeof(short)); for (j = 0; j < words; j++) g->n[j] = 0; g->sign += (g->sign < 0) ? (-words) : (words); } else { k = size + words; carry = 0; for (j = size - 1; j >= 0; j--) { dat = g->n[j]; g->n[k--] = (unsigned short)((dat >> crem) | carry); carry = (unsigned short)(dat << rem); } do { g->n[k--] = carry; carry = 0; } while (k >= 0); k = size + words; if (g->n[k] == 0) --k; g->sign = sign * (k + 1); } }
void gshiftleft(int bits, giant g) { /* shift g left bits bits. Equivalent to g = g*2^bits */ int rem = bits & (GIANT_BITS_PER_DIGIT - 1); int crem = GIANT_BITS_PER_DIGIT - rem; int digits = 1 + (bits >> GIANT_LOG2_BITS_PER_DIGIT); int size = abs(g->sign); int j; int k; int sign = gsign(g); giantDigit carry; giantDigit dat; #if FEE_DEBUG if(bits < 0) { CKRaise("gshiftleft(-bits)\n"); } #endif /* FEE_DEBUG */ if(!bits) return; if(!size) return; if((size+digits) > (int)g->capacity) { CKRaise("gshiftleft overflow"); return; } k = size - 1 + digits; // (MSD of result + 1) carry = 0; /* bug fix for 32-bit giantDigits; this is also an optimization for * other sizes. rem=0 means we're shifting strictly by digits, no * bit shifts. */ if(rem == 0) { g->n[k] = 0; // XXX hack - for sign fixup for(j=size-1; j>=0; j--) { g->n[--k] = g->n[j]; } do{ g->n[--k] = 0; } while(k>0); } else { /* * normal unaligned case * FIXME - this writes past g->n[size-1] the first time thru! */ for(j=size-1; j>=0; j--) { dat = g->n[j]; g->n[k--] = (dat >> crem) | carry; carry = (dat << rem); } do{ g->n[k--] = carry; carry = 0; } while(k>=0); } k = size - 1 + digits; if(g->n[k] == 0) --k; g->sign = sign * (k+1); if (abs(g->sign) > g->capacity) { CKRaise("gshiftleft overflow"); } }