slong fmpr_get_si(const fmpr_t x, fmpr_rnd_t rnd) { fmpz_t t; slong v; fmpz_init(t); fmpr_get_fmpz(t, x, rnd); if (!fmpz_fits_si(t)) { flint_printf("fmpr_get_si: result does not fit in a signed slong\n"); abort(); } v = fmpz_get_si(t); fmpz_clear(t); return v; }
void arf_get_fmpz(fmpz_t z, const arf_t x, arf_rnd_t rnd) { if (arf_is_special(x)) { if (arf_is_zero(x)) { fmpz_zero(z); } else { flint_printf("arf_get_fmpz: cannot convert infinity or nan to integer\n"); abort(); } } else if (COEFF_IS_MPZ(*ARF_EXPREF(x))) { /* tiny */ if (fmpz_sgn(ARF_EXPREF(x)) < 0) { int negative = ARF_SGNBIT(x); if (rnd == ARF_RND_NEAR || rnd == ARF_RND_DOWN || (rnd == ARF_RND_FLOOR && !negative) || (rnd == ARF_RND_CEIL && negative)) { fmpz_zero(z); } else { fmpz_set_si(z, negative ? -1 : 1); } } else { flint_printf("arf_get_fmpz: number too large to convert to integer\n"); abort(); } } else { slong exp; int negative, inexact; mp_size_t xn, zn; mp_srcptr xp; __mpz_struct * zz; /* TBD: implement efficiently */ if (rnd == ARF_RND_NEAR) { fmpr_t t; fmpr_init(t); arf_get_fmpr(t, x); fmpr_get_fmpz(z, t, rnd); fmpr_clear(t); return; } exp = ARF_EXP(x); negative = ARF_SGNBIT(x); /* |x| < 1 */ if (exp <= 0) { if (rnd == ARF_RND_DOWN || (rnd == ARF_RND_FLOOR && !negative) || (rnd == ARF_RND_CEIL && negative)) { fmpz_zero(z); } else { fmpz_set_si(z, negative ? -1 : 1); } return; } ARF_GET_MPN_READONLY(xp, xn, x); /* |x| < 2^31 or 2^63 (must save 1 bit for rounding up!) */ if (exp < FLINT_BITS) { mp_limb_t v, v2; v = xp[xn - 1]; v2 = v >> (FLINT_BITS - exp); inexact = (xn > 1) || ((v2 << (FLINT_BITS - exp)) != v); if (inexact && rnd != ARF_RND_DOWN) { if (negative && (rnd == ARF_RND_UP || rnd == ARF_RND_FLOOR)) v2++; if (!negative && (rnd == ARF_RND_UP || rnd == ARF_RND_CEIL)) v2++; } if (negative) fmpz_neg_ui(z, v2); else fmpz_set_ui(z, v2); return; } /* |x| >= 1 */ zn = (exp + FLINT_BITS - 1) / FLINT_BITS; zz = _fmpz_promote(z); if (zz->_mp_alloc < zn) mpz_realloc2(zz, zn * FLINT_BITS); inexact = _arf_get_integer_mpn(zz->_mp_d, xp, xn, exp); zz->_mp_size = negative ? -zn : zn; _fmpz_demote_val(z); if (inexact && rnd != ARF_RND_DOWN) { if (negative && (rnd == ARF_RND_UP || rnd == ARF_RND_FLOOR)) fmpz_sub_ui(z, z, 1); if (!negative && (rnd == ARF_RND_UP || rnd == ARF_RND_CEIL)) fmpz_add_ui(z, z, 1); } }
int main() { long iter; flint_rand_t state; printf("get_fmpz...."); fflush(stdout); flint_randinit(state); for (iter = 0; iter < 100000; iter++) { long bits; fmpr_t x; mpfr_t y; fmpz_t z, z2; mpz_t w; bits = 2 + n_randint(state, 1000); fmpr_init(x); mpfr_init2(y, bits); fmpz_init(z); fmpz_init(z2); mpz_init(w); fmpr_randtest(x, state, bits, 10); fmpr_get_mpfr(y, x, MPFR_RNDN); switch (n_randint(state, 5)) { case 0: fmpr_get_fmpz(z, x, FMPR_RND_FLOOR); mpfr_get_z(w, y, MPFR_RNDD); break; case 1: fmpr_get_fmpz(z, x, FMPR_RND_CEIL); mpfr_get_z(w, y, MPFR_RNDU); break; case 2: fmpr_get_fmpz(z, x, FMPR_RND_DOWN); mpfr_get_z(w, y, MPFR_RNDZ); break; case 3: fmpr_get_fmpz(z, x, FMPR_RND_UP); mpfr_get_z(w, y, MPFR_RNDA); break; default: fmpr_get_fmpz(z, x, FMPR_RND_NEAR); mpfr_get_z(w, y, MPFR_RNDN); break; } fmpz_set_mpz(z2, w); if (!fmpz_equal(z, z2)) { printf("FAIL\n\n"); printf("x = "); fmpr_print(x); printf("\n\n"); printf("z = "); fmpz_print(z); printf("\n\n"); printf("z2 = "); fmpz_print(z2); printf("\n\n"); abort(); } fmpr_clear(x); mpfr_clear(y); fmpz_clear(z); fmpz_clear(z2); mpz_clear(w); } flint_randclear(state); flint_cleanup(); printf("PASS\n"); return EXIT_SUCCESS; }