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
2 changes: 1 addition & 1 deletion mojoproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ readme = "README.md"
version = "0.3.0"

[dependencies]
max = "==25.2"
max = "==25.3"

[tasks]
# format the code
Expand Down
16 changes: 11 additions & 5 deletions src/decimojo/bigdecimal/bigdecimal.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -620,15 +620,20 @@ struct BigDecimal(Absable, Comparable, IntableRaising, Roundable, Writable):
return decimojo.bigdecimal.comparison.min(self, other)

@always_inline
fn root(self, root: Self, precision: Int) raises -> Self:
fn root(self, root: Self, precision: Int = 28) raises -> Self:
"""Returns the root of the BigDecimal number."""
return decimojo.bigdecimal.exponential.root(self, root, precision)

@always_inline
fn sqrt(self, precision: Int) raises -> Self:
fn sqrt(self, precision: Int = 28) raises -> Self:
"""Returns the square root of the BigDecimal number."""
return decimojo.bigdecimal.exponential.sqrt(self, precision)

@always_inline
fn cbrt(self, precision: Int = 28) raises -> Self:
"""Returns the cube root of the BigDecimal number."""
return decimojo.bigdecimal.exponential.cbrt(self, precision)

@always_inline
fn true_divide(self, other: Self, precision: Int) raises -> Self:
"""Returns the result of true division of two BigDecimal numbers.
Expand Down Expand Up @@ -798,9 +803,11 @@ struct BigDecimal(Absable, Comparable, IntableRaising, Roundable, Writable):
else:
ndigits = 3
print(
"word {}:{}{}".format(
String("word {}:{}{}")
.format(
i, " " * (10 - ndigits), String(self.coefficient.words[i])
).rjust(9, fillchar="0")
)
.rjust(9, fillchar="0")
)
print("----------------------------------------------")

Expand Down Expand Up @@ -866,7 +873,6 @@ struct BigDecimal(Absable, Comparable, IntableRaising, Roundable, Writable):
var number_of_words_to_remove = number_of_digits_to_remove // 9
var number_of_remaining_digits_to_remove = number_of_digits_to_remove % 9

var words: List[UInt32] = List[UInt32]()
words = self.coefficient.words[number_of_words_to_remove:]
var coefficient = BigUInt(words^)

Expand Down
40 changes: 40 additions & 0 deletions src/decimojo/bigdecimal/exponential.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,24 @@ from decimojo.bigdecimal.bigdecimal import BigDecimal
from decimojo.rounding_mode import RoundingMode
import decimojo.utility

# ===----------------------------------------------------------------------=== #
# List of functions in this module:
# - power(base: BigDecimal, exponent: BigDecimal, precision: Int) -> BigDecimal
# - integer_power(base: BigDecimal, exponent: BigDecimal, precision: Int) -> BigDecimal
# - root(x: BigDecimal, n: BigDecimal, precision: Int) -> BigDecimal
# - integer_root(x: BigDecimal, n: BigDecimal, precision: Int) -> BigDecimal
# - is_integer_reciprocal_and_return(n: BigDecimal) -> Tuple[Bool, BigDecimal]
# - is_odd_reciprocal(n: BigDecimal) -> Bool
# - sqrt(x: BigDecimal, precision: Int) -> BigDecimal
# - exp(x: BigDecimal, precision: Int) -> BigDecimal
# - exp_taylor_series(x: BigDecimal, minimum_precision: Int) -> BigDecimal
# - ln(x: BigDecimal, precision: Int) -> BigDecimal
# - log(x: BigDecimal, precision: Int) -> BigDecimal
# - log10(x: BigDecimal, precision: Int) -> BigDecimal
# - ln_series_expansion(x: BigDecimal, precision: Int) -> BigDecimal
# - compute_ln2(precision: Int) -> BigDecimal
# - compute_ln1d25(precision: Int) -> BigDecimal
# ===----------------------------------------------------------------------=== #

# ===----------------------------------------------------------------------=== #
# Power and root functions
Expand Down Expand Up @@ -561,6 +579,28 @@ fn sqrt(x: BigDecimal, precision: Int) raises -> BigDecimal:
return guess^


fn cbrt(x: BigDecimal, precision: Int) raises -> BigDecimal:
"""Calculate the cube root of a BigDecimal number.

Args:
x: The number to calculate the cube root of.
precision: The desired precision (number of significant digits) of the result.

Returns:
The cube root of x with the specified precision.

Raises:
Error: If x is negative.
"""

result = integer_root(
x,
BigDecimal(coefficient=BigUInt(List[UInt32](3)), scale=0, sign=False),
precision,
)
return result^


# ===----------------------------------------------------------------------=== #
# Exponential functions
# ===----------------------------------------------------------------------=== #
Expand Down
9 changes: 5 additions & 4 deletions src/decimojo/bigint/bigint.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -261,9 +261,8 @@ struct BigInt(Absable, IntableRaising, Writable):
The BigInt representation of the string.
"""
var coef: List[UInt8]
var scale: Int
var sign: Bool
coef, scale, sign = decimojo.str.parse_numeric_string(value)
coef, _scale, sign = decimojo.str.parse_numeric_string(value)

# Check if the number is zero
if len(coef) == 1 and coef[0] == UInt8(0):
Expand Down Expand Up @@ -620,8 +619,10 @@ struct BigInt(Absable, IntableRaising, Writable):
else:
ndigits = 3
print(
"word {}:{}{}".format(
String("word {}:{}{}")
.format(
i, " " * (10 - ndigits), String(self.magnitude.words[i])
).rjust(9, fillchar="0")
)
.rjust(9, fillchar="0")
)
print("----------------------------------------------")
56 changes: 44 additions & 12 deletions src/decimojo/biguint/arithmetics.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,34 @@ from decimojo.biguint.biguint import BigUInt
import decimojo.biguint.comparison
from decimojo.rounding_mode import RoundingMode

# ===----------------------------------------------------------------------=== #
# List of functions in this module:
# add(x1: BigUInt, x2: BigUInt) -> BigUInt
# add_inplace(x1: BigUInt, x2: BigUInt)
# add_inplace_by_1(x: BigUInt) -> None
# subtract(x1: BigUInt, x2: BigUInt) -> BigUInt
# negative(x: BigUInt) -> BigUInt
# absolute(x: BigUInt) -> BigUInt
# multiply(x1: BigUInt, x2: BigUInt) -> BigUInt
# floor_divide(x1: BigUInt, x2: BigUInt) -> BigUInt
# truncate_divide(x1: BigUInt, x2: BigUInt) -> BigUInt
# ceil_divide(x1: BigUInt, x2: BigUInt) -> BigUInt
# floor_modulo(x1: BigUInt, x2: BigUInt) -> BigUInt
# truncate_modulo(x1: BigUInt, x2: BigUInt) -> BigUInt
# ceil_modulo(x1: BigUInt, x2: BigUInt) -> BigUInt
# divmod(x1: BigUInt, x2: BigUInt) -> Tuple[BigUInt, BigUInt]
# scale_up_by_power_of_10(x: BigUInt, n: Int) -> BigUInt
# floor_divide_general(x1: BigUInt, x2: BigUInt) -> BigUInt
# floor_divide_partition(x1: BigUInt, x2: BigUInt) -> BigUInt
# floor_divide_inplace_by_single_word(x1: BigUInt, x2: BigUInt) -> None
# floor_divide_inplace_by_double_words(x1: BigUInt, x2: BigUInt) -> None
# floor_divide_inplace_by_2(x: BigUInt) -> None
# scale_down_by_power_of_10(x: BigUInt, n: Int) -> BigUInt
# estimate_quotient(x1: BigUInt, x2: BigUInt, j: Int, m: Int) -> UInt64
# shift_words_left(x: BigUInt, j: Int) -> BigUInt
# power_of_10(n: Int) -> BigUInt
# ===----------------------------------------------------------------------=== #

# ===----------------------------------------------------------------------=== #
# Arithmetic Operations
# add, subtract, negative, absolute, multiply, floor_divide, modulo
Expand Down Expand Up @@ -75,7 +103,7 @@ fn add(x1: BigUInt, x2: BigUInt) raises -> BigUInt:

var carry: UInt32 = 0
var ith: Int = 0
var sum_of_words: UInt32 = 0
var sum_of_words: UInt32

# Add corresponding words from both numbers
while ith < len(x1.words) or ith < len(x2.words):
Expand All @@ -102,7 +130,7 @@ fn add(x1: BigUInt, x2: BigUInt) raises -> BigUInt:
return BigUInt(words=words^)


fn add_inplace(mut x1: BigUInt, x2: BigUInt) raises:
fn add_inplace(mut x1: BigUInt, x2: BigUInt) raises -> None:
"""Increments a BigUInt number by another BigUInt number in place.

Args:
Expand Down Expand Up @@ -134,7 +162,7 @@ fn add_inplace(mut x1: BigUInt, x2: BigUInt) raises:

var carry: UInt32 = 0
var ith: Int = 0
var sum_of_words: UInt32 = 0
var sum_of_words: UInt32
var x1_len = len(x1.words)

while ith < x1_len or ith < len(x2.words):
Expand Down Expand Up @@ -164,7 +192,7 @@ fn add_inplace(mut x1: BigUInt, x2: BigUInt) raises:
return


fn add_inplace_by_1(mut x: BigUInt) raises:
fn add_inplace_by_1(mut x: BigUInt) raises -> None:
"""Increments a BigUInt number by 1."""
var i = 0
while i < len(x.words):
Expand Down Expand Up @@ -211,7 +239,7 @@ fn subtract(x1: BigUInt, x2: BigUInt) raises -> BigUInt:
var words = List[UInt32](capacity=max(len(x1.words), len(x2.words)))
var borrow: Int32 = 0
var ith: Int = 0
var difference: Int32 = 0 # Int32 is sufficient for the difference
var difference: Int32 # Int32 is sufficient for the difference

while ith < len(x1.words):
# Subtract the borrow
Expand Down Expand Up @@ -294,7 +322,7 @@ fn multiply(x1: BigUInt, x2: BigUInt) raises -> BigUInt:
# x1 = x1[0] + x1[1] * 10^9
# x2 = x2[0] + x2[1] * 10^9
# x1 * x2 = x1[0] * x2[0] + (x1[0] * x2[1] + x1[1] * x2[0]) * 10^9 + x1[1] * x2[1] * 10^18
var carry: UInt64 = 0
var carry: UInt64
for i in range(len(x1.words)):
# Skip if the word is zero
if x1.words[i] == 0:
Expand Down Expand Up @@ -769,7 +797,7 @@ fn floor_divide_partition(x1: BigUInt, x2: BigUInt) raises -> BigUInt:
var number_of_words_remainder = len(x1.words) % len(x2.words)
var number_of_words_dividend: Int
var result = x1
result.words.resize(len(x1.words) - number_of_words_remainder)
result.words.resize(len(x1.words) - number_of_words_remainder, UInt32(0))
var remainder = BigUInt(List[UInt32](capacity=len(x2.words)))
for i in range(len(x1.words) - number_of_words_remainder, len(x1.words)):
remainder.words.append(x1.words[i])
Expand Down Expand Up @@ -804,7 +832,9 @@ fn floor_divide_partition(x1: BigUInt, x2: BigUInt) raises -> BigUInt:
return result^


fn floor_divide_inplace_by_single_word(mut x1: BigUInt, x2: BigUInt) raises:
fn floor_divide_inplace_by_single_word(
mut x1: BigUInt, x2: BigUInt
) raises -> None:
"""Divides a BigUInt by a single word divisor in-place.

Args:
Expand All @@ -826,7 +856,9 @@ fn floor_divide_inplace_by_single_word(mut x1: BigUInt, x2: BigUInt) raises:
x1.remove_leading_empty_words()


fn floor_divide_inplace_by_double_words(mut x1: BigUInt, x2: BigUInt) raises:
fn floor_divide_inplace_by_double_words(
mut x1: BigUInt, x2: BigUInt
) raises -> None:
"""Divides a BigUInt by double-word divisor in-place.

Args:
Expand All @@ -846,7 +878,7 @@ fn floor_divide_inplace_by_double_words(mut x1: BigUInt, x2: BigUInt) raises:
var carry = UInt128(0)
if len(x1.words) % 2 == 1:
carry = UInt128(x1.words[-1])
x1.words.resize(len(x1.words) - 1)
x1.words.resize(len(x1.words) - 1, UInt32(0))

for i in range(len(x1.words) - 1, -1, -2):
var dividend = carry * UInt128(1_000_000_000_000_000_000) + UInt128(
Expand All @@ -861,7 +893,7 @@ fn floor_divide_inplace_by_double_words(mut x1: BigUInt, x2: BigUInt) raises:
return


fn floor_divide_inplace_by_2(mut x: BigUInt):
fn floor_divide_inplace_by_2(mut x: BigUInt) -> None:
"""Divides a BigUInt by 2 in-place.

Args:
Expand All @@ -880,7 +912,7 @@ fn floor_divide_inplace_by_2(mut x: BigUInt):

# Remove leading zeros
while len(x.words) > 1 and x.words[len(x.words) - 1] == 0:
x.words.resize(len(x.words) - 1)
x.words.resize(len(x.words) - 1, UInt32(0))


fn scale_down_by_power_of_10(x: BigUInt, n: Int) raises -> BigUInt:
Expand Down
13 changes: 6 additions & 7 deletions src/decimojo/biguint/biguint.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ struct BigUInt(Absable, IntableRaising, Writable):
raise Error(
"Error in `from_string`: The number is not an integer."
)
coef.resize(len(coef) - scale)
coef.resize(len(coef) - scale, UInt8(0))
scale = 0

var number_of_digits = len(coef) - scale
Expand Down Expand Up @@ -822,9 +822,9 @@ struct BigUInt(Absable, IntableRaising, Writable):
else:
ndigits = 3
print(
"word {}:{}{}".format(
i, " " * (10 - ndigits), String(self.words[i])
).rjust(9, fillchar="0")
String("word {}:{}{}")
.format(i, " " * (10 - ndigits), String(self.words[i]))
.rjust(9, fillchar="0")
)
print("----------------------------------------------")

Expand Down Expand Up @@ -893,10 +893,9 @@ struct BigUInt(Absable, IntableRaising, Writable):
if word_index >= len(self.words):
return 0
var word = self.words[word_index]
var digit: UInt32 = 0
for _ in range(digit_index):
word = word // 10
digit = word % 10
var digit = word % 10
return UInt8(digit)

@always_inline
Expand Down Expand Up @@ -941,7 +940,7 @@ struct BigUInt(Absable, IntableRaising, Writable):
fn remove_leading_empty_words(mut self):
"""Removes leading words of 0 from BigUInt's internal representation."""
while len(self.words) > 1 and self.words[-1] == 0:
self.words.resize(len(self.words) - 1)
self.words.resize(len(self.words) - 1, UInt32(0))

@always_inline
fn remove_trailing_digits_with_rounding(
Expand Down
32 changes: 17 additions & 15 deletions src/decimojo/decimal/arithmetics.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,6 @@ fn multiply(x1: Decimal, x2: Decimal) raises -> Decimal:
var x1_scale = x1.scale()
var x2_scale = x2.scale()
var combined_scale = x1_scale + x2_scale
"""Combined scale of the two operands."""
var is_negative = x1.is_negative() != x2.is_negative()

# SPECIAL CASE: true one
Expand Down Expand Up @@ -510,8 +509,10 @@ fn multiply(x1: Decimal, x2: Decimal) raises -> Decimal:
var prod: UInt128 = UInt128(x1_coef) * UInt128(x2_coef)
if prod > Decimal.MAX_AS_UINT128:
raise Error(
"Error in `multiply()`: The product is {}, which exceeds"
" the capacity of Decimal (2^96-1)".format(prod)
String(
"Error in `multiply()`: The product is {}, which"
" exceeds the capacity of Decimal (2^96-1)"
).format(prod)
)
else:
return Decimal.from_uint128(prod, 0, is_negative)
Expand All @@ -520,8 +521,10 @@ fn multiply(x1: Decimal, x2: Decimal) raises -> Decimal:
else:
var prod: UInt256 = UInt256(x1_coef) * UInt256(x2_coef)
raise Error(
"Error in `multiply()`: The product is {}, which exceeds the"
" capacity of Decimal (2^96-1)".format(prod)
String(
"Error in `multiply()`: The product is {}, which exceeds"
" the capacity of Decimal (2^96-1)"
).format(prod)
)

# SPECIAL CASE: Both operands are integers but with scales
Expand Down Expand Up @@ -963,13 +966,9 @@ fn divide(x1: Decimal, x2: Decimal) raises -> Decimal:
# 但我們只能算到 1.0000000000000000000000000000_5,
# 在銀行家捨去法中,我們將捨去項爲5時,向上捨去, 保留28位後爲1.0000000000000000000000000000
# 這樣的捨去法是不準確的,所以我們一律在到達餘數非零且捨去項爲5時,向上捨去
var is_exact_division: Bool = False
if rem == 0:
is_exact_division = True
else:
if digit == 5:
# Not exact division, round up the last digit
quot += 1
if (digit == 5) and (rem != 0):
# Not exact division, round up the last digit
quot += 1

var scale_of_quot = step_counter + diff_scale + adjusted_scale

Expand All @@ -980,6 +979,12 @@ fn divide(x1: Decimal, x2: Decimal) raises -> Decimal:
var ndigits_quot = decimojo.utility.number_of_digits(quot)
var ndigits_quot_int_part = ndigits_quot - scale_of_quot

print(
String(
"quot: {}, rem: {}, step_counter: {}, scale_of_quot: {}"
).format(quot, rem, step_counter, scale_of_quot)
)

# TODO: 可以考慮先降 scale 再判斷是否超出最大值.
# TODO: 爲降 scale 引入 round_to_remove_last_n_digits 函數
# If quot is within MAX, return the result
Expand Down Expand Up @@ -1062,9 +1067,6 @@ fn divide(x1: Decimal, x2: Decimal) raises -> Decimal:
step_counter += 1
# Check if division is exact

var is_exact_division: Bool = False
if rem256 == 0:
is_exact_division = True
else:
if digit == 5:
# Not exact division, round up the last digit
Expand Down
Loading