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; }
unsigned char *serialiseVerifierQueries(struct verifierCommitment_ECC **commitment_boxes, int arrayLen, int *outputLen) { unsigned char *commBuffer; int i, totalLength = sizeof(int), bufferOffset = sizeof(int); for(i = 0; i < arrayLen; i ++) { totalLength += sizeof(mp_limb_t) * ( mpz_size(commitment_boxes[i] -> c) + mpz_size(commitment_boxes[i] -> t) ); } commBuffer = (unsigned char *) calloc(totalLength, sizeof(unsigned char)); memcpy(commBuffer, &arrayLen, sizeof(int)); for(i = 0; i < arrayLen; i ++) { serialiseMPZ(commitment_boxes[i] -> c, commBuffer, &bufferOffset); serialiseMPZ(commitment_boxes[i] -> t, commBuffer, &bufferOffset); } *outputLen = bufferOffset; return commBuffer; }
unsigned char *serialise_CRS(struct params_CnC *params, int *bufferOffset) { unsigned char *output; int i, totalLength = 0, tempInt; *bufferOffset = sizeof(int); totalLength = ( sizeof(mp_limb_t) * mpz_size(params -> crs -> g_1) ); for(i = 0 ; i < params -> crs -> stat_SecParam; i ++) { totalLength += ( sizeof(mp_limb_t) * mpz_size(params -> crs -> h_0_List[i]) ); totalLength += ( sizeof(mp_limb_t) * mpz_size(params -> crs -> h_1_List[i]) ); } tempInt = (2 * params -> crs -> stat_SecParam) + 2; tempInt *= sizeof(int); output = (unsigned char *) calloc(tempInt + totalLength, sizeof(unsigned char)); memcpy(output, &(params -> crs -> stat_SecParam), sizeof(int)); serialiseMPZ(params -> crs -> g_1, output, bufferOffset); for(i = 0; i < params -> crs -> stat_SecParam; i ++) { serialiseMPZ(params -> crs -> h_0_List[i], output, bufferOffset); } for(i = 0; i < params -> crs -> stat_SecParam; i ++) { serialiseMPZ(params -> crs -> h_1_List[i], output, bufferOffset); } return output; }
void dump_abort (mpz_t dividend, mpz_t divisor) { fprintf (stderr, "ERROR\n"); printf("nn = %ld, dn = %ld\n", mpz_size(dividend), mpz_size(divisor)); fprintf (stderr, "dividend = "); debug_mp (dividend, -16); fprintf (stderr, "divisor = "); debug_mp (divisor, -16); abort(); }
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); }
static int hgcd_ref (struct hgcd_ref *hgcd, mpz_t a, mpz_t b) { mp_size_t n = MAX (mpz_size (a), mpz_size (b)); mp_size_t s = n/2 + 1; mpz_t q; int res; if (mpz_size (a) <= s || mpz_size (b) <= s) return 0; res = mpz_cmp (a, b); if (res < 0) { mpz_sub (b, b, a); if (mpz_size (b) <= s) return 0; mpz_set_ui (hgcd->m[0][0], 1); mpz_set_ui (hgcd->m[0][1], 0); mpz_set_ui (hgcd->m[1][0], 1); mpz_set_ui (hgcd->m[1][1], 1); } else if (res > 0) { mpz_sub (a, a, b); if (mpz_size (a) <= s) return 0; mpz_set_ui (hgcd->m[0][0], 1); mpz_set_ui (hgcd->m[0][1], 1); mpz_set_ui (hgcd->m[1][0], 0); mpz_set_ui (hgcd->m[1][1], 1); } else return 0; mpz_init (q); for (;;) { ASSERT (mpz_size (a) > s); ASSERT (mpz_size (b) > s); if (mpz_cmp (a, b) > 0) { if (!sdiv_qr (q, a, s, a, b)) break; mpz_addmul (hgcd->m[0][1], q, hgcd->m[0][0]); mpz_addmul (hgcd->m[1][1], q, hgcd->m[1][0]); } else { if (!sdiv_qr (q, b, s, b, a)) break; mpz_addmul (hgcd->m[0][0], q, hgcd->m[0][1]); mpz_addmul (hgcd->m[1][0], q, hgcd->m[1][1]); } } mpz_clear (q); return 1; }
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); }
// Verifier serialises it's C and T. (Having already sent the C_Commit to the prover). unsigned char *verifierQuery_ECC(struct verifierCommitment_ECC *commitment_box, int *outputLen) { unsigned char *commBuffer; int totalLength = 2 * sizeof(int), bufferOffset = 0; totalLength += sizeof(mp_limb_t) * (mpz_size(commitment_box -> c) + mpz_size(commitment_box -> t)); commBuffer = (unsigned char *) calloc(totalLength, sizeof(unsigned char)); serialiseMPZ(commitment_box -> c, commBuffer, &bufferOffset); serialiseMPZ(commitment_box -> t, commBuffer, &bufferOffset); *outputLen = bufferOffset; return commBuffer; }
static void mpz_to_mpn (mp_ptr ap, mp_size_t an, const mpz_t b) { mp_size_t bn = mpz_size (b); ASSERT_ALWAYS (bn <= an); MPN_COPY_INCR (ap, mpz_limbs_read (b), bn); MPN_ZERO (ap + bn, an - bn); }
static Py_hash_t Pympq_hash(PympqObject *self) { #ifdef _PyHASH_MODULUS Py_hash_t hash = 0; mpz_t temp, temp1, mask; if (self->hash_cache != -1) return self->hash_cache; mpz_inoc(temp); mpz_inoc(temp1); mpz_inoc(mask); mpz_set_si(mask, 1); mpz_mul_2exp(mask, mask, _PyHASH_BITS); mpz_sub_ui(mask, mask, 1); if (!mpz_invert(temp, mpq_denref(self->q), mask)) { mpz_cloc(temp); mpz_cloc(temp1); mpz_cloc(mask); hash = _PyHASH_INF; if (mpz_sgn(mpq_numref(self->q))<0) hash = -hash; self->hash_cache = hash; return hash; } mpz_set(temp1, mask); mpz_sub_ui(temp1, temp1, 2); mpz_powm(temp, mpq_denref(self->q), temp1, mask); mpz_tdiv_r(temp1, mpq_numref(self->q), mask); mpz_mul(temp, temp, temp1); hash = (Py_hash_t)mpn_mod_1(temp->_mp_d, mpz_size(temp), _PyHASH_MODULUS); if (mpz_sgn(mpq_numref(self->q))<0) hash = -hash; if (hash==-1) hash = -2; mpz_cloc(temp); mpz_cloc(temp1); mpz_cloc(mask); self->hash_cache = hash; return hash; #else PyObject *temp; if (self->hash_cache != -1) return self->hash_cache; if (!(temp = Pympq_To_PyFloat(self))) { SYSTEM_ERROR("Could not convert 'mpq' to float."); return -1; } self->hash_cache = PyObject_Hash(temp); Py_DECREF(temp); return self->hash_cache; #endif }
unsigned long int ZZ::Hash() const { mp_limb_t * limb = data[0]._mp_d; size_t size = mpz_size(data); mp_limb_t hash = size; for (int i = 0; i < size; ++i, ++limb) hash ^= *limb; return hash; }
int mpz_eq_mpn (mp_ptr ap, mp_size_t an, const mpz_t b) { mp_size_t bn = mpz_size (b); return (bn >= 0 && bn <= an && mpn_cmp (ap, mpz_limbs_read (b), bn) == 0 && (an == bn || mpn_zero_p (ap + bn, an - bn))); }
static PyObject * GMPy_MPZ_bit_length_method(PyObject *self, PyObject *other) { mp_bitcnt_t n = 0; if (mpz_size(MPZ(self))) n = mpz_sizeinbase(MPZ(self), 2); return PyIntOrLong_FromMpBitCnt(n); }
void mpz_limbs_copy (mp_limb_t *xp, mpz_srcptr x, mp_size_t n) { mp_size_t xn = mpz_size (x); assert (xn <= n); mpn_copyi (xp, mpz_limbs_read (x), xn); if (xn < n) mpn_zero (xp + xn, n - xn); }
// Prover computes the Zs to send and serialises them for sending. unsigned char *computeAndSerialise_ECC(struct eccParams *params, int stat_SecParam, unsigned char *J_set, struct msgOneArrays_ECC *msgArray, struct witnessStruct *witnessesArray, mpz_t *cShares, struct alphaAndA_Struct *alphaAndA, int *outputLen) { unsigned char *commBuffer, *zBuffer, *cBuffer, *aBuffer; mpz_t temp1, temp2, *z_ToSend, *temp; int i, j_in_I = 0, j_not_I = 0; int bufferOffset = sizeof(int), totalLength; int zLength = 0, cLength = 0, aLength = 0; mpz_init(temp1); mpz_init(temp2); totalLength = (2 * stat_SecParam + 3) * sizeof(int); z_ToSend = (mpz_t*) calloc(stat_SecParam, sizeof(mpz_t)); for(i = 0; i < stat_SecParam; i ++) { mpz_init(z_ToSend[i]); // i IS in I = J^{bar} if(0x00 == J_set[i]) { mpz_set(z_ToSend[i], msgArray -> notI_Struct -> Z_array[j_not_I]); j_not_I ++; } else { // z_i = c_i * w_i + ρ_i mpz_mul(temp1, cShares[i], witnessesArray -> witnesses[i]); mpz_add(temp2, temp1, msgArray -> roeArray[j_in_I]); mpz_mod(z_ToSend[i], temp2, params -> n); j_in_I ++; } } zBuffer = serialiseMPZ_Array(z_ToSend, stat_SecParam, &zLength); cBuffer = serialiseMPZ_Array(cShares, stat_SecParam, &cLength); aBuffer = (unsigned char*) calloc(sizeof(int) + (mpz_size(alphaAndA -> a) * sizeof(mp_limb_t)), sizeof(unsigned char)); serialiseMPZ(alphaAndA -> a, aBuffer, &aLength); commBuffer = (unsigned char *) calloc(zLength + cLength + aLength, sizeof(unsigned char)); memcpy(commBuffer, zBuffer, zLength); memcpy(commBuffer + zLength, cBuffer, cLength); memcpy(commBuffer + zLength + cLength, aBuffer, aLength); *outputLen = zLength + cLength + aLength; return commBuffer; }
void prove_SingleDH_Tuple(int writeSocket, int readSocket, mpz_t witness, struct eccPoint *g_0, struct eccPoint *g_1, struct eccPoint *u, struct eccPoint *v, struct eccParams *params, gmp_randstate_t *state) { unsigned char *commBuffer; struct eccPoint *a, *b; int i, commBufferLen = 0, bufferOffset = 0, length; mpz_t r, *e, unmodded, eW, finalReply; mpz_init(r); mpz_init(unmodded); mpz_init(eW); mpz_init(finalReply); mpz_urandomm(r, *state, params -> n); a = windowedScalarPoint(r, g_0, params); b = windowedScalarPoint(r, g_1, params); commBufferLen = sizeOfSerial_ECCPoint(a) + sizeOfSerial_ECCPoint(b); commBuffer = (unsigned char *) calloc(commBufferLen, sizeof(unsigned char)); serialise_ECC_Point(a, commBuffer, &bufferOffset); serialise_ECC_Point(b, commBuffer, &bufferOffset); sendBoth(writeSocket, commBuffer, bufferOffset); free(commBuffer); bufferOffset = 0; commBuffer = receiveBoth(readSocket, commBufferLen); e = deserialiseMPZ(commBuffer, &bufferOffset); free(commBuffer); mpz_mul(eW, *e, witness); mpz_add(unmodded, eW, r); mpz_add(finalReply, unmodded, params -> n); bufferOffset = 0; commBufferLen = sizeof(int) + (sizeof(mp_limb_t) * mpz_size(finalReply)); commBuffer = (unsigned char *) calloc(commBufferLen, sizeof(unsigned char)); serialiseMPZ(finalReply, commBuffer, &bufferOffset); sendBoth(writeSocket, commBuffer, bufferOffset); free(commBuffer); mpz_clear(r); mpz_clear(unmodded); mpz_clear(eW); mpz_clear(finalReply); mpz_clear(*e); free(e); }
int srp_check_signature(guint32 address, const gchar *signature_raw) { gchar *result_raw; gchar check[32]; mpz_t result; mpz_t modulus; mpz_t signature; size_t size, alloc_size; int cmp_result; /* build the "check" array */ memcpy(check, &address, 4); memset(check + 4, 0xBB, 28); /* initialize the modulus */ mpz_init2(modulus, 1024); mpz_import(modulus, 128, -1, 1, 0, 0, srp_sig_n); /* initialize the server signature */ mpz_init2(signature, 1024); mpz_import(signature, 128, -1, 1, 0, 0, signature_raw); /* initialize the result */ mpz_init2(result, 1024); /* calculate the result */ mpz_powm_ui(result, signature, SRP_SIGNATURE_KEY, modulus); /* clear (free) the intermediates */ mpz_clear(signature); mpz_clear(modulus); /* allocate space for raw signature */ alloc_size = mpz_size(result) * sizeof(mp_limb_t); result_raw = (gchar *) g_malloc(alloc_size); if (!result_raw) { mpz_clear(result); return 0; } /* get a byte array of the signature */ mpz_export(result_raw, &size, -1, 1, 0, 0, result); /* clear (free) the result */ mpz_clear(result); /* check the result */ cmp_result = (memcmp(result_raw, check, 32) == 0); /* free the result_raw buffer */ g_free(result_raw); /* return */ return cmp_result; }
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; }
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; }
static int sdiv_qr (mpz_t q, mpz_t r, mp_size_t s, const mpz_t a, const mpz_t b) { mpz_fdiv_qr (q, r, a, b); if (mpz_size (r) <= s) { mpz_add (r, r, b); mpz_sub_ui (q, q, 1); } return (mpz_sgn (q) > 0); }
mp_size_t fmpz_size(const fmpz_t f) { fmpz d = *f; if (d == 0) return 0; if (!COEFF_IS_MPZ(d)) return 1; else return mpz_size(COEFF_TO_PTR(d)); }
unsigned char *deserialiseProverTwo_ECC_1Of2(mpz_t **z_ToSend, mpz_t **cShares, struct alphaAndA_Struct **alphaAndA, int arrayLen, int *outputLen) { unsigned char *commBuffer; int i, j; int bufferOffset = sizeof(int); int totalLength = sizeof(int); for(i = 0; i < arrayLen; i ++) { totalLength += sizeof(mp_limb_t) * (mpz_size(z_ToSend[i][0]) + mpz_size(z_ToSend[i][1])); totalLength += sizeof(mp_limb_t) * (mpz_size(cShares[i][0]) + mpz_size(cShares[i][1])); totalLength += (mpz_size(alphaAndA[i] -> a) * sizeof(mp_limb_t)); totalLength += (5 * sizeof(int)); } commBuffer = (unsigned char *) calloc(totalLength, sizeof(unsigned char)); memcpy(commBuffer, &arrayLen, sizeof(int)); for(i = 0; i < arrayLen; i ++) { serialiseMPZ(z_ToSend[i][0], commBuffer, &bufferOffset); serialiseMPZ(z_ToSend[i][1], commBuffer, &bufferOffset); serialiseMPZ(cShares[i][0], commBuffer, &bufferOffset); serialiseMPZ(cShares[i][1], commBuffer, &bufferOffset); serialiseMPZ(alphaAndA[i] -> a, commBuffer, &bufferOffset); } *outputLen = bufferOffset; return commBuffer; }
int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("dot_bound_limbs...."); fflush(stdout); for (i = 0; i < 1000000; i++) { slong len; nmod_t mod; mp_limb_t m; int limbs1, limbs2; mpz_t t; len = n_randint(state, 10000) + 1; m = n_randtest_not_zero(state); nmod_init(&mod, m); limbs1 = _nmod_vec_dot_bound_limbs(len, mod); mpz_init2(t, 4*FLINT_BITS); flint_mpz_set_ui(t, m-1); mpz_mul(t, t, t); flint_mpz_mul_ui(t, t, len); limbs2 = mpz_size(t); if (limbs1 != limbs2) { flint_printf("FAIL:\n"); flint_printf("m = %wu\n", m); flint_printf("len = %wd\n", len); flint_printf("limbs1 = %d\n", limbs1); flint_printf("limbs2 = %d\n", limbs2); gmp_printf("bound: %Zd\n", t); abort(); } mpz_clear(t); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; }
int verify_SingleDH_Tuple(int writeSocket, int readSocket, struct eccPoint *g_0, struct eccPoint *g_1, struct eccPoint *u, struct eccPoint *v, struct eccParams *params, gmp_randstate_t *state) { unsigned char *commBuffer; int i, commBufferLen = 0, bufferOffset = 0, verified = 0; struct eccPoint *a, *uCheck, *b, *vCheck, *x, *y; mpz_t e, *z; bufferOffset = 0; commBuffer = receiveBoth(readSocket, commBufferLen); a = deserialise_ECC_Point(commBuffer, &bufferOffset); b = deserialise_ECC_Point(commBuffer, &bufferOffset); free(commBuffer); mpz_init(e); mpz_urandomm(e, *state, params -> n); bufferOffset = 0; commBufferLen = sizeof(int) + (sizeof(mp_limb_t) * mpz_size(e)); commBuffer = (unsigned char *) calloc(commBufferLen, sizeof(unsigned char)); serialiseMPZ(e, commBuffer, &bufferOffset); sendBoth(writeSocket, commBuffer, bufferOffset); free(commBuffer); bufferOffset = 0; commBuffer = receiveBoth(readSocket, commBufferLen); z = deserialiseMPZ(commBuffer, &bufferOffset); free(commBuffer); uCheck = windowedScalarPoint(*z, g_0, params); vCheck = windowedScalarPoint(*z, g_1, params); x = windowedScalarPoint(e, u, params); y = windowedScalarPoint(e, v, params); groupOp_PlusEqual(a, x, params); groupOp_PlusEqual(b, y, params); verified = eccPointsEqual(a, uCheck) | eccPointsEqual(b, vCheck); return verified; }
/* Get a pointer to an n limb area, for read-only operation. n must be greater or equal to the current size, and the mpz is zero-padded if needed. */ const mp_limb_t * mpz_limbs_read_n (mpz_ptr x, mp_size_t n) { mp_size_t xn = mpz_size (x); mp_ptr xp; assert (xn <= n); xp = mpz_limbs_modify (x, n); if (xn < n) mpn_zero (xp + xn, n - xn); return xp; }
void my_mpz_mul (mpz_t r, mpz_srcptr a, mpz_srcptr b) { mp_limb_t *tp; mp_size_t tn, an, bn; an = mpz_size (a); bn = mpz_size (b); assert (an > 0); assert (bn > 0); tn = an + bn; tp = mpz_limbs_write (r, tn); if (an > bn) mpn_mul (tp, mpz_limbs_read (a), an, mpz_limbs_read (b), bn); else mpn_mul (tp, mpz_limbs_read (b), bn, mpz_limbs_read (a), an); if (mpz_sgn (a) != mpz_sgn(b)) tn = - tn; mpz_limbs_finish (r, tn); }
static PyObject * GMPy_MPZ_bit_length_function(PyObject *self, PyObject *other) { mp_bitcnt_t n = 0; MPZ_Object* tempx; if (!(tempx = GMPy_MPZ_From_Integer(other, NULL))) { TYPE_ERROR("bit_length() requires 'mpz' argument"); return NULL; } if (mpz_size(MPZ(tempx))) n = mpz_sizeinbase(tempx->z, 2); Py_DECREF((PyObject*)tempx); return PyIntOrLong_FromMpBitCnt(n); }
int mpz_limbs_cmp (mpz_srcptr a, const mp_limb_t *bp, mp_size_t bn) { mp_size_t an = mpz_size (a); assert (mpz_sgn (a) >= 0); assert (bn >= 0); if (an < bn) return -1; if (an > bn) return 1; if (an == 0) return 0; return mpn_cmp (mpz_limbs_read(a), bp, an); }
// Take a J-set and serialise the secrets for all circuits indicated by this J-set. // Also serialise the seeds of the randomness used to build each circuit. unsigned char *serialise_Requested_CircuitSecrets(struct secret_builderPRS_Keys *secret_inputs, ub4 **circuitSeeds, unsigned char *J_set, int *outputLength) { unsigned char *outputBuffer; int totalLength = 0, outputOffset = 0, j = 0, k; ub4 tempUB4; unsigned int temp = 0; // Calculate the size of the buffer needed. for(j = 0; j < secret_inputs -> stat_SecParam; j ++) { if(0x01 == J_set[j]) { // Int for size of MPZ. totalLength += sizeof(int); totalLength += ( sizeof(mp_limb_t) * mpz_size(secret_inputs -> secret_circuitKeys[j]) ); // Size of seed. totalLength += 256 * sizeof(ub4); } } outputBuffer = (unsigned char *) calloc(totalLength, sizeof(unsigned char)); // For each circuit in the J-set. for(j = 0; j < secret_inputs -> stat_SecParam; j ++) { if(0x01 == J_set[j]) { // Serialise circuit secret serialiseMPZ(secret_inputs -> secret_circuitKeys[j], outputBuffer, &outputOffset); // Serialise circuti seed. for(k = 0; k < 256; k ++) { tempUB4 = circuitSeeds[j][k]; memcpy(outputBuffer + outputOffset, &tempUB4, sizeof(ub4)); outputOffset += sizeof(ub4); } } } // Set output length for sending purposes. *outputLength = outputOffset; return outputBuffer; }
/*------------------------------------------------------------------*/ static void compute_remainder_tree(uint32 first, uint32 last, relation_batch_t *rb, mpz_t numerator) { /* recursively compute numerator % (each relation in rb->relations) */ uint32 mid = (first + last) / 2; mpz_t relation_prod, remainder; /* recursion base case: numerator already fits in an mp_t, so manually compute the remainder and postprocess each relation */ if (mpz_size(numerator) * GMP_LIMB_BITS/32 <= MAX_MP_WORDS) { if (mpz_sgn(numerator) > 0) { mp_t num; gmp2mp(numerator, &num); while (first <= last) check_relation(rb, first++, &num); } return; } /* multiply together the unfactored parts of all the relations from first to last */ mpz_init(relation_prod); mpz_init(remainder); multiply_relations(first, last, rb, relation_prod); /* use the remainder to deal with the left and right halves of the relation list */ if (mpz_cmp(numerator, relation_prod) < 0) { mpz_clear(relation_prod); compute_remainder_tree(first, mid, rb, numerator); compute_remainder_tree(mid + 1, last, rb, numerator); } else { mpz_tdiv_r(remainder, numerator, relation_prod); mpz_clear(relation_prod); compute_remainder_tree(first, mid, rb, remainder); compute_remainder_tree(mid + 1, last, rb, remainder); } mpz_clear(remainder); }