aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJ08nY2025-03-21 23:50:56 +0100
committerJ08nY2025-03-21 23:50:56 +0100
commitea8200d09d93a7b45332cb897f80464a761e766f (patch)
treef36b1e798a74291f0ccb1801d7eda1f98451ab43
parent4bf51fc47b31cf03fd725fb90cc3ae53d178d172 (diff)
downloadecgen-ea8200d09d93a7b45332cb897f80464a761e766f.tar.gz
ecgen-ea8200d09d93a7b45332cb897f80464a761e766f.tar.zst
ecgen-ea8200d09d93a7b45332cb897f80464a761e766f.zip
Make the CM method work with the -u switch! Walk down volcanoes!
Diffstat (limited to '')
-rw-r--r--src/cm/cm.c2
-rw-r--r--src/cm/cm_any.c99
-rw-r--r--src/cm/cm_any.h9
-rwxr-xr-xtest/ecgen.sh1
4 files changed, 110 insertions, 1 deletions
diff --git a/src/cm/cm.c b/src/cm/cm.c
index 04b988a..9845500 100644
--- a/src/cm/cm.c
+++ b/src/cm/cm.c
@@ -69,6 +69,8 @@ static void cm_ginit(gen_f *generators, bool prime) {
if (prime) {
generators[OFFSET_CURVE] = &cm_gen_curve_prime;
generators[OFFSET_POINTS] = &points_gen_prime;
+ } else if (GET_BOOL(unique)) {
+ generators[OFFSET_CURVE] = &cm_gen_curve_unique;
} else {
generators[OFFSET_CURVE] = &cm_gen_curve_any;
}
diff --git a/src/cm/cm_any.c b/src/cm/cm_any.c
index a0cd475..368ce77 100644
--- a/src/cm/cm_any.c
+++ b/src/cm/cm_any.c
@@ -347,6 +347,103 @@ GENERATOR(cm_gen_curve_any) {
return 1;
}
+GENERATOR(cm_gen_curve_unique) {
+ HAS_ARG(args);
+ pari_sp ltop = avma;
+ const char *order_s = (const char *)args->args;
+ GEN order = strtoi(order_s);
+ GEN e;
+ if (min_d && min_roots && min_curve == curve &&
+ min_roots->used < min_roots->total) {
+ debug_log("Reusing roots.");
+ // We can just use the roots we have stored and take some out.
+ e = cm_construct_curve(order, min_d->d, min_d->p, min_roots, false);
+ } else if (min_d && min_curve == curve) {
+ debug_log("Reusing min D = %Pi", min_d->d);
+ // We just have the discriminant but no roots (or they are used up), we
+ // need to continue
+ if (min_d->d && isclone(min_d->d)) {
+ gunclone(min_d->d);
+ }
+ if (min_d->p && isclone(min_d->p)) {
+ gunclone(min_d->p);
+ }
+ good_qdisc_minimal(min_d, order);
+ min_d->d = gclone(min_d->d);
+ min_d->p = gclone(min_d->p);
+ debug_log("Got min D = %Pi", min_d->d);
+ if (min_roots) {
+ cm_update_roots(min_d->d, min_d->p, min_roots);
+ } else {
+ min_roots = cm_make_roots(min_d->d, min_d->p);
+ }
+ e = cm_construct_curve(order, min_d->d, min_d->p, min_roots, false);
+ } else {
+ // We have nothing. Start fresh.
+ debug_log("Fresh start.");
+ if (!min_d) {
+ min_d = try_calloc(sizeof(cm_any_qdisc_t));
+ }
+ if (min_d->d && isclone(min_d->d)) {
+ gunclone(min_d->d);
+ }
+ if (min_d->p && isclone(min_d->p)) {
+ gunclone(min_d->p);
+ }
+ good_qdisc_minimal(min_d, order);
+ min_d->d = gclone(min_d->d);
+ min_d->p = gclone(min_d->p);
+ debug_log("Got min D = %Pi", min_d->d);
+ min_roots = cm_make_roots(min_d->d, min_d->p);
+ min_curve = curve;
+ e = cm_construct_curve(order, min_d->d, min_d->p, min_roots, false);
+ }
+
+ if (e == NULL) {
+ fprintf(err, "Could not construct curve.");
+ avma = ltop;
+ return -3;
+ }
+
+ GEN group = ellff_get_group(e);
+ long len = glength(group);
+ if (len == 2) {
+ debug_log("Walking down with structure %Ps.", group);
+ GEN d = gcopy(min_d->d);
+ GEN one = gel(group, 1);
+ GEN two = gel(group, 2);
+ GEN towalk = cmpii(one, two) < 0 ? one : two;
+ GEN factored = Z_factor(towalk);
+ GEN primes = gel(factored, 1);
+ GEN powers = gel(factored, 2);
+ for (long i = 1; i <= glength(primes); ++i) {
+ GEN prime = gel(primes, i);
+ GEN power = gel(powers, i);
+ debug_log("Walking down with %Pi %Pi", prime, power);
+ GEN exp = mulis(power, 2);
+ GEN mul = powii(prime, exp);
+ d = mulii(d, mul);
+ }
+ if (min_d->d && isclone(min_d->d)) {
+ gunclone(min_d->d);
+ }
+ min_d->d = gclone(d);
+ if (min_roots) {
+ cm_update_roots(min_d->d, min_d->p, min_roots);
+ } else {
+ min_roots = cm_make_roots(min_d->d, min_d->p);
+ }
+ e = cm_construct_curve(order, min_d->d, min_d->p, min_roots, false);
+ //TODO: Stack cleanup here
+ }
+
+ curve->field = min_d->p;
+ curve->a = ell_get_a4(e);
+ curve->b = ell_get_a6(e);
+ curve->curve = e;
+ return 1;
+}
+
GENERATOR(cm_gen_order) {
HAS_ARG(args);
const char *order_s = (const char *)args->args;
@@ -361,4 +458,4 @@ void cm_any_quit() {
if (min_roots) {
cm_free_roots(min_roots);
}
-} \ No newline at end of file
+}
diff --git a/src/cm/cm_any.h b/src/cm/cm_any.h
index c5407cb..05e5103 100644
--- a/src/cm/cm_any.h
+++ b/src/cm/cm_any.h
@@ -76,6 +76,15 @@ GENERATOR(cm_gen_curve_any);
* @param state
* @return
*/
+GENERATOR(cm_gen_curve_unique);
+
+/**
+ * @brief
+ * @param curve
+ * @param args
+ * @param state
+ * @return
+ */
GENERATOR(cm_gen_order);
/**
diff --git a/test/ecgen.sh b/test/ecgen.sh
index 38670bc..adf0c81 100755
--- a/test/ecgen.sh
+++ b/test/ecgen.sh
@@ -189,6 +189,7 @@ function cm() {
assert_raises "${ecgen} --fp --order=2147483723 32"
assert_raises "${ecgen} --fp --order=123456789012345678901234567890123456789012345678901234568197 196"
assert_raises "${ecgen} --fp --order=46874566546,3546,3125 64"
+ assert_raises "${ecgen} --fp -u --order=46874566546,3546,3125 64"
assert_raises "${ecgen} --fp --order=0 16" 1
assert_raises "${ecgen} --fp --order=0x1000 8" 1
}