void addg(giant a, giant b) /* b := b + a, any signs any result. */ { int asgn = a->sign, bsgn = b->sign; if (asgn == 0) return; if (bsgn == 0) { gtog(a, b); return; } if ((asgn < 0) == (bsgn < 0)) { if (bsgn > 0) { normal_addg(a, b); return; } absg(b); if (a != b) absg(a); normal_addg(a, b); negg(b); if (a != b) negg(a); return; } if (bsgn > 0) { negg(a); if (gcompg(b, a) >= 0) { normal_subg(a, b); negg(a); return; } reverse_subg(a, b); negg(a); negg(b); return; } negg(b); if (gcompg(b, a) < 0) { reverse_subg(a, b); return; } normal_subg(a, b); negg(b); return; }
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); }
main(int argc, char **argv) { giant p = newgiant(CM_SHORTS); giant u = newgiant(CM_SHORTS); giant v = newgiant(CM_SHORTS); giant g[6]; giant plus_order = newgiant(CM_SHORTS); giant minus_order = newgiant(CM_SHORTS); giant a = newgiant(CM_SHORTS); giant b = newgiant(CM_SHORTS); int d, dc, olen, k; init_tools(CM_SHORTS); /* Basic algorithms. */ printf("Give base prime p:\n"); fflush(stdout); gin(p); for(dc=0; dc < 6; dc++) g[dc] = newgiant(CM_SHORTS); for(dc = 0; dc < DCOUNT; dc++) { d = disc12[dc]; /* Next, seek representation 4N = u^2 + |d| v^2. */ if(cornacchia4(p, d, u, v) == 0) continue; /* Here, (u,v) give the quadratic representation of 4p. */ printf("D: %d\n", d); fflush(stdout); gtog(u, g[0]); switch(d) { case -3: olen = 3; /* Six orders: p + 1 +- g[0,1,2]. */ gtog(u, g[1]); gtog(v, g[2]); addg(g[2], g[2]); addg(v, g[2]); /* g[2] := 3v. */ addg(g[2], g[1]); gshiftright(1, g[1]); /* g[1] = (u + 3v)/2. */ subg(u, g[2]); gshiftright(1, g[2]); absg(g[2]); /* g[2] = |u-3v|/2. */ break; case -4: olen = 2; /* Four orders: p + 1 +- g[0,1]. */ gtog(v, g[1]); addg(g[1], g[1]); /* g[1] = 2v. */ break; default: olen = 1; /* Two orders: p + 1 +- g[0]. */ } for(k=0; k < olen; k++) { gtog(p, plus_order); iaddg(1, plus_order); gtog(p, minus_order); iaddg(1, minus_order); addg(g[k], plus_order); subg(g[k], minus_order); printf("curve orders: \n"); printf("(%d) ", prime_probable(plus_order)); gout(plus_order); printf("(%d) ", prime_probable(minus_order)); gout(minus_order); } } }