mirror of
https://github.com/vale981/arb
synced 2025-03-06 09:51:39 -05:00
120 lines
2.9 KiB
C
120 lines
2.9 KiB
C
/*
|
|
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_dft.h"
|
|
|
|
void
|
|
_acb_dft_cyc_init_z_fac(acb_dft_cyc_t t, n_factor_t fac, slong dv, acb_ptr z, slong dz, slong len, slong prec)
|
|
{
|
|
slong i, j, num;
|
|
t->n = len;
|
|
num = 0;
|
|
for (i = 0; i < fac.num; i++)
|
|
num += fac.exp[i];
|
|
t->num = num;
|
|
t->cyc = flint_malloc(num * sizeof(acb_dft_step_struct));
|
|
|
|
if (z == NULL)
|
|
{
|
|
if (DFT_VERB)
|
|
flint_printf("dft_cyc: init z[%wu]\n", t->n);
|
|
z = _acb_vec_init(t->n);
|
|
_acb_vec_unit_roots(z, -t->n, t->n, prec);
|
|
dz = 1;
|
|
t->zclear = 1;
|
|
}
|
|
else
|
|
{
|
|
if (DFT_VERB)
|
|
flint_printf("dft_cyc: roots of order %wu already computed\n", t->n);
|
|
t->zclear = 0;
|
|
}
|
|
|
|
t->z = z;
|
|
|
|
num = 0;
|
|
for (i = 0; i < fac.num; i++)
|
|
{
|
|
for (j = 0; j < fac.exp[i]; j++)
|
|
{
|
|
slong m, M;
|
|
m = fac.p[i];
|
|
M = (len /= m);
|
|
t->cyc[num].m = m;
|
|
t->cyc[num].M = M;
|
|
t->cyc[num].dv = dv;
|
|
t->cyc[num].z = z;
|
|
t->cyc[num].dz = dz;
|
|
/* TODO: ugly, reorder should solve this */
|
|
if (num == t->num - 1)
|
|
_acb_dft_precomp_init(t->cyc[num].pre, dv, z, dz, m, prec);
|
|
else
|
|
_acb_dft_precomp_init(t->cyc[num].pre, M, z, dz * M, m, prec);
|
|
dv *= m;
|
|
dz *= m;
|
|
num++;
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
_acb_dft_cyc_init(acb_dft_cyc_t t, slong dv, slong len, slong prec)
|
|
{
|
|
n_factor_t fac;
|
|
n_factor_init(&fac);
|
|
if (len)
|
|
n_factor(&fac, len, 1);
|
|
else
|
|
fac.num = 0;
|
|
_acb_dft_cyc_init_z_fac(t, fac, dv, NULL, 0, len, prec);
|
|
}
|
|
|
|
void
|
|
acb_dft_cyc_clear(acb_dft_cyc_t t)
|
|
{
|
|
slong i;
|
|
for (i = 0; i < t->num; i++)
|
|
acb_dft_precomp_clear(t->cyc[i].pre);
|
|
if (t->zclear)
|
|
_acb_vec_clear(t->z, t->n);
|
|
flint_free(t->cyc);
|
|
}
|
|
|
|
void
|
|
acb_dft_cyc_precomp(acb_ptr w, acb_srcptr v, const acb_dft_cyc_t cyc, slong prec)
|
|
{
|
|
if (cyc->num == 0)
|
|
{
|
|
if (cyc->n == 1)
|
|
acb_set(w, v);
|
|
}
|
|
else
|
|
acb_dft_step(w, v, cyc->cyc, cyc->num, prec);
|
|
}
|
|
|
|
void
|
|
acb_dft_cyc(acb_ptr w, acb_srcptr v, slong len, slong prec)
|
|
{
|
|
acb_dft_cyc_t cyc;
|
|
acb_dft_cyc_init(cyc, len, prec);
|
|
acb_dft_cyc_precomp(w, v, cyc, prec);
|
|
acb_dft_cyc_clear(cyc);
|
|
}
|
|
|
|
void
|
|
acb_dft_inverse_cyc(acb_ptr w, acb_srcptr v, slong len, slong prec)
|
|
{
|
|
/* divide before to keep v const */
|
|
_acb_vec_scalar_div_ui(w, v, len, len, prec);
|
|
acb_vec_swap_ri(w, len);
|
|
acb_dft_cyc(w, w, len, prec);
|
|
acb_vec_swap_ri(w, len);
|
|
}
|