math.big: fix toom-cook 3-way multiplication (#24888)

This commit is contained in:
Mike 2025-07-13 18:36:46 +03:00 committed by GitHub
parent 54fec7b772
commit f06def7d6d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 34 additions and 14 deletions

View File

@ -108,9 +108,9 @@ fn subtract_digit_array(operand_a []u32, operand_b []u32, mut storage []u32) {
shrink_tail_zeros(mut storage) shrink_tail_zeros(mut storage)
} }
const karatsuba_multiplication_limit = 240 const karatsuba_multiplication_limit = 70
const toom3_multiplication_limit = 10_000 const toom3_multiplication_limit = 360
@[inline] @[inline]
fn multiply_digit_array(operand_a []u32, operand_b []u32, mut storage []u32) { fn multiply_digit_array(operand_a []u32, operand_b []u32, mut storage []u32) {

View File

@ -948,3 +948,9 @@ fn test_integer_from_bytes_ignores_potential_leading_zero_bytes() {
} }
} }
} }
fn test_pow2_is_power_of_2() {
for n in 22000 .. 22010 {
assert big.two_int.pow(n).is_power_of_2(), 'pow2: ${n}'
}
}

View File

@ -164,12 +164,20 @@ fn toom3_multiply_digit_array(operand_a []u32, operand_b []u32, mut storage []u3
// Slices of a and b // Slices of a and b
a0 := Integer{ a0 := Integer{
digits: unsafe { operand_a[0..k] } digits: unsafe { operand_a[..k] }
signum: 1 signum: if operand_a[..k].all(it == 0) {
0
} else {
1
}
} }
a1 := Integer{ a1 := Integer{
digits: unsafe { operand_a[k..k2] } digits: unsafe { operand_a[k..k2] }
signum: 1 signum: if operand_a[k..k2].all(it == 0) {
0
} else {
1
}
} }
a2 := Integer{ a2 := Integer{
digits: unsafe { operand_a[k2..] } digits: unsafe { operand_a[k2..] }
@ -187,22 +195,28 @@ fn toom3_multiply_digit_array(operand_a []u32, operand_b []u32, mut storage []u3
signum: 1 signum: 1
} }
} else if operand_b.len < k2 { } else if operand_b.len < k2 {
b0 = Integer{ if !operand_b[..k].all(it == 0) {
digits: operand_b[0..k] b0 = Integer{
signum: 1 digits: operand_b[..k]
signum: 1
}
} }
b1 = Integer{ b1 = Integer{
digits: operand_b[k..] digits: operand_b[k..]
signum: 1 signum: 1
} }
} else { } else {
b0 = Integer{ if !operand_b[..k].all(it == 0) {
digits: operand_b[0..k] b0 = Integer{
signum: 1 digits: operand_b[..k]
signum: 1
}
} }
b1 = Integer{ if !operand_b[k..k2].all(it == 0) {
digits: operand_b[k..k2] b1 = Integer{
signum: 1 digits: operand_b[k..k2]
signum: 1
}
} }
b2 = Integer{ b2 = Integer{
digits: operand_b[k2..] digits: operand_b[k2..]