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
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ magic.lock
.helix
# Temporary files
tempCodeRunnerFile.mojo
/temp*.mojo
temp.md
temp*.mojo
kgen.trace.json*
# macOS environments
.DS_Store
Expand Down
24 changes: 12 additions & 12 deletions pixi.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,39 +6,39 @@ license = "Apache-2.0"
name = "decimojo"
platforms = ["osx-arm64", "linux-64"]
readme = "README.md"
version = "0.5.0"
version = "0.6.0"

[dependencies]
mojo = "==25.5"
mojo = "==0.25.6"

[tasks]
# format the code
format = "pixi run mojo format ./src && pixi run mojo format ./benches && pixi run mojo format ./tests && pixi run mojo format ./docs"

# compile the package
p = "clear && pixi run package"
package = "pixi run format && pixi run package_decimojo && pixi run package_tomlmojo"
package_decimojo = "pixi run mojo package src/decimojo && cp decimojo.mojopkg tests/ && cp decimojo.mojopkg benches/ && rm decimojo.mojopkg"
package_tomlmojo = "pixi run mojo package src/tomlmojo && mv tomlmojo.mojopkg tests/"
package = "pixi run format && pixi run package_decimojo && pixi run package_tomlmojo"
p = "clear && pixi run package"

# clean the package files in tests folder
clean = "rm tests/decimojo.mojopkg && rm benches/decimojo.mojopkg && rm tests/tomlmojo.mojopkg"
c = "clear && pixi run clean"
clean = "rm tests/decimojo.mojopkg && rm benches/decimojo.mojopkg && rm tests/tomlmojo.mojopkg"

# tests (use the mojo testing tool)
test = "pixi run package && pixi run mojo test tests -D ASSERT=all --filter"
t = "clear && pixi run package && pixi run mojo test tests -D ASSERT=all --filter"
b = "pixi run t big"
t = "clear && pixi run package && pixi run mojo test tests -D ASSERT=all --filter"
test = "pixi run package && pixi run mojo test tests -D ASSERT=all --filter"

# benches
dec = "clear && pixi run package && cd benches/decimal && pixi run mojo run -I ../ bench.mojo && cd ../.. && pixi run clean"
bint = "clear && pixi run package && cd benches/bigint && pixi run mojo run -I ../ bench.mojo && cd ../.. && pixi run clean"
buint = "clear && pixi run package && cd benches/biguint && pixi run mojo run -I ../ bench.mojo && cd ../.. && pixi run clean"
bdec = "clear && pixi run package && cd benches/bigdecimal && pixi run mojo run -I ../ bench.mojo && cd ../.. && pixi run clean"
dec_debug = "clear && pixi run package && cd benches/decimal && pixi run mojo run -I ../ -D ASSERT=all bench.mojo && cd ../.. && pixi run clean"
bdec_debug = "clear && pixi run package && cd benches/bigdecimal && pixi run mojo run -I ../ -D ASSERT=all bench.mojo && cd ../.. && pixi run clean"
bint = "clear && pixi run package && cd benches/bigint && pixi run mojo run -I ../ bench.mojo && cd ../.. && pixi run clean"
bint_debug = "clear && pixi run package && cd benches/bigint && pixi run mojo run -I ../ -D ASSERT=all bench.mojo && cd ../.. && pixi run clean"
buint = "clear && pixi run package && cd benches/biguint && pixi run mojo run -I ../ bench.mojo && cd ../.. && pixi run clean"
buint_debug = "clear && pixi run package && cd benches/biguint && pixi run mojo run -I ../ -D ASSERT=all bench.mojo && cd ../.. && pixi run clean"
bdec_debug = "clear && pixi run package && cd benches/bigdecimal && pixi run mojo run -I ../ -D ASSERT=all bench.mojo && cd ../.. && pixi run clean"
dec = "clear && pixi run package && cd benches/decimal && pixi run mojo run -I ../ bench.mojo && cd ../.. && pixi run clean"
dec_debug = "clear && pixi run package && cd benches/decimal && pixi run mojo run -I ../ -D ASSERT=all bench.mojo && cd ../.. && pixi run clean"

# doc
doc = "clear && pixi run mojo doc -o docs/doc.json --diagnose-missing-doc-strings --validate-doc-strings src/decimojo"
30 changes: 17 additions & 13 deletions src/decimojo/bigdecimal/arithmetics.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ fn add(x1: BigDecimal, x2: BigDecimal) raises -> BigDecimal:
if x1.coefficient.is_zero():
if x2.coefficient.is_zero():
return BigDecimal(
coefficient=BigUInt.ZERO,
coefficient=BigUInt.zero(),
scale=max_scale,
sign=False,
)
Expand Down Expand Up @@ -86,7 +86,9 @@ fn add(x1: BigDecimal, x2: BigDecimal) raises -> BigDecimal:
return BigDecimal(coefficient=coef2^, scale=max_scale, sign=x2.sign)
else:
# |x1| == |x2|, signs differ, result is 0
return BigDecimal(coefficient=BigUInt.ZERO, scale=max_scale, sign=False)
return BigDecimal(
coefficient=BigUInt.zero(), scale=max_scale, sign=False
)


fn subtract(x1: BigDecimal, x2: BigDecimal) raises -> BigDecimal:
Expand Down Expand Up @@ -114,7 +116,7 @@ fn subtract(x1: BigDecimal, x2: BigDecimal) raises -> BigDecimal:
if x2.coefficient.is_zero():
if x1.coefficient.is_zero():
return BigDecimal(
coefficient=BigUInt.ZERO,
coefficient=BigUInt.zero(),
scale=max_scale,
sign=False,
)
Expand Down Expand Up @@ -146,7 +148,9 @@ fn subtract(x1: BigDecimal, x2: BigDecimal) raises -> BigDecimal:
return BigDecimal(coefficient=coef2^, scale=max_scale, sign=not x1.sign)
else:
# |x1| == |x2|, result is 0
return BigDecimal(coefficient=BigUInt.ZERO, scale=max_scale, sign=False)
return BigDecimal(
coefficient=BigUInt.zero(), scale=max_scale, sign=False
)


fn multiply(x1: BigDecimal, x2: BigDecimal) -> BigDecimal:
Expand All @@ -168,7 +172,7 @@ fn multiply(x1: BigDecimal, x2: BigDecimal) -> BigDecimal:
# Handle zero operands as special cases for efficiency
if x1.coefficient.is_zero() or x2.coefficient.is_zero():
return BigDecimal(
coefficient=BigUInt.ZERO,
coefficient=BigUInt.zero(),
scale=x1.scale + x2.scale,
sign=x1.sign != x2.sign,
)
Expand Down Expand Up @@ -211,7 +215,7 @@ fn true_divide(
# Handle dividend of zero
if x.coefficient.is_zero():
return BigDecimal(
coefficient=BigUInt.ZERO,
coefficient=BigUInt.zero(),
scale=x.scale - y.scale,
sign=x.sign != y.sign,
)
Expand Down Expand Up @@ -273,7 +277,7 @@ fn true_divide_fast(
x.coefficient, -extra_words * 9
)
else:
coef_x = x.coefficient
coef_x = x.coefficient.copy()

var coef = coef_x // y.coefficient
var scale = x.scale + extra_digits - y.scale
Expand Down Expand Up @@ -334,7 +338,7 @@ fn true_divide_general(
x.coefficient, extra_words
)
else:
coef_x = x.coefficient
coef_x = x.coefficient.copy()

var coef = coef_x // y.coefficient
if coef * y.coefficient == coef_x:
Expand All @@ -359,7 +363,7 @@ fn true_divide_general(
)
result.round_to_precision(
precision,
RoundingMode.ROUND_HALF_EVEN,
RoundingMode.half_even(),
remove_extra_digit_due_to_rounding=True,
fill_zeros_to_precision=False,
)
Expand Down Expand Up @@ -394,7 +398,7 @@ fn true_divide_inexact(
# Handle dividend of zero
if x1.coefficient.is_zero():
return BigDecimal(
coefficient=BigUInt.ZERO,
coefficient=BigUInt.zero(),
scale=number_of_significant_digits,
sign=x1.sign != x2.sign,
)
Expand All @@ -410,7 +414,7 @@ fn true_divide_inexact(
buffer_digits = max(0, buffer_digits)

# Scale up the dividend to ensure sufficient precision
var scaled_x1 = x1.coefficient
var scaled_x1 = x1.coefficient.copy()
if buffer_digits > 0:
scaled_x1.multiply_inplace_by_power_of_ten(buffer_digits)

Expand All @@ -423,7 +427,7 @@ fn true_divide_inexact(
var digits_to_remove = result_digits - number_of_significant_digits
quotient = quotient.remove_trailing_digits_with_rounding(
digits_to_remove,
RoundingMode.ROUND_DOWN,
RoundingMode.down(),
remove_extra_digit_due_to_rounding=False,
)
# Adjust the scale accordingly
Expand Down Expand Up @@ -459,7 +463,7 @@ fn truncate_divide(x1: BigDecimal, x2: BigDecimal) raises -> BigDecimal:

# Handle dividend of zero
if x1.coefficient.is_zero():
return BigDecimal(BigUInt.ZERO, 0, False)
return BigDecimal(BigUInt.zero(), 0, False)

# Calculate adjusted scales to align decimal points
var scale_diff = x1.scale - x2.scale
Expand Down
32 changes: 16 additions & 16 deletions src/decimojo/bigdecimal/bigdecimal.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -101,20 +101,20 @@ struct BigDecimal(
@implicit
fn __init__(out self, coefficient: BigUInt):
"""Constructs a BigDecimal from a BigUInt object."""
self.coefficient = coefficient
self.coefficient = coefficient.copy()
self.scale = 0
self.sign = False

fn __init__(out self, coefficient: BigUInt, scale: Int, sign: Bool):
"""Constructs a BigDecimal from its components."""
self.coefficient = coefficient
self.coefficient = coefficient.copy()
self.scale = scale
self.sign = sign

@implicit
fn __init__(out self, value: BigInt):
"""Constructs a BigDecimal from a big interger."""
self.coefficient = value.magnitude
self.coefficient = value.magnitude.copy()
self.scale = 0
self.sign = value.sign

Expand Down Expand Up @@ -205,7 +205,7 @@ struct BigDecimal(
fn from_int(value: Int) -> Self:
"""Creates a BigDecimal from an integer."""
if value == 0:
return Self(coefficient=BigUInt.ZERO, scale=0, sign=False)
return Self(coefficient=BigUInt.zero(), scale=0, sign=False)

var words = List[UInt32](capacity=2)
var sign: Bool
Expand Down Expand Up @@ -255,7 +255,7 @@ struct BigDecimal(
constrained[dtype.is_integral(), "dtype must be integral."]()

if value == 0:
return Self(coefficient=BigUInt.ZERO, scale=0, sign=False)
return Self(coefficient=BigUInt.zero(), scale=0, sign=False)

return Self(
coefficient=BigUInt.from_absolute_integral_scalar(value),
Expand Down Expand Up @@ -284,7 +284,7 @@ struct BigDecimal(
]()

if value == 0:
return Self(coefficient=BigUInt.ZERO, scale=0, sign=False)
return Self(coefficient=BigUInt.zero(), scale=0, sign=False)

if value != value: # Check for NaN
raise Error("`from_scalar()`: Cannot convert NaN to BigUInt")
Expand All @@ -308,10 +308,10 @@ struct BigDecimal(
Returns:
The BigDecimal representation of the string.
"""
var coef: List[UInt8]
var scale: Int
var sign: Bool
coef, scale, sign = decimojo.str.parse_numeric_string(value)
_tuple = decimojo.str.parse_numeric_string(value)
var ref coef: List[UInt8] = _tuple[0]
var scale: Int = _tuple[1]
var sign: Bool = _tuple[2]

var number_of_digits = len(coef)
var number_of_words = number_of_digits // 9
Expand Down Expand Up @@ -664,10 +664,10 @@ struct BigDecimal(
return decimojo.bigdecimal.rounding.round(
self,
ndigits=ndigits,
rounding_mode=RoundingMode.ROUND_HALF_EVEN,
rounding_mode=RoundingMode.half_even(),
)
except e:
return self
return self.copy()

@always_inline
fn __round__(self) -> Self:
Expand All @@ -677,10 +677,10 @@ struct BigDecimal(
"""
try:
return decimojo.bigdecimal.rounding.round(
self, ndigits=0, rounding_mode=RoundingMode.ROUND_HALF_EVEN
self, ndigits=0, rounding_mode=RoundingMode.half_even()
)
except e:
return self
return self.copy()

# ===------------------------------------------------------------------=== #
# Other dunders
Expand Down Expand Up @@ -731,7 +731,7 @@ struct BigDecimal(
fn e(precision: Int) raises -> Self:
"""Returns the mathematical constant e to the specified precision."""
return decimojo.bigdecimal.exponential.exp(
x=Self(BigUInt.ONE), precision=precision
x=Self(BigUInt.one()), precision=precision
)

# === Exponentional operations === #
Expand Down Expand Up @@ -951,7 +951,7 @@ struct BigDecimal(
)

if precision_diff <= 0:
return self
return self.copy()

return Self(
decimojo.biguint.arithmetics.multiply_by_power_of_ten(
Expand Down
8 changes: 4 additions & 4 deletions src/decimojo/bigdecimal/comparison.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -143,12 +143,12 @@ fn greater_than_or_equal(x1: BigDecimal, x2: BigDecimal) -> Bool:
fn max(x1: BigDecimal, x2: BigDecimal) -> BigDecimal:
"""Returns the maximum of x1 and x2."""
if compare(x1, x2) >= 0:
return x1
return x2
return x1.copy()
return x2.copy()


fn min(x1: BigDecimal, x2: BigDecimal) -> BigDecimal:
"""Returns the minimum of x1 and x2."""
if compare(x1, x2) <= 0:
return x1
return x2
return x1.copy()
return x2.copy()
19 changes: 11 additions & 8 deletions src/decimojo/bigdecimal/constants.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -176,13 +176,16 @@ fn pi(precision: Int) raises -> BigDecimal:
return pi_chudnovsky_binary_split(precision)


@fieldwise_init
struct Rational:
"""Represents a rational number p/q for exact arithmetic."""

var p: BigInt # numerator
var q: BigInt # denominator

fn __init__(out self, p: BigInt, q: BigInt):
self.p = p.copy()
self.q = q.copy()


fn pi_chudnovsky_binary_split(precision: Int) raises -> BigDecimal:
"""Calculates π using Chudnovsky algorithm with binary splitting.
Expand Down Expand Up @@ -218,7 +221,7 @@ fn pi_chudnovsky_binary_split(precision: Int) raises -> BigDecimal:

result.round_to_precision(
precision,
RoundingMode.ROUND_HALF_EVEN,
RoundingMode.half_even(),
remove_extra_digit_due_to_rounding=True,
fill_zeros_to_precision=False,
)
Expand All @@ -244,7 +247,7 @@ fn chudnovsky_split(a: Int, b: Int, precision: Int) raises -> Rational:
var l_k = bint_545140134 * BigInt(a) + bint_13591409

# X(k) = (-262537412640768000)^k
var x_k = bint_1
var x_k = bint_1^
for _ in range(a):
x_k *= bint_262537412640768000

Expand All @@ -256,7 +259,7 @@ fn chudnovsky_split(a: Int, b: Int, precision: Int) raises -> Rational:
var term_p = m_k_rational.p * l_k
var term_q = m_k_rational.q * x_k

return Rational(term_p, term_q)
return Rational(term_p^, term_q^)

# Recursive case: split range in half
var mid = (a + b) // 2
Expand All @@ -267,7 +270,7 @@ fn chudnovsky_split(a: Int, b: Int, precision: Int) raises -> Rational:
var combined_p = left.p * right.q + right.p * left.q
var combined_q = left.q * right.q

return Rational(combined_p, combined_q)
return Rational(combined_p^, combined_q^)


fn compute_m_k_rational(k: Int) raises -> Rational:
Expand All @@ -279,12 +282,12 @@ fn compute_m_k_rational(k: Int) raises -> Rational:
return Rational(bint_1, bint_1)

# Compute numerator: (6k)! / (3k)! = (3k+1) * (3k+2) * ... * (6k)
var numerator = bint_1
var numerator = bint_1.copy()
for i in range(3 * k + 1, 6 * k + 1):
numerator *= BigInt(i)

# Compute denominator: (k!)³
var k_factorial = bint_1
var k_factorial = bint_1.copy()
for i in range(1, k + 1):
k_factorial *= BigInt(i)

Expand Down Expand Up @@ -321,7 +324,7 @@ fn pi_machin(precision: Int) raises -> BigDecimal:

result.round_to_precision(
precision,
RoundingMode.ROUND_HALF_EVEN,
RoundingMode.half_even(),
remove_extra_digit_due_to_rounding=True,
fill_zeros_to_precision=False,
)
Expand Down
Loading