arb/acb_poly/graeffe_transform.c
Matthias Gessinger 89545adbcc Slightly optimize memory usage
Save some memory by using smaller arrays for the even and odd terms.
Adjust the loop lengths, to accomodate for shorter arrays
not overwriting "outdated" data.

E.g.: If a and b are aliased, then the first poly_mul does not overwrite
the leading coefficient, which leads to incorrect results.
2021-07-28 16:07:46 +02:00

61 lines
1.5 KiB
C

/*
Copyright (C) 2021 Matthias Gessinger
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_poly.h"
void
_acb_poly_graeffe_transform(acb_ptr b, acb_srcptr a, slong len, slong prec)
{
slong lo, le, ls;
slong i;
acb_ptr pe, po;
if (len <= 1)
{
_acb_vec_set(b, a, len);
return;
}
lo = len / 2;
ls = 2 * lo - 1;
le = (len - 1) / 2 + 1;
po = _acb_vec_init(lo);
pe = _acb_vec_init(FLINT_MAX(le, ls));
for (i = len - 1; i >= 0; i--)
{
if (i % 2 == 0)
acb_set(pe + i / 2, a + i);
else
acb_set(po + i / 2, a + i);
}
_acb_poly_mul(b, pe, le, pe, le, prec);
_acb_poly_mul(pe, po, lo, po, lo, prec);
_acb_poly_sub(b + 1, b + 1, ls, pe, ls, prec);
if (len % 2 == 0)
{
_acb_vec_neg(b, b, len - 1);
acb_set(b + (len - 1), pe + (len - 2));
}
_acb_vec_clear(pe, FLINT_MAX(le, ls));
_acb_vec_clear(po, lo);
}
void
acb_poly_graeffe_transform(acb_poly_t b, const acb_poly_t a, slong prec)
{
acb_poly_fit_length(b, a->length);
_acb_poly_graeffe_transform(b->coeffs, a->coeffs, a->length, prec);
_acb_poly_set_length(b, a->length);
}