int test_bernoulli_mod_p(unsigned long p) { unsigned long *res = (unsigned long*) flint_stack_alloc((p-1)/2); if(!bernoulli_mod_p_mpz(res, p)) { printf("Could not factor p = %d\n", p); flint_stack_release(); return FALSE; } int result = verify_bernoulli_mod_p(res, p); flint_stack_release(); return result; }
void fmpz_tdiv(fmpz_t res, const fmpz_t a, const fmpz_t b) { long a0 = a[0]; long b0 = b[0]; unsigned long sizea = FLINT_ABS(a0); unsigned long sizeb = FLINT_ABS(b0); while ((!a[sizea]) && (sizea)) sizea--; while ((!b[sizeb]) && (sizeb)) sizeb--; mp_limb_t mslimb; fmpz_t temp; if (sizeb == 0) { printf("Error: division by zero!\n"); abort(); } else if (sizea < sizeb) // Todo: make this deal with sizea == sizeb but a < b { res[0] = 0; } else { temp = (fmpz_t) flint_stack_alloc(sizeb); mpn_tdiv_qr(res+1, temp, 0, a+1, sizea, b+1, sizeb); res[0] = sizea - sizeb + 1; if ((long) (a0 ^ b0) < 0) res[0] = -res[0]; flint_stack_release(); } NORM(res); }
// truncated multiplication for fmpz void fmpz_mul_trunc(fmpz_t res, fmpz_t a, fmpz_t b, unsigned long trunc) { unsigned long sizea = FLINT_MIN(fmpz_size(a), trunc); unsigned long sizeb = FLINT_MIN(fmpz_size(b), trunc); while ((!a[sizea]) && (sizea)) sizea--; while ((!b[sizeb]) && (sizeb)) sizeb--; if ((sizea == 0) || (sizeb == 0)) { res[0] = 0; return; } if (trunc >= sizea + sizeb) { mp_limb_t mslimb; if (sizea >= sizeb) mslimb = F_mpn_mul(res+1, a+1, sizea, b+1, sizeb); else mslimb = F_mpn_mul(res+1, b+1, sizeb, a+1, sizea); res[0] = sizea + sizeb - (mslimb == 0); } else { mp_limb_t mslimb; fmpz_t temp = flint_stack_alloc(sizea + sizeb + 1); if (sizea >= sizeb) mslimb = F_mpn_mul_trunc(temp+1, a+1, sizea, b+1, sizeb, trunc); else mslimb = F_mpn_mul_trunc(temp+1, b+1, sizeb, a+1, sizea, trunc); temp[0] = trunc; if (UNLIKELY(!mslimb)) __fmpz_normalise(temp); // normalise if most significant limb == 0 fmpz_set(res, temp); flint_stack_release(); } if ((long) (a[0] ^ b[0]) < 0L) res[0] = -res[0]; }
void fmpz_addmul(fmpz_t res, const fmpz_t a, const fmpz_t b) { long a0 = a[0]; long b0 = b[0]; unsigned long sizea = FLINT_ABS(a0); unsigned long sizeb = FLINT_ABS(b0); while ((!a[sizea]) && (sizea)) sizea--; while ((!b[sizeb]) && (sizeb)) sizeb--; fmpz_t temp; mp_limb_t mslimb; if (sizea && sizeb) { if (sizea + sizeb < 100) { temp = (fmpz_t) flint_stack_alloc_small(sizea + sizeb + 1); if (sizea >= sizeb) mslimb = mpn_mul(temp+1, a+1, sizea, b+1, sizeb); else mslimb = mpn_mul(temp+1, b+1, sizeb, a+1, sizea); temp[0] = sizea + sizeb - (mslimb == 0); if ((long) (a[0] ^ b[0]) < 0) temp[0] = -temp[0]; fmpz_add(res, res, temp); flint_stack_release_small(); } else { temp = (fmpz_t) flint_stack_alloc(sizea + sizeb + 1); if (sizea >= sizeb) mslimb = F_mpn_mul(temp+1, a+1, sizea, b+1, sizeb); else mslimb = F_mpn_mul(temp+1, b+1, sizeb, a+1, sizea); temp[0] = sizea + sizeb - (mslimb == 0); if ((long) (a[0] ^ b[0]) < 0) temp[0] = -temp[0]; fmpz_add(res, res, temp); flint_stack_release(); } } }
void tiny_poly_clear(poly_t * poly_inf) { mpz_clear(poly_inf->C); flint_stack_release(); // release all A_inv2B[i] flint_stack_release(); // release soln1 flint_stack_release(); // release soln2 flint_stack_release(); // release A_inv flint_stack_release(); // release inv_p2 flint_stack_release(); // release A_inv2B flint_stack_release(); // release A_modp flint_stack_release(); // release A_ind flint_stack_release(); // release B_terms }
void fmpz_mul(fmpz_t res, const fmpz_t a, const fmpz_t b) { long a0 = a[0]; long b0 = b[0]; unsigned long sizea = FLINT_ABS(a0); unsigned long sizeb = FLINT_ABS(b0); while ((!a[sizea]) && (sizea)) sizea--; while ((!b[sizeb]) && (sizeb)) sizeb--; mp_limb_t mslimb; fmpz_t temp; if ((sizea == 0) || (sizeb == 0)) { res[0] = 0; } else if (sizea + sizeb < 100) { temp = (fmpz_t) flint_stack_alloc_small(sizea + sizeb + 1); if (sizea > sizeb) mslimb = mpn_mul(temp+1, a+1, sizea, b+1, sizeb); else if (sizea == sizeb) { mpn_mul_n(temp+1, a+1, b+1, sizeb); mslimb = temp[2*sizeb]; } else mslimb = mpn_mul(temp+1, b+1, sizeb, a+1, sizea); temp[0] = sizea + sizeb - (mslimb == 0); F_mpn_copy(res, temp, temp[0]+1); if ((long) (a0 ^ b0) < 0) res[0] = -res[0]; flint_stack_release_small(); } else if (sizea + sizeb < 2*FLINT_FFT_LIMBS_CROSSOVER) { temp = (fmpz_t) flint_stack_alloc(sizea + sizeb + 1); if (sizea > sizeb) mslimb = mpn_mul(temp+1, a+1, sizea, b+1, sizeb); else if (sizea == sizeb) { mpn_mul_n(temp+1, a+1, b+1, sizeb); mslimb = temp[2*sizeb]; } else mslimb = mpn_mul(temp+1, b+1, sizeb, a+1, sizea); temp[0] = sizea + sizeb - (mslimb == 0); F_mpn_copy(res, temp, temp[0]+1); if ((long) (a0 ^ b0) < 0) res[0] = -res[0]; flint_stack_release(); } else { if (sizea >= sizeb) mslimb = F_mpn_mul(res+1, a+1, sizea, b+1, sizeb); else mslimb = F_mpn_mul(res+1, b+1, sizeb, a+1, sizea); res[0] = sizea+sizeb - (mslimb == 0); if ((long) (a0 ^ b0) < 0) res[0] = -res[0]; } }
void fmpz_fdiv(fmpz_t res, const fmpz_t a, const fmpz_t b) { long a0 = a[0]; long b0 = b[0]; unsigned long sizea = FLINT_ABS(a0); unsigned long sizeb = FLINT_ABS(b0); while ((!a[sizea]) && (sizea)) sizea--; while ((!b[sizeb]) && (sizeb)) sizeb--; mp_limb_t mslimb; fmpz_t temp; if (sizeb == 0) { printf("Error: division by zero!\n"); abort(); } else if (sizea < sizeb) // Todo: make this deal with sizea == sizeb but a < b { if (((long) (a0 ^ b0) < 0L) && (a0)) { res[0] = -1L; res[1] = 1; } else res[0] = 0; return; } else { temp = (fmpz_t) flint_stack_alloc(sizeb); mpn_tdiv_qr(res+1, temp, 0, a+1, sizea, b+1, sizeb); res[0] = sizea - sizeb + 1; if ((long) (a0 ^ b0) < 0L) res[0] = -res[0]; NORM(res); if ((long) (a0 ^ b0) < 0L) { unsigned long i = 0; for (; i < sizeb; i++) { if (temp[i]) break; } if (i < sizeb) { fmpz_sub_ui_inplace(res, 1UL); } } flint_stack_release(); } }
void fmpz_gcd(fmpz_t output, fmpz_t x1, fmpz_t x2) { ulong size1 = FLINT_ABS(x1[0]); ulong size2 = FLINT_ABS(x2[0]); mpz_t m1, m2, m0, m_out; m1->_mp_d = x1 + 1; m2->_mp_d = x2 + 1; m1->_mp_alloc = size1; m1->_mp_size = size1; m2->_mp_alloc = size2; m2->_mp_size = size2; ulong size_out = FLINT_MAX(size1, size2)+1; m0->_mp_d = flint_stack_alloc(size_out); m0->_mp_alloc = size_out; m0->_mp_size = 0; mpz_gcd(m0, m1, m2); size_out = m0->_mp_size; F_mpn_copy(output + 1, m0->_mp_d, size_out); output[0] = size_out; flint_stack_release(); }
void compute_B_terms(QS_t * qs_inf, poly_t * poly_inf) { unsigned long s = poly_inf->s; unsigned long * A_ind = poly_inf->A_ind; unsigned long * A_modp = poly_inf->A_modp; unsigned long * B_terms = poly_inf->B_terms; prime_t * factor_base = qs_inf->factor_base; unsigned long limbs = qs_inf->prec+1; unsigned long limbs2; unsigned long * A = poly_inf->A; unsigned long * B = poly_inf->B; unsigned long p, i; unsigned long * temp1 = (unsigned long *) flint_stack_alloc(limbs); unsigned long temp; mp_limb_t msl; double pinv; for (i = 0; i < s; i++) { p = factor_base[A_ind[i]].p; pinv = z_precompute_inverse(p); mpn_divmod_1(temp1 + 1, A + 1, A[0], p); temp1[0] = A[0] - (temp1[A[0]] == 0); A_modp[i] = (temp = mpn_mod_1(temp1 + 1, temp1[0], p)); temp = z_invert(temp, p); temp = z_mulmod_precomp(temp, qs_inf->sqrts[A_ind[i]], p, pinv); if (temp > p/2) temp = p - temp; msl = mpn_mul_1(B_terms + i*limbs + 1, temp1 + 1, temp1[0], temp); if (msl) { B_terms[i*limbs + temp1[0] + 1] = msl; B_terms[i*limbs] = temp1[0] + 1; } else B_terms[i*limbs] = temp1[0]; #if B_TERMS mpz_t temp; mpz_init(temp); fmpz_to_mpz(temp, B_terms + i*limbs); gmp_printf("B_%ld = %Zd\n", i, temp); mpz_clear(temp); #endif } F_mpn_copy(B, B_terms, B_terms[0]+1); // Set B to the sum of the B terms if (limbs > B_terms[0] + 1) F_mpn_clear(B + B_terms[0] + 1, limbs - B_terms[0] - 1); for (i = 1; i < s; i++) { limbs2 = B_terms[i*limbs]; msl = mpn_add_n(B+1, B+1, B_terms + i*limbs + 1, limbs2); if (msl) mpn_add_1(B + limbs2 + 1, B + limbs2 + 1, limbs - limbs2 - 1, msl); } B[0] = limbs - 1; while (!B[B[0]] && B[0]) B[0]--; #if B_TERMS mpz_t temp2; mpz_init(temp2); fmpz_to_mpz(temp2, B); gmp_printf("B = %Zd\n", temp2); mpz_clear(temp2); #endif flint_stack_release(); // release temp1 }
void compute_A(QS_t * qs_inf, poly_t * poly_inf) { unsigned long min = poly_inf->min; unsigned long span = poly_inf->span; unsigned long s = poly_inf->s; unsigned long * A_ind = poly_inf->A_ind; unsigned long * A = poly_inf->A; unsigned long * target_A = poly_inf->target_A; unsigned long * current_A = (unsigned long *) flint_stack_alloc(qs_inf->prec+1); unsigned long * diff = (unsigned long *) flint_stack_alloc(qs_inf->prec+1); unsigned long * best_diff = (unsigned long *) flint_stack_alloc(qs_inf->prec+1); prime_t * factor_base = qs_inf->factor_base; unsigned long factor, p; unsigned long best1, best2, best3; unsigned long odds = s - 3; mp_limb_t msl; int taken; long i, j, k; A[0] = 1; A[1] = 1; for (i = 0; i < odds; i++) // Randomly choose the first s-3 prime factors of A with odd indices { do { taken = 0; A_ind[i] = ((z_randint(span) + min) | 1); if (A_ind[i] == min + span) A_ind[i] -= 2; for (j = 0; j < i; j++) { if (A_ind[i] == A_ind[j]) taken = 1; } } while (taken); msl = mpn_mul_1(A+1, A+1, A[0], factor_base[A_ind[i]].p); if (msl) // Compute the product of these s-3 primes { A[A[0]+1] = msl; A[0]++; } } for (k = 0; k < 30; k++) // Now try 8 different sets of even index primes as the remaining factors { F_mpn_copy(current_A, A, A[0] + 1); for (i = 0; i < 3; i++) // Randomly choose the last 3 prime factors of A with even indices { do { taken = 0; A_ind[s-3+i] = ((z_randint(span) + min) & -2L); if (A_ind[s-3+i] < min) A_ind[s-3+i] += 2; for (j = 0; j < i; j++) { if (A_ind[s-3+i] == A_ind[s-3+j]) taken = 1; } } while (taken); msl = mpn_mul_1(current_A+1, current_A+1, current_A[0], factor_base[A_ind[s-3+i]].p); if (msl) // Compute the product of these s-3 primes and the odd indexed primes { current_A[current_A[0]+1] = msl; current_A[0]++; } } if (k == 0) // Just store the first difference as the best one { if (target_A[0] >= current_A[0]) // Compute the difference with the target A { msl = mpn_sub(best_diff+1, target_A+1, target_A[0], current_A+1, current_A[0]); best_diff[0] = target_A[0]; } else { msl = mpn_sub(best_diff+1, current_A+1, current_A[0], target_A+1, target_A[0]); best_diff[0] = current_A[0]; } if (msl) F_mpn_negate(best_diff+1, best_diff+1, best_diff[0]); while ((!best_diff[best_diff[0]]) && (best_diff[0])) best_diff[0]--; // Normalise best_diff best1 = A_ind[s-3]; best2 = A_ind[s-2]; best3 = A_ind[s-1]; continue; } if (target_A[0] >= current_A[0]) // Compute the difference with the target A { msl = mpn_sub(diff+1, target_A+1, target_A[0], current_A+1, current_A[0]); diff[0] = target_A[0]; } else { msl = mpn_sub(diff+1, current_A+1, current_A[0], target_A+1, target_A[0]); diff[0] = current_A[0]; } if (msl) F_mpn_negate(diff+1, diff+1, diff[0]); while ((!diff[diff[0]]) && (diff[0])) diff[0]--; // Normalise diff if ((diff[0] < best_diff[0]) || ((diff[0] == best_diff[0]) && (mpn_cmp(diff+1, best_diff+1, diff[0]) < 0))) // The new diff is better { F_mpn_copy(best_diff, diff, diff[0]+1); best1 = A_ind[s-3]; best2 = A_ind[s-2]; best3 = A_ind[s-1]; } } A_ind[s-3] = best1; // Multiply A by the product of these 3 primes and store their indices A_ind[s-2] = best2; A_ind[s-1] = best3; for (i = 0; i < 3; i++) { msl = mpn_mul_1(A+1, A+1, A[0], factor_base[A_ind[s+i-3]].p); if (msl) { A[A[0]+1] = msl; A[0]++; } } #if POLY_A mpz_t A_disp, targ_A; mpz_init(A_disp); mpz_init(targ_A); fmpz_to_mpz(A_disp, A); fmpz_to_mpz(targ_A, target_A); gmp_printf("A = %Zd, target A = %Zd\n", A_disp, targ_A); mpz_clear(A_disp); mpz_clear(targ_A); #endif /*for (i = 0; i < s; i++) { p = factor_base[A_ind[i]].p; poly_inf->inv_p2[i] = z_precompute_inverse(p*p); } */ fmpz_to_mpz(poly_inf->A_mpz, A); flint_stack_release(); // release current_A flint_stack_release(); // release diff flint_stack_release(); // release best_diff }
void poly_clear(poly_t * poly_inf) { mpz_clear(poly_inf->A_mpz); mpz_clear(poly_inf->B_mpz); mpz_clear(poly_inf->C); flint_stack_release(); // release all A_inv2B[i] flint_stack_release(); // release posn1 flint_stack_release(); // release posn2 flint_stack_release(); // release soln1 flint_stack_release(); // release soln2 flint_stack_release(); // release A_inv flint_stack_release(); // release inv_p2 flint_stack_release(); // release A_inv2B flint_stack_release(); // release A_modp flint_stack_release(); // release A_ind flint_stack_release(); // release target_A flint_stack_release(); // release A flint_stack_release(); // release B_terms flint_stack_release(); // release B }
void sqrts_clear(void) { flint_stack_release(); }
int fmpz_divides(fmpz_t q, const fmpz_t a, const fmpz_t b) { long a0 = a[0]; long b0 = b[0]; unsigned long sizea = FLINT_ABS(a0); unsigned long sizeb = FLINT_ABS(b0); mp_limb_t mslimb; fmpz_t temp; if (sizeb == 0) { printf("Error: division by zero!\n"); abort(); } else if (sizea == 0) { q[0] = 0; return 1; } else if (sizea < sizeb) { return 0; } else if (sizea == sizeb) { int cmp = fmpz_cmpabs(a, b); if (cmp < 0) return 0; if (cmp == 0) { if ((long) (a0 ^ b0) < 0L) q[0] = -1L; else q[0] = 1L; q[1] = 1; return 1; } } if (fmpz_is_one(b)) { fmpz_set(q, a); return 1; } if (fmpz_is_m1(b)) { fmpz_neg(q, a); return 1; } temp = (fmpz_t) flint_stack_alloc(sizeb + 2); mpn_tdiv_qr(q+1, temp+1, 0, a+1, sizea, b+1, sizeb); temp[0] = sizeb; NORM(temp); if (temp[0] != 0) { flint_stack_release(); return 0; } q[0] = sizea - sizeb + 1; NORM(q); if ((long) (a0 ^ b0) < 0L) q[0] = -q[0]; flint_stack_release(); return 1; }
void fmpz_mod(fmpz_t res, const fmpz_t a, const fmpz_t b) { long a0 = a[0]; long b0 = b[0]; unsigned long sizea = FLINT_ABS(a0); unsigned long sizeb = b0; while ((!a[sizea]) && (sizea)) sizea--; while ((!b[sizeb]) && (sizeb)) sizeb--; mp_limb_t mslimb; fmpz_t temp, temp2; if (sizeb == 0) { printf("Error: division by zero!\n"); abort(); } else if (sizea < sizeb) { if ((long) a0 < 0L) { temp = (fmpz_t) flint_stack_alloc(sizeb + 2); fmpz_add(temp, a, b); fmpz_set(res, temp); flint_stack_release(); } else fmpz_set(res, a); return; } else if ((sizea == sizeb) && (fmpz_cmpabs(a, b) < 0L)) { if (fmpz_sgn(a) < 0) fmpz_add(res, a, b); else fmpz_set(res, a); return; } else { if (fmpz_is_one(b)) { fmpz_set_ui(res, 0L); return; } temp = (fmpz_t) flint_stack_alloc(sizea - sizeb + 1); temp2 = (fmpz_t) flint_stack_alloc(sizeb + 2); mpn_tdiv_qr(temp, temp2+1, 0, a+1, sizea, b+1, sizeb); temp2[0] = sizeb; NORM(temp2); if (a0 < 0L) { unsigned long i = 0; for (; i < sizeb; i++) { if (temp2[i+1]) break; } if (i < sizeb) { fmpz_sub(temp2, b, temp2); } fmpz_set(res, temp2); } else fmpz_set(res, temp2); flint_stack_release(); flint_stack_release(); } }
void primes_clear(void) { flint_stack_release(); }
void sizes_clear(void) { flint_stack_release(); }
void fmpz_comb_init(fmpz_comb_t comb, ulong * primes, ulong num_primes) { ulong i, j, k; comb->primes = primes; comb->num_primes = num_primes; ulong n = 0L; while (num_primes > (1L<<n)) n++; comb->n = n; ulong num; // create zn_poly modulus information comb->mod = (zn_mod_t *) flint_heap_alloc_bytes(sizeof(zn_mod_t)*num_primes); for (ulong i = 0; i < num_primes; i++) zn_mod_init(comb->mod[i], primes[i]); if (n == 0) return; // nothing to do // allocate space for comb comb->comb = (fmpz_t **) flint_heap_alloc(n); j = (1L<<(n - 1)); ulong size = 2; mp_limb_t * ptr; for (i = 0; i < n; i++) { comb->comb[i] = (fmpz_t *) flint_heap_alloc(j); ptr = (mp_limb_t *) flint_heap_alloc((1L<<n) + j); for (k = 0; k < j; k++, ptr += (size + 1)) { comb->comb[i][k] = ptr; } j/=2; size*=2; } // allocate space for res comb->res = (fmpz_t **) flint_heap_alloc(n); j = (1L<<(n - 1)); size = 2; for (i = 0; i < n; i++) { comb->res[i] = (fmpz_t *) flint_heap_alloc(j); ptr = (mp_limb_t *) flint_heap_alloc((1L<<n) + j); for (k = 0; k < j; k++, ptr += (size + 1)) { comb->res[i][k] = ptr; } j/=2; size*=2; } // compute products of pairs of primes and place in comb for (i = 0, j = 0; i + 2 <= num_primes; i += 2, j++) { fmpz_set_ui(comb->comb[0][j], primes[i]); fmpz_mul_ui(comb->comb[0][j], comb->comb[0][j], primes[i+1]); } if (i < num_primes) // in case number of primes is odd { fmpz_set_ui(comb->comb[0][j], primes[i]); i+=2; j++; } num = (1L<<n); // set the rest of the entries on that row of the comb to 1 for (; i < num; i += 2, j++) { fmpz_set_ui(comb->comb[0][j], 1L); } // compute rest of comb by multiplying in pairs ulong log_comb = 1; num /= 2; while (num >= 2) { for (i = 0, j = 0; i < num; i += 2, j++) { fmpz_mul(comb->comb[log_comb][j], comb->comb[log_comb-1][i], comb->comb[log_comb-1][i+1]); } log_comb++; num /= 2; } // compute inverses from pairs of primes fmpz_t temp = (fmpz_t) flint_stack_alloc(2); fmpz_t temp2 = (fmpz_t) flint_stack_alloc(2); for (i = 0, j = 0; i + 2 <= num_primes; i += 2, j++) { fmpz_set_ui(temp, primes[i]); fmpz_set_ui(temp2, primes[i+1]); fmpz_invert(comb->res[0][j], temp, temp2); } flint_stack_release(); //temp2 flint_stack_release(); //temp ulong log_res = 1; num = (1L<<(n - 1)); // compute remaining inverses, each level combining pairs from the level below while (log_res < n) { for (i = 0, j = 0; i < num; i += 2, j++) { fmpz_invert(comb->res[log_res][j], comb->comb[log_res-1][i], comb->comb[log_res-1][i+1]); } log_res++; num /= 2; } }
void flint_stack_release_small(void) { flint_stack_release(); }