void arb_max(arb_t z, const arb_t x, const arb_t y, slong prec) { arf_t left, right, t, xr, yr; if (arf_is_nan(arb_midref(x)) || arf_is_nan(arb_midref(y))) { arb_indeterminate(z); return; } arf_init(left); arf_init(right); arf_init(t); arf_init_set_mag_shallow(xr, arb_radref(x)); arf_init_set_mag_shallow(yr, arb_radref(y)); arf_sub(left, arb_midref(x), xr, prec, ARF_RND_FLOOR); arf_sub(t, arb_midref(y), yr, prec, ARF_RND_FLOOR); arf_max(left, left, t); arf_add(right, arb_midref(x), xr, prec, ARF_RND_CEIL); arf_add(t, arb_midref(y), yr, prec, ARF_RND_CEIL); arf_max(right, right, t); arb_set_interval_arf(z, left, right, prec); arf_clear(left); arf_clear(right); arf_clear(t); }
int arf_sub_special(arf_t z, const arf_t x, const arf_t y, slong prec, arf_rnd_t rnd) { if (arf_is_zero(x)) { if (arf_is_zero(y)) { arf_zero(z); return 0; } else return arf_neg_round(z, y, prec, rnd); } else if (arf_is_zero(y)) { return arf_set_round(z, x, prec, rnd); } else if (arf_is_nan(x) || arf_is_nan(y) || (arf_is_pos_inf(x) && arf_is_pos_inf(y)) || (arf_is_neg_inf(x) && arf_is_neg_inf(y))) { arf_nan(z); return 0; } else if (arf_is_special(x)) { arf_set(z, x); return 0; } else { arf_neg(z, y); return 0; } }
int arb_richcmp_fallback(const arb_t x, const arb_t y, int op) { arf_t xa, xb, ya, yb; int res; arf_init(xa); arf_init(xb); arf_init(ya); arf_init(yb); arb_infimum(xa, x); arb_supremum(xb, x); arb_infimum(ya, y); arb_supremum(yb, y); if (arf_is_nan(xa) || arf_is_nan(ya)) { res = 0; } else { if (op == 0) /* eq */ { res = arf_equal(xa, xb) && arf_equal(ya, yb) && arf_equal(xa, ya); } else if (op == 1) /* ne */ { res = (arf_cmp(yb, xa) < 0) || (arf_cmp(xb, ya) < 0); } else if (op == 2) /* le */ { res = (arf_cmp(xb, ya) <= 0); } else if (op == 3) /* lt */ { res = (arf_cmp(xb, ya) < 0); } else if (op == 4) /* ge */ { res = (arf_cmp(xa, yb) >= 0); } else /* gt */ { res = (arf_cmp(xa, yb) > 0); } } arf_clear(xa); arf_clear(xb); arf_clear(ya); arf_clear(yb); return res; }
int arb_contains_arf(const arb_t x, const arf_t y) { if (arf_is_nan(y)) { return arf_is_nan(arb_midref(x)); } else if (arf_is_nan(arb_midref(x))) { return 1; } else if (arb_is_exact(x)) { return arf_equal(arb_midref(x), y); } else { arf_t t; arf_struct tmp[3]; int result; arf_init(t); /* y >= xm - xr <=> 0 >= xm - xr - y */ arf_init_set_shallow(tmp + 0, arb_midref(x)); arf_init_neg_mag_shallow(tmp + 1, arb_radref(x)); arf_init_neg_shallow(tmp + 2, y); arf_sum(t, tmp, 3, MAG_BITS, ARF_RND_DOWN); result = (arf_sgn(t) <= 0); if (result) { /* y <= xm + xr <=> 0 <= xm + xr - y */ arf_init_set_mag_shallow(tmp + 1, arb_radref(x)); arf_sum(t, tmp, 3, MAG_BITS, ARF_RND_DOWN); result = (arf_sgn(t) >= 0); } arf_clear(t); return result; } }
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; }
static void arb_infimum(arf_t res, const arb_t x) { if (arf_is_nan(arb_midref(x))) { arf_nan(res); } else if (mag_is_inf(arb_radref(x))) { arf_neg_inf(res); } else { arf_set_mag(res, arb_radref(x)); arf_sub(res, arb_midref(x), res, ARF_PREC_EXACT, ARF_RND_FLOOR); } }
static void arb_supremum(arf_t res, const arb_t x) { if (arf_is_nan(arb_midref(x))) { arf_nan(res); } else if (mag_is_inf(arb_radref(x))) { arf_pos_inf(res); } else { arf_set_mag(res, arb_radref(x)); arf_add(res, res, arb_midref(x), ARF_PREC_EXACT, ARF_RND_CEIL); } }
void _arb_sin_cos_generic(arb_t s, arb_t c, const arf_t x, const mag_t xrad, slong prec) { int want_sin, want_cos; slong maglim; want_sin = (s != NULL); want_cos = (c != NULL); if (arf_is_zero(x) && mag_is_zero(xrad)) { if (want_sin) arb_zero(s); if (want_cos) arb_one(c); return; } if (!arf_is_finite(x) || !mag_is_finite(xrad)) { if (arf_is_nan(x)) { if (want_sin) arb_indeterminate(s); if (want_cos) arb_indeterminate(c); } else { if (want_sin) arb_zero_pm_one(s); if (want_cos) arb_zero_pm_one(c); } return; } maglim = FLINT_MAX(65536, 4 * prec); if (mag_cmp_2exp_si(xrad, -16) > 0 || arf_cmpabs_2exp_si(x, maglim) > 0) { _arb_sin_cos_wide(s, c, x, xrad, prec); return; } if (arf_cmpabs_2exp_si(x, -(prec/2) - 2) <= 0) { mag_t t, u, v; mag_init(t); mag_init(u); mag_init(v); arf_get_mag(t, x); mag_add(t, t, xrad); mag_mul(u, t, t); /* |sin(z)-z| <= z^3/6 */ if (want_sin) { arf_set(arb_midref(s), x); mag_set(arb_radref(s), xrad); arb_set_round(s, s, prec); mag_mul(v, u, t); mag_div_ui(v, v, 6); arb_add_error_mag(s, v); } /* |cos(z)-1| <= z^2/2 */ if (want_cos) { arf_one(arb_midref(c)); mag_mul_2exp_si(arb_radref(c), u, -1); } mag_clear(t); mag_clear(u); mag_clear(v); return; } if (mag_is_zero(xrad)) { arb_sin_cos_arf_generic(s, c, x, prec); } else { mag_t t; slong exp, radexp; mag_init_set(t, xrad); exp = arf_abs_bound_lt_2exp_si(x); radexp = MAG_EXP(xrad); if (radexp < MAG_MIN_LAGOM_EXP || radexp > MAG_MAX_LAGOM_EXP) radexp = MAG_MIN_LAGOM_EXP; if (want_cos && exp < -2) prec = FLINT_MIN(prec, 20 - FLINT_MAX(exp, radexp) - radexp); else prec = FLINT_MIN(prec, 20 - radexp); arb_sin_cos_arf_generic(s, c, x, prec); /* todo: could use quadratic bound */ if (want_sin) mag_add(arb_radref(s), arb_radref(s), t); if (want_cos) mag_add(arb_radref(c), arb_radref(c), t); mag_clear(t); } }
int main() { long iter; flint_rand_t state; printf("atan_arf...."); fflush(stdout); flint_randinit(state); /* self-consistency test */ for (iter = 0; iter < 5000; iter++) { arf_t x; arb_t y1, y2; long prec1, prec2, acc1, acc2; prec1 = 2 + n_randint(state, 9000); prec2 = 2 + n_randint(state, 9000); arf_init(x); arb_init(y1); arb_init(y2); arf_randtest_special(x, state, 1 + n_randint(state, 9000), 200); arb_randtest_special(y1, state, 1 + n_randint(state, 9000), 200); arb_randtest_special(y2, state, 1 + n_randint(state, 9000), 200); if (n_randint(state, 2)) arf_add_ui(x, x, 1, 2 + n_randint(state, 9000), ARF_RND_DOWN); arb_atan_arf(y1, x, prec1); arb_atan_arf(y2, x, prec2); if (!arb_overlaps(y1, y2)) { printf("FAIL: overlap\n\n"); printf("prec1 = %ld, prec2 = %ld\n\n", prec1, prec2); printf("x = "); arf_print(x); printf("\n\n"); printf("y1 = "); arb_print(y1); printf("\n\n"); printf("y2 = "); arb_print(y2); printf("\n\n"); abort(); } acc1 = arb_rel_accuracy_bits(y1); acc2 = arb_rel_accuracy_bits(y2); if (!arf_is_nan(x)) { if (acc1 < prec1 - 2 || acc2 < prec2 - 2) { printf("FAIL: accuracy\n\n"); printf("prec1 = %ld, prec2 = %ld\n\n", prec1, prec2); printf("acc1 = %ld, acc2 = %ld\n\n", acc1, acc2); printf("x = "); arf_printd(x, 50); printf("\n\n"); printf("y1 = "); arb_printd(y1, 50); printf("\n\n"); printf("y2 = "); arb_printd(y2, 50); printf("\n\n"); abort(); } } arf_clear(x); arb_clear(y1); arb_clear(y2); } flint_randclear(state); flint_cleanup(); printf("PASS\n"); return EXIT_SUCCESS; }
int main() { long iter; flint_rand_t state; printf("add_error...."); fflush(stdout); flint_randinit(state); for (iter = 0; iter < 10000; iter++) { arb_t a, b, c; arf_t m, r; arb_init(a); arb_init(b); arb_init(c); arf_init(m); arf_init(r); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 10); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 10); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 10); arf_randtest_special(m, state, 1 + n_randint(state, 2000), 10); arf_randtest_special(r, state, 1 + n_randint(state, 2000), 10); /* c = a plus error bounds */ arb_set(c, a); arf_set(arb_midref(b), m); arf_get_mag(arb_radref(b), r); arb_add_error(c, b); /* b = a + random point */ arb_set(b, a); if (n_randint(state, 2)) arf_add(arb_midref(b), arb_midref(b), m, ARF_PREC_EXACT, ARF_RND_DOWN); else arf_sub(arb_midref(b), arb_midref(b), m, ARF_PREC_EXACT, ARF_RND_DOWN); if (n_randint(state, 2)) arf_add(arb_midref(b), arb_midref(b), r, ARF_PREC_EXACT, ARF_RND_DOWN); else arf_sub(arb_midref(b), arb_midref(b), r, ARF_PREC_EXACT, ARF_RND_DOWN); /* should this be done differently? */ if (arf_is_nan(arb_midref(b))) arf_zero(arb_midref(b)); if (!arb_contains(c, b)) { printf("FAIL (arb_add_error)\n\n"); printf("a = "); arb_printn(a, 50, 0); printf("\n\n"); printf("b = "); arb_printn(b, 50, 0); printf("\n\n"); printf("c = "); arb_printn(c, 50, 0); printf("\n\n"); abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arf_clear(m); arf_clear(r); } for (iter = 0; iter < 10000; iter++) { arb_t a, b, c; arf_t m; arb_init(a); arb_init(b); arb_init(c); arf_init(m); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 10); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 10); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 10); arf_randtest_special(m, state, 1 + n_randint(state, 2000), 10); /* c = a plus error bounds */ arb_set(c, a); arb_add_error_arf(c, m); /* b = a + random point */ arb_set(b, a); if (n_randint(state, 2)) arf_add(arb_midref(b), arb_midref(b), m, ARF_PREC_EXACT, ARF_RND_DOWN); else arf_sub(arb_midref(b), arb_midref(b), m, ARF_PREC_EXACT, ARF_RND_DOWN); /* should this be done differently? */ if (arf_is_nan(arb_midref(b))) arf_zero(arb_midref(b)); if (!arb_contains(c, b)) { printf("FAIL (arb_add_error_arf)\n\n"); printf("a = "); arb_printn(a, 50, 0); printf("\n\n"); printf("b = "); arb_printn(b, 50, 0); printf("\n\n"); printf("c = "); arb_printn(c, 50, 0); printf("\n\n"); abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arf_clear(m); } for (iter = 0; iter < 10000; iter++) { arb_t a, b, c; arf_t t; mag_t r; arb_init(a); arb_init(b); arb_init(c); mag_init(r); arf_init(t); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 10); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 10); mag_randtest(r, state, 10); /* c = a plus error bounds */ arb_set(c, a); arb_add_error_mag(c, r); /* b = a + random point */ arb_set(b, a); arf_set_mag(t, r); if (n_randint(state, 2)) arf_add(arb_midref(b), arb_midref(b), t, ARF_PREC_EXACT, ARF_RND_DOWN); else arf_sub(arb_midref(b), arb_midref(b), t, ARF_PREC_EXACT, ARF_RND_DOWN); /* should this be done differently? */ if (arf_is_nan(arb_midref(b))) arf_zero(arb_midref(b)); if (!arb_contains(c, b)) { printf("FAIL (arb_add_error_mag)\n\n"); printf("a = "); arb_printn(a, 50, 0); printf("\n\n"); printf("b = "); arb_printn(b, 50, 0); printf("\n\n"); printf("c = "); arb_printn(c, 50, 0); printf("\n\n"); abort(); } arb_clear(a); arb_clear(b); arb_clear(c); mag_clear(r); arf_clear(t); } for (iter = 0; iter < 10000; iter++) { arb_t a, b, c; arf_t t; long e; arb_init(a); arb_init(b); arb_init(c); arf_init(t); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 10); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 10); e = n_randint(state, 10) - 10; /* c = a plus error bounds */ arb_set(c, a); arb_add_error_2exp_si(c, e); /* b = a + random point */ arb_set(b, a); arf_one(t); arf_mul_2exp_si(t, t, e); if (n_randint(state, 2)) arf_add(arb_midref(b), arb_midref(b), t, ARF_PREC_EXACT, ARF_RND_DOWN); else arf_sub(arb_midref(b), arb_midref(b), t, ARF_PREC_EXACT, ARF_RND_DOWN); /* should this be done differently? */ if (arf_is_nan(arb_midref(b))) arf_zero(arb_midref(b)); if (!arb_contains(c, b)) { printf("FAIL (arb_add_error_2exp_si)\n\n"); printf("a = "); arb_printn(a, 50, 0); printf("\n\n"); printf("b = "); arb_printn(b, 50, 0); printf("\n\n"); printf("c = "); arb_printn(c, 50, 0); printf("\n\n"); abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arf_clear(t); } for (iter = 0; iter < 10000; iter++) { arb_t a, b, c; arf_t t; fmpz_t e; arb_init(a); arb_init(b); arb_init(c); arf_init(t); fmpz_init(e); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 10); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 10); fmpz_randtest(e, state, 10); /* c = a plus error bounds */ arb_set(c, a); arb_add_error_2exp_fmpz(c, e); /* b = a + random point */ arb_set(b, a); arf_one(t); arf_mul_2exp_fmpz(t, t, e); if (n_randint(state, 2)) arf_add(arb_midref(b), arb_midref(b), t, ARF_PREC_EXACT, ARF_RND_DOWN); else arf_sub(arb_midref(b), arb_midref(b), t, ARF_PREC_EXACT, ARF_RND_DOWN); /* should this be done differently? */ if (arf_is_nan(arb_midref(b))) arf_zero(arb_midref(b)); if (!arb_contains(c, b)) { printf("FAIL (arb_add_error_2exp_fmpz)\n\n"); printf("a = "); arb_printn(a, 50, 0); printf("\n\n"); printf("b = "); arb_printn(b, 50, 0); printf("\n\n"); printf("c = "); arb_printn(c, 50, 0); printf("\n\n"); abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arf_clear(t); fmpz_clear(e); } flint_randclear(state); flint_cleanup(); printf("PASS\n"); return EXIT_SUCCESS; }
int arf_sum(arf_t s, arf_srcptr terms, long len, long prec, arf_rnd_t rnd) { arf_ptr blocks; long i, j, used; int have_merged, res; /* first check if the result is inf or nan */ { int have_pos_inf = 0; int have_neg_inf = 0; for (i = 0; i < len; i++) { if (arf_is_pos_inf(terms + i)) { if (have_neg_inf) { arf_nan(s); return 0; } have_pos_inf = 1; } else if (arf_is_neg_inf(terms + i)) { if (have_pos_inf) { arf_nan(s); return 0; } have_neg_inf = 1; } else if (arf_is_nan(terms + i)) { arf_nan(s); return 0; } } if (have_pos_inf) { arf_pos_inf(s); return 0; } if (have_neg_inf) { arf_neg_inf(s); return 0; } } blocks = flint_malloc(sizeof(arf_struct) * len); for (i = 0; i < len; i++) arf_init(blocks + i); /* put all terms into blocks */ used = 0; for (i = 0; i < len; i++) { if (!arf_is_zero(terms + i)) { arf_set(blocks + used, terms + i); used++; } } /* merge blocks until all are well separated */ have_merged = 1; while (used >= 2 && have_merged) { have_merged = 0; for (i = 0; i < used && !have_merged; i++) { for (j = i + 1; j < used && !have_merged; j++) { if (_arf_are_close(blocks + i, blocks + j, prec)) { arf_add(blocks + i, blocks + i, blocks + j, ARF_PREC_EXACT, ARF_RND_DOWN); /* remove the merged block */ arf_swap(blocks + j, blocks + used - 1); used--; /* remove the updated block if the sum is zero */ if (arf_is_zero(blocks + i)) { arf_swap(blocks + i, blocks + used - 1); used--; } have_merged = 1; } } } } if (used == 0) { arf_zero(s); res = 0; } else if (used == 1) { res = arf_set_round(s, blocks + 0, prec, rnd); } else { /* find the two largest blocks */ for (i = 1; i < used; i++) if (arf_cmpabs(blocks + 0, blocks + i) < 0) arf_swap(blocks + 0, blocks + i); for (i = 2; i < used; i++) if (arf_cmpabs(blocks + 1, blocks + i) < 0) arf_swap(blocks + 1, blocks + i); res = _arf_add_eps(s, blocks + 0, arf_sgn(blocks + 1), prec, rnd); } for (i = 0; i < len; i++) arf_clear(blocks + i); flint_free(blocks); return res; }