mirror of
https://github.com/vale981/arb
synced 2025-03-04 17:01:40 -05:00
reduce z' mod tau' in theta functions to support larger arguments with reasonable performance
This commit is contained in:
parent
64fd8a8920
commit
380ce57f6a
5 changed files with 152 additions and 10 deletions
|
@ -64,7 +64,10 @@ int main()
|
|||
{
|
||||
acb_set_dddd(z, testdata[i][0], 0.0, testdata[i][1], 0.0);
|
||||
acb_set_dddd(tau, testdata[i][2], 0.0, testdata[i][3], 0.0);
|
||||
acb_set_dddd(p2, testdata[i][4], EPS, testdata[i][5], EPS);
|
||||
if (i == NUM_TESTS - 1) /* sensitive to rounding errors in doubles */
|
||||
acb_set_dddd(p2, testdata[i][4], 1e-6, testdata[i][5], 1e-6);
|
||||
else
|
||||
acb_set_dddd(p2, testdata[i][4], EPS, testdata[i][5], EPS);
|
||||
|
||||
acb_elliptic_zeta(p1, z, tau, 2 + n_randint(state, 400));
|
||||
|
||||
|
@ -77,6 +80,18 @@ int main()
|
|||
flint_printf("p2 = "); acb_printd(p2, 15); flint_printf("\n\n");
|
||||
flint_abort();
|
||||
}
|
||||
|
||||
acb_elliptic_zeta(p2, z, tau, 2 + n_randint(state, 800));
|
||||
|
||||
if (!acb_overlaps(p1, p2))
|
||||
{
|
||||
flint_printf("FAIL (test value 2)\n");
|
||||
flint_printf("tau = "); acb_printd(tau, 15); flint_printf("\n\n");
|
||||
flint_printf("z = "); acb_printd(z, 15); flint_printf("\n\n");
|
||||
flint_printf("p1 = "); acb_printd(p1, 15); flint_printf("\n\n");
|
||||
flint_printf("p2 = "); acb_printd(p2, 15); flint_printf("\n\n");
|
||||
flint_abort();
|
||||
}
|
||||
}
|
||||
|
||||
acb_clear(z);
|
||||
|
|
|
@ -63,7 +63,10 @@ int main()
|
|||
{
|
||||
acb_set_dddd(z, testdata[i][0], 0.0, testdata[i][1], 0.0);
|
||||
acb_set_dddd(tau, testdata[i][2], 0.0, testdata[i][3], 0.0);
|
||||
acb_set_dddd(p2, testdata[i][4], EPS, testdata[i][5], EPS);
|
||||
if (i == NUM_TESTS - 1) /* sensitive to rounding errors in doubles */
|
||||
acb_set_dddd(p2, testdata[i][4], 1e-6, testdata[i][5], 1e-6);
|
||||
else
|
||||
acb_set_dddd(p2, testdata[i][4], EPS, testdata[i][5], EPS);
|
||||
|
||||
acb_modular_elliptic_p(p1, z, tau, 2 + n_randint(state, 1000));
|
||||
|
||||
|
@ -76,6 +79,18 @@ int main()
|
|||
flint_printf("p2 = "); acb_printd(p2, 15); flint_printf("\n\n");
|
||||
flint_abort();
|
||||
}
|
||||
|
||||
acb_modular_elliptic_p(p2, z, tau, 2 + n_randint(state, 1000));
|
||||
|
||||
if (!acb_overlaps(p1, p2))
|
||||
{
|
||||
flint_printf("FAIL (test value 2)\n");
|
||||
flint_printf("tau = "); acb_printd(tau, 15); flint_printf("\n\n");
|
||||
flint_printf("z = "); acb_printd(z, 15); flint_printf("\n\n");
|
||||
flint_printf("p1 = "); acb_printd(p1, 15); flint_printf("\n\n");
|
||||
flint_printf("p2 = "); acb_printd(p2, 15); flint_printf("\n\n");
|
||||
flint_abort();
|
||||
}
|
||||
}
|
||||
|
||||
acb_clear(z);
|
||||
|
|
|
@ -140,6 +140,7 @@ acb_modular_theta(acb_t theta1, acb_t theta2,
|
|||
if (C == 0)
|
||||
{
|
||||
acb_set(z_prime, z);
|
||||
acb_one(A);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -157,18 +158,59 @@ acb_modular_theta(acb_t theta1, acb_t theta2,
|
|||
acb_sqrt(A, A, prec);
|
||||
|
||||
/* B = exp(-pi i c z^2/(c*tau+d)) */
|
||||
/* we first compute the argument here */
|
||||
if (acb_is_zero(z))
|
||||
{
|
||||
acb_one(B);
|
||||
acb_zero(B);
|
||||
}
|
||||
else
|
||||
{
|
||||
acb_mul(B, z_prime, z, prec);
|
||||
acb_mul_fmpz(B, B, &g->c, prec);
|
||||
acb_exp_pi_i(B, B, prec);
|
||||
}
|
||||
}
|
||||
|
||||
/* reduce z_prime modulo tau_prime if the imaginary part is large */
|
||||
if (arf_cmpabs_2exp_si(arb_midref(acb_imagref(z_prime)), 4) > 0)
|
||||
{
|
||||
arb_t nn;
|
||||
arb_init(nn);
|
||||
arf_div(arb_midref(nn), arb_midref(acb_imagref(z_prime)),
|
||||
arb_midref(acb_imagref(tau_prime)), prec, ARF_RND_DOWN);
|
||||
arf_mul_2exp_si(arb_midref(nn), arb_midref(nn), 1);
|
||||
arf_add_ui(arb_midref(nn), arb_midref(nn), 1, prec, ARF_RND_DOWN);
|
||||
arf_mul_2exp_si(arb_midref(nn), arb_midref(nn), -1);
|
||||
arf_floor(arb_midref(nn), arb_midref(nn));
|
||||
|
||||
/* transform z_prime further */
|
||||
acb_submul_arb(z_prime, tau_prime, nn, prec);
|
||||
|
||||
/* add -tau n^2 - 2nz to B */
|
||||
arb_mul_2exp_si(nn, nn, 1);
|
||||
acb_submul_arb(B, z_prime, nn, prec);
|
||||
arb_mul_2exp_si(nn, nn, -1);
|
||||
arb_sqr(nn, nn, prec);
|
||||
acb_submul_arb(B, tau_prime, nn, prec);
|
||||
|
||||
/* theta1, theta4 pick up factors (-1)^n */
|
||||
if (!arf_is_int_2exp_si(arb_midref(nn), 1))
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
if (S[i] == 0 || S[i] == 3)
|
||||
R[i] += 4;
|
||||
}
|
||||
}
|
||||
|
||||
C = 1;
|
||||
|
||||
arb_clear(nn);
|
||||
}
|
||||
|
||||
if (C != 0)
|
||||
acb_exp_pi_i(B, B, prec);
|
||||
|
||||
/* compute q_{1/4}, q */
|
||||
acb_mul_2exp_si(q4, tau_prime, -2);
|
||||
acb_exp_pi_i(q4, q4, prec);
|
||||
|
|
|
@ -64,7 +64,7 @@ acb_modular_theta_jet(acb_ptr theta1, acb_ptr theta2,
|
|||
acb_t z_prime, tau_prime, q, q4, w, A;
|
||||
acb_ptr B;
|
||||
acb_ptr thetas[4];
|
||||
int w_is_unit, R[4], S[4], C;
|
||||
int w_is_unit, R[4], S[4], C, rescale;
|
||||
slong k;
|
||||
|
||||
if (len == 0)
|
||||
|
@ -85,7 +85,8 @@ acb_modular_theta_jet(acb_ptr theta1, acb_ptr theta2,
|
|||
acb_modular_fundamental_domain_approx(tau_prime, g, tau,
|
||||
one_minus_eps, prec);
|
||||
|
||||
if (psl2z_is_one(g))
|
||||
if (psl2z_is_one(g) &&
|
||||
arf_cmpabs_2exp_si(arb_midref(acb_imagref(z)), 4) <= 0)
|
||||
{
|
||||
acb_modular_theta_jet_notransform(theta1, theta2, theta3, theta4,
|
||||
z, tau, len, prec);
|
||||
|
@ -110,9 +111,13 @@ acb_modular_theta_jet(acb_ptr theta1, acb_ptr theta2,
|
|||
if (C == 0)
|
||||
{
|
||||
acb_set(z_prime, z);
|
||||
acb_one(A);
|
||||
rescale = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
rescale = 1;
|
||||
|
||||
/* B = 1/(c*tau+d) (temporarily) */
|
||||
acb_mul_fmpz(B, tau, &g->c, prec);
|
||||
acb_add_fmpz(B, B, &g->d, prec);
|
||||
|
@ -144,10 +149,73 @@ acb_modular_theta_jet(acb_ptr theta1, acb_ptr theta2,
|
|||
acb_mul(B, z_prime, z, prec);
|
||||
acb_mul_fmpz(B, B, &g->c, prec);
|
||||
|
||||
/* B = exp(-pi i c (z+x)^2/(c*tau+d)) */
|
||||
_acb_poly_exp_pi_i_series(B, B, FLINT_MIN(len, 3), len, prec);
|
||||
/* we will have B = exp(-pi i c (z+x)^2/(c*tau+d))
|
||||
after computing the exponential later */
|
||||
}
|
||||
|
||||
/* reduce z_prime modulo tau_prime if the imaginary part is large */
|
||||
if (arf_cmpabs_2exp_si(arb_midref(acb_imagref(z_prime)), 4) > 0)
|
||||
{
|
||||
arb_t nn;
|
||||
arb_init(nn);
|
||||
arf_div(arb_midref(nn), arb_midref(acb_imagref(z_prime)),
|
||||
arb_midref(acb_imagref(tau_prime)), prec, ARF_RND_DOWN);
|
||||
arf_mul_2exp_si(arb_midref(nn), arb_midref(nn), 1);
|
||||
arf_add_ui(arb_midref(nn), arb_midref(nn), 1, prec, ARF_RND_DOWN);
|
||||
arf_mul_2exp_si(arb_midref(nn), arb_midref(nn), -1);
|
||||
arf_floor(arb_midref(nn), arb_midref(nn));
|
||||
|
||||
/* transform z_prime further */
|
||||
acb_submul_arb(z_prime, tau_prime, nn, prec);
|
||||
|
||||
/* add -tau n^2 - 2n(z+x)' to B */
|
||||
arb_mul_2exp_si(nn, nn, 1);
|
||||
acb_submul_arb(B, z_prime, nn, prec);
|
||||
if (len >= 2)
|
||||
{
|
||||
acb_t u;
|
||||
acb_init(u);
|
||||
|
||||
/* the x picks up a factor -1/(tau*c+d) */
|
||||
if (rescale)
|
||||
{
|
||||
acb_mul_fmpz(u, tau, &g->c, prec);
|
||||
acb_add_fmpz(u, u, &g->d, prec);
|
||||
acb_inv(u, u, prec);
|
||||
acb_neg(u, u);
|
||||
acb_mul_arb(u, u, nn, prec);
|
||||
acb_sub(B + 1, B + 1, u, prec);
|
||||
}
|
||||
else
|
||||
{
|
||||
acb_sub_arb(B + 1, B + 1, nn, prec);
|
||||
}
|
||||
|
||||
acb_clear(u);
|
||||
}
|
||||
arb_mul_2exp_si(nn, nn, -1);
|
||||
arb_sqr(nn, nn, prec);
|
||||
acb_submul_arb(B, tau_prime, nn, prec);
|
||||
|
||||
/* theta1, theta4 pick up factors (-1)^n */
|
||||
if (!arf_is_int_2exp_si(arb_midref(nn), 1))
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
if (S[i] == 0 || S[i] == 3)
|
||||
R[i] += 4;
|
||||
}
|
||||
}
|
||||
|
||||
C = 1;
|
||||
|
||||
arb_clear(nn);
|
||||
}
|
||||
|
||||
if (C != 0)
|
||||
_acb_poly_exp_pi_i_series(B, B, FLINT_MIN(len, 3), len, prec);
|
||||
|
||||
/* compute q_{1/4}, q */
|
||||
acb_mul_2exp_si(q4, tau_prime, -2);
|
||||
acb_exp_pi_i(q4, q4, prec);
|
||||
|
@ -162,8 +230,9 @@ acb_modular_theta_jet(acb_ptr theta1, acb_ptr theta2,
|
|||
w, w_is_unit, q, len, prec);
|
||||
|
||||
/* correct for change of variables */
|
||||
if (C != 0)
|
||||
if (rescale)
|
||||
{
|
||||
/* [-1/(tau*c+d)]]^k */
|
||||
acb_mul_fmpz(z_prime, tau, &g->c, prec);
|
||||
acb_add_fmpz(z_prime, z_prime, &g->d, prec);
|
||||
acb_inv(z_prime, z_prime, prec);
|
||||
|
|
|
@ -427,6 +427,7 @@ To avoid confusion, we only write `q^k` when `k` is an integer.
|
|||
|
||||
Evaluates the Jacobi theta functions `\theta_i(z,\tau)`, `i = 1, 2, 3, 4`
|
||||
simultaneously. This function moves `\tau` to the fundamental domain
|
||||
and then also reduces `z` modulo `\tau`
|
||||
before calling :func:`acb_modular_theta_sum`.
|
||||
|
||||
.. function:: void acb_modular_theta_jet_notransform(acb_ptr theta1, acb_ptr theta2, acb_ptr theta3, acb_ptr theta4, const acb_t z, const acb_t tau, slong len, slong prec)
|
||||
|
@ -437,7 +438,7 @@ To avoid confusion, we only write `q^k` when `k` is an integer.
|
|||
with respect to *z*, writing the first *len* coefficients in the power
|
||||
series `\theta_i(z+x,\tau) \in \mathbb{C}[[x]]` to
|
||||
each respective output variable. The *notransform* version does not
|
||||
move `\tau` to the fundamental domain during the computation.
|
||||
move `\tau` to the fundamental domain or reduce `z` during the computation.
|
||||
|
||||
The Dedekind eta function
|
||||
-------------------------------------------------------------------------------
|
||||
|
|
Loading…
Add table
Reference in a new issue