#include "mpn_extras.h"
#include "thread_support.h"
#include "gmpcompat.h"
#include "fmpz.h"
#include "fmpz_vec.h"
static void _fmpz_vec_set_fft_coeff(fmpz * coeffs_m, slong i,
const nn_ptr * coeffs_f, slong limbs, slong sign)
{
slong size;
ulong * data;
mpz_ptr mcoeffs_m;
coeffs_m += i;
if (sign)
{
ulong halflimb = UWORD(1) << (FLINT_BITS - 1);
{
mcoeffs_m = _fmpz_promote(coeffs_m);
data = FLINT_MPZ_REALLOC(mcoeffs_m, limbs);
if ((coeffs_f[i][limbs - 1] > halflimb) || coeffs_f[i][limbs])
{
mpn_neg(data, coeffs_f[i], limbs);
mpn_add_1(data, data, limbs, WORD(1));
size = limbs;
while ((size) && (data[size - 1] == 0)) size--;
mcoeffs_m->_mp_size = -size;
if (size >= WORD(-1)) _fmpz_demote_val(coeffs_m);
}
else
{
flint_mpn_copyi(data, coeffs_f[i], limbs);
size = limbs;
while ((size) && (data[size - 1] == WORD(0))) size--;
mcoeffs_m->_mp_size = size;
if (size <= 1) _fmpz_demote_val(coeffs_m);
}
}
}
else
{
{
mcoeffs_m = _fmpz_promote(coeffs_m);
data = FLINT_MPZ_REALLOC(mcoeffs_m, limbs);
flint_mpn_copyi(data, coeffs_f[i], limbs);
size = limbs;
while ((size) && (data[size - 1] == WORD(0))) size--;
mcoeffs_m->_mp_size = size;
if (size <= 1) _fmpz_demote_val(coeffs_m);
}
}
}
typedef struct
{
fmpz * coeffs_m;
const nn_ptr * coeffs_f;
slong limbs;
int sign;
}
work_t;
static void
worker(slong i, work_t * work)
{
_fmpz_vec_set_fft_coeff(work->coeffs_m, i, work->coeffs_f, work->limbs, work->sign);
}
void _fmpz_vec_set_fft(fmpz * coeffs_m, slong length,
const nn_ptr * coeffs_f, slong limbs, slong sign)
{
work_t work;
slong max_threads;
work.coeffs_m = coeffs_m;
work.coeffs_f = coeffs_f;
work.limbs = limbs;
work.sign = sign;
max_threads = flint_get_num_threads();
max_threads = FLINT_MIN(max_threads, 1e-5 * limbs * length + 1);
flint_parallel_do((do_func_t) worker, &work, length, max_threads, FLINT_PARALLEL_UNIFORM);
}