/*
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 .
*/
#include
#include "acb_dirichlet.h"
#include "flint/profiler.h"
#define LOG 0
#define CSV 1
#define JSON 2
typedef void (*do_f) (ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv);
static void
do_empty(ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv)
{
return;
}
static void
do_dlog_primeloop(ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv)
{
slong k, l;
nmod_t order;
nmod_init(&order, dirichlet_order_char(G, chi));
for (k = 0; k < nv; k++)
v[k] = 0;
for (l = G->neven; l < G->num; l++)
{
dirichlet_prime_group_struct P = G->P[l];
dlog_vec_loop_add(v, nv, P.g, chi->log[l], P.pe, P.phi.n, order);
}
dirichlet_vec_set_null(v, G, nv);
}
static void
do_eratos(ulong *v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv)
{
slong k, p, pmax;
nmod_t order;
n_primes_t iter;
n_primes_init(iter);
nmod_init(&order, dirichlet_order_char(G, chi));
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] = DIRICHLET_CHI_NULL;
}
else
{
long chip;
chip = dirichlet_chi(G, chi, p);
for (k = p; k < nv; k += p)
if (v[k] != -1)
v[k] = nmod_add(v[k], chip, 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,
dirichlet_chi_vec_loop,
do_dlog_primeloop,
dirichlet_chi_vec_primeloop,
do_eratos,
dirichlet_chi_vec,
dirichlet_chi_vec,
dirichlet_chi_vec,
dirichlet_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]);
flint_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++)
{
dirichlet_group_t G;
dirichlet_char_t chi;
dirichlet_group_init(G, q);
dirichlet_char_init(chi, G);
if (l >= 6)
dirichlet_group_dlog_precompute(G, (l == 6) ? 1 : (l==7) ? 20 : 100);
for (r = 0; r < nr; r++)
{
dirichlet_char_log(chi, G, rand[r] % q);
func[l](v, G, chi, nv[j]);
}
if (l >= 6)
dirichlet_group_dlog_clear(G);
dirichlet_char_clear(chi);
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;
}