1 /* Implementation of the multiplication algorithm for Toom-Cook 6.5-way.
3 Contributed to the GNU project by Marco Bodrato.
5 THE FUNCTION IN THIS FILE IS INTERNAL WITH A MUTABLE INTERFACE. IT IS ONLY
6 SAFE TO REACH IT THROUGH DOCUMENTED INTERFACES. IN FACT, IT IS ALMOST
7 GUARANTEED THAT IT WILL CHANGE OR DISAPPEAR IN A FUTURE GNU MP RELEASE.
9 Copyright 2009, 2010 Free Software Foundation, Inc.
11 This file is part of the GNU MP Library.
13 The GNU MP Library is free software; you can redistribute it and/or modify
14 it under the terms of the GNU Lesser General Public License as published by
15 the Free Software Foundation; either version 3 of the License, or (at your
16 option) any later version.
18 The GNU MP Library is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
21 License for more details.
23 You should have received a copy of the GNU Lesser General Public License
24 along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */
31 #if GMP_NUMB_BITS < 21
32 #error Not implemented.
35 #if TUNE_PROGRAM_BUILD
36 #define MAYBE_mul_basecase 1
37 #define MAYBE_mul_toom22 1
38 #define MAYBE_mul_toom33 1
39 #define MAYBE_mul_toom6h 1
41 #define MAYBE_mul_basecase \
42 (MUL_TOOM6H_THRESHOLD < 6 * MUL_TOOM22_THRESHOLD)
43 #define MAYBE_mul_toom22 \
44 (MUL_TOOM6H_THRESHOLD < 6 * MUL_TOOM33_THRESHOLD)
45 #define MAYBE_mul_toom33 \
46 (MUL_TOOM6H_THRESHOLD < 6 * MUL_TOOM44_THRESHOLD)
47 #define MAYBE_mul_toom6h \
48 (MUL_FFT_THRESHOLD >= 6 * MUL_TOOM6H_THRESHOLD)
51 #define TOOM6H_MUL_N_REC(p, a, b, n, ws) \
53 if (MAYBE_mul_basecase \
54 && BELOW_THRESHOLD (n, MUL_TOOM22_THRESHOLD)) \
55 mpn_mul_basecase (p, a, n, b, n); \
56 else if (MAYBE_mul_toom22 \
57 && BELOW_THRESHOLD (n, MUL_TOOM33_THRESHOLD)) \
58 mpn_toom22_mul (p, a, n, b, n, ws); \
59 else if (MAYBE_mul_toom33 \
60 && BELOW_THRESHOLD (n, MUL_TOOM44_THRESHOLD)) \
61 mpn_toom33_mul (p, a, n, b, n, ws); \
62 else if (! MAYBE_mul_toom6h \
63 || BELOW_THRESHOLD (n, MUL_TOOM6H_THRESHOLD)) \
64 mpn_toom44_mul (p, a, n, b, n, ws); \
66 mpn_toom6h_mul (p, a, n, b, n, ws); \
69 #define TOOM6H_MUL_REC(p, a, na, b, nb, ws) \
70 do { mpn_mul (p, a, na, b, nb); \
73 /* Toom-6.5 , compute the product {pp,an+bn} <- {ap,an} * {bp,bn}
74 With: an >= bn >= 46, an*6 < bn * 17.
75 It _may_ work with bn<=46 and bn*17 < an*6 < bn*18
77 Evaluate in: infinity, +4, -4, +2, -2, +1, -1, +1/2, -1/2, +1/4, -1/4, 0.
79 /* Estimate on needed scratch:
80 S(n) <= (n+5)\6*10+4+MAX(S((n+5)\6),1+2*(n+5)\6),
81 since n>42; S(n) <= ceil(log(n)/log(6))*(10+4)+n*12\6 < n*2 + lg2(n)*6
85 mpn_toom6h_mul (mp_ptr pp,
86 mp_srcptr ap, mp_size_t an,
87 mp_srcptr bp, mp_size_t bn, mp_ptr scratch)
93 /***************************** decomposition *******************************/
96 /* Can not handle too much unbalancement */
98 /* Can not handle too much unbalancement */
99 ASSERT((an*3 < bn * 8) || ( bn >= 46 && an*6 < bn * 17 ));
101 /* Limit num/den is a rational number between
102 (12/11)^(log(4)/log(2*4-1)) and (12/11)^(log(6)/log(2*6-1)) */
103 #define LIMIT_numerator (18)
104 #define LIMIT_denominat (17)
106 if( an * LIMIT_denominat < LIMIT_numerator * bn ) /* is 6*... < 6*... */
108 else if( an * 5 * LIMIT_numerator < LIMIT_denominat * 7 * bn )
110 else if( an * 5 * LIMIT_denominat < LIMIT_numerator * 7 * bn )
112 else if( an * LIMIT_numerator < LIMIT_denominat * 2 * bn ) /* is 4*... < 8*... */
114 else if( an * LIMIT_denominat < LIMIT_numerator * 2 * bn ) /* is 4*... < 8*... */
120 n = 1 + (q * an >= p * bn ? (an - 1) / (size_t) p : (bn - 1) / (size_t) q);
126 /* With LIMIT = 16/15, the following recover is needed only if bn<=73*/
127 if (half) { /* Recover from badly chosen splitting */
128 if (s<1) {p--; s+=n; half=0;}
129 else if (t<1) {q--; t+=n; half=0;}
131 #undef LIMIT_numerator
132 #undef LIMIT_denominat
134 ASSERT (0 < s && s <= n);
135 ASSERT (0 < t && t <= n);
136 ASSERT (half || s + t > 3);
139 #define r4 (pp + 3 * n) /* 3n+1 */
140 #define r2 (pp + 7 * n) /* 3n+1 */
141 #define r0 (pp +11 * n) /* s+t <= 2*n */
142 #define r5 (scratch) /* 3n+1 */
143 #define r3 (scratch + 3 * n + 1) /* 3n+1 */
144 #define r1 (scratch + 6 * n + 2) /* 3n+1 */
145 #define v0 (pp + 7 * n) /* n+1 */
146 #define v1 (pp + 8 * n+1) /* n+1 */
147 #define v2 (pp + 9 * n+2) /* n+1 */
148 #define v3 (scratch + 9 * n + 3) /* n+1 */
149 #define wsi (scratch + 9 * n + 3) /* 3n+1 */
150 #define wse (scratch +10 * n + 4) /* 2n+1 */
152 /* Alloc also 3n+1 limbs for wsi... toom_interpolate_12pts may
154 /* if (scratch == NULL) */
155 /* scratch = TMP_SALLOC_LIMBS(mpn_toom6_sqr_itch(n * 6)); */
156 ASSERT (12 * n + 6 <= mpn_toom6h_mul_itch(an,bn));
157 ASSERT (12 * n + 6 <= mpn_toom6_sqr_itch(n * 6));
159 /********************** evaluation and recursive calls *********************/
161 sign = mpn_toom_eval_pm2rexp (v2, v0, p, ap, n, s, 1, pp) ^
162 mpn_toom_eval_pm2rexp (v3, v1, q, bp, n, t, 1, pp);
163 TOOM6H_MUL_N_REC(pp, v0, v1, n + 1, wse); /* A(-1/2)*B(-1/2)*2^. */
164 TOOM6H_MUL_N_REC(r5, v2, v3, n + 1, wse); /* A(+1/2)*B(+1/2)*2^. */
165 mpn_toom_couple_handling (r5, 2 * n + 1, pp, sign, n, 1+half , half);
168 sign = mpn_toom_eval_pm1 (v2, v0, p, ap, n, s, pp);
170 sign ^= mpn_toom_eval_dgr3_pm1 (v3, v1, bp, n, t, pp);
172 sign ^= mpn_toom_eval_pm1 (v3, v1, q, bp, n, t, pp);
173 TOOM6H_MUL_N_REC(pp, v0, v1, n + 1, wse); /* A(-1)*B(-1) */
174 TOOM6H_MUL_N_REC(r3, v2, v3, n + 1, wse); /* A(1)*B(1) */
175 mpn_toom_couple_handling (r3, 2 * n + 1, pp, sign, n, 0, 0);
178 sign = mpn_toom_eval_pm2exp (v2, v0, p, ap, n, s, 2, pp) ^
179 mpn_toom_eval_pm2exp (v3, v1, q, bp, n, t, 2, pp);
180 TOOM6H_MUL_N_REC(pp, v0, v1, n + 1, wse); /* A(-4)*B(-4) */
181 TOOM6H_MUL_N_REC(r1, v2, v3, n + 1, wse); /* A(+4)*B(+4) */
182 mpn_toom_couple_handling (r1, 2 * n + 1, pp, sign, n, 2, 4);
185 sign = mpn_toom_eval_pm2rexp (v2, v0, p, ap, n, s, 2, pp) ^
186 mpn_toom_eval_pm2rexp (v3, v1, q, bp, n, t, 2, pp);
187 TOOM6H_MUL_N_REC(pp, v0, v1, n + 1, wse); /* A(-1/4)*B(-1/4)*4^. */
188 TOOM6H_MUL_N_REC(r4, v2, v3, n + 1, wse); /* A(+1/4)*B(+1/4)*4^. */
189 mpn_toom_couple_handling (r4, 2 * n + 1, pp, sign, n, 2*(1+half), 2*(half));
192 sign = mpn_toom_eval_pm2 (v2, v0, p, ap, n, s, pp) ^
193 mpn_toom_eval_pm2 (v3, v1, q, bp, n, t, pp);
194 TOOM6H_MUL_N_REC(pp, v0, v1, n + 1, wse); /* A(-2)*B(-2) */
195 TOOM6H_MUL_N_REC(r2, v2, v3, n + 1, wse); /* A(+2)*B(+2) */
196 mpn_toom_couple_handling (r2, 2 * n + 1, pp, sign, n, 1, 2);
205 TOOM6H_MUL_N_REC(pp, ap, bp, n, wsi);
210 TOOM6H_MUL_REC(r0, ap + p * n, s, bp + q * n, t, wsi);
212 TOOM6H_MUL_REC(r0, bp + q * n, t, ap + p * n, s, wsi);
216 mpn_toom_interpolate_12pts (pp, r1, r3, r5, n, s+t, half, wsi);
227 #undef TOOM6H_MUL_N_REC
228 #undef TOOM6H_MUL_REC
229 #undef MAYBE_mul_basecase
230 #undef MAYBE_mul_toom22
231 #undef MAYBE_mul_toom33
232 #undef MAYBE_mul_toom6h