diff --git a/inversion-c/inversion_template.c b/inversion-c/inversion_template.c new file mode 100644 index 0000000000..c54062dae0 --- /dev/null +++ b/inversion-c/inversion_template.c @@ -0,0 +1,55 @@ +#define MAKE_FN_NAME1(x,y) x ## y +#define MAKE_FN_NAME(x,y) MAKE_FN_NAME1(x,y) + +#define PRECOMP MAKE_FN_NAME(CURVE_DESCRIPTION,_divstep_precomp) +#define MSAT MAKE_FN_NAME(CURVE_DESCRIPTION,_msat) +#define MONE MAKE_FN_NAME(CURVE_DESCRIPTION,_set_one) +#define DIVSTEP MAKE_FN_NAME(CURVE_DESCRIPTION,_divstep) +#define OPP MAKE_FN_NAME(CURVE_DESCRIPTION,_opp) +#define MUL MAKE_FN_NAME(CURVE_DESCRIPTION,_mul) + +#if LEN_PRIME < 46 +#define ITERATIONS (((49 * LEN_PRIME) + 80) / 17) +#else +#define ITERATIONS (((49 * LEN_PRIME) + 57) / 17) +#endif + +#define SAT_LIMBS LIMBS + 1 /* we might need 2 more bits to represent m in twos complement */ +#define BYTES 8 * (((LEN_PRIME - 1) / 64) + 1) + +void inverse(WORD out[LIMBS], WORD g[SAT_LIMBS]) { + + WORD precomp[LIMBS]; + PRECOMP(precomp); + + WORD d = 1; + WORD f[SAT_LIMBS]; + WORD v[LIMBS]; + WORD r[LIMBS]; + WORD out1; + WORD out2[SAT_LIMBS], out3[SAT_LIMBS], out4[LIMBS], out5[LIMBS]; + + MSAT(f); + MONE(r); + for (int j = 0; j < LIMBS; j++) v[j] = 0; + + for (int i = 0; i < ITERATIONS - (ITERATIONS % 2); i+=2) { + DIVSTEP(&out1,out2,out3,out4,out5,d,f,g,v,r); + DIVSTEP(&d,f,g,v,r,out1,out2,out3,out4,out5); + } + if (ITERATIONS % 2) { + DIVSTEP(&out1,out2,out3,out4,out5,d,f,g,v,r); + for (int k = 0; k < LIMBS; k++) v[k] = out4[k]; + for (int k = 0; k < SAT_LIMBS; k++) f[k] = out2[k]; + } + + WORD h[LIMBS]; + if (f[SAT_LIMBS - 1] >> (WORDSIZE - 1)) { + OPP(h, v); + for (int k = 0; k < LIMBS; k++) v[k] = h[k]; + } + + MUL(out, v, precomp); + + return; +} diff --git a/inversion-c/inversion_test_template.c b/inversion-c/inversion_test_template.c new file mode 100644 index 0000000000..524dd832b3 --- /dev/null +++ b/inversion-c/inversion_test_template.c @@ -0,0 +1,54 @@ +#include +#include +#include +#include + +#define MAKE_FN_NAME1(x,y) x ## y +#define MAKE_FN_NAME(x,y) MAKE_FN_NAME1(x,y) + +#define FROM_BYTES MAKE_FN_NAME(CURVE_DESCRIPTION,_from_bytes) +#define TO_BYTES MAKE_FN_NAME(CURVE_DESCRIPTION,_to_bytes) +#define FROM_MONTGOMERY MAKE_FN_NAME(CURVE_DESCRIPTION,_from_montgomery) + +int main() { + WORD res[LIMBS], out[LIMBS], g[SAT_LIMBS], g1[LIMBS], g2[LIMBS], g3[LIMBS]; + uint8_t a[BYTES]; + + int seed = time(0); + srand(seed); + printf("%i\n", seed); + + for (int j = 0; j < 1000; j++) { + int i; + for (i = 0; i < BYTES; i++) { + a[i] = rand() % 256; + if (i > BYTES - 8) a[i] = 0; + } + + FROM_BYTES(g1,a); + FROM_BYTES(g2,a); + FROM_MONTGOMERY(g3,g2); + + for (int i = 0; i < LIMBS; i++) g[i] = g3[i]; + g[SAT_LIMBS - 1] = 0; + + inverse(out,g); + + MUL(res,out,g1); + FROM_MONTGOMERY(out,res); + TO_BYTES(a,out); + + if (a[0] != 1) { + printf("FAIL\n"); + return 2; + } + for (i = 1; i < BYTES; i++) { + if (a[i] != 0) { + printf("FAIL\n"); + return 1; + } + } + } + printf("PASS\n"); + return 0; +}