void arf_twobytwo_diag(arf_t u1, arf_t u2, const arf_t a, const arf_t b, const arf_t d, slong prec) { // Compute the orthogonal matrix that diagonalizes // // A = [a b] // [b d] // // This matrix will have the form // // U = [cos x , -sin x] // [sin x, cos x] // // where the diagonal matrix is U^t A U. // We set u1 = cos x, u2 = -sin x. if(arf_is_zero(b)) { arf_set_ui(u1, 1); arf_set_ui(u2, 0); return; } arf_t x; arf_init(x); arf_mul(u1, b, b, prec, ARF_RND_NEAR); // u1 = b^2 arf_sub(u2, a, d, prec, ARF_RND_NEAR); // u2 = a - d arf_mul_2exp_si(u2, u2, -1); // u2 = (a - d)/2 arf_mul(u2, u2, u2, prec, ARF_RND_NEAR); // u2 = ( (a - d)/2 )^2 arf_add(u1, u1, u2, prec, ARF_RND_NEAR); // u1 = b^2 + ( (a-d)/2 )^2 arf_sqrt(u1, u1, prec, ARF_RND_NEAR); // u1 = sqrt(above) arf_mul_2exp_si(u1, u1, 1); // u1 = 2 (sqrt (above) ) arf_add(u1, u1, d, prec, ARF_RND_NEAR); // u1 += d arf_sub(u1, u1, a, prec, ARF_RND_NEAR); // u1 -= a arf_mul_2exp_si(u1, u1, -1); // u1 = (d - a)/2 + sqrt(b^2 + ( (a-d)/2 )^2) arf_mul(x, u1, u1, prec, ARF_RND_NEAR); arf_addmul(x, b, b, prec, ARF_RND_NEAR); // x = u1^2 + b^2 arf_sqrt(x, x, prec, ARF_RND_NEAR); // x = sqrt(u1^2 + b^2) arf_div(u2, u1, x, prec, ARF_RND_NEAR); arf_div(u1, b, x, prec, ARF_RND_NEAR); arf_neg(u1, u1); arf_clear(x); }
void arb_sqrtpos(arb_t z, const arb_t x, long prec) { if (!arb_is_finite(x)) { if (mag_is_zero(arb_radref(x)) && arf_is_pos_inf(arb_midref(x))) arb_pos_inf(z); else arb_zero_pm_inf(z); } else if (arb_contains_nonpositive(x)) { arf_t t; arf_init(t); arf_set_mag(t, arb_radref(x)); arf_add(t, arb_midref(x), t, MAG_BITS, ARF_RND_CEIL); if (arf_sgn(t) <= 0) { arb_zero(z); } else { arf_sqrt(t, t, MAG_BITS, ARF_RND_CEIL); arf_mul_2exp_si(t, t, -1); arf_set(arb_midref(z), t); arf_get_mag(arb_radref(z), t); } arf_clear(t); } else { arb_sqrt(z, x, prec); } arb_nonnegative_part(z, z, prec); }
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; }