void mpz_to_z32(mpz_t src, z32 *dest) { int i; #if GMP_LIMB_BITS == 32 for (i=0; i < mpz_size(src); i++) dest->val[i] = mpz_getlimbn(src, i); dest->size = mpz_size(src); #else int j = 0; for (i=0; i < mpz_size(src); i++) { uint64 tmp = mpz_getlimbn(src, i); dest->val[j] = (uint32)tmp; dest->val[j+1] = (uint32)(tmp >> 32); j += 2; } if (dest->val[j-1] == 0) dest->size = j-1; else dest->size = j; #endif return; }
void testmain (int argc, char **argv) { unsigned i; unsigned long e; mpz_t u, s, r, bs; mpz_init (u); mpz_init (s); mpz_init (r); mpz_init (bs); for (i = 0; i < COUNT; i++) { mini_rrandomb (u, MAXBITS); mini_rrandomb (bs, 12); e = mpz_getlimbn (bs, 0) % mpz_sizeinbase (u, 2) + 2; if ((e & 1) && (mpz_getlimbn (bs, 0) & (1L<<10))) mpz_neg (u, u); mpz_rootrem (s, r, u, e); if (!rootrem_valid_p (u, s, r, e)) { fprintf (stderr, "mpz_rootrem(%lu-th) failed:\n", e); dump ("u", u); dump ("root", s); dump ("rem", r); abort (); } } mpz_clear (bs); mpz_clear (u); mpz_clear (s); mpz_clear (r); }
uint64 mpz_get_64(mpz_t src) { uint64 out = mpz_getlimbn(src, 0); #if GMP_LIMB_BITS == 32 if (mpz_size(src) >= 2) out |= ((uint64)mpz_getlimbn(src, 1) << 32ULL); #endif return out; }
void mpz_get_v(ulong *v, mpz_t src) { size_t i; asm_zero(v); for (i=0; i<mpz_size(src); i++) v[i]=mpz_getlimbn(src,i); }
void testmain (int argc, char **argv) { unsigned i; mpz_t a, b, res, ref; mpz_init (a); mpz_init (b); mpz_init (res); mpz_init (ref); for (i = 0; i < COUNT; i++) { mini_random_op3 (OP_MUL, MAXBITS, a, b, ref); if (mpz_sgn(ref) == 0) /* my_mpz_mul requires a != 0, b != 0 */ continue; my_mpz_mul (res, a, b); if (mpz_cmp (res, ref)) { fprintf (stderr, "my_mpz_mul failed:\n"); dump ("a", a); dump ("b", b); dump ("r", res); dump ("ref", ref); abort (); } /* The following test exploits a side-effect of my_mpz_mul: res points to a buffer with at least an+bn limbs, and the limbs above the result are zeroed. */ if (mpz_size (b) > 0 && mpz_getlimbn (res, mpz_size(a)) != mpz_limbs_read (res) [mpz_size(a)]) { fprintf (stderr, "getlimbn - limbs_read differ.\n"); abort (); } if ((i % 4 == 0) && mpz_size (res) > 1) { mpz_realloc2 (res, 1); if (mpz_cmp_ui (res, 0)) { fprintf (stderr, "mpz_realloc2 did not clear res.\n"); abort (); } mpz_limbs_finish (ref, 0); if (mpz_cmp_d (ref, 0)) { fprintf (stderr, "mpz_limbs_finish did not clear res.\n"); abort (); } } } mpz_clear (a); mpz_clear (b); mpz_clear (res); mpz_clear (ref); }
int main (int argc, char **argv) { mpz_t x2; mpz_t root1; mp_size_t x2_size; int i; int reps = 5000; unsigned long nth; gmp_randstate_ptr rands; mpz_t bs; unsigned long bsi, size_range; tests_start (); rands = RANDS; mpz_init (bs); if (argc == 2) reps = atoi (argv[1]); mpz_init (x2); mpz_init (root1); /* This triggers a gcc 4.3.2 bug */ mpz_set_str (x2, "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80000000000000000000000000000000000000000000000000000000000000002", 16); mpz_root (root1, x2, 2); check_one (root1, x2, 2, -1); for (i = 0; i < reps; i++) { mpz_urandomb (bs, rands, 32); size_range = mpz_get_ui (bs) % 12 + 2; mpz_urandomb (bs, rands, size_range); x2_size = mpz_get_ui (bs) + 10; mpz_rrandomb (x2, rands, x2_size); mpz_urandomb (bs, rands, 15); nth = mpz_getlimbn (bs, 0) % mpz_sizeinbase (x2, 2) + 2; mpz_root (root1, x2, nth); mpz_urandomb (bs, rands, 4); bsi = mpz_get_ui (bs); if ((bsi & 1) != 0) { /* With 50% probability, set x2 near a perfect power. */ mpz_pow_ui (x2, root1, nth); if ((bsi & 2) != 0) { mpz_sub_ui (x2, x2, bsi >> 2); mpz_abs (x2, x2); } else
long double _ecl_big_to_long_double(cl_object o) { long double output = 0; int i, l = mpz_size(o->big.big_num), exp = 0; for (i = 0; i < l; i++) { output += ldexpl(mpz_getlimbn(o->big.big_num, i), exp); exp += GMP_LIMB_BITS; } return (mpz_sgn(o->big.big_num) < 0)? -output : output; }
int main (int argc, char **argv) { mpz_t x2; mpz_t x; mpz_t temp, temp2; mp_size_t x2_size; int i; int reps = 1000; unsigned long nth; gmp_randstate_ptr rands; mpz_t bs; unsigned long bsi, size_range; tests_start (); rands = RANDS; mpz_init (bs); if (argc == 2) reps = atoi (argv[1]); mpz_init (x2); mpz_init (x); mpz_init (temp); mpz_init (temp2); for (i = 0; i < reps; i++) { mpz_urandomb (bs, rands, 32); size_range = mpz_get_ui (bs) % 12 + 2; mpz_urandomb (bs, rands, size_range); x2_size = mpz_get_ui (bs) + 10; mpz_rrandomb (x2, rands, x2_size); mpz_urandomb (bs, rands, 15); nth = mpz_getlimbn (bs, 0) % mpz_sizeinbase (x2, 2) + 2; mpz_root (x, x2, nth); mpz_urandomb (bs, rands, 4); bsi = mpz_get_ui (bs); if ((bsi & 1) != 0) { /* With 50% probability, set x2 near a perfect power. */ mpz_pow_ui (x2, x, nth); if ((bsi & 2) != 0) { mpz_sub_ui (x2, x2, bsi >> 2); mpz_abs (x2, x2); } else
static void nettle_mpz_to_octets(size_t length, uint8_t *s, const mpz_t x, uint8_t sign) { uint8_t *dst = s + length - 1; size_t size = mpz_size(x); size_t i; for (i = 0; i<size; i++) { mp_limb_t limb = mpz_getlimbn(x, i); size_t j; for (j = 0; length && j < sizeof(mp_limb_t); j++) { *dst-- = sign ^ (limb & 0xff); limb >>= 8; length--; } } if (length) memset(s, sign, length); }
/* @param x The number to get wMNAF for @param len [out] Destination for the length of wMNAF @return array with wMNAF representation @return NULL in case of errors */ signed char * ecc_wMNAF (mpz_t x, size_t * wmnaf_len) { int b, c; char sign = 1; size_t i, len; signed char *ret = NULL; if (!(sign = mpz_sgn (x))) { /* x == 0 */ ret = malloc (1); if (ret == NULL) goto done; ret[0] = 0; *wmnaf_len = 1; goto done; } /* total number of bits */ len = mpz_sizeinbase (x, 2); /* wMNAF is at most (len + 1) bits long */ ret = malloc (len + 1); if (ret == NULL) goto done; /* get (w + 1) Least Significant Bits */ c = (mpz_getlimbn (x, 0)) & WBITS; /* how many bits we've already processed */ i = 0; while ((c != 0) || (i + WMNAF_WINSIZE + 1 < len)) { if (c & 1) { /* LSB == 1 */ if (c >= BASEW) { b = c - BASEWW; } else { b = c; } c -= b; } else { b = 0; } ret[i++] = sign * b; /* fill c with next LSB */ c >>= 1; c += BASEW * mpz_unitstbit (x, i + WMNAF_WINSIZE); } *wmnaf_len = i--; /* do modified wNAF * check if wNAF starts with 1 and * (w + 1)th bit is negative */ if ((ret[i] == 1) && (ret[i - (WMNAF_WINSIZE + 1)] < 0)) { ret[i - (WMNAF_WINSIZE + 1)] += BASEW; ret[i - 1] = 1; *wmnaf_len = i; } done: return ret; }
/*-------------------------------------------------------------------*/ static uint32 get_final_sqrt(msieve_obj *obj, gmp_poly_t *alg_poly, gmp_poly_t *prod, gmp_poly_t *isqrt_mod_q, mpz_t q) { /* the main q-adic Newton iteration. On input, isqrt_mod_q contains the starting value of the reciprocal square root R[0](x) of the polynomial prod(x). The iteration is R[k](x) = R[k-1](x) * (3 - prod(x)*R[k-1](x)^2) / 2 mod (q^(2^k)) and at the end of iteration k, prod(x)*R[k-1](x)^2 mod (q^(2^k)) is 1. We keep iterating until q^(2^k) is larger than the size of the coefficients of the square root (i.e. about half the size of the coefficients of prod(x)). Then the square root to use is R[k](x) * prod(x) mod (q^(2^k)), which is written to isqrt_mod_q */ uint32 i, j; uint32 prod_bits, prod_max_bits; uint32 num_iter; /* initialize */ gmp_poly_bits(prod, &prod_bits, &prod_max_bits); /* since prod(x) only matters mod q^(2^(final_k)), we can cut the memory use in half by changing prod(x) to this. Remember final_k as well */ i = mpz_get_ui(q); for (num_iter = 0; mpz_sizeinbase(q, 2) < prod_max_bits / 2 + 4000; num_iter++) { mpz_mul(q, q, q); } gmp_poly_mod_q(prod, q, prod); mpz_set_ui(q, (unsigned long)i); mpz_realloc2(q, 33); /* do the main iteration */ for (i = 0; i < num_iter; i++) { gmp_poly_t tmp_poly; /* square the previous modulus */ mpz_mul(q, q, q); /* compute prod(x) * (previous R)^2 */ gmp_poly_init(&tmp_poly); gmp_poly_mod_q(prod, q, &tmp_poly); gmp_poly_mul(&tmp_poly, isqrt_mod_q, alg_poly, 0); gmp_poly_mod_q(&tmp_poly, q, &tmp_poly); gmp_poly_mul(&tmp_poly, isqrt_mod_q, alg_poly, 0); gmp_poly_mod_q(&tmp_poly, q, &tmp_poly); /* compute ( (3 - that) / 2 ) mod q */ mpz_sub_ui(tmp_poly.coeff[0], tmp_poly.coeff[0], (unsigned long)3); for (j = 0; j <= tmp_poly.degree; j++) { mpz_t *c = tmp_poly.coeff + j; if (mpz_sgn(*c) != 0) { mpz_neg(*c, *c); if (mpz_tstbit(*c, (unsigned long)0)) mpz_add(*c, *c, q); mpz_tdiv_q_2exp(*c, *c, (unsigned long)1); } } /* finally, compute the new R(x) by multiplying the result above by the old R(x) */ gmp_poly_mul(&tmp_poly, isqrt_mod_q, alg_poly, 1); gmp_poly_mod_q(&tmp_poly, q, isqrt_mod_q); gmp_poly_clear(&tmp_poly); } /* attempt to compute the square root. First multiply R(x) by prod(x), deleting prod(x) since we won't need it beyond this point */ gmp_poly_mul(isqrt_mod_q, prod, alg_poly, 1); gmp_poly_mod_q(isqrt_mod_q, q, isqrt_mod_q); /* this is a little tricky. Up until now we've been working modulo big numbers, but the coef- ficients of the square root are just integers, and may be negative. Negative numbers mod q have a numerical value near that of +q, but we want the square root to have a negative coef- ficient in that case. Hence, if the top few words of any coefficent of the square root match the top few words of q, we assume this coefficient is negative and subtract q from it. Theoretically we could be wrong, and the coefficient really is supposed to be a big positive number near q in size. However, if q is thousands of bits larger than the size we expect for the square root coefficients, this is so unlikely that it's not worth worrying about */ for (i = 0; i <= isqrt_mod_q->degree; i++) { mpz_t *c = isqrt_mod_q->coeff + i; size_t limbs = mpz_size(*c); if (limbs == mpz_size(q) && mpz_getlimbn(*c, (mp_size_t)(limbs-1)) == mpz_getlimbn(q, (mp_size_t)(limbs-1)) && mpz_getlimbn(*c, (mp_size_t)(limbs-2)) == mpz_getlimbn(q, (mp_size_t)(limbs-2)) && mpz_getlimbn(*c, (mp_size_t)(limbs-3)) == mpz_getlimbn(q, (mp_size_t)(limbs-3))) { mpz_sub(*c, *c, q); } } /* another heuristic: we will assume the Newton iteration has converged if, after applying the correction above for negative square root coefficients, the total number of bits in the coefficients of the resulting polynomial is much smaller than we would expect from random polynomials modulo q */ gmp_poly_bits(isqrt_mod_q, &prod_bits, &i); if (prod_bits >= (isqrt_mod_q->degree + 1) * mpz_sizeinbase(q, 2) - 100) { logprintf(obj, "Newton iteration failed to converge\n"); return 0; } return 1; }
/* For now we don't take into account go stop_asap and chkfilename */ int ecm_stage1_batch (mpz_t f, mpres_t x, mpres_t A, mpmod_t n, double B1, double *B1done, int batch, mpz_t s) { mp_limb_t d_1; mpz_t d_2; mpres_t x1, z1, x2, z2; unsigned long i; mpres_t t, u; int ret = ECM_NO_FACTOR_FOUND; MEMORY_TAG; mpres_init (x1, n); MEMORY_TAG; mpres_init (z1, n); MEMORY_TAG; mpres_init (x2, n); MEMORY_TAG; mpres_init (z2, n); MEMORY_TAG; mpres_init (t, n); MEMORY_TAG; mpres_init (u, n); if (batch == 2) { MEMORY_TAG; mpres_init (d_2, n); } MEMORY_UNTAG; /* initialize P */ mpres_set (x1, x, n); mpres_set_ui (z1, 1, n); /* P1 <- 1P */ /* Compute d=(A+2)/4 from A and d'=B*d thus d' = 2^(GMP_NUMB_BITS-2)*(A+2) */ if (batch == 1) { mpres_get_z (u, A, n); mpz_add_ui (u, u, 2); mpz_mul_2exp (u, u, GMP_NUMB_BITS - 2); mpres_set_z_for_gcd (u, u, n); /* reduces u mod n */ if (mpz_size (u) > 1) { mpres_get_z (u, A, n); outputf (OUTPUT_ERROR, "Error, d'=B*(A+2)/4 should fit in a mp_limb_t, A=%Zd\n", u); return ECM_ERROR; } d_1 = mpz_getlimbn (u, 0); } else { /* b = (A0+2)*B/4, where B=2^(k*GMP_NUMB_BITS) for MODMULN or REDC, B=2^GMP_NUMB_BITS for batch1, and B=1 otherwise */ mpres_add_ui (d_2, A, 2, n); mpres_div_2exp (d_2, d_2, 2, n); } /* Compute 2P : no need to duplicate P, the coordinates are simple. */ mpres_set_ui (x2, 9, n); if (batch == 1) /* here d = d_1 / GMP_NUMB_BITS */ { /* warning: mpres_set_ui takes an unsigned long which has only 32 bits on Windows, while d_1 might have 64 bits */ ASSERT_ALWAYS (mpz_size (u) == 1 && mpz_getlimbn (u, 0) == d_1); mpres_set_z (z2, u, n); mpres_div_2exp (z2, z2, GMP_NUMB_BITS, n); } else mpres_set (z2, d_2, n); mpres_mul_2exp (z2, z2, 6, n); mpres_add_ui (z2, z2, 8, n); /* P2 <- 2P = (9 : : 64d+8) */ /* invariant: if j represents the upper bits of s, then P1 = j*P and P2=(j+1)*P */ mpresn_pad (x1, n); mpresn_pad (z1, n); mpresn_pad (x2, n); mpresn_pad (z2, n); /* now perform the double-and-add ladder */ if (batch == 1) { for (i = mpz_sizeinbase (s, 2) - 1; i-- > 0;) { if (mpz_tstbit (s, i) == 0) /* (j,j+1) -> (2j,2j+1) */ /* P2 <- P1+P2 P1 <- 2*P1 */ dup_add_batch1 (x1, z1, x2, z2, t, u, d_1, n); else /* (j,j+1) -> (2j+1,2j+2) */ /* P1 <- P1+P2 P2 <- 2*P2 */ dup_add_batch1 (x2, z2, x1, z1, t, u, d_1, n); } } else /* batch = 2 */ { mpresn_pad (d_2, n); for (i = mpz_sizeinbase (s, 2) - 1; i-- > 0;) { if (mpz_tstbit (s, i) == 0) /* (j,j+1) -> (2j,2j+1) */ /* P2 <- P1+P2 P1 <- 2*P1 */ dup_add_batch2 (x1, z1, x2, z2, t, u, d_2, n); else /* (j,j+1) -> (2j+1,2j+2) */ /* P1 <- P1+P2 P2 <- 2*P2 */ dup_add_batch2 (x2, z2, x1, z1, t, u, d_2, n); } } *B1done=B1; mpresn_unpad (x1); mpresn_unpad (z1); if (!mpres_invert (u, z1, n)) /* Factor found? */ { mpres_gcd (f, z1, n); ret = ECM_FACTOR_FOUND_STEP1; } mpres_mul (x, x1, u, n); mpz_clear (x1); mpz_clear (z1); mpz_clear (x2); mpz_clear (z2); mpz_clear (t); mpz_clear (u); if (batch == 2) { mpz_clear (d_2); } return ret; }
static unsigned long get_digit(void *a, int n) { LTC_ARGCHK(a != NULL); return mpz_getlimbn(a, n); }
static ltc_mp_digit get_digit(void *a, int n) { LTC_ARGCHK(a != NULL); return mpz_getlimbn(a, n); }
static PyObject * GMPy_MPZ_pack(PyObject *self, PyObject *args) { mp_bitcnt_t nbits, total_bits, tempx_bits; Py_ssize_t index, lst_count, i, temp_bits, limb_count; PyObject *lst; mpz_t temp; MPZ_Object *result, *tempx = 0; CTXT_Object *context = NULL; if (PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("pack() requires 'list','int' arguments"); return NULL; } nbits = mp_bitcnt_t_From_Integer(PyTuple_GET_ITEM(args, 1)); if (nbits == (mp_bitcnt_t)(-1) && PyErr_Occurred()) { return NULL; } if (!PyList_Check(PyTuple_GET_ITEM(args, 0))) { TYPE_ERROR("pack() requires 'list','int' arguments"); return NULL; } if (!(result = GMPy_MPZ_New(context))) return NULL; lst = PyTuple_GET_ITEM(args, 0); lst_count = PyList_GET_SIZE(lst); total_bits = nbits * lst_count; if ((total_bits / lst_count) != nbits) { VALUE_ERROR("result too large to store in an 'mpz'"); return NULL; } mpz_set_ui(result->z, 0); mpz_setbit(result->z, total_bits + (mp_bits_per_limb * 2)); mpz_init(temp); mpz_set_ui(temp, 0); limb_count = 0; tempx_bits = 0; for (index = 0; index < lst_count; index++) { if (!(tempx = GMPy_MPZ_From_Integer(PyList_GetItem(lst, index), context)) || (mpz_sgn(tempx->z) < 0) || (mpz_sizeinbase(tempx->z,2) > (size_t)nbits)) { TYPE_ERROR("pack() requires list elements be positive integers < 2^n bits"); mpz_clear(temp); Py_XDECREF((PyObject*)tempx); Py_DECREF((PyObject*)result); return NULL; } mpz_mul_2exp(tempx->z, tempx->z, tempx_bits); mpz_add(temp, temp, tempx->z); tempx_bits += nbits; i = 0; temp_bits = mpz_sizeinbase(temp, 2) * mpz_sgn(temp); while (tempx_bits >= (mp_bitcnt_t)mp_bits_per_limb) { if (temp_bits > 0) { result->z->_mp_d[limb_count] = mpz_getlimbn(temp, i); } i += 1; tempx_bits -= mp_bits_per_limb; limb_count += 1; temp_bits -= mp_bits_per_limb; } if (temp_bits > 0) { mpz_tdiv_q_2exp(temp, temp, mp_bits_per_limb * i); } else { mpz_set_ui(temp, 0); } Py_DECREF((PyObject*)tempx); } result->z->_mp_d[limb_count] = mpz_getlimbn(temp, 0); mpz_clrbit(result->z, total_bits + (mp_bits_per_limb * 2)); mpz_clear(temp); return (PyObject*)result; }
static PyObject * GMPy_MPZ_unpack(PyObject *self, PyObject *args) { mp_bitcnt_t nbits, total_bits, guard_bit, extra_bits, temp_bits; Py_ssize_t index = 0, lst_count, i, lst_ptr = 0; PyObject *result; mpz_t temp; mp_limb_t extra = 0; MPZ_Object *item, *tempx = NULL; CTXT_Object *context = NULL; if (PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("unpack() requires 'int','int' arguments"); return NULL; } nbits = mp_bitcnt_t_From_Integer(PyTuple_GET_ITEM(args, 1)); if (nbits == (mp_bitcnt_t)(-1) && PyErr_Occurred()) { return NULL; } if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), context))) { TYPE_ERROR("unpack() requires 'int','int' arguments"); return NULL; } if (mpz_sgn(tempx->z) < 0) { VALUE_ERROR("unpack() requires x >= 0"); return NULL; } if (mpz_sgn(tempx->z) == 0) { total_bits = 0; } else { total_bits = mpz_sizeinbase(tempx->z, 2); } lst_count = total_bits / nbits; if ((total_bits % nbits) || !lst_count) { lst_count += 1; } if (!(result = PyList_New(lst_count))) { Py_DECREF((PyObject*)tempx); return NULL; } if (mpz_sgn(tempx->z) == 0) { if (!(item = GMPy_MPZ_New(context))) { Py_DECREF((PyObject*)tempx); Py_DECREF(result); return NULL; } mpz_set_ui(item->z, 0); PyList_SET_ITEM(result, 0, (PyObject*)item); Py_DECREF((PyObject*)tempx); return result; } mpz_init(temp); guard_bit = nbits + (2 * mp_bits_per_limb); extra_bits = 0; index = 0; while (lst_ptr < lst_count) { i = 0; temp_bits = 0; mpz_set_ui(temp, 0); mpz_setbit(temp, guard_bit); while (temp_bits + extra_bits < nbits) { temp->_mp_d[i++] = mpz_getlimbn(tempx->z, index++); temp_bits += mp_bits_per_limb; } mpz_clrbit(temp, guard_bit); mpz_mul_2exp(temp, temp, extra_bits); if (mpz_sgn(temp) == 0 && extra != 0) { mpz_set_ui(temp, 1); temp->_mp_d[0] = extra; } else { mpn_add_1(temp->_mp_d, temp->_mp_d, mpz_size(temp), extra); } temp_bits += extra_bits; while ((lst_ptr < lst_count) && (temp_bits >= nbits)) { if(!(item = GMPy_MPZ_New(context))) { mpz_clear(temp); Py_DECREF((PyObject*)tempx); Py_DECREF(result); return NULL; } mpz_tdiv_r_2exp(item->z, temp, nbits); PyList_SET_ITEM(result, lst_ptr++, (PyObject*)item); mpz_tdiv_q_2exp(temp, temp, nbits); temp_bits -= nbits; } extra = mpz_getlimbn(temp, 0); extra_bits = temp_bits; } Py_DECREF((PyObject*)tempx); mpz_clear(temp); return result; }
/*-------------------------------------------------------------------*/ void alg_square_root(msieve_obj *obj, mp_poly_t *mp_alg_poly, mp_t *n, mp_t *c, signed_mp_t *m1, signed_mp_t *m0, abpair_t *rlist, uint32 num_relations, uint32 check_q, mp_t *sqrt_a) { /* external interface for computing the algebraic square root */ uint32 i; gmp_poly_t alg_poly; gmp_poly_t d_alg_poly; gmp_poly_t prod; gmp_poly_t alg_sqrt; relation_prod_t prodinfo; double log2_prodsize; mpz_t q; /* initialize */ mpz_init(q); gmp_poly_init(&alg_poly); gmp_poly_init(&d_alg_poly); gmp_poly_init(&prod); gmp_poly_init(&alg_sqrt); /* convert the algebraic poly to arbitrary precision */ for (i = 0; i < mp_alg_poly->degree; i++) { signed_mp_t *coeff = mp_alg_poly->coeff + i; mp2gmp(&coeff->num, alg_poly.coeff[i]); if (coeff->sign == NEGATIVE) mpz_neg(alg_poly.coeff[i], alg_poly.coeff[i]); } alg_poly.degree = mp_alg_poly->degree - 1; /* multiply all the relations together */ prodinfo.monic_poly = &alg_poly; prodinfo.rlist = rlist; prodinfo.c = c; logprintf(obj, "multiplying %u relations\n", num_relations); multiply_relations(&prodinfo, 0, num_relations - 1, &prod); logprintf(obj, "multiply complete, coefficients have about " "%3.2lf million bits\n", (double)mpz_sizeinbase(prod.coeff[0], 2) / 1e6); /* perform a sanity check on the result */ i = verify_product(&prod, rlist, num_relations, check_q, c, mp_alg_poly); free(rlist); if (i == 0) { logprintf(obj, "error: relation product is incorrect\n"); goto finished; } /* multiply by the square of the derivative of alg_poly; this will guarantee that the square root of prod actually is an element of the number field defined by alg_poly. If we didn't do this, we run the risk of the main Newton iteration not converging */ gmp_poly_monic_derivative(&alg_poly, &d_alg_poly); gmp_poly_mul(&d_alg_poly, &d_alg_poly, &alg_poly, 0); gmp_poly_mul(&prod, &d_alg_poly, &alg_poly, 1); /* pick the initial small prime to start the Newton iteration. To save both time and memory, choose an initial prime such that squaring it a large number of times will produce a value just a little larger than we need to calculate the square root. Note that contrary to what some authors write, pretty much any starting prime is okay. The Newton iteration has a division by 2, so that 2 must be invertible mod the prime (this is guaranteed for odd primes). Also, the Newton iteration will fail if both square roots have the same value mod the prime; however, even a 16-bit prime makes this very unlikely */ i = mpz_size(prod.coeff[0]); log2_prodsize = (double)GMP_LIMB_BITS * (i - 2) + log(mpz_getlimbn(prod.coeff[0], (mp_size_t)(i-1)) * pow(2.0, (double)GMP_LIMB_BITS) + mpz_getlimbn(prod.coeff[0], (mp_size_t)(i-2))) / M_LN2 + 10000; while (log2_prodsize > 31.5) log2_prodsize *= 0.5; mpz_set_d(q, (uint32)pow(2.0, log2_prodsize) + 1); /* get the initial inverse square root */ if (!get_initial_inv_sqrt(obj, mp_alg_poly, &prod, &alg_sqrt, q)) { goto finished; } /* compute the actual square root */ if (get_final_sqrt(obj, &alg_poly, &prod, &alg_sqrt, q)) convert_to_integer(&alg_sqrt, n, c, m1, m0, sqrt_a); finished: gmp_poly_clear(&prod); gmp_poly_clear(&alg_sqrt); gmp_poly_clear(&alg_poly); gmp_poly_clear(&d_alg_poly); mpz_clear(q); }
int main (int argc, char **argv) { mpz_t base, exp, mod; mpz_t r1, r2, base2; mp_size_t base_size, exp_size, mod_size; unsigned long int exp2; int i; int reps = 100; gmp_randstate_ptr rands; mpz_t bs; unsigned long bsi, size_range; tests_start (); rands = RANDS; mpz_init (bs); if (argc == 2) reps = atoi (argv[1]); mpz_init (base); mpz_init (exp); mpz_init (mod); mpz_init (r1); mpz_init (r2); mpz_init (base2); for (i = 0; i < reps; i++) { mpz_urandomb (bs, rands, 32); size_range = mpz_get_ui (bs) % 18 + 2; do /* Loop until mathematically well-defined. */ { mpz_urandomb (bs, rands, size_range); base_size = mpz_get_ui (bs); mpz_rrandomb (base, rands, base_size); mpz_urandomb (bs, rands, 6L); exp_size = mpz_get_ui (bs); mpz_rrandomb (exp, rands, exp_size); exp2 = mpz_getlimbn (exp, (mp_size_t) 0); } while (mpz_cmp_ui (base, 0) == 0 && exp2 == 0); do { mpz_urandomb (bs, rands, size_range); mod_size = mpz_get_ui (bs); mpz_rrandomb (mod, rands, mod_size); } while (mpz_cmp_ui (mod, 0) == 0); mpz_urandomb (bs, rands, 2); bsi = mpz_get_ui (bs); if ((bsi & 1) != 0) mpz_neg (base, base); /* printf ("%ld %ld\n", SIZ (base), SIZ (mod)); */ #if 0 putc ('\n', stderr); debug_mp (base, -16); debug_mp (mod, -16); #endif mpz_powm_ui (r1, base, exp2, mod); MPZ_CHECK_FORMAT (r1); mpz_set_ui (r2, 1); mpz_set (base2, base); mpz_mod (r2, r2, mod); /* needed when exp==0 and mod==1 */ while (exp2 != 0) { if (exp2 % 2 != 0) { mpz_mul (r2, r2, base2); mpz_mod (r2, r2, mod); } mpz_mul (base2, base2, base2); mpz_mod (base2, base2, mod); exp2 = exp2 / 2; } #if 0 debug_mp (r1, -16); debug_mp (r2, -16); #endif if (mpz_cmp (r1, r2) != 0) { fprintf (stderr, "\ntest %d: Incorrect results for operands:\n", i); debug_mp (base, -16); debug_mp (exp, -16); debug_mp (mod, -16); fprintf (stderr, "mpz_powm_ui result:\n"); debug_mp (r1, -16); fprintf (stderr, "reference result:\n"); debug_mp (r2, -16); abort (); } } mpz_clear (bs); mpz_clear (base); mpz_clear (exp); mpz_clear (mod); mpz_clear (r1); mpz_clear (r2); mpz_clear (base2); tests_end (); exit (0); }