/* Compute e^x. */ static void exp_mpn (mp1 ex, mp1 x) { unsigned int n; mp1 xp; mp2 tmp; mp_limb_t chk; mp1 tol; memset (xp, 0, sizeof (mp1)); memset (ex, 0, sizeof (mp1)); xp[FRAC / mpbpl] = (mp_limb_t)1 << FRAC % mpbpl; memset (tol, 0, sizeof (mp1)); tol[(FRAC - TOL) / mpbpl] = (mp_limb_t)1 << (FRAC - TOL) % mpbpl; n = 0; do { /* Calculate sum(x^n/n!) until the next term is sufficiently small. */ mpn_mul_n (tmp, xp, x, SZ); assert(tmp[SZ * 2 - 1] == 0); if (n > 0) mpn_divmod_1 (xp, tmp + FRAC / mpbpl, SZ, n); chk = mpn_add_n (ex, ex, xp, SZ); assert (chk == 0); ++n; assert (n < 80); /* Catch too-high TOL. */ } while (n < 10 || mpn_cmp (xp, tol, SZ) >= 0); }
void fmpz_tdiv_ui(fmpz_t output, const fmpz_t input, const unsigned long x) { output[0] = input[0]; unsigned long size = FLINT_ABS(input[0]); mpn_divmod_1(output+1, input+1, size, x); NORM(output); }
void sdiv (const MINT *dividend, signed short int divisor_short, MINT *quot, short *rem_ptr) { mp_size_t sign_dividend; signed long int sign_divisor; mp_size_t dividend_size, quot_size; mp_ptr dividend_ptr, quot_ptr; mp_limb_t divisor_limb; mp_limb_t remainder_limb; sign_dividend = dividend->_mp_size; dividend_size = ABS (dividend->_mp_size); if (dividend_size == 0) { quot->_mp_size = 0; *rem_ptr = 0; return; } sign_divisor = divisor_short; divisor_limb = (unsigned short) ABS (divisor_short); /* No need for temporary allocation and copying even if QUOT == DIVIDEND as the divisor is just one limb, and thus no intermediate remainders need to be stored. */ if (quot->_mp_alloc < dividend_size) _mp_realloc (quot, dividend_size); quot_ptr = quot->_mp_d; dividend_ptr = dividend->_mp_d; remainder_limb = mpn_divmod_1 (quot_ptr, dividend_ptr, dividend_size, divisor_limb); *rem_ptr = sign_dividend >= 0 ? remainder_limb : -remainder_limb; /* The quotient is DIVIDEND_SIZE limbs, but the most significant might be zero. Set QUOT_SIZE properly. */ quot_size = dividend_size - (quot_ptr[dividend_size - 1] == 0); quot->_mp_size = (sign_divisor ^ sign_dividend) >= 0 ? quot_size : -quot_size; }
/* Divide (arrayg, limbsg) by the positive value gc inplace and return the number of limbs written */ mp_size_t mpn_tdiv_q_fmpz_inplace(mp_ptr arrayg, mp_size_t limbsg, fmpz_t gc) { if (fmpz_size(gc) == 1) { mpn_divmod_1(arrayg, arrayg, limbsg, fmpz_get_ui(gc)); return limbsg - (arrayg[limbsg - 1] == 0); } else { mp_size_t tlimbs; __mpz_struct * mpz_ptr = COEFF_TO_PTR(*gc); mp_ptr temp = flint_malloc(limbsg*sizeof(mp_limb_t)); mpn_copyi(temp, arrayg, limbsg); mpn_tdiv_q(arrayg, temp, limbsg, mpz_ptr->_mp_d, mpz_ptr->_mp_size); tlimbs = limbsg - mpz_ptr->_mp_size + 1; tlimbs -= (arrayg[tlimbs - 1] == 0); flint_free(temp); return tlimbs; } }
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 }
/* mpn_divmod_1 was a function in gmp 3.0.1 and earlier, but marked obsolete in both gmp 2 and 3. As of gmp 3.1 it's a macro calling mpn_divrem_1. */ mp_limb_t __MPN (divmod_1) (mp_ptr dst, mp_srcptr src, mp_size_t size, mp_limb_t divisor) { return mpn_divmod_1 (dst, src, size, divisor); }