int arf_add(arf_ptr z, arf_srcptr x, arf_srcptr y, slong prec, arf_rnd_t rnd) { mp_size_t xn, yn; mp_srcptr xptr, yptr; slong shift; if (arf_is_special(x) || arf_is_special(y)) { return arf_add_special(z, x, y, prec, rnd); } shift = _fmpz_sub_small(ARF_EXPREF(x), ARF_EXPREF(y)); if (shift < 0) { arf_srcptr __t; __t = x; x = y; y = __t; shift = -shift; } ARF_GET_MPN_READONLY(xptr, xn, x); ARF_GET_MPN_READONLY(yptr, yn, y); return _arf_add_mpn(z, xptr, xn, ARF_SGNBIT(x), ARF_EXPREF(x), yptr, yn, ARF_SGNBIT(y), shift, prec, rnd); }
int arf_equal(const arf_t x, const arf_t y) { mp_size_t n; if (x == y) return 1; if (ARF_XSIZE(x) != ARF_XSIZE(y)) return 0; if (!fmpz_equal(ARF_EXPREF(x), ARF_EXPREF(y))) return 0; n = ARF_SIZE(x); if (n == 0) return 1; if (n == 1) return ARF_NOPTR_D(x)[0] == ARF_NOPTR_D(y)[0]; if (n == 2) return (ARF_NOPTR_D(x)[0] == ARF_NOPTR_D(y)[0] && ARF_NOPTR_D(x)[1] == ARF_NOPTR_D(y)[1]); return mpn_cmp(ARF_PTR_D(x), ARF_PTR_D(y), n) == 0; }
int _arf_are_close(const arf_t x, const arf_t y, long prec) { fmpz_t xb, yb; fmpz_t delta; int result; fmpz_init(xb); fmpz_init(yb); fmpz_init(delta); arf_bot(xb, x); arf_bot(yb, y); if (fmpz_cmp(ARF_EXPREF(x), ARF_EXPREF(y)) >= 0) fmpz_sub(delta, xb, ARF_EXPREF(y)); else fmpz_sub(delta, yb, ARF_EXPREF(x)); fmpz_sub_ui(delta, delta, 64); result = (fmpz_cmp_ui(delta, prec) < 0); fmpz_clear(xb); fmpz_clear(yb); fmpz_clear(delta); return result; }
int arf_set_round(arf_t y, const arf_t x, slong prec, arf_rnd_t rnd) { if (arf_is_special(x)) { arf_set(y, x); return 0; } else { int inexact; slong fix; mp_size_t xn; mp_srcptr xptr; if (y == x) { mp_ptr xtmp; TMP_INIT; ARF_GET_MPN_READONLY(xptr, xn, x); /* exact */ if (xn * FLINT_BITS <= prec) return 0; if ((xn - 1) * FLINT_BITS < prec) { /* exact */ if ((xptr[0] << (prec - (xn-1) * FLINT_BITS)) == 0) return 0; } /* inexact */ TMP_START; xtmp = TMP_ALLOC(xn * sizeof(mp_limb_t)); flint_mpn_copyi(xtmp, xptr, xn); inexact = _arf_set_round_mpn(y, &fix, xtmp, xn, ARF_SGNBIT(x), prec, rnd); _fmpz_add_fast(ARF_EXPREF(y), ARF_EXPREF(x), fix); TMP_END; return inexact; } else { ARF_GET_MPN_READONLY(xptr, xn, x); inexact = _arf_set_round_mpn(y, &fix, xptr, xn, ARF_SGNBIT(x), prec, rnd); _fmpz_add_fast(ARF_EXPREF(y), ARF_EXPREF(x), fix); return inexact; } } }
int arf_sub_si(arf_ptr z, arf_srcptr x, slong y, slong prec, arf_rnd_t rnd) { mp_size_t xn, yn; mp_srcptr xptr, yptr; mp_limb_t ytmp; int xsgnbit, ysgnbit; fmpz yexp; slong shift; if (y == 0) { return arf_set_round(z, x, prec, rnd); } else if (arf_is_special(x)) { if (arf_is_zero(x)) { arf_set_si(z, y); return arf_neg_round(z, z, prec, rnd); } else { arf_set(z, x); return 0; } } ysgnbit = (y < 0); if (ysgnbit) ytmp = -y; else ytmp = y; yptr = &ytmp; yn = 1; yexp = FLINT_BITS; ysgnbit ^= 1; shift = _fmpz_sub_small(ARF_EXPREF(x), &yexp); xsgnbit = ARF_SGNBIT(x); ARF_GET_MPN_READONLY(xptr, xn, x); if (shift >= 0) return _arf_add_mpn(z, xptr, xn, xsgnbit, ARF_EXPREF(x), yptr, yn, ysgnbit, shift, prec, rnd); else return _arf_add_mpn(z, yptr, yn, ysgnbit, &yexp, xptr, xn, xsgnbit, -shift, prec, rnd); }
int _arf_add_eps(arf_t s, const arf_t x, int sgn, long prec, arf_rnd_t rnd) { arf_t t; long bits; bits = arf_bits(x); if (bits == 0) { printf("_arf_add_eps\n"); abort(); } bits = FLINT_MAX(bits, prec) + 10; arf_init(t); arf_set_si(t, sgn); arf_mul_2exp_fmpz(t, t, ARF_EXPREF(x)); arf_mul_2exp_si(t, t, -bits); arf_add(s, x, t, prec, rnd); arf_clear(t); return 1; }
void arb_log_arf_huge(arb_t z, const arf_t x, slong prec) { arf_t t; arb_t c; fmpz_t exp; slong wp; arf_init(t); arb_init(c); fmpz_init(exp); fmpz_neg(exp, ARF_EXPREF(x)); arf_mul_2exp_fmpz(t, x, exp); wp = prec + 4 - fmpz_bits(exp); wp = FLINT_MAX(wp, 4); arb_log_arf(z, t, wp); arb_const_log2(c, prec + 4); arb_submul_fmpz(z, c, exp, prec); arf_clear(t); arb_clear(c); fmpz_clear(exp); }
int arf_add_fmpz_2exp(arf_ptr z, arf_srcptr x, const fmpz_t y, const fmpz_t exp, slong prec, arf_rnd_t rnd) { mp_size_t xn, yn; mp_srcptr xptr, yptr; mp_limb_t ytmp; int xsgnbit, ysgnbit, inexact; fmpz_t yexp; slong shift; if (fmpz_is_zero(y)) { return arf_set_round(z, x, prec, rnd); } else if (arf_is_special(x)) { if (arf_is_zero(x)) { inexact = arf_set_round_fmpz(z, y, prec, rnd); arf_mul_2exp_fmpz(z, z, exp); return inexact; } else { arf_set(z, x); return 0; } } FMPZ_GET_MPN_READONLY(ysgnbit, yn, yptr, ytmp, *y) fmpz_init(yexp); fmpz_add_ui(yexp, exp, yn * FLINT_BITS); shift = _fmpz_sub_small(ARF_EXPREF(x), yexp); xsgnbit = ARF_SGNBIT(x); ARF_GET_MPN_READONLY(xptr, xn, x); if (shift >= 0) inexact = _arf_add_mpn(z, xptr, xn, xsgnbit, ARF_EXPREF(x), yptr, yn, ysgnbit, shift, prec, rnd); else inexact = _arf_add_mpn(z, yptr, yn, ysgnbit, yexp, xptr, xn, xsgnbit, -shift, prec, rnd); fmpz_clear(yexp); return inexact; }
int arf_sub_fmpz(arf_ptr z, arf_srcptr x, const fmpz_t y, slong prec, arf_rnd_t rnd) { mp_size_t xn, yn; mp_srcptr xptr, yptr; mp_limb_t ytmp; int xsgnbit, ysgnbit; fmpz yexp; slong shift; if (fmpz_is_zero(y)) { return arf_set_round(z, x, prec, rnd); } else if (arf_is_special(x)) { if (arf_is_zero(x)) { arf_set_fmpz(z, y); return arf_neg_round(z, z, prec, rnd); } else { arf_set(z, x); return 0; } } FMPZ_GET_MPN_READONLY(ysgnbit, yn, yptr, ytmp, *y) yexp = yn * FLINT_BITS; shift = _fmpz_sub_small(ARF_EXPREF(x), &yexp); ysgnbit ^= 1; xsgnbit = ARF_SGNBIT(x); ARF_GET_MPN_READONLY(xptr, xn, x); if (shift >= 0) return _arf_add_mpn(z, xptr, xn, xsgnbit, ARF_EXPREF(x), yptr, yn, ysgnbit, shift, prec, rnd); else return _arf_add_mpn(z, yptr, yn, ysgnbit, &yexp, xptr, xn, xsgnbit, -shift, prec, rnd); }
/* atan(x) = x + eps, |eps| < x^3*/ void arb_atan_eps(arb_t z, const arf_t x, slong prec) { fmpz_t mag; fmpz_init(mag); fmpz_mul_ui(mag, ARF_EXPREF(x), 3); arb_set_arf(z, x); arb_set_round(z, z, prec); arb_add_error_2exp_fmpz(z, mag); fmpz_clear(mag); }
void arf_set_fmpr(arf_t y, const fmpr_t x) { if (fmpr_is_special(x)) { if (fmpr_is_zero(x)) arf_zero(y); else if (fmpr_is_pos_inf(x)) arf_pos_inf(y); else if (fmpr_is_neg_inf(x)) arf_neg_inf(y); else arf_nan(y); } else { arf_set_fmpz(y, fmpr_manref(x)); fmpz_add_inline(ARF_EXPREF(y), ARF_EXPREF(y), fmpr_expref(x)); } }
int arf_cmpabs(const arf_t x, const arf_t y) { int ec, mc; mp_size_t xn, yn; mp_srcptr xp, yp; if (arf_is_special(x) || arf_is_special(y)) { if (arf_equal(x, y)) return 0; if (arf_is_nan(x) || arf_is_nan(y)) return 0; if (arf_is_zero(x)) return -1; if (arf_is_zero(y)) return 1; if (arf_is_inf(x)) return arf_is_inf(y) ? 0 : 1; if (arf_is_inf(y)) return -1; return -1; } ec = fmpz_cmp(ARF_EXPREF(x), ARF_EXPREF(y)); if (ec != 0) return (ec < 0) ? -1 : 1; ARF_GET_MPN_READONLY(xp, xn, x); ARF_GET_MPN_READONLY(yp, yn, y); if (xn >= yn) mc = mpn_cmp(xp + xn - yn, yp, yn); else mc = mpn_cmp(xp, yp + yn - xn, xn); if (mc != 0) return (mc < 0) ? -1 : 1; if (xn != yn) return (xn < yn) ? -1 : 1; return 0; }
int arf_cmp_2exp_si(const arf_t x, long e) { if (arf_is_special(x)) { if (arf_is_zero(x)) return -1; if (arf_is_pos_inf(x)) return 1; if (arf_is_neg_inf(x)) return -1; return 0; } if (ARF_SGNBIT(x)) return -1; /* Fast path. */ if (!COEFF_IS_MPZ(ARF_EXP(x))) { if (ARF_IS_POW2(x) && (ARF_EXP(x) - 1 == e)) return 0; else return (ARF_EXP(x) <= e) ? -1 : 1; } if (ARF_IS_POW2(x)) { fmpz_t t; fmpz_init(t); fmpz_one(t); fmpz_add_si(t, t, e); if (fmpz_equal(ARF_EXPREF(x), t)) { fmpz_clear(t); return 0; } fmpz_clear(t); } return (fmpz_cmp_si(ARF_EXPREF(x), e) <= 0) ? -1 : 1; }
int arf_sub(arf_ptr z, arf_srcptr x, arf_srcptr y, slong prec, arf_rnd_t rnd) { mp_size_t xn, yn; mp_srcptr xptr, yptr; slong shift; if (arf_is_special(x) || arf_is_special(y)) { return arf_sub_special(z, x, y, prec, rnd); } shift = _fmpz_sub_small(ARF_EXPREF(x), ARF_EXPREF(y)); ARF_GET_MPN_READONLY(xptr, xn, x); ARF_GET_MPN_READONLY(yptr, yn, y); if (shift >= 0) return _arf_add_mpn(z, xptr, xn, ARF_SGNBIT(x), ARF_EXPREF(x), yptr, yn, ARF_SGNBIT(y) ^ 1, shift, prec, rnd); else return _arf_add_mpn(z, yptr, yn, ARF_SGNBIT(y) ^ 1, ARF_EXPREF(y), xptr, xn, ARF_SGNBIT(x), -shift, prec, rnd); }
void _arb_poly_get_scale(fmpz_t scale, arb_srcptr x, slong xlen, arb_srcptr y, slong ylen) { slong xa, xb, ya, yb, den; fmpz_zero(scale); /* ignore zeros (and infs/nans!); find the first and last finite nonzero entries to determine the scale */ xa = 0; xb = xlen - 1; while (xa < xlen && arf_is_special(arb_midref(x + xa))) xa++; while (xb > xa && arf_is_special(arb_midref(x + xb))) xb--; ya = 0; yb = ylen - 1; while (ya < ylen && arf_is_special(arb_midref(y + ya))) ya++; while (yb > ya && arf_is_special(arb_midref(y + yb))) yb--; /* compute average of exponent differences, weighted by the lengths */ if (xa <= xb && ya <= yb && (xa < xb || ya < yb)) { fmpz_add(scale, scale, ARF_EXPREF(arb_midref(x + xb))); fmpz_sub(scale, scale, ARF_EXPREF(arb_midref(x + xa))); fmpz_add(scale, scale, ARF_EXPREF(arb_midref(y + yb))); fmpz_sub(scale, scale, ARF_EXPREF(arb_midref(y + ya))); den = (xb - xa) + (yb - ya); /* scale = floor(scale / den + 1/2) = floor((2 scale + den) / (2 den)) */ fmpz_mul_2exp(scale, scale, 1); fmpz_add_ui(scale, scale, den); fmpz_fdiv_q_ui(scale, scale, 2 * den); } }
/* requires x != 1 */ static void arf_log_via_mpfr(arf_t z, const arf_t x, slong prec, arf_rnd_t rnd) { mpfr_t xf, zf; mp_ptr zptr, tmp; mp_srcptr xptr; mp_size_t xn, zn, val; TMP_INIT; TMP_START; zn = (prec + FLINT_BITS - 1) / FLINT_BITS; tmp = TMP_ALLOC(zn * sizeof(mp_limb_t)); ARF_GET_MPN_READONLY(xptr, xn, x); xf->_mpfr_d = (mp_ptr) xptr; xf->_mpfr_prec = xn * FLINT_BITS; xf->_mpfr_sign = ARF_SGNBIT(x) ? -1 : 1; xf->_mpfr_exp = ARF_EXP(x); zf->_mpfr_d = tmp; zf->_mpfr_prec = prec; zf->_mpfr_sign = 1; zf->_mpfr_exp = 0; mpfr_set_emin(MPFR_EMIN_MIN); mpfr_set_emax(MPFR_EMAX_MAX); mpfr_log(zf, xf, arf_rnd_to_mpfr(rnd)); val = 0; while (tmp[val] == 0) val++; ARF_GET_MPN_WRITE(zptr, zn - val, z); flint_mpn_copyi(zptr, tmp + val, zn - val); if (zf->_mpfr_sign < 0) ARF_NEG(z); fmpz_set_si(ARF_EXPREF(z), zf->_mpfr_exp); TMP_END; }
void arb_const_log2(arb_t res, slong prec) { if (prec < ARB_LOG_TAB2_LIMBS * FLINT_BITS - 16) { slong exp; /* just reading the table is known to give the correct rounding */ _arf_set_round_mpn(arb_midref(res), &exp, arb_log_log2_tab, ARB_LOG_TAB2_LIMBS, 0, prec, ARF_RND_NEAR); _fmpz_set_si_small(ARF_EXPREF(arb_midref(res)), exp); /* 1/2 ulp error */ _fmpz_set_si_small(MAG_EXPREF(arb_radref(res)), exp - prec); MAG_MAN(arb_radref(res)) = MAG_ONE_HALF; } else { arb_const_log2_hypgeom(res, prec); } }
/* atan(x) = pi/2 - eps, eps < 1/x <= 2^(1-mag) */ void arb_atan_inf_eps(arb_t z, const arf_t x, slong prec) { fmpz_t mag; fmpz_init(mag); fmpz_neg(mag, ARF_EXPREF(x)); fmpz_add_ui(mag, mag, 1); if (arf_sgn(x) > 0) { arb_const_pi(z, prec); } else { arb_const_pi(z, prec); arb_neg(z, z); } arb_mul_2exp_si(z, z, -1); arb_add_error_2exp_fmpz(z, mag); fmpz_clear(mag); }
static __inline__ void _arb_vec_get_fmpz_2exp_blocks(fmpz * coeffs, fmpz * exps, slong * blocks, const fmpz_t scale, arb_srcptr x, slong len, slong prec) { fmpz_t top, bot, t, b, v, block_top, block_bot; slong i, j, s, block, bits, maxheight; int in_zero; fmpz_init(top); fmpz_init(bot); fmpz_init(t); fmpz_init(b); fmpz_init(v); fmpz_init(block_top); fmpz_init(block_bot); blocks[0] = 0; block = 0; in_zero = 1; if (prec == ARF_PREC_EXACT) maxheight = ARF_PREC_EXACT; else maxheight = ALPHA * prec + BETA; for (i = 0; i < len; i++) { bits = arf_bits(arb_midref(x + i)); /* Skip (must be zero, since we assume there are no Infs/NaNs). */ if (bits == 0) continue; /* Bottom and top exponent of current number */ fmpz_set(top, ARF_EXPREF(arb_midref(x + i))); fmpz_submul_ui(top, scale, i); fmpz_sub_ui(bot, top, bits); /* Extend current block. */ if (in_zero) { fmpz_swap(block_top, top); fmpz_swap(block_bot, bot); } else { fmpz_max(t, top, block_top); fmpz_min(b, bot, block_bot); fmpz_sub(v, t, b); /* extend current block */ if (fmpz_cmp_ui(v, maxheight) < 0) { fmpz_swap(block_top, t); fmpz_swap(block_bot, b); } else /* start new block */ { /* write exponent for previous block */ fmpz_set(exps + block, block_bot); block++; blocks[block] = i; fmpz_swap(block_top, top); fmpz_swap(block_bot, bot); } } in_zero = 0; } /* write exponent for last block */ fmpz_set(exps + block, block_bot); /* end marker */ blocks[block + 1] = len; /* write the block data */ for (i = 0; blocks[i] != len; i++) { for (j = blocks[i]; j < blocks[i + 1]; j++) { if (arf_is_special(arb_midref(x + j))) { fmpz_zero(coeffs + j); } else { /* TODO: make this a single operation */ arf_get_fmpz_2exp(coeffs + j, bot, arb_midref(x + j)); fmpz_mul_ui(t, scale, j); fmpz_sub(t, bot, t); s = _fmpz_sub_small(t, exps + i); if (s < 0) abort(); /* Bug catcher */ fmpz_mul_2exp(coeffs + j, coeffs + j, s); } } } fmpz_clear(top); fmpz_clear(bot); fmpz_clear(t); fmpz_clear(b); fmpz_clear(v); fmpz_clear(block_top); fmpz_clear(block_bot); }
void arb_mul_naive(arb_t z, const arb_t x, const arb_t y, slong prec) { arf_t zm_exact, zm_rounded, zr, t, u; arf_init(zm_exact); arf_init(zm_rounded); arf_init(zr); arf_init(t); arf_init(u); arf_mul(zm_exact, arb_midref(x), arb_midref(y), ARF_PREC_EXACT, ARF_RND_DOWN); arf_set_round(zm_rounded, zm_exact, prec, ARB_RND); /* rounding error */ if (arf_equal(zm_exact, zm_rounded)) { arf_zero(zr); } else { fmpz_t e; fmpz_init(e); /* more accurate, but not what we are testing arf_sub(zr, zm_exact, zm_rounded, MAG_BITS, ARF_RND_UP); arf_abs(zr, zr); */ fmpz_sub_ui(e, ARF_EXPREF(zm_rounded), prec); arf_one(zr); arf_mul_2exp_fmpz(zr, zr, e); fmpz_clear(e); } /* propagated error */ if (!arb_is_exact(x)) { arf_set_mag(t, arb_radref(x)); arf_abs(u, arb_midref(y)); arf_addmul(zr, t, u, MAG_BITS, ARF_RND_UP); } if (!arb_is_exact(y)) { arf_set_mag(t, arb_radref(y)); arf_abs(u, arb_midref(x)); arf_addmul(zr, t, u, MAG_BITS, ARF_RND_UP); } if (!arb_is_exact(x) && !arb_is_exact(y)) { arf_set_mag(t, arb_radref(x)); arf_set_mag(u, arb_radref(y)); arf_addmul(zr, t, u, MAG_BITS, ARF_RND_UP); } arf_set(arb_midref(z), zm_rounded); arf_get_mag(arb_radref(z), zr); arf_clear(zm_exact); arf_clear(zm_rounded); arf_clear(zr); arf_clear(t); arf_clear(u); }
int main() { slong iter, iter2; flint_rand_t state; flint_printf("addmul_si...."); fflush(stdout); flint_randinit(state); for (iter = 0; iter < 1000 * arb_test_multiplier(); iter++) { arf_t x, z, v; slong y; slong prec, r1, r2; arf_rnd_t rnd; arf_init(x); arf_init(z); arf_init(v); for (iter2 = 0; iter2 < 100; iter2++) { arf_randtest_special(x, state, 2000, 100); y = z_randtest(state); arf_randtest_special(z, state, 2000, 100); arf_set(v, z); prec = 2 + n_randint(state, 2000); if (n_randint(state, 10) == 0 && fmpz_bits(ARF_EXPREF(x)) < 10 && fmpz_bits(ARF_EXPREF(z)) < 10) { prec = ARF_PREC_EXACT; } switch (n_randint(state, 5)) { case 0: rnd = ARF_RND_DOWN; break; case 1: rnd = ARF_RND_UP; break; case 2: rnd = ARF_RND_FLOOR; break; case 3: rnd = ARF_RND_CEIL; break; default: rnd = ARF_RND_NEAR; break; } switch (n_randint(state, 2)) { case 0: r1 = arf_addmul_si(z, x, y, prec, rnd); r2 = arf_addmul_si_naive(v, x, y, prec, rnd); if (!arf_equal(z, v) || r1 != r2) { flint_printf("FAIL!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = %wd", y); flint_printf("\n\n"); flint_printf("z = "); arf_debug(z); flint_printf("\n\n"); flint_printf("v = "); arf_debug(v); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); abort(); } break; default: r2 = arf_addmul_si_naive(v, v, y, prec, rnd); r1 = arf_addmul_si(z, z, y, prec, rnd); if (!arf_equal(v, z) || r1 != r2) { flint_printf("FAIL (aliasing)!\n"); flint_printf("prec = %wd, rnd = %d\n\n", prec, rnd); flint_printf("y = %wd", y); flint_printf("\n\n"); flint_printf("v = "); arf_print(v); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("r1 = %wd, r2 = %wd\n", r1, r2); abort(); } break; } } arf_clear(x); arf_clear(z); arf_clear(v); } flint_randclear(state); flint_cleanup(); flint_printf("PASS\n"); return EXIT_SUCCESS; }
int arf_submul_mpz(arf_ptr z, arf_srcptr x, const mpz_t y, slong prec, arf_rnd_t rnd) { mp_size_t xn, yn, zn, tn, alloc; mp_srcptr xptr, yptr, zptr; mp_ptr tptr, tptr2; fmpz_t texp, yexp; slong shift; int tsgnbit, ysgnbit, inexact; ARF_MUL_TMP_DECL yn = FLINT_ABS(y->_mp_size); if (arf_is_special(x) || yn == 0 || arf_is_special(z)) { if (arf_is_zero(z)) { /* TODO: make more efficient */ arf_mul_mpz(z, x, y, ARF_PREC_EXACT, rnd); return arf_neg_round(z, z, prec, rnd); } else if (arf_is_finite(x)) { return arf_set_round(z, z, prec, rnd); } else { /* todo: speed up */ arf_t t; arf_init(t); arf_mul_mpz(t, x, y, ARF_PREC_EXACT, ARF_RND_DOWN); inexact = arf_sub(z, z, t, prec, rnd); arf_clear(t); return inexact; } } ARF_GET_MPN_READONLY(xptr, xn, x); yptr = y->_mp_d; ysgnbit = (y->_mp_size > 0); *yexp = yn * FLINT_BITS; ARF_GET_MPN_READONLY(zptr, zn, z); fmpz_init(texp); tsgnbit = ARF_SGNBIT(x) ^ ysgnbit; alloc = tn = xn + yn; ARF_MUL_TMP_ALLOC(tptr2, alloc) tptr = tptr2; ARF_MPN_MUL(tptr, xptr, xn, yptr, yn); shift = (tptr[tn - 1] == 0) * FLINT_BITS; tn -= (tptr[tn - 1] == 0); _fmpz_add2_fast(texp, ARF_EXPREF(x), yexp, -shift); shift = _fmpz_sub_small(ARF_EXPREF(z), texp); if (shift >= 0) inexact = _arf_add_mpn(z, zptr, zn, ARF_SGNBIT(z), ARF_EXPREF(z), tptr, tn, tsgnbit, shift, prec, rnd); else inexact = _arf_add_mpn(z, tptr, tn, tsgnbit, texp, zptr, zn, ARF_SGNBIT(z), -shift, prec, rnd); ARF_MUL_TMP_FREE(tptr2, alloc) fmpz_clear(texp); return inexact; }
int arf_submul(arf_ptr z, arf_srcptr x, arf_srcptr y, slong prec, arf_rnd_t rnd) { mp_size_t xn, yn, zn, tn, alloc; mp_srcptr xptr, yptr, zptr; mp_ptr tptr, tptr2; fmpz_t texp; slong shift; int tsgnbit, inexact; ARF_MUL_TMP_DECL if (arf_is_special(x) || arf_is_special(y) || arf_is_special(z)) { if (arf_is_zero(z)) { return arf_neg_mul(z, x, y, prec, rnd); } else if (arf_is_finite(x) && arf_is_finite(y)) { return arf_set_round(z, z, prec, rnd); } else { /* todo: speed up */ arf_t t; arf_init(t); arf_mul(t, x, y, ARF_PREC_EXACT, ARF_RND_DOWN); inexact = arf_sub(z, z, t, prec, rnd); arf_clear(t); return inexact; } } tsgnbit = ARF_SGNBIT(x) ^ ARF_SGNBIT(y) ^ 1; ARF_GET_MPN_READONLY(xptr, xn, x); ARF_GET_MPN_READONLY(yptr, yn, y); ARF_GET_MPN_READONLY(zptr, zn, z); fmpz_init(texp); _fmpz_add2_fast(texp, ARF_EXPREF(x), ARF_EXPREF(y), 0); shift = _fmpz_sub_small(ARF_EXPREF(z), texp); alloc = tn = xn + yn; ARF_MUL_TMP_ALLOC(tptr2, alloc) tptr = tptr2; ARF_MPN_MUL(tptr, xptr, xn, yptr, yn); tn -= (tptr[0] == 0); tptr += (tptr[0] == 0); if (shift >= 0) inexact = _arf_add_mpn(z, zptr, zn, ARF_SGNBIT(z), ARF_EXPREF(z), tptr, tn, tsgnbit, shift, prec, rnd); else inexact = _arf_add_mpn(z, tptr, tn, tsgnbit, texp, zptr, zn, ARF_SGNBIT(z), -shift, prec, rnd); ARF_MUL_TMP_FREE(tptr2, alloc) fmpz_clear(texp); return inexact; }
void acb_hypgeom_airy(acb_t ai, acb_t aip, acb_t bi, acb_t bip, const acb_t z, slong prec) { arf_srcptr re, im; double x, y, t, zmag, z15, term_est, airy_est, abstol; slong n, wp; if (!acb_is_finite(z)) { if (ai != NULL) acb_indeterminate(ai); if (aip != NULL) acb_indeterminate(aip); if (bi != NULL) acb_indeterminate(bi); if (bip != NULL) acb_indeterminate(bip); return; } re = arb_midref(acb_realref(z)); im = arb_midref(acb_imagref(z)); wp = prec * 1.03 + 15; /* tiny input -- use direct method and pick n without underflowing */ if (arf_cmpabs_2exp_si(re, -64) < 0 && arf_cmpabs_2exp_si(im, -64) < 0) { if (arf_cmpabs_2exp_si(re, -wp) < 0 && arf_cmpabs_2exp_si(im, -wp) < 0) { n = 1; /* very tiny input */ } else { if (arf_cmpabs(re, im) > 0) zmag = fmpz_get_d(ARF_EXPREF(re)); else zmag = fmpz_get_d(ARF_EXPREF(im)); zmag = (zmag + 1) * (1.0 / LOG2); n = wp / (-zmag) + 1; } acb_hypgeom_airy_direct(ai, aip, bi, bip, z, n, wp); } /* huge input -- use asymptotics and pick n without overflowing */ else if ((arf_cmpabs_2exp_si(re, 64) > 0 || arf_cmpabs_2exp_si(im, 64) > 0)) { if (arf_cmpabs_2exp_si(re, prec) > 0 || arf_cmpabs_2exp_si(im, prec) > 0) { n = 1; /* very huge input */ } else { x = fmpz_get_d(ARF_EXPREF(re)); y = fmpz_get_d(ARF_EXPREF(im)); zmag = (FLINT_MAX(x, y) - 2) * (1.0 / LOG2); n = asymp_pick_terms(wp, zmag); n = FLINT_MAX(n, 1); } acb_hypgeom_airy_asymp(ai, aip, bi, bip, z, n, wp); } else /* moderate input */ { x = arf_get_d(re, ARF_RND_DOWN); y = arf_get_d(im, ARF_RND_DOWN); zmag = sqrt(x * x + y * y); z15 = zmag * sqrt(zmag); if (zmag >= 4.0 && (n = asymp_pick_terms(wp, log(zmag))) != -1) { acb_hypgeom_airy_asymp(ai, aip, bi, bip, z, n, wp); } else if (zmag <= 1.5) { t = 3 * (wp * LOG2) / (2 * z15 * EXP1); t = (wp * LOG2) / (2 * d_lambertw(t)); n = FLINT_MAX(t + 1, 2); acb_hypgeom_airy_direct(ai, aip, bi, bip, z, n, wp); } else { /* estimate largest term: log2(exp(2(z^3/9)^(1/2))) */ term_est = 0.96179669392597560491 * z15; /* estimate the smaller of Ai and Bi */ airy_est = estimate_airy(x, y, (ai != NULL || aip != NULL)); /* estimate absolute tolerance and necessary working precision */ abstol = airy_est - wp; wp = wp + term_est - airy_est; wp = FLINT_MAX(wp, 10); t = 3 * (-abstol * LOG2) / (2 * z15 * EXP1); t = (-abstol * LOG2) / (2 * d_lambertw(t)); n = FLINT_MAX(t + 1, 2); if (acb_is_exact(z)) acb_hypgeom_airy_direct(ai, aip, bi, bip, z, n, wp); else acb_hypgeom_airy_direct_prop(ai, aip, bi, bip, z, n, wp); } } if (ai != NULL) acb_set_round(ai, ai, prec); if (aip != NULL) acb_set_round(aip, aip, prec); if (bi != NULL) acb_set_round(bi, bi, prec); if (bip != NULL) acb_set_round(bip, bip, prec); }
void arb_atan_arf(arb_t z, const arf_t x, slong prec) { if (arf_is_special(x)) { if (arf_is_zero(x)) { arb_zero(z); } else if (arf_is_pos_inf(x)) { arb_const_pi(z, prec); arb_mul_2exp_si(z, z, -1); } else if (arf_is_neg_inf(x)) { arb_const_pi(z, prec); arb_mul_2exp_si(z, z, -1); arb_neg(z, z); } else { arb_indeterminate(z); } } else if (COEFF_IS_MPZ(*ARF_EXPREF(x))) { if (fmpz_sgn(ARF_EXPREF(x)) < 0) arb_atan_eps(z, x, prec); else arb_atan_inf_eps(z, x, prec); } else { slong exp, wp, wn, N, r; mp_srcptr xp; mp_size_t xn, tn; mp_ptr tmp, w, t, u; mp_limb_t p1, q1bits, p2, q2bits, error, error2; int negative, inexact, reciprocal; TMP_INIT; exp = ARF_EXP(x); negative = ARF_SGNBIT(x); if (exp < -(prec/2) - 2 || exp > prec + 2) { if (exp < 0) arb_atan_eps(z, x, prec); else arb_atan_inf_eps(z, x, prec); return; } ARF_GET_MPN_READONLY(xp, xn, x); /* Special case: +/- 1 (we require |x| != 1 later on) */ if (exp == 1 && xn == 1 && xp[xn-1] == LIMB_TOP) { arb_const_pi(z, prec); arb_mul_2exp_si(z, z, -2); if (negative) arb_neg(z, z); return; } /* Absolute working precision (NOT rounded to a limb multiple) */ wp = prec - FLINT_MIN(0, exp) + 4; /* Too high precision to use table */ if (wp > ARB_ATAN_TAB2_PREC) { arb_atan_arf_bb(z, x, prec); return; } /* Working precision in limbs */ wn = (wp + FLINT_BITS - 1) / FLINT_BITS; TMP_START; tmp = TMP_ALLOC_LIMBS(4 * wn + 3); w = tmp; /* requires wn+1 limbs */ t = w + wn + 1; /* requires wn+1 limbs */ u = t + wn + 1; /* requires 2wn+1 limbs */ /* ----------------------------------------------------------------- */ /* Convert x or 1/x to a fixed-point number |w| < 1 */ /* ----------------------------------------------------------------- */ if (exp <= 0) /* |x| < 1 */ { reciprocal = 0; /* todo: just zero top */ flint_mpn_zero(w, wn); /* w = x as a fixed-point number */ error = _arf_get_integer_mpn(w, xp, xn, exp + wn * FLINT_BITS); } else /* |x| > 1 */ { slong one_exp, one_limbs, one_bits; mp_ptr one; reciprocal = 1; one_exp = xn * FLINT_BITS + wn * FLINT_BITS - exp; flint_mpn_zero(w, wn); /* 1/x becomes zero */ if (one_exp >= FLINT_BITS - 1) { /* w = 1/x */ one_limbs = one_exp / FLINT_BITS; one_bits = one_exp % FLINT_BITS; if (one_limbs + 1 >= xn) { one = TMP_ALLOC_LIMBS(one_limbs + 1); flint_mpn_zero(one, one_limbs); one[one_limbs] = UWORD(1) << one_bits; /* todo: only zero necessary part */ flint_mpn_zero(w, wn); mpn_tdiv_q(w, one, one_limbs + 1, xp, xn); /* Now w must be < 1 since x > 1 and we rounded down; thus w[wn] must be zero */ } } /* todo: moderate powers of two would be exact... */ error = 1; } /* ----------------------------------------------------------------- */ /* Table-based argument reduction */ /* ----------------------------------------------------------------- */ /* choose p such that p/q <= x < (p+1)/q */ if (wp <= ARB_ATAN_TAB1_PREC) q1bits = ARB_ATAN_TAB1_BITS; else q1bits = ARB_ATAN_TAB21_BITS; p1 = w[wn-1] >> (FLINT_BITS - q1bits); /* atan(w) = atan(p/q) + atan(w2) */ /* where w2 = (q*w-p)/(q+p*w) */ if (p1 != 0) { t[wn] = (UWORD(1) << q1bits) + mpn_mul_1(t, w, wn, p1); flint_mpn_zero(u, wn); u[2 * wn] = mpn_lshift(u + wn, w, wn, q1bits) - p1; mpn_tdiv_q(w, u, 2 * wn + 1, t, wn + 1); error++; /* w2 is computed with 1 ulp error */ } /* Do a second round of argument reduction */ if (wp <= ARB_ATAN_TAB1_PREC) { p2 = 0; } else { q2bits = ARB_ATAN_TAB21_BITS + ARB_ATAN_TAB22_BITS; p2 = w[wn-1] >> (FLINT_BITS - q2bits); if (p2 != 0) { t[wn] = (UWORD(1) << q2bits) + mpn_mul_1(t, w, wn, p2); flint_mpn_zero(u, wn); u[2 * wn] = mpn_lshift(u + wn, w, wn, q2bits) - p2; mpn_tdiv_q(w, u, 2 * wn + 1, t, wn + 1); error++; } } /* |w| <= 2^-r */ r = _arb_mpn_leading_zeros(w, wn); /* N >= (wp-r)/(2r) */ N = (wp - r + (2*r-1)) / (2*r); /* Evaluate Taylor series */ _arb_atan_taylor_rs(t, &error2, w, wn, N, 1); /* Taylor series evaluation error */ error += error2; /* Size of output number */ tn = wn; /* First table lookup */ if (p1 != 0) { if (wp <= ARB_ATAN_TAB1_PREC) mpn_add_n(t, t, arb_atan_tab1[p1] + ARB_ATAN_TAB1_LIMBS - tn, tn); else mpn_add_n(t, t, arb_atan_tab21[p1] + ARB_ATAN_TAB2_LIMBS - tn, tn); error++; } /* Second table lookup */ if (p2 != 0) { mpn_add_n(t, t, arb_atan_tab22[p2] + ARB_ATAN_TAB2_LIMBS - tn, tn); error++; } /* pi/2 - atan(1/x) */ if (reciprocal) { t[tn] = LIMB_ONE - mpn_sub_n(t, arb_atan_pi2_minus_one + ARB_ATAN_TAB2_LIMBS - tn, t, tn); /* result can be >= 1 */ tn += (t[tn] != 0); /* error of pi/2 */ error++; } /* The accumulated arithmetic error */ mag_set_ui_2exp_si(arb_radref(z), error, -wn * FLINT_BITS); /* Truncation error from the Taylor series */ mag_add_ui_2exp_si(arb_radref(z), arb_radref(z), 1, -r*(2*N+1)); /* Set the midpoint */ inexact = _arf_set_mpn_fixed(arb_midref(z), t, tn, wn, negative, prec, ARB_RND); if (inexact) arf_mag_add_ulp(arb_radref(z), arb_radref(z), arb_midref(z), prec); TMP_END; } }
int arf_root(arf_ptr z, arf_srcptr x, ulong k, slong prec, arf_rnd_t rnd) { mp_size_t xn, zn, val; mp_srcptr xptr; mp_ptr tmp, zptr; mpfr_t xf, zf; fmpz_t q, r; int inexact; if (k == 0) { arf_nan(z); return 0; } if (k == 1) return arf_set_round(z, x, prec, rnd); if (k == 2) return arf_sqrt(z, x, prec, rnd); if (arf_is_special(x)) { if (arf_is_neg_inf(x)) arf_nan(z); else arf_set(z, x); return 0; } if (ARF_SGNBIT(x)) { arf_nan(z); return 0; } fmpz_init(q); fmpz_init(r); /* x = m * 2^e where e = qk + r */ /* x^(1/k) = (m * 2^(qk+r))^(1/k) */ /* x^(1/k) = (m * 2^r)^(1/k) * 2^q */ fmpz_set_ui(r, k); fmpz_fdiv_qr(q, r, ARF_EXPREF(x), r); ARF_GET_MPN_READONLY(xptr, xn, x); zn = (prec + FLINT_BITS - 1) / FLINT_BITS; zf->_mpfr_d = tmp = flint_malloc(zn * sizeof(mp_limb_t)); zf->_mpfr_prec = prec; zf->_mpfr_sign = 1; zf->_mpfr_exp = 0; xf->_mpfr_d = (mp_ptr) xptr; xf->_mpfr_prec = xn * FLINT_BITS; xf->_mpfr_sign = 1; xf->_mpfr_exp = fmpz_get_ui(r); inexact = mpfr_root(zf, xf, k, arf_rnd_to_mpfr(rnd)); inexact = (inexact != 0); val = 0; while (tmp[val] == 0) val++; ARF_GET_MPN_WRITE(zptr, zn - val, z); flint_mpn_copyi(zptr, tmp + val, zn - val); fmpz_add_si(ARF_EXPREF(z), q, zf->_mpfr_exp); flint_free(tmp); fmpz_clear(q); fmpz_clear(r); return inexact; }
int main() { long iter, iter2; flint_rand_t state; printf("add_fmpz...."); fflush(stdout); flint_randinit(state); for (iter = 0; iter < 10000; iter++) { arf_t x, z, v; fmpz_t y; long prec, r1, r2; arf_rnd_t rnd; arf_init(x); arf_init(z); arf_init(v); fmpz_init(y); for (iter2 = 0; iter2 < 100; iter2++) { arf_randtest_special(x, state, 2000, 10); fmpz_randtest(y, state, 2000); prec = 2 + n_randint(state, 2000); if (n_randint(state, 10) == 0 && fmpz_bits(ARF_EXPREF(x)) < 10) { prec = ARF_PREC_EXACT; } switch (n_randint(state, 4)) { case 0: rnd = ARF_RND_DOWN; break; case 1: rnd = ARF_RND_UP; break; case 2: rnd = ARF_RND_FLOOR; break; default: rnd = ARF_RND_CEIL; break; } switch (n_randint(state, 2)) { case 0: r1 = arf_add_fmpz(z, x, y, prec, rnd); r2 = arf_add_fmpz_naive(v, x, y, prec, rnd); if (!arf_equal(z, v) || r1 != r2) { printf("FAIL!\n"); printf("prec = %ld, rnd = %d\n\n", prec, rnd); printf("x = "); arf_print(x); printf("\n\n"); printf("y = "); fmpz_print(y); printf("\n\n"); printf("z = "); arf_print(z); printf("\n\n"); printf("v = "); arf_print(v); printf("\n\n"); printf("r1 = %ld, r2 = %ld\n", r1, r2); abort(); } break; default: r2 = arf_add_fmpz_naive(v, x, y, prec, rnd); r1 = arf_add_fmpz(x, x, y, prec, rnd); if (!arf_equal(x, v) || r1 != r2) { printf("FAIL (aliasing)!\n"); printf("prec = %ld, rnd = %d\n\n", prec, rnd); printf("x = "); arf_print(x); printf("\n\n"); printf("y = "); fmpz_print(y); printf("\n\n"); printf("v = "); arf_print(v); printf("\n\n"); printf("r1 = %ld, r2 = %ld\n", r1, r2); abort(); } break; } } arf_clear(x); arf_clear(z); arf_clear(v); fmpz_clear(y); } flint_randclear(state); flint_cleanup(); printf("PASS\n"); return EXIT_SUCCESS; }
int main() { slong iter; flint_rand_t state; flint_printf("set_round...."); fflush(stdout); flint_randinit(state); { arf_t x, y, z; arf_init(x); arf_init(y); arf_init(z); for (iter = 0; iter < 100000 * arb_test_multiplier(); iter++) { slong bits1, bits2; int ret1, ret2; mpfr_t g1, g2; fmpz_t e; arf_rnd_t rnd; bits1 = 1 + n_randint(state, 1000); bits2 = 2 + n_randint(state, 1000); if (n_randint(state, 100) == 0) bits2 = ARF_PREC_EXACT; switch (n_randint(state, 5)) { case 0: rnd = ARF_RND_DOWN; break; case 1: rnd = ARF_RND_UP; break; case 2: rnd = ARF_RND_FLOOR; break; case 3: rnd = ARF_RND_CEIL; break; default: rnd = ARF_RND_NEAR; break; } fmpz_init(e); mpfr_init2(g1, FLINT_MAX(2, bits1)); mpfr_init2(g2, FLINT_MIN(bits2, 10000)); if (n_randint(state, 100) == 0) { arf_clear(x); arf_clear(y); arf_clear(z); arf_init(x); arf_init(y); arf_init(z); } /* dirty output variables */ if (n_randint(state, 2)) { arf_randtest_special(y, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); arf_randtest_special(z, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); } arf_randtest_special(x, state, bits1, 1 + n_randint(state, 10)); arf_get_mpfr(g1, x, MPFR_RNDD); /* exact */ /* test large exponents */ if (n_randint(state, 4) == 0) fmpz_randtest(e, state, 1 + n_randint(state, 100)); if (!arf_is_special(x)) fmpz_add(ARF_EXPREF(x), ARF_EXPREF(x), e); ret1 = arf_set_round(y, x, bits2, rnd); ret2 = mpfr_set(g2, g1, arf_rnd_to_mpfr(rnd)); arf_set_mpfr(z, g2); if (!arf_is_special(y)) fmpz_sub(ARF_EXPREF(y), ARF_EXPREF(y), e); if (!arf_equal(y, z) || ((ret1 == ARF_RESULT_EXACT) != (ret2 == 0))) { flint_printf("FAIL\n\n"); flint_printf("bits1: %wd\n", bits1); flint_printf("bits2: %wd\n", bits2); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("ret1 = %d, ret2 = %d\n\n", ret1, ret2); flint_abort(); } if (!arf_is_special(x)) fmpz_add(ARF_EXPREF(x), ARF_EXPREF(x), e); ret1 = arf_set_round(y, x, bits2, rnd); arf_set(z, x); ret2 = arf_set_round(z, z, bits2, rnd); if (!arf_equal(y, z) || ret1 != ret2) { flint_printf("FAIL (aliasing)\n\n"); flint_printf("bits1: %wd\n", bits1); flint_printf("bits2: %wd\n", bits2); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("z = "); arf_print(z); flint_printf("\n\n"); flint_printf("ret1 = %d, ret2 = %d\n\n", ret1, ret2); flint_abort(); } mpfr_clear(g1); mpfr_clear(g2); fmpz_clear(e); } arf_clear(x); arf_clear(y); arf_clear(z); } flint_randclear(state); flint_cleanup(); flint_printf("PASS\n"); return EXIT_SUCCESS; }
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() { slong iter; flint_rand_t state; flint_printf("set_round_uiui...."); fflush(stdout); flint_randinit(state); for (iter = 0; iter < 1000000 * arb_test_multiplier(); iter++) { arf_t x, y; slong prec, fix1, fix2; int ret1, ret2, sgnbit; mp_limb_t t[2]; arf_rnd_t rnd; prec = 2 + n_randint(state, 1000); arf_init(x); arf_init(y); arf_randtest_special(x, state, 1 + n_randint(state, 200), 1 + n_randint(state, 100)); arf_randtest_special(y, state, 1 + n_randint(state, 200), 1 + n_randint(state, 100)); do { t[0] = n_randtest(state); t[1] = n_randtest(state); } while (t[0] == 0 && t[1] == 0); sgnbit = n_randint(state, 2); switch (n_randint(state, 10)) { case 0: rnd = ARF_RND_DOWN; break; case 1: rnd = ARF_RND_UP; break; case 2: rnd = ARF_RND_FLOOR; break; case 3: rnd = ARF_RND_CEIL; break; default: rnd = ARF_RND_NEAR; break; } if (t[1] != 0) { ret1 = _arf_set_round_mpn(x, &fix1, t, 2, sgnbit, prec, rnd); fmpz_set_si(ARF_EXPREF(x), 2 * FLINT_BITS + fix1); } else { ret1 = _arf_set_round_mpn(x, &fix1, t, 1, sgnbit, prec, rnd); fmpz_set_si(ARF_EXPREF(x), FLINT_BITS + fix1); } ret2 = _arf_set_round_uiui(y, &fix2, t[1], t[0], sgnbit, prec, rnd); fmpz_set_si(ARF_EXPREF(y), 2 * FLINT_BITS + fix2); if (!arf_equal(x, y) || (ret1 != ret2)) { flint_printf("FAIL\n\n"); flint_printf("prec = %wd", prec); flint_printf("\n\n"); flint_printf("hi = %wu, lo = %wu\n\n", t[1], t[0]); flint_printf("x = "); arf_print(x); flint_printf("\n\n"); flint_printf("y = "); arf_print(y); flint_printf("\n\n"); flint_printf("ret1 = %d, ret2 = %d\n\n", ret1, ret2); abort(); } arf_clear(x); arf_clear(y); } flint_randclear(state); flint_cleanup(); flint_printf("PASS\n"); return EXIT_SUCCESS; }