aboutsummaryrefslogtreecommitdiff
path: root/src/cm
diff options
context:
space:
mode:
Diffstat (limited to 'src/cm')
-rw-r--r--src/cm/cm.c17
-rw-r--r--src/cm/p1363.c391
-rw-r--r--src/cm/p1363.h39
3 files changed, 444 insertions, 3 deletions
diff --git a/src/cm/cm.c b/src/cm/cm.c
index 71e720c..43ae515 100644
--- a/src/cm/cm.c
+++ b/src/cm/cm.c
@@ -2,10 +2,21 @@
* ecgen, tool for generating Elliptic curve domain parameters
* Copyright (C) 2017 J08nY
*/
+/**
+ * @file cm.c
+ */
#include "cm.h"
-#include "io/output.h"
+#include "exhaustive/anomalous.h"
+#include "p1363.h"
int cm_do(config_t *cfg) {
- debug("# Starting Complex Multiplication method\n");
- return INT_MIN;
+ GEN D = stoi(71);
+ form_t **forms;
+ size_t nforms = p1363_forms(D, &forms);
+ for (size_t i = 0; i < nforms; ++i) {
+ p1363_invariant(D, forms[i]);
+ }
+
+ p1363_free(&forms, nforms);
+ return 0;
}
diff --git a/src/cm/p1363.c b/src/cm/p1363.c
new file mode 100644
index 0000000..24d28cb
--- /dev/null
+++ b/src/cm/p1363.c
@@ -0,0 +1,391 @@
+/*
+ * ecgen, tool for generating Elliptic curve domain parameters
+ * Copyright (C) 2017 J08nY
+ */
+/**
+ * @file p1363.c
+ */
+#include "p1363.h"
+#include <pari/paripriv.h>
+
+GEN p1363_group(GEN D) {
+ pari_sp ltop = avma;
+ GEN s = mpfloor(sqrtr(rdivis(D, 3, BIGDEFAULTPREC)));
+ long llen = itos(s) * 2;
+ GEN l = gtovec0(gen_0, llen);
+
+ long j = 1;
+ GEN B = gen_0;
+ for (; cmpii(B, s) <= 0; B = addii(B, gen_1)) {
+ GEN B2 = sqri(B);
+ GEN d = addii(D, B2);
+ GEN lower = mulis(B, 2);
+ GEN upper = gsqrt(d, BIGDEFAULTPREC);
+
+ GEN divs = divisors(d);
+ long len = glength(divs);
+ for (long i = 1; i <= len; ++i) {
+ GEN div = gel(divs, i);
+ if (gcmp(div, lower) >= 0 && gcmp(div, upper) <= 0) {
+ GEN A = div;
+ GEN C = divii(d, A);
+ GEN gcd = gcdii(gcdii(A, lower), C);
+
+ if (gequal1(gcd)) {
+ GEN v = gtovec0(gen_0, 3);
+ gel(v, 1) = A;
+ gel(v, 2) = B;
+ gel(v, 3) = C;
+ gel(l, j++) = v;
+ if (cmpii(gen_0, lower) < 0 && cmpii(lower, A) < 0 &&
+ cmpii(A, C) < 0) {
+ GEN n = gtovec0(gen_0, 3);
+ gel(n, 1) = A;
+ gel(n, 2) = negi(B);
+ gel(n, 3) = C;
+ gel(l, j++) = n;
+ }
+ }
+ }
+ }
+ }
+ return gerepilecopy(ltop, vec_shorten(l, j - 1));
+}
+
+long p1363_num(GEN group) { return glength(group); }
+
+size_t p1363_forms(GEN D, form_t ***forms) {
+ GEN group = p1363_group(D);
+ size_t nforms = (size_t)p1363_num(group);
+ *forms = pari_malloc(nforms * sizeof(form_t *));
+ memset(*forms, 0, nforms * sizeof(form_t *));
+
+ for (size_t i = 0; i < nforms; ++i) {
+ (*forms)[i] = pari_malloc(sizeof(form_t));
+ memset((*forms)[i], 0, sizeof(form_t));
+ (*forms)[i]->A = gel(gel(group, i + 1), 1);
+ (*forms)[i]->B = gel(gel(group, i + 1), 2);
+ (*forms)[i]->C = gel(gel(group, i + 1), 3);
+ }
+
+ return nforms;
+}
+
+void p1363_free(form_t ***forms, size_t nforms) {
+ if (*forms) {
+ for (size_t i = 0; i < nforms; ++i) {
+ if ((*forms)[i]) {
+ pari_free((*forms)[i]);
+ (*forms)[i] = NULL;
+ }
+ }
+ pari_free(*forms);
+ *forms = NULL;
+ }
+}
+
+GEN p1363_func_F(GEN z) {
+ pari_sp ltop = avma;
+
+ if (gequal0(z)) {
+ return gcopy(gen_1);
+ }
+ GEN sum = cgetc(BIGDEFAULTPREC * 5);
+ gel(sum, 1) = real_1(BIGDEFAULTPREC * 5);
+ gel(sum, 2) = real_0(BIGDEFAULTPREC * 5);
+ pari_printf("initial sum = %Ps\n", sum);
+ GEN last;
+
+ GEN j = gcopy(gen_1);
+ do {
+ last = gcopy(sum);
+
+ GEN j3 = mulsi(3, sqri(j));
+ GEN quota = divis(subii(j3, j), 2);
+ GEN quotb = divis(addii(j3, j), 2);
+
+ GEN term = gadd(gpow(z, quota, BIGDEFAULTPREC),
+ gpow(z, quotb, BIGDEFAULTPREC));
+ pari_printf("%Ps %Ps \n", sum, term);
+ if (mod2(j) == 0) {
+ sum = gadd(sum, term);
+ } else {
+ sum = gsub(sum, term);
+ }
+
+ addiiz(j, gen_1, j);
+ if (gc_needed(ltop, 1)) gerepileall(ltop, 3, &j, &sum, &last);
+ } while (!gequal(sum, last));
+
+ pari_printf("end sum = %Ps, last = %Ps\n", sum, last);
+
+ return gerepilecopy(ltop, sum);
+}
+
+GEN p1363_func_fzero(GEN D, form_t *form) {
+ pari_sp ltop = avma;
+
+ GEN upper = p1363_func_F(gneg(form->theta));
+ GEN lower = p1363_func_F(gsqr(form->theta));
+ GEN front = gpow(form->theta, gdivgs(gen_m1, 24), BIGDEFAULTPREC * 5);
+
+ GEN result = gmul(gdiv(upper, lower), front);
+
+ return gerepilecopy(ltop, result);
+}
+
+GEN p1363_func_fone(GEN D, form_t *form) {
+ pari_sp ltop = avma;
+
+ GEN upper = p1363_func_F(form->theta);
+ GEN lower = p1363_func_F(gsqr(form->theta));
+ GEN front = gpow(form->theta, gdivgs(gen_m1, 24), BIGDEFAULTPREC * 5);
+
+ GEN result = gmul(gdiv(upper, lower), front);
+
+ return gerepilecopy(ltop, result);
+}
+
+GEN p1363_func_ftwo(GEN D, form_t *form) {
+ pari_sp ltop = avma;
+
+ GEN upper = p1363_func_F(gpowgs(form->theta, 4));
+ GEN lower = p1363_func_F(gsqr(form->theta));
+ GEN front = gmul(sqrti(gen_2),
+ gpow(form->theta, gdivgs(gen_1, 12), BIGDEFAULTPREC * 5));
+
+ GEN result = gmul(gdiv(upper, lower), front);
+
+ return gerepilecopy(ltop, result);
+}
+
+void p1363_m8(GEN D, form_t *form) { form->m8 = mod8(D); }
+
+void p1363_I(GEN D, form_t *form) {
+ switch (form->m8) {
+ case 1:
+ case 2:
+ case 6:
+ case 7:
+ form->I = 3;
+ break;
+ case 5:
+ form->I = 6;
+ break;
+ case 3:
+ if (dvdis(D, 3)) {
+ form->I = 2;
+ } else {
+ form->I = 0;
+ }
+ break;
+ default:
+ pari_err_DOMAIN("p1636_I", "D", "==", stoi(8), D);
+ }
+}
+
+void p1363_J(GEN D, form_t *form) {
+ pari_sp ltop = avma;
+ GEN ac = mulii(form->A, form->C);
+
+ if (mod2(ac) == 1) {
+ form->J = 0;
+ } else {
+ if (mod2(form->C) == 0) {
+ form->J = 1;
+ } else if (mod2(form->A) == 0) {
+ form->J = 2;
+ } else {
+ pari_err_BUG("hwat?");
+ }
+ }
+ avma = ltop;
+}
+
+void p1363_K(GEN D, form_t *form) {
+ switch (form->m8) {
+ case 1:
+ case 2:
+ case 6:
+ form->K = 2;
+ break;
+ case 3:
+ case 7:
+ form->K = 1;
+ break;
+ case 5:
+ form->K = 5;
+ break;
+ default:
+ pari_err_DOMAIN("p1636_I", "D", "==", stoi(8), D);
+ }
+}
+
+void p1363_L(GEN D, form_t *form) {
+ pari_sp ltop = avma;
+ GEN ac = mulii(form->A, form->C);
+ long a2 = mod2(form->A);
+ long c2 = mod2(form->C);
+
+ if (mod2(ac) == 1 || (form->m8 == 5 && mod2(form->C) == 0)) {
+ form->L = addii(subii(form->A, form->C), mulii(sqri(form->A), form->C));
+ } else {
+ if (a2 == 0) {
+ if (form->m8 == 3) {
+ form->L = addii(subii(form->A, form->C),
+ mulsi(5, mulii(form->A, sqri(form->C))));
+ } else {
+ form->L = subii(subii(form->A, form->C),
+ mulii(form->A, sqri(form->C)));
+ }
+ } else if (c2 == 0) {
+ form->L = subii(addii(form->A, mulsi(2, form->C)),
+ mulii(form->A, sqri(form->C)));
+ } else {
+ pari_err_BUG("what?");
+ }
+ }
+ form->L = gerepileupto(ltop, form->L);
+}
+
+void p1363_M(GEN D, form_t *form) {
+ pari_sp ltop = avma;
+ GEN quot;
+ if (mod2(form->A) == 0) {
+ quot = divis(subis(sqri(form->C), 1), 8);
+ } else {
+ quot = divis(subis(sqri(form->A), 1), 8);
+ }
+ form->M = gerepileupto(ltop, powii(gen_m1, quot));
+}
+
+void p1363_N(GEN D, form_t *form) {
+ pari_sp ltop = avma;
+ long ac2 = mod2(mulii(form->A, form->C));
+
+ switch (form->m8) {
+ case 5:
+ form->N = gen_1;
+ break;
+ case 1:
+ case 2:
+ case 6:
+ form->N = gcopy(form->M);
+ break;
+ case 3:
+ if (ac2 == 0) {
+ form->N = negi(form->M);
+ } else {
+ form->N = gen_1;
+ }
+ break;
+ case 7:
+ if (ac2 == 0) {
+ form->N = gen_1;
+ } else {
+ form->N = gcopy(form->M);
+ }
+ break;
+ default:
+ pari_err_DOMAIN("p1363_N", "D", "=", stoi(8), D);
+ }
+ form->N = gerepileupto(ltop, form->N);
+}
+
+void p1363_lambda(GEN D, form_t *form) {
+ pari_sp ltop = avma;
+ GEN pik = mulri(mppi(BIGDEFAULTPREC), stoi(form->K));
+ GEN quot = divrs(pik, 24);
+ form->lambda = gerepileupto(ltop, expIr(quot));
+}
+
+void p1363_theta(GEN D, form_t *form) {
+ pari_sp ltop = avma;
+
+ GEN upper = gadd(gneg(gsqrt(D, BIGDEFAULTPREC)), gmul(form->B, gen_I()));
+ GEN quot = gmul(gdiv(upper, form->A), mppi(BIGDEFAULTPREC));
+
+ form->theta = gerepileupto(ltop, gexp(quot, BIGDEFAULTPREC));
+}
+
+GEN p1363_invariant(GEN D, form_t *form) {
+ pari_printf("[A,B,C] = %Pi %Pi %Pi\n", form->A, form->B, form->C);
+ pari_sp ltop = avma;
+
+ p1363_m8(D, form);
+ p1363_I(D, form);
+ printf("I = %li\n", form->I);
+ p1363_J(D, form);
+ printf("J = %li\n", form->J);
+ p1363_K(D, form);
+ printf("K = %li\n", form->K);
+ p1363_L(D, form);
+ pari_printf("L = %Pi\n", form->L);
+ p1363_M(D, form);
+ pari_printf("M = %Pi\n", form->M);
+ p1363_N(D, form);
+ pari_printf("N = %Pi\n", form->N);
+ p1363_lambda(D, form);
+ pari_printf("lambda = %Ps\n", form->lambda);
+ p1363_theta(D, form);
+ pari_printf("theta = %Ps\n", form->theta);
+
+ GEN G = gcdii(D, stoi(3));
+ pari_printf("G = %Pi\n", G);
+
+ GEN bl = mulii(form->B, form->L);
+
+ GEN lmbl = gpow(form->lambda, negi(bl), BIGDEFAULTPREC);
+ pari_printf("lmbl = %Ps\n", lmbl);
+
+ GEN mi6 = gneg(gdiv(stoi(form->I), stoi(6)));
+ GEN powmi6 = gpow(gen_2, mi6, BIGDEFAULTPREC);
+ pari_printf("powmi6 = %Ps\n", powmi6);
+
+ GEN f = gen_0;
+ switch (form->J) {
+ case 0:
+ f = p1363_func_fzero(D, form);
+ break;
+ case 1:
+ f = p1363_func_fone(D, form);
+ break;
+ case 2:
+ f = p1363_func_ftwo(D, form);
+ break;
+ default:
+ pari_err_DOMAIN("p1363_invariant", "J", ">", stoi(2),
+ stoi(form->J));
+ }
+
+ pari_printf("f = %Ps\n", f);
+
+ GEN fK = gpow(f, stoi(form->K), BIGDEFAULTPREC);
+ pari_printf("fK = %Ps\n", fK);
+
+ GEN in = gmul(lmbl, powmi6);
+ pari_printf("in = %Ps\n", in);
+ GEN inner = gmul(gmul(form->N, in), fK);
+ pari_printf("inner = %Ps\n", inner);
+ GEN result = gpow(inner, G, BIGDEFAULTPREC);
+ pari_printf("result = %Ps\n", result);
+
+ return gerepilecopy(ltop, result);
+}
+
+GEN p1363_poly(GEN D, form_t **forms, size_t nforms) {
+ pari_sp ltop = avma;
+ long v = fetch_var();
+ name_var(v, "t");
+
+ GEN terms = gtovec0(gen_0, nforms);
+ for (size_t i = 0; i < nforms; ++i) {
+ gel(terms, i + 1) = gsub(pol_x(v), p1363_invariant(D, forms[i]));
+ }
+
+ GEN result = gen_1;
+ for (size_t i = 0; i < nforms; ++i) {
+ gmulz(result, gel(terms, i + 1), result);
+ }
+ return gerepilecopy(ltop, result);
+}
diff --git a/src/cm/p1363.h b/src/cm/p1363.h
new file mode 100644
index 0000000..e5c9fbd
--- /dev/null
+++ b/src/cm/p1363.h
@@ -0,0 +1,39 @@
+/*
+ * ecgen, tool for generating Elliptic curve domain parameters
+ * Copyright (C) 2017 J08nY
+ */
+/**
+ * @file p1363.h
+ */
+#ifndef ECGEN_P1363_H
+#define ECGEN_P1363_H
+
+#include <pari/pari.h>
+
+typedef struct form_t {
+ GEN A;
+ GEN B;
+ GEN C;
+
+ long m8;
+
+ long I;
+ long J;
+ long K;
+ GEN L;
+ GEN M;
+ GEN N;
+
+ GEN lambda;
+ GEN theta;
+} form_t;
+
+size_t p1363_forms(GEN D, form_t ***forms);
+
+void p1363_free(form_t ***forms, size_t nforms);
+
+GEN p1363_invariant(GEN D, form_t *form);
+
+GEN p1363_poly(GEN D, form_t **forms, size_t nforms);
+
+#endif // ECGEN_P1363_H