void fmpz_invert(fmpz_t res, fmpz_t x, fmpz_t m) { if (m[0] == 0) { printf("Error: division by zero!\n"); abort(); } fmpz_t s0, U, V, temp; unsigned long size = fmpz_size(m); // U may use fmpz_size(m) + 1 limbs after the sum, and gmp requires +1 U = fmpz_init(size + 2); V = fmpz_init(size + 2); s0 = fmpz_init(size + 2); temp = fmpz_init(size + 2); // U := (x%m) + abs(m) // V := abs(m) fmpz_abs(V, m); fmpz_mod(U, x, V); fmpz_add(U, U, V); // Compute s0 such that 1 = s0 * x % m mpn_gcdext(temp+1, s0+1, (long *) s0, U+1, fmpz_size(U), V+1, fmpz_size(V)); fmpz_mod(res, s0, m); fmpz_clear(temp); fmpz_clear(s0); fmpz_clear(V); fmpz_clear(U); }
static int ref_modinv (mp_limb_t *rp, const mp_limb_t *ap, const mp_limb_t *mp, mp_size_t mn) { mp_limb_t tp[4*(mn+1)]; mp_limb_t *up = tp; mp_limb_t *vp = tp + mn+1; mp_limb_t *gp = tp + 2*(mn+1); mp_limb_t *sp = tp + 3*(mn+1); mp_size_t gn, sn; mpn_copyi (up, ap, mn); mpn_copyi (vp, mp, mn); gn = mpn_gcdext (gp, sp, &sn, up, mn, vp, mn); if (gn != 1 || gp[0] != 1) return 0; if (sn < 0) mpn_sub (sp, mp, mn, sp, -sn); else if (sn < mn) /* Zero-pad. */ mpn_zero (sp + sn, mn - sn); mpn_copyi (rp, sp, mn); return 1; }
void fp_invn_low(dig_t *c, const dig_t *a) { mp_size_t cn; align dig_t s[FP_DIGS], t[2 * FP_DIGS], u[FP_DIGS + 1]; #if FP_RDC == MONTY dv_zero(t + FP_DIGS, FP_DIGS); dv_copy(t, a, FP_DIGS); fp_rdcn_low(u, t); #else fp_copy(u, a); #endif dv_copy(s, fp_prime_get(), FP_DIGS); mpn_gcdext(t, c, &cn, u, FP_DIGS, s, FP_DIGS); if (cn < 0) { dv_zero(c - cn, FP_DIGS + cn); mpn_sub_n(c, fp_prime_get(), c, FP_DIGS); } else { dv_zero(c + cn, FP_DIGS - cn); } #if FP_RDC == MONTY dv_zero(t, FP_DIGS); dv_copy(t + FP_DIGS, c, FP_DIGS); mpn_tdiv_qr(u, c, 0, t, 2 * FP_DIGS, fp_prime_get(), FP_DIGS); #endif }
static int modinv_gcd (const struct ecc_curve *ecc, mp_limb_t *rp, mp_limb_t *ap, mp_limb_t *tp) { mp_size_t size = ecc->p.size; mp_limb_t *up = tp; mp_limb_t *vp = tp + size+1; mp_limb_t *gp = tp + 2*(size+1); mp_limb_t *sp = tp + 3*(size+1); mp_size_t gn, sn; mpn_copyi (up, ap, size); mpn_copyi (vp, ecc->p.m, size); gn = mpn_gcdext (gp, sp, &sn, up, size, vp, size); if (gn != 1 || gp[0] != 1) return 0; if (sn < 0) mpn_sub (sp, ecc->p.m, size, sp, -sn); else if (sn < size) /* Zero-pad. */ mpn_zero (sp + sn, size - sn); mpn_copyi (rp, sp, size); return 1; }
int mpfq_p_127_735_inv(mpfq_p_127_735_dst_field k, mpfq_p_127_735_dst_elt z, mpfq_p_127_735_src_elt x) { #if 1 invmod_2(z, x, k->p); #else mp_limb_t s1[2+1], s2[2+1]; mp_limb_t r1[2+1], r2[2+1]; mp_size_t r1n, r2n; int i; add_2(s1, x, k->p); mpfq_p_127_735_copy(k, s2, k->p); if (cmp_2(s1, s2) == 0) { fprintf(stderr, "error in inv_fp_2: division by 0\n"); exit(1); } assert (cmp_2(s1, s2) > 0); r1n = mpn_gcdext(r1, r2, &r2n, s1, 2, s2, 2); // Non invertible element ? if ((r1n != 1) || (r1[0] != 1UL)) { fprintf(stderr, "warning in inv_fp_2: non invertible element\n"); if ((r1n <= 1) && (r1[0] == 0UL)) { fprintf(stderr, "hum... in fact this is a division by 0\n"); exit(1); } else { mpn2mpz(k->factor, r1, r1n); return 1; } } // OK. GCD is one. make the result positive and put it in z. assert ((r1n == 1) && (r1[0] == 1UL)); if (r2n < 0) { for (i = -r2n; i < 2; ++i) r2[i] = 0UL; sub_2(r2, k->p, r2); } else { for (i = r2n; i < 2; ++i) r2[i] = 0UL; } mpfq_p_127_735_copy(k, z, r2); #endif }
void Inv(modp& ans,const modp& x,const Zp_Data& ZpD) { mp_limb_t g[MAX_MOD_SZ],xx[MAX_MOD_SZ],yy[MAX_MOD_SZ]; mp_size_t sz; mpn_copyi(xx,x.x,ZpD.t); mpn_copyi(yy,ZpD.prA,ZpD.t); mpn_gcdext(g,ans.x,&sz,xx,ZpD.t,yy,ZpD.t); if (sz<0) { mpn_sub(ans.x,ZpD.prA,ZpD.t,ans.x,-sz); sz=-sz; } else { for (int i=sz; i<ZpD.t; i++) { ans.x[i]=0; } } if (ZpD.montgomery) { ZpD.Mont_Mult(ans.x,ans.x,ZpD.R3); } }
void mpz_gcdext (mpz_ptr g, mpz_ptr s, mpz_ptr t, mpz_srcptr a, mpz_srcptr b) { mp_size_t asize, bsize, usize, vsize; mp_srcptr ap, bp; mp_ptr up, vp; mp_size_t gsize, ssize, tmp_ssize; mp_ptr gp, sp, tmp_gp, tmp_sp; mpz_srcptr u, v; mpz_ptr ss, tt; __mpz_struct stmp, gtmp; TMP_DECL; TMP_MARK; /* mpn_gcdext requires that U >= V. Therefore, we often have to swap U and V. This in turn leads to a lot of complications. The computed cofactor will be the wrong one, so we have to fix that up at the end. */ asize = ABS (SIZ (a)); bsize = ABS (SIZ (b)); ap = PTR (a); bp = PTR (b); if (asize > bsize || (asize == bsize && mpn_cmp (ap, bp, asize) > 0)) { usize = asize; vsize = bsize; up = (mp_ptr) TMP_ALLOC ((usize + 1) * BYTES_PER_MP_LIMB); vp = (mp_ptr) TMP_ALLOC ((vsize + 1) * BYTES_PER_MP_LIMB); MPN_COPY (up, ap, usize); MPN_COPY (vp, bp, vsize); u = a; v = b; ss = s; tt = t; } else { usize = bsize; vsize = asize; up = (mp_ptr) TMP_ALLOC ((usize + 1) * BYTES_PER_MP_LIMB); vp = (mp_ptr) TMP_ALLOC ((vsize + 1) * BYTES_PER_MP_LIMB); MPN_COPY (up, bp, usize); MPN_COPY (vp, ap, vsize); u = b; v = a; ss = t; tt = s; } tmp_gp = (mp_ptr) TMP_ALLOC ((usize + 1) * BYTES_PER_MP_LIMB); tmp_sp = (mp_ptr) TMP_ALLOC ((usize + 1) * BYTES_PER_MP_LIMB); if (vsize == 0) { tmp_sp[0] = 1; tmp_ssize = 1; MPN_COPY (tmp_gp, up, usize); gsize = usize; } else gsize = mpn_gcdext (tmp_gp, tmp_sp, &tmp_ssize, up, usize, vp, vsize); ssize = ABS (tmp_ssize); PTR (>mp) = tmp_gp; SIZ (>mp) = gsize; PTR (&stmp) = tmp_sp; SIZ (&stmp) = (tmp_ssize ^ SIZ (u)) >= 0 ? ssize : -ssize; if (tt != NULL) { if (SIZ (v) == 0) SIZ (tt) = 0; else { mpz_t x; MPZ_TMP_INIT (x, ssize + usize + 1); mpz_mul (x, &stmp, u); mpz_sub (x, >mp, x); mpz_tdiv_q (tt, x, v); } } if (ss != NULL) { if (ALLOC (ss) < ssize) _mpz_realloc (ss, ssize); sp = PTR (ss); MPN_COPY (sp, tmp_sp, ssize); SIZ (ss) = SIZ (&stmp); } if (ALLOC (g) < gsize) _mpz_realloc (g, gsize); gp = PTR (g); MPN_COPY (gp, tmp_gp, gsize); SIZ (g) = gsize; TMP_FREE; }
void mpz_gcdext (mpz_ptr g, mpz_ptr s, mpz_ptr t, mpz_srcptr a, mpz_srcptr b) { mp_size_t asize, bsize; mp_ptr tmp_ap, tmp_bp; mp_size_t gsize, ssize, tmp_ssize; mp_ptr gp, tmp_gp, tmp_sp; TMP_DECL; /* mpn_gcdext requires that Usize >= Vsize. Therefore, we often have to swap U and V. The computed cofactor will be the "smallest" one, which is faster to produce. The wanted one will be computed here; this is needed anyway when both are requested. */ asize = ABSIZ (a); bsize = ABSIZ (b); if (asize < bsize) { MPZ_SRCPTR_SWAP (a, b); MP_SIZE_T_SWAP (asize, bsize); MPZ_PTR_SWAP (s, t); } if (bsize == 0) { /* g = |a|, s = sgn(a), t = 0. */ ssize = SIZ (a) >= 0 ? (asize != 0) : -1; gp = MPZ_REALLOC (g, asize); MPN_COPY (gp, PTR (a), asize); SIZ (g) = asize; if (t != NULL) SIZ (t) = 0; if (s != NULL) { SIZ (s) = ssize; PTR (s)[0] = 1; } return; } TMP_MARK; TMP_ALLOC_LIMBS_2 (tmp_ap, asize, tmp_bp, bsize); MPN_COPY (tmp_ap, PTR (a), asize); MPN_COPY (tmp_bp, PTR (b), bsize); TMP_ALLOC_LIMBS_2 (tmp_gp, bsize, tmp_sp, bsize + 1); gsize = mpn_gcdext (tmp_gp, tmp_sp, &tmp_ssize, tmp_ap, asize, tmp_bp, bsize); ssize = ABS (tmp_ssize); tmp_ssize = SIZ (a) >= 0 ? tmp_ssize : -tmp_ssize; if (t != NULL) { mpz_t x; __mpz_struct gtmp, stmp; PTR (>mp) = tmp_gp; SIZ (>mp) = gsize; PTR (&stmp) = tmp_sp; SIZ (&stmp) = tmp_ssize; MPZ_TMP_INIT (x, ssize + asize + 1); mpz_mul (x, &stmp, a); mpz_sub (x, >mp, x); mpz_divexact (t, x, b); } if (s != NULL) { mp_ptr sp; sp = MPZ_REALLOC (s, ssize); MPN_COPY (sp, tmp_sp, ssize); SIZ (s) = tmp_ssize; } gp = MPZ_REALLOC (g, gsize); MPN_COPY (gp, tmp_gp, gsize); SIZ (g) = gsize; TMP_FREE; }