Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions src/decimojo/bigdecimal/arithmetics.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,6 @@ fn multiply(x1: BigDecimal, x2: BigDecimal) -> BigDecimal:
)


# TODO: Optimize when divided by power of 10
fn true_divide(
x: BigDecimal, y: BigDecimal, precision: Int
) raises -> BigDecimal:
Expand Down Expand Up @@ -270,8 +269,7 @@ fn true_divide_fast(
x.coefficient, extra_words
)
elif extra_words < 0:
# TODO: Replace this with `floor_divide_by_power_of_billion()`
coef_x = decimojo.biguint.arithmetics.floor_divide_by_power_of_ten(
coef_x = decimojo.biguint.arithmetics.floor_divide_by_power_of_billion(
x.coefficient, -extra_words * 9
)
else:
Expand Down
98 changes: 90 additions & 8 deletions src/decimojo/biguint/arithmetics.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -1269,15 +1269,24 @@ fn multiply_inplace_by_uint32_le_4(mut x: BigUInt, y: UInt32):


fn multiply_by_power_of_ten(x: BigUInt, n: Int) -> BigUInt:
"""Multiplies a BigUInt by 10^n if n > 0, otherwise doing nothing.
"""Multiplies a BigUInt by 10^n (n >= 0).

Args:
x: The BigUInt value to multiply.
n: The power of 10 to multiply by.

Returns:
A new BigUInt containing the result of the multiplication.

Notes:

In non-debug model, if n is less than or equal to 0, the function returns x
unchanged. In debug mode, it asserts that n is non-negative.
"""
debug_assert[assert_mode="none"](
n >= 0, "multiply_by_power_of_ten(): n must be non-negative, got ", n
)

if n <= 0:
return x

Expand Down Expand Up @@ -1332,12 +1341,23 @@ fn multiply_by_power_of_ten(x: BigUInt, n: Int) -> BigUInt:


fn multiply_inplace_by_power_of_ten(mut x: BigUInt, n: Int):
"""Multiplies a BigUInt in-place by 10^n if n > 0, otherwise doing nothing.
"""Multiplies a BigUInt in-place by 10^n (n >= 0).

Args:
x: The BigUInt value to multiply.
n: The power of 10 to multiply by.

Notes:

In non-debug model, if n is less than or equal to 0, the function returns x
unchanged. In debug mode, it asserts that n is non-negative.
"""
debug_assert[assert_mode="none"](
n >= 0,
"multiply_inplace_by_power_of_ten(): n must be non-negative, got ",
n,
)

if n <= 0:
return

Expand Down Expand Up @@ -1412,13 +1432,23 @@ fn multiply_inplace_by_power_of_ten(mut x: BigUInt, n: Int):


fn multiply_by_power_of_billion(x: BigUInt, n: Int) -> BigUInt:
"""Multiplies a BigUInt by (10^9)^n if n > 0.
"""Multiplies a BigUInt by (10^9)^n (n >= 0).
This equals to adding 9n zeros (n words) to the end of the number.

Args:
x: The BigUInt value to multiply.
n: The power of 10^9 to multiply by. Should be non-negative.

Notes:

In non-debug model, if n is less than or equal to 0, the function returns x
unchanged. In debug mode, it asserts that n is non-negative.
"""
debug_assert[assert_mode="none"](
n >= 0,
"multiply_by_power_of_billion(): n must be non-negative, got ",
n,
)

if n <= 0:
return x # No change needed
Expand All @@ -1442,13 +1472,23 @@ fn multiply_by_power_of_billion(x: BigUInt, n: Int) -> BigUInt:


fn multiply_inplace_by_power_of_billion(mut x: BigUInt, n: Int):
"""Multiplies a BigUInt in-place by (10^9)^n if n > 0.
"""Multiplies a BigUInt in-place by (10^9)^n (n >= 0).
This equals to adding 9n zeros (n words) to the end of the number.

Args:
x: The BigUInt value to multiply.
n: The power of 10^9 to multiply by. Should be non-negative.

Notes:

In non-debug model, if n is less than or equal to 0, the function returns x
unchanged. In debug mode, it asserts that n is non-negative.
"""
debug_assert[assert_mode="none"](
n >= 0,
"multiply_inplace_by_power_of_billion(): n must be non-negative, got ",
n,
)

if n <= 0:
return # No change needed
Expand Down Expand Up @@ -2031,15 +2071,15 @@ fn floor_divide_by_power_of_ten(x: BigUInt, n: Int) -> BigUInt:

Args:
x: The BigUInt value to divide.
n: The power of 10 to divide by.
n: The power of 10 to divide by. Should be non-negative.

Returns:
A new BigUInt containing the result of the multiplication.

Notes:

Please note that this function does not check if n is negative.
Please ensure that n is non-negative before calling this function.
In non-debug model, if n is less than or equal to 0, the function returns x
unchanged. In debug mode, it asserts that n is non-negative.
"""
debug_assert[assert_mode="none"](
n >= 0,
Expand All @@ -2050,7 +2090,7 @@ fn floor_divide_by_power_of_ten(x: BigUInt, n: Int) -> BigUInt:
),
)

if n == 0:
if n <= 0:
return x

# First remove the last words (10^9)
Expand Down Expand Up @@ -2103,6 +2143,48 @@ fn floor_divide_by_power_of_ten(x: BigUInt, n: Int) -> BigUInt:
return result^


fn floor_divide_by_power_of_billion(x: BigUInt, n: Int) -> BigUInt:
"""Floor divides a BigUInt by (10^9)^n (n>=0).
This function is equivalent to removing the last n words of the number.

Args:
x: The BigUInt value to divide.
n: The power of 10^9 to divide by. Should be non-negative.

Returns:
A new BigUInt containing the result of the division.

Notes:

In non-debug model, if n is less than or equal to 0, the function returns x
unchanged. In debug mode, it asserts that n is non-negative.
"""
debug_assert[assert_mode="none"](
n >= 0,
(
"biguint.arithmetics.floor_divide_by_power_of_billion(): "
"n must be non-negative but got "
+ String(n)
),
)

if n <= 0:
return x

var n_words_of_result = len(x.words) - n
if n_words_of_result <= 0:
# If we need to drop more words than exists, result is zero
return BigUInt.ZERO
else:
var result = BigUInt(unsafe_uninit_length=n_words_of_result)
memcpy(
dest=result.words._data,
src=x.words._data + n,
count=n_words_of_result,
)
return result^


# FAST RUCURSIVE DIVISION ALGORITHM
# =============================== #
# The following functions implement the Burnikel-Ziegler algorithm.
Expand Down