@@ -1973,14 +1973,17 @@ bvt bv_utilst::unsigned_karatsuba_multiplier(const bvt &_op0, const bvt &_op1)
1973
1973
return unsigned_multiplier (_op0, _op1);
1974
1974
1975
1975
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
-
1980
1976
if (op_size == 1 )
1981
1977
return {prop.land (_op0[0 ], _op1[0 ])};
1982
1978
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 ;
1984
1987
1985
1988
// We split each of the operands in half and treat them as coefficients of a
1986
1989
// 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)
2012
2015
// Therefore, after adding (dh + cg) the multiplication can safely be added
2013
2016
// over just 2 bits.
2014
2017
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 ()};
2019
2022
2020
2023
bvt z0 = unsigned_karatsuba_full_multiplier (x0, y0);
2021
2024
bvt z1 = add (
2022
2025
unsigned_karatsuba_multiplier (x1, y0),
2023
2026
unsigned_karatsuba_multiplier (x0, y1));
2024
2027
bvt z1_full = concatenate (zeros (half_op_size), z1);
2025
2028
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;
2027
2034
}
2028
2035
2029
2036
bvt bv_utilst::unsigned_toom_cook_multiplier (const bvt &_op0, const bvt &_op1)
0 commit comments