Merge remote-tracking branch 'upstream/master' into cmake2

This commit is contained in:
Isuru Fernando 2016-10-14 17:47:20 +05:30
commit 36357d6abd
204 changed files with 12505 additions and 455 deletions

View file

@ -8,7 +8,7 @@ make -j4 > /dev/null 2>&1
make install make install
cd .. cd ..
wget http://www.mpfr.org/mpfr-current/mpfr-3.1.4.tar.bz2 wget http://www.mpfr.org/mpfr-3.1.4/mpfr-3.1.4.tar.bz2
tar -xf mpfr-3.1.4.tar.bz2 tar -xf mpfr-3.1.4.tar.bz2
cd mpfr-3.1.4 cd mpfr-3.1.4
./configure --with-gmp=$HOME/deps --prefix=$HOME/deps --disable-static ./configure --with-gmp=$HOME/deps --prefix=$HOME/deps --disable-static

1
.gitignore vendored
View file

@ -1,5 +1,6 @@
Makefile Makefile
build/* build/*
libarb.so* libarb.so*
libarb.a
doc/build/* doc/build/*
*.ppm *.ppm

View file

@ -6,7 +6,7 @@ addons:
- texinfo - texinfo
os: os:
- osx # - osx
- linux - linux
compiler: compiler:

View file

@ -13,8 +13,8 @@ QUIET_AR = @echo ' ' AR ' ' $@;
AT=@ AT=@
BUILD_DIRS = fmpr arf mag arb arb_mat arb_poly arb_calc acb acb_mat acb_poly \ BUILD_DIRS = fmpr arf mag arb arb_mat arb_poly arb_calc acb acb_mat acb_poly \
acb_calc acb_hypgeom acb_modular acb_dirichlet bernoulli hypgeom \ acb_calc acb_hypgeom acb_modular dirichlet acb_dirichlet arb_hypgeom bernoulli hypgeom \
fmpz_extras bool_mat partitions \ fmpz_extras bool_mat partitions dlog \
$(EXTRA_BUILD_DIRS) $(EXTRA_BUILD_DIRS)
TEMPLATE_DIRS = TEMPLATE_DIRS =

View file

@ -8,7 +8,7 @@ GNU Lesser General Public License (LGPL), version 2.1 or later.
![arb logo](http://fredrikj.net/blog/2015/01/arb-2-5-0-released/arbtext.png) ![arb logo](http://fredrikj.net/blog/2015/01/arb-2-5-0-released/arbtext.png)
Documentation: http://fredrikj.net/arb/ Documentation: http://arblib.org
Development updates: http://fredrikj.net/blog/ Development updates: http://fredrikj.net/blog/
@ -70,7 +70,7 @@ can rely on Arb's automatic error bound tracking to get an output
that is guaranteed to be accurate -- no error analysis that is guaranteed to be accurate -- no error analysis
needs to be done by the user. needs to be done by the user.
For several other example programs, see: http://fredrikj.net/arb/examples.html For more example programs, see: http://arblib.org/examples.html
## General features ## General features
@ -140,7 +140,7 @@ Arb depends on FLINT (http://flintlib.org/), either
GMP (http://gmplib.org) or MPIR (http://mpir.org), GMP (http://gmplib.org) or MPIR (http://mpir.org),
and MPFR (http://mpfr.org). and MPFR (http://mpfr.org).
See http://fredrikj.net/arb/setup.html for instructions See http://arblib.org/setup.html for instructions
on building and installing Arb directly from the source code. on building and installing Arb directly from the source code.
Arb might also be available (or coming soon) as a package for Arb might also be available (or coming soon) as a package for
your Linux distribution. your Linux distribution.

20
acb.h
View file

@ -48,12 +48,7 @@ acb_init(acb_t x)
arb_init(acb_imagref(x)); arb_init(acb_imagref(x));
} }
ACB_INLINE void void acb_clear(acb_t x);
acb_clear(acb_t x)
{
arb_clear(acb_realref(x));
arb_clear(acb_imagref(x));
}
ACB_INLINE acb_ptr ACB_INLINE acb_ptr
_acb_vec_init(slong n) _acb_vec_init(slong n)
@ -1014,6 +1009,14 @@ acb_printd(const acb_t z, slong digits)
acb_fprintd(stdout, z, digits); acb_fprintd(stdout, z, digits);
} }
void acb_fprintn(FILE * fp, const acb_t z, long digits, ulong flags);
ACB_INLINE void
acb_printn(const acb_t x, slong digits, ulong flags)
{
acb_fprintn(stdout, x, digits, flags);
}
void acb_randtest(acb_t z, flint_rand_t state, slong prec, slong mag_bits); void acb_randtest(acb_t z, flint_rand_t state, slong prec, slong mag_bits);
void acb_randtest_special(acb_t z, flint_rand_t state, slong prec, slong mag_bits); void acb_randtest_special(acb_t z, flint_rand_t state, slong prec, slong mag_bits);
@ -1132,6 +1135,11 @@ _acb_vec_get_unique_fmpz_vec(fmpz * res, acb_srcptr vec, slong len)
/* sort complex numbers in a nice-to-display order */ /* sort complex numbers in a nice-to-display order */
void _acb_vec_sort_pretty(acb_ptr vec, slong len); void _acb_vec_sort_pretty(acb_ptr vec, slong len);
/* roots of unity */
void acb_nth_root(acb_t res, ulong order, slong prec);
void _acb_vec_nth_roots_pe(acb_ptr z, slong p, slong e, slong len, slong step, slong prec);
void _acb_vec_nth_roots(acb_ptr z, slong len, slong prec);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

37
acb/clear.c Normal file
View file

@ -0,0 +1,37 @@
/*
Copyright (C) 2016 Fredrik Johansson
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "acb.h"
/* The clear methods are not defined as inlines since this inflates
the code size. We inline the content manually here to avoid function
call overhead. Question: would calling arb_clear twice here be worth
the call overhead, by improving branch prediction? */
void
acb_clear(acb_t x)
{
ARF_DEMOTE(arb_midref(acb_realref(x)));
if (COEFF_IS_MPZ(ARF_EXP(arb_midref(acb_realref(x)))))
_fmpz_clear_mpz(ARF_EXP(arb_midref(acb_realref(x))));
if (COEFF_IS_MPZ(MAG_EXP(arb_radref(acb_realref(x)))))
_fmpz_clear_mpz(MAG_EXP(arb_radref(acb_realref(x))));
ARF_DEMOTE(arb_midref(acb_imagref(x)));
if (COEFF_IS_MPZ(ARF_EXP(arb_midref(acb_imagref(x)))))
_fmpz_clear_mpz(ARF_EXP(arb_midref(acb_imagref(x))));
if (COEFF_IS_MPZ(MAG_EXP(arb_radref(acb_imagref(x)))))
_fmpz_clear_mpz(MAG_EXP(arb_radref(acb_imagref(x))));
}

50
acb/fprintn.c Normal file
View file

@ -0,0 +1,50 @@
/*
Copyright (C) 2015 Fredrik Johansson
Copyright (C) 2015 Arb authors
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "acb.h"
void
acb_fprintn(FILE * file, const acb_t z, long digits, ulong flags)
{
if (arb_is_zero(acb_imagref(z)))
{
arb_fprintn(file, acb_realref(z), digits, flags);
}
else if (arb_is_zero(acb_realref(z)))
{
arb_fprintn(file, acb_imagref(z), digits, flags);
flint_fprintf(file, "*I");
}
else
{
arb_fprintn(file, acb_realref(z), digits, flags);
if ((arb_is_exact(acb_imagref(z)) || (flags & ARB_STR_NO_RADIUS))
&& arf_sgn(arb_midref(acb_imagref(z))) < 0)
{
arb_t t;
arb_init(t);
arb_neg(t, acb_imagref(z));
flint_fprintf(file, " - ");
arb_fprintn(file, t, digits, flags);
arb_clear(t);
}
else
{
flint_fprintf(file, " + ");
arb_fprintn(file, acb_imagref(z), digits, flags);
}
flint_fprintf(file, "*I");
}
}

42
acb/nth_root.c Normal file
View file

@ -0,0 +1,42 @@
/*
Copyright (C) 2016 Pascal Molin
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "acb_dirichlet.h"
static void
_acb_nth_root(acb_t res, ulong order, slong prec)
{
fmpq_t t;
fmpq_init(t);
fmpq_set_si(t, 2, order);
arb_sin_cos_pi_fmpq(acb_imagref(res), acb_realref(res), t, prec);
fmpq_clear(t);
}
void
acb_nth_root(acb_t res, ulong order, slong prec)
{
switch (order)
{
case 1:
acb_one(res);
break;
case 2:
acb_set_si(res, -1);
break;
case 4:
acb_onei(res);
break;
default:
_acb_nth_root(res, order, prec);
break;
}
}

View file

@ -59,6 +59,8 @@ _acb_sinc_diffbound(acb_t res, const acb_t z, slong prec)
arf_set(arb_midref(acb_realref(res)), arb_midref(acb_realref(z))); arf_set(arb_midref(acb_realref(res)), arb_midref(acb_realref(z)));
arf_set(arb_midref(acb_imagref(res)), arb_midref(acb_imagref(z))); arf_set(arb_midref(acb_imagref(res)), arb_midref(acb_imagref(z)));
mag_zero(arb_radref(acb_realref(res)));
mag_zero(arb_radref(acb_imagref(res)));
_acb_sinc_direct(res, res, prec); _acb_sinc_direct(res, res, prec);

91
acb/vec_nth_root.c Normal file
View file

@ -0,0 +1,91 @@
/*
Copyright (C) 2016 Pascal Molin
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "acb_dirichlet.h"
/* assume xs has size >= len * step */
void
_acb_vec_set_powers_step(acb_ptr xs, slong n, slong len, slong step, slong prec)
{
slong i, j;
prec += n_clog(n, 2);
for (i = 0, j = 0; i < len; i++, j += step)
{
if (i == 0)
acb_one(xs + j);
else if (i == 1)
acb_nth_root(xs + j, n, prec);
else if (i % 2 == 0)
acb_mul(xs + j, xs + j / 2, xs + j / 2, prec);
else
acb_mul(xs + j, xs + j - step, xs + step, prec);
}
}
/* assume len = p^e and z has size >= len * step */
void
_acb_vec_nth_roots_pe(acb_ptr z, slong p, slong e, slong len, slong step, slong prec)
{
if (e <= 1)
{
_acb_vec_set_powers_step(z, p, len, step, prec);
}
else
{
slong q, r;
_acb_vec_nth_roots_pe(z, p, e - 1, len / p, step * p, prec);
_acb_vec_set_powers_step(z, n_pow(p, e), p, step, prec);
for (q = p; q < len; q += p)
for (r = 1; r < p; r++)
acb_mul(z + (q + r) * step, z + q * step, z + r * step, prec);
}
}
void
_acb_vec_nth_roots(acb_ptr z, slong len, slong prec)
{
slong i, q;
n_factor_t fac;
acb_one(z + 0);
n_factor_init(&fac);
n_factor(&fac, len, 0);
q = 1;
for (i = 0; i < fac.num; i++)
{
slong p, e, pe, mp, mq;
p = fac.p[i];
e = fac.exp[i];
pe = n_pow(p, e);
mp = len / pe;
mq = len / q;
_acb_vec_nth_roots_pe(z, p, e, pe, mp, prec);
if (i > 0)
{
slong k, l;
for (k = mp; k < len; k += mp)
{
for (l = mq; l < len - k; l += mq)
acb_mul(z + k + l, z + k, z + l, prec);
for (; l < len; l += mq)
acb_mul(z + k + l - len, z + k, z + l, prec);
}
}
q *= pe;
}
}

View file

@ -1,6 +1,7 @@
/* /*
Copyright (C) 2015 Jonathan Bober Copyright (C) 2015 Jonathan Bober
Copyright (C) 2016 Fredrik Johansson Copyright (C) 2016 Fredrik Johansson
Copyright (C) 2016 Pascal Molin
This file is part of Arb. This file is part of Arb.
@ -13,43 +14,98 @@
#ifndef ACB_DIRICHLET_H #ifndef ACB_DIRICHLET_H
#define ACB_DIRICHLET_H #define ACB_DIRICHLET_H
#ifdef ACB_DIRICHLET_INLINES_C
#define ACB_DIRICHLET_INLINE
#else
#define ACB_DIRICHLET_INLINE static __inline__
#endif
#include "acb.h" #include "acb.h"
#include "dirichlet.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
typedef struct
{
ulong q; /* modulus */
ulong q_even; /* even part of modulus */
ulong q_odd; /* odd part of modulus */
ulong phi_q; /* phi(q) */
ulong phi_q_odd; /* phi(q_odd) */
slong num; /* number of odd prime factors */
ulong * primes; /* odd primes p[k] */
ulong * exponents; /* exponents e[k] */
ulong * generators; /* generator for each odd prime p[k] */
ulong * PHI; /* PHI(k) = phi(q_odd) / phi(p[k]^e[k]) */
}
acb_dirichlet_group_struct;
typedef acb_dirichlet_group_struct acb_dirichlet_group_t[1];
void _acb_dirichlet_euler_product_real_ui(arb_t res, ulong s, void _acb_dirichlet_euler_product_real_ui(arb_t res, ulong s,
const signed char * chi, int mod, int reciprocal, slong prec); const signed char * chi, int mod, int reciprocal, slong prec);
void acb_dirichlet_eta(acb_t res, const acb_t s, slong prec); void acb_dirichlet_eta(acb_t res, const acb_t s, slong prec);
void acb_dirichlet_group_init(acb_dirichlet_group_t G, ulong q); void acb_dirichlet_pairing(acb_t res, const dirichlet_group_t G, ulong m, ulong n, slong prec);
void acb_dirichlet_pairing_char(acb_t res, const dirichlet_group_t G, const dirichlet_char_t a, const dirichlet_char_t b, slong prec);
void acb_dirichlet_group_clear(acb_dirichlet_group_t G); /* precompute powers of a root of unity */
typedef struct
{
ulong order;
acb_t z;
slong size;
slong depth;
acb_ptr * Z;
}
acb_dirichlet_powers_struct;
void acb_dirichlet_chi(acb_t res, const acb_dirichlet_group_t G, ulong m, ulong n, slong prec); typedef acb_dirichlet_powers_struct acb_dirichlet_powers_t[1];
void _acb_dirichlet_powers_init(acb_dirichlet_powers_t t, ulong order, slong size, slong depth, slong prec);
void acb_dirichlet_powers_init(acb_dirichlet_powers_t t, ulong order, slong num, slong prec);
void acb_dirichlet_powers_clear(acb_dirichlet_powers_t t);
void acb_dirichlet_power(acb_t z, const acb_dirichlet_powers_t t, ulong n, slong prec);
void acb_dirichlet_chi(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, ulong n, slong prec);
void acb_dirichlet_chi_vec(acb_ptr v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv, slong prec);
void acb_dirichlet_arb_quadratic_powers(arb_ptr v, slong nv, const arb_t x, slong prec);
void acb_dirichlet_qseries_arb(acb_t res, acb_srcptr a, const arb_t x, slong len, slong prec);
void acb_dirichlet_qseries_arb_powers_naive(acb_t res, const arb_t x, int parity, const ulong *a, const acb_dirichlet_powers_t z, slong len, slong prec);
void acb_dirichlet_qseries_arb_powers_smallorder(acb_t res, const arb_t x, int parity, const ulong *a, const acb_dirichlet_powers_t z, slong len, slong prec);
ulong acb_dirichlet_theta_length_d(ulong q, double x, slong prec);
ulong acb_dirichlet_theta_length(ulong q, const arb_t x, slong prec);
void mag_tail_kexpk2_arb(mag_t res, const arb_t a, ulong n);
void _acb_dirichlet_theta_argument_at_arb(arb_t xt, ulong q, const arb_t t, slong prec);
void acb_dirichlet_theta_arb(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, const arb_t t, slong prec);
void acb_dirichlet_ui_theta_arb(acb_t res, const dirichlet_group_t G, ulong a, const arb_t t, slong prec);
void acb_dirichlet_gauss_sum_naive(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec);
void acb_dirichlet_gauss_sum_factor(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec);
void acb_dirichlet_gauss_sum_order2(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec);
void acb_dirichlet_gauss_sum_theta(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec);
void acb_dirichlet_gauss_sum(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec);
void acb_dirichlet_root_number_theta(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec);
void acb_dirichlet_root_number(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec);
void acb_dirichlet_si_poly_evaluate(acb_t res, slong * v, slong len, const acb_t z, slong prec);
void acb_dirichlet_jacobi_sum_naive(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi1, const dirichlet_char_t chi2, slong prec);
ulong jacobi_one_prime(ulong p, ulong e, ulong pe, ulong cond);
void acb_dirichlet_jacobi_sum_factor(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi1, const dirichlet_char_t chi2, slong prec);
void acb_dirichlet_jacobi_sum_gauss(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi1, const dirichlet_char_t chi2, slong prec);
void acb_dirichlet_jacobi_sum(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi1, const dirichlet_char_t chi2, slong prec);
void acb_dirichlet_jacobi_sum_ui(acb_t res, const dirichlet_group_t G, ulong a, ulong b, slong prec);
void acb_dirichlet_l_euler_product(acb_t res, const acb_t s, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec);
void acb_dirichlet_l_hurwitz(acb_t res, const acb_t s, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec);
void acb_dirichlet_l(acb_t res, const acb_t s, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec);
void acb_dirichlet_l_jet(acb_ptr res, const acb_t s, const dirichlet_group_t G, const dirichlet_char_t chi, int deflate, slong len, slong prec);
/* utils */
ACB_DIRICHLET_INLINE void
acb_vec_printd(acb_srcptr vec, slong len, slong digits)
{
slong i;
for (i = 0; i < len; i++)
acb_printd(vec + i, digits), flint_printf("\n");
}
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif #endif

View file

@ -0,0 +1,38 @@
/*
Copyright (C) 2016 Pascal Molin
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "acb_dirichlet.h"
/* TODO: BSGS can reduce to nv mul */
void
acb_dirichlet_arb_quadratic_powers(arb_ptr v, slong nv, const arb_t x, slong prec)
{
slong i;
arb_t dx, x2;
arb_init(dx);
arb_init(x2);
arb_set(dx, x);
arb_mul(x2, x, x, prec);
for (i = 0; i < nv; i++)
{
if (i == 0)
arb_one(v + i);
else if (i == 1)
arb_set_round(v + i, x, prec);
else
{
arb_mul(dx, dx, x2, prec);
arb_mul(v + i, v + i - 1, dx, prec);
}
}
arb_clear(dx);
arb_clear(x2);
}

View file

@ -1,6 +1,7 @@
/* /*
Copyright (C) 2015 Jonathan Bober Copyright (C) 2015 Jonathan Bober
Copyright (C) 2016 Fredrik Johansson Copyright (C) 2016 Fredrik Johansson
Copyright (C) 2016 Pascal Molin
This file is part of Arb. This file is part of Arb.
@ -12,116 +13,19 @@
#include "acb_dirichlet.h" #include "acb_dirichlet.h"
/* todo: modular arithmetic */
static ulong
chi_odd_exponent(const acb_dirichlet_group_t G, ulong m, ulong n)
{
ulong x, k, pk, gk, logm, logn;
x = 0;
for (k = 0; k < G->num; k++)
{
pk = n_pow(G->primes[k], G->exponents[k]);
gk = G->generators[k] % pk;
logm = n_discrete_log_bsgs(m % pk, gk, pk);
logn = n_discrete_log_bsgs(n % pk, gk, pk);
x = (x + G->PHI[k] * logm * logn) % G->phi_q_odd;
}
return x;
}
static ulong
chi_even_exponent(const acb_dirichlet_group_t G, ulong m, ulong n)
{
ulong x;
ulong q_even = G->q_even;
if (q_even <= 2)
return 0;
x = 0;
if ((m % 4 == 3) && (n % 4 == 3))
x = q_even / 8;
if (q_even > 4)
{
ulong g2, logm, logn;
g2 = 5;
if (m % 4 == 3)
{
m = n_negmod(m, q_even);
}
if (n % 4 == 3)
{
n = n_negmod(n, q_even);
}
logm = n_discrete_log_bsgs(m % q_even, g2, q_even);
logn = n_discrete_log_bsgs(n % q_even, g2, q_even);
x += logm * logn;
}
return x % (q_even / 4);
}
void void
acb_dirichlet_chi(acb_t res, const acb_dirichlet_group_t G, ulong m, ulong n, slong prec) acb_dirichlet_chi(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, ulong n, slong prec)
{
fmpq_t t, u;
ulong odd_part, even_part;
ulong q_even = G->q_even;
ulong q_odd = G->q_odd;
if ((q_even > 1 && (n % 2 == 0)) || (q_odd > 1 && (n_gcd(q_odd, n) != 1)))
{ {
ulong expo;
expo = dirichlet_chi(G, chi, n);
if (expo == DIRICHLET_CHI_NULL)
acb_zero(res); acb_zero(res);
return;
}
if (q_even > 2)
{
if (q_even == 4)
{
if (m % 4 == 3 && n % 4 == 3)
even_part = q_even / 2; /* -1 */
else
even_part = 0; /* 1 */
}
else else
{ {
even_part = 4 * chi_even_exponent(G, m % q_even, n % q_even); fmpq_t t;
}
}
else
{
even_part = 0;
}
if (q_odd > 1)
odd_part = chi_odd_exponent(G, m % q_odd, n % q_odd);
else
odd_part = 0;
fmpq_init(t); fmpq_init(t);
fmpq_init(u); fmpq_set_si(t, 2 * expo , G->expo);
fmpq_set_si(t, 2 * even_part, q_even);
fmpq_set_si(u, 2 * odd_part, G->phi_q_odd);
fmpq_add(t, t, u);
arb_sin_cos_pi_fmpq(acb_imagref(res), acb_realref(res), t, prec); arb_sin_cos_pi_fmpq(acb_imagref(res), acb_realref(res), t, prec);
fmpq_clear(t); fmpq_clear(t);
fmpq_clear(u);
} }
}

38
acb_dirichlet/chi_vec.c Normal file
View file

@ -0,0 +1,38 @@
/*
Copyright (C) 2016 Pascal Molin
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "acb_dirichlet.h"
void
acb_dirichlet_chi_vec(acb_ptr v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv, slong prec)
{
slong k;
ulong * a, order;
acb_dirichlet_powers_t t;
a = flint_malloc(nv * sizeof(ulong));
order = dirichlet_order_char(G, chi);
dirichlet_chi_vec_order(a, G, chi, order, nv);
acb_dirichlet_powers_init(t, order, nv, prec);
acb_zero(v + 0);
for (k = 0; k < nv; k++)
{
if (a[k] != DIRICHLET_CHI_NULL)
acb_dirichlet_power(v + k, t, a[k], prec);
else
acb_zero(v + k);
}
acb_dirichlet_powers_clear(t);
flint_free(a);
}

View file

@ -34,4 +34,3 @@ acb_dirichlet_eta(acb_t res, const acb_t s, slong prec)
acb_clear(t); acb_clear(t);
} }
} }

112
acb_dirichlet/gauss_sum.c Normal file
View file

@ -0,0 +1,112 @@
/*
Copyright (C) 2016 Pascal Molin
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "acb_dirichlet.h"
static void
gauss_sum_non_primitive(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, ulong cond, slong prec)
{
slong k, mu = 1;
ulong NN0 = G->q / cond;
/* G(chi) = mu(N/N0)chi0(N/N0)G(chi0) */
if (NN0 % 2 == 0)
{
if (G->q % 4)
mu = -1;
else
{
acb_zero(res);
return;
}
}
for (k = G->neven; k < G->num; k++)
{
ulong p = G->P[k].p;
if (G->P[k].e > 1 && NN0 % (p*p) == 0)
{
acb_zero(res);
return;
}
if (NN0 % p == 0)
mu *= -1;
}
if (chi->n == 1)
{
acb_set_si(res, mu);
}
else
{
dirichlet_group_t G0;
dirichlet_char_t chi0;
acb_t z;
/* primitive char associated to chi */
dirichlet_subgroup_init(G0, G, cond);
dirichlet_char_init(chi0, G0);
dirichlet_char_lower(chi0, G0, chi, G);
acb_init(z);
acb_dirichlet_gauss_sum(z, G0, chi0, prec);
acb_dirichlet_chi(res, G0, chi0, NN0, prec);
acb_mul(res, res, z, prec);
acb_mul_si(res, res, mu, prec);
dirichlet_group_clear(G0);
dirichlet_char_clear(chi0);
acb_clear(z);
}
}
void
acb_dirichlet_gauss_sum(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec)
{
ulong cond = dirichlet_conductor_char(G, chi);
/* TODO: no need, factor also does it... */
if (cond != G->q)
{
gauss_sum_non_primitive(res, G, chi, cond, prec);
}
else if (dirichlet_char_is_real(G, chi))
{
acb_dirichlet_gauss_sum_order2(res, G, chi, prec);
}
else if (G->num > 1 && G->num > G->neven)
{
acb_dirichlet_gauss_sum_factor(res, G, chi, prec);
}
else
{
/* must be non primitive */
if (acb_dirichlet_theta_length_d(G->q, 1, prec) > G->q)
acb_dirichlet_gauss_sum_naive(res, G, chi, prec);
else
acb_dirichlet_gauss_sum_theta(res, G, chi, prec);
}
}
void
acb_dirichlet_gauss_sum_ui(acb_t res, const dirichlet_group_t G, ulong a, slong prec)
{
dirichlet_char_t chi;
dirichlet_char_init(chi, G);
dirichlet_char_log(chi, G, a);
acb_dirichlet_gauss_sum(res, G, chi, prec);
dirichlet_char_clear(chi);
}

View file

@ -0,0 +1,70 @@
/*
Copyright (C) 2016 Pascal Molin
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "acb_dirichlet.h"
void
acb_dirichlet_gauss_sum_factor(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec)
{
slong k;
acb_t tmp;
/* early check */
for (k = (G->neven == 2); k < G->num; k++)
{
/* if e > 1 and not primitive, 0 */
if (chi->log[k] % G->P[k].p == 0 && G->P[k].e > 1)
{
acb_zero(res);
return;
}
}
/* factor */
acb_one(res);
acb_init(tmp);
for (k = (G->neven == 2); k < G->num; k++)
{
ulong pe = G->P[k].pe.n;
dirichlet_group_t Gp;
dirichlet_char_t chip;
dirichlet_subgroup_init(Gp, G, pe);
dirichlet_char_init(chip, Gp);
chip->n = chi->n % pe;
if (k == 1 && G->neven == 2)
{
chip->log[0] = chi->log[0];
chip->log[1] = chi->log[1];
}
else
chip->log[0] = chi->log[k];
/* chi_pe(a, q/pe) * G_pe(a) */
acb_dirichlet_gauss_sum(tmp, Gp, chip, prec);
acb_mul(res, res, tmp, prec);
acb_dirichlet_chi(tmp, Gp, chip, (G->q / pe) % pe, prec);
acb_mul(res, res, tmp, prec);
dirichlet_char_clear(chip);
dirichlet_group_clear(Gp);
}
if (G->q_even == 2)
acb_neg(res, res);
acb_clear(tmp);
}

View file

@ -0,0 +1,31 @@
/*
Copyright (C) 2016 Pascal Molin
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "acb_dirichlet.h"
#include "acb_poly.h"
void
acb_dirichlet_gauss_sum_naive(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec)
{
acb_t z;
acb_ptr v;
v = _acb_vec_init(G->q);
acb_dirichlet_chi_vec(v, G, chi, G->q, prec);
acb_init(z);
acb_nth_root(z, G->q, prec);
_acb_poly_evaluate(res, v, G->q, z, prec);
acb_clear(z);
_acb_vec_clear(v, G->q);
}

View file

@ -0,0 +1,27 @@
/*
Copyright (C) 2016 Pascal Molin
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "acb_dirichlet.h"
void
acb_dirichlet_gauss_sum_order2(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec)
{
if (dirichlet_parity_char(G, chi))
{
arb_zero(acb_realref(res));
arb_sqrt_ui(acb_imagref(res), G->q, prec);
}
else
{
arb_zero(acb_imagref(res));
arb_sqrt_ui(acb_realref(res), G->q, prec);
}
}

View file

@ -0,0 +1,35 @@
/*
Copyright (C) 2016 Pascal Molin
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "acb_dirichlet.h"
void
acb_dirichlet_gauss_sum_theta(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec)
{
ulong cond = dirichlet_conductor_char(G, chi);
if (cond < G->q || (G->q == 300 && (chi->n == 71 || chi->n == 131))
|| (G->q == 600 && (chi->n == 11 || chi->n == 491)))
{
flint_printf("gauss_sum_theta: non available for non primitive character"
"or exceptional characters chi_300(71,.), chi_300(131,.), "
"chi_600(11,.) and chi_600(491,.)\n");
abort();
}
else
{
acb_t iq;
acb_init(iq);
acb_dirichlet_gauss_sum_order2(iq, G, chi, prec);
acb_dirichlet_root_number_theta(res, G, chi, prec);
acb_mul(res, res, iq, prec);
acb_clear(iq);
}
}

View file

@ -1,84 +0,0 @@
/*
Copyright (C) 2015 Jonathan Bober
Copyright (C) 2016 Fredrik Johansson
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "acb_dirichlet.h"
static ulong
primitive_root_p_and_p2(ulong p)
{
if (p == 40487)
return 10;
#if FLINT_BITS == 64
if (p == UWORD(6692367337))
return 7;
if (p > UWORD(1000000000000))
{
printf("primitive root: p > 10^12 not implemented");
abort();
}
#endif
return n_primitive_root_prime(p);
}
void
acb_dirichlet_group_init(acb_dirichlet_group_t G, ulong q)
{
slong k;
n_factor_t fac;
G->q = q;
G->q_odd = q;
G->q_even = 1;
while (G->q_odd % 2 == 0)
{
G->q_odd /= 2;
G->q_even *= 2;
}
n_factor_init(&fac);
n_factor(&fac, G->q_odd, 1);
G->num = fac.num;
G->primes = flint_malloc(G->num * sizeof(ulong));
G->exponents = flint_malloc(G->num * sizeof(ulong));
G->generators = flint_malloc(G->num * sizeof(ulong));
G->PHI = flint_malloc(G->num * sizeof(ulong));
for (k = 0; k < G->num; k++)
{
G->primes[k] = fac.p[k];
G->exponents[k] = fac.exp[k];
}
G->phi_q_odd = 1;
for (k = 0; k < G->num; k++)
G->phi_q_odd *= (G->primes[k] - 1) * n_pow(G->primes[k], G->exponents[k]-1);
if (G->q_even == 1)
G->phi_q = G->phi_q_odd;
else
G->phi_q = G->phi_q_odd * (G->q_even / 2);
for (k = 0; k < G->num; k++)
{
ulong phi;
G->generators[k] = primitive_root_p_and_p2(G->primes[k]);
phi = n_pow(G->primes[k], G->exponents[k] - 1) * (G->primes[k] - 1);
G->PHI[k] = G->phi_q_odd / phi;
}
}

109
acb_dirichlet/jacobi_sum.c Normal file
View file

@ -0,0 +1,109 @@
/*
Copyright (C) 2016 Pascal Molin
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "acb_dirichlet.h"
/* J_N(1,a) = sum on x = 1 mod some p | q */
ulong
jacobi_one_prime(ulong p, ulong e, ulong pe, ulong cond)
{
if (e > 1 && cond % (p*p) == 0)
{
return 0;
}
else
{
slong r = (e > 1) ? pe / p : 1;
if (cond % p)
return r * (p - 2);
else
return -r;
}
}
static ulong
jacobi_one(const dirichlet_group_t G, ulong cond)
{
slong k, r = 1;
for (k = 0; k < G->num; k++)
r *= jacobi_one_prime(G->P[k].p, G->P[k].e,
G->P[k].pe.n, cond);
return r;
}
void
acb_dirichlet_jacobi_sum(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi1, const dirichlet_char_t chi2, slong prec)
{
if (G->q_even > 1)
{
acb_zero(res);
}
else if (chi1->n == 1 || chi2->n == 1)
{
ulong cond = (chi1->n == 1) ? dirichlet_conductor_char(G, chi2) : dirichlet_conductor_char(G, chi1);
acb_set_si(res, jacobi_one(G, cond));
}
else if (nmod_mul(chi1->n, chi2->n, G->mod) == 1)
{
ulong n;
n = jacobi_one(G, dirichlet_conductor_char(G, chi1));
if (dirichlet_parity_char(G, chi1))
acb_set_si(res, -n);
else
acb_set_si(res, n);
}
else
{
if (G->q <= 150)
acb_dirichlet_jacobi_sum_naive(res, G, chi1, chi2, prec);
else if (G->num > 1)
acb_dirichlet_jacobi_sum_factor(res, G, chi1, chi2, prec);
else if (G->P[0].e > 1)
acb_dirichlet_jacobi_sum_naive(res, G, chi1, chi2, prec);
else
acb_dirichlet_jacobi_sum_gauss(res, G, chi1, chi2, prec);
}
}
void
acb_dirichlet_jacobi_sum_ui(acb_t res, const dirichlet_group_t G, ulong a, ulong b, slong prec)
{
if (G->q_even > 1)
{
acb_zero(res);
}
else if (a == 1 || b == 1)
{
ulong cond = (a == 1) ? dirichlet_conductor_ui(G, b) : dirichlet_conductor_ui(G, a);
acb_set_si(res, jacobi_one(G, cond));
}
else if (nmod_mul(a, b, G->mod) == 1)
{
ulong n;
n = jacobi_one(G, dirichlet_conductor_ui(G, a));
if (dirichlet_parity_ui(G, a))
acb_set_si(res, -n);
else
acb_set_si(res, n);
}
else
{
dirichlet_char_t chi1, chi2;
dirichlet_char_init(chi1, G);
dirichlet_char_init(chi2, G);
dirichlet_char_log(chi1, G, a);
dirichlet_char_log(chi2, G, b);
acb_dirichlet_jacobi_sum(res, G, chi1, chi2, prec);
dirichlet_char_clear(chi1);
dirichlet_char_clear(chi2);
}
}

View file

@ -0,0 +1,76 @@
/*
Copyright (C) 2016 Pascal Molin
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "acb_dirichlet.h"
void
acb_dirichlet_jacobi_sum_factor(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi1, const dirichlet_char_t chi2, slong prec)
{
slong k;
acb_t tmp;
acb_init(tmp);
acb_one(res);
/* TODO: efficient subgroup */
for (k = 0; k < G->num; k++)
{
nmod_t pe;
ulong p, e, ap, bp;
p = G->P[k].p;
e = G->P[k].e;
pe = G->P[k].pe;
ap = chi1->n % pe.n;
bp = chi2->n % pe.n;
if (ap == 1 || bp == 1 || nmod_mul(ap, bp, pe) == 1)
{
slong r;
ulong cond;
cond = (ap == 1) ? dirichlet_conductor_char(G, chi2) : dirichlet_conductor_char(G, chi1);
r = jacobi_one_prime(p, e, pe.n, cond);
/* chi(a,-1) if ap * bp = 1 */
if (ap != 1 && bp != 1)
r *= n_jacobi_unsigned(ap, p);
acb_mul_si(res, res, r, prec);
}
else
{
dirichlet_group_t Gp;
dirichlet_char_t chi1p, chi2p;
dirichlet_group_init(Gp, pe.n);
dirichlet_char_init(chi1p, Gp);
dirichlet_char_init(chi2p, Gp);
chi1p->n = ap;
chi1p->log[0] = chi1->log[k];
chi2p->n = ap;
chi2p->log[0] = chi2->log[k];
/* TODO: work out gauss relations for e > 1 */
if (p <= 100 || e > 1)
acb_dirichlet_jacobi_sum_naive(tmp, Gp, chi1p, chi2p, prec);
else
acb_dirichlet_jacobi_sum_gauss(tmp, Gp, chi1p, chi2p, prec);
acb_mul(res, res, tmp, prec);
dirichlet_char_clear(chi1p);
dirichlet_char_clear(chi2p);
dirichlet_group_clear(Gp);
}
}
acb_clear(tmp);
}

View file

@ -0,0 +1,38 @@
/*
Copyright (C) 2016 Pascal Molin
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "acb_dirichlet.h"
/* should use only for prime power modulus */
void
acb_dirichlet_jacobi_sum_gauss(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi1, const dirichlet_char_t chi2, slong prec)
{
/* J_q(a,b)G_q(ab) = G_q(a)G_q(b) */
acb_t tmp;
dirichlet_char_t chi12;
dirichlet_char_init(chi12, G);
dirichlet_char_mul(chi12, G, chi1, chi2);
acb_init(tmp);
acb_dirichlet_gauss_sum(res, G, chi1, prec);
if (chi2->n == chi1->n)
acb_set(tmp, res);
else
acb_dirichlet_gauss_sum(tmp, G, chi2, prec);
acb_mul(res, res, tmp, prec);
acb_dirichlet_gauss_sum(tmp, G, chi12, prec);
acb_div(res, res, tmp, prec);
dirichlet_char_clear(chi12);
acb_clear(tmp);
}

View file

@ -0,0 +1,61 @@
/*
Copyright (C) 2016 Pascal Molin
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "acb_dirichlet.h"
void
acb_dirichlet_jacobi_sum_naive(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi1, const dirichlet_char_t chi2, slong prec)
{
ulong k1, k2, m1, m2, g, e, m;
ulong * v1, * v2;
slong *v;
nmod_t expo;
acb_t z;
v1 = flint_malloc(G->q * sizeof(ulong));
v2 = flint_malloc(G->q * sizeof(ulong));
dirichlet_vec_set_null(v1, G, G->q);
dirichlet_chi_vec_loop(v1, G, chi1, G->q);
dirichlet_vec_set_null(v2, G, G->q);
dirichlet_chi_vec_loop(v2, G, chi2, G->q);
nmod_init(&expo, G->expo);
m1 = dirichlet_order_char(G, chi1);
m2 = dirichlet_order_char(G, chi2);
g = m1 * m2 / n_gcd(m1, m2);
m = G->expo / g;
v = flint_malloc(g * sizeof(slong));
for (e = 0; e < g; e++)
v[e] = 0;
for (k1 = 2, k2 = G->q - 1; k2 > 1; k1++, k2--)
{
if (v1[k1] == DIRICHLET_CHI_NULL ||
v2[k2] == DIRICHLET_CHI_NULL)
continue;
e = nmod_add(v1[k1], v2[k2], expo) / m;
v[e]++;
}
acb_init(z);
acb_nth_root(z, g, prec);
acb_dirichlet_si_poly_evaluate(res, v, g, z, prec);
acb_clear(z);
flint_free(v);
flint_free(v2);
flint_free(v1);
}

View file

@ -1,5 +1,6 @@
/* /*
Copyright (C) 2016 Fredrik Johansson Copyright (C) 2016 Fredrik Johansson
Copyright (C) 2016 Pascal Molin
This file is part of Arb. This file is part of Arb.
@ -13,39 +14,16 @@
void void
acb_dirichlet_l(acb_t res, const acb_t s, acb_dirichlet_l(acb_t res, const acb_t s,
const acb_dirichlet_group_t G, ulong m, slong prec) const dirichlet_group_t G, const dirichlet_char_t chi, slong prec)
{ {
acb_t chi, t, u, a; /* this cutoff is probably too conservative when q is large */
ulong k; if (arf_cmp_d(arb_midref(acb_realref(s)), 8 + 0.5 * prec / log(prec)) >= 0)
acb_init(chi);
acb_init(t);
acb_init(u);
acb_init(a);
acb_zero(t);
for (k = 1; k <= G->q; k++)
{ {
acb_dirichlet_chi(chi, G, m, k, prec); acb_dirichlet_l_euler_product(res, s, G, chi, prec);
}
if (!acb_is_zero(chi)) else
{ {
acb_set_ui(a, k); acb_dirichlet_l_hurwitz(res, s, G, chi, prec);
acb_div_ui(a, a, G->q, prec);
acb_hurwitz_zeta(u, s, a, prec);
acb_addmul(t, chi, u, prec);
} }
} }
acb_set_ui(u, G->q);
acb_neg(a, s);
acb_pow(u, u, a, prec);
acb_mul(res, t, u, prec);
acb_clear(chi);
acb_clear(t);
acb_clear(u);
acb_clear(a);
}

View file

@ -0,0 +1,128 @@
/*
Copyright (C) 2016 Fredrik Johansson
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "acb_dirichlet.h"
#define ONE_OVER_LOG2 1.4426950408889634
void
acb_dirichlet_l_euler_product(acb_t res, const acb_t s,
const dirichlet_group_t G, const dirichlet_char_t chi, slong prec)
{
arf_t left;
slong wp, powprec, left_s;
ulong p, p_limit;
double p_needed_approx, powmag, logp, errmag;
int is_real;
acb_t t, u, v, c;
mag_t err;
if (!acb_is_finite(s))
{
acb_indeterminate(res);
return;
}
arf_init(left);
arf_set_mag(left, arb_radref(acb_realref(s)));
arf_sub(left, arb_midref(acb_realref(s)), left, 2 * MAG_BITS, ARF_RND_FLOOR);
/* Require re(s) >= 2. */
if (arf_cmp_si(left, 2) < 0)
{
acb_indeterminate(res);
arf_clear(left);
return;
}
is_real = acb_is_real(s) && dirichlet_char_is_real(G, chi);
/* L(s) ~= 1. */
if (arf_cmp_si(left, prec) > 0)
{
acb_one(res);
mag_hurwitz_zeta_uiui(arb_radref(acb_realref(res)), prec, 2);
if (!is_real)
mag_set(arb_radref(acb_imagref(res)), arb_radref(acb_realref(res)));
acb_inv(res, res, prec);
arf_clear(left);
return;
}
left_s = arf_get_si(left, ARF_RND_FLOOR);
/* Heuristic. */
wp = prec + FLINT_BIT_COUNT(prec) + (prec / left_s) + 4;
/* Don't work too hard if a small s was passed as input. */
p_limit = 100 + prec * sqrt(prec);
/* Truncating at p ~= 2^(prec/s) gives an error of 2^-prec */
if (((double) prec) / left_s > 50.0)
p_needed_approx = pow(2.0, 50.0);
else
p_needed_approx = pow(2.0, ((double) prec) / left_s);
p_needed_approx = FLINT_MIN(p_limit, p_needed_approx);
/* todo: use this to determine whether to precompute chi */
acb_init(t);
acb_init(u);
acb_init(v);
acb_init(c);
acb_one(v);
for (p = 2; p < p_limit; p = n_nextprime(p, 1))
{
/* p^s */
logp = log(p);
powmag = left_s * logp * ONE_OVER_LOG2;
/* zeta(s,p) ~= 1/p^s + 1/((s-1) p^(s-1)) */
errmag = (log(left_s - 1.0) + (left_s - 1.0) * logp) * ONE_OVER_LOG2;
errmag = FLINT_MIN(powmag, errmag);
if (errmag > prec + 2)
break;
powprec = FLINT_MAX(wp - powmag, 8);
acb_dirichlet_chi(c, G, chi, p, powprec);
if (!acb_is_zero(c))
{
acb_set_ui(t, p);
acb_pow(t, t, s, powprec);
acb_set_round(u, v, powprec);
acb_div(t, u, t, powprec);
acb_mul(t, t, c, powprec);
acb_sub(v, v, t, wp);
}
}
mag_init(err);
mag_hurwitz_zeta_uiui(err, left_s, p);
if (is_real)
arb_add_error_mag(acb_realref(v), err);
else
acb_add_error_mag(v, err);
mag_clear(err);
acb_inv(res, v, prec);
acb_clear(t);
acb_clear(u);
acb_clear(v);
acb_clear(c);
arf_clear(left);
}

80
acb_dirichlet/l_hurwitz.c Normal file
View file

@ -0,0 +1,80 @@
/*
Copyright (C) 2016 Fredrik Johansson
Copyright (C) 2016 Pascal Molin
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "acb_dirichlet.h"
#include "acb_poly.h"
void
acb_dirichlet_l_hurwitz(acb_t res, const acb_t s,
const dirichlet_group_t G, const dirichlet_char_t chi, slong prec)
{
ulong order, chin, mult;
acb_t t, u, a;
acb_ptr z;
dirichlet_char_t cn;
int deflate;
/* remove pole in Hurwitz zeta at s = 1 */
deflate = 0;
if (acb_is_one(s))
{
if (dirichlet_char_is_principal(G, chi))
{
acb_indeterminate(res);
return;
}
deflate = 1;
}
dirichlet_char_init(cn, G);
acb_init(t);
acb_init(u);
acb_init(a);
dirichlet_char_one(cn, G);
acb_zero(t);
prec += n_clog(G->phi_q, 2);
order = dirichlet_order_char(G, chi);
mult = G->expo / order;
z = _acb_vec_init(order);
_acb_vec_nth_roots(z, order, prec);
do {
chin = dirichlet_pairing_char(G, chi, cn) / mult;
acb_set_ui(a, cn->n);
acb_div_ui(a, a, G->q, prec);
if (deflate == 0)
acb_hurwitz_zeta(u, s, a, prec);
else
_acb_poly_zeta_cpx_series(u, s, a, 1, 1, prec);
acb_addmul(t, z + chin, u, prec);
} while (dirichlet_char_next(cn, G) >= 0);
acb_set_ui(u, G->q);
acb_neg(a, s);
acb_pow(u, u, a, prec);
acb_mul(res, t, u, prec);
dirichlet_char_clear(cn);
_acb_vec_clear(z, order);
acb_clear(t);
acb_clear(u);
acb_clear(a);
}

119
acb_dirichlet/l_jet.c Normal file
View file

@ -0,0 +1,119 @@
/*
Copyright (C) 2016 Fredrik Johansson
Copyright (C) 2016 Pascal Molin
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "acb_dirichlet.h"
#include "acb_poly.h"
void
acb_dirichlet_l_jet(acb_ptr res, const acb_t s,
const dirichlet_group_t G, const dirichlet_char_t chi,
int deflate, slong len, slong prec)
{
ulong order, chin, mult, phi;
acb_t a;
acb_ptr t, u, z;
dirichlet_char_t cn;
int deflate_hurwitz;
if (len <= 0)
return;
if (G->q == 1)
{
acb_init(a);
acb_one(a);
_acb_poly_zeta_cpx_series(res, s, a, deflate, len, prec);
acb_clear(a);
return;
}
if (len == 1 && !(deflate && dirichlet_char_is_principal(G, chi)))
{
acb_dirichlet_l(res, s, G, chi, prec);
return;
}
if (dirichlet_char_is_principal(G, chi))
deflate_hurwitz = deflate;
else
deflate_hurwitz = acb_is_one(s);
dirichlet_char_init(cn, G);
t = _acb_vec_init(len);
u = _acb_vec_init(len + 2);
acb_init(a);
dirichlet_char_one(cn, G);
prec += n_clog(G->phi_q, 2);
order = dirichlet_order_char(G, chi);
mult = G->expo / order;
z = _acb_vec_init(order);
_acb_vec_nth_roots(z, order, prec);
phi = 0;
do
{
chin = dirichlet_pairing_char(G, chi, cn) / mult;
acb_set_ui(a, cn->n);
acb_div_ui(a, a, G->q, prec);
_acb_poly_zeta_cpx_series(u, s, a, deflate_hurwitz, len, prec);
_acb_vec_scalar_addmul(t, u, len, z + chin, prec);
phi++;
}
while (dirichlet_char_next(cn, G) >= 0);
if (dirichlet_char_is_principal(G, chi) && deflate)
{
/* res = t * q^(-(s+x)) + [phi(q) * (q^(-(s+x)) - q^-1) / ((s+x)-1)] */
if (acb_is_one(s))
{
acb_set_ui(a, G->q);
_acb_poly_acb_invpow_cpx(u, a, s, len + 1, prec);
_acb_poly_mullow(res, t, len, u, len, len, prec);
acb_set_ui(u, phi);
_acb_vec_scalar_addmul(res, u + 1, len, u, prec);
}
else
{
acb_sub_ui(u, s, 1, prec);
acb_one(u + 1);
acb_set_ui(a, G->q);
_acb_poly_acb_invpow_cpx(u + 2, a, s, len, prec);
_acb_poly_mullow(res, t, len, u + 2, len, len, prec);
acb_inv(a, a, prec);
acb_sub(u + 2, u + 2, a, prec);
_acb_poly_div_series(t, u + 2, len, u, 2, len, prec);
acb_set_ui(u, phi);
_acb_vec_scalar_addmul(res, t, len, u, prec);
}
}
else
{
/* res = t * q^(-(s+x)) */
acb_set_ui(a, G->q);
_acb_poly_acb_invpow_cpx(u, a, s, len, prec);
_acb_poly_mullow(res, t, len, u, len, len, prec);
}
dirichlet_char_clear(cn);
_acb_vec_clear(z, order);
_acb_vec_clear(t, len);
_acb_vec_clear(u, len + 2);
acb_clear(a);
}

29
acb_dirichlet/pairing.c Normal file
View file

@ -0,0 +1,29 @@
/*
Copyright (C) 2016 Pascal Molin
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "acb_dirichlet.h"
void
acb_dirichlet_pairing(acb_t res, const dirichlet_group_t G, ulong m, ulong n, slong prec)
{
ulong expo;
expo = dirichlet_pairing(G, m, n);
if (expo == DIRICHLET_CHI_NULL)
acb_zero(res);
else
{
fmpq_t t;
fmpq_init(t);
fmpq_set_si(t, 2 * expo, G->expo);
arb_sin_cos_pi_fmpq(acb_imagref(res), acb_realref(res), t, prec);
fmpq_clear(t);
}
}

View file

@ -0,0 +1,29 @@
/*
Copyright (C) 2016 Pascal Molin
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "acb_dirichlet.h"
void
acb_dirichlet_pairing_char(acb_t res, const dirichlet_group_t G, const dirichlet_char_t a, const dirichlet_char_t b, slong prec)
{
ulong expo;
expo = dirichlet_pairing_char(G, a, b);
if (expo == DIRICHLET_CHI_NULL)
acb_zero(res);
else
{
fmpq_t t;
fmpq_init(t);
fmpq_set_si(t, 2 * expo, G->expo);
arb_sin_cos_pi_fmpq(acb_imagref(res), acb_realref(res), t, prec);
fmpq_clear(t);
}
}

36
acb_dirichlet/power.c Normal file
View file

@ -0,0 +1,36 @@
/*
Copyright (C) 2016 Pascal Molin
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "acb_dirichlet.h"
#include "acb_poly.h"
void
acb_dirichlet_power(acb_t z, const acb_dirichlet_powers_t t, ulong n, slong prec)
{
if (!t->depth)
{
acb_pow_ui(z, t->z, n, prec);
}
else
{
slong k;
ulong r;
r = n % t->size;
n = n / t->size;
acb_set(z, t->Z[0] + r);
for (k = 1; k < t->depth && n; k++)
{
r = n % t->size;
n = n / t->size;
acb_mul(z, z, t->Z[k] + r, prec);
}
}
}

View file

@ -0,0 +1,24 @@
/*
Copyright (C) 2016 Pascal Molin
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "acb_dirichlet.h"
void
acb_dirichlet_powers_clear(acb_dirichlet_powers_t t)
{
slong k;
for (k = 0; k < t->depth; k++)
_acb_vec_clear(t->Z[k], t->size);
flint_free(t->Z);
acb_clear(t->z);
}

View file

@ -0,0 +1,51 @@
/*
Copyright (C) 2016 Pascal Molin
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "acb_dirichlet.h"
#include "acb_poly.h"
void
_acb_dirichlet_powers_init(acb_dirichlet_powers_t t, ulong order, slong size, slong depth, slong prec)
{
slong k;
t->order = order;
acb_init(t->z);
acb_nth_root(t->z, order, prec);
t->size = size;
t->depth = depth;
if (depth)
{
acb_struct * z;
z = t->z + 0;
t->Z = flint_malloc(depth * sizeof(acb_ptr));
for (k = 0; k < depth; k++)
{
t->Z[k] = _acb_vec_init(size);
_acb_vec_set_powers(t->Z[k], z, size, prec);
z = t->Z[k] + 1;
}
}
else
{
t->Z = NULL;
}
}
void
acb_dirichlet_powers_init(acb_dirichlet_powers_t t, ulong order, slong num, slong prec)
{
slong size, depth;
depth = (num > order) ? 1 : n_flog(order, num);
size = n_root(order, depth) + 1;
_acb_dirichlet_powers_init(t, order, size, depth, prec);
}

View file

@ -0,0 +1,128 @@
/*
Copyright (C) 2016 Pascal Molin
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include "acb_dirichlet.h"
#include "profiler.h"
#define LOG 0
#define CSV 1
#define JSON 2
typedef void (*do_f) (acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong prec);
int main(int argc, char *argv[])
{
int out;
ulong n, nref, maxq = 5000;
ulong * rand;
flint_rand_t state;
slong r, nr;
int l, nf = 5;
do_f func[5] = { acb_dirichlet_gauss_sum_naive,
acb_dirichlet_gauss_sum_factor,
acb_dirichlet_gauss_sum_theta,
acb_dirichlet_gauss_sum,
acb_dirichlet_gauss_sum };
char * name[5] = { "naive", "factor", "theta", "default", "precomp" };
int i, ni = 5;
ulong qmin[5] = { 3, 50, 500, 1000, 10000 };
ulong qmax[5] = { 50, 100, 599, 1050, 10030 };
int j, nj = 3;
slong prec[3] = { 64, 128, 1024 };
if (argc < 2)
out = LOG;
else if (!strcmp(argv[1], "json"))
out = JSON;
else if (!strcmp(argv[1], "csv"))
out = CSV;
else if (!strcmp(argv[1], "log"))
out = LOG;
else
{
printf("usage: %s [log|csv|json]\n", argv[0]);
abort();
}
if (out == CSV)
flint_printf("# %-12s, %7s, %7s, %7s, %7s\n","name", "prec", "qmin", "qmax", "time");
for (j = 0; j < nj; j++)
{
for (i = 0; i < ni; i++)
{
if (out == LOG)
flint_printf("G_q(a) at prec %wu for all %wu <= q <= %wu....\n", prec[j], qmin[i], qmax[i]);
for (l = 0; l < nf; l++)
{
ulong q;
if (qmin[i] > 2000 && l == 0)
continue;
if (out == LOG)
flint_printf("%-14s ... ", name[l]);
else if (out == CSV)
flint_printf("%-12s, %7d, %7d, %7d, ", name[l], prec[j], qmin[i], qmax[i]);
else if (out == JSON)
flint_printf("{ \"name\": \"%s\", \"prec\": %d, \"qmin\": %d, \"qmax\": %d, \"time\": ",
name[l], prec[j], qmin[i], qmax[i]);
TIMEIT_ONCE_START
for (q = qmin[i]; q <= qmax[i]; q++)
{
acb_dirichlet_group_t G;
acb_dirichlet_char_t chi;
acb_t res;
if (q % 4 == 2)
continue;
acb_dirichlet_group_init(G, q);
if (l == 4)
acb_dirichlet_group_dlog_precompute(G, 1);
acb_dirichlet_char_init(chi, G);
acb_dirichlet_char_first_primitive(chi, G);
acb_init(res);
do {
func[l](res, G, chi, prec[j]);
} while (acb_dirichlet_char_next_primitive(chi, G) >= 0);
acb_clear(res);
acb_dirichlet_char_clear(chi);
if (l == 4)
acb_dirichlet_group_dlog_clear(G);
acb_dirichlet_group_clear(G);
}
TIMEIT_ONCE_STOP
if (out == JSON)
flint_printf("}\n");
else
flint_printf("\n");
}
}
}
flint_cleanup();
return EXIT_SUCCESS;
}

View file

@ -0,0 +1,124 @@
/*
Copyright (C) 2016 Pascal Molin
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include "acb_dirichlet.h"
#include "profiler.h"
#define LOG 0
#define CSV 1
#define JSON 2
typedef void (*do_f) (acb_t res, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi1, const acb_dirichlet_char_t chi2, slong prec);
int main(int argc, char *argv[])
{
int out;
ulong n, nref, maxq = 5000;
ulong * rand;
flint_rand_t state;
slong r, nr;
int l, nf = 4;
do_f func[4] = { acb_dirichlet_jacobi_sum_naive,
acb_dirichlet_jacobi_sum_factor,
acb_dirichlet_jacobi_sum_gauss,
acb_dirichlet_jacobi_sum };
char * name[4] = { "naive", "factor", "gauss", "default" };
int i, ni = 4;
ulong qmin[4] = { 3, 51, 501, 10001 };
ulong qmax[4] = { 30, 100, 550, 10050 };
int j, nj = 3;
slong prec[3] = { 64, 128, 1024 };
if (argc < 2)
out = LOG;
else if (!strcmp(argv[1], "json"))
out = JSON;
else if (!strcmp(argv[1], "csv"))
out = CSV;
else if (!strcmp(argv[1], "log"))
out = LOG;
else
{
printf("usage: %s [log|csv|json]\n", argv[0]);
abort();
}
if (out == CSV)
flint_printf("# %-12s, %7s, %7s, %7s, %7s\n","name", "prec", "qmin", "qmax", "time");
for (j = 0; j < nj; j++)
{
for (i = 0; i < ni; i++)
{
if (out == LOG)
flint_printf("J_q(a,b) at prec %wu for all %wu <= q <= %wu....\n", prec[j], qmin[i], qmax[i]);
for (l = 0; l < nf; l++)
{
ulong q;
if (out == LOG)
flint_printf("%-14s ... ", name[l]);
else if (out == CSV)
flint_printf("%-12s, %7d, %7d, %7d, ", name[l], prec[j], qmin[i], qmax[i]);
else if (out == JSON)
flint_printf("{ \"name\": \"%s\", \"prec\": %d, \"qmin\": %d, \"qmax\": %d, \"time\": ",
name[l], prec[j], qmin[i], qmax[i]);
TIMEIT_ONCE_START
for (q = qmin[i]; q <= qmax[i]; q+=2)
{
acb_dirichlet_group_t G;
acb_dirichlet_char_t chi1, chi2;
acb_t res;
acb_dirichlet_group_init(G, q);
acb_dirichlet_char_init(chi1, G);
acb_dirichlet_char_init(chi2, G);
acb_init(res);
do {
slong c = 0;
acb_dirichlet_char_set(chi2, G, chi1);
do {
func[l](res, G, chi1, chi2, prec[j]);
} while (acb_dirichlet_char_next(chi2, G) >= 0 && c++ < 30);
} while (acb_dirichlet_char_next(chi1, G) >= 0);
acb_clear(res);
acb_dirichlet_char_clear(chi1);
acb_dirichlet_char_clear(chi2);
acb_dirichlet_group_clear(G);
}
TIMEIT_ONCE_STOP
if (out == JSON)
flint_printf("}\n");
else
flint_printf("\n");
}
}
}
flint_cleanup();
return EXIT_SUCCESS;
}

View file

@ -0,0 +1,205 @@
/*
Copyright (C) 2016 Pascal Molin
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include "acb_dirichlet.h"
static int usage(char *argv[])
{
printf("usage: %s [--progress <step>] [--all] [--odd] [--prec <bits>] [--onlymod] {qmin qmax | --value q a}\n", argv[0]);
return 1;
}
static void
value(ulong q, ulong a, slong prec, slong digits)
{
acb_dirichlet_group_t G;
acb_dirichlet_char_t chi;
acb_t res;
arb_t one;
acb_dirichlet_group_init(G, q);
acb_dirichlet_char_init(chi, G);
acb_dirichlet_char(chi, G, a);
acb_init(res);
arb_init(one);
arb_one(one);
acb_dirichlet_theta_arb(res, G, chi, one, prec);
acb_printd(res, digits);
flint_printf("\n");
arb_clear(one);
acb_clear(res);
acb_dirichlet_group_clear(G);
acb_dirichlet_char_clear(chi);
}
static void
check_q(ulong q, int odd, slong prec, slong digits, int onlymod)
{
slong s;
ulong k, len;
acb_dirichlet_group_t G;
acb_dirichlet_conrey_t x;
acb_dirichlet_group_init(G, q);
acb_dirichlet_conrey_init(x, G);
acb_ptr theta, z;
arb_t z1;
arb_ptr t;
theta = _acb_vec_init(G->phi_q);
z = _acb_vec_init(G->phi_q);
arb_init(z1);
arb_const_pi(z1, prec);
arb_div_ui(z1, z1, q, prec);
arb_neg(z1, z1);
arb_exp(z1, z1, prec);
/* len = acb_dirichlet_theta_length_d(q, 1., prec); */
t = _arb_vec_init(q);
acb_dirichlet_arb_quadratic_powers(t, q, z1, prec);
for (s = 0; s <= odd; s++)
{
k = 0;
acb_dirichlet_conrey_one(x, G);
do {
acb_set_arb(z + k, t + x->n);
k++;
} while (acb_dirichlet_conrey_next(x, G) >= 0);
acb_dirichlet_dft_conrey(theta, z, G, prec);
/* check zeros */
acb_dirichlet_conrey_one(x, G);
for (k = 0; k < G->phi_q; k++)
{
if (acb_contains_zero(theta + k)
&& acb_dirichlet_conrey_conductor(G, x) == q
&& acb_dirichlet_conrey_parity(G, x) == s)
{
if (onlymod)
{
flint_printf("%wu,%wu\n",q,x->n);
}
else
{
flint_printf("\ntheta null q = %wu, n = %wu\n",q, x->n);
acb_printd(theta + k, digits);
flint_printf("\n");
}
}
acb_dirichlet_conrey_next(x, G);
}
if (odd)
{
/* change t for odd characters */
for (k = 0; k < q; k++)
arb_mul_ui(t + k, t + k, k, prec);
}
}
_arb_vec_clear(t, q);
_acb_vec_clear(theta, G->phi_q);
_acb_vec_clear(z, G->phi_q);
arb_clear(z1);
acb_dirichlet_conrey_clear(x);
acb_dirichlet_group_clear(G);
}
int main(int argc, char *argv[])
{
int i, all = 0, odd = 0, onlymod = 0, eval = 0;
slong prec = 50, digits = 10;
slong step = 0;
ulong q, qmin, qmax;
n_primes_t iter;
if (argc < 3)
return usage(argv);
for (i = 1; i < argc - 2; i++)
{
if (!strcmp(argv[i],"--eval"))
eval = 1;
if (!strcmp(argv[i],"--all"))
all = 1;
if (!strcmp(argv[i],"--onlymod"))
onlymod = 1;
else if (!strcmp(argv[i],"--odd"))
odd = 1;
else if (!strcmp(argv[i],"--progress"))
{
i++;
step = atol(argv[i]);
}
else if (!strcmp(argv[i],"--prec"))
{
i++;
prec = atol(argv[i]);
digits = floor(prec * 0.3);
}
}
if (argc < i + 2)
return usage(argv);
qmin = atol(argv[i]);
qmax = atol(argv[i+1]);
if (eval)
{
value(qmin, qmax, prec, digits);
}
else
{
if (all)
{
for (q = qmin; q <= qmax; q++)
{
if (q % 4 == 2)
continue;
check_q(q, odd, prec, digits, onlymod);
if (step && q % step == 0)
flint_printf("[%wu]",q);
}
}
else
{
ulong p;
slong it = 0;
/* look for vanishing theta values for prime power moduli */
n_primes_init(iter);
while ((p = n_primes_next(iter)) < qmax)
{
for (q = p; q < qmin; q*= p);
for (; q < qmax; q *= p)
check_q(q, odd, prec, digits, onlymod);
if (step && (it++ % step == 0))
flint_printf("[%wu]",p);
}
n_primes_clear(iter);
}
}
flint_cleanup();
return EXIT_SUCCESS;
}

View file

@ -0,0 +1,200 @@
/*
Copyright (C) 2016 Pascal Molin
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include "acb_dirichlet.h"
#include "profiler.h"
#define LOG 0
#define CSV 1
#define JSON 2
typedef void (*do_f) (ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv);
static void
do_empty(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv)
{
return;
}
static void
do_dlog_primeloop(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv)
{
slong k, l;
for (k = 0; k < nv; k++)
v[k] = 0;
for (l = G->neven; l < G->num; l++)
{
acb_dirichlet_prime_group_struct P = G->P[l];
dlog_vec_loop_add(v, nv, P.g, chi->expo[l], P.pe, P.phi, chi->order);
}
acb_dirichlet_ui_vec_set_null(v, G, nv);
}
static void
do_eratos(ulong *v, const acb_dirichlet_group_t G, const acb_dirichlet_char_t chi, slong nv)
{
slong k, p, pmax;
n_primes_t iter;
n_primes_init(iter);
pmax = (nv < G->q) ? nv : G->q;
v[1] = 0;
while ((p = n_primes_next(iter)) < pmax)
{
if (G->q % p == 0)
{
for (k = p; k < nv; k += p)
v[k] = ACB_DIRICHLET_CHI_NULL;
}
else
{
long chip;
chip = acb_dirichlet_ui_chi(G, chi, p);
for (k = p; k < nv; k += p)
if (v[k] != -1)
v[k] = nmod_add(v[k], chip, chi->order);
}
}
n_primes_clear(iter);
}
int main(int argc, char *argv[])
{
int out;
ulong n, nref, maxq = 5000;
ulong * rand;
flint_rand_t state;
slong r, nr;
int l, nf = 9;
do_f func[9] = { do_empty, acb_dirichlet_ui_chi_vec_loop, do_dlog_primeloop,
acb_dirichlet_ui_chi_vec_primeloop, do_eratos,
acb_dirichlet_ui_chi_vec,
acb_dirichlet_ui_chi_vec,
acb_dirichlet_ui_chi_vec,
acb_dirichlet_ui_chi_vec };
char * name[9] = { "char only", "big loop", "prime loops",
"prime dlog_vec", "manual eratos", "default",
"precomp 1", "precomp 20", "precomp 100" };
int i, ni = 5;
ulong qmin[5] = { 2, 1000, 3000, 10000, 100000 };
ulong qmax[5] = { 500, 2000, 5000, 12000, 100500 };
int j, nj = 3;
slong nv[3] = { 50, 300, 2000 };
nr = 20;
flint_randinit(state);
rand = flint_malloc(nr * sizeof(ulong));
for (r = 0; r < nr; r++)
rand[r] = n_randprime(state, 42, 0);
if (argc < 2)
out = LOG;
else if (!strcmp(argv[1], "json"))
out = JSON;
else if (!strcmp(argv[1], "csv"))
out = CSV;
else if (!strcmp(argv[1], "log"))
out = LOG;
else
{
printf("usage: %s [log|csv|json]\n", argv[0]);
abort();
}
if (out == CSV)
flint_printf("# %-12s, %7s, %7s, %7s, %7s\n","name", "num", "qmin", "qmax", "time");
for (j = 0; j < nj; j++)
{
ulong * v;
v = flint_malloc(nv[j] * sizeof(ulong));
for (i = 0; i < ni; i++)
{
if (out == LOG)
flint_printf("%wu * ui_chi(rand, 1..%wu) for all %wu <= q <= %wu....\n", nr, nv[j], qmin[i], qmax[i]);
for (l = 0; l < nf; l++)
{
ulong q;
/* eratos too slow */
if (l == 4 && i > 2)
continue;
if (out == LOG)
flint_printf("%-14s ... ", name[l]);
else if (out == CSV)
flint_printf("%-12s, %7d, %7d, %7d, ", name[l], nv[j], qmin[i], qmax[i]);
else if (out == JSON)
flint_printf("{ \"name\": \"%s\", \"num\": %d, \"qmin\": %d, \"qmax\": %d, \"time\": ",
name[l], nv[j], qmin[i], qmax[i]);
TIMEIT_ONCE_START
for (q = qmin[i]; q <= qmax[i]; q++)
{
acb_dirichlet_group_t G;
acb_dirichlet_char_t chi;
acb_dirichlet_group_init(G, q);
acb_dirichlet_char_init(chi, G);
if (l >= 6)
acb_dirichlet_group_dlog_precompute(G, (l == 6) ? 1 : (l==7) ? 20 : 100);
for (r = 0; r < nr; r++)
{
acb_dirichlet_char(chi, G, rand[r] % q);
func[l](v, G, chi, nv[j]);
}
if (l >= 6)
acb_dirichlet_group_dlog_clear(G);
acb_dirichlet_char_clear(chi);
acb_dirichlet_group_clear(G);
}
TIMEIT_ONCE_STOP
if (out == JSON)
flint_printf("}\n");
else
flint_printf("\n");
}
}
flint_free(v);
}
flint_free(rand);
flint_randclear(state);
flint_cleanup();
return EXIT_SUCCESS;
}

View file

@ -0,0 +1,42 @@
/*
Copyright (C) 2016 Pascal Molin
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "acb_dirichlet.h"
/* sum a_k x^(k^2), assume a[0] = 0 */
void
acb_dirichlet_qseries_arb(acb_t res, acb_srcptr a, const arb_t x, slong len, slong prec)
{
slong k;
arb_t xk2, dx, x2;
arb_init(xk2);
arb_init(dx);
arb_init(x2);
arb_set(dx, x);
arb_set(xk2, dx);
arb_mul(x2, dx, dx, prec);
acb_mul_arb(res, a + 1, xk2, prec);
/* TODO: reduce prec */
for (k = 2; k < len; k++)
{
arb_mul(dx, dx, x2, prec);
arb_mul(xk2, xk2, dx, prec);
acb_addmul_arb(res, a + k, xk2, prec);
}
arb_clear(xk2);
arb_clear(x2);
arb_clear(dx);
}

View file

@ -0,0 +1,100 @@
/*
Copyright (C) 2016 Pascal Molin
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "acb_dirichlet.h"
#include "acb_poly.h"
void
acb_dirichlet_qseries_arb_powers_naive(acb_t res, const arb_t x, int parity, const ulong *a, const acb_dirichlet_powers_t z, slong len, slong prec)
{
slong k;
arb_t xk2, dx, x2;
acb_t zk;
arb_init(xk2);
arb_init(dx);
arb_init(x2);
acb_init(zk);
arb_set(dx, x);
arb_set(xk2, dx);
arb_mul(x2, dx, dx, prec);
acb_set_arb(res, xk2);
/* TODO: reduce prec */
for (k = 2; k < len; k++)
{
arb_mul(dx, dx, x2, prec);
arb_mul(xk2, xk2, dx, prec);
if (a[k] != DIRICHLET_CHI_NULL)
{
acb_dirichlet_power(zk, z, a[k], prec);
if (parity)
acb_mul_si(zk, zk, k, prec);
acb_addmul_arb(res, zk, xk2, prec);
}
}
arb_clear(xk2);
arb_clear(x2);
arb_clear(dx);
acb_clear(zk);
}
/* small order, multiply by chi at the end */
void
acb_dirichlet_qseries_arb_powers_smallorder(acb_t res, const arb_t x, int parity, const ulong *a, const acb_dirichlet_powers_t z, slong len, slong prec)
{
slong k;
ulong order = z->order;
arb_t xk2, kxk2, dx, x2;
acb_ptr t;
arb_init(xk2);
arb_init(dx);
arb_init(x2);
arb_init(kxk2);
arb_set(dx, x);
arb_set(xk2, x);
arb_mul(x2, x, x, prec);
t = _acb_vec_init(order);
_acb_vec_zero(t, order);
arb_set(acb_realref(t + 0), xk2);
/* TODO: reduce precision at each step */
for (k = 2; k < len; k++)
{
arb_mul(dx, dx, x2, prec);
arb_mul(xk2, xk2, dx, prec);
if (a[k] != DIRICHLET_CHI_NULL)
{
if (parity)
{
arb_mul_si(kxk2, xk2, k, prec);
arb_add(acb_realref(t + a[k]), acb_realref(t + a[k]), kxk2, prec);
}
else
{
arb_add(acb_realref(t + a[k]), acb_realref(t + a[k]), xk2, prec);
}
}
}
/* now Hörner */
_acb_poly_evaluate(res, t, order, z->z, prec);
_acb_vec_clear(t, order);
arb_clear(xk2);
arb_clear(x2);
arb_clear(dx);
}

View file

@ -0,0 +1,52 @@
/*
Copyright (C) 2016 Pascal Molin
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "acb_dirichlet.h"
void
acb_dirichlet_root_number_theta(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec)
{
arb_t x;
acb_t eps;
arb_init(x);
arb_one(x);
acb_dirichlet_theta_arb(res, G, chi, x, prec);
acb_init(eps);
acb_conj(eps, res);
acb_div(res, res, eps, prec);
arb_clear(x);
acb_clear(eps);
}
void
acb_dirichlet_root_number(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, slong prec)
{
if (dirichlet_conductor_char(G, chi) < G->q)
{
flint_printf("root number: need primitive character\n");
abort();
}
else if (G->num > 1)
{
acb_t iq;
acb_init(iq);
acb_dirichlet_gauss_sum_order2(iq, G, chi, prec);
acb_dirichlet_gauss_sum(res, G, chi, prec);
acb_div(res, res, iq, prec);
acb_clear(iq);
}
else
{
acb_dirichlet_root_number_theta(res, G, chi, prec);
}
}

View file

@ -0,0 +1,62 @@
/*
Copyright (C) 2016 Fredrik Johansson
Copyright (C) 2016 Pascal Molin
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "acb_dirichlet.h"
/* bsgs evaluation */
void
acb_dirichlet_si_poly_evaluate(acb_t res, slong * v, slong len, const acb_t z, slong prec)
{
slong k, r, m;
acb_t sq;
acb_ptr zk;
if (len < 3)
{
if (len == 0)
{
acb_zero(res);
}
else if (len == 1)
{
acb_set_si(res, v[0]);
}
else if (len == 2)
{
acb_mul_si(res, z, v[1], prec);
acb_add_si(res, res, v[0], prec);
}
return;
}
m = n_sqrt(len) + 1;
zk = _acb_vec_init(m + 1);
_acb_vec_set_powers(zk, z, m + 1, prec);
acb_init(sq);
acb_zero(res);
k = len - 1;
r = k % m;
for (; k >= 0; r = m - 1)
{
acb_zero(sq);
for (; r >= 0; r--, k--)
acb_addmul_si(sq, zk + r, v[k], prec);
acb_mul(res, res, zk + m, prec);
acb_add(res, res, sq, prec);
}
_acb_vec_clear(zk, m + 1);
acb_clear(sq);
}

View file

@ -23,13 +23,15 @@ int main()
for (iter = 0; iter < 10000 * arb_test_multiplier(); iter++) for (iter = 0; iter < 10000 * arb_test_multiplier(); iter++)
{ {
acb_t zn1, zn2, zn1n2, zn1zn2; acb_t zn1, zn2, zn1n2, zn1zn2;
acb_dirichlet_group_t G; dirichlet_group_t G;
dirichlet_char_t chi;
ulong q, m, n1, n2, iter2; ulong q, m, n1, n2, iter2;
int res; int res;
q = 1 + n_randint(state, 1000); q = 1 + n_randint(state, 1000);
acb_dirichlet_group_init(G, q); dirichlet_group_init(G, q);
dirichlet_char_init(chi, G);
acb_init(zn1); acb_init(zn1);
acb_init(zn2); acb_init(zn2);
acb_init(zn1n2); acb_init(zn1n2);
@ -42,12 +44,31 @@ int main()
m = 1 + n_randint(state, q); m = 1 + n_randint(state, q);
} while (n_gcd(q, m) != 1); } while (n_gcd(q, m) != 1);
dirichlet_char_log(chi, G, m);
n1 = n_randint(state, 1000); n1 = n_randint(state, 1000);
n2 = n_randint(state, 1000); n2 = n_randint(state, 1000);
acb_dirichlet_chi(zn1, G, m, n1, 53); acb_dirichlet_chi(zn1, G, chi, n1, 53);
acb_dirichlet_chi(zn2, G, m, n2, 53); acb_dirichlet_pairing(zn2, G, m, n1, 53);
acb_dirichlet_chi(zn1n2, G, m, n1 * n2, 53); if (!acb_overlaps(zn1, zn2))
{
flint_printf("FAIL: overlap\n\n");
flint_printf("q = %wu\n\n", q);
flint_printf("m = %wu\n\n", m);
flint_printf("n = %wu\n\n", n1);
flint_printf("char = "); acb_printd(zn1, 15); flint_printf("\n\n");
flint_printf("pairing = "); acb_printd(zn2, 15); flint_printf("\n\n");
dirichlet_char_print(G, chi);
dirichlet_char_log(chi, G, m);
flint_printf("log(m) = "); dirichlet_char_print(G, chi);
dirichlet_char_log(chi, G, n1);
flint_printf("log(n1) = "); dirichlet_char_print(G, chi);
abort();
}
acb_dirichlet_pairing(zn2, G, m, n2, 53);
acb_dirichlet_pairing(zn1n2, G, m, n1 * n2, 53);
acb_mul(zn1zn2, zn1, zn2, 53); acb_mul(zn1zn2, zn1, zn2, 53);
if (!acb_overlaps(zn1n2, zn1zn2)) if (!acb_overlaps(zn1n2, zn1zn2))
@ -74,7 +95,7 @@ int main()
{ {
if (n_gcd(q, m) == 1) if (n_gcd(q, m) == 1)
{ {
acb_dirichlet_chi(zn2, G, m, n1, 53); acb_dirichlet_pairing(zn2, G, m, n1, 53);
acb_add(zn1, zn1, zn2, 53); acb_add(zn1, zn1, zn2, 53);
} }
} }
@ -96,7 +117,8 @@ int main()
} }
} }
acb_dirichlet_group_clear(G); dirichlet_group_clear(G);
dirichlet_char_clear(chi);
acb_clear(zn1); acb_clear(zn1);
acb_clear(zn2); acb_clear(zn2);
acb_clear(zn1n2); acb_clear(zn1n2);
@ -108,4 +130,3 @@ int main()
flint_printf("PASS\n"); flint_printf("PASS\n");
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

View file

@ -0,0 +1,81 @@
/*
Copyright (C) 2016 Pascal Molin
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "acb_dirichlet.h"
int main()
{
slong prec = 128;
ulong q;
flint_printf("gauss....");
fflush(stdout);
/* check Gauss sums */
for (q = 3; q < 250; q ++)
{
dirichlet_group_t G;
dirichlet_char_t chi;
acb_t s1, s2, s3, s4;
dirichlet_group_init(G, q);
dirichlet_char_init(chi, G);
acb_init(s1);
acb_init(s2);
acb_init(s3);
acb_init(s4);
dirichlet_char_one(chi, G);
while (1) {
acb_dirichlet_gauss_sum_naive(s1, G, chi, prec);
acb_dirichlet_gauss_sum(s2, G, chi, prec);
acb_dirichlet_gauss_sum_factor(s3, G, chi, prec);
if (dirichlet_conductor_char(G, chi) == G->q)
acb_dirichlet_gauss_sum_theta(s4, G, chi, prec);
else
acb_set(s4, s1);
if (!acb_overlaps(s1, s2)
|| !acb_overlaps(s1, s3)
|| !acb_overlaps(s1, s4))
{
flint_printf("FAIL: G(chi_%wu(%wu))\n\n", q, chi->n);
flint_printf("\nnaive ");
acb_printd(s1, 25);
flint_printf("\ndefault ");
acb_printd(s2, 25);
flint_printf("\nfactor ");
acb_printd(s3, 25);
flint_printf("\ntheta ");
acb_printd(s4, 25);
abort();
}
if (dirichlet_char_next(chi, G) < 0)
break;
}
acb_clear(s1);
acb_clear(s2);
acb_clear(s3);
acb_clear(s4);
dirichlet_group_clear(G);
dirichlet_char_clear(chi);
}
flint_cleanup();
flint_printf("PASS\n");
return EXIT_SUCCESS;
}

View file

@ -0,0 +1,88 @@
/*
Copyright (C) 2016 Pascal Molin
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "acb_dirichlet.h"
int main()
{
slong prec = 128;
ulong q;
flint_printf("jacobi....");
fflush(stdout);
/* check Jacobi sums */
for (q = 29 * 29; q > 1; q = q%2 ? 3*q+1 : q/2)
{
slong m1, m2;
dirichlet_group_t G;
dirichlet_char_t chi1, chi2;
acb_t s1, s2;
dirichlet_group_init(G, q);
dirichlet_char_init(chi1, G);
dirichlet_char_init(chi2, G);
acb_init(s1);
acb_init(s2);
dirichlet_char_one(chi1, G);
for (m1 = 0; m1 < 50; m1++)
{
dirichlet_char_one(chi2, G);
for (m2 = 0; m2 < 50; m2++)
{
acb_dirichlet_jacobi_sum_naive(s1, G, chi1, chi2, prec);
acb_dirichlet_jacobi_sum(s2, G, chi1, chi2, prec);
if (!acb_overlaps(s1, s2))
{
flint_printf("FAIL: J_%wu(%wu,%wu)",
q, chi1->n, chi2->n);
flint_printf("\nnaive ");
acb_printd(s1, 25);
flint_printf("\ndefault ");
acb_printd(s2, 25);
flint_printf("\n");
flint_printf("cond = %wu, %wu, %wu\n",
dirichlet_conductor_char(G, chi1),
dirichlet_conductor_char(G, chi2),
dirichlet_conductor_ui(G, nmod_mul(chi1->n, chi2->n, G->mod))
);
abort();
}
if (dirichlet_char_next(chi2, G) < 0)
break;
}
if (dirichlet_char_next(chi1, G) < 0)
break;
}
acb_clear(s1);
acb_clear(s2);
dirichlet_group_clear(G);
dirichlet_char_clear(chi1);
dirichlet_char_clear(chi2);
}
flint_cleanup();
flint_printf("PASS\n");
return EXIT_SUCCESS;
}

145
acb_dirichlet/test/t-l.c Normal file
View file

@ -0,0 +1,145 @@
/*
Copyright (C) 2016 Pascal Molin
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "acb_dirichlet.h"
#define nq 5
#define nx 3
int main()
{
slong i, j;
ulong q[nq] = {3, 5, 61, 91, 800};
ulong m[nq] = {2, 4, 11, 2, 3};
slong prec = 150;
acb_ptr x;
/* cannot test at s = 1 with hurwitz */
const char * x_r[nx] = { "1", "0.5", "0.5" };
const char * x_i[nx] = { "1", "0", "6" };
acb_t ref, res;
/*
default(realprecision, 54)
X = [ 1 + I, 1/2, 1/2 + 6 * I ]
C = [Mod(2,3),Mod(4,5),Mod(11,61),Mod(2,91),Mod(3,800)]
v = concat([ [lfun(c,x) | x<-X] | c<-C])
apply(z->printf("\"%s\",\n",real(z)),v)
apply(z->printf("\"%s\",\n",imag(z)),v)
*/
const char * ref_r[nq * nx] = {
"0.655527984002548033786648216345221087939439503905627469",
"0.480867557696828626181220063235589877776829730832371863",
"1.56831301727577320813799211138797101541772722814204757",
"0.521271244517346991221550773660594765406476858135844321",
"0.231750947504015755883383661760877226427886696409005898",
"0.275543455389521803395512886745330595086898302178508437",
"0.598221809458540554839300433683735304093606595684903281",
"0.489264190003695740292779374874163221990017067040417393",
"0.573331076412428980263984182365365715292560207445592018",
"0.510279695870740409778738767334484809708615155539404548",
"0.635626509594367380604827545000418331455019188562281349",
"0.129304857274642475564179442785425797926079767522671163",
"1.18088858810025653590356481638012816019876881487868657",
"2.17175778983760437737667738885959799183430688287297767",
"3.41568550810774629867945639900431994221065497147578087"
};
const char * ref_i[nq * nx] = {
"0.220206044893215842652155131408935133596486560067476474",
"0",
"-0.969458654385732175077973304161399773236957587792986099",
"0.354614573267731219242838516784605303288232150760467423",
"0",
"-0.995392028773643947872231871832838543767598301887892796",
"1.04370497561090171487193145841005574472705644411957863",
"-0.108902811943905225853677097712717212629591264759957602",
"-0.232114369998608907337769019848201890558327186146689311",
"-0.133300066189980774635445078240315148544665020358019145",
"0.0119464572932630291870372694406253796888930803905106876",
"-0.567660589679294457801153713636532209809112025502518666",
"-0.654079942571300523223917775358845549990877148918886474",
"0.970337207245832214408380510793679653538607483205616894",
"-1.43652482351673593824956935036654893593947145947637807"
};
flint_printf("l....");
fflush(stdout);
x = _acb_vec_init(nx);
for (j = 0; j < nx; j++)
{
if (arb_set_str(acb_realref(x + j), x_r[j], prec) ||
arb_set_str(acb_imagref(x + j), x_i[j], prec) )
{
flint_printf("error while setting x[%ld] <- %s+I*%s\n",
j, x_r[j], x_i[j]);
abort();
}
}
acb_init(ref);
acb_init(res);
for (i = 0; i < nq; i++)
{
dirichlet_group_t G;
dirichlet_char_t chi;
dirichlet_group_init(G, q[i]);
dirichlet_char_init(chi, G);
dirichlet_char_log(chi, G, m[i]);
for (j = 0; j < nx; j++)
{
if (arb_set_str(acb_realref(ref), ref_r[i * nx + j], prec - 10) ||
arb_set_str(acb_imagref(ref), ref_i[i * nx + j], prec - 10) )
{
flint_printf("error while setting ref <- %s+I*%s\n",
ref_r[i * nx + j], ref_i[i * nx + j]);
abort();
}
acb_dirichlet_l_hurwitz(res, x + j, G, chi, prec + 10);
if (!acb_contains(ref, res))
{
flint_printf("FAIL:\n\n");
flint_printf("q = %wu\n", q[i]);
flint_printf("m = %wu\n", m[i]);
flint_printf("x = ");
acb_printd(x, 54);
flint_printf("\nref = ");
acb_printd(ref, 54);
flint_printf("\nl(chi,x) = ");
acb_printd(res, 54);
flint_printf("\n\n");
abort();
}
}
dirichlet_char_clear(chi);
dirichlet_group_clear(G);
}
acb_clear(ref);
acb_clear(res);
_acb_vec_clear(x, nx);
flint_cleanup();
flint_printf("PASS\n");
return EXIT_SUCCESS;
}

View file

@ -0,0 +1,85 @@
/*
Copyright (C) 2016 Fredrik Johansson
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "acb_dirichlet.h"
int main()
{
slong iter;
flint_rand_t state;
flint_printf("l_euler_product....");
fflush(stdout);
flint_randinit(state);
for (iter = 0; iter < 500 * arb_test_multiplier(); iter++)
{
acb_t s, t, u;
dirichlet_group_t G;
dirichlet_char_t chi;
ulong q, k;
slong prec;
acb_init(s);
acb_init(t);
acb_init(u);
q = 1 + n_randint(state, 50);
prec = 2 + n_randint(state, 500);
k = n_randint(state, n_euler_phi(q));
dirichlet_group_init(G, q);
dirichlet_char_init(chi, G);
dirichlet_char_index(chi, G, k);
if (n_randint(state, 2))
{
acb_set_ui(s, 2 + n_randint(state, prec + 50));
}
else
{
acb_randtest(s, state, 2 + n_randint(state, 200), 2);
arb_abs(acb_realref(s), acb_realref(s));
if (n_randint(state, 2))
acb_add_ui(s, s, n_randtest(state), prec);
}
if (n_randint(state, 2))
acb_dirichlet_l_hurwitz(t, s, G, chi, prec);
else
acb_dirichlet_l_euler_product(t, s, G, chi, prec * 1.5);
acb_dirichlet_l_euler_product(u, s, G, chi, prec);
if (!acb_overlaps(t, u))
{
flint_printf("FAIL: overlap\n\n");
flint_printf("iter = %ld q = %lu k = %lu prec = %ld\n\n", iter, q, k, prec);
flint_printf("s = "); acb_printn(s, 100, 0); flint_printf("\n\n");
flint_printf("t = "); acb_printn(t, 100, 0); flint_printf("\n\n");
flint_printf("u = "); acb_printn(u, 100, 0); flint_printf("\n\n");
abort();
}
dirichlet_char_clear(chi);
dirichlet_group_clear(G);
acb_clear(s);
acb_clear(t);
acb_clear(u);
}
flint_randclear(state);
flint_cleanup();
flint_printf("PASS\n");
return EXIT_SUCCESS;
}

View file

@ -0,0 +1,201 @@
/*
Copyright (C) 2016 Fredrik Johansson
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "acb_dirichlet.h"
/* Laurent expansions at s = 1 of first 10 principal L-functions */
/* with mpmath:
chis = [[1],[0,1],[0,1,1],[0,1,0,1],[0,1,1,1,1],[0,1,0,0,0,1],[0,1,1,1,1,1,1],
[0,1,0,1,0,1,0,1],[0,1,1,0,1,1,0,1,1],[0,1,0,1,0,0,0,1,0,1]]
mp.dps = 40
for chi in chis:
phi = chi.count(1); q = len(chi)
L = lambda s: dirichlet(s, chi) - phi/((s-1)*q)
c0 = taylor(L, 1, 0, method="quad")
c1 = taylor(L, 1, 5, singular=True)[1:]
for c in c0 + c1:
print nstr(c, 20) + ",",
print
*/
#define TESTQ 10
#define TESTLEN 6
static const double laurent_data[TESTQ][TESTLEN] = {
{0.57721566490153286061, 0.072815845483676724861, -0.0048451815964361592423,
-0.00034230573671722431103, 0.000096890419394470835728, -6.6110318108421891813e-6},
{0.63518142273073908501, 0.11634237461305384831, -0.018765738937942729408,
0.00061334298434914532242, 0.00042338142025747308027, -0.00010545096447379519004},
{0.7510145394903918042, 0.058764477744540050414, -0.019011359100973296683,
0.0056382252365739175151, -0.0009550480622176659462, 0.000021808301216554848718},
{0.63518142273073908501, 0.11634237461305384831, -0.018765738937942729408,
0.00061334298434914532242, 0.00042338142025747308027, -0.00010545096447379519004},
{0.78366011440804636341, -0.014977808062405260803, 0.0090104707969118845102,
0.003603799084856807634, -0.0029351216034181476022, 0.00093077685173004747355},
{0.60655632993184433857, 0.2095885418562151802, -0.060844893711330538429,
0.0068080382961291386117, 0.0022236616427578346453, -0.0013581825996235430782},
{0.77274344835207292411, -0.047596894381510269689, 0.035406039531261788462,
-0.0054159870134630085898, -0.0019749752308692423114, 0.0014492998471928196325},
{0.63518142273073908501, 0.11634237461305384831, -0.018765738937942729408,
0.00061334298434914532242, 0.00042338142025747308027, -0.00010545096447379519004},
{0.7510145394903918042, 0.058764477744540050414, -0.019011359100973296683,
0.0056382252365739175151, -0.0009550480622176659462, 0.000021808301216554848718},
{0.66908892942800130547, 0.16801639259476784034, -0.072611999814034642781,
0.024624650443138705595, -0.004951850872731033514, -0.00020178815459414925709}
};
int main()
{
slong iter;
flint_rand_t state;
flint_printf("l_jet....");
fflush(stdout);
flint_randinit(state);
/* test Laurent series at s = 1 */
{
acb_t s, t;
dirichlet_group_t G;
dirichlet_char_t chi;
acb_ptr vec;
ulong q;
slong i;
acb_init(s);
acb_init(t);
vec = _acb_vec_init(TESTLEN);
acb_one(s);
for (q = 1; q <= TESTQ; q++)
{
dirichlet_group_init(G, q);
dirichlet_char_init(chi, G);
acb_dirichlet_l_jet(vec, s, G, chi, 1, TESTLEN, 100);
for (i = 0; i < TESTLEN; i++)
{
acb_set_d(t, laurent_data[q - 1][i]);
mag_set_d(arb_radref(acb_realref(t)),
fabs(laurent_data[q - 1][i]) * 1e-14);
if (!acb_overlaps(vec + i, t))
{
flint_printf("FAIL: Laurent series\n\n");
flint_printf("q = %wu i = %wd\n\n", q, i);
flint_printf("r1 = "); acb_printn(vec + i, 50, 0); flint_printf("\n\n");
flint_printf("r2 = "); acb_printn(t, 50, 0); flint_printf("\n\n");
abort();
}
}
dirichlet_char_clear(chi);
dirichlet_group_clear(G);
}
acb_clear(s);
acb_clear(t);
_acb_vec_clear(vec, TESTLEN);
}
/* test self-consistency */
for (iter = 0; iter < 1000 * arb_test_multiplier(); iter++)
{
acb_t s;
dirichlet_group_t G;
dirichlet_char_t chi;
acb_ptr vec1, vec2;
slong len1, len2;
slong prec1, prec2;
int deflate1, deflate2;
ulong q, k;
slong i;
len1 = n_randint(state, 5);
len2 = n_randint(state, 5);
prec1 = 2 + n_randint(state, 100);
prec2 = 2 + n_randint(state, 100);
deflate1 = n_randint(state, 2);
deflate2 = n_randint(state, 2);
q = 1 + n_randint(state, 20);
k = n_randint(state, n_euler_phi(q));
dirichlet_group_init(G, q);
dirichlet_char_init(chi, G);
dirichlet_char_index(chi, G, k);
acb_init(s);
vec1 = _acb_vec_init(len1);
vec2 = _acb_vec_init(len2);
if (n_randint(state, 4) == 0)
acb_one(s);
else
acb_randtest(s, state, 2 + n_randint(state, 200), 2);
acb_dirichlet_l_jet(vec1, s, G, chi, deflate1, len1, prec1);
acb_dirichlet_l_jet(vec2, s, G, chi, deflate2, len2, prec2);
if (deflate1 != deflate2 && dirichlet_char_is_principal(G, chi))
{
/* add or subtract phi(q)/((s+x-1)q) */
acb_t t, u;
acb_init(t);
acb_init(u);
acb_set_ui(t, n_euler_phi(q));
acb_div_ui(t, t, q, prec1);
acb_sub_ui(u, s, 1, prec1);
for (i = 0; i < len1; i++)
{
acb_div(t, t, u, prec1);
if (deflate1)
acb_add(vec1 + i, vec1 + i, t, prec1);
else
acb_sub(vec1 + i, vec1 + i, t, prec1);
acb_neg(t, t);
}
acb_clear(t);
acb_clear(u);
}
for (i = 0; i < FLINT_MIN(len1, len2); i++)
{
if (!acb_overlaps(vec1 + i, vec2 + i))
{
flint_printf("FAIL: overlap\n\n");
flint_printf("iter = %wd q = %wu k = %wu i = %wd\n\n", iter, q, k, i);
flint_printf("s = "); acb_printn(s, 50, 0); flint_printf("\n\n");
flint_printf("r1 = "); acb_printn(vec1 + i, 50, 0); flint_printf("\n\n");
flint_printf("r2 = "); acb_printn(vec2 + i, 50, 0); flint_printf("\n\n");
abort();
}
}
dirichlet_char_clear(chi);
dirichlet_group_clear(G);
acb_clear(s);
_acb_vec_clear(vec1, len1);
_acb_vec_clear(vec2, len2);
}
flint_randclear(state);
flint_cleanup();
flint_printf("PASS\n");
return EXIT_SUCCESS;
}

View file

@ -0,0 +1,119 @@
/*
Copyright (C) 2016 Pascal Molin
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "acb_dirichlet.h"
int main()
{
slong prec = 64;
ulong q;
flint_printf("thetanull....");
fflush(stdout);
/* check the only theta functions
* theta(chi) = sum chi(k)* k^odd * exp(-Pi * k^2 / q)
* vanishing at 1 correspond to two specific
* characters of moduli 300 and 600 + conjugates
*/
for (q = 3; q < 1000; q ++)
{
dirichlet_group_t G;
dirichlet_char_t chi;
ulong * v, nv, k;
acb_t sum;
acb_ptr z;
arb_t eq;
arb_ptr t, kt, tt;
if (q % 4 == 2)
/* no primitive character mod q */
continue;
dirichlet_group_init(G, q);
dirichlet_char_init(chi, G);
z = _acb_vec_init(G->expo);
_acb_vec_nth_roots(z, G->expo, prec);
nv = acb_dirichlet_theta_length_d(q, 1, prec);
v = flint_malloc(nv * sizeof(ulong));
arb_init(eq);
arb_const_pi(eq, prec);
arb_div_ui(eq, eq, q, prec);
arb_neg(eq, eq);
arb_exp(eq, eq, prec);
t = _arb_vec_init(nv);
acb_dirichlet_arb_quadratic_powers(t, nv, eq, prec);
kt = _arb_vec_init(nv);
for (k = 1; k < nv; k++)
arb_mul_ui(kt + k, t + k, k, prec);
/* theta function on primitive characters */
acb_init(sum);
dirichlet_char_first_primitive(chi, G);
do {
acb_zero(sum);
dirichlet_chi_vec(v, G, chi, nv);
tt = dirichlet_parity_char(G, chi) ? kt : t;
for (k = 1; k < nv; k++)
if (v[k] != DIRICHLET_CHI_NULL)
acb_addmul_arb(sum, z + v[k], tt + k, prec);
if ((q == 300 && (chi->n == 71 || chi->n == 131))
|| (q == 600 && (chi->n == 11 || chi->n == 491)))
{
if (!acb_contains_zero(sum))
{
flint_printf("FAIL: Theta(chi_%wu(%wu))=", q, chi->n);
acb_printd(sum, 10);
flint_printf("\n");
dirichlet_char_print(G, chi);
flint_printf("\n");
abort();
}
}
else if (acb_contains_zero(sum))
{
flint_printf("FAIL: Theta(chi_%wu(%wu))=", q, chi->n);
acb_printd(sum, 10);
flint_printf("\n");
dirichlet_char_print(G, chi);
flint_printf("\n");
abort();
}
} while (dirichlet_char_next_primitive(chi, G) >= 0);
_acb_vec_clear(z, G->expo);
_arb_vec_clear(kt, nv);
_arb_vec_clear(t, nv);
acb_clear(sum);
arb_clear(eq);
flint_free(v);
dirichlet_group_clear(G);
dirichlet_char_clear(chi);
}
flint_cleanup();
flint_printf("PASS\n");
return EXIT_SUCCESS;
}

104
acb_dirichlet/theta_arb.c Normal file
View file

@ -0,0 +1,104 @@
/*
Copyright (C) 2016 Pascal Molin
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "acb_dirichlet.h"
#include "acb_poly.h"
void
_acb_dirichlet_theta_arb_smallorder(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, const arb_t xt, slong len, slong prec)
{
ulong order;
ulong * a;
int parity;
acb_dirichlet_powers_t z;
parity = dirichlet_parity_char(G, chi);
order = dirichlet_order_char(G, chi);
a = flint_malloc(len * sizeof(ulong));
dirichlet_chi_vec_order(a, G, chi, order, len);
_acb_dirichlet_powers_init(z, order, 0, 0, prec);
acb_dirichlet_qseries_arb_powers_smallorder(res, xt, parity, a, z, len, prec);
acb_dirichlet_powers_clear(z);
flint_free(a);
}
void
_acb_dirichlet_theta_arb_series(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, const arb_t xt, slong len, slong prec)
{
acb_ptr a;
a = _acb_vec_init(len);
acb_dirichlet_chi_vec(a, G, chi, len, prec);
if (dirichlet_parity_char(G, chi))
{
slong k;
for (k = 2; k < len; k++)
acb_mul_si(a + k, a + k, k, prec);
}
acb_dirichlet_qseries_arb(res, a, xt, len, prec);
_acb_vec_clear(a, len);
}
void
_acb_dirichlet_theta_arb_naive(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, const arb_t xt, slong len, slong prec)
{
ulong order, * a;
acb_dirichlet_powers_t z;
int parity;
parity = dirichlet_parity_char(G, chi);
order = dirichlet_order_char(G, chi);
a = flint_malloc(len * sizeof(ulong));
dirichlet_chi_vec_order(a, G, chi, order, len);
acb_dirichlet_powers_init(z, order, len, prec);
acb_dirichlet_qseries_arb_powers_naive(res, xt, parity, a, z, len, prec);
acb_dirichlet_powers_clear(z);
flint_free(a);
}
void
acb_dirichlet_theta_arb(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi, const arb_t t, slong prec)
{
slong len;
ulong order;
arb_t xt;
mag_t e;
len = acb_dirichlet_theta_length(G->q, t, prec);
arb_init(xt);
_acb_dirichlet_theta_argument_at_arb(xt, G->q, t, prec);
mag_init(e);
mag_tail_kexpk2_arb(e, xt, len);
arb_neg(xt, xt);
arb_exp(xt, xt, prec);
/* TODO: tune this limit */
order = dirichlet_order_char(G, chi);
if (order < 30)
_acb_dirichlet_theta_arb_smallorder(res, G, chi, xt, len, prec);
else
_acb_dirichlet_theta_arb_naive(res, G, chi, xt, len, prec);
arb_add_error_mag(acb_realref(res), e);
arb_add_error_mag(acb_imagref(res), e);
mag_clear(e);
acb_mul_2exp_si(res, res, 1);
arb_clear(xt);
}

View file

@ -0,0 +1,80 @@
/*
Copyright (C) 2016 Pascal Molin
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "acb_dirichlet.h"
#include <math.h>
#define PI 3.14159265358
#define LOG2 0.69314718055
ulong
acb_dirichlet_theta_length_d(ulong q, double t, slong prec)
{
double a, la;
a = PI / (double)q * t * t;
la = (a < .3) ? -log(2*a*(1-a)) : .8;
la = ((double)prec * LOG2 + la) / a;
return ceil(sqrt(la)+.5);
}
ulong
acb_dirichlet_theta_length(ulong q, const arb_t t, slong prec)
{
double dt;
ulong len;
arf_t at;
arf_init(at);
arb_get_lbound_arf(at, t, 53);
dt = arf_get_d(at, ARF_RND_DOWN);
len = acb_dirichlet_theta_length_d(q, dt, prec);
arf_clear(at);
return len;
}
/* bound for sum_{k>n} k*exp(-a k^2) */
void
mag_tail_kexpk2_arb(mag_t res, const arb_t a, ulong n)
{
mag_t m;
mag_init(m);
arb_get_mag_lower(m, a);
/* a < 1/4 */
if (mag_cmp_2exp_si(m, -2) <= 0)
{
mag_t c;
mag_init(c);
mag_mul_ui_lower(res, m, n*n-n+1); /* todo: possible overflow */
mag_expinv(res, res);
/* c = 2a(1+2a) */
mag_mul_2exp_si(m, m, 1);
mag_one(c);
mag_add_lower(c, m, c);
mag_mul_lower(c, m, c);
mag_div(res, res, c);
mag_clear(c);
}
else
{
mag_mul_ui_lower(res, m, n*n-n-1); /* todo: possible overflow */
mag_expinv(res, res);
mag_mul_ui(res, res, 2);
}
mag_clear(m);
}
/* a(t) = Pi / q * t^2 */
void
_acb_dirichlet_theta_argument_at_arb(arb_t xt, ulong q, const arb_t t, slong prec)
{
arb_const_pi(xt, prec);
arb_div_ui(xt, xt, q, prec);
arb_mul(xt, xt, t, prec);
arb_mul(xt, xt, t, prec);
}

View file

@ -0,0 +1,25 @@
/*
Copyright (C) 2016 Pascal Molin
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "acb_dirichlet.h"
void
acb_dirichlet_ui_theta_arb(acb_t res, const dirichlet_group_t G, ulong a, const arb_t t, slong prec)
{
dirichlet_char_t chi;
dirichlet_char_init(chi, G);
dirichlet_char_log(chi, G, a);
acb_dirichlet_theta_arb(res, G, chi, t, prec);
dirichlet_char_clear(chi);
}

View file

@ -105,6 +105,7 @@ int acb_hypgeom_u_use_asymp(const acb_t z, slong prec);
void acb_hypgeom_m_asymp(acb_t res, const acb_t a, const acb_t b, const acb_t z, int regularized, slong prec); void acb_hypgeom_m_asymp(acb_t res, const acb_t a, const acb_t b, const acb_t z, int regularized, slong prec);
void acb_hypgeom_m_1f1(acb_t res, const acb_t a, const acb_t b, const acb_t z, int regularized, slong prec); void acb_hypgeom_m_1f1(acb_t res, const acb_t a, const acb_t b, const acb_t z, int regularized, slong prec);
void acb_hypgeom_m(acb_t res, const acb_t a, const acb_t b, const acb_t z, int regularized, slong prec); void acb_hypgeom_m(acb_t res, const acb_t a, const acb_t b, const acb_t z, int regularized, slong prec);
void acb_hypgeom_1f1(acb_t res, const acb_t a, const acb_t b, const acb_t z, int regularized, slong prec);
void acb_hypgeom_bessel_j_0f1(acb_t res, const acb_t nu, const acb_t z, slong prec); void acb_hypgeom_bessel_j_0f1(acb_t res, const acb_t nu, const acb_t z, slong prec);
void acb_hypgeom_bessel_j_asymp(acb_t res, const acb_t nu, const acb_t z, slong prec); void acb_hypgeom_bessel_j_asymp(acb_t res, const acb_t nu, const acb_t z, slong prec);

View file

@ -14,7 +14,7 @@
void void
acb_hypgeom_gamma_lower(acb_t res, const acb_t s, const acb_t z, int regularized, slong prec) acb_hypgeom_gamma_lower(acb_t res, const acb_t s, const acb_t z, int regularized, slong prec)
{ {
acb_t s1, nz, t; acb_t s1, nz, t, u;
if (!acb_is_finite(s) || !acb_is_finite(z)) if (!acb_is_finite(s) || !acb_is_finite(z))
{ {
@ -25,6 +25,7 @@ acb_hypgeom_gamma_lower(acb_t res, const acb_t s, const acb_t z, int regularized
acb_init(s1); acb_init(s1);
acb_init(nz); acb_init(nz);
acb_init(t); acb_init(t);
acb_init(u);
acb_add_ui(s1, s, 1, prec); acb_add_ui(s1, s, 1, prec);
acb_neg(nz, z); acb_neg(nz, z);
@ -32,17 +33,17 @@ acb_hypgeom_gamma_lower(acb_t res, const acb_t s, const acb_t z, int regularized
if (regularized == 0) if (regularized == 0)
{ {
/* \gamma(s, z) = s^-1 z^s 1F1(s, 1+s, -z) */ /* \gamma(s, z) = s^-1 z^s 1F1(s, 1+s, -z) */
acb_hypgeom_m(res, s, s1, nz, 0, prec); acb_hypgeom_m(u, s, s1, nz, 0, prec);
acb_pow(t, z, s, prec); acb_pow(t, z, s, prec);
acb_mul(res, res, t, prec); acb_mul(u, u, t, prec);
acb_div(res, res, s, prec); acb_div(res, u, s, prec);
} }
else if (regularized == 1) else if (regularized == 1)
{ {
/* P(s, z) = z^s \gamma^{*}(s, z) */ /* P(s, z) = z^s \gamma^{*}(s, z) */
acb_hypgeom_m(res, s, s1, nz, 1, prec); acb_hypgeom_m(u, s, s1, nz, 1, prec);
acb_pow(t, z, s, prec); acb_pow(t, z, s, prec);
acb_mul(res, res, t, prec); acb_mul(res, u, t, prec);
} }
else if (regularized == 2) else if (regularized == 2)
{ {
@ -53,4 +54,6 @@ acb_hypgeom_gamma_lower(acb_t res, const acb_t s, const acb_t z, int regularized
acb_clear(s1); acb_clear(s1);
acb_clear(nz); acb_clear(nz);
acb_clear(t); acb_clear(t);
acb_clear(u);
} }

View file

@ -311,3 +311,9 @@ acb_hypgeom_m(acb_t res, const acb_t a, const acb_t b, const acb_t z, int regula
acb_set_round(res, res, prec); acb_set_round(res, res, prec);
} }
void
acb_hypgeom_1f1(acb_t res, const acb_t a, const acb_t b, const acb_t z, int regularized, slong prec)
{
acb_hypgeom_m(res, a, b, z, regularized, prec);
}

View file

@ -69,6 +69,8 @@ ACB_POLY_INLINE slong acb_poly_degree(const acb_poly_t poly)
return poly->length - 1; return poly->length - 1;
} }
slong acb_poly_valuation(const acb_poly_t poly);
ACB_POLY_INLINE int ACB_POLY_INLINE int
acb_poly_is_zero(const acb_poly_t z) acb_poly_is_zero(const acb_poly_t z)
{ {
@ -173,6 +175,10 @@ void acb_poly_set(acb_poly_t dest, const acb_poly_t src);
void acb_poly_set_round(acb_poly_t dest, const acb_poly_t src, slong prec); void acb_poly_set_round(acb_poly_t dest, const acb_poly_t src, slong prec);
void acb_poly_set_trunc(acb_poly_t res, const acb_poly_t poly, slong n);
void acb_poly_set_trunc_round(acb_poly_t res, const acb_poly_t poly, slong n, slong prec);
void acb_poly_set_arb_poly(acb_poly_t poly, const arb_poly_t re); void acb_poly_set_arb_poly(acb_poly_t poly, const arb_poly_t re);
void acb_poly_set2_arb_poly(acb_poly_t poly, const arb_poly_t re, const arb_poly_t im); void acb_poly_set2_arb_poly(acb_poly_t poly, const arb_poly_t re, const arb_poly_t im);
@ -232,6 +238,12 @@ void _acb_poly_sub(acb_ptr res, acb_srcptr poly1, slong len1,
void acb_poly_sub(acb_poly_t res, const acb_poly_t poly1, void acb_poly_sub(acb_poly_t res, const acb_poly_t poly1,
const acb_poly_t poly2, slong prec); const acb_poly_t poly2, slong prec);
void acb_poly_add_series(acb_poly_t res, const acb_poly_t poly1,
const acb_poly_t poly2, slong len, slong prec);
void acb_poly_sub_series(acb_poly_t res, const acb_poly_t poly1,
const acb_poly_t poly2, slong len, slong prec);
ACB_POLY_INLINE void ACB_POLY_INLINE void
acb_poly_neg(acb_poly_t res, const acb_poly_t poly) acb_poly_neg(acb_poly_t res, const acb_poly_t poly)
{ {

32
acb_poly/add_series.c Normal file
View file

@ -0,0 +1,32 @@
/*
Copyright (C) 2016 Fredrik Johansson
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "acb_poly.h"
void
acb_poly_add_series(acb_poly_t res, const acb_poly_t poly1,
const acb_poly_t poly2, slong len, slong prec)
{
slong len1, len2;
len1 = poly1->length;
len2 = poly2->length;
len1 = FLINT_MIN(len1, len);
len2 = FLINT_MIN(len2, len);
len = FLINT_MAX(len1, len2);
acb_poly_fit_length(res, len);
_acb_poly_add(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, prec);
_acb_poly_set_length(res, len);
_acb_poly_normalise(res);
}

35
acb_poly/set_trunc.c Normal file
View file

@ -0,0 +1,35 @@
/*
Copyright (C) 2016 Fredrik Johansson
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "acb_poly.h"
void
acb_poly_set_trunc(acb_poly_t res, const acb_poly_t poly, slong n)
{
if (poly == res)
{
acb_poly_truncate(res, n);
}
else
{
slong rlen;
rlen = FLINT_MIN(n, poly->length);
while (rlen > 0 && acb_is_zero(poly->coeffs + rlen - 1))
rlen--;
acb_poly_fit_length(res, rlen);
_acb_vec_set(res->coeffs, poly->coeffs, rlen);
_acb_poly_set_length(res, rlen);
}
}

View file

@ -0,0 +1,36 @@
/*
Copyright (C) 2016 Fredrik Johansson
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "acb_poly.h"
void
acb_poly_set_trunc_round(acb_poly_t res, const acb_poly_t poly, slong n, slong prec)
{
if (poly == res)
{
acb_poly_truncate(res, n);
_acb_vec_set_round(res->coeffs, res->coeffs, res->length, prec);
}
else
{
slong rlen;
rlen = FLINT_MIN(n, poly->length);
while (rlen > 0 && acb_is_zero(poly->coeffs + rlen - 1))
rlen--;
acb_poly_fit_length(res, rlen);
_acb_vec_set_round(res->coeffs, poly->coeffs, rlen, prec);
_acb_poly_set_length(res, rlen);
}
}

32
acb_poly/sub_series.c Normal file
View file

@ -0,0 +1,32 @@
/*
Copyright (C) 2016 Fredrik Johansson
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "acb_poly.h"
void
acb_poly_sub_series(acb_poly_t res, const acb_poly_t poly1,
const acb_poly_t poly2, slong len, slong prec)
{
slong len1, len2;
len1 = poly1->length;
len2 = poly2->length;
len1 = FLINT_MIN(len1, len);
len2 = FLINT_MIN(len2, len);
len = FLINT_MAX(len1, len2);
acb_poly_fit_length(res, len);
_acb_poly_sub(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, prec);
_acb_poly_set_length(res, len);
_acb_poly_normalise(res);
}

View file

@ -0,0 +1,83 @@
/*
Copyright (C) 2012 Fredrik Johansson
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "acb_poly.h"
int main()
{
slong iter;
flint_rand_t state;
flint_printf("add_series....");
fflush(stdout);
flint_randinit(state);
for (iter = 0; iter < 1000 * arb_test_multiplier(); iter++)
{
acb_poly_t a, b, c, d;
slong len, prec;
acb_poly_init(a);
acb_poly_init(b);
acb_poly_init(c);
acb_poly_init(d);
acb_poly_randtest(a, state, 1 + n_randint(state, 10), 100, 10);
acb_poly_randtest(b, state, 1 + n_randint(state, 10), 100, 10);
acb_poly_randtest(c, state, 1 + n_randint(state, 10), 100, 10);
acb_poly_randtest(d, state, 1 + n_randint(state, 10), 100, 10);
prec = 2 + n_randint(state, 100);
len = n_randint(state, 10);
acb_poly_add_series(c, a, b, len, prec);
acb_poly_add(d, a, b, prec);
acb_poly_truncate(d, len);
if (!acb_poly_equal(c, d))
{
flint_printf("FAIL\n\n");
flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n");
flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n");
flint_printf("c = "); acb_poly_printd(c, 15); flint_printf("\n\n");
flint_printf("c = "); acb_poly_printd(c, 15); flint_printf("\n\n");
abort();
}
acb_poly_set(d, a);
acb_poly_add_series(d, d, b, len, prec);
if (!acb_poly_equal(d, c))
{
flint_printf("FAIL (aliasing 1)\n\n");
abort();
}
acb_poly_set(d, b);
acb_poly_add_series(d, a, d, len, prec);
if (!acb_poly_equal(d, c))
{
flint_printf("FAIL (aliasing 2)\n\n");
abort();
}
acb_poly_clear(a);
acb_poly_clear(b);
acb_poly_clear(c);
acb_poly_clear(d);
}
flint_randclear(state);
flint_cleanup();
flint_printf("PASS\n");
return EXIT_SUCCESS;
}

View file

@ -0,0 +1,79 @@
/*
Copyright (C) 2016 Fredrik Johansson
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "acb_poly.h"
int
main(void)
{
int iter;
flint_rand_t state;
flint_printf("set_trunc_round....");
fflush(stdout);
flint_randinit(state);
for (iter = 0; iter < 1000 * arb_test_multiplier(); iter++)
{
acb_poly_t a, b, c, d, e;
slong n, prec;
acb_poly_init(a);
acb_poly_init(b);
acb_poly_init(c);
acb_poly_init(d);
acb_poly_init(e);
acb_poly_randtest(a, state, n_randint(state, 10), 2 + n_randint(state, 200), 10);
acb_poly_randtest(b, state, n_randint(state, 10), 2 + n_randint(state, 200), 10);
acb_poly_randtest(c, state, n_randint(state, 10), 2 + n_randint(state, 200), 10);
acb_poly_randtest(d, state, n_randint(state, 10), 2 + n_randint(state, 200), 10);
acb_poly_randtest(e, state, n_randint(state, 10), 2 + n_randint(state, 200), 10);
n = n_randint(state, 10);
prec = 2 + n_randint(state, 200);
acb_poly_set_trunc(b, a, n);
acb_poly_set_round(b, b, prec);
acb_poly_set_round(c, a, prec);
acb_poly_set_trunc(c, c, n);
acb_poly_set_trunc_round(d, a, n, prec);
acb_poly_set(e, a);
acb_poly_set_trunc_round(e, e, n, prec);
if (!acb_poly_equal(b, c) || !acb_poly_equal(c, d) || !acb_poly_equal(d, e))
{
flint_printf("FAIL\n\n");
acb_poly_printd(a, 50), flint_printf("\n\n");
acb_poly_printd(b, 50), flint_printf("\n\n");
acb_poly_printd(c, 50), flint_printf("\n\n");
acb_poly_printd(d, 50), flint_printf("\n\n");
acb_poly_printd(e, 50), flint_printf("\n\n");
abort();
}
acb_poly_clear(a);
acb_poly_clear(b);
acb_poly_clear(c);
acb_poly_clear(d);
acb_poly_clear(e);
}
flint_randclear(state);
flint_cleanup();
flint_printf("PASS\n");
return 0;
}

View file

@ -0,0 +1,83 @@
/*
Copyright (C) 2012 Fredrik Johansson
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "acb_poly.h"
int main()
{
slong iter;
flint_rand_t state;
flint_printf("sub_series....");
fflush(stdout);
flint_randinit(state);
for (iter = 0; iter < 1000 * arb_test_multiplier(); iter++)
{
acb_poly_t a, b, c, d;
slong len, prec;
acb_poly_init(a);
acb_poly_init(b);
acb_poly_init(c);
acb_poly_init(d);
acb_poly_randtest(a, state, 1 + n_randint(state, 10), 100, 10);
acb_poly_randtest(b, state, 1 + n_randint(state, 10), 100, 10);
acb_poly_randtest(c, state, 1 + n_randint(state, 10), 100, 10);
acb_poly_randtest(d, state, 1 + n_randint(state, 10), 100, 10);
prec = 2 + n_randint(state, 100);
len = n_randint(state, 10);
acb_poly_sub_series(c, a, b, len, prec);
acb_poly_sub(d, a, b, prec);
acb_poly_truncate(d, len);
if (!acb_poly_equal(c, d))
{
flint_printf("FAIL\n\n");
flint_printf("a = "); acb_poly_printd(a, 15); flint_printf("\n\n");
flint_printf("b = "); acb_poly_printd(b, 15); flint_printf("\n\n");
flint_printf("c = "); acb_poly_printd(c, 15); flint_printf("\n\n");
flint_printf("c = "); acb_poly_printd(c, 15); flint_printf("\n\n");
abort();
}
acb_poly_set(d, a);
acb_poly_sub_series(d, d, b, len, prec);
if (!acb_poly_equal(d, c))
{
flint_printf("FAIL (aliasing 1)\n\n");
abort();
}
acb_poly_set(d, b);
acb_poly_sub_series(d, a, d, len, prec);
if (!acb_poly_equal(d, c))
{
flint_printf("FAIL (aliasing 2)\n\n");
abort();
}
acb_poly_clear(a);
acb_poly_clear(b);
acb_poly_clear(c);
acb_poly_clear(d);
}
flint_randclear(state);
flint_cleanup();
flint_printf("PASS\n");
return EXIT_SUCCESS;
}

25
acb_poly/valuation.c Normal file
View file

@ -0,0 +1,25 @@
/*
Copyright (C) 2016 Fredrik Johansson
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "acb_poly.h"
slong
acb_poly_valuation(const acb_poly_t poly)
{
slong i, len = poly->length;
for (i = 0; i < len; i++)
if (!acb_is_zero(poly->coeffs + i))
return i;
return -1;
}

7
arb.h
View file

@ -54,12 +54,7 @@ arb_init(arb_t x)
mag_init(arb_radref(x)); mag_init(arb_radref(x));
} }
ARB_INLINE void void arb_clear(arb_t x);
arb_clear(arb_t x)
{
arf_clear(arb_midref(x));
mag_clear(arb_radref(x));
}
ARB_INLINE arb_ptr ARB_INLINE arb_ptr
_arb_vec_init(slong n) _arb_vec_init(slong n)

28
arb/clear.c Normal file
View file

@ -0,0 +1,28 @@
/*
Copyright (C) 2016 Fredrik Johansson
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "arb.h"
/* The clear methods are not defined as inlines since this inflates
the code size. We inline the content manually here to avoid function
call overhead. */
void
arb_clear(arb_t x)
{
ARF_DEMOTE(arb_midref(x));
if (COEFF_IS_MPZ(ARF_EXP(arb_midref(x))))
_fmpz_clear_mpz(ARF_EXP(arb_midref(x)));
if (COEFF_IS_MPZ(MAG_EXP(arb_radref(x))))
_fmpz_clear_mpz(MAG_EXP(arb_radref(x)));
}

103
arb_hypgeom.h Normal file
View file

@ -0,0 +1,103 @@
/*
Copyright (C) 2016 Fredrik Johansson
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#ifndef ARB_HYPGEOM_H
#define ARB_HYPGEOM_H
#include "arb.h"
#include "arb_poly.h"
#ifdef __cplusplus
extern "C" {
#endif
void arb_hypgeom_pfq(arb_t res, arb_srcptr a, slong p, arb_srcptr b, slong q,
const arb_t z, int regularized, slong prec);
void arb_hypgeom_0f1(arb_t res, const arb_t a, const arb_t z, int regularized, slong prec);
void arb_hypgeom_m(arb_t res, const arb_t a, const arb_t b, const arb_t z, int regularized, slong prec);
void arb_hypgeom_1f1(arb_t res, const arb_t a, const arb_t b, const arb_t z, int regularized, slong prec);
void arb_hypgeom_u(arb_t res, const arb_t a, const arb_t b, const arb_t z, slong prec);
void arb_hypgeom_2f1(arb_t res, const arb_t a, const arb_t b, const arb_t c, const arb_t z, int regularized, slong prec);
void arb_hypgeom_erf(arb_t res, const arb_t z, slong prec);
void _arb_hypgeom_erf_series(arb_ptr g, arb_srcptr h, slong hlen, slong len, slong prec);
void arb_hypgeom_erf_series(arb_poly_t g, const arb_poly_t h, slong len, slong prec);
void arb_hypgeom_erfc(arb_t res, const arb_t z, slong prec);
void _arb_hypgeom_erfc_series(arb_ptr g, arb_srcptr h, slong hlen, slong len, slong prec);
void arb_hypgeom_erfc_series(arb_poly_t g, const arb_poly_t h, slong len, slong prec);
void arb_hypgeom_erfi(arb_t res, const arb_t z, slong prec);
void _arb_hypgeom_erfi_series(arb_ptr g, arb_srcptr h, slong hlen, slong len, slong prec);
void arb_hypgeom_erfi_series(arb_poly_t g, const arb_poly_t h, slong len, slong prec);
void arb_hypgeom_fresnel(arb_t res1, arb_t res2, const arb_t z, int normalized, slong prec);
void _arb_hypgeom_fresnel_series(arb_ptr s, arb_ptr c, arb_srcptr h, slong hlen, int normalized, slong len, slong prec);
void arb_hypgeom_fresnel_series(arb_poly_t s, arb_poly_t c, const arb_poly_t h, int normalized, slong len, slong prec);
void arb_hypgeom_ei(arb_t res, const arb_t z, slong prec);
void _arb_hypgeom_ei_series(arb_ptr g, arb_srcptr h, slong hlen, slong len, slong prec);
void arb_hypgeom_ei_series(arb_poly_t g, const arb_poly_t h, slong len, slong prec);
void arb_hypgeom_si(arb_t res, const arb_t z, slong prec);
void _arb_hypgeom_si_series(arb_ptr g, arb_srcptr h, slong hlen, slong len, slong prec);
void arb_hypgeom_si_series(arb_poly_t g, const arb_poly_t h, slong len, slong prec);
void arb_hypgeom_ci(arb_t res, const arb_t z, slong prec);
void _arb_hypgeom_ci_series(arb_ptr g, arb_srcptr h, slong hlen, slong len, slong prec);
void arb_hypgeom_ci_series(arb_poly_t g, const arb_poly_t h, slong len, slong prec);
void arb_hypgeom_shi(arb_t res, const arb_t z, slong prec);
void _arb_hypgeom_shi_series(arb_ptr g, arb_srcptr h, slong hlen, slong len, slong prec);
void arb_hypgeom_shi_series(arb_poly_t g, const arb_poly_t h, slong len, slong prec);
void arb_hypgeom_chi(arb_t res, const arb_t z, slong prec);
void _arb_hypgeom_chi_series(arb_ptr g, arb_srcptr h, slong hlen, slong len, slong prec);
void arb_hypgeom_chi_series(arb_poly_t g, const arb_poly_t h, slong len, slong prec);
void arb_hypgeom_li(arb_t res, const arb_t z, int offset, slong prec);
void _arb_hypgeom_li_series(arb_ptr g, arb_srcptr h, slong hlen, int offset, slong len, slong prec);
void arb_hypgeom_li_series(arb_poly_t g, const arb_poly_t h, int offset, slong len, slong prec);
void arb_hypgeom_bessel_j(arb_t res, const arb_t nu, const arb_t z, slong prec);
void arb_hypgeom_bessel_y(arb_t res, const arb_t nu, const arb_t z, slong prec);
void arb_hypgeom_bessel_jy(arb_t res1, arb_t res2, const arb_t nu, const arb_t z, slong prec);
void arb_hypgeom_bessel_i(arb_t res, const arb_t nu, const arb_t z, slong prec);
void arb_hypgeom_bessel_k(arb_t res, const arb_t nu, const arb_t z, slong prec);
void arb_hypgeom_airy(arb_t ai, arb_t aip, arb_t bi, arb_t bip, const arb_t z, slong prec);
void arb_hypgeom_airy_jet(arb_ptr ai, arb_ptr bi, const arb_t z, slong len, slong prec);
void arb_hypgeom_airy_series(arb_poly_t ai, arb_poly_t ai_prime,
arb_poly_t bi, arb_poly_t bi_prime, const arb_poly_t z, slong len, slong prec);
void _arb_hypgeom_airy_series(arb_ptr ai, arb_ptr ai_prime,
arb_ptr bi, arb_ptr bi_prime, arb_srcptr z, slong zlen, slong len, slong prec);
void arb_hypgeom_expint(arb_t res, const arb_t s, const arb_t z, slong prec);
void arb_hypgeom_gamma_lower(arb_t res, const arb_t s, const arb_t z, int regularized, slong prec);
void _arb_hypgeom_gamma_lower_series(arb_ptr g, const arb_t s, arb_srcptr h, slong hlen, int regularized, slong n, slong prec);
void arb_hypgeom_gamma_lower_series(arb_poly_t g, const arb_t s, const arb_poly_t h, int regularized, slong n, slong prec);
void arb_hypgeom_gamma_upper(arb_t res, const arb_t s, const arb_t z, int regularized, slong prec);
void _arb_hypgeom_gamma_upper_series(arb_ptr g, const arb_t s, arb_srcptr h, slong hlen, int regularized, slong n, slong prec);
void arb_hypgeom_gamma_upper_series(arb_poly_t g, const arb_t s, const arb_poly_t h, int regularized, slong n, slong prec);
void arb_hypgeom_beta_lower(arb_t res, const arb_t a, const arb_t c, const arb_t z, int regularized, slong prec);
void arb_hypgeom_beta_lower_series(arb_poly_t res, const arb_t a, const arb_t b, const arb_poly_t z, int regularized, slong len, slong prec);
void _arb_hypgeom_beta_lower_series(arb_ptr res, const arb_t a, const arb_t b, arb_srcptr z, slong zlen, int regularized, slong len, slong prec);
#ifdef __cplusplus
}
#endif
#endif

46
arb_hypgeom/airy.c Normal file
View file

@ -0,0 +1,46 @@
/*
Copyright (C) 2015 Fredrik Johansson
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "arb_hypgeom.h"
#include "acb_hypgeom.h"
void
arb_hypgeom_airy(arb_t ai, arb_t aip, arb_t bi, arb_t bip, const arb_t z, slong prec)
{
acb_struct tmp[5];
if (ai != NULL) acb_init(tmp);
if (aip != NULL) acb_init(tmp + 1);
if (bi != NULL) acb_init(tmp + 2);
if (bip != NULL) acb_init(tmp + 3);
acb_init(tmp + 4);
acb_set_arb(tmp + 4, z);
acb_hypgeom_airy(ai ? tmp : NULL,
aip ? tmp + 1 : NULL,
bi ? tmp + 2 : NULL,
bip ? tmp + 3 : NULL,
tmp + 4, prec);
if (ai != NULL) arb_set(ai, acb_realref(tmp));
if (aip != NULL) arb_set(aip, acb_realref(tmp + 1));
if (bi != NULL) arb_set(bi, acb_realref(tmp + 2));
if (bip != NULL) arb_set(bip, acb_realref(tmp + 3));
if (ai != NULL) acb_clear(tmp);
if (aip != NULL) acb_clear(tmp + 1);
if (bi != NULL) acb_clear(tmp + 2);
if (bip != NULL) acb_clear(tmp + 3);
acb_clear(tmp + 4);
}

50
arb_hypgeom/airy_jet.c Normal file
View file

@ -0,0 +1,50 @@
/*
Copyright (C) 2016 Fredrik Johansson
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "arb_hypgeom.h"
static void
airy_recurrence(arb_ptr ai, const arb_t z, slong len, slong prec)
{
slong k;
if (len >= 3)
{
arb_mul(ai + 2, ai, z, prec);
arb_mul_2exp_si(ai + 2, ai + 2, -1);
}
for (k = 3; k < len; k++)
{
arb_mul(ai + k, ai + k - 2, z, prec);
arb_add(ai + k, ai + k, ai + k - 3, prec);
arb_div_ui(ai + k, ai + k, k * (k - 1), prec);
}
}
void
arb_hypgeom_airy_jet(arb_ptr ai, arb_ptr bi, const arb_t z, slong len, slong prec)
{
if (len <= 0)
return;
if (len == 1)
{
arb_hypgeom_airy(ai, NULL, bi, NULL, z, prec);
return;
}
arb_hypgeom_airy(ai, ai ? (ai + 1) : NULL, bi, bi ? (bi + 1) : NULL, z, prec);
if (ai != NULL) airy_recurrence(ai, z, len, prec);
if (bi != NULL) airy_recurrence(bi, z, len, prec);
}

127
arb_hypgeom/airy_series.c Normal file
View file

@ -0,0 +1,127 @@
/*
Copyright (C) 2016 Fredrik Johansson
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "arb_hypgeom.h"
void
_arb_hypgeom_airy_series(arb_ptr ai, arb_ptr ai_prime,
arb_ptr bi, arb_ptr bi_prime, arb_srcptr z, slong zlen, slong len, slong prec)
{
arb_ptr t, u, v;
slong tlen = len + ((ai_prime != NULL) || (bi_prime != NULL));
zlen = FLINT_MIN(zlen, len);
if (zlen <= 0)
return;
if (zlen == 1)
{
arb_hypgeom_airy(ai, ai_prime, bi, bi_prime, z, prec);
return;
}
t = _arb_vec_init(tlen);
u = _arb_vec_init(tlen);
v = _arb_vec_init(len);
arb_hypgeom_airy_jet((ai || ai_prime) ? t : NULL,
(bi || bi_prime) ? u : NULL, z, tlen, prec);
/* compose with nonconstant part */
arb_zero(v);
_arb_vec_set(v + 1, z + 1, zlen - 1);
if (ai != NULL) _arb_poly_compose_series(ai, t, len, v, zlen, len, prec);
if (bi != NULL) _arb_poly_compose_series(bi, u, len, v, zlen, len, prec);
/* todo: use chain rule to avoid compositions for derivatives? */
if (ai_prime != NULL)
{
_arb_poly_derivative(t, t, len + 1, prec);
_arb_poly_compose_series(ai_prime, t, len, v, zlen, len, prec);
}
if (bi_prime != NULL)
{
_arb_poly_derivative(u, u, len + 1, prec);
_arb_poly_compose_series(bi_prime, u, len, v, zlen, len, prec);
}
_arb_vec_clear(t, tlen);
_arb_vec_clear(u, tlen);
_arb_vec_clear(v, len);
}
void
arb_hypgeom_airy_series(arb_poly_t ai, arb_poly_t ai_prime,
arb_poly_t bi, arb_poly_t bi_prime, const arb_poly_t z, slong len, slong prec)
{
if (len == 0)
{
if (ai != NULL) arb_poly_zero(ai);
if (ai_prime != NULL) arb_poly_zero(ai_prime);
if (bi != NULL) arb_poly_zero(bi);
if (bi_prime != NULL) arb_poly_zero(bi_prime);
return;
}
if (z->length <= 1)
len = 1;
if (ai != NULL) arb_poly_fit_length(ai, len);
if (ai_prime != NULL) arb_poly_fit_length(ai_prime, len);
if (bi != NULL) arb_poly_fit_length(bi, len);
if (bi_prime != NULL) arb_poly_fit_length(bi_prime, len);
if (z->length == 0)
{
arb_t t;
arb_init(t);
_arb_hypgeom_airy_series(
ai ? ai->coeffs : NULL, ai_prime ? ai_prime->coeffs : NULL,
bi ? bi->coeffs : NULL, bi_prime ? bi_prime->coeffs : NULL,
t, 1, len, prec);
arb_clear(t);
}
else
{
_arb_hypgeom_airy_series(
ai ? ai->coeffs : NULL, ai_prime ? ai_prime->coeffs : NULL,
bi ? bi->coeffs : NULL, bi_prime ? bi_prime->coeffs : NULL,
z->coeffs, z->length, len, prec);
}
if (ai != NULL)
{
_arb_poly_set_length(ai, len);
_arb_poly_normalise(ai);
}
if (ai_prime != NULL)
{
_arb_poly_set_length(ai_prime, len);
_arb_poly_normalise(ai_prime);
}
if (bi != NULL)
{
_arb_poly_set_length(bi, len);
_arb_poly_normalise(bi);
}
if (bi_prime != NULL)
{
_arb_poly_set_length(bi_prime, len);
_arb_poly_normalise(bi_prime);
}
}

View file

@ -0,0 +1,114 @@
/*
Copyright (C) 2016 Fredrik Johansson
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "arb_hypgeom.h"
void
_arb_hypgeom_beta_lower_series(arb_ptr res,
const arb_t a, const arb_t b, arb_srcptr z, slong zlen, int regularized,
slong len, slong prec)
{
arb_ptr t, u, v;
arb_t c, d, e;
zlen = FLINT_MIN(zlen, len);
if (zlen == 1)
{
arb_hypgeom_beta_lower(res, a, b, z, regularized, prec);
_arb_vec_zero(res + 1, len - 1);
return;
}
t = _arb_vec_init(len);
u = _arb_vec_init(len);
v = _arb_vec_init(zlen - 1);
arb_init(c);
arb_init(d);
arb_init(e);
arb_hypgeom_beta_lower(d, a, b, z, regularized, prec);
if (regularized)
{
/* todo: except in special cases, we already compute a bunch of
gamma functions in beta_lower, so we could avoid recomputing them */
arb_add(e, a, b, prec);
arb_gamma(e, e, prec);
arb_rgamma(c, a, prec);
arb_mul(e, e, c, prec);
arb_rgamma(c, b, prec);
arb_mul(e, e, c, prec);
}
/* u = (1-z)^(b-1) */
_arb_vec_neg(t, z, zlen);
arb_add_ui(t, t, 1, prec);
arb_sub_ui(c, b, 1, prec);
_arb_poly_pow_arb_series(u, t, FLINT_MIN(zlen, len - 1), c, len - 1, prec);
/* t = z^(a-1) */
arb_sub_ui(c, a, 1, prec);
_arb_poly_pow_arb_series(t, z, FLINT_MIN(zlen, len - 1), c, len - 1, prec);
/* v = z' */
_arb_poly_derivative(v, z, zlen, prec);
_arb_poly_mullow(res, t, len - 1, u, len - 1, len - 1, prec);
_arb_poly_mullow(t, res, len - 1, v, zlen - 1, len - 1, prec);
_arb_poly_integral(res, t, len, prec);
if (regularized)
{
_arb_vec_scalar_mul(res, res, len, e, prec);
}
arb_set(res, d);
_arb_vec_clear(t, len);
_arb_vec_clear(u, len);
_arb_vec_clear(v, zlen - 1);
arb_clear(c);
arb_clear(d);
arb_clear(e);
}
void arb_hypgeom_beta_lower_series(arb_poly_t res,
const arb_t a, const arb_t b, const arb_poly_t z, int regularized,
slong len, slong prec)
{
if (len == 0)
{
arb_poly_zero(res);
return;
}
arb_poly_fit_length(res, len);
if (z->length == 0)
{
arb_t t;
arb_init(t);
_arb_hypgeom_beta_lower_series(res->coeffs, a, b, t, 1,
regularized, len, prec);
arb_clear(t);
}
else
{
_arb_hypgeom_beta_lower_series(res->coeffs, a, b, z->coeffs,
z->length, regularized, len, prec);
}
_arb_poly_set_length(res, len);
_arb_poly_normalise(res);
}

80
arb_hypgeom/chi_series.c Normal file
View file

@ -0,0 +1,80 @@
/*
Copyright (C) 2016 Fredrik Johansson
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "arb_hypgeom.h"
void
_arb_hypgeom_chi_series(arb_ptr g, arb_srcptr h, slong hlen, slong len, slong prec)
{
arb_t c;
if (!arb_is_positive(h))
{
_arb_vec_indeterminate(g, len);
return;
}
arb_init(c);
arb_hypgeom_chi(c, h, prec);
hlen = FLINT_MIN(hlen, len);
if (hlen == 1)
{
_arb_vec_zero(g + 1, len - 1);
}
else
{
arb_ptr t, u, v;
t = _arb_vec_init(len);
u = _arb_vec_init(len);
v = _arb_vec_init(len);
/* Chi(h(x)) = integral([h'(x) / h(x)] cosh(h(x)) */
_arb_poly_cosh_series(t, h, hlen, len - 1, prec);
_arb_poly_derivative(u, h, hlen, prec);
_arb_poly_mullow(v, t, len - 1, u, len - 1, len - 1, prec);
_arb_poly_div_series(u, v, len - 1, h, hlen, len - 1, prec);
_arb_poly_integral(g, u, len, prec);
_arb_vec_clear(t, len);
_arb_vec_clear(u, len);
_arb_vec_clear(v, len);
}
arb_swap(g, c);
arb_clear(c);
}
void
arb_hypgeom_chi_series(arb_poly_t g, const arb_poly_t h, slong len, slong prec)
{
slong hlen = h->length;
if (len == 0)
{
arb_poly_zero(g);
return;
}
if (hlen == 0)
{
arb_poly_inv_series(g, h, len, prec);
return;
}
arb_poly_fit_length(g, len);
_arb_hypgeom_chi_series(g->coeffs, h->coeffs, hlen, len, prec);
_arb_poly_set_length(g, len);
_arb_poly_normalise(g);
}

80
arb_hypgeom/ci_series.c Normal file
View file

@ -0,0 +1,80 @@
/*
Copyright (C) 2016 Fredrik Johansson
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "arb_hypgeom.h"
void
_arb_hypgeom_ci_series(arb_ptr g, arb_srcptr h, slong hlen, slong len, slong prec)
{
arb_t c;
if (!arb_is_positive(h))
{
_arb_vec_indeterminate(g, len);
return;
}
arb_init(c);
arb_hypgeom_ci(c, h, prec);
hlen = FLINT_MIN(hlen, len);
if (hlen == 1)
{
_arb_vec_zero(g + 1, len - 1);
}
else
{
arb_ptr t, u, v;
t = _arb_vec_init(len);
u = _arb_vec_init(len);
v = _arb_vec_init(len);
/* Ci(h(x)) = integral([h'(x) / h(x)] cos(h(x)) */
_arb_poly_cos_series(t, h, hlen, len - 1, prec);
_arb_poly_derivative(u, h, hlen, prec);
_arb_poly_mullow(v, t, len - 1, u, len - 1, len - 1, prec);
_arb_poly_div_series(u, v, len - 1, h, hlen, len - 1, prec);
_arb_poly_integral(g, u, len, prec);
_arb_vec_clear(t, len);
_arb_vec_clear(u, len);
_arb_vec_clear(v, len);
}
arb_swap(g, c);
arb_clear(c);
}
void
arb_hypgeom_ci_series(arb_poly_t g, const arb_poly_t h, slong len, slong prec)
{
slong hlen = h->length;
if (len == 0)
{
arb_poly_zero(g);
return;
}
if (hlen == 0)
{
arb_poly_inv_series(g, h, len, prec);
return;
}
arb_poly_fit_length(g, len);
_arb_hypgeom_ci_series(g->coeffs, h->coeffs, hlen, len, prec);
_arb_poly_set_length(g, len);
_arb_poly_normalise(g);
}

80
arb_hypgeom/ei_series.c Normal file
View file

@ -0,0 +1,80 @@
/*
Copyright (C) 2016 Fredrik Johansson
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "arb_hypgeom.h"
void
_arb_hypgeom_ei_series(arb_ptr g, arb_srcptr h, slong hlen, slong len, slong prec)
{
arb_t c;
if (arb_contains_zero(h))
{
_arb_vec_indeterminate(g, len);
return;
}
arb_init(c);
arb_hypgeom_ei(c, h, prec);
hlen = FLINT_MIN(hlen, len);
if (hlen == 1)
{
_arb_vec_zero(g + 1, len - 1);
}
else
{
arb_ptr t, u, v;
t = _arb_vec_init(len);
u = _arb_vec_init(len);
v = _arb_vec_init(len);
/* Ei(h(x)) = integral([h'(x) / h(x)] exp(h(x)) */
_arb_poly_exp_series(t, h, hlen, len - 1, prec);
_arb_poly_derivative(u, h, hlen, prec);
_arb_poly_mullow(v, t, len - 1, u, len - 1, len - 1, prec);
_arb_poly_div_series(u, v, len - 1, h, hlen, len - 1, prec);
_arb_poly_integral(g, u, len, prec);
_arb_vec_clear(t, len);
_arb_vec_clear(u, len);
_arb_vec_clear(v, len);
}
arb_swap(g, c);
arb_clear(c);
}
void
arb_hypgeom_ei_series(arb_poly_t g, const arb_poly_t h, slong len, slong prec)
{
slong hlen = h->length;
if (len == 0)
{
arb_poly_zero(g);
return;
}
if (hlen == 0)
{
arb_poly_inv_series(g, h, len, prec);
return;
}
arb_poly_fit_length(g, len);
_arb_hypgeom_ei_series(g->coeffs, h->coeffs, hlen, len, prec);
_arb_poly_set_length(g, len);
_arb_poly_normalise(g);
}

75
arb_hypgeom/erf_series.c Normal file
View file

@ -0,0 +1,75 @@
/*
Copyright (C) 2016 Fredrik Johansson
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "arb_hypgeom.h"
void
_arb_hypgeom_erf_series(arb_ptr g, arb_srcptr h, slong hlen, slong len, slong prec)
{
arb_t c;
arb_init(c);
arb_hypgeom_erf(c, h, prec);
hlen = FLINT_MIN(hlen, len);
if (hlen == 1)
{
_arb_vec_zero(g + 1, len - 1);
}
else
{
arb_ptr t, u;
slong ulen;
t = _arb_vec_init(len);
u = _arb_vec_init(len);
/* erf(h(x)) = integral(h'(x) exp(-h(x)^2)) * (2/sqrt(pi)) */
ulen = FLINT_MIN(len, 2 * hlen - 1);
_arb_poly_mullow(u, h, hlen, h, hlen, ulen, prec);
_arb_vec_neg(u, u, ulen);
_arb_poly_exp_series(u, u, ulen, len, prec);
_arb_poly_derivative(t, h, hlen, prec);
_arb_poly_mullow(g, u, len, t, hlen - 1, len, prec);
_arb_poly_integral(g, g, len, prec);
arb_const_sqrt_pi(t, prec);
arb_inv(t, t, prec);
arb_mul_2exp_si(t, t, 1);
_arb_vec_scalar_mul(g, g, len, t, prec);
_arb_vec_clear(t, len);
_arb_vec_clear(u, len);
}
arb_swap(g, c);
arb_clear(c);
}
void
arb_hypgeom_erf_series(arb_poly_t g, const arb_poly_t h, slong len, slong prec)
{
slong hlen = h->length;
if (hlen == 0 || len == 0)
{
arb_poly_zero(g);
return;
}
arb_poly_fit_length(g, len);
_arb_hypgeom_erf_series(g->coeffs, h->coeffs, hlen, len, prec);
_arb_poly_set_length(g, len);
_arb_poly_normalise(g);
}

82
arb_hypgeom/erfc_series.c Normal file
View file

@ -0,0 +1,82 @@
/*
Copyright (C) 2016 Fredrik Johansson
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "arb_hypgeom.h"
void
_arb_hypgeom_erfc_series(arb_ptr g, arb_srcptr h, slong hlen, slong len, slong prec)
{
arb_t c;
arb_init(c);
arb_hypgeom_erfc(c, h, prec);
hlen = FLINT_MIN(hlen, len);
if (hlen == 1)
{
_arb_vec_zero(g + 1, len - 1);
}
else
{
arb_ptr t, u;
slong ulen;
t = _arb_vec_init(len);
u = _arb_vec_init(len);
/* erfc(h(x)) = integral(-h'(x) exp(-h(x)^2)) * (2/sqrt(pi)) */
ulen = FLINT_MIN(len, 2 * hlen - 1);
_arb_poly_mullow(u, h, hlen, h, hlen, ulen, prec);
_arb_vec_neg(u, u, ulen);
_arb_poly_exp_series(u, u, ulen, len, prec);
_arb_poly_derivative(t, h, hlen, prec);
_arb_poly_mullow(g, u, len, t, hlen - 1, len, prec);
_arb_poly_integral(g, g, len, prec);
arb_const_sqrt_pi(t, prec);
arb_inv(t, t, prec);
arb_mul_2exp_si(t, t, 1);
_arb_vec_scalar_mul(g, g, len, t, prec);
_arb_vec_neg(g, g, len);
_arb_vec_clear(t, len);
_arb_vec_clear(u, len);
}
arb_swap(g, c);
arb_clear(c);
}
void
arb_hypgeom_erfc_series(arb_poly_t g, const arb_poly_t h, slong len, slong prec)
{
slong hlen = h->length;
if (len == 0)
{
arb_poly_zero(g);
return;
}
if (hlen == 0)
{
arb_poly_one(g);
return;
}
arb_poly_fit_length(g, len);
_arb_hypgeom_erfc_series(g->coeffs, h->coeffs, hlen, len, prec);
_arb_poly_set_length(g, len);
_arb_poly_normalise(g);
}

74
arb_hypgeom/erfi_series.c Normal file
View file

@ -0,0 +1,74 @@
/*
Copyright (C) 2016 Fredrik Johansson
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "arb_hypgeom.h"
void
_arb_hypgeom_erfi_series(arb_ptr g, arb_srcptr h, slong hlen, slong len, slong prec)
{
arb_t c;
arb_init(c);
arb_hypgeom_erfi(c, h, prec);
hlen = FLINT_MIN(hlen, len);
if (hlen == 1)
{
_arb_vec_zero(g + 1, len - 1);
}
else
{
arb_ptr t, u;
slong ulen;
t = _arb_vec_init(len);
u = _arb_vec_init(len);
/* erfi(h(x)) = integral(h'(x) exp(h(x)^2)) * (2/sqrt(pi)) */
ulen = FLINT_MIN(len, 2 * hlen - 1);
_arb_poly_mullow(u, h, hlen, h, hlen, ulen, prec);
_arb_poly_exp_series(u, u, ulen, len, prec);
_arb_poly_derivative(t, h, hlen, prec);
_arb_poly_mullow(g, u, len, t, hlen - 1, len, prec);
_arb_poly_integral(g, g, len, prec);
arb_const_sqrt_pi(t, prec);
arb_inv(t, t, prec);
arb_mul_2exp_si(t, t, 1);
_arb_vec_scalar_mul(g, g, len, t, prec);
_arb_vec_clear(t, len);
_arb_vec_clear(u, len);
}
arb_swap(g, c);
arb_clear(c);
}
void
arb_hypgeom_erfi_series(arb_poly_t g, const arb_poly_t h, slong len, slong prec)
{
slong hlen = h->length;
if (hlen == 0 || len == 0)
{
arb_poly_zero(g);
return;
}
arb_poly_fit_length(g, len);
_arb_hypgeom_erfi_series(g->coeffs, h->coeffs, hlen, len, prec);
_arb_poly_set_length(g, len);
_arb_poly_normalise(g);
}

View file

@ -0,0 +1,112 @@
/*
Copyright (C) 2016 Fredrik Johansson
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "arb_hypgeom.h"
void
_arb_hypgeom_fresnel_series(arb_ptr s, arb_ptr c,
arb_srcptr h, slong hlen, int normalized, slong len, slong prec)
{
hlen = FLINT_MIN(hlen, len);
if (hlen == 1)
{
arb_hypgeom_fresnel(s, c, h, normalized, prec);
if (s != NULL) _arb_vec_zero(s + 1, len - 1);
if (c != NULL) _arb_vec_zero(c + 1, len - 1);
}
else
{
arb_t s0, c0;
arb_ptr t, u, v;
slong ulen;
arb_init(s0);
arb_init(c0);
arb_hypgeom_fresnel((s != NULL) ? s0 : NULL,
(c != NULL) ? c0 : NULL, h, normalized, prec);
t = _arb_vec_init(len);
u = _arb_vec_init(len);
v = _arb_vec_init(len);
/* normalized: */
/* C(h(x)) = integral(h'(x) cos(-(pi/2) h(x)^2)) */
/* S(h(x)) = -integral(h'(x) sin(-(pi/2) h(x)^2)) */
ulen = FLINT_MIN(len, 2 * hlen - 1);
_arb_poly_mullow(u, h, hlen, h, hlen, ulen, prec);
_arb_vec_neg(u, u, ulen);
if (normalized)
{
_arb_vec_scalar_mul_2exp_si(u, u, ulen, -1);
_arb_poly_sin_cos_pi_series(u, v, u, ulen, len, prec);
}
else
{
_arb_poly_sin_cos_series(u, v, u, ulen, len, prec);
}
_arb_poly_derivative(t, h, hlen, prec);
if (s != NULL)
{
_arb_poly_mullow(s, u, len, t, hlen - 1, len, prec);
_arb_poly_integral(s, s, len, prec);
_arb_vec_neg(s, s, len);
arb_swap(s, s0);
}
if (c != NULL)
{
_arb_poly_mullow(c, v, len, t, hlen - 1, len, prec);
_arb_poly_integral(c, c, len, prec);
arb_swap(c, c0);
}
_arb_vec_clear(t, len);
_arb_vec_clear(u, len);
_arb_vec_clear(v, len);
arb_clear(s0);
arb_clear(c0);
}
}
void
arb_hypgeom_fresnel_series(arb_poly_t s, arb_poly_t c,
const arb_poly_t h, int normalized, slong len, slong prec)
{
slong hlen = h->length;
if (hlen == 0 || len == 0)
{
if (s != NULL) arb_poly_zero(s);
if (c != NULL) arb_poly_zero(c);
return;
}
if (s != NULL) arb_poly_fit_length(s, len);
if (c != NULL) arb_poly_fit_length(c, len);
_arb_hypgeom_fresnel_series((s != NULL) ? s->coeffs : NULL,
(c != NULL) ? c->coeffs : NULL,
h->coeffs, hlen, normalized, len, prec);
if (s != NULL) _arb_poly_set_length(s, len);
if (c != NULL) _arb_poly_set_length(c, len);
if (s != NULL) _arb_poly_normalise(s);
if (c != NULL) _arb_poly_normalise(c);
}

View file

@ -0,0 +1,128 @@
/*
Copyright (C) 2016 Arb authors
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "arb_poly.h"
#include "arb_hypgeom.h"
void
_arb_hypgeom_gamma_lower_series(arb_ptr g, const arb_t s, arb_srcptr h, slong hlen, int regularized, slong n, slong prec)
{
arb_t c;
hlen = FLINT_MIN(hlen, n);
if (regularized == 2 && arb_is_int(s) && arb_is_nonpositive(s))
{
arb_t ns;
arb_init(ns);
arb_neg(ns, s);
if (g == h)
{
arb_ptr t = _arb_vec_init(hlen);
_arb_vec_set(t, h, hlen);
_arb_poly_pow_arb_series(g, t, hlen, ns, n, prec);
_arb_vec_clear(t, hlen);
}
else
{
_arb_poly_pow_arb_series(g, h, hlen, ns, n, prec);
}
arb_clear(ns);
return;
}
arb_init(c);
arb_hypgeom_gamma_lower(c, s, h, regularized, prec);
if (hlen == 1)
{
_arb_vec_zero(g + 1, n - 1);
}
else
{
arb_ptr t, u, v;
arb_ptr w = NULL;
t = _arb_vec_init(n);
u = _arb_vec_init(n);
v = _arb_vec_init(n);
if (regularized == 2)
{
w = _arb_vec_init(n);
arb_neg(t, s);
_arb_poly_pow_arb_series(w, h, hlen, t, n, prec);
}
/* gamma(s, h(x)) = integral(h'(x) h(x)^(s-1) exp(-h(x)) */
arb_sub_ui(u, s, 1, prec);
_arb_poly_pow_arb_series(t, h, hlen, u, n, prec);
_arb_poly_derivative(u, h, hlen, prec);
_arb_poly_mullow(v, t, n, u, hlen - 1, n, prec);
_arb_vec_neg(t, h, hlen);
_arb_poly_exp_series(t, t, hlen, n, prec);
_arb_poly_mullow(g, v, n, t, n, n, prec);
_arb_poly_integral(g, g, n, prec);
if (regularized == 1)
{
arb_rgamma(t, s, prec);
_arb_vec_scalar_mul(g, g, n, t, prec);
}
else if (regularized == 2)
{
arb_rgamma(t, s, prec);
_arb_vec_scalar_mul(g, g, n, t, prec);
_arb_vec_set(u, g, n);
_arb_poly_mullow(g, u, n, w, n, n, prec);
_arb_vec_clear(w, n);
}
_arb_vec_clear(t, n);
_arb_vec_clear(u, n);
_arb_vec_clear(v, n);
}
arb_swap(g, c);
arb_clear(c);
}
void
arb_hypgeom_gamma_lower_series(arb_poly_t g, const arb_t s,
const arb_poly_t h, int regularized, slong n, slong prec)
{
slong hlen = h->length;
if (n == 0)
{
arb_poly_zero(g);
return;
}
arb_poly_fit_length(g, n);
if (hlen == 0)
{
arb_t t;
arb_init(t);
_arb_hypgeom_gamma_lower_series(g->coeffs, s, t, 1, regularized, n, prec);
arb_clear(t);
}
else
{
_arb_hypgeom_gamma_lower_series(
g->coeffs, s, h->coeffs, hlen, regularized, n, prec);
}
_arb_poly_set_length(g, n);
_arb_poly_normalise(g);
}

View file

@ -0,0 +1,106 @@
/*
Copyright (C) 2015 Fredrik Johansson
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "arb_poly.h"
#include "arb_hypgeom.h"
void
_arb_hypgeom_gamma_upper_series(arb_ptr g, const arb_t s, arb_srcptr h, slong hlen, int regularized, slong n, slong prec)
{
arb_t c;
arb_init(c);
arb_hypgeom_gamma_upper(c, s, h, regularized, prec);
hlen = FLINT_MIN(hlen, n);
if (hlen == 1)
{
_arb_vec_zero(g + 1, n - 1);
}
else
{
arb_ptr t, u, v;
arb_ptr w = NULL;
t = _arb_vec_init(n);
u = _arb_vec_init(n);
v = _arb_vec_init(n);
if (regularized == 2)
{
w = _arb_vec_init(n);
arb_neg(t, s);
_arb_poly_pow_arb_series(w, h, hlen, t, n, prec);
}
/* Gamma(s, h(x)) = -integral(h'(x) h(x)^(s-1) exp(-h(x)) */
arb_sub_ui(u, s, 1, prec);
_arb_poly_pow_arb_series(t, h, hlen, u, n, prec);
_arb_poly_derivative(u, h, hlen, prec);
_arb_poly_mullow(v, t, n, u, hlen - 1, n, prec);
_arb_vec_neg(t, h, hlen);
_arb_poly_exp_series(t, t, hlen, n, prec);
_arb_poly_mullow(g, v, n, t, n, n, prec);
_arb_poly_integral(g, g, n, prec);
_arb_vec_neg(g, g, n);
if (regularized == 1)
{
arb_rgamma(t, s, prec);
_arb_vec_scalar_mul(g, g, n, t, prec);
}
else if (regularized == 2)
{
_arb_vec_set(u, g, n);
_arb_poly_mullow(g, u, n, w, n, n, prec);
_arb_vec_clear(w, n);
}
_arb_vec_clear(t, n);
_arb_vec_clear(u, n);
_arb_vec_clear(v, n);
}
arb_swap(g, c);
arb_clear(c);
}
void
arb_hypgeom_gamma_upper_series(arb_poly_t g, const arb_t s,
const arb_poly_t h, int regularized, slong n, slong prec)
{
slong hlen = h->length;
if (n == 0)
{
arb_poly_zero(g);
return;
}
arb_poly_fit_length(g, n);
if (hlen == 0)
{
arb_t t;
arb_init(t);
_arb_hypgeom_gamma_upper_series(g->coeffs, s, t, 1, regularized, n, prec);
arb_clear(t);
}
else
{
_arb_hypgeom_gamma_upper_series(
g->coeffs, s, h->coeffs, hlen, regularized, n, prec);
}
_arb_poly_set_length(g, n);
_arb_poly_normalise(g);
}

82
arb_hypgeom/li_series.c Normal file
View file

@ -0,0 +1,82 @@
/*
Copyright (C) 2016 Fredrik Johansson
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "arb_hypgeom.h"
void
_arb_hypgeom_li_series(arb_ptr g, arb_srcptr h, slong hlen, int offset, slong len, slong prec)
{
arb_t c;
if (!arb_is_positive(h) || arb_contains_si(h, 1))
{
_arb_vec_indeterminate(g, len);
return;
}
arb_init(c);
arb_hypgeom_li(c, h, offset, prec);
hlen = FLINT_MIN(hlen, len);
if (hlen == 1)
{
_arb_vec_zero(g + 1, len - 1);
}
else if (len == 2)
{
arb_log(g, h, prec);
arb_div(g + 1, h + 1, g, prec);
}
else
{
arb_ptr t, u;
t = _arb_vec_init(len);
u = _arb_vec_init(hlen);
/* li(h(x)) = integral(h'(x) / log(h(x))) */
_arb_poly_log_series(t, h, hlen, len - 1, prec);
_arb_poly_derivative(u, h, hlen, prec);
_arb_poly_div_series(g, u, hlen - 1, t, len - 1, len - 1, prec);
_arb_poly_integral(g, g, len, prec);
_arb_vec_clear(t, len);
_arb_vec_clear(u, hlen);
}
arb_swap(g, c);
arb_clear(c);
}
void
arb_hypgeom_li_series(arb_poly_t g, const arb_poly_t h, int offset, slong len, slong prec)
{
slong hlen = h->length;
if (len == 0)
{
arb_poly_zero(g);
return;
}
if (hlen == 0)
{
arb_poly_inv_series(g, h, len, prec);
return;
}
arb_poly_fit_length(g, len);
_arb_hypgeom_li_series(g->coeffs, h->coeffs, hlen, offset, len, prec);
_arb_poly_set_length(g, len);
_arb_poly_normalise(g);
}

61
arb_hypgeom/shi_series.c Normal file
View file

@ -0,0 +1,61 @@
/*
Copyright (C) 2016 Fredrik Johansson
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "arb_hypgeom.h"
#include "acb_hypgeom.h"
/* todo: use a sinch function? */
void
_arb_hypgeom_shi_series(arb_ptr g, arb_srcptr h, slong hlen, slong len, slong prec)
{
hlen = FLINT_MIN(hlen, len);
if (hlen == 1)
{
arb_hypgeom_shi(g, h, prec);
_arb_vec_zero(g + 1, len - 1);
}
else
{
acb_ptr t;
slong i;
t = _acb_vec_init(len);
for (i = 0; i < hlen; i++)
arb_set(acb_realref(t + i), h + i);
_acb_hypgeom_shi_series(t, t, hlen, len, prec);
for (i = 0; i < len; i++)
arb_swap(g + i, acb_realref(t + i));
_acb_vec_clear(t, len);
}
}
void
arb_hypgeom_shi_series(arb_poly_t g, const arb_poly_t h, slong len, slong prec)
{
slong hlen = h->length;
if (hlen == 0 || len == 0)
{
arb_poly_zero(g);
return;
}
arb_poly_fit_length(g, len);
_arb_hypgeom_shi_series(g->coeffs, h->coeffs, hlen, len, prec);
_arb_poly_set_length(g, len);
_arb_poly_normalise(g);
}

70
arb_hypgeom/si_series.c Normal file
View file

@ -0,0 +1,70 @@
/*
Copyright (C) 2016 Fredrik Johansson
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "arb_hypgeom.h"
void
_arb_hypgeom_si_series(arb_ptr g, arb_srcptr h, slong hlen, slong len, slong prec)
{
arb_t c;
arb_init(c);
arb_hypgeom_si(c, h, prec);
hlen = FLINT_MIN(hlen, len);
if (hlen == 1)
{
_arb_vec_zero(g + 1, len - 1);
}
else if (len == 2)
{
arb_sinc(g, h, prec);
arb_mul(g + 1, g, h + 1, prec);
}
else
{
arb_ptr t, u;
t = _arb_vec_init(len - 1);
u = _arb_vec_init(hlen - 1);
/* Si(h(x)) = integral(h'(x) sinc(h(x))) */
_arb_poly_sinc_series(t, h, hlen, len - 1, prec);
_arb_poly_derivative(u, h, hlen, prec);
_arb_poly_mullow(g, t, len - 1, u, hlen - 1, len - 1, prec);
_arb_poly_integral(g, g, len, prec);
_arb_vec_clear(t, len - 1);
_arb_vec_clear(u, hlen - 1);
}
arb_swap(g, c);
arb_clear(c);
}
void
arb_hypgeom_si_series(arb_poly_t g, const arb_poly_t h, slong len, slong prec)
{
slong hlen = h->length;
if (hlen == 0 || len == 0)
{
arb_poly_zero(g);
return;
}
arb_poly_fit_length(g, len);
_arb_hypgeom_si_series(g->coeffs, h->coeffs, hlen, len, prec);
_arb_poly_set_length(g, len);
_arb_poly_normalise(g);
}

462
arb_hypgeom/wrappers.c Normal file
View file

@ -0,0 +1,462 @@
/*
Copyright (C) 2016 Fredrik Johansson
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "arb_hypgeom.h"
#include "acb_hypgeom.h"
void
arb_hypgeom_erf(arb_t res, const arb_t z, slong prec)
{
if (!arb_is_finite(z))
{
arb_indeterminate(res);
}
else
{
acb_t t;
acb_init(t);
arb_set(acb_realref(t), z);
acb_hypgeom_erf(t, t, prec);
arb_swap(res, acb_realref(t));
acb_clear(t);
}
}
void
arb_hypgeom_erfc(arb_t res, const arb_t z, slong prec)
{
if (!arb_is_finite(z))
{
arb_indeterminate(res);
}
else
{
acb_t t;
acb_init(t);
arb_set(acb_realref(t), z);
acb_hypgeom_erfc(t, t, prec);
arb_swap(res, acb_realref(t));
acb_clear(t);
}
}
void
arb_hypgeom_erfi(arb_t res, const arb_t z, slong prec)
{
if (!arb_is_finite(z))
{
arb_indeterminate(res);
}
else
{
acb_t t;
acb_init(t);
arb_set(acb_realref(t), z);
acb_hypgeom_erfi(t, t, prec);
arb_swap(res, acb_realref(t));
acb_clear(t);
}
}
void
arb_hypgeom_fresnel(arb_t res1, arb_t res2, const arb_t z, int normalized, slong prec)
{
if (!arb_is_finite(z))
{
if (res1 != NULL) arb_indeterminate(res1);
if (res2 != NULL) arb_indeterminate(res2);
}
else
{
acb_t t, u;
acb_init(t);
acb_init(u);
arb_set(acb_realref(t), z);
acb_hypgeom_fresnel(res1 ? t : NULL, res2 ? u : NULL, t, normalized, prec);
if (res1 != NULL) arb_swap(res1, acb_realref(t));
if (res2 != NULL) arb_swap(res2, acb_realref(u));
acb_clear(t);
acb_clear(u);
}
}
void
arb_hypgeom_ei(arb_t res, const arb_t z, slong prec)
{
if (!arb_is_finite(z))
{
arb_indeterminate(res);
}
else
{
acb_t t;
acb_init(t);
arb_set(acb_realref(t), z);
acb_hypgeom_ei(t, t, prec);
arb_swap(res, acb_realref(t));
acb_clear(t);
}
}
void
arb_hypgeom_si(arb_t res, const arb_t z, slong prec)
{
if (!arb_is_finite(z))
{
arb_indeterminate(res);
}
else
{
acb_t t;
acb_init(t);
arb_set(acb_realref(t), z);
acb_hypgeom_si(t, t, prec);
arb_swap(res, acb_realref(t));
acb_clear(t);
}
}
void
arb_hypgeom_ci(arb_t res, const arb_t z, slong prec)
{
if (!arb_is_finite(z) || !arb_is_positive(z))
{
arb_indeterminate(res);
}
else
{
acb_t t;
acb_init(t);
arb_set(acb_realref(t), z);
acb_hypgeom_ci(t, t, prec);
arb_swap(res, acb_realref(t));
acb_clear(t);
}
}
void
arb_hypgeom_shi(arb_t res, const arb_t z, slong prec)
{
if (!arb_is_finite(z))
{
arb_indeterminate(res);
}
else
{
acb_t t;
acb_init(t);
arb_set(acb_realref(t), z);
acb_hypgeom_shi(t, t, prec);
arb_swap(res, acb_realref(t));
acb_clear(t);
}
}
void
arb_hypgeom_chi(arb_t res, const arb_t z, slong prec)
{
if (!arb_is_finite(z) || !arb_is_positive(z))
{
arb_indeterminate(res);
}
else
{
acb_t t;
acb_init(t);
arb_set(acb_realref(t), z);
acb_hypgeom_chi(t, t, prec);
arb_swap(res, acb_realref(t));
acb_clear(t);
}
}
void
arb_hypgeom_li(arb_t res, const arb_t z, int offset, slong prec)
{
if (!arb_is_finite(z) || !arb_is_nonnegative(z))
{
arb_indeterminate(res);
}
else
{
acb_t t;
acb_init(t);
arb_set(acb_realref(t), z);
acb_hypgeom_li(t, t, offset, prec);
arb_swap(res, acb_realref(t));
acb_clear(t);
}
}
void
arb_hypgeom_0f1(arb_t res, const arb_t a, const arb_t z, int regularized, slong prec)
{
acb_t t, u;
acb_init(t);
acb_init(u);
arb_set(acb_realref(t), a);
arb_set(acb_realref(u), z);
acb_hypgeom_0f1(t, t, u, regularized, prec);
if (acb_is_finite(t) && acb_is_real(t))
arb_swap(res, acb_realref(t));
else
arb_indeterminate(res);
acb_clear(t);
acb_clear(u);
}
void
arb_hypgeom_m(arb_t res, const arb_t a, const arb_t b, const arb_t z, int regularized, slong prec)
{
acb_t t, u, v;
acb_init(t);
acb_init(u);
acb_init(v);
arb_set(acb_realref(t), a);
arb_set(acb_realref(u), b);
arb_set(acb_realref(v), z);
acb_hypgeom_m(t, t, u, v, regularized, prec);
if (acb_is_finite(t) && acb_is_real(t))
arb_swap(res, acb_realref(t));
else
arb_indeterminate(res);
acb_clear(t);
acb_clear(u);
acb_clear(v);
}
void
arb_hypgeom_1f1(arb_t res, const arb_t a, const arb_t b, const arb_t z, int regularized, slong prec)
{
arb_hypgeom_m(res, a, b, z, regularized, prec);
}
void
arb_hypgeom_u(arb_t res, const arb_t a, const arb_t b, const arb_t z, slong prec)
{
acb_t t, u, v;
acb_init(t);
acb_init(u);
acb_init(v);
arb_set(acb_realref(t), a);
arb_set(acb_realref(u), b);
arb_set(acb_realref(v), z);
acb_hypgeom_u(t, t, u, v, prec);
if (acb_is_finite(t) && acb_is_real(t))
arb_swap(res, acb_realref(t));
else
arb_indeterminate(res);
acb_clear(t);
acb_clear(u);
acb_clear(v);
}
void
arb_hypgeom_2f1(arb_t res, const arb_t a, const arb_t b, const arb_t c, const arb_t z, int regularized, slong prec)
{
acb_t t, u, v, w;
acb_init(t);
acb_init(u);
acb_init(v);
acb_init(w);
arb_set(acb_realref(t), a);
arb_set(acb_realref(u), b);
arb_set(acb_realref(v), c);
arb_set(acb_realref(w), z);
acb_hypgeom_2f1(t, t, u, v, w, regularized, prec);
if (acb_is_finite(t) && acb_is_real(t))
arb_swap(res, acb_realref(t));
else
arb_indeterminate(res);
acb_clear(t);
acb_clear(u);
acb_clear(v);
acb_clear(w);
}
void
arb_hypgeom_pfq(arb_t res, arb_srcptr a, slong p, arb_srcptr b, slong q, const arb_t z, int regularized, slong prec)
{
acb_ptr t;
slong i;
t = _acb_vec_init(p + q + 1);
for (i = 0; i < p; i++)
arb_set(acb_realref(t + i), a + i);
for (i = 0; i < q; i++)
arb_set(acb_realref(t + p + i), b + i);
arb_set(acb_realref(t + p + q), z);
acb_hypgeom_pfq(t, t, p, t + p, q, t + p + q, regularized, prec);
if (acb_is_finite(t) && acb_is_real(t))
arb_swap(res, acb_realref(t));
else
arb_indeterminate(res);
_acb_vec_clear(t, p + q + 1);
}
void
arb_hypgeom_bessel_j(arb_t res, const arb_t nu, const arb_t z, slong prec)
{
acb_t t, u;
acb_init(t);
acb_init(u);
arb_set(acb_realref(t), nu);
arb_set(acb_realref(u), z);
acb_hypgeom_bessel_j(t, t, u, prec);
if (acb_is_finite(t) && acb_is_real(t))
arb_swap(res, acb_realref(t));
else
arb_indeterminate(res);
acb_clear(t);
acb_clear(u);
}
void
arb_hypgeom_bessel_y(arb_t res, const arb_t nu, const arb_t z, slong prec)
{
acb_t t, u;
acb_init(t);
acb_init(u);
arb_set(acb_realref(t), nu);
arb_set(acb_realref(u), z);
acb_hypgeom_bessel_y(t, t, u, prec);
if (acb_is_finite(t) && acb_is_real(t))
arb_swap(res, acb_realref(t));
else
arb_indeterminate(res);
acb_clear(t);
acb_clear(u);
}
void
arb_hypgeom_bessel_jy(arb_t res1, arb_t res2, const arb_t nu, const arb_t z, slong prec)
{
acb_t t, u;
acb_init(t);
acb_init(u);
arb_set(acb_realref(t), nu);
arb_set(acb_realref(u), z);
acb_hypgeom_bessel_jy(t, u, t, u, prec);
if (acb_is_finite(t) && acb_is_real(t))
arb_swap(res1, acb_realref(t));
else
arb_indeterminate(res1);
if (acb_is_finite(u) && acb_is_real(u))
arb_swap(res2, acb_realref(u));
else
arb_indeterminate(res2);
acb_clear(t);
acb_clear(u);
}
void
arb_hypgeom_bessel_i(arb_t res, const arb_t nu, const arb_t z, slong prec)
{
acb_t t, u;
acb_init(t);
acb_init(u);
arb_set(acb_realref(t), nu);
arb_set(acb_realref(u), z);
acb_hypgeom_bessel_i(t, t, u, prec);
if (acb_is_finite(t) && acb_is_real(t))
arb_swap(res, acb_realref(t));
else
arb_indeterminate(res);
acb_clear(t);
acb_clear(u);
}
void
arb_hypgeom_bessel_k(arb_t res, const arb_t nu, const arb_t z, slong prec)
{
acb_t t, u;
acb_init(t);
acb_init(u);
arb_set(acb_realref(t), nu);
arb_set(acb_realref(u), z);
acb_hypgeom_bessel_k(t, t, u, prec);
if (acb_is_finite(t) && acb_is_real(t))
arb_swap(res, acb_realref(t));
else
arb_indeterminate(res);
acb_clear(t);
acb_clear(u);
}
void
arb_hypgeom_expint(arb_t res, const arb_t s, const arb_t z, slong prec)
{
acb_t t, u;
acb_init(t);
acb_init(u);
arb_set(acb_realref(t), s);
arb_set(acb_realref(u), z);
acb_hypgeom_expint(t, t, u, prec);
if (acb_is_finite(t) && acb_is_real(t))
arb_swap(res, acb_realref(t));
else
arb_indeterminate(res);
acb_clear(t);
acb_clear(u);
}
void
arb_hypgeom_gamma_lower(arb_t res, const arb_t s, const arb_t z, int regularized, slong prec)
{
acb_t t, u;
acb_init(t);
acb_init(u);
arb_set(acb_realref(t), s);
arb_set(acb_realref(u), z);
acb_hypgeom_gamma_lower(t, t, u, regularized, prec);
if (acb_is_finite(t) && acb_is_real(t))
arb_swap(res, acb_realref(t));
else
arb_indeterminate(res);
acb_clear(t);
acb_clear(u);
}
void
arb_hypgeom_gamma_upper(arb_t res, const arb_t s, const arb_t z, int regularized, slong prec)
{
acb_t t, u;
acb_init(t);
acb_init(u);
arb_set(acb_realref(t), s);
arb_set(acb_realref(u), z);
acb_hypgeom_gamma_upper(t, t, u, regularized, prec);
if (acb_is_finite(t) && acb_is_real(t))
arb_swap(res, acb_realref(t));
else
arb_indeterminate(res);
acb_clear(t);
acb_clear(u);
}
void
arb_hypgeom_beta_lower(arb_t res, const arb_t a, const arb_t b, const arb_t z, int regularized, slong prec)
{
acb_t t, u, v;
acb_init(t);
acb_init(u);
acb_init(v);
arb_set(acb_realref(t), a);
arb_set(acb_realref(u), b);
arb_set(acb_realref(v), z);
acb_hypgeom_beta_lower(t, t, u, v, regularized, prec);
if (acb_is_finite(t) && acb_is_real(t))
arb_swap(res, acb_realref(t));
else
arb_indeterminate(res);
acb_clear(t);
acb_clear(u);
acb_clear(v);
}

View file

@ -65,6 +65,10 @@ void arb_poly_set(arb_poly_t poly, const arb_poly_t src);
void arb_poly_set_round(arb_poly_t poly, const arb_poly_t src, slong prec); void arb_poly_set_round(arb_poly_t poly, const arb_poly_t src, slong prec);
void arb_poly_set_trunc(arb_poly_t res, const arb_poly_t poly, slong n);
void arb_poly_set_trunc_round(arb_poly_t res, const arb_poly_t poly, slong n, slong prec);
/* Basic manipulation */ /* Basic manipulation */
ARB_POLY_INLINE slong arb_poly_length(const arb_poly_t poly) ARB_POLY_INLINE slong arb_poly_length(const arb_poly_t poly)
@ -77,6 +81,8 @@ ARB_POLY_INLINE slong arb_poly_degree(const arb_poly_t poly)
return poly->length - 1; return poly->length - 1;
} }
slong arb_poly_valuation(const arb_poly_t poly);
ARB_POLY_INLINE int ARB_POLY_INLINE int
arb_poly_is_zero(const arb_poly_t z) arb_poly_is_zero(const arb_poly_t z)
{ {
@ -210,6 +216,12 @@ void _arb_poly_sub(arb_ptr res, arb_srcptr poly1, slong len1,
void arb_poly_sub(arb_poly_t res, const arb_poly_t poly1, void arb_poly_sub(arb_poly_t res, const arb_poly_t poly1,
const arb_poly_t poly2, slong prec); const arb_poly_t poly2, slong prec);
void arb_poly_add_series(arb_poly_t res, const arb_poly_t poly1,
const arb_poly_t poly2, slong len, slong prec);
void arb_poly_sub_series(arb_poly_t res, const arb_poly_t poly1,
const arb_poly_t poly2, slong len, slong prec);
ARB_POLY_INLINE void ARB_POLY_INLINE void
arb_poly_neg(arb_poly_t res, const arb_poly_t poly) arb_poly_neg(arb_poly_t res, const arb_poly_t poly)
{ {

32
arb_poly/add_series.c Normal file
View file

@ -0,0 +1,32 @@
/*
Copyright (C) 2016 Fredrik Johansson
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "arb_poly.h"
void
arb_poly_add_series(arb_poly_t res, const arb_poly_t poly1,
const arb_poly_t poly2, slong len, slong prec)
{
slong len1, len2;
len1 = poly1->length;
len2 = poly2->length;
len1 = FLINT_MIN(len1, len);
len2 = FLINT_MIN(len2, len);
len = FLINT_MAX(len1, len2);
arb_poly_fit_length(res, len);
_arb_poly_add(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, prec);
_arb_poly_set_length(res, len);
_arb_poly_normalise(res);
}

35
arb_poly/set_trunc.c Normal file
View file

@ -0,0 +1,35 @@
/*
Copyright (C) 2016 Fredrik Johansson
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "arb_poly.h"
void
arb_poly_set_trunc(arb_poly_t res, const arb_poly_t poly, slong n)
{
if (poly == res)
{
arb_poly_truncate(res, n);
}
else
{
slong rlen;
rlen = FLINT_MIN(n, poly->length);
while (rlen > 0 && arb_is_zero(poly->coeffs + rlen - 1))
rlen--;
arb_poly_fit_length(res, rlen);
_arb_vec_set(res->coeffs, poly->coeffs, rlen);
_arb_poly_set_length(res, rlen);
}
}

View file

@ -0,0 +1,36 @@
/*
Copyright (C) 2016 Fredrik Johansson
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "arb_poly.h"
void
arb_poly_set_trunc_round(arb_poly_t res, const arb_poly_t poly, slong n, slong prec)
{
if (poly == res)
{
arb_poly_truncate(res, n);
_arb_vec_set_round(res->coeffs, res->coeffs, res->length, prec);
}
else
{
slong rlen;
rlen = FLINT_MIN(n, poly->length);
while (rlen > 0 && arb_is_zero(poly->coeffs + rlen - 1))
rlen--;
arb_poly_fit_length(res, rlen);
_arb_vec_set_round(res->coeffs, poly->coeffs, rlen, prec);
_arb_poly_set_length(res, rlen);
}
}

32
arb_poly/sub_series.c Normal file
View file

@ -0,0 +1,32 @@
/*
Copyright (C) 2016 Fredrik Johansson
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "arb_poly.h"
void
arb_poly_sub_series(arb_poly_t res, const arb_poly_t poly1,
const arb_poly_t poly2, slong len, slong prec)
{
slong len1, len2;
len1 = poly1->length;
len2 = poly2->length;
len1 = FLINT_MIN(len1, len);
len2 = FLINT_MIN(len2, len);
len = FLINT_MAX(len1, len2);
arb_poly_fit_length(res, len);
_arb_poly_sub(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, prec);
_arb_poly_set_length(res, len);
_arb_poly_normalise(res);
}

View file

@ -0,0 +1,83 @@
/*
Copyright (C) 2012 Fredrik Johansson
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "arb_poly.h"
int main()
{
slong iter;
flint_rand_t state;
flint_printf("add_series....");
fflush(stdout);
flint_randinit(state);
for (iter = 0; iter < 1000 * arb_test_multiplier(); iter++)
{
arb_poly_t a, b, c, d;
slong len, prec;
arb_poly_init(a);
arb_poly_init(b);
arb_poly_init(c);
arb_poly_init(d);
arb_poly_randtest(a, state, 1 + n_randint(state, 10), 100, 10);
arb_poly_randtest(b, state, 1 + n_randint(state, 10), 100, 10);
arb_poly_randtest(c, state, 1 + n_randint(state, 10), 100, 10);
arb_poly_randtest(d, state, 1 + n_randint(state, 10), 100, 10);
prec = 2 + n_randint(state, 100);
len = n_randint(state, 10);
arb_poly_add_series(c, a, b, len, prec);
arb_poly_add(d, a, b, prec);
arb_poly_truncate(d, len);
if (!arb_poly_equal(c, d))
{
flint_printf("FAIL\n\n");
flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n");
flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n");
flint_printf("c = "); arb_poly_printd(c, 15); flint_printf("\n\n");
flint_printf("c = "); arb_poly_printd(c, 15); flint_printf("\n\n");
abort();
}
arb_poly_set(d, a);
arb_poly_add_series(d, d, b, len, prec);
if (!arb_poly_equal(d, c))
{
flint_printf("FAIL (aliasing 1)\n\n");
abort();
}
arb_poly_set(d, b);
arb_poly_add_series(d, a, d, len, prec);
if (!arb_poly_equal(d, c))
{
flint_printf("FAIL (aliasing 2)\n\n");
abort();
}
arb_poly_clear(a);
arb_poly_clear(b);
arb_poly_clear(c);
arb_poly_clear(d);
}
flint_randclear(state);
flint_cleanup();
flint_printf("PASS\n");
return EXIT_SUCCESS;
}

View file

@ -0,0 +1,79 @@
/*
Copyright (C) 2016 Fredrik Johansson
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "arb_poly.h"
int
main(void)
{
int iter;
flint_rand_t state;
flint_printf("set_trunc_round....");
fflush(stdout);
flint_randinit(state);
for (iter = 0; iter < 1000 * arb_test_multiplier(); iter++)
{
arb_poly_t a, b, c, d, e;
slong n, prec;
arb_poly_init(a);
arb_poly_init(b);
arb_poly_init(c);
arb_poly_init(d);
arb_poly_init(e);
arb_poly_randtest(a, state, n_randint(state, 10), 2 + n_randint(state, 200), 10);
arb_poly_randtest(b, state, n_randint(state, 10), 2 + n_randint(state, 200), 10);
arb_poly_randtest(c, state, n_randint(state, 10), 2 + n_randint(state, 200), 10);
arb_poly_randtest(d, state, n_randint(state, 10), 2 + n_randint(state, 200), 10);
arb_poly_randtest(e, state, n_randint(state, 10), 2 + n_randint(state, 200), 10);
n = n_randint(state, 10);
prec = 2 + n_randint(state, 200);
arb_poly_set_trunc(b, a, n);
arb_poly_set_round(b, b, prec);
arb_poly_set_round(c, a, prec);
arb_poly_set_trunc(c, c, n);
arb_poly_set_trunc_round(d, a, n, prec);
arb_poly_set(e, a);
arb_poly_set_trunc_round(e, e, n, prec);
if (!arb_poly_equal(b, c) || !arb_poly_equal(c, d) || !arb_poly_equal(d, e))
{
flint_printf("FAIL\n\n");
arb_poly_printd(a, 50), flint_printf("\n\n");
arb_poly_printd(b, 50), flint_printf("\n\n");
arb_poly_printd(c, 50), flint_printf("\n\n");
arb_poly_printd(d, 50), flint_printf("\n\n");
arb_poly_printd(e, 50), flint_printf("\n\n");
abort();
}
arb_poly_clear(a);
arb_poly_clear(b);
arb_poly_clear(c);
arb_poly_clear(d);
arb_poly_clear(e);
}
flint_randclear(state);
flint_cleanup();
flint_printf("PASS\n");
return 0;
}

View file

@ -0,0 +1,83 @@
/*
Copyright (C) 2012 Fredrik Johansson
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "arb_poly.h"
int main()
{
slong iter;
flint_rand_t state;
flint_printf("sub_series....");
fflush(stdout);
flint_randinit(state);
for (iter = 0; iter < 1000 * arb_test_multiplier(); iter++)
{
arb_poly_t a, b, c, d;
slong len, prec;
arb_poly_init(a);
arb_poly_init(b);
arb_poly_init(c);
arb_poly_init(d);
arb_poly_randtest(a, state, 1 + n_randint(state, 10), 100, 10);
arb_poly_randtest(b, state, 1 + n_randint(state, 10), 100, 10);
arb_poly_randtest(c, state, 1 + n_randint(state, 10), 100, 10);
arb_poly_randtest(d, state, 1 + n_randint(state, 10), 100, 10);
prec = 2 + n_randint(state, 100);
len = n_randint(state, 10);
arb_poly_sub_series(c, a, b, len, prec);
arb_poly_sub(d, a, b, prec);
arb_poly_truncate(d, len);
if (!arb_poly_equal(c, d))
{
flint_printf("FAIL\n\n");
flint_printf("a = "); arb_poly_printd(a, 15); flint_printf("\n\n");
flint_printf("b = "); arb_poly_printd(b, 15); flint_printf("\n\n");
flint_printf("c = "); arb_poly_printd(c, 15); flint_printf("\n\n");
flint_printf("c = "); arb_poly_printd(c, 15); flint_printf("\n\n");
abort();
}
arb_poly_set(d, a);
arb_poly_sub_series(d, d, b, len, prec);
if (!arb_poly_equal(d, c))
{
flint_printf("FAIL (aliasing 1)\n\n");
abort();
}
arb_poly_set(d, b);
arb_poly_sub_series(d, a, d, len, prec);
if (!arb_poly_equal(d, c))
{
flint_printf("FAIL (aliasing 2)\n\n");
abort();
}
arb_poly_clear(a);
arb_poly_clear(b);
arb_poly_clear(c);
arb_poly_clear(d);
}
flint_randclear(state);
flint_cleanup();
flint_printf("PASS\n");
return EXIT_SUCCESS;
}

25
arb_poly/valuation.c Normal file
View file

@ -0,0 +1,25 @@
/*
Copyright (C) 2016 Fredrik Johansson
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "arb_poly.h"
slong
arb_poly_valuation(const arb_poly_t poly)
{
slong i, len = poly->length;
for (i = 0; i < len; i++)
if (!arb_is_zero(poly->coeffs + i))
return i;
return -1;
}

13
arf.h
View file

@ -228,12 +228,7 @@ arf_init(arf_t x)
ARF_XSIZE(x) = 0; ARF_XSIZE(x) = 0;
} }
ARF_INLINE void void arf_clear(arf_t x);
arf_clear(arf_t x)
{
fmpz_clear(ARF_EXPREF(x));
ARF_DEMOTE(x);
}
ARF_INLINE void ARF_INLINE void
arf_zero(arf_t x) arf_zero(arf_t x)
@ -348,6 +343,12 @@ int arf_cmp(const arf_t x, const arf_t y);
int arf_cmpabs(const arf_t x, const arf_t y); int arf_cmpabs(const arf_t x, const arf_t y);
int arf_cmp_si(const arf_t x, slong y);
int arf_cmp_ui(const arf_t x, ulong y);
int arf_cmp_d(const arf_t x, double y);
ARF_INLINE void ARF_INLINE void
arf_swap(arf_t y, arf_t x) arf_swap(arf_t y, arf_t x)
{ {

23
arf/clear.c Normal file
View file

@ -0,0 +1,23 @@
/*
Copyright (C) 2016 Fredrik Johansson
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "arf.h"
void
arf_clear(arf_t x)
{
ARF_DEMOTE(x);
/* fmpz_clear(), but avoids a redundant store */
if (COEFF_IS_MPZ(ARF_EXP(x)))
_fmpz_clear_mpz(ARF_EXP(x));
}

View file

@ -59,3 +59,25 @@ arf_cmp(const arf_t x, const arf_t y)
return 0; return 0;
} }
int arf_cmp_si(const arf_t x, slong y)
{
arf_t t;
arf_init_set_si(t, y); /* no need to free */
return arf_cmp(x, t);
}
int arf_cmp_ui(const arf_t x, ulong y)
{
arf_t t;
arf_init_set_ui(t, y); /* no need to free */
return arf_cmp(x, t);
}
int arf_cmp_d(const arf_t x, double y)
{
arf_t t;
arf_init(t); /* no need to free */
arf_set_d(t, y);
return arf_cmp(x, t);
}

161
dirichlet.h Normal file
View file

@ -0,0 +1,161 @@
/*
Copyright (C) 2016 Pascal Molin
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#ifndef DIRICHLET_H
#define DIRICHLET_H
#ifdef DIRICHLET_INLINES_C
#define DIRICHLET_INLINE
#else
#define DIRICHLET_INLINE static __inline__
#endif
#include "dlog.h"
#ifdef __cplusplus
extern "C" {
#endif
#define MAX_FACTORS 15
/* should this dlog pointer be in the prime or the global group? */
typedef struct
{
ulong p; /* underlying prime */
int e; /* exponent */
nmod_t pe; /* modulus */
nmod_t phi; /* phi(p^e) */
ulong g; /* conrey generator */
dlog_precomp_struct * dlog; /* precomputed data for discrete log mod p^e */
}
dirichlet_prime_group_struct;
typedef struct
{
ulong q; /* modulus */
ulong q_even; /* even part of modulus */
nmod_t mod; /* modulus with precomputed inverse */
ulong rad_q; /* radical = product of odd primes */
ulong phi_q; /* phi(q) = group size */
slong neven; /* number of even components (in 0,1,2)*/
slong num; /* number of prime components (even + odd) */
ulong expo; /* exponent = largest order in G */
dirichlet_prime_group_struct * P;
ulong * generators; /* generators lifted mod q */
ulong * PHI; /* PHI(k) = expo / phi(k) */
}
dirichlet_group_struct;
typedef dirichlet_group_struct dirichlet_group_t[1];
DIRICHLET_INLINE ulong
dirichlet_group_size(const dirichlet_group_t G)
{
return G->phi_q;
}
void dirichlet_group_init(dirichlet_group_t G, ulong q);
void dirichlet_subgroup_init(dirichlet_group_t H, const dirichlet_group_t G, ulong h);
void dirichlet_group_clear(dirichlet_group_t G);
void dirichlet_group_dlog_precompute(dirichlet_group_t G, ulong num);
void dirichlet_group_dlog_clear(dirichlet_group_t G);
/* properties of elements without log */
ulong dirichlet_number_primitive(const dirichlet_group_t G);
ulong dirichlet_conductor_ui(const dirichlet_group_t G, ulong a);
int dirichlet_parity_ui(const dirichlet_group_t G, ulong a);
ulong dirichlet_order_ui(const dirichlet_group_t G, ulong a);
/* characters, keep both number and log */
typedef struct
{
ulong n; /* number */
ulong * log; /* s.t. prod generators[k]^log[k] = number */
}
dirichlet_char_struct;
typedef dirichlet_char_struct dirichlet_char_t[1];
void dirichlet_char_init(dirichlet_char_t x, const dirichlet_group_t G);
void dirichlet_char_clear(dirichlet_char_t x);
void dirichlet_char_print(const dirichlet_group_t G, const dirichlet_char_t x);
DIRICHLET_INLINE void
dirichlet_char_set(dirichlet_char_t x, const dirichlet_group_t G, const dirichlet_char_t y)
{
slong k;
x->n = y->n;
for (k = 0; k < G->num; k++)
x->log[k] = y->log[k];
}
DIRICHLET_INLINE int
dirichlet_char_eq(const dirichlet_char_t x, const dirichlet_char_t y)
{
return (x->n == y->n);
}
int dirichlet_char_eq_deep(const dirichlet_group_t G, const dirichlet_char_t x, const dirichlet_char_t y);
int dirichlet_parity_char(const dirichlet_group_t G, const dirichlet_char_t x);
ulong dirichlet_conductor_char(const dirichlet_group_t G, const dirichlet_char_t x);
ulong dirichlet_order_char(const dirichlet_group_t G, const dirichlet_char_t x);
void dirichlet_char_log(dirichlet_char_t x, const dirichlet_group_t G, ulong m);
ulong dirichlet_char_exp(dirichlet_char_t x, const dirichlet_group_t G);
void dirichlet_char_index(dirichlet_char_t x, const dirichlet_group_t G, ulong j);
ulong dirichlet_index_char(const dirichlet_group_t G, const dirichlet_char_t x);
void dirichlet_char_one(dirichlet_char_t x, const dirichlet_group_t G);
void dirichlet_char_first_primitive(dirichlet_char_t x, const dirichlet_group_t G);
int dirichlet_char_next(dirichlet_char_t x, const dirichlet_group_t G);
int dirichlet_char_next_primitive(dirichlet_char_t x, const dirichlet_group_t G);
void dirichlet_char_mul(dirichlet_char_t c, const dirichlet_group_t G, const dirichlet_char_t a, const dirichlet_char_t b);
void dirichlet_char_pow(dirichlet_char_t c, const dirichlet_group_t G, const dirichlet_char_t a, ulong n);
void dirichlet_char_lower(dirichlet_char_t y, const dirichlet_group_t H, const dirichlet_char_t x, const dirichlet_group_t G);
void dirichlet_char_lift(dirichlet_char_t y, const dirichlet_group_t G, const dirichlet_char_t x, const dirichlet_group_t H);
#define DIRICHLET_CHI_NULL UWORD_MAX
ulong dirichlet_pairing(const dirichlet_group_t G, ulong m, ulong n);
ulong dirichlet_pairing_char(const dirichlet_group_t G, const dirichlet_char_t a, const dirichlet_char_t b);
DIRICHLET_INLINE int
dirichlet_char_is_principal(const dirichlet_group_t G, const dirichlet_char_t chi)
{
return (chi->n == 1);
}
DIRICHLET_INLINE int
dirichlet_char_is_real(const dirichlet_group_t G, const dirichlet_char_t chi)
{
return G->q <= 4 || (nmod_mul(chi->n, chi->n, G->mod) == 1);
}
ulong dirichlet_chi(const dirichlet_group_t G, const dirichlet_char_t chi, ulong n);
void dirichlet_vec_set_null(ulong *v, const dirichlet_group_t G, slong nv);
void dirichlet_chi_vec_loop(ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv);
void dirichlet_chi_vec_primeloop(ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv);
void dirichlet_chi_vec(ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv);
void dirichlet_chi_vec_loop_order(ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi, ulong order, slong nv);
void dirichlet_chi_vec_primeloop_order(ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi, ulong order, slong nv);
void dirichlet_chi_vec_order(ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi, ulong order, slong nv);
#ifdef __cplusplus
}
#endif
#endif

33
dirichlet/chi.c Normal file
View file

@ -0,0 +1,33 @@
/*
Copyright (C) 2016 Pascal Molin
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "dirichlet.h"
ulong
dirichlet_chi(const dirichlet_group_t G, const dirichlet_char_t chi, ulong n)
{
if (n_gcd(G->q, n) > 1)
{
return DIRICHLET_CHI_NULL;
}
else
{
ulong v;
dirichlet_char_t x;
dirichlet_char_init(x, G);
dirichlet_char_log(x, G, n);
v = dirichlet_pairing_char(G, chi, x);
dirichlet_char_clear(x);
return v;
}
}

30
dirichlet/chi_vec.c Normal file
View file

@ -0,0 +1,30 @@
/*
Copyright (C) 2016 Pascal Molin
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "dirichlet.h"
void
dirichlet_chi_vec(ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv)
{
if (2 * nv > G->phi_q)
dirichlet_chi_vec_loop(v, G, chi, nv);
else
dirichlet_chi_vec_primeloop(v, G, chi, nv);
}
void
dirichlet_chi_vec_order(ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi, ulong order, slong nv)
{
if (2 * nv > G->phi_q)
dirichlet_chi_vec_loop_order(v, G, chi, order, nv);
else
dirichlet_chi_vec_primeloop_order(v, G, chi, order, nv);
}

Some files were not shown because too many files have changed in this diff Show more