Skip to content

Commit 3b3bfdf

Browse files
Middle product for arb_poly, acb_poly
1 parent f83f0df commit 3b3bfdf

24 files changed

+1242
-111
lines changed

doc/source/acb_poly.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,16 @@ Arithmetic
347347
If the same variable is passed for *A* and *B*, sets *C* to
348348
the square of *A*.
349349

350+
.. function:: void _acb_poly_mulmid_transpose(acb_ptr z, acb_srcptr x, slong xlen, acb_srcptr y, slong ylen, slong nlo, slong nhi, slong prec)
351+
void acb_poly_mulmid_transpose(acb_poly_t res, const acb_poly_t poly1, const acb_poly_t poly2, slong nlo, slong nhi, slong prec)
352+
void _acb_poly_mulmid_classical(acb_ptr z, acb_srcptr x, slong xlen, acb_srcptr y, slong ylen, slong nlo, slong nhi, slong prec)
353+
void acb_poly_mulmid_classical(acb_poly_t res, const acb_poly_t poly1, const acb_poly_t poly2, slong nlo, slong nhi, slong prec)
354+
void _acb_poly_mulmid(acb_ptr z, acb_srcptr x, slong xlen, acb_srcptr y, slong ylen, slong nlo, slong nhi, slong prec)
355+
void acb_poly_mulmid(acb_poly_t res, const acb_poly_t poly1, const acb_poly_t poly2, slong nlo, slong nhi, slong prec)
356+
357+
Analogous to *mullow* functions, but compute the product truncated
358+
at length *nhi* and right-shifted by *nlo*.
359+
350360
.. function:: void _acb_poly_inv_series(acb_ptr Qinv, acb_srcptr Q, slong Qlen, slong len, slong prec)
351361

352362
Sets *{Qinv, len}* to the power series inverse of *{Q, Qlen}*. Uses Newton iteration.

doc/source/arb_poly.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,16 @@ Arithmetic
343343
If the same variable is passed for *A* and *B*, sets *C* to the
344344
square of *A*.
345345

346+
.. function:: void _arb_poly_mulmid_block(arb_ptr z, arb_srcptr x, slong xlen, arb_srcptr y, slong ylen, slong nlo, slong nhi, slong prec)
347+
void arb_poly_mulmid_block(arb_poly_t res, const arb_poly_t poly1, const arb_poly_t poly2, slong nlo, slong nhi, slong prec)
348+
void _arb_poly_mulmid_classical(arb_ptr z, arb_srcptr x, slong xlen, arb_srcptr y, slong ylen, slong nlo, slong nhi, slong prec)
349+
void arb_poly_mulmid_classical(arb_poly_t res, const arb_poly_t poly1, const arb_poly_t poly2, slong nlo, slong nhi, slong prec)
350+
void _arb_poly_mulmid(arb_ptr z, arb_srcptr x, slong xlen, arb_srcptr y, slong ylen, slong nlo, slong nhi, slong prec)
351+
void arb_poly_mulmid(arb_poly_t res, const arb_poly_t poly1, const arb_poly_t poly2, slong nlo, slong nhi, slong prec)
352+
353+
Analogous to *mullow* functions, but compute the product truncated
354+
at length *nhi* and right-shifted by *nlo*.
355+
346356
.. function:: void _arb_poly_inv_series(arb_ptr Q, arb_srcptr A, slong Alen, slong len, slong prec)
347357

348358
Sets *{Q, len}* to the power series inverse of *{A, Alen}*. Uses Newton iteration.

src/acb_poly.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,13 @@ void _acb_poly_mul(acb_ptr C,
333333
void acb_poly_mul(acb_poly_t res, const acb_poly_t poly1,
334334
const acb_poly_t poly2, slong prec);
335335

336+
void _acb_poly_mulmid_transpose(acb_ptr z, acb_srcptr x, slong xlen, acb_srcptr y, slong ylen, slong nlo, slong nhi, slong prec);
337+
void acb_poly_mulmid_transpose(acb_poly_t res, const acb_poly_t poly1, const acb_poly_t poly2, slong nlo, slong nhi, slong prec);
338+
void _acb_poly_mulmid_classical(acb_ptr z, acb_srcptr x, slong xlen, acb_srcptr y, slong ylen, slong nlo, slong nhi, slong prec);
339+
void acb_poly_mulmid_classical(acb_poly_t res, const acb_poly_t poly1, const acb_poly_t poly2, slong nlo, slong nhi, slong prec);
340+
void _acb_poly_mulmid(acb_ptr z, acb_srcptr x, slong xlen, acb_srcptr y, slong ylen, slong nlo, slong nhi, slong prec);
341+
void acb_poly_mulmid(acb_poly_t res, const acb_poly_t poly1, const acb_poly_t poly2, slong nlo, slong nhi, slong prec);
342+
336343
ACB_POLY_INLINE void
337344
_acb_poly_mul_monic(acb_ptr res, acb_srcptr poly1, slong len1,
338345
acb_srcptr poly2, slong len2, slong prec)

src/acb_poly/exp_series.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,16 +49,16 @@ _acb_poly_exp_series_newton(acb_ptr f, acb_ptr g,
4949
slong l = m - 1; /* shifted for derivative */
5050

5151
/* g := exp(-h) + O(x^m) */
52-
_acb_poly_mullow(T, f, m, g, m2, m, prec);
53-
_acb_poly_mullow(g + m2, g, m2, T + m2, m - m2, m - m2, prec);
52+
_acb_poly_mulmid(T, f, m, g, m2, m2, m, prec);
53+
_acb_poly_mullow(g + m2, g, m2, T, m - m2, m - m2, prec);
5454
_acb_vec_neg(g + m2, g + m2, m - m2);
5555

5656
/* U := h' + g (f' - f h') + O(x^(n-1))
5757
Note: should replace h' by h' mod x^(m-1) */
5858
_acb_vec_zero(f + m, n - m);
59-
_acb_poly_mullow(T, f, n, hprime, n, n, prec); /* should be mulmid */
59+
_acb_poly_mulmid(T, f, n, hprime, n, l, n, prec);
6060
_acb_poly_derivative(U, f, n, prec); acb_zero(U + n - 1); /* should skip low terms */
61-
_acb_vec_sub(U + l, U + l, T + l, n - l, prec);
61+
_acb_vec_sub(U + l, U + l, T, n - l, prec);
6262
_acb_poly_mullow(T + l, g, n - m, U + l, n - m, n - m, prec);
6363
_acb_vec_add(U + l, hprime + l, T + l, n - m, prec);
6464

@@ -71,8 +71,8 @@ _acb_poly_exp_series_newton(acb_ptr f, acb_ptr g,
7171
/* not needed if we only want exp(x) */
7272
if (n == len && inverse)
7373
{
74-
_acb_poly_mullow(T, f, n, g, m, n, prec);
75-
_acb_poly_mullow(g + m, g, m, T + m, n - m, n - m, prec);
74+
_acb_poly_mulmid(T, f, n, g, m, m, n, prec);
75+
_acb_poly_mullow(g + m, g, m, T, n - m, n - m, prec);
7676
_acb_vec_neg(g + m, g + m, n - m);
7777
}
7878

src/acb_poly/inv_series.c

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,6 @@
1212
#include "arb_poly.h"
1313
#include "acb_poly.h"
1414

15-
#define MULLOW(z, x, xn, y, yn, nn, prec) \
16-
if ((xn) >= (yn)) \
17-
_acb_poly_mullow(z, x, xn, y, yn, nn, prec); \
18-
else \
19-
_acb_poly_mullow(z, y, yn, x, xn, nn, prec); \
20-
2115
void
2216
_acb_poly_inv_series(acb_ptr Qinv,
2317
acb_srcptr Q, slong Qlen, slong len, slong prec)
@@ -60,22 +54,22 @@ _acb_poly_inv_series(acb_ptr Qinv,
6054
slong Qnlen, Wlen, W2len;
6155
acb_ptr W;
6256

63-
W = _acb_vec_init(len);
57+
W = _acb_vec_init(len / 2);
6458

6559
NEWTON_INIT(blen, len)
6660
NEWTON_LOOP(m, n)
6761

6862
Qnlen = FLINT_MIN(Qlen, n);
6963
Wlen = FLINT_MIN(Qnlen + m - 1, n);
7064
W2len = Wlen - m;
71-
MULLOW(W, Q, Qnlen, Qinv, m, Wlen, prec);
72-
MULLOW(Qinv + m, Qinv, m, W + m, W2len, n - m, prec);
65+
_acb_poly_mulmid(W, Q, Qnlen, Qinv, m, m, Wlen, prec);
66+
_acb_poly_mullow(Qinv + m, Qinv, m, W, W2len, n - m, prec);
7367
_acb_vec_neg(Qinv + m, Qinv + m, n - m);
7468

7569
NEWTON_END_LOOP
7670
NEWTON_END
7771

78-
_acb_vec_clear(W, len);
72+
_acb_vec_clear(W, len / 2);
7973
}
8074
}
8175
}

src/acb_poly/mullow_transpose.c

Lines changed: 83 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,27 +13,47 @@
1313
#include "acb_poly.h"
1414

1515
void
16-
_acb_poly_mullow_transpose(acb_ptr res,
16+
_acb_poly_mulmid_transpose(acb_ptr res,
1717
acb_srcptr poly1, slong len1,
18-
acb_srcptr poly2, slong len2, slong n, slong prec)
18+
acb_srcptr poly2, slong len2, slong nlo, slong nhi, slong prec)
1919
{
2020
arb_ptr a, b, c, d, e, f, w;
2121
arb_ptr t;
2222
slong i;
2323

24-
len1 = FLINT_MIN(len1, n);
25-
len2 = FLINT_MIN(len2, n);
24+
len1 = FLINT_MIN(len1, nhi);
25+
len2 = FLINT_MIN(len2, nhi);
26+
27+
slong nlo2 = (len1 + len2 - 1) - nlo;
2628

27-
w = flint_malloc(sizeof(arb_struct) * (2 * (len1 + len2 + n)));
29+
if (len1 > nlo2)
30+
{
31+
slong trunc = len1 - nlo2;
32+
poly1 += trunc;
33+
len1 -= trunc;
34+
nlo -= trunc;
35+
nhi -= trunc;
36+
}
37+
38+
if (len2 > nlo2)
39+
{
40+
slong trunc = len2 - nlo2;
41+
poly2 += trunc;
42+
len2 -= trunc;
43+
nlo -= trunc;
44+
nhi -= trunc;
45+
}
46+
47+
w = flint_malloc(sizeof(arb_struct) * (2 * (len1 + len2 + (nhi - nlo))));
2848
a = w;
2949
b = a + len1;
3050
c = b + len1;
3151
d = c + len2;
3252
e = d + len2;
33-
f = e + n;
53+
f = e + (nhi - nlo);
3454

3555
/* (e+fi) = (a+bi)(c+di) = (ac - bd) + (ad + bc)i */
36-
t = _arb_vec_init(n);
56+
t = _arb_vec_init(nhi - nlo);
3757

3858
for (i = 0; i < len1; i++)
3959
{
@@ -47,38 +67,84 @@ _acb_poly_mullow_transpose(acb_ptr res,
4767
d[i] = *acb_imagref(poly2 + i);
4868
}
4969

50-
for (i = 0; i < n; i++)
70+
for (i = 0; i < nhi - nlo; i++)
5171
{
5272
e[i] = *acb_realref(res + i);
5373
f[i] = *acb_imagref(res + i);
5474
}
5575

56-
_arb_poly_mullow(e, a, len1, c, len2, n, prec);
57-
_arb_poly_mullow(t, b, len1, d, len2, n, prec);
58-
_arb_vec_sub(e, e, t, n, prec);
76+
_arb_poly_mulmid(e, a, len1, c, len2, nlo, nhi, prec);
77+
_arb_poly_mulmid(t, b, len1, d, len2, nlo, nhi, prec);
78+
_arb_vec_sub(e, e, t, nhi - nlo, prec);
5979

60-
_arb_poly_mullow(f, a, len1, d, len2, n, prec);
80+
_arb_poly_mulmid(f, a, len1, d, len2, nlo, nhi, prec);
6181
/* squaring */
6282
if (poly1 == poly2 && len1 == len2)
6383
{
64-
_arb_vec_scalar_mul_2exp_si(f, f, n, 1);
84+
_arb_vec_scalar_mul_2exp_si(f, f, nhi - nlo, 1);
6585
}
6686
else
6787
{
68-
_arb_poly_mullow(t, b, len1, c, len2, n, prec);
69-
_arb_vec_add(f, f, t, n, prec);
88+
_arb_poly_mulmid(t, b, len1, c, len2, nlo, nhi, prec);
89+
_arb_vec_add(f, f, t, nhi - nlo, prec);
7090
}
7191

72-
for (i = 0; i < n; i++)
92+
for (i = 0; i < nhi - nlo; i++)
7393
{
7494
*acb_realref(res + i) = e[i];
7595
*acb_imagref(res + i) = f[i];
7696
}
7797

78-
_arb_vec_clear(t, n);
98+
_arb_vec_clear(t, nhi - nlo);
7999
flint_free(w);
80100
}
81101

102+
void
103+
_acb_poly_mullow_transpose(acb_ptr res,
104+
acb_srcptr poly1, slong len1,
105+
acb_srcptr poly2, slong len2, slong n, slong prec)
106+
{
107+
_acb_poly_mulmid_transpose(res, poly1, len1, poly2, len2, 0, n, prec);
108+
}
109+
110+
void
111+
acb_poly_mulmid_transpose(acb_poly_t res, const acb_poly_t poly1,
112+
const acb_poly_t poly2, slong nlo, slong nhi, slong prec)
113+
{
114+
slong xlen, ylen, zlen;
115+
116+
xlen = poly1->length;
117+
ylen = poly2->length;
118+
119+
if (xlen == 0 || ylen == 0 || nlo >= FLINT_MIN(nhi, xlen + ylen - 1))
120+
{
121+
acb_poly_zero(res);
122+
return;
123+
}
124+
125+
nhi = FLINT_MIN(nhi, xlen + ylen - 1);
126+
zlen = nhi - nlo;
127+
128+
if (res == poly1 || res == poly2)
129+
{
130+
acb_poly_t tmp;
131+
acb_poly_init2(tmp, zlen);
132+
_acb_poly_mulmid_transpose(tmp->coeffs, poly1->coeffs, xlen,
133+
poly2->coeffs, ylen, nlo, nhi, prec);
134+
acb_poly_swap(res, tmp);
135+
acb_poly_clear(tmp);
136+
}
137+
else
138+
{
139+
acb_poly_fit_length(res, zlen);
140+
_acb_poly_mulmid_transpose(res->coeffs, poly1->coeffs, xlen,
141+
poly2->coeffs, ylen, nlo, nhi, prec);
142+
}
143+
144+
_acb_poly_set_length(res, zlen);
145+
_acb_poly_normalise(res);
146+
}
147+
82148
void
83149
acb_poly_mullow_transpose(acb_poly_t res, const acb_poly_t poly1,
84150
const acb_poly_t poly2,

src/acb_poly/mulmid.c

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/*
2+
Copyright (C) 2012 Fredrik Johansson
3+
4+
This file is part of FLINT.
5+
6+
FLINT is free software: you can redistribute it and/or modify it under
7+
the terms of the GNU Lesser General Public License (LGPL) as published
8+
by the Free Software Foundation; either version 3 of the License, or
9+
(at your option) any later version. See <https://www.gnu.org/licenses/>.
10+
*/
11+
12+
#include <math.h>
13+
#include "acb_poly.h"
14+
15+
void
16+
_acb_poly_mulmid(acb_ptr res,
17+
acb_srcptr poly1, slong len1,
18+
acb_srcptr poly2, slong len2, slong nlo, slong nhi, slong prec)
19+
{
20+
if (len1 <= 7 || len2 <= 7 || nhi <= 7)
21+
{
22+
_acb_poly_mulmid_classical(res, poly1, len1, poly2, len2, nlo, nhi, prec);
23+
}
24+
else
25+
{
26+
slong cutoff;
27+
double p;
28+
29+
if (prec <= 2 * FLINT_BITS)
30+
{
31+
cutoff = 110;
32+
}
33+
else
34+
{
35+
p = log(prec);
36+
37+
cutoff = 10000.0 / (p * p * p);
38+
cutoff = FLINT_MIN(cutoff, 60);
39+
if (poly1 == poly2 && prec >= 256)
40+
cutoff *= 1.25;
41+
if (poly1 == poly2 && prec >= 4096)
42+
cutoff *= 1.25;
43+
cutoff = FLINT_MAX(cutoff, 8);
44+
}
45+
46+
/* todo: tuning copied from mullow; needs retuning for small nhi - nlo */
47+
if (2 * FLINT_MIN(len1, len2) <= cutoff || nhi <= cutoff)
48+
_acb_poly_mulmid_classical(res, poly1, len1, poly2, len2, nlo, nhi, prec);
49+
else
50+
_acb_poly_mulmid_transpose(res, poly1, len1, poly2, len2, nlo, nhi, prec);
51+
}
52+
}
53+
54+
void
55+
acb_poly_mulmid(acb_poly_t res, const acb_poly_t poly1,
56+
const acb_poly_t poly2, slong nlo, slong nhi, slong prec)
57+
{
58+
slong xlen, ylen, zlen;
59+
60+
xlen = poly1->length;
61+
ylen = poly2->length;
62+
63+
if (xlen == 0 || ylen == 0 || nlo >= FLINT_MIN(nhi, xlen + ylen - 1))
64+
{
65+
acb_poly_zero(res);
66+
return;
67+
}
68+
69+
nhi = FLINT_MIN(nhi, xlen + ylen - 1);
70+
zlen = nhi - nlo;
71+
72+
if (res == poly1 || res == poly2)
73+
{
74+
acb_poly_t tmp;
75+
acb_poly_init2(tmp, zlen);
76+
_acb_poly_mulmid(tmp->coeffs, poly1->coeffs, xlen,
77+
poly2->coeffs, ylen, nlo, nhi, prec);
78+
acb_poly_swap(res, tmp);
79+
acb_poly_clear(tmp);
80+
}
81+
else
82+
{
83+
acb_poly_fit_length(res, zlen);
84+
_acb_poly_mulmid(res->coeffs, poly1->coeffs, xlen,
85+
poly2->coeffs, ylen, nlo, nhi, prec);
86+
}
87+
88+
_acb_poly_set_length(res, zlen);
89+
_acb_poly_normalise(res);
90+
}

0 commit comments

Comments
 (0)