#include "arb_mat.h"
#include "acb.h"
#include "acb_mat.h"
#include "acb_theta.h"
static void
acb_theta_local_bound_ci(arb_t c0, arb_t c1, arb_t c2, acb_srcptr z, const acb_mat_t tau)
{
slong lp = ACB_THETA_LOW_PREC;
slong g = acb_mat_nrows(tau);
arb_mat_t yinv;
arb_mat_t cho;
arb_ptr y, w;
arb_t t, s;
slong k, j;
arb_mat_init(yinv, g, g);
arb_mat_init(cho, g, g);
y = _arb_vec_init(g);
w = _arb_vec_init(g);
arb_init(t);
arb_init(s);
_acb_vec_get_imag(y, z, g);
acb_siegel_cho_yinv(cho, yinv, tau, lp);
arb_one(c0);
arb_mul_2exp_si(c0, c0, g);
for (k = 0; k < g; k++)
{
arb_mul_2exp_si(t, arb_mat_entry(cho, k, k), 1);
arb_add_si(t, t, 1, lp);
arb_mul(c0, c0, t, lp);
}
arb_const_pi(t, lp);
arb_mat_scalar_mul_arb(yinv, yinv, t, lp);
arb_mat_vector_mul_col(w, yinv, y, lp);
arb_dot(c1, NULL, 0, y, 1, w, 1, g, lp);
arb_nonnegative_part(c1, c1);
arb_sqrt(c1, c1, lp);
arb_zero(c2);
arb_mat_cho(cho, yinv, lp);
arb_mat_transpose(cho, cho);
for (k = 0; k < g; k++)
{
arb_zero(s);
for (j = k; j < g; j++)
{
arb_abs(t, arb_mat_entry(cho, k, j));
arb_add(s, s, t, lp);
}
arb_sqr(s, s, lp);
arb_add(c2, c2, s, lp);
}
arb_nonnegative_part(c2, c2);
arb_sqrt(c2, c2, lp);
arb_mat_clear(yinv);
arb_mat_clear(cho);
_arb_vec_clear(y, g);
_arb_vec_clear(w, g);
arb_clear(t);
arb_clear(s);
}
void
acb_theta_ql_local_bound(arb_t c, arb_t rho, acb_srcptr z, const acb_mat_t tau, slong ord)
{
slong lp = ACB_THETA_LOW_PREC;
slong b = ord + 1;
arb_t t, c0, c1, c2;
arf_t x;
arb_init(t);
arb_init(c0);
arb_init(c1);
arb_init(c2);
arf_init(x);
acb_theta_local_bound_ci(c0, c1, c2, z, tau);
arb_mul(t, c1, c2, lp);
arb_mul_2exp_si(t, t, 1);
arb_sqr(rho, t, lp);
arb_sqr(t, c2, lp);
arb_mul_si(t, t, 8 * (2 * b - 1), lp);
arb_add(rho, rho, t, lp);
arb_sqrt(rho, rho, lp);
arb_mul(t, c1, c2, lp);
arb_submul_si(rho, t, 2, lp);
arb_sqr(t, c2, lp);
arb_mul_2exp_si(t, t, 2);
arb_div(rho, rho, t, lp);
arb_set_si(t, 1);
arb_min(rho, rho, t, lp);
arb_mul(c, c2, rho, lp);
arb_add(c, c, c1, lp);
arb_sqr(c, c, lp);
arb_exp(c, c, lp);
arb_mul(c, c, c0, lp);
arb_set_si(t, 1);
arb_max(c, c, t, lp);
arb_clear(t);
arb_clear(c0);
arb_clear(c1);
arb_clear(c2);
arf_clear(x);
}