mirror of
https://github.com/vale981/arb
synced 2025-03-04 17:01:40 -05:00
159 lines
4.1 KiB
C
159 lines
4.1 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_precomp_init(acb_dft_pre_t pre, slong dv, acb_ptr z, slong dz, slong len, slong prec)
|
|
{
|
|
pre->n = len;
|
|
if (len <= 1)
|
|
{
|
|
pre->type = DFT_NAIVE;
|
|
_acb_dft_naive_init(pre->t.naive, dv, z, dz, len, prec);
|
|
}
|
|
else if (n_is_prime(len))
|
|
{
|
|
if (len < 100)
|
|
{
|
|
pre->type = DFT_NAIVE;
|
|
_acb_dft_naive_init(pre->t.naive, dv, z, dz, len, prec);
|
|
}
|
|
else
|
|
{
|
|
pre->type = DFT_CONV;
|
|
/* FIXME: do not recompute the same bluestein
|
|
* scheme if needed several times */
|
|
_acb_dft_bluestein_init(pre->t.bluestein, dv, len, prec);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
n_factor_t fac;
|
|
|
|
n_factor_init(&fac);
|
|
n_factor(&fac, len, 1);
|
|
|
|
if (fac.num == 1)
|
|
{
|
|
/* TODO: could be p^e, or 2^e, but with dv shift */
|
|
if (fac.p[0] == 2)
|
|
{
|
|
pre->type = DFT_RAD2;
|
|
_acb_dft_rad2_init(pre->t.rad2, dv, fac.exp[0], prec);
|
|
}
|
|
else
|
|
{
|
|
pre->type = DFT_CYC;
|
|
_acb_dft_cyc_init_z_fac(pre->t.cyc, fac, dv, z, dz, len, prec);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pre->type = DFT_CRT;
|
|
_acb_dft_crt_init(pre->t.crt, dv, len, prec);
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
acb_dft_precomp_init(acb_dft_pre_t pre, slong len, slong prec)
|
|
{
|
|
_acb_dft_precomp_init(pre, 1, NULL, 0, len, prec);
|
|
}
|
|
|
|
void
|
|
acb_dft_precomp_clear(acb_dft_pre_t pre)
|
|
{
|
|
switch (pre->type)
|
|
{
|
|
case DFT_NAIVE:
|
|
acb_dft_naive_clear(pre->t.naive);
|
|
break;
|
|
case DFT_CYC:
|
|
acb_dft_cyc_clear(pre->t.cyc);
|
|
break;
|
|
case DFT_PROD:
|
|
acb_dft_prod_clear(pre->t.prod);
|
|
break;
|
|
case DFT_CRT:
|
|
acb_dft_crt_clear(pre->t.crt);
|
|
break;
|
|
case DFT_RAD2:
|
|
acb_dft_rad2_clear(pre->t.rad2);
|
|
break;
|
|
case DFT_CONV:
|
|
acb_dft_bluestein_clear(pre->t.bluestein);
|
|
break;
|
|
default:
|
|
flint_printf("acb_dft_clear: unknown strategy code %i\n", pre->type);
|
|
abort();
|
|
break;
|
|
}
|
|
}
|
|
|
|
void
|
|
acb_dft_precomp(acb_ptr w, acb_srcptr v, const acb_dft_pre_t pre, slong prec)
|
|
{
|
|
switch (pre->type)
|
|
{
|
|
case DFT_NAIVE:
|
|
acb_dft_naive_precomp(w, v, pre->t.naive, prec);
|
|
break;
|
|
case DFT_CYC:
|
|
acb_dft_cyc_precomp(w, v, pre->t.cyc, prec);
|
|
break;
|
|
case DFT_PROD:
|
|
acb_dft_prod_precomp(w, v, pre->t.prod, prec);
|
|
break;
|
|
case DFT_CRT:
|
|
acb_dft_crt_precomp(w, v, pre->t.crt, prec);
|
|
break;
|
|
case DFT_RAD2:
|
|
acb_dft_rad2_precomp(w, v, pre->t.rad2, prec);
|
|
break;
|
|
case DFT_CONV:
|
|
acb_dft_bluestein_precomp(w, v, pre->t.bluestein, prec);
|
|
break;
|
|
default:
|
|
flint_printf("acb_dft_precomp: unknown strategy code %i\n", pre->type);
|
|
abort();
|
|
break;
|
|
}
|
|
}
|
|
|
|
void
|
|
acb_dft(acb_ptr w, acb_srcptr v, slong len, slong prec)
|
|
{
|
|
acb_dft_pre_t t;
|
|
acb_dft_precomp_init(t, len, prec);
|
|
acb_dft_precomp(w, v, t, prec);
|
|
acb_dft_precomp_clear(t);
|
|
}
|
|
|
|
void
|
|
acb_dft_inverse_precomp(acb_ptr w, acb_srcptr v, const acb_dft_pre_t pre, slong prec)
|
|
{
|
|
slong k;
|
|
acb_dft_precomp(w, v, pre, prec);
|
|
for (k = 1; 2 * k < pre->n; k++)
|
|
acb_swap(w + k, w + pre->n - k);
|
|
_acb_vec_scalar_div_ui(w, w, pre->n, pre->n, prec);
|
|
}
|
|
void
|
|
acb_dft_inverse(acb_ptr w, acb_srcptr v, slong len, slong prec)
|
|
{
|
|
slong k;
|
|
acb_dft(w, v, len, prec);
|
|
for (k = 1; 2 * k < len; k++)
|
|
acb_swap(w + k, w + len - k);
|
|
_acb_vec_scalar_div_ui(w, w, len, len, prec);
|
|
}
|