Skip to content

Commit 04da081

Browse files
committed
fixup! Implement Karatsuba's multiplication algorithm
1 parent 6bb2450 commit 04da081

File tree

1 file changed

+17
-10
lines changed

1 file changed

+17
-10
lines changed

src/solvers/flattening/bv_utils.cpp

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -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

20292036
bvt bv_utilst::unsigned_toom_cook_multiplier(const bvt &_op0, const bvt &_op1)

0 commit comments

Comments
 (0)