diff --git a/.gitignore b/.gitignore index 4d788aa..4256700 100644 --- a/.gitignore +++ b/.gitignore @@ -13,7 +13,8 @@ magic.lock .helix # Temporary files tempCodeRunnerFile.mojo -/temp*.mojo +temp.md +temp*.mojo kgen.trace.json* # macOS environments .DS_Store diff --git a/pixi.toml b/pixi.toml index c5cb959..dac41ce 100644 --- a/pixi.toml +++ b/pixi.toml @@ -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" diff --git a/src/decimojo/bigdecimal/arithmetics.mojo b/src/decimojo/bigdecimal/arithmetics.mojo index 17ea1dc..595a4d7 100644 --- a/src/decimojo/bigdecimal/arithmetics.mojo +++ b/src/decimojo/bigdecimal/arithmetics.mojo @@ -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, ) @@ -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: @@ -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, ) @@ -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: @@ -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, ) @@ -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, ) @@ -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 @@ -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: @@ -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, ) @@ -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, ) @@ -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) @@ -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 @@ -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 diff --git a/src/decimojo/bigdecimal/bigdecimal.mojo b/src/decimojo/bigdecimal/bigdecimal.mojo index f4cb08f..0b9e4eb 100644 --- a/src/decimojo/bigdecimal/bigdecimal.mojo +++ b/src/decimojo/bigdecimal/bigdecimal.mojo @@ -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 @@ -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 @@ -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), @@ -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") @@ -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 @@ -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: @@ -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 @@ -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 === # @@ -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( diff --git a/src/decimojo/bigdecimal/comparison.mojo b/src/decimojo/bigdecimal/comparison.mojo index 21ec7ea..baff1d1 100644 --- a/src/decimojo/bigdecimal/comparison.mojo +++ b/src/decimojo/bigdecimal/comparison.mojo @@ -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() diff --git a/src/decimojo/bigdecimal/constants.mojo b/src/decimojo/bigdecimal/constants.mojo index e3c2e15..c0f31a6 100644 --- a/src/decimojo/bigdecimal/constants.mojo +++ b/src/decimojo/bigdecimal/constants.mojo @@ -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. @@ -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, ) @@ -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 @@ -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 @@ -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: @@ -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) @@ -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, ) diff --git a/src/decimojo/bigdecimal/exponential.mojo b/src/decimojo/bigdecimal/exponential.mojo index bae5365..c07f87f 100644 --- a/src/decimojo/bigdecimal/exponential.mojo +++ b/src/decimojo/bigdecimal/exponential.mojo @@ -81,20 +81,20 @@ fn power( " base)" ) else: - return BigDecimal(BigUInt.ZERO, 0, False) + return BigDecimal(BigUInt.zero(), 0, False) if exponent.coefficient.is_zero(): - return BigDecimal(BigUInt.ONE, 0, False) # x^0 = 1 + return BigDecimal(BigUInt.one(), 0, False) # x^0 = 1 - if base == BigDecimal(BigUInt.ONE, 0, False): - return BigDecimal(BigUInt.ONE, 0, False) # 1^y = 1 + if base == BigDecimal(BigUInt.one(), 0, False): + return BigDecimal(BigUInt.one(), 0, False) # 1^y = 1 - if exponent == BigDecimal(BigUInt.ONE, 0, False): + if exponent == BigDecimal(BigUInt.one(), 0, False): # return base # x^1 = x - var result = base + var result = base.copy() result.round_to_precision( precision, - rounding_mode=RoundingMode.ROUND_HALF_EVEN, + rounding_mode=RoundingMode.half_even(), remove_extra_digit_due_to_rounding=True, fill_zeros_to_precision=False, ) @@ -124,7 +124,7 @@ fn power( exp_result.round_to_precision( precision, - rounding_mode=RoundingMode.ROUND_HALF_EVEN, + rounding_mode=RoundingMode.half_even(), remove_extra_digit_due_to_rounding=True, fill_zeros_to_precision=False, ) @@ -152,25 +152,25 @@ fn integer_power( abs_exp.scale ) elif abs_exp.scale == 0: - exp_value = abs_exp.coefficient + exp_value = abs_exp.coefficient.copy() else: exp_value = abs_exp.coefficient.multiply_by_power_of_ten(-abs_exp.scale) - var result = BigDecimal(BigUInt.ONE, 0, False) - var current_power = base + var result = BigDecimal(BigUInt.one(), 0, False) + var current_power = base.copy() # Handle negative exponent: result will be 1/positive_power var is_negative_exponent = exponent.sign # Binary exponentiation algorithm: x^n = (x^2)^(n/2) if n is even - while exp_value > BigUInt.ZERO: + while exp_value > BigUInt.zero(): if exp_value.words[0] % 2 == 1: # If current bit is set, multiply result by current power result = result * current_power # Round to avoid coefficient explosion result.round_to_precision( working_precision, - rounding_mode=RoundingMode.ROUND_DOWN, + rounding_mode=RoundingMode.down(), remove_extra_digit_due_to_rounding=False, fill_zeros_to_precision=False, ) @@ -179,7 +179,7 @@ fn integer_power( # Round to avoid coefficient explosion current_power.round_to_precision( working_precision, - rounding_mode=RoundingMode.ROUND_DOWN, + rounding_mode=RoundingMode.down(), remove_extra_digit_due_to_rounding=False, fill_zeros_to_precision=False, ) @@ -188,13 +188,13 @@ fn integer_power( # For negative exponents, compute reciprocal if is_negative_exponent: - result = BigDecimal(BigUInt.ONE, 0, False).true_divide( + result = BigDecimal(BigUInt.one(), 0, False).true_divide( result, working_precision ) result.round_to_precision( precision, - rounding_mode=RoundingMode.ROUND_HALF_EVEN, + rounding_mode=RoundingMode.half_even(), remove_extra_digit_due_to_rounding=False, fill_zeros_to_precision=False, ) @@ -231,11 +231,9 @@ fn root(x: BigDecimal, n: BigDecimal, precision: Int) raises -> BigDecimal: if not n.sign: if n.is_integer(): return integer_root(x, n, precision) - var is_integer_reciprocal: Bool - var integer_reciprocal: BigDecimal - is_integer_reciprocal, integer_reciprocal = ( - is_integer_reciprocal_and_return(n) - ) + _tuple = is_integer_reciprocal_and_return(n) + var is_integer_reciprocal: Bool = _tuple[0] + var ref integer_reciprocal: BigDecimal = _tuple[1] if is_integer_reciprocal: # If m = 1/n is an integer, use integer_root return integer_power(x, integer_reciprocal, precision) @@ -243,17 +241,17 @@ fn root(x: BigDecimal, n: BigDecimal, precision: Int) raises -> BigDecimal: # Handle negative n as 1/(x^(1/|n|)) if n.sign: var positive_root = root(x, -n, working_precision) - var result = BigDecimal(BigUInt.ONE, 0, False).true_divide( + var result = BigDecimal(BigUInt.one(), 0, False).true_divide( positive_root, precision ) return result^ # Handle special cases for x if x.coefficient.is_zero(): - return BigDecimal(BigUInt.ZERO, 0, False) + return BigDecimal(BigUInt.zero(), 0, False) if x.is_one(): - return BigDecimal(BigUInt.ONE, 0, False) + return BigDecimal(BigUInt.one(), 0, False) # Check if x is negative - only odd integer roots of negative numbers are defined if x.sign: @@ -279,7 +277,7 @@ fn root(x: BigDecimal, n: BigDecimal, precision: Int) raises -> BigDecimal: result.round_to_precision( precision=precision, - rounding_mode=RoundingMode.ROUND_HALF_EVEN, + rounding_mode=RoundingMode.half_even(), remove_extra_digit_due_to_rounding=True, fill_zeros_to_precision=True, ) @@ -324,10 +322,10 @@ fn integer_root( # Special case: n = 1 (1st root is just the number itself) if n.is_one(): - var result = x + var result = x.copy() result.round_to_precision( precision, - rounding_mode=RoundingMode.ROUND_HALF_EVEN, + rounding_mode=RoundingMode.half_even(), remove_extra_digit_due_to_rounding=True, fill_zeros_to_precision=False, ) @@ -339,11 +337,11 @@ fn integer_root( # Handle special cases for x if x.coefficient.is_zero(): - return BigDecimal(BigUInt.ZERO, 0, False) + return BigDecimal(BigUInt.zero(), 0, False) # For x = 1, the result is always 1 if x.is_one(): - return BigDecimal(BigUInt.ONE, 0, False) + return BigDecimal(BigUInt.one(), 0, False) var result_sign = False # Check if x is negative @@ -353,7 +351,7 @@ fn integer_root( if n.scale > 0: n_uint = n.coefficient.floor_divide_by_power_of_ten(n.scale) else: # n.scale <= 0 - n_uint = n.coefficient + n_uint = n.coefficient.copy() if n_uint.words[0] % 2 == 1: # Odd root result_sign = True @@ -371,7 +369,7 @@ fn integer_root( result.round_to_precision( precision=precision, - rounding_mode=RoundingMode.ROUND_HALF_EVEN, + rounding_mode=RoundingMode.half_even(), remove_extra_digit_due_to_rounding=True, fill_zeros_to_precision=False, ) @@ -391,11 +389,11 @@ fn is_integer_reciprocal_and_return( True if 1/n is an odd integer, False otherwise. The integer reciprocal of n. """ - var m = BigDecimal(BigUInt.ONE, 0, False).true_divide( + var m = BigDecimal(BigUInt.one(), 0, False).true_divide( n, precision=n.coefficient.number_of_digits() + 9 ) - return Tuple(m.is_integer(), m) + return Tuple(m.is_integer(), m^) fn is_odd_reciprocal(n: BigDecimal) raises -> Bool: @@ -416,7 +414,7 @@ fn is_odd_reciprocal(n: BigDecimal) raises -> Bool: # If n is of form 1/m where m is an odd integer, then 1/n = m is odd # This is true when n = 1/m for odd integer m - var m = BigDecimal(BigUInt.ONE, 0, False).true_divide( + var m = BigDecimal(BigUInt.one(), 0, False).true_divide( n, precision=n.coefficient.number_of_digits() + 9 ) @@ -478,7 +476,7 @@ fn sqrt_decimal_approach(x: BigDecimal, precision: Int) raises -> BigDecimal: ) if x.coefficient.is_zero(): - return BigDecimal(BigUInt.ZERO, (x.scale + 1) // 2, False) + return BigDecimal(BigUInt.zero(), (x.scale + 1) // 2, False) # Initial guess # A decimal has coefficient and scale @@ -545,11 +543,11 @@ fn sqrt_decimal_approach(x: BigDecimal, precision: Int) raises -> BigDecimal: # Newton's method iterations # x_{n+1} = (x_n + N/x_n) / 2 - var prev_guess = BigDecimal(BigUInt.ZERO, 0, False) + var prev_guess = BigDecimal(BigUInt.zero(), 0, False) var iteration_count = 0 while guess != prev_guess and iteration_count < 100: - prev_guess = guess + prev_guess = guess.copy() var quotient = x.true_divide_inexact(guess, working_precision) var sum = guess + quotient guess = sum.true_divide(BigDecimal(BigUInt(2), 0, 0), working_precision) @@ -558,10 +556,10 @@ fn sqrt_decimal_approach(x: BigDecimal, precision: Int) raises -> BigDecimal: # Round to the desired precision var ndigits_to_remove = guess.coefficient.number_of_digits() - precision if ndigits_to_remove > 0: - var coefficient = guess.coefficient + var coefficient = guess.coefficient.copy() coefficient = coefficient.remove_trailing_digits_with_rounding( ndigits_to_remove, - rounding_mode=RoundingMode.ROUND_HALF_UP, + rounding_mode=RoundingMode.half_up(), remove_extra_digit_due_to_rounding=True, ) guess.coefficient = coefficient^ @@ -574,14 +572,14 @@ fn sqrt_decimal_approach(x: BigDecimal, precision: Int) raises -> BigDecimal: var guess_coefficient_without_trailing_zeros = ( guess.coefficient.remove_trailing_digits_with_rounding( guess.coefficient.number_of_trailing_zeros(), - rounding_mode=RoundingMode.ROUND_DOWN, + rounding_mode=RoundingMode.down(), remove_extra_digit_due_to_rounding=False, ) ) var x_coefficient_without_trailing_zeros = ( x.coefficient.remove_trailing_digits_with_rounding( x.coefficient.number_of_trailing_zeros(), - rounding_mode=RoundingMode.ROUND_DOWN, + rounding_mode=RoundingMode.down(), remove_extra_digit_due_to_rounding=False, ) ) @@ -594,7 +592,7 @@ fn sqrt_decimal_approach(x: BigDecimal, precision: Int) raises -> BigDecimal: ) // 2 guess.round_to_precision( precision=expected_ndigits_of_result, - rounding_mode=RoundingMode.ROUND_DOWN, + rounding_mode=RoundingMode.down(), remove_extra_digit_due_to_rounding=False, fill_zeros_to_precision=False, ) @@ -644,7 +642,7 @@ fn sqrt(x: BigDecimal, precision: Int) raises -> BigDecimal: ) if x.coefficient.is_zero(): - return BigDecimal(BigUInt.ZERO, (x.scale + 1) // 2, False) + return BigDecimal(BigUInt.zero(), (x.scale + 1) // 2, False) # STEP 1: Extend the coefficient by 10^(2p-s) var working_precision = precision + 9 # p @@ -660,7 +658,7 @@ fn sqrt(x: BigDecimal, precision: Int) raises -> BigDecimal: ) ) elif n_digits_to_extend == 0: - extended_coefficient = x.coefficient + extended_coefficient = x.coefficient.copy() else: # n_digits_to_extend < 0 extended_coefficient = ( decimojo.biguint.arithmetics.floor_divide_by_power_of_ten( @@ -693,7 +691,7 @@ fn sqrt(x: BigDecimal, precision: Int) raises -> BigDecimal: ) result.round_to_precision( precision=precision, - rounding_mode=RoundingMode.ROUND_HALF_UP, + rounding_mode=RoundingMode.half_up(), remove_extra_digit_due_to_rounding=True, fill_zeros_to_precision=False, ) @@ -750,7 +748,7 @@ fn exp(x: BigDecimal, precision: Int) raises -> BigDecimal: # Handle special cases if x.coefficient.is_zero(): return BigDecimal( - BigUInt.ONE, x.scale, x.sign + BigUInt.one(), x.scale, x.sign ) # e^0 = 1, return with same scale and sign # For very large positive values, result will overflow BigDecimal capacity @@ -761,21 +759,21 @@ fn exp(x: BigDecimal, precision: Int) raises -> BigDecimal: # For very large negative values, result will be effectively zero if x.sign and x.exponent() >= 20: # x < -10^20 - return BigDecimal(BigUInt.ZERO, precision, False) + return BigDecimal(BigUInt.zero(), precision, False) # Handle negative x using identity: exp(-x) = 1/exp(x) if x.sign: var pos_result = exp(-x, precision + 2) - return BigDecimal(BigUInt.ONE, 0, False).true_divide( + return BigDecimal(BigUInt.one(), 0, False).true_divide( pos_result, precision ) # Range reduction for faster convergence # If x >= 0.1, use exp(x) = exp(x/2)² - if x >= BigDecimal(BigUInt.ONE, 1, False): + if x >= BigDecimal(BigUInt.one(), 1, False): # var t_before_range_reduction = time.perf_counter_ns() var k = 0 - var threshold = BigDecimal(BigUInt.ONE, 0, False) + var threshold = BigDecimal(BigUInt.one(), 0, False) while threshold.exponent() <= x.exponent() + 1: threshold.coefficient = ( threshold.coefficient + threshold.coefficient @@ -796,14 +794,14 @@ fn exp(x: BigDecimal, precision: Int) raises -> BigDecimal: result = result * result result.round_to_precision( precision=working_precision, - rounding_mode=RoundingMode.ROUND_HALF_UP, + rounding_mode=RoundingMode.half_up(), remove_extra_digit_due_to_rounding=False, fill_zeros_to_precision=False, ) result.round_to_precision( precision=precision, - rounding_mode=RoundingMode.ROUND_HALF_EVEN, + rounding_mode=RoundingMode.half_even(), remove_extra_digit_due_to_rounding=False, fill_zeros_to_precision=False, ) @@ -833,7 +831,7 @@ fn exp(x: BigDecimal, precision: Int) raises -> BigDecimal: result.round_to_precision( precision=precision, - rounding_mode=RoundingMode.ROUND_HALF_EVEN, + rounding_mode=RoundingMode.half_even(), remove_extra_digit_due_to_rounding=True, fill_zeros_to_precision=False, ) @@ -867,9 +865,9 @@ fn exp_taylor_series( # print("DEBUG: x =", x) var max_number_of_terms = Int(minimum_precision * 2.5) + 1 - var result = BigDecimal(BigUInt.ONE, 0, False) - var term = BigDecimal(BigUInt.ONE, 0, False) - var n = BigUInt.ONE + var result = BigDecimal(BigUInt.one(), 0, False) + var term = BigDecimal(BigUInt.one(), 0, False) + var n = BigUInt.one() # Calculate Taylor series: 1 + x + x²/2! + x³/3! + ... for _ in range(1, max_number_of_terms): @@ -881,11 +879,11 @@ fn exp_taylor_series( term = term * add_on term.round_to_precision( precision=minimum_precision, - rounding_mode=RoundingMode.ROUND_HALF_UP, + rounding_mode=RoundingMode.half_up(), remove_extra_digit_due_to_rounding=False, fill_zeros_to_precision=False, ) - n += BigUInt.ONE + n += BigUInt.one() # Add term to result result += term @@ -898,7 +896,7 @@ fn exp_taylor_series( result.round_to_precision( precision=minimum_precision, - rounding_mode=RoundingMode.ROUND_HALF_UP, + rounding_mode=RoundingMode.half_up(), remove_extra_digit_due_to_rounding=False, fill_zeros_to_precision=False, ) @@ -935,8 +933,8 @@ fn ln(x: BigDecimal, precision: Int) raises -> BigDecimal: ) if x.coefficient.is_zero(): raise Error("Error in `ln`: Cannot compute logarithm of zero") - if x == BigDecimal(BigUInt.ONE, 0, False): - return BigDecimal(BigUInt.ZERO, 0, False) # ln(1) = 0 + if x == BigDecimal(BigUInt.one(), 0, False): + return BigDecimal(BigUInt.zero(), 0, False) # ln(1) = 0 # Range reduction to improve convergence # ln(x) = ln(m * 2^a * 5^b) = @@ -946,7 +944,7 @@ fn ln(x: BigDecimal, precision: Int) raises -> BigDecimal: # = ln(m) + (a+b*2)*ln(2) + b*ln(1.25) # where 0.5 <= m < 1.5 # Use Taylor series for ln(m) = ln(1+z) - var m = x + var m = x.copy() var power_of_2: Int = 0 var power_of_5: Int = 0 # First, scale down to [0.1, 1) @@ -975,7 +973,7 @@ fn ln(x: BigDecimal, precision: Int) raises -> BigDecimal: # Use series expansion for ln(m) = ln(1+z) = z - z²/2 + z³/3 - ... var result = ln_series_expansion( - m - BigDecimal(BigUInt.ONE, 0, False), working_precision + m - BigDecimal(BigUInt.one(), 0, False), working_precision ) # print("Result after series expansion:", result) @@ -999,7 +997,7 @@ fn ln(x: BigDecimal, precision: Int) raises -> BigDecimal: # Round to final precision result.round_to_precision( precision=precision, - rounding_mode=RoundingMode.ROUND_HALF_EVEN, + rounding_mode=RoundingMode.half_even(), remove_extra_digit_due_to_rounding=True, fill_zeros_to_precision=False, ) @@ -1049,10 +1047,10 @@ fn log(x: BigDecimal, base: BigDecimal, precision: Int) raises -> BigDecimal: x.coefficient.number_of_digits() == x.scale + 1 and x.coefficient.words[-1] == 1 ): - return BigDecimal(BigUInt.ZERO, 0, False) # log_base(1) = 0 + return BigDecimal(BigUInt.zero(), 0, False) # log_base(1) = 0 if x == base: - return BigDecimal(BigUInt.ONE, 0, False) # log_base(base) = 1 + return BigDecimal(BigUInt.one(), 0, False) # log_base(base) = 1 # Optimization for base 10 if ( @@ -1105,7 +1103,7 @@ fn log10(x: BigDecimal, precision: Int) raises -> BigDecimal: x.coefficient.number_of_digits() == x.scale + 1 and x.coefficient.words[-1] == 1 ): - return BigDecimal(BigUInt.ZERO, 0, False) # log10(1) = 0 + return BigDecimal(BigUInt.zero(), 0, False) # log10(1) = 0 # Use the identity: log10(x) = ln(x) / ln(10) var ln_result = ln(x, working_precision) @@ -1140,12 +1138,12 @@ fn ln_series_expansion( # print("DEBUG: ln_series_expansion for z =", z) if z.is_zero(): - return BigDecimal(BigUInt.ZERO, 0, False) + return BigDecimal(BigUInt.zero(), 0, False) var max_terms = Int(working_precision * 2.5) + 1 - var result = BigDecimal(BigUInt.ZERO, working_precision, False) - var term = z - var k = BigUInt.ONE + var result = BigDecimal(BigUInt.zero(), working_precision, False) + var term = z.copy() + var k = BigUInt.one() # Use the series ln(1+z) = z - z²/2 + z³/3 - z⁴/4 + ... result += term # First term is just x @@ -1155,10 +1153,10 @@ fn ln_series_expansion( for _ in range(2, max_terms): # Update for next iteration - multiply by z and divide by k term = term * z # z^k - k += BigUInt.ONE + k += BigUInt.one() # Alternate sign: -1^(k+1) = -1 when k is even, 1 when k is odd - var sign = k % BigUInt(2) == BigUInt.ZERO + var sign = k % BigUInt(2) == BigUInt.zero() var next_term = term.true_divide_inexact( BigDecimal(k, 0, False), working_precision ) @@ -1179,7 +1177,7 @@ fn ln_series_expansion( # print("DEBUG: ln_series_expansion result:", result) result.round_to_precision( precision=working_precision, - rounding_mode=RoundingMode.ROUND_DOWN, + rounding_mode=RoundingMode.down(), remove_extra_digit_due_to_rounding=False, fill_zeros_to_precision=False, ) @@ -1230,7 +1228,7 @@ fn compute_ln2(working_precision: Int) raises -> BigDecimal: ) result.round_to_precision( precision=working_precision, - rounding_mode=RoundingMode.ROUND_DOWN, + rounding_mode=RoundingMode.down(), remove_extra_digit_due_to_rounding=False, fill_zeros_to_precision=False, ) @@ -1242,11 +1240,11 @@ fn compute_ln2(working_precision: Int) raises -> BigDecimal: var words = List[UInt32](capacity=number_of_words) for _ in range(number_of_words): words.append(UInt32(333_333_333)) - var x = BigDecimal(BigUInt(words), number_of_words * 9, False) # x = 1/3 + var x = BigDecimal(BigUInt(words^), number_of_words * 9, False) # x = 1/3 - var result = BigDecimal(BigUInt.ZERO, 0, False) + var result = BigDecimal(BigUInt.zero(), 0, False) var term = x * BigDecimal(BigUInt(2), 0, False) # First term: 2*(1/3) - var k = BigDecimal(BigUInt.ONE, 0, False) + var k = BigDecimal(BigUInt.one(), 0, False) # Add terms: 2*(x + x³/3 + x⁵/5 + ...) for _ in range(1, max_terms): @@ -1259,7 +1257,7 @@ fn compute_ln2(working_precision: Int) raises -> BigDecimal: result.round_to_precision( precision=working_precision, - rounding_mode=RoundingMode.ROUND_DOWN, + rounding_mode=RoundingMode.down(), remove_extra_digit_due_to_rounding=False, fill_zeros_to_precision=False, ) diff --git a/src/decimojo/bigdecimal/rounding.mojo b/src/decimojo/bigdecimal/rounding.mojo index c0e7bfe..482fbc0 100644 --- a/src/decimojo/bigdecimal/rounding.mojo +++ b/src/decimojo/bigdecimal/rounding.mojo @@ -53,7 +53,7 @@ fn round( """ var ndigits_to_remove = number.scale - ndigits if ndigits_to_remove == 0: - return number + return number.copy() if ndigits_to_remove < 0: # Add trailing zeros to the number return number.extend_precision(precision_diff=-ndigits_to_remove) @@ -63,7 +63,7 @@ fn round( # If the number of digits to remove is greater than # the number of digits in the coefficient, return 0. return BigDecimal( - coefficient=BigUInt.ZERO, + coefficient=BigUInt.zero(), scale=ndigits, sign=number.sign, ) @@ -132,7 +132,7 @@ fn round_to_precision( number.coefficient = ( number.coefficient.remove_trailing_digits_with_rounding( ndigits=1, - rounding_mode=RoundingMode.ROUND_DOWN, + rounding_mode=RoundingMode.down(), remove_extra_digit_due_to_rounding=False, ) ) diff --git a/src/decimojo/bigdecimal/trigonometric.mojo b/src/decimojo/bigdecimal/trigonometric.mojo index caf78a2..1a3548a 100644 --- a/src/decimojo/bigdecimal/trigonometric.mojo +++ b/src/decimojo/bigdecimal/trigonometric.mojo @@ -56,7 +56,7 @@ fn sin(x: BigDecimal, precision: Int) raises -> BigDecimal: var result: BigDecimal if x.is_zero(): - return BigDecimal(BigUInt.ZERO) + return BigDecimal(BigUInt.zero()) var bdec_2 = BigDecimal.from_raw_components(UInt32(2), scale=0, sign=False) var bdec_4 = BigDecimal.from_raw_components(UInt32(4), scale=0, sign=False) @@ -76,7 +76,7 @@ fn sin(x: BigDecimal, precision: Int) raises -> BigDecimal: # x_reduced = x mod 2π x_reduced = x % bdec_2pi else: - x_reduced = x + x_reduced = x.copy() # Step 2: Reduce [-2π, -6] or [6, 2π] to [6-2π, 2π-6] # sin(x) = sin(x - 2π) @@ -140,7 +140,7 @@ fn sin(x: BigDecimal, 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, ) @@ -171,16 +171,16 @@ fn sin_taylor_series( var working_precision = minimum_precision + BUFFER_DIGITS if x.is_zero(): - return BigDecimal(BigUInt.ZERO) + return BigDecimal(BigUInt.zero()) - var term = x # x^n / n! - var result = x + var term = x.copy() # x^n / n! + var result = x.copy() var x_squared = x * x var n = 1 var sign = -1 # Continue until term is smaller than desired precision - var epsilon = BigDecimal(BigUInt.ONE, scale=working_precision, sign=False) + var epsilon = BigDecimal(BigUInt.one(), scale=working_precision, sign=False) while term.compare_absolute(epsilon) > 0: # x^n = x^(n-2) * x^2 / ((n-1)(n)) @@ -198,7 +198,7 @@ fn sin_taylor_series( # Ensure that the result will not explode in size result.round_to_precision( working_precision, - rounding_mode=RoundingMode.ROUND_DOWN, + rounding_mode=RoundingMode.down(), remove_extra_digit_due_to_rounding=False, fill_zeros_to_precision=False, ) @@ -224,7 +224,7 @@ fn cos(x: BigDecimal, precision: Int) raises -> BigDecimal: var working_precision = precision + BUFFER_DIGITS if x.is_zero(): - return BigDecimal(BigUInt.ONE) + return BigDecimal(BigUInt.one()) # cos(x) = sin(π/2 - x) var pi = decimojo.bigdecimal.constants.pi(precision=working_precision) @@ -261,13 +261,13 @@ fn cos_taylor_series( ) var bdec_1 = BigDecimal.from_raw_components(UInt32(1), scale=0, sign=False) - var term = bdec_1 # Current term: x^n / n! - var result = bdec_1 # Start with 1 + var term = bdec_1.copy() # Current term: x^n / n! + var result = bdec_1.copy() # Start with 1 var x_squared = x * x var n = 0 # Current power (0, 2, 4, 6, ...) var sign = -1 # Alternating sign - var epsilon = BigDecimal(BigUInt.ONE, scale=working_precision, sign=False) + var epsilon = BigDecimal(BigUInt.one(), scale=working_precision, sign=False) while term.compare_absolute(epsilon) > 0: n += 2 # Next even power: 2, 4, 6, 8, ... @@ -286,7 +286,7 @@ fn cos_taylor_series( # # Prevent size explosion result.round_to_precision( working_precision, - rounding_mode=RoundingMode.ROUND_DOWN, + rounding_mode=RoundingMode.down(), remove_extra_digit_due_to_rounding=False, fill_zeros_to_precision=False, ) @@ -351,7 +351,7 @@ fn tan_cot(x: BigDecimal, precision: Int, is_tan: Bool) raises -> BigDecimal: if x.is_zero(): if is_tan: - return BigDecimal(BigUInt.ZERO) + return BigDecimal(BigUInt.zero()) else: # cot(0) is undefined, but we return 0 for consistency # since tan(0) is defined as 0. @@ -366,7 +366,7 @@ fn tan_cot(x: BigDecimal, precision: Int, is_tan: Bool) raises -> BigDecimal: var two_pi = bdec_2 * pi var pi_div_2 = pi.true_divide(bdec_2, precision=working_precision_pi) - var x_reduced = x + var x_reduced = x.copy() # First reduce to (-π, π) range if x_reduced.compare_absolute(pi) > 0: x_reduced = x_reduced % two_pi @@ -400,7 +400,7 @@ fn tan_cot(x: BigDecimal, precision: Int, is_tan: Bool) 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, ) @@ -430,7 +430,7 @@ fn csc(x: BigDecimal, precision: Int) raises -> BigDecimal: var sin_x = sin(x, precision=working_precision) - return BigDecimal(BigUInt.ONE).true_divide(sin_x, precision=precision) + return BigDecimal(BigUInt.one()).true_divide(sin_x, precision=precision) fn sec(x: BigDecimal, precision: Int) raises -> BigDecimal: @@ -448,14 +448,14 @@ fn sec(x: BigDecimal, precision: Int) raises -> BigDecimal: This function calculates sec(x) = 1 / cos(x). """ if x.is_zero(): - return BigDecimal(BigUInt.ONE) + return BigDecimal(BigUInt.one()) alias BUFFER_DIGITS = 9 var working_precision = precision + BUFFER_DIGITS var cos_x = cos(x, precision=working_precision) - return BigDecimal(BigUInt.ONE).true_divide(cos_x, precision=precision) + return BigDecimal(BigUInt.one()).true_divide(cos_x, precision=precision) # ===----------------------------------------------------------------------=== # @@ -522,7 +522,7 @@ fn arctan(x: BigDecimal, 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, ) @@ -557,15 +557,15 @@ fn arctan_taylor_series( UInt32(0), scale=minimum_precision, sign=x.sign ) - var term = x # x^n - var term_divided = x # x^n / n - var result = x + var term = x.copy() # x^n + var term_divided = x.copy() # x^n / n + var result = x.copy() var x_squared = x * x var n = 1 var sign = -1 # Continue until term is smaller than desired precision - var epsilon = BigDecimal(BigUInt.ONE, scale=working_precision, sign=False) + var epsilon = BigDecimal(BigUInt.one(), scale=working_precision, sign=False) while term_divided.compare_absolute(epsilon) > 0: n += 2 @@ -581,7 +581,7 @@ fn arctan_taylor_series( # Ensure that the result will not explode in size result.round_to_precision( working_precision, - rounding_mode=RoundingMode.ROUND_DOWN, + rounding_mode=RoundingMode.down(), remove_extra_digit_due_to_rounding=False, fill_zeros_to_precision=False, ) diff --git a/src/decimojo/bigint/arithmetics.mojo b/src/decimojo/bigint/arithmetics.mojo index 04897e8..123471d 100644 --- a/src/decimojo/bigint/arithmetics.mojo +++ b/src/decimojo/bigint/arithmetics.mojo @@ -40,13 +40,13 @@ fn add(x1: BigInt, x2: BigInt) -> BigInt: len(x1.magnitude.words) == 1, "decimojo.bigint.arithmetics.add(): leading zero words in x1", ) - return x2 + return x2.copy() if x2.is_zero(): debug_assert[assert_mode="none"]( len(x2.magnitude.words) == 1, "decimojo.bigint.arithmetics.add(): leading zero words in x2", ) - return x1 + return x1.copy() # If signs are different, delegate to `subtract` if x1.sign != x2.sign: @@ -94,7 +94,7 @@ fn subtract(x1: BigInt, x2: BigInt) -> BigInt: len(x2.magnitude.words) == 1, "decimojo.bigint.arithmetics.add(): leading zero words in x2", ) - return x1 + return x1.copy() # If the minuend is zero, return the negated subtrahend if x1.is_zero(): debug_assert[assert_mode="none"]( @@ -117,7 +117,7 @@ fn subtract(x1: BigInt, x2: BigInt) -> BigInt: var sign: Bool if comparison_result > 0: # |x1| > |x2| # Subtract smaller from larger - magnitude = x1.magnitude + magnitude = x1.magnitude.copy() decimojo.biguint.arithmetics.subtract_inplace_no_check( magnitude, x2.magnitude ) @@ -125,7 +125,7 @@ fn subtract(x1: BigInt, x2: BigInt) -> BigInt: else: # |x1| < |x2| # Subtract larger from smaller and negate the result - magnitude = x2.magnitude + magnitude = x2.magnitude.copy() decimojo.biguint.arithmetics.subtract_inplace_no_check( magnitude, x1.magnitude ) @@ -154,7 +154,7 @@ fn negative(x: BigInt) -> BigInt: ) return BigInt() - var result = x + var result = x.copy() result.sign = not result.sign return result^ @@ -171,7 +171,7 @@ fn absolute(x: BigInt) -> BigInt: if x.sign: return -x else: - return x + return x.copy() fn multiply(x1: BigInt, x2: BigInt) -> BigInt: diff --git a/src/decimojo/bigint/bigint.mojo b/src/decimojo/bigint/bigint.mojo index 804baef..ddd3163 100644 --- a/src/decimojo/bigint/bigint.mojo +++ b/src/decimojo/bigint/bigint.mojo @@ -81,7 +81,7 @@ struct BigInt( @implicit fn __init__(out self, magnitude: BigUInt): """Constructs a BigInt from a BigUInt object.""" - self.magnitude = magnitude + self.magnitude = magnitude.copy() self.sign = False fn __init__(out self, magnitude: BigUInt, sign: Bool): @@ -92,7 +92,7 @@ struct BigInt( sign: The sign of the BigInt. """ - self.magnitude = magnitude + self.magnitude = magnitude.copy() self.sign = sign fn __init__(out self, words: List[UInt32], sign: Bool): @@ -111,7 +111,7 @@ struct BigInt( (2) the words are smaller than `999_999_999`. """ - self.magnitude = BigUInt(words) + self.magnitude = BigUInt(words.copy()) self.sign = sign fn __init__(out self, var *words: UInt32, sign: Bool) raises: @@ -200,7 +200,7 @@ struct BigInt( if len(words) == 0: return Self() - return Self(BigUInt(words), sign) + return Self(BigUInt(words^), sign) @staticmethod fn from_words(*words: UInt32, sign: Bool) raises -> Self: @@ -306,9 +306,9 @@ struct BigInt( Returns: The BigInt representation of the string. """ - var coef: List[UInt8] - 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 sign: Bool = _tuple[2] # Check if the number is zero if len(coef) == 1 and coef[0] == UInt8(0): diff --git a/src/decimojo/biguint/arithmetics.mojo b/src/decimojo/biguint/arithmetics.mojo index 61a09d6..4f68ca4 100644 --- a/src/decimojo/biguint/arithmetics.mojo +++ b/src/decimojo/biguint/arithmetics.mojo @@ -106,7 +106,7 @@ fn negative(x: BigUInt) raises -> BigUInt: previous_error=None, ) ) - return BigUInt.ZERO # Return zero + return BigUInt.zero() # Return zero fn absolute(x: BigUInt) -> BigUInt: @@ -118,7 +118,7 @@ fn absolute(x: BigUInt) -> BigUInt: Returns: A new BigUInt containing the absolute value of x. """ - return x + return x.copy() # ===----------------------------------------------------------------------=== # @@ -154,25 +154,25 @@ fn add(x: BigUInt, y: BigUInt) -> BigUInt: debug_assert[assert_mode="none"]( len(x.words) == 1, "add(): leading zero words" ) - return y + return y.copy() if y.is_zero(): debug_assert[assert_mode="none"]( len(y.words) == 1, "add(): leading zero words" ) - return x + return x.copy() if len(x.words) == 1: if len(y.words) == 1: # If both numbers are single-word, we can handle them with UInt32 return BigUInt.from_uint32(x.words[0] + y.words[0]) else: # If x is single-word, we can handle it with UInt32 - var result = y + var result = y.copy() add_inplace_by_uint32(result, x.words[0]) return result^ if len(y.words) == 1: # If y is single-word, we can handle it with UInt32 - var result = x + var result = x.copy() add_inplace_by_uint32(result, y.words[0]) return result^ @@ -351,7 +351,7 @@ fn add_inplace(mut x: BigUInt, y: BigUInt) -> None: debug_assert[assert_mode="none"]( len(x.words) == 1, "add_inplace(): leading zero words" ) - x.words = y.words # Copy the words from y + x.words = y.words.copy() # Copy the words from y return if y.is_zero(): debug_assert[assert_mode="none"]( @@ -504,13 +504,13 @@ fn subtract_school(x: BigUInt, y: BigUInt) raises -> BigUInt: debug_assert[assert_mode="none"]( len(y.words) == 1, "subtract_school(): leading zero words" ) - return x + return x.copy() # We need to determine which number has the larger magnitude var comparison_result = x.compare(y) if comparison_result == 0: # |x| = |y| - return BigUInt.ZERO # Return zero + return BigUInt.zero() # Return zero if comparison_result < 0: raise Error( OverflowError( @@ -600,13 +600,13 @@ fn subtract_simd(x: BigUInt, y: BigUInt) raises -> BigUInt: debug_assert[assert_mode="none"]( len(y.words) == 1, "subtract_simd(): leading zero words" ) - return x + return x.copy() # We need to determine which number has the larger magnitude var comparison_result = x.compare(y) if comparison_result == 0: # |x| = |y| - return BigUInt.ZERO # Return zero + return BigUInt.zero() # Return zero if comparison_result < 0: raise Error( OverflowError( @@ -829,22 +829,22 @@ fn multiply(x: BigUInt, y: BigUInt) -> BigUInt: if len(x.words) == 1: var x_word = x.words[0] if x_word == 0: - return BigUInt.ZERO + return BigUInt.zero() elif x_word == 1: - return y + return y.copy() else: - var result = y + var result = y.copy() multiply_inplace_by_uint32(result, x_word) return result^ if len(y.words) == 1: var y_word = y.words[0] if y_word == 0: - return BigUInt.ZERO + return BigUInt.zero() if y_word == 1: - return x + return x.copy() else: - var result = x + var result = x.copy() multiply_inplace_by_uint32(result, y_word) return result^ @@ -933,7 +933,7 @@ fn multiply_slices_school( if n_words_x_slice == 1: var x_word = x.words[bounds_x[0]] if x_word == 0: - return BigUInt.ZERO + return BigUInt.zero() elif x_word == 1: return BigUInt.from_slice(y, (bounds_y[0], bounds_y[1])) else: @@ -943,7 +943,7 @@ fn multiply_slices_school( if n_words_y_slice == 1: var y_word = y.words[bounds_y[0]] if y_word == 0: - return BigUInt.ZERO + return BigUInt.zero() elif y_word == 1: return BigUInt.from_slice(x, (bounds_x[0], bounds_x[1])) else: @@ -1027,7 +1027,7 @@ fn multiply_slices_karatsuba( if x.is_zero_in_bounds(bounds=bounds_x) or y.is_zero_in_bounds( bounds=bounds_y ): - return BigUInt.ZERO + return BigUInt.zero() # Number of words in the slice 1: end_x - start_x # Number of words in the slice 2: end_y - start_y @@ -1296,13 +1296,13 @@ fn multiply_by_power_of_ten(x: BigUInt, n: Int) -> BigUInt: ) if n <= 0: - return x + return x.copy() if x.is_zero(): debug_assert[assert_mode="none"]( len(x.words) == 1, "multiply_by_power_of_ten(): leading zero words" ) - return BigUInt.ZERO # Multiplying zero by anything is still zero + return BigUInt.zero() # Multiplying zero by anything is still zero var number_of_zero_words = n // 9 var number_of_remaining_digits = n % 9 @@ -1462,7 +1462,7 @@ fn multiply_by_power_of_billion(x: BigUInt, n: Int) -> BigUInt: ) if n <= 0: - return x # No change needed + return x.copy() # No change needed if x.is_zero(): debug_assert[assert_mode="none"]( @@ -1471,7 +1471,7 @@ fn multiply_by_power_of_billion(x: BigUInt, n: Int) -> BigUInt: ) # If x is zero, we can just return # No need to add zeros, it will still be zero - return BigUInt.ZERO + return BigUInt.zero() var res = BigUInt(unsafe_uninit_length=len(x.words) + n) # Fill the first n words with zeros @@ -1594,22 +1594,22 @@ fn floor_divide(x: BigUInt, y: BigUInt) raises -> BigUInt: len(x.words) == 1, "biguint.arithmetics.floor_divide(): x has leading zero words", ) - return BigUInt.ZERO # Return zero + return BigUInt.zero() # Return zero # CASE: x is not greater than y var comparison_result: Int8 = x.compare(y) # SUB-CASE: dividend < divisor if comparison_result < 0: - return BigUInt.ZERO # Return zero + return BigUInt.zero() # Return zero # SUB-CASE: dividend == divisor if comparison_result == 0: - return BigUInt.ONE # Return one + return BigUInt.one() # Return one # CASE: y is single word if len(y.words) == 1: # SUB-CASE: Division by one if y.words[0] == 1: - return x + return x.copy() # SUB-CASE: Single word // single word if len(x.words) == 1: var result = BigUInt.from_uint32_unsafe(x.words[0] // y.words[0]) @@ -1690,22 +1690,22 @@ fn floor_divide_school(x: BigUInt, y: BigUInt) raises -> BigUInt: len(x.words) == 1, "biguint.arithmetics.floor_divide(): x has leading zero words", ) - return BigUInt.ZERO # Return zero + return BigUInt.zero() # Return zero # CASE: x is not greater than y var comparison_result: Int8 = x.compare(y) # SUB-CASE: dividend < divisor if comparison_result < 0: - return BigUInt.ZERO # Return zero + return BigUInt.zero() # Return zero # SUB-CASE: dividend == divisor if comparison_result == 0: - return BigUInt.ONE + return BigUInt.one() # CASE: y is single word if len(y.words) == 1: # SUB-CASE: Division by one if y.words[0] == 1: - return x + return x.copy() # SUB-CASE: Single word // single word if len(x.words) == 1: var result = BigUInt.from_uint32_unsafe(x.words[0] // y.words[0]) @@ -1729,7 +1729,7 @@ fn floor_divide_school(x: BigUInt, y: BigUInt) raises -> BigUInt: # Use the schoolbook division algorithm # Initialize result and remainder var result = BigUInt(uninitialized_capacity=len(x.words)) - var remainder = x + var remainder = x.copy() # Shift and initialize var n_words_diff = len(remainder.words) - len(y.words) @@ -1746,7 +1746,7 @@ fn floor_divide_school(x: BigUInt, y: BigUInt) raises -> BigUInt: quotient = floor_divide_estimate_quotient(remainder, y, index_of_word) # Calculate trial product - trial_product = y + trial_product = y.copy() multiply_inplace_by_uint32(trial_product, quotient) multiply_inplace_by_power_of_billion(trial_product, index_of_word) @@ -2124,17 +2124,17 @@ fn floor_divide_by_power_of_ten(x: BigUInt, n: Int) -> BigUInt: ) if n <= 0: - return x + return x.copy() # First remove the last words (10^9) var result: BigUInt if len(x.words) == 1: - result = x + result = x.copy() else: var word_shift = n // 9 # If we need to drop more words than exists, result is zero if word_shift >= len(x.words): - return BigUInt.ZERO + return BigUInt.zero() # Create result with the remaining words result = BigUInt(uninitialized_capacity=len(x.words) - word_shift) for i in range(word_shift, len(x.words)): @@ -2202,12 +2202,12 @@ fn floor_divide_by_power_of_billion(x: BigUInt, n: Int) -> BigUInt: ) if n <= 0: - return x + return x.copy() 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 + return BigUInt.zero() else: var result = BigUInt(unsafe_uninit_length=n_words_of_result) memcpy( @@ -2260,8 +2260,8 @@ fn floor_divide_burnikel_ziegler( # (1) it is of the form j*2^k and # (2) the most significant word is at least 500_000_000. - var normalized_b = b - var normalized_a = a + var normalized_b = b.copy() + var normalized_a = a.copy() var ndigits_to_shift: Int if normalized_b.words[-1] < 500_000_000: @@ -2326,8 +2326,8 @@ fn floor_divide_burnikel_ziegler( if normalized_a.words[-1] >= 500_000_000: t += 1 - var z = BigUInt.ZERO # Remainder of the division - var q = BigUInt.ZERO + var z = BigUInt.zero() # Remainder of the division + var q = BigUInt.zero() var q_i: BigUInt for i in range(t - 2, -1, -1): @@ -2341,7 +2341,9 @@ fn floor_divide_burnikel_ziegler( if i == t - 2: # The first iteration, we can use the slize of normalized_a - q, z = floor_divide_slices_two_by_one( + # TODO: Refine this when Mojo support move values of unpacked tuples + # https://github.com/modular/modular/issues/5330 + _tuple = floor_divide_slices_two_by_one( normalized_a, normalized_b, bounds_a=((t - 2) * n, len(normalized_a.words)), @@ -2349,8 +2351,10 @@ fn floor_divide_burnikel_ziegler( n=n, cut_off=cut_off, ) + q = _tuple[0].copy() + z = _tuple[1].copy() else: - q_i, z = floor_divide_slices_two_by_one( + _tuple = floor_divide_slices_two_by_one( z, normalized_b, bounds_a=(0, len(z.words)), @@ -2358,6 +2362,8 @@ fn floor_divide_burnikel_ziegler( n=n, cut_off=cut_off, ) + q_i = _tuple[0].copy() + z = _tuple[1].copy() decimojo.biguint.arithmetics.multiply_inplace_by_power_of_billion( q, n ) @@ -2417,14 +2423,19 @@ fn floor_divide_two_by_one( var b0 = BigUInt.from_slice(b, bounds=(0, n // 2)) var b1 = BigUInt.from_slice(b, bounds=(n // 2, n)) - var q, r = floor_divide_three_by_two( + # TODO: Refine this when Mojo support move values of unpacked tuples + _tuple = floor_divide_three_by_two( a3, a2, a1, b1, b0, n // 2, cut_off ) # q is q1 + var q = _tuple[0].copy() + var ref r = _tuple[1] + var r0 = BigUInt.from_slice(r, bounds=(0, n // 2)) var r1 = BigUInt.from_slice(r, bounds=(n // 2, n)) - var q0, s = floor_divide_three_by_two( - r1, r0, a0, b1, b0, n // 2, cut_off - ) + # TODO: Refine this when Mojo support move values of unpacked tuples + _tuple = floor_divide_three_by_two(r1, r0, a0, b1, b0, n // 2, cut_off) + var ref q0 = _tuple[0] # q0 + var s = _tuple[1].copy() # s is the final remainder # q -> q1q0 decimojo.biguint.arithmetics.multiply_inplace_by_power_of_billion( @@ -2469,26 +2480,29 @@ fn floor_divide_three_by_two( len(a2.words) == 1, "floor_divide_three_by_two(): leading zero words", ) - a2a1 = a1 + a2a1 = a1.copy() else: - a2a1 = a2 + a2a1 = a2.copy() decimojo.biguint.arithmetics.multiply_inplace_by_power_of_billion( a2a1, n ) a2a1 += a1 - var q, c = floor_divide_two_by_one(a2a1, b1, n, cut_off) + # TODO: Refine this when Mojo support move values of unpacked tuples + _tuple = floor_divide_two_by_one(a2a1, b1, n, cut_off) + var q = _tuple[0].copy() + var ref c = _tuple[1] # c is the carry var d = q * b0 decimojo.biguint.arithmetics.multiply_inplace_by_power_of_billion(c, n) var r = c + a0 if r < d: - var b = b1 + var b = b1.copy() decimojo.biguint.arithmetics.multiply_inplace_by_power_of_billion(b, n) b += b0 - q -= BigUInt.ONE + q -= BigUInt.one() r += b if r < d: - q -= BigUInt.ONE + q -= BigUInt.one() r += b r -= d @@ -2567,25 +2581,30 @@ fn floor_divide_slices_two_by_one( # We just need to use three-by-two division once: a2a1a0 // b1b0 # Note that the condition must be short-circuited to avoid slicing # an empty BigUInt. - var q, r = floor_divide_slices_three_by_two( + _tuple = floor_divide_slices_three_by_two( a, b, bounds_a, bounds_b, n // 2, cut_off ) - return (q^, r^) + # _tuple = (q, r) + return _tuple^ else: var bounds_a1a3 = (bounds_a[0] + n // 2, bounds_a[1]) # We use the most significant three parts of the dividend # a3a2a1 // b1b0 - var q, r = floor_divide_slices_three_by_two( + _tuple = floor_divide_slices_three_by_two( a, b, bounds_a1a3, bounds_b, n // 2, cut_off ) + var q = _tuple[0].copy() # q is q1 + var ref r = _tuple[1] # r is the carry multiply_inplace_by_power_of_billion(r, n // 2) add_inplace_by_slice(r, a, (bounds_a[0], bounds_a[0] + n // 2)) - var q0, s = floor_divide_slices_three_by_two( + _tuple = floor_divide_slices_three_by_two( r, b, (0, len(r.words)), bounds_b, n // 2, cut_off ) + var ref q0 = _tuple[0] # q0 + var s = _tuple[1].copy() # s is the final remainder # q -> q1q0 decimojo.biguint.arithmetics.multiply_inplace_by_power_of_billion( @@ -2640,10 +2659,10 @@ fn floor_divide_slices_three_by_two( if a.words[bounds_a[1] - 1] >= b.words[bounds_b[1] - 1]: var r = BigUInt.from_slice(a, (bounds_a[0], bounds_a[1])) subtract_inplace(r, BigUInt.from_slice(b, bounds_b)) - return (BigUInt.ONE, r^) + return (BigUInt.one(), r^) else: return ( - BigUInt.ZERO, + BigUInt.zero(), BigUInt.from_slice(a, bounds_a), ) @@ -2653,19 +2672,22 @@ fn floor_divide_slices_three_by_two( var bounds_b1 = (bounds_b[0] + n, bounds_b[1]) var bounds_b0 = (bounds_b[0], bounds_b[0] + n) - q, c = floor_divide_slices_two_by_one( + _tuple = floor_divide_slices_two_by_one( a, b, bounds_a2a1, bounds_b1, n, cut_off ) + var q = _tuple[0].copy() + var ref c = _tuple[1] # c is the carry + var d = multiply_slices(q, b, (0, len(q.words)), bounds_b0) decimojo.biguint.arithmetics.multiply_inplace_by_power_of_billion(c, n) var r = add_slices(c, a, bounds_x=(0, len(c.words)), bounds_y=bounds_a0) if r < d: - q -= BigUInt.ONE + q -= BigUInt.one() # r = r + b add_inplace_by_slice(r, b, bounds_y=bounds_b) if r < d: - q -= BigUInt.ONE + q -= BigUInt.one() # r = r + b add_inplace_by_slice(r, b, bounds_y=bounds_b) @@ -2855,15 +2877,15 @@ fn floor_modulo(x1: BigUInt, x2: BigUInt) raises -> BigUInt: debug_assert[assert_mode="none"]( len(x1.words) == 1, "truncate_modulo(): leading zero words" ) - return BigUInt.ZERO # Return zero + return BigUInt.zero() # Return zero # CASE: Divisor is one - no remainder if x2.is_one(): - return BigUInt.ZERO # Always divisible with no remainder + return BigUInt.zero() # Always divisible with no remainder # CASE: |dividend| < |divisor| - the remainder is the dividend itself if x1.compare(x2) < 0: - return x1 + return x1.copy() # Calculate quotient with truncation var quotient: BigUInt @@ -2952,15 +2974,15 @@ fn ceil_modulo(x1: BigUInt, x2: BigUInt) raises -> BigUInt: debug_assert[assert_mode="none"]( len(x1.words) == 1, "ceil_modulo(): leading zero words" ) - return BigUInt.ZERO # Return zero + return BigUInt.zero() # Return zero # CASE: Divisor is one - no remainder if x2.is_one(): - return BigUInt.ZERO # Always divisible with no remainder + return BigUInt.zero() # Always divisible with no remainder # CASE: |dividend| < |divisor| - the remainder is the dividend itself if x1.compare(x2) < 0: - return x1 + return x1.copy() # Calculate quotient with truncation var quotient = floor_divide(x1, x2) @@ -2971,7 +2993,7 @@ fn ceil_modulo(x1: BigUInt, x2: BigUInt) raises -> BigUInt: debug_assert[assert_mode="none"]( len(remainder.words) == 1, "ceil_modulo(): leading zero words" ) - return BigUInt.ZERO # No remainder + return BigUInt.zero() # No remainder else: return subtract(x2, remainder) @@ -3189,7 +3211,7 @@ fn power_of_10(n: Int) raises -> BigUInt: ) if n == 0: - return BigUInt.ONE + return BigUInt.one() # Handle small powers directly if n < 9: @@ -3202,7 +3224,7 @@ fn power_of_10(n: Int) raises -> BigUInt: var words = n // 9 var remainder = n % 9 - var result = BigUInt.ZERO + var result = BigUInt.zero() # Add leading zeros for full power-of-billion words for _ in range(words): diff --git a/src/decimojo/biguint/biguint.mojo b/src/decimojo/biguint/biguint.mojo index a9aae22..6b9c16f 100644 --- a/src/decimojo/biguint/biguint.mojo +++ b/src/decimojo/biguint/biguint.mojo @@ -588,7 +588,7 @@ struct BigUInt( else: if value == 0: - return BigUInt.ZERO + return materialize[BigUInt.ZERO]() var sign = True if value < 0 else False @@ -633,10 +633,10 @@ struct BigUInt( Returns: The BigUInt 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] if (not ignore_sign) and sign: raise Error( @@ -1071,7 +1071,7 @@ struct BigUInt( fn __rshift__(self, shift_amount: Int) -> Self: """Returns the result of floored divison by 2 to the power of `shift_amount`. """ - var result = self + var result = self.copy() for _ in range(shift_amount): decimojo.biguint.arithmetics.floor_divide_inplace_by_2(result) return result^ @@ -1457,7 +1457,7 @@ struct BigUInt( ) var result = Self(1) - var base = self + var base = self.copy() var exp = exponent while exp > 0: if exp % 2 == 1: @@ -1465,7 +1465,7 @@ struct BigUInt( base = base * base exp //= 2 - return result + return result^ fn power(self, exponent: Self) raises -> Self: """Returns the result of raising this number to the power of `exponent`. @@ -1851,7 +1851,7 @@ struct BigUInt( ) ) if ndigits == 0: - return self + return self.copy() if ndigits > self.number_of_digits(): raise Error( ValueError( @@ -1874,15 +1874,15 @@ struct BigUInt( ) var round_up: Bool = False - if rounding_mode == RoundingMode.ROUND_DOWN: + if rounding_mode == RoundingMode.down(): pass - elif rounding_mode == RoundingMode.ROUND_UP: + elif rounding_mode == RoundingMode.up(): if self.number_of_trailing_zeros() < ndigits: round_up = True - elif rounding_mode == RoundingMode.ROUND_HALF_UP: + elif rounding_mode == RoundingMode.half_up(): if self.ith_digit(ndigits - 1) >= 5: round_up = True - elif rounding_mode == RoundingMode.ROUND_HALF_EVEN: + elif rounding_mode == RoundingMode.half_even(): var cut_off_digit = self.ith_digit(ndigits - 1) if cut_off_digit > 5: round_up = True diff --git a/src/decimojo/biguint/exponential.mojo b/src/decimojo/biguint/exponential.mojo index e31cc69..846e2b5 100644 --- a/src/decimojo/biguint/exponential.mojo +++ b/src/decimojo/biguint/exponential.mojo @@ -47,9 +47,9 @@ fn sqrt(x: BigUInt) -> BigUInt: # Use built-in methods for small numbers (up to 2 words) if len(x.words) == 1: if x.words[0] == 0: - return BigUInt.ZERO + return BigUInt.zero() elif x.words[0] == 1: - return BigUInt.ONE + return BigUInt.one() else: return BigUInt.from_uint32_unsafe(math.sqrt(x.words[0])) @@ -71,13 +71,13 @@ fn sqrt(x: BigUInt) -> BigUInt: len(x.words) == 1, "biguint.exponential.sqrt(): 0 hould be a single word", ) - return BigUInt.ZERO + return BigUInt.zero() # Start with a initial guess # The initial guess is smaller or equal to the actual square root var guess = sqrt_initial_guess(x) if guess.is_zero(): - return BigUInt.ONE + return BigUInt.one() # Newton's iteration: x_{k+1} = (x_k + n/x_k) / 2 # Continue until convergence @@ -87,7 +87,7 @@ fn sqrt(x: BigUInt) -> BigUInt: var iterations = 0 while True: iterations += 1 - prev_guess = guess + prev_guess = guess.copy() # Calculate (x_k + n/x_k) // 2 try: @@ -95,16 +95,16 @@ fn sqrt(x: BigUInt) -> BigUInt: quotient = x.floor_divide(guess) except: # This should not happen - quotient = BigUInt.ONE + quotient = BigUInt.one() guess += quotient decimojo.biguint.arithmetics.floor_divide_inplace_by_2(guess) if guess == prev_guess: break - if prev_guess == guess + BigUInt.ONE: + if prev_guess == guess + BigUInt.one(): break - if guess == prev_guess + BigUInt.ONE: + if guess == prev_guess + BigUInt.one(): return prev_guess^ # # Ensure we return the floor of the square root diff --git a/src/decimojo/decimal128/arithmetics.mojo b/src/decimojo/decimal128/arithmetics.mojo index b290e13..5f29637 100644 --- a/src/decimojo/decimal128/arithmetics.mojo +++ b/src/decimojo/decimal128/arithmetics.mojo @@ -1202,7 +1202,7 @@ fn truncate_divide(x1: Decimal128, x2: Decimal128) raises -> Decimal128: A new Decimal128 containing the integral part of x1 / x2. """ try: - return divide(x1, x2).round(0, RoundingMode.ROUND_DOWN) + return divide(x1, x2).round(0, RoundingMode.down()) except e: raise Error("Error in `divide()`: ", e) diff --git a/src/decimojo/decimal128/comparison.mojo b/src/decimojo/decimal128/comparison.mojo index 23383b7..6a7f042 100644 --- a/src/decimojo/decimal128/comparison.mojo +++ b/src/decimojo/decimal128/comparison.mojo @@ -109,7 +109,7 @@ fn compare_absolute(x: Decimal128, y: Decimal128) -> Int8: if x_scale == y_scale and x_coef == y_coef: return 0 if x_scale == y_scale: - return (Int8(x_coef > y_coef)) - (Int8(x_coef < y_coef)) + return Int8((Int(x_coef > y_coef)) - (Int(x_coef < y_coef))) # CASE: The scales are different # Compare the integral part first diff --git a/src/decimojo/decimal128/decimal128.mojo b/src/decimojo/decimal128/decimal128.mojo index 4117e1c..702552f 100644 --- a/src/decimojo/decimal128/decimal128.mojo +++ b/src/decimojo/decimal128/decimal128.mojo @@ -1379,7 +1379,7 @@ struct Decimal128( return decimojo.decimal128.rounding.round( self, ndigits=ndigits, - rounding_mode=RoundingMode.ROUND_HALF_EVEN, + rounding_mode=RoundingMode.half_even(), ) except e: return self @@ -1389,7 +1389,7 @@ struct Decimal128( """**OVERLOAD**.""" try: return decimojo.decimal128.rounding.round( - self, ndigits=0, rounding_mode=RoundingMode.ROUND_HALF_EVEN + self, ndigits=0, rounding_mode=RoundingMode.half_even() ) except e: return self diff --git a/src/decimojo/decimal128/utility.mojo b/src/decimojo/decimal128/utility.mojo index a976098..f2a541e 100644 --- a/src/decimojo/decimal128/utility.mojo +++ b/src/decimojo/decimal128/utility.mojo @@ -208,7 +208,7 @@ fn sqrt(x: UInt128) -> UInt128: var r: UInt128 = 0 - for p in range(sys.bitwidthof[UInt128]() // 2 - 1, -1, -1): + for p in range(sys.bit_width_of[UInt128]() // 2 - 1, -1, -1): var new_bit = UInt128(1) << p var would_be = r | new_bit var squared = would_be * would_be @@ -333,17 +333,17 @@ fn round_to_keep_first_n_digits[ var truncated_value = value // divisor var remainder = value % divisor - # If RoundingMode is ROUND_DOWN, just truncate the value - if rounding_mode == RoundingMode.ROUND_DOWN: + # If RoundingMode is down(), just truncate the value + if rounding_mode == RoundingMode.down(): pass - # If RoundingMode is ROUND_UP, round up the value if remainder is greater than 0 - elif rounding_mode == RoundingMode.ROUND_UP: + # If RoundingMode is up(), round up the value if remainder is greater than 0 + elif rounding_mode == RoundingMode.up(): if remainder > 0: truncated_value += 1 - # If RoundingMode is ROUND_HALF_UP, round up the value if remainder is greater than 5 - elif rounding_mode == RoundingMode.ROUND_HALF_UP: + # If RoundingMode is half_up(), round up the value if remainder is greater than 5 + elif rounding_mode == RoundingMode.half_up(): var cutoff_value = 5 * power_of_10[dtype](ndigits_to_remove - 1) if remainder >= cutoff_value: truncated_value += 1 diff --git a/src/decimojo/rounding_mode.mojo b/src/decimojo/rounding_mode.mojo index c05300e..515cab6 100644 --- a/src/decimojo/rounding_mode.mojo +++ b/src/decimojo/rounding_mode.mojo @@ -81,13 +81,13 @@ struct RoundingMode(Stringable): return String(self) == other fn __str__(self) -> String: - if self == Self.ROUND_DOWN: + if self == materialize[Self.ROUND_DOWN](): return "ROUND_DOWN" - elif self == Self.ROUND_HALF_UP: + elif self == materialize[Self.ROUND_HALF_UP](): return "ROUND_HALF_UP" - elif self == Self.ROUND_HALF_EVEN: + elif self == materialize[Self.ROUND_HALF_EVEN](): return "ROUND_HALF_EVEN" - elif self == Self.ROUND_UP: + elif self == materialize[Self.ROUND_UP](): return "ROUND_UP" else: return "UNKNOWN_ROUNDING_MODE" diff --git a/src/decimojo/str.mojo b/src/decimojo/str.mojo index 21f0431..5be5aaf 100644 --- a/src/decimojo/str.mojo +++ b/src/decimojo/str.mojo @@ -212,4 +212,4 @@ fn parse_numeric_string( # 1.234e8 -> 1234e5 -> 1234 and scale = -5 scale -= raw_exponent - return Tuple(coef, scale, mantissa_sign) + return Tuple(coef^, scale, mantissa_sign) diff --git a/src/decimojo/tests.mojo b/src/decimojo/tests.mojo index 6e785c2..15eddfb 100644 --- a/src/decimojo/tests.mojo +++ b/src/decimojo/tests.mojo @@ -52,7 +52,7 @@ struct TestCase(Copyable, Movable, Stringable, Writable): self.expected = other.expected self.description = other.description - fn __moveinit__(out self, var other: Self): + fn __moveinit__(out self, deinit other: Self): self.a = other.a^ self.b = other.b^ self.expected = other.expected^ @@ -135,4 +135,4 @@ fn load_test_cases[ ) ) - return test_cases + return test_cases^ diff --git a/src/tomlmojo/parser.mojo b/src/tomlmojo/parser.mojo index 9ba7008..626b196 100644 --- a/src/tomlmojo/parser.mojo +++ b/src/tomlmojo/parser.mojo @@ -24,7 +24,7 @@ from collections import Dict from .tokenizer import Token, TokenType, Tokenizer -struct TOMLValue(Copyable, Movable): +struct TOMLValue(Copyable, ImplicitlyCopyable, Movable): """Represents a value in the TOML document.""" var type: TOMLValueType @@ -85,6 +85,15 @@ struct TOMLValue(Copyable, Movable): self.array_values = List[TOMLValue]() self.table_values = Dict[String, TOMLValue]() + fn __copyinit__(out self, other: Self): + self.type = other.type + self.string_value = other.string_value + self.int_value = other.int_value + self.float_value = other.float_value + self.bool_value = other.bool_value + self.array_values = other.array_values.copy() + self.table_values = other.table_values.copy() + fn as_string(self) -> String: """Get the value as a string.""" if self.type == TOMLValueType.STRING: @@ -122,7 +131,7 @@ struct TOMLValue(Copyable, Movable): return False -struct TOMLValueType(Copyable, Movable): +struct TOMLValueType(Copyable, ImplicitlyCopyable, Movable): """Types of values in TOML.""" # Aliases to mimic enum constants @@ -216,13 +225,13 @@ struct TOMLDocument(Copyable, Movable): table_name in self.root and self.root[table_name].type == TOMLValueType.TABLE ): - return self.root[table_name].table_values + return self.root[table_name].table_values.copy() return Dict[String, TOMLValue]() fn get_array(self, key: String) raises -> List[TOMLValue]: """Get an array from the document.""" if key in self.root and self.root[key].type == TOMLValueType.ARRAY: - return self.root[key].array_values + return self.root[key].array_values.copy() return List[TOMLValue]() fn get_array_of_tables( @@ -236,9 +245,9 @@ struct TOMLDocument(Copyable, Movable): if value.type == TOMLValueType.ARRAY: for table_value in value.array_values: if table_value.type == TOMLValueType.TABLE: - result.append(table_value.table_values) + result.append(table_value.table_values.copy()) - return result + return result^ struct TOMLParser: @@ -253,13 +262,13 @@ struct TOMLParser: self.current_index = 0 fn __init__(out self, tokens: List[Token]): - self.tokens = tokens + self.tokens = tokens.copy() self.current_index = 0 fn current_token(self) -> Token: """Get the current token.""" if self.current_index < len(self.tokens): - return self.tokens[self.current_index] + return self.tokens[self.current_index].copy() # Return EOF token if we're past the end return Token(TokenType.EOF, "", 0, 0) @@ -280,7 +289,7 @@ struct TOMLParser: self.advance() var value = self.parse_value() - return (key, value) + return (key^, value^) fn parse_value(mut self) raises -> TOMLValue: """Parse a TOML value.""" @@ -320,8 +329,8 @@ struct TOMLParser: var result = TOMLValue() result.type = TOMLValueType.ARRAY - result.array_values = array - return result + result.array_values = array^ + return result^ # Default to NULL value return TOMLValue() @@ -352,15 +361,15 @@ struct TOMLParser: # Parse key-value pairs until we reach a new table or EOF while self.current_token().type == TokenType.KEY: - key, value = self.parse_key_value() + key, value = self.parse_key_value().copy() if key: - table_values[key] = value + table_values[key] = value^ # Skip newline if self.current_token().type == TokenType.NEWLINE: self.advance() - return (table_name, table_values) + return (table_name^, table_values^) fn parse(mut self) raises -> TOMLDocument: """Parse the tokens into a TOMLDocument.""" @@ -374,13 +383,13 @@ struct TOMLParser: continue elif token.type == TokenType.TABLE_START: - var table_name: String - var table_values: Dict[String, TOMLValue] - table_name, table_values = self.parse_table() + _tuple = self.parse_table() + var table_name: String = _tuple[0].copy() + var table_values: Dict[String, TOMLValue] = _tuple[1].copy() if table_name: var table_value = TOMLValue() table_value.type = TOMLValueType.TABLE - table_value.table_values = table_values + table_value.table_values = table_values^ document.root[table_name] = table_value elif token.type == TokenType.ARRAY_OF_TABLES_START: @@ -412,7 +421,7 @@ struct TOMLParser: var value: TOMLValue key, value = self.parse_key_value() if key: - table_values[key] = value + table_values[key] = value^ # Skip newline if self.current_token().type == TokenType.NEWLINE: @@ -421,7 +430,7 @@ struct TOMLParser: # Create table value var table_value = TOMLValue() table_value.type = TOMLValueType.TABLE - table_value.table_values = table_values + table_value.table_values = table_values^ # Add to array of tables if ( @@ -443,25 +452,25 @@ struct TOMLParser: var value: TOMLValue key, value = self.parse_key_value() if key: - document.root[key] = value + document.root[key] = value^ # Skip newline if self.current_token().type == TokenType.NEWLINE: self.advance() elif token.type == TokenType.ARRAY_START: - var table_name: String - var table_values: Dict[String, TOMLValue] - table_name, table_values = self.parse_table() + _tuple = self.parse_table() + var table_name: String = _tuple[0].copy() + var table_values: Dict[String, TOMLValue] = _tuple[1].copy() if table_name: var table_value = TOMLValue() table_value.type = TOMLValueType.TABLE - table_value.table_values = table_values - document.root[table_name] = table_value + table_value.table_values = table_values^ + document.root[table_name^] = table_value^ else: self.advance() - return document + return document^ fn parse_string(input: String) raises -> TOMLDocument: diff --git a/src/tomlmojo/tokenizer.mojo b/src/tomlmojo/tokenizer.mojo index faa42e6..06af2e4 100644 --- a/src/tomlmojo/tokenizer.mojo +++ b/src/tomlmojo/tokenizer.mojo @@ -65,7 +65,7 @@ struct SourcePosition: self.index += 1 -struct TokenType(Copyable, Movable): +struct TokenType(Copyable, ImplicitlyCopyable, Movable): """ TokenType mimics an enum for token types in TOML. """ @@ -316,7 +316,7 @@ struct Tokenizer: ) self._advance() # Skip \r self._advance() # Skip \n - return token + return token^ else: token = Token( TokenType.NEWLINE, @@ -325,7 +325,7 @@ struct Tokenizer: self.position.column, ) self._advance() - return token + return token^ elif self.current_char == "\n": token = Token( TokenType.NEWLINE, @@ -334,28 +334,28 @@ struct Tokenizer: self.position.column, ) self._advance() - return token + return token^ if self.current_char == "=": token = Token( TokenType.EQUAL, "=", self.position.line, self.position.column ) self._advance() - return token + return token^ if self.current_char == ",": token = Token( TokenType.COMMA, ",", self.position.line, self.position.column ) self._advance() - return token + return token^ if self.current_char == ".": token = Token( TokenType.DOT, ".", self.position.line, self.position.column ) self._advance() - return token + return token^ if self.current_char == "[": # Check if next char is also [ @@ -369,7 +369,7 @@ struct Tokenizer: ) self._advance() # Skip first [ self._advance() # Skip second [ - return token + return token^ else: # Regular table start token = Token( @@ -379,7 +379,7 @@ struct Tokenizer: self.position.column, ) self._advance() - return token + return token^ if self.current_char == "]": token = Token( @@ -389,7 +389,7 @@ struct Tokenizer: self.position.column, ) self._advance() - return token + return token^ if self.current_char == QUOTE or self.current_char == LITERAL_QUOTE: return self._read_string() @@ -413,7 +413,7 @@ struct Tokenizer: self.position.column, ) self._advance() - return token + return token^ fn tokenize(mut self) -> List[Token]: """Tokenize the entire source text.""" @@ -421,11 +421,11 @@ struct Tokenizer: var token = self.next_token() while token.type != TokenType.EOF and token.type != TokenType.ERROR: - tokens.append(token) + tokens.append(token^) token = self.next_token() # Add EOF token if token.type == TokenType.EOF: - tokens.append(token) + tokens.append(token^) - return tokens + return tokens^ diff --git a/tests/bigdecimal/test_bigdecimal_rounding.mojo b/tests/bigdecimal/test_bigdecimal_rounding.mojo index 08a7461..367b3f4 100644 --- a/tests/bigdecimal/test_bigdecimal_rounding.mojo +++ b/tests/bigdecimal/test_bigdecimal_rounding.mojo @@ -24,7 +24,9 @@ fn test_bigdecimal_rounding() raises: pydecimal.getcontext().rounding = pydecimal.ROUND_DOWN test_cases = load_test_cases(toml, "round_down_tests") for test_case in test_cases: - var result = BDec(test_case.a).round(Int(test_case.b), ROUND_DOWN) + var result = BDec(test_case.a).round( + Int(test_case.b), RoundingMode.down() + ) try: testing.assert_equal( lhs=String(result), @@ -51,7 +53,9 @@ fn test_bigdecimal_rounding() raises: pydecimal.getcontext().rounding = pydecimal.ROUND_UP test_cases = load_test_cases(toml, "round_up_tests") for test_case in test_cases: - var result = BDec(test_case.a).round(Int(test_case.b), ROUND_UP) + var result = BDec(test_case.a).round( + Int(test_case.b), RoundingMode.up() + ) try: testing.assert_equal( lhs=String(result), @@ -78,7 +82,9 @@ fn test_bigdecimal_rounding() raises: pydecimal.getcontext().rounding = pydecimal.ROUND_HALF_UP test_cases = load_test_cases(toml, "round_half_up_tests") for test_case in test_cases: - var result = BDec(test_case.a).round(Int(test_case.b), ROUND_HALF_UP) + var result = BDec(test_case.a).round( + Int(test_case.b), RoundingMode.up() + ) try: testing.assert_equal( lhs=String(result), @@ -105,7 +111,9 @@ fn test_bigdecimal_rounding() raises: pydecimal.getcontext().rounding = pydecimal.ROUND_HALF_EVEN test_cases = load_test_cases(toml, "round_half_even_tests") for test_case in test_cases: - var result = BDec(test_case.a).round(Int(test_case.b), ROUND_HALF_EVEN) + var result = BDec(test_case.a).round( + Int(test_case.b), RoundingMode.half_even() + ) try: testing.assert_equal( lhs=String(result), @@ -131,7 +139,9 @@ fn test_bigdecimal_rounding() raises: test_cases = load_test_cases(toml, "extreme_value_tests") for test_case in test_cases: - var result = BDec(test_case.a).round(Int(test_case.b), ROUND_HALF_EVEN) + var result = BDec(test_case.a).round( + Int(test_case.b), RoundingMode.half_even() + ) try: testing.assert_equal( lhs=String(result), @@ -157,7 +167,9 @@ fn test_bigdecimal_rounding() raises: test_cases = load_test_cases(toml, "edge_case_tests") for test_case in test_cases: - var result = BDec(test_case.a).round(Int(test_case.b), ROUND_HALF_EVEN) + var result = BDec(test_case.a).round( + Int(test_case.b), RoundingMode.half_even() + ) try: testing.assert_equal( lhs=String(result), @@ -186,7 +198,9 @@ fn test_bigdecimal_rounding() raises: test_cases = load_test_cases(toml, "precision_tests") for test_case in test_cases: - var result = BDec(test_case.a).round(Int(test_case.b), ROUND_HALF_EVEN) + var result = BDec(test_case.a).round( + Int(test_case.b), RoundingMode.half_even() + ) try: testing.assert_equal( lhs=String(result), @@ -212,7 +226,9 @@ fn test_bigdecimal_rounding() raises: test_cases = load_test_cases(toml, "scientific_tests") for test_case in test_cases: - var result = BDec(test_case.a).round(Int(test_case.b), ROUND_HALF_EVEN) + var result = BDec(test_case.a).round( + Int(test_case.b), RoundingMode.half_even() + ) try: testing.assert_equal( lhs=String(result), diff --git a/tests/decimal128/test_decimal128_quantize.mojo b/tests/decimal128/test_decimal128_quantize.mojo index 50dba0d..89c8a27 100644 --- a/tests/decimal128/test_decimal128_quantize.mojo +++ b/tests/decimal128/test_decimal128_quantize.mojo @@ -97,7 +97,7 @@ fn test_rounding_modes() raises: var py_value = pydecimal.Decimal("3.5") var py_quantizer = pydecimal.Decimal("1") - var result1 = test_value.quantize(quantizer, RoundingMode.ROUND_HALF_EVEN) + var result1 = test_value.quantize(quantizer, RoundingMode.half_even()) var py_result1 = py_value.quantize( py_quantizer, rounding=pydecimal.ROUND_HALF_EVEN ) @@ -107,7 +107,7 @@ fn test_rounding_modes() raises: "ROUND_HALF_EVEN gave incorrect result: " + String(result1), ) - var result2 = test_value.quantize(quantizer, RoundingMode.ROUND_HALF_UP) + var result2 = test_value.quantize(quantizer, RoundingMode.half_up()) var py_result2 = py_value.quantize( py_quantizer, rounding=pydecimal.ROUND_HALF_UP ) @@ -117,7 +117,7 @@ fn test_rounding_modes() raises: "ROUND_HALF_UP gave incorrect result: " + String(result2), ) - var result3 = test_value.quantize(quantizer, RoundingMode.ROUND_DOWN) + var result3 = test_value.quantize(quantizer, RoundingMode.down()) var py_result3 = py_value.quantize( py_quantizer, rounding=pydecimal.ROUND_DOWN ) @@ -127,7 +127,7 @@ fn test_rounding_modes() raises: "ROUND_DOWN gave incorrect result: " + String(result3), ) - var result4 = test_value.quantize(quantizer, RoundingMode.ROUND_UP) + var result4 = test_value.quantize(quantizer, RoundingMode.up()) var py_result4 = py_value.quantize( py_quantizer, rounding=pydecimal.ROUND_UP ) @@ -138,7 +138,7 @@ fn test_rounding_modes() raises: ) var neg_test_value = Decimal128("-3.5") - var result5 = neg_test_value.quantize(quantizer, RoundingMode.ROUND_DOWN) + var result5 = neg_test_value.quantize(quantizer, RoundingMode.down()) var py_neg_value = pydecimal.Decimal("-3.5") var py_result5 = py_neg_value.quantize( py_quantizer, rounding=pydecimal.ROUND_DOWN @@ -149,7 +149,7 @@ fn test_rounding_modes() raises: "ROUND_DOWN with negative gave incorrect result: " + String(result5), ) - var result6 = neg_test_value.quantize(quantizer, RoundingMode.ROUND_UP) + var result6 = neg_test_value.quantize(quantizer, RoundingMode.up()) var py_result6 = py_neg_value.quantize( py_quantizer, rounding=pydecimal.ROUND_UP ) @@ -224,7 +224,7 @@ fn test_edge_cases() raises: var value5 = Decimal128("-1.5") var quant5 = Decimal128("1") - var result5 = value5.quantize(quant5, RoundingMode.ROUND_HALF_EVEN) + var result5 = value5.quantize(quant5, RoundingMode.half_even()) var py_value5 = pydecimal.Decimal("-1.5") var py_quant5 = pydecimal.Decimal("1") var py_result5 = py_value5.quantize( @@ -263,7 +263,7 @@ fn test_special_cases() raises: var value2 = Decimal128("2.5") var quant2 = Decimal128("1") - var result2 = value2.quantize(quant2, RoundingMode.ROUND_HALF_EVEN) + var result2 = value2.quantize(quant2, RoundingMode.half_even()) var py_value2 = pydecimal.Decimal("2.5") var py_quant2 = pydecimal.Decimal("1") var py_result2 = py_value2.quantize( @@ -364,10 +364,10 @@ fn test_comprehensive_comparison() raises: pydecimal.getcontext().prec = 28 # Match DeciMojo's precision # Define rounding modes to test - var mojo_round_half_even = RoundingMode.ROUND_HALF_EVEN - var mojo_round_half_up = RoundingMode.ROUND_HALF_UP - var mojo_round_down = RoundingMode.ROUND_DOWN - var mojo_round_up = RoundingMode.ROUND_UP + var mojo_round_half_even = RoundingMode.half_even() + var mojo_round_half_up = RoundingMode.half_up() + var mojo_round_down = RoundingMode.down() + var mojo_round_up = RoundingMode.up() var py_round_half_even = pydecimal.ROUND_HALF_EVEN var py_round_half_up = pydecimal.ROUND_HALF_UP diff --git a/tests/decimal128/test_decimal128_round.mojo b/tests/decimal128/test_decimal128_round.mojo index 1516a50..0fd9b2e 100644 --- a/tests/decimal128/test_decimal128_round.mojo +++ b/tests/decimal128/test_decimal128_round.mojo @@ -43,19 +43,19 @@ fn test_different_rounding_modes() raises: var test_value = Decimal128("123.456") # Test case 1: Round down (truncate) - var result1 = test_value.round(2, RoundingMode.ROUND_DOWN) + var result1 = test_value.round(2, RoundingMode.down()) testing.assert_equal(String(result1), "123.45", "Rounding down") # Test case 2: Round up (away from zero) - var result2 = test_value.round(2, RoundingMode.ROUND_UP) + var result2 = test_value.round(2, RoundingMode.up()) testing.assert_equal(String(result2), "123.46", "Rounding up") # Test case 3: Round half up - var result3 = test_value.round(2, RoundingMode.ROUND_HALF_UP) + var result3 = test_value.round(2, RoundingMode.half_up()) testing.assert_equal(String(result3), "123.46", "Rounding half up") # Test case 4: Round half even (banker's rounding) - var result4 = test_value.round(2, RoundingMode.ROUND_HALF_EVEN) + var result4 = test_value.round(2, RoundingMode.half_even()) testing.assert_equal(String(result4), "123.46", "Rounding half even") print("Rounding mode tests passed!") @@ -68,25 +68,25 @@ fn test_edge_cases() raises: var half_value = Decimal128("123.5") testing.assert_equal( - String(half_value.round(0, RoundingMode.ROUND_DOWN)), + String(half_value.round(0, RoundingMode.down())), "123", "Rounding 0.5 down", ) testing.assert_equal( - String(half_value.round(0, RoundingMode.ROUND_UP)), + String(half_value.round(0, RoundingMode.up())), "124", "Rounding 0.5 up", ) testing.assert_equal( - String(half_value.round(0, RoundingMode.ROUND_HALF_UP)), + String(half_value.round(0, RoundingMode.half_up())), "124", "Rounding 0.5 half up", ) testing.assert_equal( - String(half_value.round(0, RoundingMode.ROUND_HALF_EVEN)), + String(half_value.round(0, RoundingMode.half_even())), "124", "Rounding 0.5 half even (even is 124)", ) @@ -94,7 +94,7 @@ fn test_edge_cases() raises: # Another test with half to even value var half_even_value = Decimal128("124.5") testing.assert_equal( - String(half_even_value.round(0, RoundingMode.ROUND_HALF_EVEN)), + String(half_even_value.round(0, RoundingMode.half_even())), "124", "Rounding 124.5 half even (even is 124)", ) @@ -113,19 +113,19 @@ fn test_edge_cases() raises: var negative_value = Decimal128("-123.456") testing.assert_equal( - String(negative_value.round(2, RoundingMode.ROUND_DOWN)), + String(negative_value.round(2, RoundingMode.down())), "-123.45", "Rounding negative number down", ) testing.assert_equal( - String(negative_value.round(2, RoundingMode.ROUND_UP)), + String(negative_value.round(2, RoundingMode.up())), "-123.46", "Rounding negative number up", ) testing.assert_equal( - String(negative_value.round(2, RoundingMode.ROUND_HALF_EVEN)), + String(negative_value.round(2, RoundingMode.half_even())), "-123.46", "Rounding negative number half even", ) diff --git a/tests/decimal128/test_decimal128_truncate_divide.mojo b/tests/decimal128/test_decimal128_truncate_divide.mojo index a7c791c..966caa6 100644 --- a/tests/decimal128/test_decimal128_truncate_divide.mojo +++ b/tests/decimal128/test_decimal128_truncate_divide.mojo @@ -213,7 +213,7 @@ fn test_mathematical_relationships() raises: var a2 = Decimal128("10.5") var b2 = Decimal128("2.5") var floor_div2 = a2 // b2 - var div_floored = (a2 / b2).round(0, RoundingMode.ROUND_DOWN) + var div_floored = (a2 / b2).round(0, RoundingMode.down()) testing.assert_equal( String(floor_div2), String(div_floored), diff --git a/tests/decimal128/test_decimal128_utility.mojo b/tests/decimal128/test_decimal128_utility.mojo index 351b7ca..79d7507 100644 --- a/tests/decimal128/test_decimal128_utility.mojo +++ b/tests/decimal128/test_decimal128_utility.mojo @@ -3,7 +3,6 @@ Tests for the utility functions in the decimojo.utility module. """ from testing import assert_equal, assert_true -import max from decimojo.prelude import dm, Decimal128, RoundingMode from decimojo.decimal128.utility import (