@@ -1973,14 +1973,17 @@ bvt bv_utilst::unsigned_karatsuba_multiplier(const bvt &_op0, const bvt &_op1)
19731973 return unsigned_multiplier (_op0, _op1);
19741974
19751975 const std::size_t op_size = _op0.size ();
1976- // only use this approach for powers of two
1977- if (op_size == 0 || (op_size & (op_size - 1 )) != 0 )
1978- return unsigned_multiplier (_op0, _op1);
1979-
19801976 if (op_size == 1 )
19811977 return {prop.land (_op0[0 ], _op1[0 ])};
19821978
1983- const std::size_t half_op_size = op_size >> 1 ;
1979+ // Make sure we work with operands the length of which are powers of two
1980+ const std::size_t log2 = address_bits (op_size);
1981+ PRECONDITION (sizeof (std::size_t ) * CHAR_BIT > log2);
1982+ const std::size_t two_to_log2 = (std::size_t )1 << log2;
1983+ bvt a = zero_extension (_op0, two_to_log2);
1984+ bvt b = zero_extension (_op1, two_to_log2);
1985+
1986+ const std::size_t half_op_size = two_to_log2 >> 1 ;
19841987
19851988 // We split each of the operands in half and treat them as coefficients of a
19861989 // polynomial a * 2^half_op_size + b. Straightforward polynomial
@@ -2012,18 +2015,22 @@ bvt bv_utilst::unsigned_karatsuba_multiplier(const bvt &_op0, const bvt &_op1)
20122015 // Therefore, after adding (dh + cg) the multiplication can safely be added
20132016 // over just 2 bits.
20142017
2015- bvt x0{_op0 .begin (), _op0 .begin () + half_op_size};
2016- bvt x1{_op0 .begin () + half_op_size, _op0 .end ()};
2017- bvt y0{_op1 .begin (), _op1 .begin () + half_op_size};
2018- bvt y1{_op1 .begin () + half_op_size, _op1 .end ()};
2018+ bvt x0{a .begin (), a .begin () + half_op_size};
2019+ bvt x1{a .begin () + half_op_size, a .end ()};
2020+ bvt y0{b .begin (), b .begin () + half_op_size};
2021+ bvt y1{b .begin () + half_op_size, b .end ()};
20192022
20202023 bvt z0 = unsigned_karatsuba_full_multiplier (x0, y0);
20212024 bvt z1 = add (
20222025 unsigned_karatsuba_multiplier (x1, y0),
20232026 unsigned_karatsuba_multiplier (x0, y1));
20242027 bvt z1_full = concatenate (zeros (half_op_size), z1);
20252028
2026- return add (z0, z1_full);
2029+ bvt result = add (z0, z1_full);
2030+ CHECK_RETURN (result.size () >= op_size);
2031+ if (result.size () > op_size)
2032+ result.resize (op_size);
2033+ return result;
20272034}
20282035
20292036bvt bv_utilst::unsigned_toom_cook_multiplier (const bvt &_op0, const bvt &_op1)
0 commit comments