diff options
Diffstat (limited to 'src/cm/custom.c')
| -rw-r--r-- | src/cm/custom.c | 198 |
1 files changed, 145 insertions, 53 deletions
diff --git a/src/cm/custom.c b/src/cm/custom.c index 9309ed9..c8d6d8b 100644 --- a/src/cm/custom.c +++ b/src/cm/custom.c @@ -3,7 +3,13 @@ * Copyright (C) 2017 J08nY */ #include "custom.h" +#include <obj/obj.h> #include "io/input.h" +#include "io/output.h" +#include "obj/curve.h" +#include "obj/point.h" +#include "obj/subgroup.h" +#include "util/bits.h" static bool custom_is_disc(GEN test) { bool result = true; @@ -19,37 +25,7 @@ static GEN custom_disc(GEN order, GEN prime) { GEN t = subii(order, addii(prime, gen_1)); GEN v2D = subii(mulis(prime, 4), sqri(t)); - GEN max_divisor = gen_1; - GEN min_D = v2D; - - // Optional part that sometimes makes the discriminant smaller, at the cost - // factoring v2D. - GEN fctr = factor(v2D); - long len = glength(gel(fctr, 1)); - for (long i = 1; i <= len; ++i) { - GEN value = gmael(fctr, 1, i); - GEN mul = gmael(fctr, 2, i); - GEN pow; - if (mod2(mul) == 0) { - pow = mul; - } else { - pow = subis(mul, 1); - } - if (equalis(pow, 0)) { - continue; - } - GEN divi = powii(value, pow); - if (mpcmp(divi, max_divisor) > 0) { - GEN candidate_D = divii(v2D, divi); - if (signe(candidate_D) == 1) { - setsigne(candidate_D, -1); - } - if (custom_is_disc(candidate_D)) { - max_divisor = divi; - min_D = candidate_D; - } - } - } + GEN min_D = core(v2D); if (signe(min_D) == 1) { setsigne(min_D, -1); @@ -81,31 +57,107 @@ static custom_quadr_t custom_prime_input(GEN order) { return result; } +static size_t custom_add_primes(GEN r, GEN order, GEN **primes, + size_t nprimes) { + size_t nalloc = nprimes; + if (nprimes == 0) { + nalloc = 10; + *primes = try_calloc(sizeof(GEN) * nalloc); + debug_log("calloc %lu", sizeof(GEN) * nalloc); + } + + GEN logN = ground(glog(order, BIGDEFAULTPREC)); + + GEN rlog = mulii(r, logN); + GEN rplog = mulii(addis(r, 1), logN); + + forprime_t iter; + forprime_init(&iter, rlog, rplog); + GEN prime; + while ((prime = forprime_next(&iter))) { + long k = kronecker(order, prime); + if (k == 1) { + GEN pstar = prime; + GEN ppow = divis(subis(prime, 1), 2); + if (mod2(ppow) == 1) { + pstar = negi(prime); + } else { + pstar = gcopy(pstar); + } + (*primes)[nprimes++] = pstar; + if (nprimes == nalloc) { + nalloc *= 2; + *primes = try_realloc(*primes, sizeof(GEN) * nalloc); + } + } + } + + return nprimes; +} + static custom_quadr_t custom_prime_random(GEN order) { pari_sp ltop = avma; custom_quadr_t result = {0}; - GEN p; - GEN t = gen_0; - GEN v = gen_0; - GEN D; - long i = 2; - // TODO: this is wrong, order = p + 1 +- t is not kept. - while (gequal0(t)) { - D = stoi(-4 * (i / 2) + (i % 2)); - for (long j = 0; j < 100; ++j) { - p = random_prime(cfg->bits); - if (cornacchia2(negi(D), p, &t, &v)) { - break; + + GEN r = gen_0; + GEN *Sp; + size_t nprimes = custom_add_primes(r, order, &Sp, 0); + + GEN logN = ground(glog(order, BIGDEFAULTPREC)); + GEN rlog2 = sqri(mulii(r, logN)); + + GEN i = gen_0; + + while (true) { + GEN imax = int2n(nprimes); + + while (cmpii(i, imax) < 0) { + // debug_log("i %Pi", i); + pari_sp btop = avma; + GEN pprod = gen_1; + bits_t *ibits = bits_from_i_len(i, nprimes); + for (size_t j = 0; j < nprimes; ++j) { + if (GET_BIT(ibits->bits, j) == 1) { + // debug_log("multiplying %Pi", Sp[j]); + pprod = mulii(pprod, Sp[j]); + } + } + bits_free(&ibits); + if (cmpii(pprod, rlog2) < 0 && equalii(modis(pprod, 8), stoi(5))) { + // debug_log("candidate D = %Pi", pprod); + GEN x; + GEN y; + cornacchia2(negi(pprod), order, &x, &y); + GEN pp1 = addii(addis(order, 1), x); + GEN pp2 = subii(addis(order, 1), x); + if (isprime(pp1)) { + result.p = pp1; + result.D = pprod; + result.t = x; + result.v = gen_0; + gerepileall(ltop, 4, &result.p, &result.t, &result.v, + &result.D); + try_free(Sp); + return result; + } + if (isprime(pp2)) { + result.p = pp2; + result.D = pprod; + result.t = x; + result.v = gen_0; + gerepileall(ltop, 4, &result.p, &result.t, &result.v, + &result.D); + try_free(Sp); + return result; + } } + avma = btop; + i = addis(i, 1); } - }; - gerepileall(ltop, 4, &p, &t, &v, &D); - result.p = p; - result.t = t; - result.v = v; - result.D = D; - return result; + r = addis(r, 1); + nprimes = custom_add_primes(r, order, &Sp, nprimes); + } } curve_t *custom_curve() { @@ -117,9 +169,49 @@ curve_t *custom_curve() { } else { quadr = custom_prime_input(order); } - pari_printf("p = %Pi, D = %Pi, ", quadr.p, quadr.D); + debug_log("order = %Pi", order); + debug_log("p = %Pi, t = %Pi, v = %Pi, D = %Pi, ", quadr.p, quadr.t, quadr.v, + quadr.D); GEN H = polclass(quadr.D, 0, 0); - pari_printf("H = %Ps\n", H); - return NULL; + debug_log("H = %Ps", H); + + GEN r = FpX_roots(H, quadr.p); + debug_log("roots = %Ps", r); + + GEN a = NULL; + GEN e = NULL; + GEN g = NULL; + + long rlen = glength(r); + for (long i = 1; i <= rlen; ++i) { + GEN root = gel(r, i); + a = Fp_div(Fp_mul(stoi(27), root, quadr.p), + Fp_mul(stoi(4), Fp_sub(stoi(1728), root, quadr.p), quadr.p), + quadr.p); + e = ellinit(mkvec2(a, negi(a)), quadr.p, 0); + g = genrand(e); + GEN gmul = ellmul(e, g, order); + if (gequal(gmul, gtovec(gen_0))) { + debug_log("YES %Ps", e); + break; + } + } + + curve_t *result = curve_new(); + result->field = quadr.p; + result->a = a; + result->b = negi(a); + result->curve = e; + result->order = order; + result->generators = subgroups_new(1); + result->generators[0] = subgroup_new(); + result->generators[0]->generator = point_new(); + result->generators[0]->generator->point = g; + result->generators[0]->generator->order = order; + result->generators[0]->generator->cofactor = stoi(1); + result->generators[0]->npoints = 0; + result->ngens = 1; + + return result; }
\ No newline at end of file |
