2 #ifdef BN_MP_TOOM_MUL_C
3 /* LibTomMath, multiple-precision integer library -- Tom St Denis
5 * LibTomMath is a library that provides multiple-precision
6 * integer arithmetic as well as number theoretic functionality.
8 * The library was designed directly after the MPI library by
9 * Michael Fromberger but has been written from scratch with
10 * additional optimizations in place.
12 * The library is free for all purposes without any express
15 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
18 /* multiplication using the Toom-Cook 3-way algorithm
20 * Much more complicated than Karatsuba but has a lower
21 * asymptotic running time of O(N**1.464). This algorithm is
22 * only particularly useful on VERY large inputs
23 * (we're talking 1000s of digits here...).
25 int mp_toom_mul(mp_int
*a
, mp_int
*b
, mp_int
*c
)
27 mp_int w0
, w1
, w2
, w3
, w4
, tmp1
, tmp2
, a0
, a1
, a2
, b0
, b1
, b2
;
31 if ((res
= mp_init_multi(&w0
, &w1
, &w2
, &w3
, &w4
,
32 &a0
, &a1
, &a2
, &b0
, &b1
,
33 &b2
, &tmp1
, &tmp2
, NULL
)) != MP_OKAY
) {
38 B
= MIN(a
->used
, b
->used
) / 3;
40 /* a = a2 * B**2 + a1 * B + a0 */
41 if ((res
= mp_mod_2d(a
, DIGIT_BIT
* B
, &a0
)) != MP_OKAY
) {
45 if ((res
= mp_copy(a
, &a1
)) != MP_OKAY
) {
49 mp_mod_2d(&a1
, DIGIT_BIT
* B
, &a1
);
51 if ((res
= mp_copy(a
, &a2
)) != MP_OKAY
) {
56 /* b = b2 * B**2 + b1 * B + b0 */
57 if ((res
= mp_mod_2d(b
, DIGIT_BIT
* B
, &b0
)) != MP_OKAY
) {
61 if ((res
= mp_copy(b
, &b1
)) != MP_OKAY
) {
65 mp_mod_2d(&b1
, DIGIT_BIT
* B
, &b1
);
67 if ((res
= mp_copy(b
, &b2
)) != MP_OKAY
) {
73 if ((res
= mp_mul(&a0
, &b0
, &w0
)) != MP_OKAY
) {
78 if ((res
= mp_mul(&a2
, &b2
, &w4
)) != MP_OKAY
) {
82 /* w1 = (a2 + 2(a1 + 2a0))(b2 + 2(b1 + 2b0)) */
83 if ((res
= mp_mul_2(&a0
, &tmp1
)) != MP_OKAY
) {
86 if ((res
= mp_add(&tmp1
, &a1
, &tmp1
)) != MP_OKAY
) {
89 if ((res
= mp_mul_2(&tmp1
, &tmp1
)) != MP_OKAY
) {
92 if ((res
= mp_add(&tmp1
, &a2
, &tmp1
)) != MP_OKAY
) {
96 if ((res
= mp_mul_2(&b0
, &tmp2
)) != MP_OKAY
) {
99 if ((res
= mp_add(&tmp2
, &b1
, &tmp2
)) != MP_OKAY
) {
102 if ((res
= mp_mul_2(&tmp2
, &tmp2
)) != MP_OKAY
) {
105 if ((res
= mp_add(&tmp2
, &b2
, &tmp2
)) != MP_OKAY
) {
109 if ((res
= mp_mul(&tmp1
, &tmp2
, &w1
)) != MP_OKAY
) {
113 /* w3 = (a0 + 2(a1 + 2a2))(b0 + 2(b1 + 2b2)) */
114 if ((res
= mp_mul_2(&a2
, &tmp1
)) != MP_OKAY
) {
117 if ((res
= mp_add(&tmp1
, &a1
, &tmp1
)) != MP_OKAY
) {
120 if ((res
= mp_mul_2(&tmp1
, &tmp1
)) != MP_OKAY
) {
123 if ((res
= mp_add(&tmp1
, &a0
, &tmp1
)) != MP_OKAY
) {
127 if ((res
= mp_mul_2(&b2
, &tmp2
)) != MP_OKAY
) {
130 if ((res
= mp_add(&tmp2
, &b1
, &tmp2
)) != MP_OKAY
) {
133 if ((res
= mp_mul_2(&tmp2
, &tmp2
)) != MP_OKAY
) {
136 if ((res
= mp_add(&tmp2
, &b0
, &tmp2
)) != MP_OKAY
) {
140 if ((res
= mp_mul(&tmp1
, &tmp2
, &w3
)) != MP_OKAY
) {
145 /* w2 = (a2 + a1 + a0)(b2 + b1 + b0) */
146 if ((res
= mp_add(&a2
, &a1
, &tmp1
)) != MP_OKAY
) {
149 if ((res
= mp_add(&tmp1
, &a0
, &tmp1
)) != MP_OKAY
) {
152 if ((res
= mp_add(&b2
, &b1
, &tmp2
)) != MP_OKAY
) {
155 if ((res
= mp_add(&tmp2
, &b0
, &tmp2
)) != MP_OKAY
) {
158 if ((res
= mp_mul(&tmp1
, &tmp2
, &w2
)) != MP_OKAY
) {
162 /* now solve the matrix
170 using 12 subtractions, 4 shifts,
171 2 small divisions and 1 small multiplication
175 if ((res
= mp_sub(&w1
, &w4
, &w1
)) != MP_OKAY
) {
179 if ((res
= mp_sub(&w3
, &w0
, &w3
)) != MP_OKAY
) {
183 if ((res
= mp_div_2(&w1
, &w1
)) != MP_OKAY
) {
187 if ((res
= mp_div_2(&w3
, &w3
)) != MP_OKAY
) {
191 if ((res
= mp_sub(&w2
, &w0
, &w2
)) != MP_OKAY
) {
194 if ((res
= mp_sub(&w2
, &w4
, &w2
)) != MP_OKAY
) {
198 if ((res
= mp_sub(&w1
, &w2
, &w1
)) != MP_OKAY
) {
202 if ((res
= mp_sub(&w3
, &w2
, &w3
)) != MP_OKAY
) {
206 if ((res
= mp_mul_2d(&w0
, 3, &tmp1
)) != MP_OKAY
) {
209 if ((res
= mp_sub(&w1
, &tmp1
, &w1
)) != MP_OKAY
) {
213 if ((res
= mp_mul_2d(&w4
, 3, &tmp1
)) != MP_OKAY
) {
216 if ((res
= mp_sub(&w3
, &tmp1
, &w3
)) != MP_OKAY
) {
220 if ((res
= mp_mul_d(&w2
, 3, &w2
)) != MP_OKAY
) {
223 if ((res
= mp_sub(&w2
, &w1
, &w2
)) != MP_OKAY
) {
226 if ((res
= mp_sub(&w2
, &w3
, &w2
)) != MP_OKAY
) {
230 if ((res
= mp_sub(&w1
, &w2
, &w1
)) != MP_OKAY
) {
234 if ((res
= mp_sub(&w3
, &w2
, &w3
)) != MP_OKAY
) {
238 if ((res
= mp_div_3(&w1
, &w1
, NULL
)) != MP_OKAY
) {
242 if ((res
= mp_div_3(&w3
, &w3
, NULL
)) != MP_OKAY
) {
246 /* at this point shift W[n] by B*n */
247 if ((res
= mp_lshd(&w1
, 1*B
)) != MP_OKAY
) {
250 if ((res
= mp_lshd(&w2
, 2*B
)) != MP_OKAY
) {
253 if ((res
= mp_lshd(&w3
, 3*B
)) != MP_OKAY
) {
256 if ((res
= mp_lshd(&w4
, 4*B
)) != MP_OKAY
) {
260 if ((res
= mp_add(&w0
, &w1
, c
)) != MP_OKAY
) {
263 if ((res
= mp_add(&w2
, &w3
, &tmp1
)) != MP_OKAY
) {
266 if ((res
= mp_add(&w4
, &tmp1
, &tmp1
)) != MP_OKAY
) {
269 if ((res
= mp_add(&tmp1
, c
, c
)) != MP_OKAY
) {
274 mp_clear_multi(&w0
, &w1
, &w2
, &w3
, &w4
,
275 &a0
, &a1
, &a2
, &b0
, &b1
,
276 &b2
, &tmp1
, &tmp2
, NULL
);
282 /* $Source: /cvs/libtom/libtommath/bn_mp_toom_mul.c,v $ */
283 /* $Revision: 1.3 $ */
284 /* $Date: 2006/03/31 14:18:44 $ */