#include "arb_mat.h"
#include "acb.h"
#include "acb_mat.h"
#include "acb_theta.h"
void
acb_theta_ql_jet_error(arb_ptr err, acb_srcptr z, const acb_mat_t tau,
acb_srcptr dth, slong ord, slong prec)
{
slong g = acb_mat_nrows(tau);
arb_ptr abs_der;
arb_mat_t tau_err;
arb_ptr z_err;
arb_t e, f;
arf_t half;
slong nb = acb_theta_jet_nb(ord, g);
slong nb_dth = acb_theta_jet_nb(ord + 2, g);
slong * tups;
slong * new_tups;
slong j, l, m, i;
abs_der = _arb_vec_init(nb_dth);
arb_mat_init(tau_err, g, g);
z_err = _arb_vec_init(g);
arb_init(e);
arb_init(f);
arf_init(half);
tups = flint_malloc(nb * g * sizeof(slong));
new_tups = flint_malloc(g * sizeof(slong));
arf_set_si(half, 1);
arf_mul_2exp_si(half, half, -1);
for (l = 0; l < g; l++)
{
for (m = l; m < g; m++)
{
arb_zero(e);
acb_get_rad_ubound_arf(arb_midref(e), acb_mat_entry(tau, l, m), prec);
arb_set(arb_mat_entry(tau_err, l, m), e);
}
arb_zero(e);
arb_zero(f);
arf_set_mag(arb_midref(e), arb_radref(acb_imagref(&z[l])));
arf_set_mag(arb_midref(f), arb_radref(acb_realref(&z[l])));
arf_min(arb_midref(f), arb_midref(f), half);
arb_sqr(e, e, prec);
arb_sqr(f, f, prec);
arb_add(e, e, f, prec);
arb_sqrt(&z_err[l], e, prec);
}
for (j = 0; j < nb_dth; j++)
{
acb_get_abs_ubound_arf(arb_midref(&abs_der[j]), &dth[j], prec);
}
acb_theta_jet_tuples(tups, ord, g);
for (j = 0; j < nb; j++)
{
arb_zero(&err[j]);
for (l = 0; l < g; l++)
{
for (m = l; m < g; m++)
{
for (i = 0; i < g; i++)
{
new_tups[i] = tups[j * g + i];
}
new_tups[l] += 1;
new_tups[m] += 1;
i = acb_theta_jet_index(new_tups, g);
arb_mul(e, arb_mat_entry(tau_err, l, m), &abs_der[i], prec);
arb_const_pi(f, prec);
if (l == m)
{
arb_mul_2exp_si(f, f, 2);
arb_mul_si(e, e, new_tups[l] * (new_tups[l] - 1), prec);
}
else
{
arb_mul_2exp_si(f, f, 1);
arb_mul_si(e, e, new_tups[l] * new_tups[m], prec);
}
arb_div(e, e, f, prec);
arb_add(&err[j], &err[j], e, prec);
}
}
for (l = 0; l < g; l++)
{
for (i = 0; i < g; i++)
{
new_tups[i] = tups[j * g + i];
}
new_tups[l] += 1;
i = acb_theta_jet_index(new_tups, g);
arb_mul(e, &z_err[l], &abs_der[i], prec);
arb_mul_si(e, e, new_tups[l], prec);
arb_add(&err[j], &err[j], e, prec);
}
}
_arb_vec_clear(abs_der, nb_dth);
arb_mat_clear(tau_err);
_arb_vec_clear(z_err, g);
arb_clear(e);
arb_clear(f);
arf_clear(half);
flint_free(tups);
flint_free(new_tups);
}