int RingZZ::is_positive(const ring_elem f) const { mpz_ptr a = f.get_mpz(); return mpz_sgn(a) > 0; }
static PyObject * GMPY_mpz_is_fibonacci_prp(PyObject *self, PyObject *args) { MPZ_Object *n, *p, *q; PyObject *result = 0; mpz_t pmodn, zP; /* used for calculating the Lucas V sequence */ mpz_t vl, vh, ql, qh, tmp; mp_bitcnt_t s = 0, j = 0; if (PyTuple_Size(args) != 3) { TYPE_ERROR("is_fibonacci_prp() requires 3 integer arguments"); return NULL; } mpz_init(pmodn); mpz_init(zP); mpz_init(vl); mpz_init(vh); mpz_init(ql); mpz_init(qh); mpz_init(tmp); n = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL); p = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL); q = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 2), NULL); if (!n || !p || !q) { TYPE_ERROR("is_fibonacci_prp() requires 3 integer arguments"); goto cleanup; } /* Check if p*p - 4*q == 0. */ mpz_mul(tmp, p->z, p->z); mpz_mul_ui(qh, q->z, 4); mpz_sub(tmp, tmp, qh); if (mpz_sgn(tmp) == 0) { VALUE_ERROR("invalid values for p,q in is_fibonacci_prp()"); goto cleanup; } /* Verify q = +/-1 */ if ((mpz_cmp_si(q->z, 1) && mpz_cmp_si(q->z, -1)) || (mpz_sgn(p->z) <= 0)) { VALUE_ERROR("invalid values for p,q in is_fibonacci_prp()"); goto cleanup; } /* Require n > 0. */ if (mpz_sgn(n->z) <= 0) { VALUE_ERROR("is_fibonacci_prp() requires 'n' be greater than 0"); goto cleanup; } /* Check for n == 1 */ if (mpz_cmp_ui(n->z, 1) == 0) { result = Py_False; goto cleanup; } /* Handle n even. */ if (mpz_divisible_ui_p(n->z, 2)) { if (mpz_cmp_ui(n->z, 2) == 0) result = Py_True; else result = Py_False; goto cleanup; } mpz_set(zP, p->z); mpz_mod(pmodn, zP, n->z); /* mpz_lucasvmod(res, p, q, n, n); */ mpz_set_si(vl, 2); mpz_set(vh, p->z); mpz_set_si(ql, 1); mpz_set_si(qh, 1); mpz_set_si(tmp,0); s = mpz_scan1(n->z, 0); for (j = mpz_sizeinbase(n->z,2)-1; j >= s+1; j--) { /* ql = ql*qh (mod n) */ mpz_mul(ql, ql, qh); mpz_mod(ql, ql, n->z); if (mpz_tstbit(n->z,j) == 1) { /* qh = ql*q */ mpz_mul(qh, ql, q->z); /* vl = vh*vl - p*ql (mod n) */ mpz_mul(vl, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n->z); /* vh = vh*vh - 2*qh (mod n) */ mpz_mul(vh, vh, vh); mpz_mul_si(tmp, qh, 2); mpz_sub(vh, vh, tmp); mpz_mod(vh, vh, n->z); } else { /* qh = ql */ mpz_set(qh, ql); /* vh = vh*vl - p*ql (mod n) */ mpz_mul(vh, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vh, vh, tmp); mpz_mod(vh, vh, n->z); /* vl = vl*vl - 2*ql (mod n) */ mpz_mul(vl, vl, vl); mpz_mul_si(tmp, ql, 2); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n->z); } } /* ql = ql*qh */ mpz_mul(ql, ql, qh); /* qh = ql*q */ mpz_mul(qh, ql, q->z); /* vl = vh*vl - p*ql */ mpz_mul(vl, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vl, vl, tmp); /* ql = ql*qh */ mpz_mul(ql, ql, qh); for (j = 1; j <= s; j++) { /* vl = vl*vl - 2*ql (mod n) */ mpz_mul(vl, vl, vl); mpz_mul_si(tmp, ql, 2); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n->z); /* ql = ql*ql (mod n) */ mpz_mul(ql, ql, ql); mpz_mod(ql, ql, n->z); } /* vl contains our return value */ mpz_mod(vl, vl, n->z); if (mpz_cmp(vl, pmodn) == 0) result = Py_True; else result = Py_False; cleanup: Py_XINCREF(result); mpz_clear(pmodn); mpz_clear(zP); mpz_clear(vl); mpz_clear(vh); mpz_clear(ql); mpz_clear(qh); mpz_clear(tmp); Py_XDECREF((PyObject*)p); Py_XDECREF((PyObject*)q); Py_XDECREF((PyObject*)n); return result; }
static PyObject * GMPY_mpz_is_lucas_prp(PyObject *self, PyObject *args) { MPZ_Object *n, *p, *q; PyObject *result = 0; mpz_t zD, res, index; /* used for calculating the Lucas U sequence */ mpz_t uh, vl, vh, ql, qh, tmp; mp_bitcnt_t s = 0, j = 0; int ret; if (PyTuple_Size(args) != 3) { TYPE_ERROR("is_lucas_prp() requires 3 integer arguments"); return NULL; } mpz_init(zD); mpz_init(res); mpz_init(index); mpz_init(uh); mpz_init(vl); mpz_init(vh); mpz_init(ql); mpz_init(qh); mpz_init(tmp); n = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL); p = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL); q = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 2), NULL); if (!n || !p || !q) { TYPE_ERROR("is_lucas_prp() requires 3 integer arguments"); goto cleanup; } /* Check if p*p - 4*q == 0. */ mpz_mul(zD, p->z, p->z); mpz_mul_ui(tmp, q->z, 4); mpz_sub(zD, zD, tmp); if (mpz_sgn(zD) == 0) { VALUE_ERROR("invalid values for p,q in is_lucas_prp()"); goto cleanup; } /* Require n > 0. */ if (mpz_sgn(n->z) <= 0) { VALUE_ERROR("is_lucas_prp() requires 'n' be greater than 0"); goto cleanup; } /* Check for n == 1 */ if (mpz_cmp_ui(n->z, 1) == 0) { result = Py_False; goto cleanup; } /* Handle n even. */ if (mpz_divisible_ui_p(n->z, 2)) { if (mpz_cmp_ui(n->z, 2) == 0) result = Py_True; else result = Py_False; goto cleanup; } /* Check GCD */ mpz_mul(res, zD, q->z); mpz_mul_ui(res, res, 2); mpz_gcd(res, res, n->z); if ((mpz_cmp(res, n->z) != 0) && (mpz_cmp_ui(res, 1) > 0)) { VALUE_ERROR("is_lucas_prp() requires gcd(n,2*q*D) == 1"); goto cleanup; } /* index = n-(D/n), where (D/n) is the Jacobi symbol */ mpz_set(index, n->z); ret = mpz_jacobi(zD, n->z); if (ret == -1) mpz_add_ui(index, index, 1); else if (ret == 1) mpz_sub_ui(index, index, 1); /* mpz_lucasumod(res, p, q, index, n); */ mpz_set_si(uh, 1); mpz_set_si(vl, 2); mpz_set(vh, p->z); mpz_set_si(ql, 1); mpz_set_si(qh, 1); mpz_set_si(tmp,0); s = mpz_scan1(index, 0); for (j = mpz_sizeinbase(index,2)-1; j >= s+1; j--) { /* ql = ql*qh (mod n) */ mpz_mul(ql, ql, qh); mpz_mod(ql, ql, n->z); if (mpz_tstbit(index,j) == 1) { /* qh = ql*q */ mpz_mul(qh, ql, q->z); /* uh = uh*vh (mod n) */ mpz_mul(uh, uh, vh); mpz_mod(uh, uh, n->z); /* vl = vh*vl - p*ql (mod n) */ mpz_mul(vl, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n->z); /* vh = vh*vh - 2*qh (mod n) */ mpz_mul(vh, vh, vh); mpz_mul_si(tmp, qh, 2); mpz_sub(vh, vh, tmp); mpz_mod(vh, vh, n->z); } else { /* qh = ql */ mpz_set(qh, ql); /* uh = uh*vl - ql (mod n) */ mpz_mul(uh, uh, vl); mpz_sub(uh, uh, ql); mpz_mod(uh, uh, n->z); /* vh = vh*vl - p*ql (mod n) */ mpz_mul(vh, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vh, vh, tmp); mpz_mod(vh, vh, n->z); /* vl = vl*vl - 2*ql (mod n) */ mpz_mul(vl, vl, vl); mpz_mul_si(tmp, ql, 2); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n->z); } } /* ql = ql*qh */ mpz_mul(ql, ql, qh); /* qh = ql*q */ mpz_mul(qh, ql, q->z); /* uh = uh*vl - ql */ mpz_mul(uh, uh, vl); mpz_sub(uh, uh, ql); /* vl = vh*vl - p*ql */ mpz_mul(vl, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vl, vl, tmp); /* ql = ql*qh */ mpz_mul(ql, ql, qh); for (j = 1; j <= s; j++) { /* uh = uh*vl (mod n) */ mpz_mul(uh, uh, vl); mpz_mod(uh, uh, n->z); /* vl = vl*vl - 2*ql (mod n) */ mpz_mul(vl, vl, vl); mpz_mul_si(tmp, ql, 2); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n->z); /* ql = ql*ql (mod n) */ mpz_mul(ql, ql, ql); mpz_mod(ql, ql, n->z); } /* uh contains our return value */ mpz_mod(res, uh, n->z); if (mpz_cmp_ui(res, 0) == 0) result = Py_True; else result = Py_False; cleanup: Py_XINCREF(result); mpz_clear(zD); mpz_clear(res); mpz_clear(index); mpz_clear(uh); mpz_clear(vl); mpz_clear(vh); mpz_clear(ql); mpz_clear(qh); mpz_clear(tmp); Py_XDECREF((PyObject*)p); Py_XDECREF((PyObject*)q); Py_XDECREF((PyObject*)n); return result; }
static PyObject * GMPY_mpz_is_strongselfridge_prp(PyObject *self, PyObject *args) { MPZ_Object *n; PyObject *result = 0, *temp = 0; long d = 5, p = 1, q = 0, max_d = 1000000; int jacobi = 0; mpz_t zD; if (PyTuple_Size(args) != 1) { TYPE_ERROR("is_strong_selfridge_prp() requires 1 integer argument"); return NULL; } mpz_init(zD); n = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL); if (!n) { TYPE_ERROR("is_strong_selfridge_prp() requires 1 integer argument"); goto cleanup; } /* Require n > 0. */ if (mpz_sgn(n->z) <= 0) { VALUE_ERROR("is_strong_selfridge_prp() requires 'n' be greater than 0"); goto cleanup; } /* Check for n == 1 */ if (mpz_cmp_ui(n->z, 1) == 0) { result = Py_False; goto cleanup; } /* Handle n even. */ if (mpz_divisible_ui_p(n->z, 2)) { if (mpz_cmp_ui(n->z, 2) == 0) result = Py_True; else result = Py_False; goto cleanup; } mpz_set_ui(zD, d); while (1) { jacobi = mpz_jacobi(zD, n->z); /* if jacobi == 0, d is a factor of n, therefore n is composite... */ /* if d == n, then either n is either prime or 9... */ if (jacobi == 0) { if ((mpz_cmpabs(zD, n->z) == 0) && (mpz_cmp_ui(zD, 9) != 0)) { result = Py_True; goto cleanup; } else { result = Py_False; goto cleanup; } } if (jacobi == -1) break; /* if we get to the 5th d, make sure we aren't dealing with a square... */ if (d == 13) { if (mpz_perfect_square_p(n->z)) { result = Py_False; goto cleanup; } } if (d < 0) { d *= -1; d += 2; } else { d += 2; d *= -1; } /* make sure we don't search forever */ if (d >= max_d) { VALUE_ERROR("appropriate value for D cannot be found in is_strong_selfridge_prp()"); goto cleanup; } mpz_set_si(zD, d); } q = (1-d)/4; /* Since "O" is used, the refcount for n is incremented so deleting * temp will not delete n. */ temp = Py_BuildValue("Oll", n, p, q); if (!temp) goto cleanup; result = GMPY_mpz_is_stronglucas_prp(NULL, temp); Py_DECREF(temp); goto return_result; cleanup: Py_XINCREF(result); return_result: mpz_clear(zD); Py_DECREF((PyObject*)n); return result; }
static PyObject * GMPY_mpz_is_strongbpsw_prp(PyObject *self, PyObject *args) { MPZ_Object *n; PyObject *result = 0, *temp = 0; if (PyTuple_Size(args) != 1) { TYPE_ERROR("is_strong_bpsw_prp() requires 1 integer argument"); return NULL; } n = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL); if (!n) { TYPE_ERROR("is_strong_bpsw_prp() requires 1 integer argument"); goto cleanup; } /* Require n > 0. */ if (mpz_sgn(n->z) <= 0) { VALUE_ERROR("is_strong_bpsw_prp() requires 'n' be greater than 0"); goto cleanup; } /* Check for n == 1 */ if (mpz_cmp_ui(n->z, 1) == 0) { result = Py_False; goto cleanup; } /* Handle n even. */ if (mpz_divisible_ui_p(n->z, 2)) { if (mpz_cmp_ui(n->z, 2) == 0) result = Py_True; else result = Py_False; goto cleanup; } /* "O" is used to increment the reference to n so deleting temp won't * delete n. */ temp = Py_BuildValue("Oi", n, 2); if (!temp) goto cleanup; result = GMPY_mpz_is_strong_prp(NULL, temp); Py_DECREF(temp); if (result == Py_False) goto return_result; /* Remember to ignore the preceding result */ Py_DECREF(result); temp = Py_BuildValue("O", n); if (!temp) goto cleanup; result = GMPY_mpz_is_selfridge_prp(NULL, temp); Py_DECREF(temp); goto return_result; cleanup: Py_XINCREF(result); return_result: Py_DECREF((PyObject*)n); return result; }
/* can't be bothered doing the english version ... * we often just use the american version anyway. */ static size_t words_conv(Vstr_base *s1, size_t pos, const mpz_t num, int cap, int del) { size_t orig_pos = pos; struct Words_conv { const char *num; const char *str; const size_t len; mpz_t bignum; }; static struct Words_conv conv_m[] = { #if 0 WORDS_MAKE("1" VAL0_300() VAL0_3(), "centillion"), WORDS_MAKE("1" VAL0_60() VAL0_3(), "vigintillion"), WORDS_MAKE("1" VAL0_60(), "novemdecillion"), WORDS_MAKE("1" VAL0_30() VAL0_15() VAL0_12(), "octodecillion"), WORDS_MAKE("1" VAL0_30() VAL0_15() VAL0_9(), "septendecillion"), WORDS_MAKE("1" VAL0_30() VAL0_15() VAL0_6(), "sexdecillion"), WORDS_MAKE("1" VAL0_30() VAL0_15() VAL0_3(), "quindecillion"), WORDS_MAKE("1" VAL0_30() VAL0_15(), "quattuordecillion"), WORDS_MAKE("1" VAL0_30() VAL0_12(), "tredecillion"), WORDS_MAKE("1" VAL0_30() VAL0_9(), "duodecillion"), WORDS_MAKE("1" VAL0_30() VAL0_6(), "undecillion"), WORDS_MAKE("1" VAL0_30() VAL0_3(), "decillion"), WORDS_MAKE("1" VAL0_30(), "nonillion"), WORDS_MAKE("1" VAL0_15() VAL0_12(), "octillion"), WORDS_MAKE("1" VAL0_15() VAL0_9(), "septillion"), WORDS_MAKE("1" VAL0_15() VAL0_6(), "sextillion"), #endif WORDS_MAKE("1" VAL0_15() VAL0_3(), "quintillion"), WORDS_MAKE("1" VAL0_15(), "quadrillion"), WORDS_MAKE("1" VAL0_12(), "trillion"), WORDS_MAKE("1" VAL0_9(), "billion"), WORDS_MAKE("1" VAL0_6(), "million"), WORDS_MAKE("1" VAL0_3(), "thousand"), WORDS_MAKE("100", "hundred"), }; static struct Words_conv conv_and = WORDS_MAKE("&", "and"); static struct Words_conv conv_a[] = { WORDS_MAKE("90", "ninety"), WORDS_MAKE("80", "eighty"), WORDS_MAKE("70", "seventy"), WORDS_MAKE("60", "sixty"), WORDS_MAKE("50", "fifty"), WORDS_MAKE("40", "forty"), WORDS_MAKE("30", "thirty"), WORDS_MAKE("20", "twenty"), WORDS_MAKE("19", "nineteen"), WORDS_MAKE("18", "eighteen"), WORDS_MAKE("17", "seventeen"), WORDS_MAKE("16", "sixteen"), WORDS_MAKE("15", "fifteen"), WORDS_MAKE("14", "fourteen"), WORDS_MAKE("13", "thirteen"), WORDS_MAKE("12", "twelve"), WORDS_MAKE("11", "eleven"), WORDS_MAKE("10", "ten"), WORDS_MAKE("9", "nine"), WORDS_MAKE("8", "eight"), WORDS_MAKE("7", "seven"), WORDS_MAKE("6", "six"), WORDS_MAKE("5", "five"), WORDS_MAKE("4", "four"), WORDS_MAKE("3", "three"), WORDS_MAKE("2", "two"), WORDS_MAKE("1", "one"), }; static struct Words_conv conv_zero = WORDS_MAKE("0", "zero"); static struct Words_conv conv_minus = WORDS_MAKE("-", "minus"); static int done = FALSE; struct Words_conv *scan = conv_m; unsigned int alen = sizeof(conv_m) / sizeof(conv_m[0]); size_t ret = 0; mpz_t tmp; if (!done) { while (alen) { mpz_init_set_str(scan->bignum, scan->num, 10); --alen; ++scan; } scan = conv_a; alen = sizeof(conv_a) / sizeof(conv_a[0]); while (alen) { mpz_init_set_str(scan->bignum, scan->num, 10); --alen; ++scan; } scan = conv_m; alen = sizeof(conv_m) / sizeof(conv_m[0]); done = TRUE; } mpz_init_set(tmp, num); mpz_abs(tmp, tmp); if (mpz_cmp_ui(num, 0) == 0) { scan = &conv_zero; WORDS_ADD_WORD(); } else { while (alen) { mpz_t quo; mpz_init(quo); while (mpz_cmp(tmp, scan->bignum) >= 0) { size_t front = 0; mpz_tdiv_qr(quo, tmp, tmp, scan->bignum); if (!(front = words_conv(s1, pos, quo, FALSE, FALSE))) return (0); ret += front; pos += front; WORDS_ADD_WORD(); } --alen; ++scan; } if (ret && (mpz_cmp_ui(tmp, 0) != 0)) { scan = &conv_and; WORDS_ADD_WORD(); } scan = conv_a; alen = sizeof(conv_a) / sizeof(conv_a[0]); while (alen) { while (mpz_cmp(tmp, scan->bignum) >= 0) { mpz_mod(tmp, tmp, scan->bignum); WORDS_ADD_WORD(); } --alen; ++scan; } } ASSERT(ret >= 2); if (mpz_sgn(num) == -1) { scan = &conv_minus; pos = orig_pos; WORDS_ADD_WORD(); } ASSERT(ret >= 2); ++orig_pos; if (del) { /* get rid of space */ if (s1) vstr_del(s1, orig_pos, 1); --ret; } if (cap && s1 && !vstr_conv_uppercase(s1, orig_pos, 1)) /* capitalize */ return (0); return (ret); }
static PyObject * GMPy_Integer_FloorDiv(PyObject *x, PyObject *y, CTXT_Object *context) { MPZ_Object *result; if (!(result = GMPy_MPZ_New(context))) return NULL; if (CHECK_MPZANY(x)) { if (PyIntOrLong_Check(y)) { int error; native_si temp = GMPy_Integer_AsNative_siAndError(y, &error); if (!error) { if (temp > 0) { mpz_fdiv_q_ui(result->z, MPZ(x), temp); } else if (temp == 0) { ZERO_ERROR("division or modulo by zero"); Py_DECREF((PyObject*)result); return NULL; } else { mpz_cdiv_q_ui(result->z, MPZ(x), -temp); mpz_neg(result->z, result->z); } } else { mpz_set_PyIntOrLong(global.tempz, y); mpz_fdiv_q(result->z, MPZ(x), global.tempz); } return (PyObject*)result; } if (CHECK_MPZANY(y)) { if (mpz_sgn(MPZ(y)) == 0) { ZERO_ERROR("division or modulo by zero"); Py_DECREF((PyObject*)result); return NULL; } mpz_fdiv_q(result->z, MPZ(x), MPZ(y)); return (PyObject*)result; } } if (CHECK_MPZANY(y)) { if (mpz_sgn(MPZ(y)) == 0) { ZERO_ERROR("division or modulo by zero"); Py_DECREF((PyObject*)result); return NULL; } if (PyIntOrLong_Check(x)) { mpz_set_PyIntOrLong(global.tempz, x); mpz_fdiv_q(result->z, global.tempz, MPZ(y)); return (PyObject*)result; } } if (IS_INTEGER(x) && IS_INTEGER(y)) { MPZ_Object *tempx, *tempy; tempx = GMPy_MPZ_From_Integer(x, context); tempy = GMPy_MPZ_From_Integer(y, context); if (!tempx || !tempy) { Py_XDECREF((PyObject*)tempx); Py_XDECREF((PyObject*)tempy); Py_DECREF((PyObject*)result); return NULL; } if (mpz_sgn(tempy->z) == 0) { ZERO_ERROR("division or modulo by zero"); Py_XDECREF((PyObject*)tempx); Py_XDECREF((PyObject*)tempy); Py_DECREF((PyObject*)result); return NULL; } mpz_fdiv_q(result->z, tempx->z, tempy->z); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); return (PyObject*)result; } Py_DECREF((PyObject*)result); Py_RETURN_NOTIMPLEMENTED; }
void input_poly(mpz_t N, mpz_t ** A, i32_t *adeg, mpz_t ** B, i32_t *bdeg, mpz_t m, FILE *fp) /*******************************************************/ { char token[256], value[512], thisLine[1024]; int i, j, cont=1, have_m=0; mpz_t tmpA, tmpB; *adeg = *bdeg = 0; *A = xmalloc(9*sizeof(**A)); /* plenty o' room. */ *B = xmalloc(9*sizeof(**B)); for (i=0; i<9; i++) { mpz_init_set_ui((*A)[i], 0); mpz_init_set_ui((*B)[i], 0); } while (cont) { thisLine[0] = 0; fgets(thisLine, 1023, fp); if ((sscanf(thisLine, "%255s %511s", token, value)==2) && (thisLine[0] != '#')) { token[sizeof(token)-1] = 0; if (strncmp(token, "n:", 2)==0) { mpz_set_str(N, value, 10); } else if (strncmp(token, "m:", 2)==0) { mpz_set_str(m, value, 10); have_m=1; } else if ((token[0]=='c') && (token[1] >= '0') && (token[1] <= '8')) { mpz_set_str((*A)[token[1]-'0'], value, 10); *adeg = MAX(*adeg, token[1]-'0'); } else if ((token[0]=='Y') && (token[1] >= '0') && (token[1] <= '8')) { mpz_set_str((*B)[token[1]-'0'], value, 10); *bdeg = MAX(*bdeg, token[1]-'0'); } else if (strncmp(token, "END_POLY", 8)==0) { cont=0; } } if (feof(fp)) cont=0; } if (have_m == 0) { /* recover m from the linear poly */ if (*bdeg == 1) { /* assume *B is linear (it usually is) */ mpz_invert(m, (*B)[1], N); mpz_mul(m, m, (*B)[0]); mpz_neg(m, m); mpz_mod(m, m, N); } else { complain("could not find m\n"); } } else if (*bdeg == 0) { /* monic linear poly may be omitted */ mpz_set_ui((*B)[1], 1); mpz_neg((*B)[0], m); *bdeg=1; } /* Verify the polynomials: */ mpz_init_set(tmpA, (*A)[*adeg]); for (i = *adeg - 1; i >= 0; i--) { mpz_mul(tmpA, tmpA, m); mpz_add(tmpA, tmpA, (*A)[i]); mpz_mod(tmpA, tmpA, N); } mpz_init_set(tmpB, (*B)[*bdeg]); for (i = *bdeg - 1; i >= 0; i--) { mpz_mul(tmpB, tmpB, m); mpz_add(tmpB, tmpB, (*B)[i]); mpz_mod(tmpB, tmpB, N); } if (mpz_sgn(tmpA) || mpz_sgn(tmpB)) { printf("Error: m is not a common root of the polynomials:\n"); for (i=0; i<=*adeg; i++) printf("c%d: %s\n", i, mpz_get_str(value, 10, (*A)[i])); for (i=0; i<=*bdeg; i++) printf("Y%d: %s\n", i, mpz_get_str(value, 10, (*B)[i])); printf("n: "); mpz_out_str(NULL,10,N); exit(-1); } mpz_clear(tmpA); mpz_clear(tmpB); }
void input_poly(mpz_t N, mpz_t ** A, i32_t * adeg_ptr, mpz_t ** B, i32_t * bdeg_ptr, mpz_t m, FILE * input_file) /*******************************************************/ { char *input_line = NULL; size_t input_line_alloc = 0; i32_t have_m = 0; if (mpz_inp_str(N, input_file, 10) == 0) complain("Cannot read number which is to be factored: %m\n"); *adeg_ptr = -1; *bdeg_ptr = -1; while (have_m == 0) { i32_t grad; char *field; if (skip_blanks_comments(&input_line, &input_line_alloc, input_file) <= 0) complain ("Cannot read common root of NFS polynomials from input file\n"); switch (*input_line) { case 'X': if (sscanf(input_line + 1, "%d", &grad) == 0) complain("Cannot understand input line %s\n", input_line); if (grad > *adeg_ptr) { i32_t i; if (*adeg_ptr >= 0) *A = xrealloc(*A, (grad + 1) * sizeof(**A)); else *A = xmalloc((grad + 1) * sizeof(**A)); for (i = *adeg_ptr + 1; i <= grad; i++) mpz_init_set_ui((*A)[i], 0); *adeg_ptr = grad; } strtok(input_line, " \t"); field = strtok(NULL, " \t"); if (string2mpz((*A)[grad], field, 10) != 0) complain("Cannot understand number %s\n", field); break; case 'Y': if (sscanf(input_line + 1, "%d", &grad) == 0) complain("Cannot understand input line %s\n", input_line); if (grad > *bdeg_ptr) { i32_t i; if (*bdeg_ptr >= 0) *B = xrealloc(*B, (grad + 1) * sizeof(**B)); else *B = xmalloc((grad + 1) * sizeof(**B)); for (i = *bdeg_ptr + 1; i <= grad; i++) mpz_init_set_ui((*B)[i], 0); *bdeg_ptr = grad; } strtok(input_line, " \t"); field = strtok(NULL, " \t"); if (string2mpz((*B)[grad], field, 10) != 0) complain("Cannot understand number %s\n", field); break; case 'M': strtok(input_line, " \t"); field = strtok(NULL, " \t"); if (string2mpz(m, field, 10) != 0) complain("Cannot understand number %s\n", field); have_m = 1; break; } } if (*adeg_ptr == -1) { *adeg_ptr = 1; *A = xmalloc(2 * sizeof(**A)); mpz_init_set_ui((*A)[1], 1); mpz_init((*A)[0]); mpz_neg((*A)[0], m); } if (*bdeg_ptr == -1) { *bdeg_ptr = 1; *B = xmalloc(2 * sizeof(**B)); mpz_init_set_ui((*B)[1], 1); mpz_init((*B)[0]); mpz_neg((*B)[0], m); } if (*adeg_ptr == 0 || *bdeg_ptr == 0) complain("Polynomials of degree zero are not allowed\n"); { mpz_t x; i32_t i; if (mpz_sgn(*(*A + *adeg_ptr)) == 0) { complain("Leading coefficient (degree %u) vanishes\n", *adeg_ptr); } if (mpz_sgn(*(*B + *bdeg_ptr)) == 0) { complain("Leading coefficient (degree %u) vanishes\n", *bdeg_ptr); } for (i = 1, mpz_init_set(x, (*A)[*adeg_ptr]); i <= *adeg_ptr; i++) { mpz_mul(x, x, m); mpz_add(x, x, (*A)[*adeg_ptr - i]); } mpz_fdiv_r(x, x, N); if (mpz_sgn(x) != 0) { mpz_out_str(stderr, 10, m); complain(" not a root of first poly\n"); } for (i = 1, mpz_set(x, (*B)[*bdeg_ptr]); i <= *bdeg_ptr; i++) { mpz_mul(x, x, m); mpz_add(x, x, (*B)[*bdeg_ptr - i]); } mpz_fdiv_r(x, x, N); if (mpz_sgn(x) != 0) { mpz_out_str(stderr, 10, m); complain(" not a root of second poly\n"); } mpz_clear(x); } free(input_line); }
/*-------------------------------------------------------------------*/ 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; }
void check_one (mpz_srcptr a, unsigned long d) { mpz_t q, r, p, d2exp; int inplace; mpz_init (d2exp); mpz_init (q); mpz_init (r); mpz_init (p); mpz_set_ui (d2exp, 1L); mpz_mul_2exp (d2exp, d2exp, d); #define INPLACE(fun,dst,src,d) \ if (inplace) \ { \ mpz_set (dst, src); \ fun (dst, dst, d); \ } \ else \ fun (dst, src, d); for (inplace = 0; inplace <= 1; inplace++) { INPLACE (mpz_fdiv_q_2exp, q, a, d); INPLACE (mpz_fdiv_r_2exp, r, a, d); mpz_mul_2exp (p, q, d); mpz_add (p, p, r); if (mpz_sgn (r) < 0 || mpz_cmp (r, d2exp) >= 0) { printf ("mpz_fdiv_r_2exp result out of range\n"); goto error; } if (mpz_cmp (p, a) != 0) { printf ("mpz_fdiv_[qr]_2exp doesn't multiply back\n"); goto error; } INPLACE (mpz_cdiv_q_2exp, q, a, d); INPLACE (mpz_cdiv_r_2exp, r, a, d); mpz_mul_2exp (p, q, d); mpz_add (p, p, r); if (mpz_sgn (r) > 0 || mpz_cmpabs (r, d2exp) >= 0) { printf ("mpz_cdiv_r_2exp result out of range\n"); goto error; } if (mpz_cmp (p, a) != 0) { printf ("mpz_cdiv_[qr]_2exp doesn't multiply back\n"); goto error; } INPLACE (mpz_tdiv_q_2exp, q, a, d); INPLACE (mpz_tdiv_r_2exp, r, a, d); mpz_mul_2exp (p, q, d); mpz_add (p, p, r); if (mpz_sgn (r) != 0 && mpz_sgn (r) != mpz_sgn (a)) { printf ("mpz_tdiv_r_2exp result wrong sign\n"); goto error; } if (mpz_cmpabs (r, d2exp) >= 0) { printf ("mpz_tdiv_r_2exp result out of range\n"); goto error; } if (mpz_cmp (p, a) != 0) { printf ("mpz_tdiv_[qr]_2exp doesn't multiply back\n"); goto error; } } mpz_clear (d2exp); mpz_clear (q); mpz_clear (r); mpz_clear (p); return; error: mpz_trace ("a", a); printf ("d=%lu\n", d); mpz_trace ("q", q); mpz_trace ("r", r); mpz_trace ("p", p); mp_trace_base = -16; mpz_trace ("a", a); printf ("d=0x%lX\n", d); mpz_trace ("q", q); mpz_trace ("r", r); mpz_trace ("p", p); abort (); }
/*-------------------------------------------------------------------*/ static void gmp_poly_mul(gmp_poly_t *p1, gmp_poly_t *p2, gmp_poly_t *mod, uint32 free_p2) { /* multiply p1(x) by p2(x) modulo mod(x) (assumed monic) If free_p2 is nonzero the coefficients of p2(x) are freed after being used */ uint32 i, j; uint32 d = mod->degree; uint32 d1 = p1->degree; uint32 d2 = p2->degree; uint32 prod_degree; mpz_t tmp[MAX_POLY_DEGREE + 1]; /* initialize */ for (i = 0; i < MAX_POLY_DEGREE + 1; i++) mpz_init_set_ui(tmp[i], (unsigned long)0); /* multiply p1 by the leading coefficient of p2 */ for (i = 0; i <= d1; i++) { mpz_mul(tmp[i], p1->coeff[i], p2->coeff[d2]); } prod_degree = d1; if (free_p2) { mpz_realloc2(p2->coeff[d2], 1); } /* for each of the other coefficients in p2 */ for (i = d2 - 1; (int32)i >= 0; i--) { /* shift the accumulator up by one, bubbling the highest-order coefficient to the lowest */ for (j = prod_degree; (int32)j >= 0; j--) mpz_swap(tmp[j+1], tmp[j]); /* add in the product of p1(x) and coefficient i of p2 */ for (j = d1; j; j--) { mpz_addmul(tmp[j], p1->coeff[j], p2->coeff[i]); } mpz_mul(tmp[j], p1->coeff[j], p2->coeff[i]); if (free_p2) { mpz_realloc2(p2->coeff[i], 1); } /* recalculate the degree of the result */ prod_degree = d + 1; while (prod_degree && mpz_sgn(tmp[prod_degree]) == 0) prod_degree--; /* if it exceeds the degree of mod(x), subtract mod(x) * (leading accumulator coefficient) */ if (prod_degree <= d) continue; for (j = d; (int32)j >= 0; j--) { mpz_submul(tmp[j], mod->coeff[j], tmp[prod_degree]); } prod_degree--; } /* move the result in the accumulator over to p1 */ for (i = 0; i <= prod_degree; i++) { mpz_swap(p1->coeff[i], tmp[i]); mpz_clear(tmp[i]); } for (; i < MAX_POLY_DEGREE + 1; i++) mpz_clear(tmp[i]); /* recalculate the degree */ i = prod_degree; while (i > 0 && mpz_sgn(p1->coeff[i]) == 0) { mpz_realloc2(p1->coeff[i], 1); i--; } p1->degree = i; }
void eval_block(code *block, map* vars) { while (true) { code_skip_whitespace(block); if (block->source[block->pos] == '?') { uint8_t brackets = 0; size_t start, length = 0; mpz_t value; mpz_init(value); block->pos++; code_skip_whitespace(block); _parse_value(block, value, vars); code_skip_whitespace(block); start = block->pos + 1; while (true) { length++; if (block->source[block->pos] == '{') { brackets++; block->pos++; } else if (block->source[block->pos] == '}') { brackets--; block->pos++; if (brackets == 0) break; } else { block->pos++; } } if (mpz_sgn(value) == 0) { code subblock; code_init(&subblock); code_append(&subblock, block->source + start * sizeof(char), length - 2); eval_block(&subblock, vars); code_free(&subblock); } mpz_clear(value); } else if (block->source[block->pos] == '!') { mpz_t value; mpz_init(value); block->pos++; code_skip_whitespace(block); _parse_value(block, value, vars); mpz_out_str(stdout, 10, value); printf("\n"); mpz_clear(value); } else { char *var = malloc(1024 * sizeof(char)); mpz_t value; mpz_init(value); _parse_variable_name(block, var); code_skip_whitespace(block); switch (block->source[block->pos]) { case '=': block->pos++; code_skip_whitespace(block); _parse_value(block, value, vars); map_set(vars, var, value, false); break; case '+': block->pos += 2; code_skip_whitespace(block); _parse_value(block, value, vars); map_set(vars, var, value, true); break; case '-': block->pos += 2; code_skip_whitespace(block); _parse_value(block, value, vars); mpz_neg(value, value); map_set(vars, var, value, true); break; default: fprintf(stderr, "Parse error\n"); } free(var); mpz_clear(value); } code_skip_whitespace(block); if (block->pos >= block->length) return; if (block->source[block->pos] == ';') { block->pos++; } else { fprintf(stderr, "Missing ;\n"); return; } } }
static int GMPy_XMPZ_NonZero_Slot(XMPZ_Object *x) { return mpz_sgn(x->z) != 0; }
int chpl_mpz_sgn(const mpz_t op) { return mpz_sgn(op); }
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; }
static int pol_expand(curr_poly_t *c, mpz_t gmp_N, mpz_t high_coeff, mpz_t gmp_p, mpz_t gmp_d, double coeff_bound, uint32 degree) { uint32 i, j; if (mpz_cmp_ui(c->gmp_p, (mp_limb_t)1) == 0) mpz_set_ui(c->gmp_help1, (mp_limb_t)1); else { if (!mpz_invert(c->gmp_help1, gmp_d, gmp_p)) return 0; } mpz_set(c->gmp_b[1], c->gmp_help1); for (i = 2; i < degree; i++) mpz_mul(c->gmp_b[i], c->gmp_b[i-1], c->gmp_help1); mpz_set(c->gmp_c[1], gmp_d); for (i = 2; i <= degree; i++) mpz_mul(c->gmp_c[i], c->gmp_c[i-1], gmp_d); mpz_set(c->gmp_a[degree], high_coeff); mpz_set(c->gmp_help2, gmp_N); for (i = degree - 1; (int32)i >= 0; i--) { mpz_mul(c->gmp_help3, c->gmp_a[i+1], c->gmp_c[i+1]); mpz_sub(c->gmp_help3, c->gmp_help2, c->gmp_help3); mpz_tdiv_q(c->gmp_help2, c->gmp_help3, gmp_p); if (i > 0) { mpz_tdiv_q(c->gmp_a[i], c->gmp_help2, c->gmp_c[i]); mpz_mul(c->gmp_help3, c->gmp_help2, c->gmp_b[i]); mpz_sub(c->gmp_help3, c->gmp_help3, c->gmp_a[i]); mpz_tdiv_r(c->gmp_help4, c->gmp_help3, gmp_p); if (mpz_sgn(c->gmp_help4) < 0) mpz_add(c->gmp_help4, c->gmp_help4, gmp_p); mpz_add(c->gmp_a[i], c->gmp_a[i], c->gmp_help4); } } mpz_set(c->gmp_a[0], c->gmp_help2); mpz_tdiv_q_2exp(c->gmp_help1, gmp_d, (mp_limb_t)1); for (i = 0; i < degree; i++) { for (j = 0; j < MAX_CORRECT_STEPS && mpz_cmpabs(c->gmp_a[i], c->gmp_help1) > 0; j++) { if (mpz_sgn(c->gmp_a[i]) < 0) { mpz_add(c->gmp_a[i], c->gmp_a[i], gmp_d); mpz_sub(c->gmp_a[i+1], c->gmp_a[i+1], gmp_p); } else { mpz_sub(c->gmp_a[i], c->gmp_a[i], gmp_d); mpz_add(c->gmp_a[i+1], c->gmp_a[i+1], gmp_p); } } if (j == MAX_CORRECT_STEPS) return 0; } #if 0 gmp_printf("%+Zd\n", c->gmp_lina[0]); gmp_printf("%+Zd\n", c->gmp_lina[1]); for (i = 0; i <= degree; i++) gmp_printf("%+Zd\n", c->gmp_a[i]); printf("coeff ratio = %.5lf\n", fabs(mpz_get_d(c->gmp_a[degree-2])) / coeff_bound); #endif if (check_poly(c, c->gmp_a, c->gmp_lina[0], gmp_N, degree) != 1) { return 0; } if (mpz_cmpabs_d(c->gmp_a[degree - 2], coeff_bound) > 0) { return 1; } return 2; }
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; }
/* If x = p/2^r, put in y an approximation of atan(x)/x using 2^m terms for the series expansion, with an error of at most 1 ulp. Assumes |x| < 1. If X=x^2, we want 1 - X/3 + X^2/5 - ... + (-1)^k*X^k/(2k+1) + ... Assume p is non-zero. When we sum terms up to x^k/(2k+1), the denominator Q[0] is 3*5*7*...*(2k+1) ~ (2k/e)^k. */ static void mpfr_atan_aux (mpfr_ptr y, mpz_ptr p, long r, int m, mpz_t *tab) { mpz_t *S, *Q, *ptoj; unsigned long n, i, k, j, l; mpfr_exp_t diff, expo; int im, done; mpfr_prec_t mult, *accu, *log2_nb_terms; mpfr_prec_t precy = MPFR_PREC(y); MPFR_ASSERTD(mpz_cmp_ui (p, 0) != 0); accu = (mpfr_prec_t*) (*__gmp_allocate_func) ((2 * m + 2) * sizeof (mpfr_prec_t)); log2_nb_terms = accu + m + 1; /* Set Tables */ S = tab; /* S */ ptoj = S + 1*(m+1); /* p^2^j Precomputed table */ Q = S + 2*(m+1); /* Product of Odd integer table */ /* From p to p^2, and r to 2r */ mpz_mul (p, p, p); MPFR_ASSERTD (2 * r > r); r = 2 * r; /* Normalize p */ n = mpz_scan1 (p, 0); mpz_tdiv_q_2exp (p, p, n); /* exact */ MPFR_ASSERTD (r > n); r -= n; /* since |p/2^r| < 1, and p is a non-zero integer, necessarily r > 0 */ MPFR_ASSERTD (mpz_sgn (p) > 0); MPFR_ASSERTD (m > 0); /* check if p=1 (special case) */ l = 0; /* We compute by binary splitting, with X = x^2 = p/2^r: P(a,b) = p if a+1=b, P(a,c)*P(c,b) otherwise Q(a,b) = (2a+1)*2^r if a+1=b [except Q(0,1)=1], Q(a,c)*Q(c,b) otherwise S(a,b) = p*(2a+1) if a+1=b, Q(c,b)*S(a,c)+Q(a,c)*P(a,c)*S(c,b) otherwise Then atan(x)/x ~ S(0,i)/Q(0,i) for i so that (p/2^r)^i/i is small enough. The factor 2^(r*(b-a)) in Q(a,b) is implicit, thus we have to take it into account when we compute with Q. */ accu[0] = 0; /* accu[k] = Mult[0] + ... + Mult[k], where Mult[j] is the number of bits of the corresponding term S[j]/Q[j] */ if (mpz_cmp_ui (p, 1) != 0) { /* p <> 1: precompute ptoj table */ mpz_set (ptoj[0], p); for (im = 1 ; im <= m ; im ++) mpz_mul (ptoj[im], ptoj[im - 1], ptoj[im - 1]); /* main loop */ n = 1UL << m; /* the ith term being X^i/(2i+1) with X=p/2^r, we can stop when p^i/2^(r*i) < 2^(-precy), i.e. r*i > precy + log2(p^i) */ for (i = k = done = 0; (i < n) && (done == 0); i += 2, k ++) { /* initialize both S[k],Q[k] and S[k+1],Q[k+1] */ mpz_set_ui (Q[k+1], 2 * i + 3); /* Q(i+1,i+2) */ mpz_mul_ui (S[k+1], p, 2 * i + 1); /* S(i+1,i+2) */ mpz_mul_2exp (S[k], Q[k+1], r); mpz_sub (S[k], S[k], S[k+1]); /* S(i,i+2) */ mpz_mul_ui (Q[k], Q[k+1], 2 * i + 1); /* Q(i,i+2) */ log2_nb_terms[k] = 1; /* S[k]/Q[k] corresponds to 2 terms */ for (j = (i + 2) >> 1, l = 1; (j & 1) == 0; l ++, j >>= 1, k --) { /* invariant: S[k-1]/Q[k-1] and S[k]/Q[k] correspond to 2^l terms each. We combine them into S[k-1]/Q[k-1] */ MPFR_ASSERTD (k > 0); mpz_mul (S[k], S[k], Q[k-1]); mpz_mul (S[k], S[k], ptoj[l]); mpz_mul (S[k-1], S[k-1], Q[k]); mpz_mul_2exp (S[k-1], S[k-1], r << l); mpz_add (S[k-1], S[k-1], S[k]); mpz_mul (Q[k-1], Q[k-1], Q[k]); log2_nb_terms[k-1] = l + 1; /* now S[k-1]/Q[k-1] corresponds to 2^(l+1) terms */ MPFR_MPZ_SIZEINBASE2(mult, ptoj[l+1]); /* FIXME: precompute bits(ptoj[l+1]) outside the loop? */ mult = (r << (l + 1)) - mult - 1; accu[k-1] = (k == 1) ? mult : accu[k-2] + mult; if (accu[k-1] > precy) done = 1; } } }
/*-------------------------------------------------------------------------*/ static int pol_expand(curr_poly_t *c, mpz_t gmp_N) { /* compute coefficients */ mpz_mul(c->gmp_help4, c->gmp_d, c->gmp_d); mpz_mul(c->gmp_help4, c->gmp_help4, c->gmp_help4); mpz_mul(c->gmp_help4, c->gmp_help4, c->gmp_d); mpz_mul(c->gmp_help4, c->gmp_help4, c->gmp_a[5]); mpz_sub(c->gmp_help3, gmp_N, c->gmp_help4); mpz_fdiv_qr(c->gmp_help3, c->gmp_help1, c->gmp_help3, c->gmp_p); if (mpz_sgn(c->gmp_help1)) return 0; if (mpz_cmp_ui(c->gmp_p, 1) == 0) mpz_set_ui(c->gmp_help2, 1); else { if (!mpz_invert(c->gmp_help2, c->gmp_d, c->gmp_p)) return 0; } mpz_mul(c->gmp_help4, c->gmp_help2, c->gmp_help2); mpz_mul(c->gmp_help4, c->gmp_help4, c->gmp_help4); mpz_mul(c->gmp_help4, c->gmp_help4, c->gmp_help3); mpz_fdiv_r(c->gmp_a[4], c->gmp_help4, c->gmp_p); mpz_mul(c->gmp_help4, c->gmp_d, c->gmp_d); mpz_mul(c->gmp_help4, c->gmp_help4, c->gmp_help4); mpz_mul(c->gmp_help4, c->gmp_help4, c->gmp_a[4]); mpz_sub(c->gmp_help3, c->gmp_help3, c->gmp_help4); mpz_fdiv_qr(c->gmp_help3, c->gmp_help1, c->gmp_help3, c->gmp_p); if (mpz_sgn(c->gmp_help1)) return 0; mpz_mul(c->gmp_help4, c->gmp_d, c->gmp_d); mpz_mul(c->gmp_help4, c->gmp_help4, c->gmp_d); mpz_fdiv_q(c->gmp_a[3], c->gmp_help3, c->gmp_help4); mpz_fdiv_q(c->gmp_a[3], c->gmp_a[3], c->gmp_p); mpz_mul(c->gmp_a[3], c->gmp_a[3], c->gmp_p); mpz_mul(c->gmp_help4, c->gmp_help2, c->gmp_help2); mpz_mul(c->gmp_help4, c->gmp_help4, c->gmp_help2); mpz_mul(c->gmp_help4, c->gmp_help4, c->gmp_help3); mpz_fdiv_r(c->gmp_help1, c->gmp_help4, c->gmp_p); mpz_add(c->gmp_a[3], c->gmp_a[3], c->gmp_help1); mpz_mul(c->gmp_help4, c->gmp_d, c->gmp_d); mpz_mul(c->gmp_help4, c->gmp_help4, c->gmp_d); mpz_mul(c->gmp_help4, c->gmp_help4, c->gmp_a[3]); mpz_sub(c->gmp_help3, c->gmp_help3, c->gmp_help4); mpz_fdiv_qr(c->gmp_help3, c->gmp_help1, c->gmp_help3, c->gmp_p); if (mpz_sgn(c->gmp_help1)) return 0; mpz_mul(c->gmp_help4, c->gmp_d, c->gmp_d); mpz_fdiv_q(c->gmp_a[2], c->gmp_help3, c->gmp_help4); mpz_fdiv_q(c->gmp_a[2], c->gmp_a[2], c->gmp_p); mpz_mul(c->gmp_a[2], c->gmp_a[2], c->gmp_p); mpz_mul(c->gmp_help4, c->gmp_help2, c->gmp_help2); mpz_mul(c->gmp_help4, c->gmp_help4, c->gmp_help3); mpz_fdiv_r(c->gmp_help1, c->gmp_help4, c->gmp_p); mpz_add(c->gmp_a[2], c->gmp_a[2], c->gmp_help1); mpz_mul(c->gmp_help4, c->gmp_d, c->gmp_d); mpz_mul(c->gmp_help4, c->gmp_help4, c->gmp_a[2]); mpz_sub(c->gmp_help3, c->gmp_help3, c->gmp_help4); mpz_fdiv_qr(c->gmp_help3, c->gmp_help1, c->gmp_help3, c->gmp_p); if (mpz_sgn(c->gmp_help1)) return 0; mpz_fdiv_q(c->gmp_a[1], c->gmp_help3, c->gmp_d); mpz_fdiv_q(c->gmp_a[1], c->gmp_a[1], c->gmp_p); mpz_mul(c->gmp_a[1], c->gmp_a[1], c->gmp_p); mpz_mul(c->gmp_help4, c->gmp_help3, c->gmp_help2); mpz_fdiv_r(c->gmp_help1, c->gmp_help4, c->gmp_p); mpz_add(c->gmp_a[1], c->gmp_a[1], c->gmp_help1); mpz_mul(c->gmp_help4, c->gmp_d, c->gmp_a[1]); mpz_sub(c->gmp_help3, c->gmp_help3, c->gmp_help4); mpz_fdiv_qr(c->gmp_help3, c->gmp_help1, c->gmp_help3, c->gmp_p); if (mpz_sgn(c->gmp_help1)) return 0; mpz_set(c->gmp_a[0], c->gmp_help3); mpz_fdiv_qr(c->gmp_help1, c->gmp_a[3], c->gmp_a[3], c->gmp_d); mpz_add(c->gmp_help2, c->gmp_a[3], c->gmp_a[3]); if (mpz_cmp(c->gmp_d, c->gmp_help2) < 0) { mpz_sub(c->gmp_a[3], c->gmp_a[3], c->gmp_d); mpz_add_ui(c->gmp_help1, c->gmp_help1, 1); } mpz_mul(c->gmp_help1, c->gmp_help1, c->gmp_p); mpz_add(c->gmp_a[4], c->gmp_a[4], c->gmp_help1); mpz_fdiv_qr(c->gmp_help1, c->gmp_a[2], c->gmp_a[2], c->gmp_d); mpz_add(c->gmp_help2, c->gmp_a[2], c->gmp_a[2]); if (mpz_cmp(c->gmp_d, c->gmp_help2) < 0) { mpz_sub(c->gmp_a[2], c->gmp_a[2], c->gmp_d); mpz_add_ui(c->gmp_help1, c->gmp_help1, 1); } mpz_mul(c->gmp_help1, c->gmp_help1, c->gmp_p); mpz_add(c->gmp_a[3], c->gmp_a[3], c->gmp_help1); mpz_set(c->gmp_lina[1], c->gmp_p); mpz_neg(c->gmp_lina[0], c->gmp_d); mpz_invert(c->gmp_m, c->gmp_p, gmp_N); mpz_mul(c->gmp_m, c->gmp_m, c->gmp_d); mpz_mod(c->gmp_m, c->gmp_m, gmp_N); if (verbose > 2) { int i; printf("pol-expand\npol0: "); for (i = 5; i >= 0; i--) { mpz_out_str(stdout, 10, c->gmp_a[i]); printf(" "); } printf("\npol1: "); mpz_out_str(stdout, 10, c->gmp_lina[1]); printf(" "); mpz_out_str(stdout, 10, c->gmp_lina[0]); printf("\n\n"); } return 1; }
static int Pyxmpz_nonzero(PyxmpzObject *x) { return mpz_sgn(x->z) != 0; }
// x in Z_r, g, h in some group of order r // finds x such that g^x = h void element_dlog_pollard_rho(element_t x, element_t g, element_t h) { // see Blake, Seroussi and Smart // only one snark for this implementation int i, s = 20; field_ptr Zr = x->field, G = g->field; element_t asum; element_t bsum; element_t *a = _alloca(s * sizeof(element_t)); element_t *b = _alloca(s * sizeof(element_t)); element_t *m = _alloca(s * sizeof(element_t)); element_t g0, snark; darray_t hole; int interval = 5; mpz_t counter; int found = 0; mpz_init(counter); element_init(g0, G); element_init(snark, G); element_init(asum, Zr); element_init(bsum, Zr); darray_init(hole); //set up multipliers for (i = 0; i < s; i++) { element_init(a[i], Zr); element_init(b[i], Zr); element_init(m[i], G); element_random(a[i]); element_random(b[i]); element_pow_zn(g0, g, a[i]); element_pow_zn(m[i], h, b[i]); element_mul(m[i], m[i], g0); } element_random(asum); element_random(bsum); element_pow_zn(g0, g, asum); element_pow_zn(snark, h, bsum); element_mul(snark, snark, g0); record(asum, bsum, snark, hole, counter); for (;;) { int len = element_length_in_bytes(snark); unsigned char *buf = pbc_malloc(len); unsigned char hash = 0; element_to_bytes(buf, snark); for (i = 0; i < len; i++) { hash += buf[i]; } i = hash % s; pbc_free(buf); element_mul(snark, snark, m[i]); element_add(asum, asum, a[i]); element_add(bsum, bsum, b[i]); for (i = 0; i < hole->count; i++) { snapshot_ptr ss = hole->item[i]; if (!element_cmp(snark, ss->snark)) { element_sub(bsum, bsum, ss->b); element_sub(asum, ss->a, asum); //answer is x such that x * bsum = asum //complications arise if gcd(bsum, r) > 1 //which can happen if r is not prime if (!mpz_probab_prime_p(Zr->order, 10)) { mpz_t za, zb, zd, zm; mpz_init(za); mpz_init(zb); mpz_init(zd); mpz_init(zm); element_to_mpz(za, asum); element_to_mpz(zb, bsum); mpz_gcd(zd, zb, Zr->order); mpz_divexact(zm, Zr->order, zd); mpz_divexact(zb, zb, zd); //if zd does not divide za there is no solution mpz_divexact(za, za, zd); mpz_invert(zb, zb, zm); mpz_mul(zb, za, zb); mpz_mod(zb, zb, zm); do { element_pow_mpz(g0, g, zb); if (!element_cmp(g0, h)) { element_set_mpz(x, zb); break; } mpz_add(zb, zb, zm); mpz_sub_ui(zd, zd, 1); } while (mpz_sgn(zd)); mpz_clear(zm); mpz_clear(za); mpz_clear(zb); mpz_clear(zd); } else { element_div(x, asum, bsum); } found = 1; break; } } if (found) break; mpz_add_ui(counter, counter, 1); if (mpz_tstbit(counter, interval)) { record(asum, bsum, snark, hole, counter); interval++; } } for (i = 0; i < s; i++) { element_clear(a[i]); element_clear(b[i]); element_clear(m[i]); } element_clear(g0); element_clear(snark); for (i = 0; i < hole->count; i++) { snapshot_ptr ss = hole->item[i]; element_clear(ss->a); element_clear(ss->b); element_clear(ss->snark); pbc_free(ss); } darray_clear(hole); element_clear(asum); element_clear(bsum); mpz_clear(counter); }
static PyObject * GMPY_mpz_is_euler_prp(PyObject *self, PyObject *args) { MPZ_Object *a, *n; PyObject *result = 0; mpz_t res, exp; int ret; if (PyTuple_Size(args) != 2) { TYPE_ERROR("is_euler_prp() requires 2 integer arguments"); return NULL; } n = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL); a = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL); if (!a || !n) { TYPE_ERROR("is_euler_prp() requires 2 integer arguments"); goto cleanup; } mpz_init(res); mpz_init(exp); /* Require a >= 2. */ if (mpz_cmp_ui(a->z, 2) < 0) { VALUE_ERROR("is_euler_prp() requires 'a' greater than or equal to 2"); goto cleanup; } /* Require n > 0. */ if (mpz_sgn(n->z) <= 0) { VALUE_ERROR("is_euler_prp() requires 'n' be greater than 0"); goto cleanup; } /* Check for n == 1 */ if (mpz_cmp_ui(n->z, 1) == 0) { result = Py_False; goto cleanup; } /* Handle n even. */ if (mpz_divisible_ui_p(n->z, 2)) { if (mpz_cmp_ui(n->z, 2) == 0) result = Py_True; else result = Py_False; goto cleanup; } /* Check gcd(a,b) */ mpz_gcd(res, n->z, a->z); if (mpz_cmp_ui(res, 1) > 0) { VALUE_ERROR("is_euler_prp() requires gcd(n,a) == 1"); goto cleanup; } mpz_set(exp, n->z); mpz_sub_ui(exp, exp, 1); mpz_divexact_ui(exp, exp, 2); mpz_powm(res, a->z, exp, n->z); /* reuse exp to calculate jacobi(a,n) mod n */ ret = mpz_jacobi(a->z,n->z); mpz_set(exp, n->z); if (ret == -1) mpz_sub_ui(exp, exp, 1); else if (ret == 1) mpz_add_ui(exp, exp, 1); mpz_mod(exp, exp, n->z); if (mpz_cmp(res, exp) == 0) result = Py_True; else result = Py_False; cleanup: Py_XINCREF(result); mpz_clear(res); mpz_clear(exp); Py_XDECREF((PyObject*)a); Py_XDECREF((PyObject*)n); return result; }
/* Evaluate the expression E and put the result in R. */ void mpz_eval_expr (mpz_ptr r, expr_t e) { mpz_t lhs, rhs; switch (e->op) { case LIT: mpz_set (r, e->operands.val); return; case PLUS: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_add (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; case MINUS: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_sub (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; case MULT: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_mul (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; case DIV: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_fdiv_q (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; case MOD: mpz_init (rhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_abs (rhs, rhs); mpz_eval_mod_expr (r, e->operands.ops.lhs, rhs); mpz_clear (rhs); return; case REM: /* Check if lhs operand is POW expression and optimize for that case. */ if (e->operands.ops.lhs->op == POW) { mpz_t powlhs, powrhs; mpz_init (powlhs); mpz_init (powrhs); mpz_init (rhs); mpz_eval_expr (powlhs, e->operands.ops.lhs->operands.ops.lhs); mpz_eval_expr (powrhs, e->operands.ops.lhs->operands.ops.rhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_powm (r, powlhs, powrhs, rhs); if (mpz_cmp_si (rhs, 0L) < 0) mpz_neg (r, r); mpz_clear (powlhs); mpz_clear (powrhs); mpz_clear (rhs); return; } mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_fdiv_r (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; #if __GNU_MP_VERSION >= 2 case INVMOD: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_invert (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; #endif case POW: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); if (mpz_cmp_si (rhs, 0L) == 0) /* x^0 is 1 */ mpz_set_ui (r, 1L); else if (mpz_cmp_si (lhs, 0L) == 0) /* 0^y (where y != 0) is 0 */ mpz_set_ui (r, 0L); else if (mpz_cmp_ui (lhs, 1L) == 0) /* 1^y is 1 */ mpz_set_ui (r, 1L); else if (mpz_cmp_si (lhs, -1L) == 0) /* (-1)^y just depends on whether y is even or odd */ mpz_set_si (r, (mpz_get_ui (rhs) & 1) ? -1L : 1L); else if (mpz_cmp_si (rhs, 0L) < 0) /* x^(-n) is 0 */ mpz_set_ui (r, 0L); else { unsigned long int cnt; unsigned long int y; /* error if exponent does not fit into an unsigned long int. */ if (mpz_cmp_ui (rhs, ~(unsigned long int) 0) > 0) goto pow_err; y = mpz_get_ui (rhs); /* x^y == (x/(2^c))^y * 2^(c*y) */ #if __GNU_MP_VERSION >= 2 cnt = mpz_scan1 (lhs, 0); #else cnt = 0; #endif if (cnt != 0) { if (y * cnt / cnt != y) goto pow_err; mpz_tdiv_q_2exp (lhs, lhs, cnt); mpz_pow_ui (r, lhs, y); mpz_mul_2exp (r, r, y * cnt); } else mpz_pow_ui (r, lhs, y); } mpz_clear (lhs); mpz_clear (rhs); return; pow_err: error = "result of `pow' operator too large"; mpz_clear (lhs); mpz_clear (rhs); longjmp (errjmpbuf, 1); case GCD: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_gcd (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; #if __GNU_MP_VERSION > 2 || __GNU_MP_VERSION_MINOR >= 1 case LCM: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_lcm (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; #endif case AND: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_and (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; case IOR: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_ior (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; #if __GNU_MP_VERSION > 2 || __GNU_MP_VERSION_MINOR >= 1 case XOR: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_xor (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; #endif case NEG: mpz_eval_expr (r, e->operands.ops.lhs); mpz_neg (r, r); return; case NOT: mpz_eval_expr (r, e->operands.ops.lhs); mpz_com (r, r); return; case SQRT: mpz_init (lhs); mpz_eval_expr (lhs, e->operands.ops.lhs); if (mpz_sgn (lhs) < 0) { error = "cannot take square root of negative numbers"; mpz_clear (lhs); longjmp (errjmpbuf, 1); } mpz_sqrt (r, lhs); return; #if __GNU_MP_VERSION > 2 || __GNU_MP_VERSION_MINOR >= 1 case ROOT: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); if (mpz_sgn (rhs) <= 0) { error = "cannot take non-positive root orders"; mpz_clear (lhs); mpz_clear (rhs); longjmp (errjmpbuf, 1); } if (mpz_sgn (lhs) < 0 && (mpz_get_ui (rhs) & 1) == 0) { error = "cannot take even root orders of negative numbers"; mpz_clear (lhs); mpz_clear (rhs); longjmp (errjmpbuf, 1); } { unsigned long int nth = mpz_get_ui (rhs); if (mpz_cmp_ui (rhs, ~(unsigned long int) 0) > 0) { /* If we are asked to take an awfully large root order, cheat and ask for the largest order we can pass to mpz_root. This saves some error prone special cases. */ nth = ~(unsigned long int) 0; } mpz_root (r, lhs, nth); } mpz_clear (lhs); mpz_clear (rhs); return; #endif case FAC: mpz_eval_expr (r, e->operands.ops.lhs); if (mpz_size (r) > 1) { error = "result of `!' operator too large"; longjmp (errjmpbuf, 1); } mpz_fac_ui (r, mpz_get_ui (r)); return; #if __GNU_MP_VERSION >= 2 case POPCNT: mpz_eval_expr (r, e->operands.ops.lhs); { unsigned long int cnt; cnt = mpz_popcount (r); mpz_set_ui (r, cnt); } return; #endif case LOG2: mpz_eval_expr (r, e->operands.ops.lhs); { unsigned long int cnt; if (mpz_sgn (r) <= 0) { error = "logarithm of non-positive number"; longjmp (errjmpbuf, 1); } cnt = mpz_sizeinbase (r, 2); mpz_set_ui (r, cnt - 1); } return; case LOG: { unsigned long int cnt; mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); if (mpz_sgn (lhs) <= 0) { error = "logarithm of non-positive number"; mpz_clear (lhs); mpz_clear (rhs); longjmp (errjmpbuf, 1); } if (mpz_cmp_ui (rhs, 256) >= 0) { error = "logarithm base too large"; mpz_clear (lhs); mpz_clear (rhs); longjmp (errjmpbuf, 1); } cnt = mpz_sizeinbase (lhs, mpz_get_ui (rhs)); mpz_set_ui (r, cnt - 1); mpz_clear (lhs); mpz_clear (rhs); } return; case FERMAT: { unsigned long int t; mpz_init (lhs); mpz_eval_expr (lhs, e->operands.ops.lhs); t = (unsigned long int) 1 << mpz_get_ui (lhs); if (mpz_cmp_ui (lhs, ~(unsigned long int) 0) > 0 || t == 0) { error = "too large Mersenne number index"; mpz_clear (lhs); longjmp (errjmpbuf, 1); } mpz_set_ui (r, 1); mpz_mul_2exp (r, r, t); mpz_add_ui (r, r, 1); mpz_clear (lhs); } return; case MERSENNE: mpz_init (lhs); mpz_eval_expr (lhs, e->operands.ops.lhs); if (mpz_cmp_ui (lhs, ~(unsigned long int) 0) > 0) { error = "too large Mersenne number index"; mpz_clear (lhs); longjmp (errjmpbuf, 1); } mpz_set_ui (r, 1); mpz_mul_2exp (r, r, mpz_get_ui (lhs)); mpz_sub_ui (r, r, 1); mpz_clear (lhs); return; case FIBONACCI: { mpz_t t; unsigned long int n, i; mpz_init (lhs); mpz_eval_expr (lhs, e->operands.ops.lhs); if (mpz_sgn (lhs) <= 0 || mpz_cmp_si (lhs, 1000000000) > 0) { error = "Fibonacci index out of range"; mpz_clear (lhs); longjmp (errjmpbuf, 1); } n = mpz_get_ui (lhs); mpz_clear (lhs); #if __GNU_MP_VERSION > 2 || __GNU_MP_VERSION_MINOR >= 1 mpz_fib_ui (r, n); #else mpz_init_set_ui (t, 1); mpz_set_ui (r, 1); if (n <= 2) mpz_set_ui (r, 1); else { for (i = 3; i <= n; i++) { mpz_add (t, t, r); mpz_swap (t, r); } } mpz_clear (t); #endif } return; default: abort (); } }
static PyObject * GMPY_mpz_is_strong_prp(PyObject *self, PyObject *args) { MPZ_Object *a, *n; PyObject *result = 0; mpz_t s, nm1, mpz_test; mp_bitcnt_t r = 0; if (PyTuple_Size(args) != 2) { TYPE_ERROR("is_strong_prp() requires 2 integer arguments"); return NULL; } n = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL); a = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL); if (!a || !n) { TYPE_ERROR("is_strong_prp() requires 2 integer arguments"); goto cleanup; } mpz_init(s); mpz_init(nm1); mpz_init(mpz_test); /* Require a >= 2. */ if (mpz_cmp_ui(a->z, 2) < 0) { VALUE_ERROR("is_strong_prp() requires 'a' greater than or equal to 2"); goto cleanup; } /* Require n > 0. */ if (mpz_sgn(n->z) <= 0) { VALUE_ERROR("is_strong_prp() requires 'n' be greater than 0"); goto cleanup; } /* Check for n == 1 */ if (mpz_cmp_ui(n->z, 1) == 0) { result = Py_False; goto cleanup; } /* Handle n even. */ if (mpz_divisible_ui_p(n->z, 2)) { if (mpz_cmp_ui(n->z, 2) == 0) result = Py_True; else result = Py_False; goto cleanup; } /* Check gcd(a,b) */ mpz_gcd(s, n->z, a->z); if (mpz_cmp_ui(s, 1) > 0) { VALUE_ERROR("is_strong_prp() requires gcd(n,a) == 1"); goto cleanup; } mpz_set(nm1, n->z); mpz_sub_ui(nm1, nm1, 1); /* Find s and r satisfying: n-1=(2^r)*s, s odd */ r = mpz_scan1(nm1, 0); mpz_fdiv_q_2exp(s, nm1, r); /* Check a^((2^t)*s) mod n for 0 <= t < r */ mpz_powm(mpz_test, a->z, s, n->z); if ((mpz_cmp_ui(mpz_test, 1) == 0) || (mpz_cmp(mpz_test, nm1) == 0)) { result = Py_True; goto cleanup; } while (--r) { /* mpz_test = mpz_test^2%n */ mpz_mul(mpz_test, mpz_test, mpz_test); mpz_mod(mpz_test, mpz_test, n->z); if (mpz_cmp(mpz_test, nm1) == 0) { result = Py_True; goto cleanup; } } result = Py_False; cleanup: Py_XINCREF(result); mpz_clear(s); mpz_clear(nm1); mpz_clear(mpz_test); Py_XDECREF((PyObject*)a); Py_XDECREF((PyObject*)n); return result; }
void generate_mod (int limb_bits, int nail_bits) { int numb_bits = limb_bits - nail_bits; int i, divisor; mpz_init_set_ui (pp, 0L); mpz_init_set_ui (pp_norm, 0L); mpz_init_set_ui (pp_inverted, 0L); /* no more than limb_bits many factors in a one limb modulus (and of course in reality nothing like that many) */ factor_alloc = limb_bits; factor = xmalloc (factor_alloc * sizeof (*factor)); rawfactor = xmalloc (factor_alloc * sizeof (*rawfactor)); if (numb_bits % 4 != 0) { strcpy (mod34_excuse, "GMP_NUMB_BITS % 4 != 0"); goto use_pp; } max_divisor = 2*limb_bits; max_divisor_bits = log2_ceil (max_divisor); if (numb_bits / 4 < max_divisor_bits) { /* Wind back to one limb worth of max_divisor, if that will let us use mpn_mod_34lsub1. */ max_divisor = limb_bits; max_divisor_bits = log2_ceil (max_divisor); if (numb_bits / 4 < max_divisor_bits) { strcpy (mod34_excuse, "GMP_NUMB_BITS / 4 too small"); goto use_pp; } } { /* Can use mpn_mod_34lsub1, find small factors of 2^mod34_bits-1. */ mpz_t m, q, r; int multiplicity; mod34_bits = (numb_bits / 4) * 3; /* mpn_mod_34lsub1 returns a full limb value, PERFSQR_MOD_34 folds it at the mod34_bits mark, adding the two halves for a remainder of at most mod34_bits+1 many bits */ mod_bits = mod34_bits + 1; mpz_init_set_ui (m, 1L); mpz_mul_2exp (m, m, mod34_bits); mpz_sub_ui (m, m, 1L); mpz_init (q); mpz_init (r); for (i = 3; i <= max_divisor; i++) { if (! isprime (i)) continue; mpz_tdiv_qr_ui (q, r, m, (unsigned long) i); if (mpz_sgn (r) != 0) continue; /* if a repeated prime is found it's used as an i^n in one factor */ divisor = 1; multiplicity = 0; do { if (divisor > max_divisor / i) break; multiplicity++; mpz_set (m, q); mpz_tdiv_qr_ui (q, r, m, (unsigned long) i); } while (mpz_sgn (r) == 0); assert (nrawfactor < factor_alloc); rawfactor[nrawfactor].divisor = i; rawfactor[nrawfactor].multiplicity = multiplicity; nrawfactor++; } mpz_clear (m); mpz_clear (q); mpz_clear (r); } if (nrawfactor <= 2) { mpz_t new_pp; sprintf (mod34_excuse, "only %d small factor%s", nrawfactor, nrawfactor == 1 ? "" : "s"); use_pp: /* reset to two limbs of max_divisor, in case the mpn_mod_34lsub1 code tried with just one */ max_divisor = 2*limb_bits; max_divisor_bits = log2_ceil (max_divisor); mpz_init (new_pp); nrawfactor = 0; mod_bits = MIN (numb_bits, limb_bits - max_divisor_bits); /* one copy of each small prime */ mpz_set_ui (pp, 1L); for (i = 3; i <= max_divisor; i++) { if (! isprime (i)) continue; mpz_mul_ui (new_pp, pp, (unsigned long) i); if (mpz_sizeinbase (new_pp, 2) > mod_bits) break; mpz_set (pp, new_pp); assert (nrawfactor < factor_alloc); rawfactor[nrawfactor].divisor = i; rawfactor[nrawfactor].multiplicity = 1; nrawfactor++; } /* Plus an extra copy of one or more of the primes selected, if that still fits in max_divisor and the total in mod_bits. Usually only 3 or 5 will be candidates */ for (i = nrawfactor-1; i >= 0; i--) { if (rawfactor[i].divisor > max_divisor / rawfactor[i].divisor) continue; mpz_mul_ui (new_pp, pp, (unsigned long) rawfactor[i].divisor); if (mpz_sizeinbase (new_pp, 2) > mod_bits) continue; mpz_set (pp, new_pp); rawfactor[i].multiplicity++; } mod_bits = mpz_sizeinbase (pp, 2); mpz_set (pp_norm, pp); while (mpz_sizeinbase (pp_norm, 2) < numb_bits) mpz_add (pp_norm, pp_norm, pp_norm); mpz_preinv_invert (pp_inverted, pp_norm, numb_bits); mpz_clear (new_pp); } /* start the factor array */ for (i = 0; i < nrawfactor; i++) { int j; assert (nfactor < factor_alloc); factor[nfactor].divisor = 1; for (j = 0; j < rawfactor[i].multiplicity; j++) factor[nfactor].divisor *= rawfactor[i].divisor; nfactor++; } combine: /* Combine entries in the factor array. Combine the smallest entry with the biggest one that will fit with it (ie. under max_divisor), then repeat that with the new smallest entry. */ qsort (factor, nfactor, sizeof (factor[0]), f_cmp_divisor); for (i = nfactor-1; i >= 1; i--) { if (factor[i].divisor <= max_divisor / factor[0].divisor) { factor[0].divisor *= factor[i].divisor; COLLAPSE_ELEMENT (factor, i, nfactor); goto combine; } } total_fraction = 1.0; for (i = 0; i < nfactor; i++) { mpz_init (factor[i].inverse); mpz_invert_ui_2exp (factor[i].inverse, (unsigned long) factor[i].divisor, (unsigned long) mod_bits); mpz_init (factor[i].mask); square_mask (factor[i].mask, factor[i].divisor); /* fraction of possible squares */ factor[i].fraction = (double) mpz_popcount (factor[i].mask) / factor[i].divisor; /* total fraction of possible squares */ total_fraction *= factor[i].fraction; } /* best tests first (ie. smallest fraction) */ qsort (factor, nfactor, sizeof (factor[0]), f_cmp_fraction); }
static PyObject * GMPY_mpz_is_fermat_prp(PyObject *self, PyObject *args) { MPZ_Object *a, *n; PyObject *result = 0; mpz_t res, nm1; if (PyTuple_Size(args) != 2) { TYPE_ERROR("is_fermat_prp() requires 2 integer arguments"); return NULL; } n = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL); a = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL); if (!a || !n) { TYPE_ERROR("is_fermat_prp() requires 2 integer arguments"); goto cleanup; } mpz_init(res); mpz_init(nm1); /* Require a >= 2. */ if (mpz_cmp_ui(a->z, 2) < 0) { VALUE_ERROR("is_fermat_prp() requires 'a' greater than or equal to 2"); goto cleanup; } /* Require n > 0. */ if (mpz_sgn(n->z) <= 0) { VALUE_ERROR("is_fermat_prp() requires 'n' be greater than 0"); goto cleanup; } /* Check for n == 1 */ if (mpz_cmp_ui(n->z, 1) == 0) { result = Py_False; goto cleanup; } /* Handle n even. */ /* Should n even raise an exception? */ if (mpz_divisible_ui_p(n->z, 2)) { if (mpz_cmp_ui(n->z, 2) == 0) result = Py_True; else result = Py_False; goto cleanup; } /* Check gcd(a,n) */ mpz_gcd(res, n->z, a->z); if (mpz_cmp_ui(res, 1) > 0) { VALUE_ERROR("is_fermat_prp() requires gcd(n,a) == 1"); goto cleanup; } mpz_set(nm1, n->z); mpz_sub_ui(nm1, nm1, 1); mpz_powm(res, a->z, nm1, n->z); if (mpz_cmp_ui(res, 1) == 0) result = Py_True; else result = Py_False; cleanup: Py_XINCREF(result); mpz_clear(res); mpz_clear(nm1); Py_XDECREF((PyObject*)a); Py_XDECREF((PyObject*)n); return result; }
void print (int limb_bits, int nail_bits) { int i; mpz_t mhi, mlo; printf ("/* This file generated by gen-psqr.c - DO NOT EDIT. */\n"); printf ("\n"); printf ("#if GMP_LIMB_BITS != %d || GMP_NAIL_BITS != %d\n", limb_bits, nail_bits); printf ("Error, error, this data is for %d bit limb and %d bit nail\n", limb_bits, nail_bits); printf ("#endif\n"); printf ("\n"); printf ("/* Non-zero bit indicates a quadratic residue mod 0x100.\n"); printf (" This test identifies %.2f%% as non-squares (%d/256). */\n", (1.0 - sq_res_0x100_fraction) * 100.0, 0x100 - sq_res_0x100_num); printf ("static const mp_limb_t\n"); printf ("sq_res_0x100[%d] = {\n", nsq_res_0x100); for (i = 0; i < nsq_res_0x100; i++) { printf (" CNST_LIMB(0x"); mpz_out_str (stdout, 16, sq_res_0x100[i]); printf ("),\n"); } printf ("};\n"); printf ("\n"); if (mpz_sgn (pp) != 0) { printf ("/* mpn_mod_34lsub1 not used due to %s */\n", mod34_excuse); printf ("/* PERFSQR_PP = "); } else printf ("/* 2^%d-1 = ", mod34_bits); for (i = 0; i < nrawfactor; i++) { if (i != 0) printf (" * "); printf ("%d", rawfactor[i].divisor); if (rawfactor[i].multiplicity != 1) printf ("^%d", rawfactor[i].multiplicity); } printf (" %s*/\n", mpz_sgn (pp) == 0 ? "... " : ""); printf ("#define PERFSQR_MOD_BITS %d\n", mod_bits); if (mpz_sgn (pp) != 0) { printf ("#define PERFSQR_PP CNST_LIMB(0x"); mpz_out_str (stdout, 16, pp); printf (")\n"); printf ("#define PERFSQR_PP_NORM CNST_LIMB(0x"); mpz_out_str (stdout, 16, pp_norm); printf (")\n"); printf ("#define PERFSQR_PP_INVERTED CNST_LIMB(0x"); mpz_out_str (stdout, 16, pp_inverted); printf (")\n"); } printf ("\n"); mpz_init (mhi); mpz_init (mlo); printf ("/* This test identifies %.2f%% as non-squares. */\n", (1.0 - total_fraction) * 100.0); printf ("#define PERFSQR_MOD_TEST(up, usize) \\\n"); printf (" do { \\\n"); printf (" mp_limb_t r; \\\n"); if (mpz_sgn (pp) != 0) printf (" PERFSQR_MOD_PP (r, up, usize); \\\n"); else printf (" PERFSQR_MOD_34 (r, up, usize); \\\n"); for (i = 0; i < nfactor; i++) { printf (" \\\n"); printf (" /* %5.2f%% */ \\\n", (1.0 - factor[i].fraction) * 100.0); printf (" PERFSQR_MOD_%d (r, CNST_LIMB(%2d), CNST_LIMB(0x", factor[i].divisor <= limb_bits ? 1 : 2, factor[i].divisor); mpz_out_str (stdout, 16, factor[i].inverse); printf ("), \\\n"); printf (" CNST_LIMB(0x"); if ( factor[i].divisor <= limb_bits) { mpz_out_str (stdout, 16, factor[i].mask); } else { mpz_tdiv_r_2exp (mlo, factor[i].mask, (unsigned long) limb_bits); mpz_tdiv_q_2exp (mhi, factor[i].mask, (unsigned long) limb_bits); mpz_out_str (stdout, 16, mhi); printf ("), CNST_LIMB(0x"); mpz_out_str (stdout, 16, mlo); } printf (")); \\\n"); } printf (" } while (0)\n"); printf ("\n"); printf ("/* Grand total sq_res_0x100 and PERFSQR_MOD_TEST, %.2f%% non-squares. */\n", (1.0 - (total_fraction * 44.0/256.0)) * 100.0); printf ("\n"); printf ("/* helper for tests/mpz/t-perfsqr.c */\n"); printf ("#define PERFSQR_DIVISORS { 256,"); for (i = 0; i < nfactor; i++) printf (" %d,", factor[i].divisor); printf (" }\n"); mpz_clear (mhi); mpz_clear (mlo); }
static PyObject * GMPY_mpz_is_extrastronglucas_prp(PyObject *self, PyObject *args) { MPZ_Object *n, *p; PyObject *result = 0; mpz_t zD, s, nmj, nm2, res; /* these are needed for the LucasU and LucasV part of this function */ mpz_t uh, vl, vh, ql, qh, tmp; mp_bitcnt_t r = 0, j = 0; int ret = 0; if (PyTuple_Size(args) != 2) { TYPE_ERROR("is_extra_strong_lucas_prp() requires 2 integer arguments"); return NULL; } mpz_init(zD); mpz_init(s); mpz_init(nmj); mpz_init(nm2); mpz_init(res); mpz_init(uh); mpz_init(vl); mpz_init(vh); mpz_init(ql); mpz_init(qh); mpz_init(tmp); n = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL); p = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL); if (!n || !p) { TYPE_ERROR("is_extra_strong_lucas_prp() requires 2 integer arguments"); goto cleanup; } /* Check if p*p - 4 == 0. */ mpz_mul(zD, p->z, p->z); mpz_sub_ui(zD, zD, 4); if (mpz_sgn(zD) == 0) { VALUE_ERROR("invalid value for p in is_extra_strong_lucas_prp()"); goto cleanup; } /* Require n > 0. */ if (mpz_sgn(n->z) <= 0) { VALUE_ERROR("is_extra_strong_lucas_prp() requires 'n' be greater than 0"); goto cleanup; } /* Check for n == 1 */ if (mpz_cmp_ui(n->z, 1) == 0) { result = Py_False; goto cleanup; } /* Handle n even. */ if (mpz_divisible_ui_p(n->z, 2)) { if (mpz_cmp_ui(n->z, 2) == 0) result = Py_True; else result = Py_False; goto cleanup; } /* Check GCD */ mpz_mul_ui(res, zD, 2); mpz_gcd(res, res, n->z); if ((mpz_cmp(res, n->z) != 0) && (mpz_cmp_ui(res, 1) > 0)) { VALUE_ERROR("is_extra_strong_lucas_prp() requires gcd(n,2*D) == 1"); goto cleanup; } /* nmj = n - (D/n), where (D/n) is the Jacobi symbol */ mpz_set(nmj, n->z); ret = mpz_jacobi(zD, n->z); if (ret == -1) mpz_add_ui(nmj, nmj, 1); else if (ret == 1) mpz_sub_ui(nmj, nmj, 1); r = mpz_scan1(nmj, 0); mpz_fdiv_q_2exp(s, nmj, r); mpz_set(nm2, n->z); mpz_sub_ui(nm2, nm2, 2); /* make sure that either U_s == 0 mod n or V_s == +/-2 mod n, or */ /* V_((2^t)*s) == 0 mod n for some t with 0 <= t < r-1 */ mpz_set_si(uh, 1); mpz_set_si(vl, 2); mpz_set(vh, p->z); mpz_set_si(ql, 1); mpz_set_si(qh, 1); mpz_set_si(tmp,0); for (j = mpz_sizeinbase(s,2)-1; j >= 1; j--) { /* ql = ql*qh (mod n) */ mpz_mul(ql, ql, qh); mpz_mod(ql, ql, n->z); if (mpz_tstbit(s,j) == 1) { /* qh = ql*q */ mpz_set(qh, ql); /* uh = uh*vh (mod n) */ mpz_mul(uh, uh, vh); mpz_mod(uh, uh, n->z); /* vl = vh*vl - p*ql (mod n) */ mpz_mul(vl, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n->z); /* vh = vh*vh - 2*qh (mod n) */ mpz_mul(vh, vh, vh); mpz_mul_si(tmp, qh, 2); mpz_sub(vh, vh, tmp); mpz_mod(vh, vh, n->z); } else { /* qh = ql */ mpz_set(qh, ql); /* uh = uh*vl - ql (mod n) */ mpz_mul(uh, uh, vl); mpz_sub(uh, uh, ql); mpz_mod(uh, uh, n->z); /* vh = vh*vl - p*ql (mod n) */ mpz_mul(vh, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vh, vh, tmp); mpz_mod(vh, vh, n->z); /* vl = vl*vl - 2*ql (mod n) */ mpz_mul(vl, vl, vl); mpz_mul_si(tmp, ql, 2); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n->z); } } /* ql = ql*qh */ mpz_mul(ql, ql, qh); /* qh = ql*q */ mpz_set(qh, ql); /* uh = uh*vl - ql */ mpz_mul(uh, uh, vl); mpz_sub(uh, uh, ql); /* vl = vh*vl - p*ql */ mpz_mul(vl, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vl, vl, tmp); /* ql = ql*qh */ mpz_mul(ql, ql, qh); mpz_mod(uh, uh, n->z); mpz_mod(vl, vl, n->z); /* uh contains LucasU_s and vl contains LucasV_s */ if ((mpz_cmp_ui(uh, 0) == 0) || (mpz_cmp_ui(vl, 0) == 0) || (mpz_cmp(vl, nm2) == 0) || (mpz_cmp_si(vl, 2) == 0)) { result = Py_True; goto cleanup; } for (j = 1; j < r-1; j++) { /* vl = vl*vl - 2*ql (mod n) */ mpz_mul(vl, vl, vl); mpz_mul_si(tmp, ql, 2); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n->z); /* ql = ql*ql (mod n) */ mpz_mul(ql, ql, ql); mpz_mod(ql, ql, n->z); if (mpz_cmp_ui(vl, 0) == 0) { result = Py_True; goto cleanup; } } result = Py_False; cleanup: Py_XINCREF(result); mpz_clear(zD); mpz_clear(s); mpz_clear(nmj); mpz_clear(nm2); mpz_clear(res); mpz_clear(uh); mpz_clear(vl); mpz_clear(vh); mpz_clear(ql); mpz_clear(qh); mpz_clear(tmp); Py_XDECREF((PyObject*)p); Py_XDECREF((PyObject*)n); return result; }
bool RingZZ::is_zero(const ring_elem f) const { mpz_ptr a = f.get_mpz(); return mpz_sgn(a) == 0; }