Skip to content
Merged
52 changes: 52 additions & 0 deletions benches/biguint/bench_biguint_add.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ fn open_log_file() raises -> PythonObject:
"""
var python = Python.import_module("builtins")
var datetime = Python.import_module("datetime")
var pysys = Python.import_module("sys")
pysys.set_int_max_str_digits(1000000)

# Create logs directory if it doesn't exist
var log_dir = "./logs"
Expand Down Expand Up @@ -455,6 +457,56 @@ fn main() raises:
speedup_factors,
)

# Case 31: Addition with 64 words + 32 words
run_benchmark_add(
"Addition with 64 words + 32 words",
"123456789" * 64,
"987654321" * 32,
iterations,
log_file,
speedup_factors,
)

# Case 32: Addition with 256 words + 128 words
run_benchmark_add(
"Addition with 256 words + 128 words",
"123456789" * 256,
"987654321" * 128,
iterations,
log_file,
speedup_factors,
)

# Case 33: Addition with 1024 words + 512 words
run_benchmark_add(
"Addition with 1024 words + 512 words",
"123456789" * 1024,
"987654321" * 512,
iterations,
log_file,
speedup_factors,
)

# Case 34: Addition with 4096 words + 2048 words
run_benchmark_add(
"Addition with 4096 words + 2048 words",
"123456789" * 4096,
"987654321" * 2048,
iterations,
log_file,
speedup_factors,
)

# Case 35: Addition with 16384 words + 8192 words
run_benchmark_add(
"Addition with 16384 words + 8192 words",
"123456789" * 16384,
"987654321" * 8192,
iterations,
log_file,
speedup_factors,
)

# Calculate average speedup factor
var sum_speedup: Float64 = 0.0
for i in range(len(speedup_factors)):
Expand Down
118 changes: 110 additions & 8 deletions benches/biguint/bench_biguint_multiply.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,9 @@ fn main() raises:
log_print("Could not retrieve system information", log_file)

# Use fewer iterations for multiplication as it's more compute-intensive
# For large numbers, we reduce iterations to avoid long runtimes
var iterations = 100
var iterations_large = 20

# Define benchmark cases
log_print(
Expand Down Expand Up @@ -460,26 +462,126 @@ fn main() raises:
speedup_factors,
)

# Case 31: Very, very large numbers multiplication
# Case 31: 2 words * 2 words multiplication
run_benchmark_multiply(
"Extreme large numbers multiplication (9000 digits * 9000 digits)",
"123456789" * 1000, # 9000 digits
"987654321" * 1000, # 9000 digits
"2 words * 2 words multiplication",
"123456789" * 2,
"987654321" * 2,
iterations,
log_file,
speedup_factors,
)

# Case 32: Extremely large numbers multiplication
# Case 32: 4 words * 4 words multiplication
run_benchmark_multiply(
"Extreme large numbers multiplication (36000 digits * 36000 digits)",
"123456789" * 4000, # 36000 digits
"987654321" * 4000, # 36000 digits
"4 words * 4 words multiplication",
"123456789" * 4,
"987654321" * 4,
iterations,
log_file,
speedup_factors,
)

# Case 33: 8 words * 8 words multiplication
run_benchmark_multiply(
"8 words * 8 words multiplication",
"123456789" * 8,
"987654321" * 8,
iterations,
log_file,
speedup_factors,
)

# Case 34: 16 words * 16 words multiplication
run_benchmark_multiply(
"16 words * 16 words multiplication",
"123456789" * 16,
"987654321" * 16,
iterations,
log_file,
speedup_factors,
)

# Case 35: 32 words * 32 words multiplication
run_benchmark_multiply(
"32 words * 32 words multiplication",
"123456789" * 32,
"987654321" * 32,
iterations,
log_file,
speedup_factors,
)

# Case 36: 64 words * 64 words multiplication
run_benchmark_multiply(
"64 words * 64 words multiplication",
"123456789" * 64,
"987654321" * 64,
iterations,
log_file,
speedup_factors,
)

# Case 37: 128 words * 128 words multiplication
run_benchmark_multiply(
"128 words * 128 words multiplication",
"123456789" * 128,
"987654321" * 128,
iterations_large,
log_file,
speedup_factors,
)

# Case 38: 256 words * 256 words multiplication
run_benchmark_multiply(
"256 words * 256 words multiplication",
"123456789" * 256,
"987654321" * 256,
iterations_large,
log_file,
speedup_factors,
)

# Case 39: 512 words * 512 words multiplication
run_benchmark_multiply(
"512 words * 512 words multiplication",
"123456789" * 512,
"987654321" * 512,
iterations_large,
log_file,
speedup_factors,
)

# Case 40: 1024 words * 1024 words multiplication
run_benchmark_multiply(
"1024 words * 1024 words multiplication",
"123456789" * 1024,
"987654321" * 1024,
iterations_large,
log_file,
speedup_factors,
)

# Case 41: 2048 words * 2048 words multiplication
run_benchmark_multiply(
"2048 words * 2048 words multiplication",
"123456789" * 2048,
"987654321" * 2048,
iterations_large,
log_file,
speedup_factors,
)

# Case 42: 4096 words * 4096 words multiplication
run_benchmark_multiply(
"4096 words * 4096 words multiplication",
"123456789" * 4096,
"987654321" * 4096,
iterations_large,
log_file,
speedup_factors,
)

# Calculate average speedup factor
var sum_speedup: Float64 = 0.0
for i in range(len(speedup_factors)):
Expand Down
6 changes: 4 additions & 2 deletions benches/biguint/bench_biguint_multiply_complexity.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ fn main() raises:

log_print("", log_file)
log_print(
"Testing word sizes from 32 to 262144 words (powers of 2)", log_file
"Testing word sizes from 8 to 262144 words (powers of 2)", log_file
)
log_print("Each test uses 5 iterations for averaging", log_file)
log_print(
Expand All @@ -138,8 +138,10 @@ fn main() raises:
)
log_print("", log_file)

# Test sizes: powers of 2 from 32 to 262144
# Test sizes: powers of 2 from 8 to 262144
var test_sizes = List[Int]()
test_sizes.append(8)
test_sizes.append(16)
test_sizes.append(32)
test_sizes.append(64)
test_sizes.append(128)
Expand Down
18 changes: 9 additions & 9 deletions src/decimojo/bigdecimal/arithmetics.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ fn add(x1: BigDecimal, x2: BigDecimal) raises -> BigDecimal:
return x1.extend_precision(scale_factor1)

# Scale coefficients to match
var coef1 = x1.coefficient.scale_up_by_power_of_10(scale_factor1)
var coef2 = x2.coefficient.scale_up_by_power_of_10(scale_factor2)
var coef1 = x1.coefficient.multiply_by_power_of_ten(scale_factor1)
var coef2 = x2.coefficient.multiply_by_power_of_ten(scale_factor2)

# Handle addition based on signs
if x1.sign == x2.sign:
Expand Down Expand Up @@ -135,8 +135,8 @@ fn subtract(x1: BigDecimal, x2: BigDecimal) raises -> BigDecimal:
return result^

# Scale coefficients to match
var coef1 = x1.coefficient.scale_up_by_power_of_10(scale_factor1)
var coef2 = x2.coefficient.scale_up_by_power_of_10(scale_factor2)
var coef1 = x1.coefficient.multiply_by_power_of_ten(scale_factor1)
var coef2 = x2.coefficient.multiply_by_power_of_ten(scale_factor2)

# Handle subtraction based on signs
if x1.sign != x2.sign:
Expand Down Expand Up @@ -278,7 +278,7 @@ fn true_divide(
# Scale up the dividend to ensure sufficient precision
var scaled_x1 = x1.coefficient
if additional_digits > 0:
scaled_x1.scale_up_inplace_by_power_of_10(additional_digits)
scaled_x1.multiply_inplace_by_power_of_ten(additional_digits)

# Perform division
var quotient: BigUInt
Expand All @@ -301,7 +301,7 @@ fn true_divide(
if is_exact:
var num_trailing_zeros = quotient.number_of_trailing_zeros()
if num_trailing_zeros > 0:
quotient = quotient.scale_down_by_power_of_10(num_trailing_zeros)
quotient = quotient.floor_divide_by_power_of_ten(num_trailing_zeros)
result_scale -= num_trailing_zeros
# Recalculate digits after removing trailing zeros
result_digits = quotient.number_of_digits()
Expand Down Expand Up @@ -382,7 +382,7 @@ fn true_divide_inexact(
# Scale up the dividend to ensure sufficient precision
var scaled_x1 = x1.coefficient
if buffer_digits > 0:
scaled_x1.scale_up_inplace_by_power_of_10(buffer_digits)
scaled_x1.multiply_inplace_by_power_of_ten(buffer_digits)

# Perform division
var quotient: BigUInt = scaled_x1 // x2.coefficient
Expand Down Expand Up @@ -437,12 +437,12 @@ fn truncate_divide(x1: BigDecimal, x2: BigDecimal) raises -> BigDecimal:
# If scale_diff is positive, we need to scale up the dividend
# If scale_diff is negative, we need to scale up the divisor
if scale_diff > 0:
var divisor = x2.coefficient.scale_up_by_power_of_10(scale_diff)
var divisor = x2.coefficient.multiply_by_power_of_ten(scale_diff)
var quotient = x1.coefficient.truncate_divide(divisor)
return BigDecimal(quotient^, 0, x1.sign != x2.sign)

else: # scale_diff < 0
var dividend = x1.coefficient.scale_up_by_power_of_10(-scale_diff)
var dividend = x1.coefficient.multiply_by_power_of_ten(-scale_diff)
var quotient = dividend.truncate_divide(x2.coefficient)
return BigDecimal(quotient^, 0, x1.sign != x2.sign)

Expand Down
4 changes: 2 additions & 2 deletions src/decimojo/bigdecimal/comparison.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,11 @@ fn compare_absolute(x1: BigDecimal, x2: BigDecimal) -> Int8:

if scale_diff > 0:
# x1 has larger scale (more decimal places)
var scaled_x2 = x2.coefficient.scale_up_by_power_of_10(scale_diff)
var scaled_x2 = x2.coefficient.multiply_by_power_of_ten(scale_diff)
return x1.coefficient.compare(scaled_x2^)
else:
# x2 has larger scale (more decimal places)
var scaled_x1 = x1.coefficient.scale_up_by_power_of_10(-scale_diff)
var scaled_x1 = x1.coefficient.multiply_by_power_of_ten(-scale_diff)
return scaled_x1.compare(x2.coefficient)


Expand Down
8 changes: 5 additions & 3 deletions src/decimojo/bigdecimal/exponential.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -156,11 +156,13 @@ fn integer_power(
var abs_exp = abs(exponent)
var exp_value: BigUInt
if abs_exp.scale > 0:
exp_value = abs_exp.coefficient.scale_down_by_power_of_10(abs_exp.scale)
exp_value = abs_exp.coefficient.floor_divide_by_power_of_ten(
abs_exp.scale
)
elif abs_exp.scale == 0:
exp_value = abs_exp.coefficient
else:
exp_value = abs_exp.coefficient.scale_up_by_power_of_10(-abs_exp.scale)
exp_value = abs_exp.coefficient.multiply_by_power_of_ten(-abs_exp.scale)

var result = BigDecimal(BigUInt.ONE, 0, False)
var current_power = base
Expand Down Expand Up @@ -357,7 +359,7 @@ fn integer_root(
# Convert n to integer to check odd/even
var n_uint: BigUInt
if n.scale > 0:
n_uint = n.coefficient.scale_down_by_power_of_10(n.scale)
n_uint = n.coefficient.floor_divide_by_power_of_ten(n.scale)
else: # n.scale <= 0
n_uint = n.coefficient

Expand Down
6 changes: 4 additions & 2 deletions src/decimojo/bigint/bigint.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -523,8 +523,10 @@ struct BigInt(Absable, IntableRaising, Representable, Stringable, Writable):
@always_inline
fn __iadd__(mut self, other: Int) raises:
# Optimize the case `i += 1`
if (self >= 0) and (other == 1):
self.magnitude.add_inplace_by_1()
if (self >= 0) and (other >= 0) and (other <= 999_999_999):
decimojo.biguint.arithmetics.add_inplace_by_uint32(
self.magnitude, UInt32(other)
)
else:
decimojo.bigint.arithmetics.add_inplace(self, other)

Expand Down
Loading