/* Copyright (C) 2012 Fredrik Johansson This file is part of Arb. Arb is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifndef FMPR_H #define FMPR_H #if defined(__MINGW64__) || defined(_MSC_VER) #include "stdint.h" #endif #include #include #include #include #include "flint/flint.h" #include "flint/fmpz.h" #include "flint/fmpq.h" #if __FLINT_RELEASE < 20600 #include "flint/config.h" #else #include "flint/flint-config.h" #endif #include "fmpz_extras.h" #ifndef flint_abort #if __FLINT_RELEASE <= 20502 #define flint_abort abort #endif #endif #define TLS_PREFIX FLINT_TLS_PREFIX #if defined(_MSC_VER) && defined(ARB_BUILD_DLL) #define ARB_DLL __declspec(dllexport) #else #define ARB_DLL FLINT_DLL #endif #define fmpr_rnd_t int #define FMPR_RND_DOWN 0 #define FMPR_RND_UP 1 #define FMPR_RND_FLOOR 2 #define FMPR_RND_CEIL 3 #define FMPR_RND_NEAR 4 #ifdef __cplusplus extern "C" { #endif /* currently defined in the arb module, but global to the library */ double arb_test_multiplier(void); static __inline__ int rounds_up(fmpr_rnd_t rnd, int negative) { if (rnd == FMPR_RND_DOWN) return 0; if (rnd == FMPR_RND_UP) return 1; if (rnd == FMPR_RND_FLOOR) return negative; return !negative; } static __inline__ mpfr_rnd_t rnd_to_mpfr(fmpr_rnd_t rnd) { if (rnd == FMPR_RND_DOWN) return MPFR_RNDZ; else if (rnd == FMPR_RND_UP) return MPFR_RNDA; else if (rnd == FMPR_RND_FLOOR) return MPFR_RNDD; else if (rnd == FMPR_RND_CEIL) return MPFR_RNDU; else return MPFR_RNDN; } typedef struct { fmpz man; fmpz exp; } fmpr_struct; typedef fmpr_struct fmpr_t[1]; typedef fmpr_struct * fmpr_ptr; typedef const fmpr_struct * fmpr_srcptr; #define fmpr_manref(x) (&(x)->man) #define fmpr_expref(x) (&(x)->exp) static __inline__ void fmpr_init(fmpr_t x) { fmpz_init(fmpr_manref(x)); fmpz_init(fmpr_expref(x)); } static __inline__ void fmpr_clear(fmpr_t x) { fmpz_clear(fmpr_manref(x)); fmpz_clear(fmpr_expref(x)); } /* The return value encodes an error bound, or FMPR_RESULT_EXACT if exact */ #define FMPR_RESULT_EXACT WORD_MAX /* Allow 'infinite' precision for operations where a result can be computed exactly */ #define FMPR_PREC_EXACT WORD_MAX #define FMPR_PREC_ADD(prec,extra) ((prec) == FMPR_PREC_EXACT ? FMPR_PREC_EXACT : (prec) + (extra)) /* ------------------------------------------------------------------------ */ /* Special values */ /* Special values (0, +inf, -inf, NaN) are encoded using a zero mantissa. Zero is encoded with a zero exponent. */ #define FMPR_EXP_POS_INF WORD(1) #define FMPR_EXP_NEG_INF WORD(2) #define FMPR_EXP_NAN WORD(3) static __inline__ void fmpr_zero(fmpr_t x) { fmpz_zero(fmpr_manref(x)); fmpz_zero(fmpr_expref(x)); } static __inline__ int fmpr_is_zero(const fmpr_t x) { return fmpz_is_zero(fmpr_manref(x)) && fmpz_is_zero(fmpr_expref(x)); } static __inline__ int fmpr_is_special(const fmpr_t x) { return fmpz_is_zero(fmpr_manref(x)); } static __inline__ int fmpr_is_normal(const fmpr_t x) { return !fmpz_is_zero(fmpr_manref(x)); } static __inline__ int fmpr_is_inf(const fmpr_t x) { return fmpr_is_special(x) && (*fmpr_expref(x) == FMPR_EXP_POS_INF || *fmpr_expref(x) == FMPR_EXP_NEG_INF); } static __inline__ int fmpr_is_pos_inf(const fmpr_t x) { return fmpr_is_special(x) && (*fmpr_expref(x) == FMPR_EXP_POS_INF); } static __inline__ int fmpr_is_neg_inf(const fmpr_t x) { return fmpr_is_special(x) && (*fmpr_expref(x) == FMPR_EXP_NEG_INF); } static __inline__ int fmpr_is_nan(const fmpr_t x) { return fmpr_is_special(x) && (*fmpr_expref(x) == FMPR_EXP_NAN); } static __inline__ int fmpr_is_finite(const fmpr_t x) { return fmpr_is_zero(x) || !fmpr_is_special(x); } static __inline__ void fmpr_pos_inf(fmpr_t x) { fmpz_zero(fmpr_manref(x)); fmpz_set_si(fmpr_expref(x), FMPR_EXP_POS_INF); } static __inline__ void fmpr_neg_inf(fmpr_t x) { fmpz_zero(fmpr_manref(x)); fmpz_set_si(fmpr_expref(x), FMPR_EXP_NEG_INF); } static __inline__ void fmpr_nan(fmpr_t x) { fmpz_zero(fmpr_manref(x)); fmpz_set_si(fmpr_expref(x), FMPR_EXP_NAN); } static __inline__ int fmpr_is_one(const fmpr_t x) { return fmpz_is_one(fmpr_manref(x)) && fmpz_is_zero(fmpr_expref(x)); } static __inline__ void fmpr_one(fmpr_t x) { fmpz_one(fmpr_manref(x)); fmpz_zero(fmpr_expref(x)); } /* ------------------------------------------------------------------------ */ slong _fmpr_normalise_naive(fmpz_t man, fmpz_t exp, slong prec, fmpr_rnd_t rnd); static __inline__ void fmpr_set(fmpr_t y, const fmpr_t x) { if (y != x) { fmpz_set(fmpr_manref(y), fmpr_manref(x)); fmpz_set(fmpr_expref(y), fmpr_expref(x)); } } static __inline__ void fmpr_swap(fmpr_t x, fmpr_t y) { fmpz_swap(fmpr_manref(x), fmpr_manref(y)); fmpz_swap(fmpr_expref(x), fmpr_expref(y)); } slong _fmpr_set_round(fmpz_t rman, fmpz_t rexp, const fmpz_t man, const fmpz_t exp, slong prec, fmpr_rnd_t rnd); static __inline__ slong _fmpr_normalise(fmpz_t man, fmpz_t exp, slong prec, fmpr_rnd_t rnd) { if (fmpz_is_zero(man)) { fmpz_zero(man); fmpz_zero(exp); return FMPR_RESULT_EXACT; } else { return _fmpr_set_round(man, exp, man, exp, prec, rnd); } } static __inline__ slong fmpr_set_round_naive(fmpr_t y, const fmpr_t x, slong prec, fmpr_rnd_t rnd) { fmpr_set(y, x); if (fmpr_is_special(y)) return FMPR_RESULT_EXACT; else return _fmpr_normalise(fmpr_manref(y), fmpr_expref(y), prec, rnd); } static __inline__ slong fmpr_set_round(fmpr_t y, const fmpr_t x, slong prec, fmpr_rnd_t rnd) { if (fmpr_is_special(x)) { fmpr_set(y, x); return FMPR_RESULT_EXACT; } else { return _fmpr_set_round(fmpr_manref(y), fmpr_expref(y), fmpr_manref(x), fmpr_expref(x), prec, rnd); } } static __inline__ slong fmpr_set_round_fmpz_2exp(fmpr_t y, const fmpz_t x, const fmpz_t exp, slong prec, fmpr_rnd_t rnd) { if (fmpz_is_zero(x)) { fmpr_zero(y); return FMPR_RESULT_EXACT; } else { return _fmpr_set_round(fmpr_manref(y), fmpr_expref(y), x, exp, prec, rnd); } } static __inline__ slong fmpr_set_round_fmpz(fmpr_t y, const fmpz_t x, slong prec, fmpr_rnd_t rnd) { if (fmpz_is_zero(x)) { fmpr_zero(y); return FMPR_RESULT_EXACT; } else { slong ret; fmpz_t exp; fmpz_init(exp); ret = _fmpr_set_round(fmpr_manref(y), fmpr_expref(y), x, exp, prec, rnd); fmpz_clear(exp); return ret; } } slong _fmpr_set_round_mpn(slong * shift, fmpz_t man, mp_srcptr x, mp_size_t xn, int negative, slong prec, fmpr_rnd_t rnd); slong fmpr_set_round_ui_2exp_fmpz(fmpr_t z, mp_limb_t lo, const fmpz_t exp, int negative, slong prec, fmpr_rnd_t rnd); slong fmpr_set_round_uiui_2exp_fmpz(fmpr_t z, mp_limb_t hi, mp_limb_t lo, const fmpz_t exp, int negative, slong prec, fmpr_rnd_t rnd); void fmpr_ulp(fmpr_t u, const fmpr_t x, slong prec); int fmpr_check_ulp(const fmpr_t result, slong r, slong prec); static __inline__ int fmpr_equal(const fmpr_t x, const fmpr_t y) { return fmpz_equal(fmpr_expref(x), fmpr_expref(y)) && fmpz_equal(fmpr_manref(x), fmpr_manref(y)); } static __inline__ int fmpr_sgn(const fmpr_t x) { if (fmpr_is_special(x)) { if (fmpr_is_zero(x)) return 0; if (fmpr_is_pos_inf(x)) return 1; if (fmpr_is_neg_inf(x)) return -1; return 0; } return fmpz_sgn(fmpr_manref(x)); } int fmpr_cmp(const fmpr_t x, const fmpr_t y); int fmpr_cmpabs(const fmpr_t x, const fmpr_t y); int fmpr_cmpabs_ui(const fmpr_t x, ulong y); void fmpr_randtest(fmpr_t x, flint_rand_t state, slong bits, slong exp_bits); void fmpr_randtest_not_zero(fmpr_t x, flint_rand_t state, slong bits, slong exp_bits); void fmpr_randtest_special(fmpr_t x, flint_rand_t state, slong bits, slong exp_bits); int fmpr_get_mpfr(mpfr_t x, const fmpr_t y, mpfr_rnd_t rnd); void fmpr_set_mpfr(fmpr_t x, const mpfr_t y); double fmpr_get_d(const fmpr_t x, fmpr_rnd_t rnd); void fmpr_set_d(fmpr_t x, double v); static __inline__ void fmpr_set_ui(fmpr_t x, ulong c) { if (c == 0) { fmpr_zero(x); } else { int b; count_trailing_zeros(b, c); fmpz_set_ui(fmpr_manref(x), c >> b); fmpz_set_ui(fmpr_expref(x), b); } } static __inline__ void fmpr_set_si(fmpr_t x, slong c) { if (c == 0) { fmpr_zero(x); } else { int b; count_trailing_zeros(b, c); fmpz_set_si(fmpr_manref(x), c >> b); fmpz_set_ui(fmpr_expref(x), b); } } static __inline__ void fmpr_set_fmpz(fmpr_t x, const fmpz_t c) { if (fmpz_is_zero(c)) { fmpr_zero(x); } else { slong v = fmpz_val2(c); fmpz_tdiv_q_2exp(fmpr_manref(x), c, v); fmpz_set_ui(fmpr_expref(x), v); } } /* Arithmetic */ slong _fmpr_add_eps(fmpr_t z, const fmpr_t x, int sign, slong prec, fmpr_rnd_t rnd); slong _fmpr_add_mpn(fmpr_t z, mp_srcptr xman, mp_size_t xn, int xsign, const fmpz_t xexp, mp_srcptr yman, mp_size_t yn, int ysign, const fmpz_t yexp, slong shift, slong prec, fmpr_rnd_t rnd); slong _fmpr_add_1x1(fmpr_t z, mp_limb_t x, int xsign, const fmpz_t xexp, mp_limb_t y, int ysign, const fmpz_t yexp, slong shift, slong prec, slong rnd); slong fmpr_add_naive(fmpr_t z, const fmpr_t x, const fmpr_t y, slong prec, fmpr_rnd_t rnd); slong _fmpr_mul_mpn(fmpr_t z, mp_srcptr xman, mp_size_t xn, const fmpz_t xexp, mp_srcptr yman, mp_size_t yn, const fmpz_t yexp, int negative, slong prec, fmpr_rnd_t rnd); slong _fmpr_mul_1x1(fmpr_t z, mp_limb_t u, const fmpz_t xexp, mp_limb_t v, const fmpz_t yexp, int negative, slong prec, fmpr_rnd_t rnd); slong fmpr_mul_naive(fmpr_t z, const fmpr_t x, const fmpr_t y, slong prec, fmpr_rnd_t rnd); slong fmpr_mul(fmpr_t z, const fmpr_t x, const fmpr_t y, slong prec, fmpr_rnd_t rnd); slong fmpr_mul_ui(fmpr_t z, const fmpr_t x, ulong y, slong prec, fmpr_rnd_t rnd); slong fmpr_mul_si(fmpr_t z, const fmpr_t x, slong y, slong prec, fmpr_rnd_t rnd); slong fmpr_mul_fmpz(fmpr_t z, const fmpr_t x, const fmpz_t y, slong prec, fmpr_rnd_t rnd); slong fmpr_add(fmpr_t z, const fmpr_t x, const fmpr_t y, slong prec, fmpr_rnd_t rnd); slong fmpr_add_ui(fmpr_t z, const fmpr_t x, ulong y, slong prec, fmpr_rnd_t rnd); slong fmpr_add_si(fmpr_t z, const fmpr_t x, slong y, slong prec, fmpr_rnd_t rnd); slong fmpr_add_fmpz(fmpr_t z, const fmpr_t x, const fmpz_t y, slong prec, fmpr_rnd_t rnd); slong fmpr_sub(fmpr_t z, const fmpr_t x, const fmpr_t y, slong prec, fmpr_rnd_t rnd); slong fmpr_sub_ui(fmpr_t z, const fmpr_t x, ulong y, slong prec, fmpr_rnd_t rnd); slong fmpr_sub_si(fmpr_t z, const fmpr_t x, slong y, slong prec, fmpr_rnd_t rnd); slong fmpr_sub_fmpz(fmpr_t z, const fmpr_t x, const fmpz_t y, slong prec, fmpr_rnd_t rnd); slong fmpr_div(fmpr_t z, const fmpr_t x, const fmpr_t y, slong prec, fmpr_rnd_t rnd); slong fmpr_div_ui(fmpr_t z, const fmpr_t x, ulong y, slong prec, fmpr_rnd_t rnd); slong fmpr_ui_div(fmpr_t z, ulong x, const fmpr_t y, slong prec, fmpr_rnd_t rnd); slong fmpr_div_si(fmpr_t z, const fmpr_t x, slong y, slong prec, fmpr_rnd_t rnd); slong fmpr_si_div(fmpr_t z, slong x, const fmpr_t y, slong prec, fmpr_rnd_t rnd); slong fmpr_div_fmpz(fmpr_t z, const fmpr_t x, const fmpz_t y, slong prec, fmpr_rnd_t rnd); slong fmpr_fmpz_div(fmpr_t z, const fmpz_t x, const fmpr_t y, slong prec, fmpr_rnd_t rnd); slong fmpr_fmpz_div_fmpz(fmpr_t z, const fmpz_t x, const fmpz_t y, slong prec, fmpr_rnd_t rnd); slong fmpr_addmul(fmpr_t z, const fmpr_t x, const fmpr_t y, slong prec, fmpr_rnd_t rnd); slong fmpr_addmul_ui(fmpr_t z, const fmpr_t x, ulong y, slong prec, fmpr_rnd_t rnd); slong fmpr_addmul_si(fmpr_t z, const fmpr_t x, slong y, slong prec, fmpr_rnd_t rnd); slong fmpr_addmul_fmpz(fmpr_t z, const fmpr_t x, const fmpz_t y, slong prec, fmpr_rnd_t rnd); slong fmpr_submul(fmpr_t z, const fmpr_t x, const fmpr_t y, slong prec, fmpr_rnd_t rnd); slong fmpr_submul_ui(fmpr_t z, const fmpr_t x, ulong y, slong prec, fmpr_rnd_t rnd); slong fmpr_submul_si(fmpr_t z, const fmpr_t x, slong y, slong prec, fmpr_rnd_t rnd); slong fmpr_submul_fmpz(fmpr_t z, const fmpr_t x, const fmpz_t y, slong prec, fmpr_rnd_t rnd); slong fmpr_sqrt(fmpr_t y, const fmpr_t x, slong prec, fmpr_rnd_t rnd); slong fmpr_sqrt_ui(fmpr_t z, ulong x, slong prec, fmpr_rnd_t rnd); slong fmpr_sqrt_fmpz(fmpr_t z, const fmpz_t x, slong prec, fmpr_rnd_t rnd); slong fmpr_rsqrt(fmpr_t y, const fmpr_t x, slong prec, fmpr_rnd_t rnd); slong fmpr_root(fmpr_t y, const fmpr_t x, ulong k, slong prec, fmpr_rnd_t rnd); slong fmpr_log(fmpr_t y, const fmpr_t x, slong prec, fmpr_rnd_t rnd); slong fmpr_log1p(fmpr_t y, const fmpr_t x, slong prec, fmpr_rnd_t rnd); slong fmpr_exp(fmpr_t y, const fmpr_t x, slong prec, fmpr_rnd_t rnd); slong fmpr_expm1(fmpr_t y, const fmpr_t x, slong prec, fmpr_rnd_t rnd); static __inline__ void fmpr_neg(fmpr_t y, const fmpr_t x) { if (fmpr_is_special(x)) { if (fmpr_is_pos_inf(x)) fmpr_neg_inf(y); else if (fmpr_is_neg_inf(x)) fmpr_pos_inf(y); else fmpr_set(y, x); } else { fmpz_neg(fmpr_manref(y), fmpr_manref(x)); fmpz_set(fmpr_expref(y), fmpr_expref(x)); } } static __inline__ slong fmpr_neg_round(fmpr_t y, const fmpr_t x, slong prec, fmpr_rnd_t rnd) { fmpr_neg(y, x); if (fmpr_is_special(y)) return FMPR_RESULT_EXACT; else return _fmpr_normalise(fmpr_manref(y), fmpr_expref(y), prec, rnd); } static __inline__ void fmpr_abs(fmpr_t y, const fmpr_t x) { if (fmpr_sgn(x) < 0) fmpr_neg(y, x); else fmpr_set(y, x); } /* Convert return value to error bound */ static __inline__ void fmpr_set_error_result(fmpr_t err, const fmpr_t result, slong rret) { if (rret == FMPR_RESULT_EXACT) { fmpr_zero(err); } /* XXX: normally, a special value should not result from inexact arithmetic else if (fmpr_is_special(result)) { fmpr_pos_inf(err); } */ else { /* TODO: inline this */ fmpz_sub_ui(fmpr_expref(err), fmpr_expref(result), rret); fmpz_one(fmpr_manref(err)); } } static __inline__ void fmpr_add_error_result(fmpr_t err, const fmpr_t err_in, const fmpr_t result, slong rret, slong prec, fmpr_rnd_t rnd) { if (rret == FMPR_RESULT_EXACT) { fmpr_set(err, err_in); } else { fmpr_t t; fmpr_init(t); fmpr_set_error_result(t, result, rret); fmpr_add(err, err_in, t, prec, rnd); fmpr_clear(t); } } void fmpr_print(const fmpr_t x); void fmpr_printd(const fmpr_t x, slong digits); static __inline__ void fmpr_mul_2exp_si(fmpr_t y, const fmpr_t x, slong e) { if (e == 0 || fmpr_is_special(x)) { fmpr_set(y, x); } else { fmpz_set(fmpr_manref(y), fmpr_manref(x)); fmpz_add_si_inline(fmpr_expref(y), fmpr_expref(x), e); } } static __inline__ void fmpr_mul_2exp_fmpz(fmpr_t y, const fmpr_t x, const fmpz_t e) { if (e == 0 || fmpr_is_special(x)) { fmpr_set(y, x); } else { fmpz_set(fmpr_manref(y), fmpr_manref(x)); fmpz_add(fmpr_expref(y), fmpr_expref(x), e); } } void fmpr_get_fmpq(fmpq_t y, const fmpr_t x); slong fmpr_set_fmpq(fmpr_t x, const fmpq_t y, slong prec, fmpr_rnd_t rnd); void fmpr_get_fmpz(fmpz_t z, const fmpr_t x, fmpr_rnd_t rnd); slong fmpr_get_si(const fmpr_t x, fmpr_rnd_t rnd); void fmpr_set_fmpz_2exp(fmpr_t x, const fmpz_t man, const fmpz_t exp); void fmpr_get_fmpz_2exp(fmpz_t man, fmpz_t exp, const fmpr_t x); int fmpr_get_fmpz_fixed_fmpz(fmpz_t y, const fmpr_t x, const fmpz_t e); int fmpr_get_fmpz_fixed_si(fmpz_t y, const fmpr_t x, slong e); static __inline__ void fmpr_set_si_2exp_si(fmpr_t x, slong man, slong exp) { fmpr_set_si(x, man); fmpr_mul_2exp_si(x, x, exp); } static __inline__ void fmpr_set_ui_2exp_si(fmpr_t x, ulong man, slong exp) { fmpr_set_ui(x, man); fmpr_mul_2exp_si(x, x, exp); } int fmpr_cmp_2exp_si(const fmpr_t x, slong e); int fmpr_cmpabs_2exp_si(const fmpr_t x, slong e); static __inline__ void fmpr_min(fmpr_t z, const fmpr_t a, const fmpr_t b) { if (fmpr_cmp(a, b) <= 0) fmpr_set(z, a); else fmpr_set(z, b); } static __inline__ void fmpr_max(fmpr_t z, const fmpr_t a, const fmpr_t b) { if (fmpr_cmp(a, b) > 0) fmpr_set(z, a); else fmpr_set(z, b); } static __inline__ slong fmpr_bits(const fmpr_t x) { if (fmpr_is_special(x)) return 0; else return fmpz_bits(fmpr_manref(x)); } static __inline__ int fmpr_is_int(const fmpr_t x) { if (fmpr_is_special(x)) return fmpr_is_zero(x); else return fmpz_sgn(fmpr_expref(x)) >= 0; } static __inline__ int fmpr_is_int_2exp_si(const fmpr_t x, slong e) { if (fmpr_is_special(x)) return fmpr_is_zero(x); else return fmpz_cmp_si(fmpr_expref(x), e) >= 0; } #define CALL_MPFR_FUNC(r, func, y, x, prec, rnd) \ do { \ mpfr_t __t, __u; \ mpfr_rnd_t __rnd; \ __rnd = rnd_to_mpfr(rnd); \ mpfr_init2(__t, 2 + fmpz_bits(fmpr_manref(x))); \ mpfr_init2(__u, FLINT_MAX(2, prec)); \ mpfr_set_emin(MPFR_EMIN_MIN); \ mpfr_set_emax(MPFR_EMAX_MAX); \ fmpr_get_mpfr(__t, x, MPFR_RNDD); \ r = func(__u, __t, __rnd); \ if (mpfr_overflow_p() || mpfr_underflow_p()) \ { \ flint_printf("exception: mpfr overflow\n"); \ flint_abort(); \ } \ fmpr_set_mpfr(y, __u); \ if (r == 0) \ r = FMPR_RESULT_EXACT; \ else \ r = prec - fmpz_bits(fmpr_manref(y)); \ mpfr_clear(__t); \ mpfr_clear(__u); \ } while (0); #define CALL_MPFR_FUNC_K(r, func, y, x, k, prec, rnd) \ do { \ mpfr_t __t, __u; \ mpfr_rnd_t __rnd; \ __rnd = rnd_to_mpfr(rnd); \ mpfr_init2(__t, 2 + fmpz_bits(fmpr_manref(x))); \ mpfr_init2(__u, FLINT_MAX(2, prec)); \ mpfr_set_emin(MPFR_EMIN_MIN); \ mpfr_set_emax(MPFR_EMAX_MAX); \ fmpr_get_mpfr(__t, x, MPFR_RNDD); \ r = func(__u, __t, k, __rnd); \ if (mpfr_overflow_p() || mpfr_underflow_p()) \ { \ flint_printf("exception: mpfr overflow\n"); \ flint_abort(); \ } \ fmpr_set_mpfr(y, __u); \ if (r == 0) \ r = FMPR_RESULT_EXACT; \ else \ r = prec - fmpz_bits(fmpr_manref(y)); \ mpfr_clear(__t); \ mpfr_clear(__u); \ } while (0); #define CALL_MPFR_FUNC_2X1(r1, r2, func, y1, y2, x, prec, rnd) \ do { \ mpfr_t __t, __u, __v; \ mpfr_rnd_t __rnd; \ __rnd = rnd_to_mpfr(rnd); \ mpfr_init2(__t, 2 + fmpz_bits(fmpr_manref(x))); \ mpfr_init2(__u, FLINT_MAX(2, prec)); \ mpfr_init2(__v, FLINT_MAX(2, prec)); \ mpfr_set_emin(MPFR_EMIN_MIN); \ mpfr_set_emax(MPFR_EMAX_MAX); \ fmpr_get_mpfr(__t, x, MPFR_RNDD); \ func(__u, __v, __t, __rnd); \ if (mpfr_overflow_p() || mpfr_underflow_p()) \ { \ flint_printf("exception: mpfr overflow\n"); \ flint_abort(); \ } \ fmpr_set_mpfr(y1, __u); \ r1 = prec - fmpz_bits(fmpr_manref(y1)); \ fmpr_set_mpfr(y2, __v); \ r2 = prec - fmpz_bits(fmpr_manref(y2)); \ mpfr_clear(__t); \ mpfr_clear(__u); \ mpfr_clear(__v); \ } while (0); void fmpr_pow_sloppy_fmpz(fmpr_t y, const fmpr_t b, const fmpz_t e, slong prec, fmpr_rnd_t rnd); void fmpr_pow_sloppy_ui(fmpr_t y, const fmpr_t b, ulong e, slong prec, fmpr_rnd_t rnd); void fmpr_pow_sloppy_si(fmpr_t y, const fmpr_t b, slong e, slong prec, fmpr_rnd_t rnd); /* vector functions */ static __inline__ fmpr_ptr _fmpr_vec_init(slong n) { slong i; fmpr_ptr v = (fmpr_ptr) flint_malloc(sizeof(fmpr_struct) * n); for (i = 0; i < n; i++) fmpr_init(v + i); return v; } static __inline__ void _fmpr_vec_clear(fmpr_ptr v, slong n) { slong i; for (i = 0; i < n; i++) fmpr_clear(v + i); flint_free(v); } #ifdef __cplusplus } #endif #endif