Skip to content

Commit 79df4ae

Browse files
authored
[tests] Refactor the testing files for BigInt and BigUInt (#106)
This PR refactors the testing files for `BigInt` and `BigUInt` - Refactored BigInt arithmetic tests (`tests/bigint/test_bigint_arithmetics.mojo`) to use a data-driven approach by loading test cases from TOML files, significantly reducing code duplication and improving maintainability. - Added support for unary test cases in the `load_test_cases` function (`src/decimojo/tests. Mojo`) with a new `unary` parameter to differentiate between single and multi-operand tests. - Add tests for `BigUInt` which first generate very big (>20000 digits) integers, floor divide them using both DeciMojo and Python's int type, and compare them.
1 parent 8359de6 commit 79df4ae

17 files changed

+1340
-2369
lines changed

docs/internal_notes.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,4 @@
2020
- #94. Implementing pi() with Machin's formula. Time taken for precision 2048: 33.580649 seconds.
2121
- #95. Implementing pi() with Chudnovsky algorithm (binary splitting). Time taken for precision 2048: 1.771954 seconds.
2222
- #97. Implementing Karatsuba multiplication for BigUInt. Time taken for precision 2048: 0.60656999994535 seconds.
23+
- #105. Implementing Burnikel-Ziegler division for BigUInt. Time taken for precision 2048: 0.5454419999732636 seconds.

docs/todo.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ This is a to-do list for Yuhao's personal use.
44

55
- [x] (#31) The `exp()` function performs slower than Python's counterpart in specific cases. Detailed investigation reveals the bottleneck stems from multiplication operations between decimals with significant fractional components. These operations currently rely on UInt256 arithmetic, which introduces performance overhead. Optimization of the `multiply()` function is required to address these performance bottlenecks, particularly for high-precision decimal multiplication with many digits after the decimal point.
66
- [ ] When Mojo supports global variables, implement a global variable for the `BigDecimal` class to store the precision of the decimal number. This will allow users to set the precision globally, rather than having to set it for each function of the `BigDecimal` class.
7-
- [ ] Implement different methods for augmented arithmetic assignments to improve memeory-efficiency and performance.
7+
- [x] Implement different methods for augmented arithmetic assignments to improve memeory-efficiency and performance.
88
- [ ] Implement different methods for adding decimojo types with `Int` types so that an implicit conversion is not required.
9-
- [ ] Implement a method `remove_trailing_zeros` for `BigUInt`.
9+
- [x] Implement a method `remove_leading_zeros` for `BigUInt`, which removes the zero words from the most significant end of the number.
10+
- [ ] Use debug mode to check for unnecessary zero words before all arithmetic operations. This will help ensure that there are no zero words, which can simplify the speed of checking for zero because we only need to check the first word.
11+
- [ ] Use debug mode to check for uninitialized `BigUInt` before all arithmetic operations. This will help ensure that there are no uninitialized `BigUInt`.

pixi.toml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,14 @@ t = "clear && pixi run package && pixi run mojo test tests -D ASSERT=all --filte
3232
b = "pixi run t big"
3333

3434
# benches
35-
bench_decimal = "clear && pixi run package && cd benches/decimal && pixi run mojo run -I ../ -D ASSERT=all bench.mojo && cd ../.. && pixi run clean"
36-
bench_bigint = "clear && pixi run package && cd benches/bigint && pixi run mojo run -I ../ -D ASSERT=all bench.mojo && cd ../.. && pixi run clean"
37-
bench_biguint = "clear && pixi run package && cd benches/biguint && pixi run mojo run -I ../ -D ASSERT=all bench.mojo && cd ../.. && pixi run clean"
38-
bench_bigdecimal = "clear && pixi run package && cd benches/bigdecimal && pixi run mojo run -I ../ -D ASSERT=all bench.mojo && cd ../.. && pixi run clean"
39-
bench_dec = "pixi run bench_decimal"
40-
bench_bint = "pixi run bench_bigint"
41-
bench_buint = "pixi run bench_biguint"
42-
bench_bdec = "pixi run bench_bigdecimal"
35+
dec = "clear && pixi run package && cd benches/decimal && pixi run mojo run -I ../ bench.mojo && cd ../.. && pixi run clean"
36+
bint = "clear && pixi run package && cd benches/bigint && pixi run mojo run -I ../ bench.mojo && cd ../.. && pixi run clean"
37+
buint = "clear && pixi run package && cd benches/biguint && pixi run mojo run -I ../ bench.mojo && cd ../.. && pixi run clean"
38+
bdec = "clear && pixi run package && cd benches/bigdecimal && pixi run mojo run -I ../ bench.mojo && cd ../.. && pixi run clean"
39+
dec_debug = "clear && pixi run package && cd benches/decimal && pixi run mojo run -I ../ -D ASSERT=all bench.mojo && cd ../.. && pixi run clean"
40+
bint_debug = "clear && pixi run package && cd benches/bigint && pixi run mojo run -I ../ -D ASSERT=all bench.mojo && cd ../.. && pixi run clean"
41+
buint_debug = "clear && pixi run package && cd benches/biguint && pixi run mojo run -I ../ -D ASSERT=all bench.mojo && cd ../.. && pixi run clean"
42+
bdec_debug = "clear && pixi run package && cd benches/bigdecimal && pixi run mojo run -I ../ -D ASSERT=all bench.mojo && cd ../.. && pixi run clean"
4343

4444
# doc
4545
doc = "clear && pixi run mojo doc -o docs/doc.json --diagnose-missing-doc-strings --validate-doc-strings src/decimojo"

src/decimojo/biguint/arithmetics.mojo

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1064,7 +1064,7 @@ fn multiply_inplace_by_uint32(mut x: BigUInt, y: UInt32):
10641064
"""
10651065
# Short circuit cases when y is between 0 and 4
10661066
# See `multiply_inplace_by_uint32_le_4()` for details
1067-
# TODO: Check the performance of `y <= 4`
1067+
# The performance is the best when `y <= 2`
10681068
if y <= 2:
10691069
multiply_inplace_by_uint32_le_4(x, y)
10701070
return

src/decimojo/tests.mojo

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -92,22 +92,47 @@ fn parse_file(file_path: String) raises -> tomlmojo.parser.TOMLDocument:
9292
)
9393

9494

95-
fn load_test_cases(
96-
toml: tomlmojo.parser.TOMLDocument, table_name: String
97-
) raises -> List[TestCase]:
98-
"""Load test cases from a TOMLDocument."""
95+
fn load_test_cases[
96+
unary: Bool = False
97+
](toml: tomlmojo.parser.TOMLDocument, table_name: String) raises -> List[
98+
TestCase
99+
]:
100+
"""Load test cases from a TOMLDocument.
101+
102+
Parameters:
103+
unary: Whether the test cases are unary (single operand) or binary (two operands).
104+
105+
Args:
106+
toml: The TOMLDocument containing the test cases.
107+
table_name: The name of the table in the TOMLDocument to load test cases from.
108+
109+
Returns:
110+
A list of TestCase objects containing the test cases.
111+
"""
99112
# Get array of test cases
100113
var cases_array = toml.get_array_of_tables(table_name)
101114

102115
var test_cases = List[TestCase]()
103-
for case_table in cases_array:
104-
test_cases.append(
105-
TestCase(
106-
case_table["a"].as_string(),
107-
case_table["b"].as_string(),
108-
case_table["expected"].as_string(),
109-
case_table["description"].as_string(),
116+
117+
if unary:
118+
for case_table in cases_array:
119+
test_cases.append(
120+
TestCase(
121+
case_table["a"].as_string(),
122+
"",
123+
case_table["expected"].as_string(),
124+
case_table["description"].as_string(),
125+
)
126+
)
127+
else:
128+
for case_table in cases_array:
129+
test_cases.append(
130+
TestCase(
131+
case_table["a"].as_string(),
132+
case_table["b"].as_string(),
133+
case_table["expected"].as_string(),
134+
case_table["description"].as_string(),
135+
)
110136
)
111-
)
112137

113138
return test_cases

0 commit comments

Comments
 (0)