Skip to content

Commit 8a1cf97

Browse files
authored
[integer] Remove multiply_toom_cook_3 for BigUInt (#82)
This pull request includes significant changes to the `src/decimojo/biguint/arithmetics.mojo` and `src/decimojo/biguint/biguint.mojo` files, focusing on the removal of the `multiply_toom_cook_3` function, a correction to the `shift_words_left` function's documentation, and the addition of a new method to the `BigUInt` struct. ### Major Changes: **Removal of `multiply_toom_cook_3` function:** * The `multiply_toom_cook_3` function, which implemented the Toom-Cook 3-way multiplication algorithm, has been entirely removed. This includes all associated logic and comments. **Documentation Correction:** * The documentation for the `shift_words_left` function in `arithmetics.mojo` was corrected to state that the function adds trailing zeros, not leading zeros. **New Method in `BigUInt` struct:** * A new method `shift_words_left` has been added to the `BigUInt` struct, which shifts the words of the `BigUInt` to the left by a specified number of bits. This method calls the `shift_words_left` function in `arithmetics.mojo` for its implementation.
1 parent 20027ae commit 8a1cf97

File tree

2 files changed

+8
-149
lines changed

2 files changed

+8
-149
lines changed

src/decimojo/biguint/arithmetics.mojo

Lines changed: 1 addition & 149 deletions
Original file line numberDiff line numberDiff line change
@@ -604,154 +604,6 @@ fn divmod(x1: BigUInt, x2: BigUInt) raises -> Tuple[BigUInt, BigUInt]:
604604
# ===----------------------------------------------------------------------=== #
605605

606606

607-
# TODO: The subtraction can be underflowed. Use signed integers for the subtraction
608-
fn multiply_toom_cook_3(x1: BigUInt, x2: BigUInt) raises -> BigUInt:
609-
"""Implements Toom-Cook 3-way multiplication algorithm.
610-
611-
Args:
612-
x1: First operand.
613-
x2: Second operand.
614-
615-
Returns:
616-
Product of x1 and x2.
617-
618-
Notes:
619-
620-
This algorithm splits each number into 3 parts and performs 5 multiplications
621-
instead of 9, achieving O(n^log₃5) ≈ O(n^1.465) complexity.
622-
"""
623-
# Special cases
624-
if x1.is_zero() or x2.is_zero():
625-
return BigUInt()
626-
if x1.is_one():
627-
return x2
628-
if x2.is_one():
629-
return x1
630-
631-
# # Basic multiplication is faster for small numbers
632-
# if len(x1.words) < 10 or len(x2.words) < 10:
633-
# return multiply(x1, x2)
634-
635-
# Determine size for splitting
636-
var max_len = max(len(x1.words), len(x2.words))
637-
var k = (max_len + 2) // 3 # Split into thirds
638-
639-
# Split the numbers into three parts each: a = a₂·β² + a₁·β + a₀
640-
var a0_words = List[UInt32]()
641-
var a1_words = List[UInt32]()
642-
var a2_words = List[UInt32]()
643-
var b0_words = List[UInt32]()
644-
var b1_words = List[UInt32]()
645-
var b2_words = List[UInt32]()
646-
647-
# Extract parts from x1
648-
for i in range(min(k, len(x1.words))):
649-
a0_words.append(x1.words[i])
650-
for i in range(k, min(2 * k, len(x1.words))):
651-
a1_words.append(x1.words[i])
652-
for i in range(2 * k, len(x1.words)):
653-
a2_words.append(x1.words[i])
654-
655-
# Extract parts from x2
656-
for i in range(min(k, len(x2.words))):
657-
b0_words.append(x2.words[i])
658-
for i in range(k, min(2 * k, len(x2.words))):
659-
b1_words.append(x2.words[i])
660-
for i in range(2 * k, len(x2.words)):
661-
b2_words.append(x2.words[i])
662-
663-
a0 = BigUInt.from_list(a0_words^)
664-
a1 = BigUInt.from_list(a1_words^)
665-
a2 = BigUInt.from_list(a2_words^)
666-
b0 = BigUInt.from_list(b0_words^)
667-
b1 = BigUInt.from_list(b1_words^)
668-
b2 = BigUInt.from_list(b2_words^)
669-
670-
# Remove trailing zeros
671-
a0.remove_leading_empty_words()
672-
a1.remove_leading_empty_words()
673-
a2.remove_leading_empty_words()
674-
b0.remove_leading_empty_words()
675-
b1.remove_leading_empty_words()
676-
b2.remove_leading_empty_words()
677-
678-
print("DEBUG: a0 =", a0)
679-
print("DEBUG: a1 =", a1)
680-
print("DEBUG: a2 =", a2)
681-
print("DEBUG: b0 =", b0)
682-
print("DEBUG: b1 =", b1)
683-
print("DEBUG: b2 =", b2)
684-
685-
# Evaluate at points 0, 1, -1, 2, ∞
686-
# p₀ = a₀
687-
var p0_a = a0
688-
# p₁ = a₀ + a₁ + a₂
689-
var p1_a = a0 + a1 + a2
690-
# p₂ = a₀ - a₁ + a₂
691-
var p2_a = a0 + a2 - a1
692-
# p₃ = a₀ + 2a₁ + 4a₂
693-
var p3_a = a0 + a1 * BigUInt(UInt32(2)) + a2 * BigUInt(UInt32(4))
694-
# p₄ = a₂
695-
var p4_a = a2
696-
697-
# Same for b
698-
var p0_b = b0
699-
var p1_b = add(add(b0, b1), b2)
700-
var p2_b = add(subtract(b0, b1), b2)
701-
var b1_times2 = add(b1, b1)
702-
var b2_times4 = add(add(b2, b2), add(b2, b2))
703-
var p3_b = add(add(b0, b1_times2), b2_times4)
704-
var p4_b = b2
705-
706-
# Perform pointwise multiplication
707-
var r0 = multiply(p0_a, p0_b) # at 0
708-
var r1 = multiply(p1_a, p1_b) # at 1
709-
var r2 = multiply(p2_a, p2_b) # at -1
710-
var r3 = multiply(p3_a, p3_b) # at 2
711-
var r4 = multiply(p4_a, p4_b) # at ∞
712-
713-
# Interpolate to get coefficients of the result
714-
# c₀ = r₀
715-
var c0 = r0
716-
717-
# c₄ = r₄
718-
var c4 = r4
719-
720-
# TODO: The subtraction can be underflowed. Use signed integers for the subtraction
721-
# c₃ = (r₃ - r₁)/3 - (r₄ - r₂)/2 + r₄·5/6
722-
var t1 = (r3 - r1) // BigUInt(UInt32(3))
723-
var t2 = (r4 - r2) // BigUInt(UInt32(2))
724-
var t3 = r4 * BigUInt(UInt32(5)) // BigUInt(UInt32(6))
725-
var c3 = t1 + t3 - t2
726-
727-
# c₂ = (r₂ - r₀)/2 - r₄
728-
var c2 = (r2 - r0) // BigUInt(UInt32(2)) - r4
729-
730-
# c₁ = r₁ - r₀ - c₃ - c₄ - c₂
731-
var c1 = r1 - r0 - c3 - c4 - c2
732-
733-
# Combine the coefficients to get the result
734-
var result = c0
735-
736-
# c₁ * β
737-
var c1_shifted = shift_words_left(c1, k)
738-
result = result + c1_shifted
739-
740-
# c₂ * β²
741-
var c2_shifted = shift_words_left(c2, 2 * k)
742-
result = result + c2_shifted
743-
744-
# c₃ * β³
745-
var c3_shifted = shift_words_left(c3, 3 * k)
746-
result = result + c3_shifted
747-
748-
# c₄ * β⁴
749-
var c4_shifted = shift_words_left(c4, 4 * k)
750-
result = result + c4_shifted
751-
752-
return result
753-
754-
755607
fn scale_up_by_power_of_10(x: BigUInt, n: Int) raises -> BigUInt:
756608
"""Multiplies a BigUInt by 10^n (n>=0).
757609
@@ -1154,7 +1006,7 @@ fn estimate_quotient(
11541006

11551007

11561008
fn shift_words_left(num: BigUInt, positions: Int) -> BigUInt:
1157-
"""Shifts a BigUInt left by adding leading zeros.
1009+
"""Shifts a BigUInt left by adding trailing zeros.
11581010
Equivalent to multiplying by 10^(9*positions)."""
11591011
if num.is_zero():
11601012
return BigUInt()

src/decimojo/biguint/biguint.mojo

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1021,3 +1021,10 @@ struct BigUInt(Absable, IntableRaising, Writable):
10211021
1,
10221022
)
10231023
return result^
1024+
1025+
@always_inline
1026+
fn shift_words_left(self, position: Int) -> Self:
1027+
"""Shifts the words of the BigUInt to the left by `position` bits.
1028+
See `arithmetics.shift_words_left()` for more information.
1029+
"""
1030+
return decimojo.biguint.arithmetics.shift_words_left(self, position)

0 commit comments

Comments
 (0)