void fmprb_sqrt(fmprb_t z, const fmprb_t x, slong prec) { slong r; if (fmprb_contains_negative(x)) { fmpr_nan(fmprb_midref(z)); fmpr_pos_inf(fmprb_radref(z)); return; } if (fmprb_is_exact(x)) { r = fmpr_sqrt(fmprb_midref(z), fmprb_midref(x), prec, FMPR_RND_DOWN); fmpr_set_error_result(fmprb_radref(z), fmprb_midref(z), r); } else { fmpr_t err; fmpr_init(err); fmpr_sub(err, fmprb_midref(x), fmprb_radref(x), FMPRB_RAD_PREC, FMPR_RND_DOWN); fmpr_rsqrt(err, err, FMPRB_RAD_PREC, FMPR_RND_UP); fmpr_mul(err, fmprb_radref(x), err, FMPRB_RAD_PREC, FMPR_RND_UP); fmpr_mul_2exp_si(err, err, -1); r = fmpr_sqrt(fmprb_midref(z), fmprb_midref(x), prec, FMPR_RND_DOWN); fmpr_add_error_result(fmprb_radref(z), err, fmprb_midref(z), r, FMPRB_RAD_PREC, FMPR_RND_UP); fmpr_clear(err); } fmprb_adjust(z); }
/* Absolute value of rising factorial (could speed up once complex gamma is available). */ void fmpcb_rfac_abs_ubound2(fmpr_t bound, const fmpcb_t s, ulong n, long prec) { fmpr_t term, t; ulong k; /* M(k) = (a+k)^2 + b^2 M(0) = a^2 + b^2 M(k+1) = M(k) + 2*a + (2*k+1) */ fmpr_init(t); fmpr_init(term); fmpr_one(bound); /* M(0) = a^2 + b^2 */ fmprb_get_abs_ubound_fmpr(t, fmpcb_realref(s), prec); fmpr_mul(term, t, t, prec, FMPR_RND_UP); fmprb_get_abs_ubound_fmpr(t, fmpcb_imagref(s), prec); fmpr_mul(t, t, t, prec, FMPR_RND_UP); fmpr_add(term, term, t, prec, FMPR_RND_UP); /* we add t = 2*a to each term. note that this can be signed; we always want the most positive value */ fmpr_add(t, fmprb_midref(fmpcb_realref(s)), fmprb_radref(fmpcb_realref(s)), prec, FMPR_RND_CEIL); fmpr_mul_2exp_si(t, t, 1); for (k = 0; k < n; k++) { fmpr_mul(bound, bound, term, prec, FMPR_RND_UP); fmpr_add_ui(term, term, 2 * k + 1, prec, FMPR_RND_UP); fmpr_add(term, term, t, prec, FMPR_RND_UP); } fmpr_sqrt(bound, bound, prec, FMPR_RND_UP); fmpr_clear(t); fmpr_clear(term); }
void fmprb_mat_det_inplace(fmprb_t det, fmprb_mat_t A, long prec) { long i, n, sign, rank; n = fmprb_mat_nrows(A); rank = fmprb_mat_gauss_partial(A, prec); sign = (rank < 0) ? -1 : 1; rank = FLINT_ABS(rank); fmprb_set_si(det, sign); for (i = 0; i < rank; i++) fmprb_mul(det, det, fmprb_mat_entry(A, i, i), prec); /* bound unreduced part using Hadamard's inequality */ if (rank < n) { fmpr_t t; fmprb_t d; fmpr_init(t); fmprb_init(d); fmpr_one(fmprb_radref(d)); for (i = rank; i < n; i++) { fmprb_vec_get_fmpr_2norm_squared_bound(t, A->rows[i] + rank, n - rank, FMPRB_RAD_PREC); fmpr_mul(fmprb_radref(d), fmprb_radref(d), t, FMPRB_RAD_PREC, FMPR_RND_UP); } fmpr_sqrt(fmprb_radref(d), fmprb_radref(d), FMPRB_RAD_PREC, FMPR_RND_UP); fmprb_mul(det, det, d, prec); fmprb_clear(d); fmpr_clear(t); } }
void fmprb_sqrtpos(fmprb_t z, const fmprb_t x, slong prec) { if (!fmprb_is_finite(x)) { if (fmpr_is_zero(fmprb_radref(x)) && fmpr_is_pos_inf(fmprb_midref(x))) fmprb_pos_inf(z); else fmprb_zero_pm_inf(z); } else if (fmprb_contains_nonpositive(x)) { fmpr_t t; fmpr_init(t); fmpr_add(t, fmprb_midref(x), fmprb_radref(x), FMPRB_RAD_PREC, FMPR_RND_CEIL); if (fmpr_sgn(t) <= 0) { fmprb_zero(z); } else { fmpr_sqrt(t, t, FMPRB_RAD_PREC, FMPR_RND_CEIL); fmpr_mul_2exp_si(t, t, -1); fmpr_set(fmprb_midref(z), t); fmpr_set(fmprb_radref(z), t); } fmpr_clear(t); } else { fmprb_sqrt(z, x, prec); } fmprb_nonnegative_part(z, z, prec); }