arb/acb/vec_nth_root.c

92 lines
2.2 KiB
C
Raw Normal View History

2016-09-06 15:32:23 +02:00
/*
2016-09-01 12:12:33 +02:00
Copyright (C) 2016 Pascal Molin
2016-09-06 15:32:23 +02:00
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/>.
*/
2016-09-01 12:12:33 +02:00
#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)
2016-10-06 12:39:42 +02:00
acb_nth_root(xs + j, n, prec);
2016-09-01 12:12:33 +02:00
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
2016-10-04 18:19:51 +02:00
_acb_vec_nth_roots_pe(acb_ptr z, slong p, slong e, slong len, slong step, slong prec)
2016-09-01 12:12:33 +02:00
{
if (e <= 1)
{
_acb_vec_set_powers_step(z, p, len, step, prec);
}
else
{
slong q, r;
2016-10-04 18:19:51 +02:00
_acb_vec_nth_roots_pe(z, p, e - 1, len / p, step * p, prec);
2016-09-01 12:12:33 +02:00
_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
2016-10-06 12:39:42 +02:00
_acb_vec_nth_roots(acb_ptr z, slong len, slong prec)
2016-09-01 12:12:33 +02:00
{
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;
2016-10-04 18:19:51 +02:00
_acb_vec_nth_roots_pe(z, p, e, pe, mp, prec);
2016-09-01 12:12:33 +02:00
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;
}
}