void fp2_mul_basic(fp2_t c, fp2_t a, fp2_t b) { dv_t t0, t1, t2, t3, t4; dv_null(t0); dv_null(t1); dv_null(t2); dv_null(t3); dv_null(t4); TRY { dv_new(t0); dv_new(t1); dv_new(t2); dv_new(t3); dv_new(t4); /* Karatsuba algorithm. */ /* t2 = a_0 + a_1, t1 = b0 + b1. */ fp_add(t2, a[0], a[1]); fp_add(t1, b[0], b[1]); /* t3 = (a_0 + a_1) * (b0 + b1). */ fp_muln_low(t3, t2, t1); /* t0 = a_0 * b0, t4 = a_1 * b1. */ fp_muln_low(t0, a[0], b[0]); fp_muln_low(t4, a[1], b[1]); /* t2 = (a_0 * b0) + (a_1 * b1). */ fp_addc_low(t2, t0, t4); /* t1 = (a_0 * b0) + u^2 * (a_1 * b1). */ fp_subc_low(t1, t0, t4); /* t1 = u^2 * (a_1 * b1). */ for (int i = -1; i > fp_prime_get_qnr(); i--) { fp_subc_low(t1, t1, t4); } /* c_0 = t1 mod p. */ fp_rdc(c[0], t1); /* t4 = t3 - t2. */ fp_subc_low(t4, t3, t2); /* c_1 = t4 mod p. */ fp_rdc(c[1], t4); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { dv_free(t0); dv_free(t1); dv_free(t2); dv_free(t3); dv_free(t4); } }
void fp2_rdcn_low(fp2_t c, dv2_t a) { #if FP_RDC == MONTY fp_rdcn_low(c[0], a[0]); fp_rdcn_low(c[1], a[1]); #else fp_rdc(c[0], a[0]); fp_rdc(c[1], a[1]); #endif }
void fp_mul_basic(fp_t c, const fp_t a, const fp_t b) { int i; dv_t t; dig_t carry; dv_null(t); TRY { /* We need a temporary variable so that c can be a or b. */ dv_new(t); dv_zero(t, 2 * FP_DIGS); for (i = 0; i < FP_DIGS; i++) { carry = fp_mula_low(t + i, b, *(a + i)); *(t + i + FP_DIGS) = carry; } fp_rdc(c, t); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { dv_free(t); } }
void fp_mul_karat(fp_t c, const fp_t a, const fp_t b) { dv_t t; dv_null(t); TRY { /* We need a temporary variable so that c can be a or b. */ dv_new(t); dv_zero(t, 2 * FP_DIGS); if (FP_DIGS > 1) { fp_mul_karat_imp(t, a, b, FP_DIGS, FP_KARAT); } else { fp_muln_low(t, a, b); } fp_rdc(c, t); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { dv_free(t); } }
void fp_prime_conv_dig(fp_t c, dig_t a) { dv_t t; ctx_t *ctx = core_get(); bn_null(t); TRY { dv_new(t); #if FP_RDC == MONTY if (a != 1) { dv_zero(t, 2 * FP_DIGS + 1); t[FP_DIGS] = fp_mul1_low(t, ctx->conv.dp, a); fp_rdc(c, t); } else { dv_copy(c, ctx->one.dp, FP_DIGS); } #else (void)ctx; fp_zero(c); c[0] = a; #endif } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { dv_free(t); } }
void fp_prime_back(bn_t c, const fp_t a) { dv_t t; int i; dv_null(t); TRY { dv_new(t); bn_grow(c, FP_DIGS); for (i = 0; i < FP_DIGS; i++) { c->dp[i] = a[i]; } #if FP_RDC == MONTY dv_zero(t, 2 * FP_DIGS + 1); dv_copy(t, a, FP_DIGS); fp_rdc(c->dp, t); #endif c->used = FP_DIGS; c->sign = BN_POS; bn_trim(c); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { dv_free(t); } }
void fp_sqr_comba(fp_t c, const fp_t a) { dv_t t; dv_null(t); TRY { dv_new(t); fp_sqrn_low(t, a); fp_rdc(c, t); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { fp_free(t); } }
void fp_mul_comba(fp_t c, const fp_t a, const fp_t b) { dv_t t; dv_null(t); TRY { /* We need a temporary variable so that c can be a or b. */ dv_new(t); fp_muln_low(t, a, b); fp_rdc(c, t); dv_free(t); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { dv_free(t); } }
void fp_sqr_basic(fp_t c, const fp_t a) { int i; dv_t t; dv_null(t); TRY { dv_new(t); dv_zero(t, 2 * RLC_FP_DIGS); for (i = 0; i < RLC_FP_DIGS; i++) { bn_sqra_low(t + (2 * i), a + i, RLC_FP_DIGS - i); } fp_rdc(c, t); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { fp_free(t); } }
void fp_sqr_karat(fp_t c, const fp_t a) { dv_t t; dv_null(t); TRY { dv_new(t); dv_zero(t, 2 * RLC_FP_DIGS); if (RLC_FP_DIGS > 1) { fp_sqr_karat_imp(t, a, RLC_FP_DIGS, FP_KARAT); } else { fp_sqrn_low(t, a); } fp_rdc(c, t); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { dv_free(t); } }
void fp_sqrm_low(dig_t *c, const dig_t *a) { dig_t align t[2 * FP_DIGS]; fp_sqrn_low(t, a); fp_rdc(c, t); }
void fp3_sqr_basic(fp3_t c, fp3_t a) { dv_t t0, t1, t2, t3, t4, t5; dv_null(t0); dv_null(t1); dv_null(t2); dv_null(t3); dv_null(t4); dv_null(t5); TRY { dv_new(t0); dv_new(t1); dv_new(t2); dv_new(t3); dv_new(t4); dv_new(t5); /* t0 = a_0^2. */ fp_sqrn_low(t0, a[0]); /* t1 = 2 * a_1 * a_2. */ fp_dbl(t2, a[1]); fp_muln_low(t1, t2, a[2]); /* t2 = a_2^2. */ fp_sqrn_low(t2, a[2]); /* t3 = (a_0 + a_2 + a_1)^2, t4 = (a_0 + a_2 - a_1)^2. */ fp_add(t3, a[0], a[2]); fp_add(t4, t3, a[1]); fp_sub(t5, t3, a[1]); fp_sqrn_low(t3, t4); fp_sqrn_low(t4, t5); /* t4 = (t4 + t3)/2. */ fp_addd_low(t4, t4, t3); fp_hlvd_low(t4, t4); /* t3 = t3 - t4 - t1. */ fp_addc_low(t5, t1, t4); fp_subc_low(t3, t3, t5); /* c_2 = t4 - t0 - t2. */ fp_addc_low(t5, t0, t2); fp_subc_low(t4, t4, t5); fp_rdc(c[2], t4); /* c_0 = t0 + t1 * B. */ fp_subc_low(t0, t0, t1); for (int i = -1; i > fp_prime_get_cnr(); i--) { fp_subc_low(t0, t0, t1); } fp_rdc(c[0], t0); /* c_1 = t3 + t2 * B. */ fp_subc_low(t3, t3, t2); for (int i = -1; i > fp_prime_get_cnr(); i--) { fp_subc_low(t3, t3, t2); } fp_rdc(c[1], t3); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { dv_free(t0); dv_free(t1); dv_free(t2); dv_free(t3); dv_free(t4); dv_free(t5); } }
void fp3_rdc_basic(fp3_t c, dv3_t a) { fp_rdc(c[0], a[0]); fp_rdc(c[1], a[1]); fp_rdc(c[2], a[2]); }
void fp2_rdc_basic(fp2_t c, dv2_t a) { fp_rdc(c[0], a[0]); fp_rdc(c[1], a[1]); }
void fp_mulm_low(dig_t *c, const dig_t *a, const dig_t *b) { dig_t align t[2 * FP_DIGS]; fp_muln_low(t, a, b); fp_rdc(c, t); }
void fp3_mul_basic(fp3_t c, fp3_t a, fp3_t b) { dv_t t, t0, t1, t2, t3, t4, t5, t6; dv_null(t); dv_null(t0); dv_null(t1); dv_null(t2); dv_null(t3); dv_null(t4); dv_null(t5); dv_null(t6); TRY { dv_new(t); dv_new(t0); dv_new(t1); dv_new(t2); dv_new(t3); dv_new(t4); dv_new(t5); dv_new(t6); /* Karatsuba algorithm. */ /* t0 = a_0 * b_0, t1 = a_1 * b_1, t2 = a_2 * b_2. */ fp_muln_low(t0, a[0], b[0]); fp_muln_low(t1, a[1], b[1]); fp_muln_low(t2, a[2], b[2]); /* t3 = (a_1 + a_2) * (b_1 + b_2). */ fp_add(t3, a[1], a[2]); fp_add(t4, b[1], b[2]); fp_muln_low(t, t3, t4); fp_addd_low(t6, t1, t2); fp_subc_low(t4, t, t6); fp_subc_low(t3, t0, t4); for (int i = -1; i > fp_prime_get_cnr(); i--) { fp_subc_low(t3, t3, t4); } fp_add(t4, a[0], a[1]); fp_add(t5, b[0], b[1]); fp_muln_low(t, t4, t5); fp_addd_low(t4, t0, t1); fp_subc_low(t4, t, t4); fp_subc_low(t4, t4, t2); for (int i = -1; i > fp_prime_get_cnr(); i--) { fp_subc_low(t4, t4, t2); } fp_add(t5, a[0], a[2]); fp_add(t6, b[0], b[2]); fp_muln_low(t, t5, t6); fp_addd_low(t6, t0, t2); fp_subc_low(t5, t, t6); fp_addc_low(t5, t5, t1); /* c_0 = t3 mod p. */ fp_rdc(c[0], t3); /* c_1 = t4 mod p. */ fp_rdc(c[1], t4); /* c_2 = t5 mod p. */ fp_rdc(c[2], t5); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { dv_free(t); dv_free(t0); dv_free(t1); dv_free(t2); dv_free(t3); dv_free(t4); dv_free(t5); dv_free(t6); } }