#include "acf.h"
void
acf_approx_sqrt(acf_t y, const acf_t x, slong prec, arf_rnd_t rnd)
{
arf_t r, t, u;
slong wp;
int sgn;
#define a acf_realref(x)
#define b acf_imagref(x)
#define c acf_realref(y)
#define d acf_imagref(y)
if (arf_is_zero(b))
{
if (arf_sgn(a) >= 0)
{
arf_sqrt(c, a, prec, rnd);
arf_zero(d);
return;
}
else
{
arf_neg(d, a);
arf_sqrt(d, d, prec, rnd);
arf_zero(c);
return;
}
}
if (arf_is_zero(a))
{
if (arf_sgn(b) >= 0)
{
arf_mul_2exp_si(c, b, -1);
arf_sqrt(c, c, prec, rnd);
arf_set(d, c);
return;
}
else
{
arf_mul_2exp_si(c, b, -1);
arf_neg(c, c);
arf_sqrt(c, c, prec, rnd);
arf_neg(d, c);
return;
}
}
wp = prec + 4;
arf_init(r);
arf_init(t);
arf_init(u);
arf_sosq(r, acf_realref(x), acf_imagref(x), wp, rnd);
arf_sqrt(r, r, wp, rnd);
if (arf_sgn(a) >= 0)
{
arf_add(t, r, a, wp, rnd);
arf_mul_2exp_si(u, t, 1);
arf_sqrt(u, u, wp, rnd);
arf_div(d, b, u, prec, rnd);
arf_set_round(c, u, prec, rnd);
arf_mul_2exp_si(c, c, -1);
}
else
{
arf_sub(u, r, a, wp, rnd);
sgn = arf_sgn(b);
arf_mul_2exp_si(t, u, 1);
arf_sqrt(t, t, wp, rnd);
arf_div(c, b, t, prec, rnd);
arf_abs(c, c);
arf_set_round(d, t, prec, rnd);
arf_mul_2exp_si(d, d, -1);
if (sgn < 0)
arf_neg(d, d);
}
arf_clear(r);
arf_clear(t);
arf_clear(u);
#undef a
#undef b
#undef c
#undef d
}