diff --git a/pixi.toml b/pixi.toml index 460e732..226330d 100644 --- a/pixi.toml +++ b/pixi.toml @@ -1,16 +1,15 @@ [project] authors = ["ZHU Yuhao 朱宇浩 "] -channels = ["https://conda.modular.com/max", "https://repo.prefix.dev/modular-community", "conda-forge"] -# channels = ["https://conda.modular.com/max-nightly", "https://conda.modular.com/max", "https://repo.prefix.dev/modular-community", "conda-forge"] +channels = ["https://conda.modular.com/max-nightly", "https://conda.modular.com/max", "https://repo.prefix.dev/modular-community", "conda-forge"] description = "An arbitrary-precision decimal and integer mathematics library for Mojo" license = "Apache-2.0" name = "decimojo" platforms = ["osx-arm64", "linux-64"] readme = "README.md" -version = "0.4.1" +version = "0.5.0" [dependencies] -max = "==25.4" +max = ">25.4" [tasks] # format the code diff --git a/src/decimojo/bigdecimal/bigdecimal.mojo b/src/decimojo/bigdecimal/bigdecimal.mojo index 28a81b4..26f8bdc 100644 --- a/src/decimojo/bigdecimal/bigdecimal.mojo +++ b/src/decimojo/bigdecimal/bigdecimal.mojo @@ -40,12 +40,15 @@ This will be configurable in future when Mojo supports global variables. """ -@value struct BigDecimal( Absable, + AnyType, Comparable, + Copyable, FloatableRaising, IntableRaising, + Movable, + Representable, Roundable, Stringable, Writable, @@ -167,7 +170,7 @@ struct BigDecimal( @staticmethod fn from_raw_components( - owned words: List[UInt32], scale: Int = 0, sign: Bool = False + var words: List[UInt32], scale: Int = 0, sign: Bool = False ) -> Self: """**UNSAFE** Creates a BigDecimal from its raw components. The raw components are words, scale, and sign. @@ -617,32 +620,32 @@ struct BigDecimal( # ===------------------------------------------------------------------=== # @always_inline - fn __gt__(self, other: BigDecimal) -> Bool: + fn __gt__(self, other: Self) -> Bool: """Returns whether self is greater than other.""" return decimojo.bigdecimal.comparison.compare(self, other) > 0 @always_inline - fn __ge__(self, other: BigDecimal) -> Bool: + fn __ge__(self, other: Self) -> Bool: """Returns whether self is greater than or equal to other.""" return decimojo.bigdecimal.comparison.compare(self, other) >= 0 @always_inline - fn __lt__(self, other: BigDecimal) -> Bool: + fn __lt__(self, other: Self) -> Bool: """Returns whether self is less than other.""" return decimojo.bigdecimal.comparison.compare(self, other) < 0 @always_inline - fn __le__(self, other: BigDecimal) -> Bool: + fn __le__(self, other: Self) -> Bool: """Returns whether self is less than or equal to other.""" return decimojo.bigdecimal.comparison.compare(self, other) <= 0 @always_inline - fn __eq__(self, other: BigDecimal) -> Bool: + fn __eq__(self, other: Self) -> Bool: """Returns whether self equals other.""" return decimojo.bigdecimal.comparison.compare(self, other) == 0 @always_inline - fn __ne__(self, other: BigDecimal) -> Bool: + fn __ne__(self, other: Self) -> Bool: """Returns whether self does not equal other.""" return decimojo.bigdecimal.comparison.compare(self, other) != 0 @@ -728,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=BigDecimal(BigUInt.ONE), precision=precision + x=Self(BigUInt.ONE), precision=precision ) # === Exponentional operations === # @@ -914,7 +917,7 @@ struct BigDecimal( """ return self.coefficient.number_of_digits() - 1 - self.scale - fn extend_precision(self, precision_diff: Int) -> BigDecimal: + fn extend_precision(self, precision_diff: Int) -> Self: """Returns a number with additional decimal places (trailing zeros). This multiplies the coefficient by 10^precision_diff and increases the scale accordingly, preserving the numeric value. @@ -933,10 +936,11 @@ struct BigDecimal( In debug mode, negative `precision_diff` raises an assertion error. Examples: + ``` - print(BigDecimal("123.456).scale_up(5)) # Output: 123.45600000 - print(BigDecimal("123456").scale_up(3)) # Output: 123456.000 - print(BigDecimal("123456").scale_up(-1)) # Output: 123456 (no change) + print(BigDecimal("123.456).extend_precision(5)) # Output: 123.45600000 + print(BigDecimal("123456").extend_precision(3)) # Output: 123456.000 + print(BigDecimal("123456").extend_precision(-1)) # Output: 123456 (no change) ``` """ debug_assert( @@ -949,7 +953,7 @@ struct BigDecimal( if precision_diff <= 0: return self - return BigDecimal( + return Self( decimojo.biguint.arithmetics.multiply_by_power_of_ten( self.coefficient, precision_diff ), @@ -974,9 +978,9 @@ struct BigDecimal( Examples: ``` - print(BigDecimal("123.456).scale_up(5)) # Output: 123.45600000 - print(BigDecimal("123456").scale_up(3)) # Output: 123456.000 - print(BigDecimal("123456").scale_up(-1)) # Output: 123456 (no change) + BigDecimal("123.456).extend_precision_inplace(5) # Output: 123.45600000 + BigDecimal("123456").extend_precision_inplace(3) # Output: 123456.000 + BigDecimal("123456").extend_precision_inplace(-1) # Output: 123456 (no change) ``` """ debug_assert( @@ -1107,7 +1111,7 @@ struct BigDecimal( """Returns True if this number represents zero.""" return self.coefficient.is_zero() - fn normalize(self) raises -> BigDecimal: + fn normalize(self) raises -> Self: """Removes trailing zeros from coefficient while adjusting scale. Notes: @@ -1115,7 +1119,7 @@ struct BigDecimal( Only call it when necessary. Do not normalize after every operation. """ if self.coefficient.is_zero(): - return BigDecimal(BigUInt(UInt32(0)), 0, False) + return Self(BigUInt(UInt32(0)), 0, False) var number_of_digits_to_remove = self.number_of_trailing_zeros() @@ -1146,7 +1150,7 @@ struct BigDecimal( else: # number_of_remaining_digits_to_remove == 8 coefficient = coefficient // BigUInt(UInt32(100_000_000)) - return BigDecimal( + return Self( coefficient, self.scale - number_of_digits_to_remove, self.sign, diff --git a/src/decimojo/bigdecimal/constants.mojo b/src/decimojo/bigdecimal/constants.mojo index 7b2c265..fd565a4 100644 --- a/src/decimojo/bigdecimal/constants.mojo +++ b/src/decimojo/bigdecimal/constants.mojo @@ -179,7 +179,7 @@ fn pi(precision: Int) raises -> BigDecimal: return pi_chudnovsky_binary_split(precision) -@value +@fieldwise_init struct Rational: """Represents a rational number p/q for exact arithmetic.""" diff --git a/src/decimojo/bigint/arithmetics.mojo b/src/decimojo/bigint/arithmetics.mojo index f36d87e..fa42408 100644 --- a/src/decimojo/bigint/arithmetics.mojo +++ b/src/decimojo/bigint/arithmetics.mojo @@ -18,9 +18,6 @@ Implements basic arithmetic functions for the BigInt type. """ -import time -import testing - from decimojo.bigint.bigint import BigInt from decimojo.biguint.biguint import BigUInt from decimojo.rounding_mode import RoundingMode @@ -38,8 +35,16 @@ fn add(x1: BigInt, x2: BigInt) raises -> BigInt: """ # If one of the numbers is zero, return the other number if x1.is_zero(): + debug_assert[assert_mode="none"]( + len(x1.magnitude.words) == 1, + "decimojo.bigint.arithmetics.add(): leading zero words in x1", + ) return x2 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 # If signs are different, delegate to `subtract` @@ -82,9 +87,17 @@ fn subtract(x1: BigInt, x2: BigInt) raises -> BigInt: """ # If the subtrahend is zero, return the minuend 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 # If the minuend is zero, return the negated subtrahend if x1.is_zero(): + debug_assert[assert_mode="none"]( + len(x1.magnitude.words) == 1, + "decimojo.bigint.arithmetics.add(): leading zero words in x1", + ) return -x2 # If signs are different, delegate to `add` @@ -126,6 +139,10 @@ fn negative(x: BigInt) -> BigInt: """ # If x is zero, return zero if x.is_zero(): + debug_assert[assert_mode="none"]( + len(x.magnitude.words) == 1, + "decimojo.bigint.arithmetics.add(): leading zero words in x", + ) return BigInt() var result = x diff --git a/src/decimojo/bigint/bigint.mojo b/src/decimojo/bigint/bigint.mojo index bcec24d..de382a2 100644 --- a/src/decimojo/bigint/bigint.mojo +++ b/src/decimojo/bigint/bigint.mojo @@ -24,8 +24,6 @@ mathematical methods that do not implement a trait. """ from memory import UnsafePointer -import testing -import time import decimojo.bigint.arithmetics import decimojo.bigint.comparison @@ -37,8 +35,17 @@ import decimojo.str alias BInt = BigInt -@value -struct BigInt(Absable, IntableRaising, Representable, Stringable, Writable): +struct BigInt( + Absable, + AnyType, + Comparable, + Copyable, + IntableRaising, + Movable, + Representable, + Stringable, + Writable, +): """Represents a base-10 arbitrary-precision signed integer. Notes: @@ -106,7 +113,7 @@ struct BigInt(Absable, IntableRaising, Representable, Stringable, Writable): self.magnitude = BigUInt(words) self.sign = sign - fn __init__(out self, owned *words: UInt32, sign: Bool) raises: + fn __init__(out self, var *words: UInt32, sign: Bool) raises: """***UNSAFE!*** Initializes a BigInt from raw components. It does not check whether the words are invalid. See `from_words()` for safer initialization. @@ -175,7 +182,7 @@ struct BigInt(Absable, IntableRaising, Representable, Stringable, Writable): # ===------------------------------------------------------------------=== # @staticmethod - fn from_list(owned words: List[UInt32], sign: Bool) raises -> Self: + fn from_list(var words: List[UInt32], sign: Bool) raises -> Self: """Initializes a BigInt from a list of UInt32 words safely. If the list is empty, the BigInt is initialized with value 0. diff --git a/src/decimojo/biguint/arithmetics.mojo b/src/decimojo/biguint/arithmetics.mojo index 8e03af5..d41caca 100644 --- a/src/decimojo/biguint/arithmetics.mojo +++ b/src/decimojo/biguint/arithmetics.mojo @@ -21,14 +21,12 @@ Implements basic arithmetic functions for the BigUInt type. from algorithm import vectorize import math from memory import memcpy, memset_zero -import time -import testing from decimojo.biguint.biguint import BigUInt import decimojo.biguint.comparison from decimojo.rounding_mode import RoundingMode -alias CUTOFF_KARATSUBA: Int = 64 +alias CUTOFF_KARATSUBA = 64 """The cutoff number of words for using Karatsuba multiplication.""" alias CUTOFF_BURNIKEL_ZIEGLER = 32 """The cutoff number of words for using Burnikel-Ziegler division.""" @@ -287,10 +285,10 @@ fn add_slices_simd( @parameter fn vector_add[simd_width: Int](i: Int): - words.data.store[width=simd_width]( + words._data.store[width=simd_width]( i, - x.words.data.load[width=simd_width](i + bounds_x[0]) - + y.words.data.load[width=simd_width](i + bounds_y[0]), + x.words._data.load[width=simd_width](i + bounds_x[0]) + + y.words._data.load[width=simd_width](i + bounds_y[0]), ) vectorize[vector_add, BigUInt.VECTOR_WIDTH]( @@ -315,9 +313,9 @@ fn add_slices_simd( @parameter fn vector_copy_rest_from_longer[simd_width: Int](i: Int): - words.data.store[width=simd_width]( + words._data.store[width=simd_width]( n_words_shorter_slice + i, - longer[].words.data.load[width=simd_width]( + longer[].words._data.load[width=simd_width]( longer_start + n_words_shorter_slice + i ), ) @@ -366,10 +364,10 @@ fn add_inplace(mut x: BigUInt, y: BigUInt) -> None: @parameter fn vector_add[simd_width: Int](i: Int): - x.words.data.store[width=simd_width]( + x.words._data.store[width=simd_width]( i, - x.words.data.load[width=simd_width](i) - + y.words.data.load[width=simd_width](i), + x.words._data.load[width=simd_width](i) + + y.words._data.load[width=simd_width](i), ) vectorize[vector_add, BigUInt.VECTOR_WIDTH](len(y.words)) @@ -415,10 +413,10 @@ fn add_inplace_by_slice( @parameter fn vector_add[simd_width: Int](i: Int): - x.words.data.store[width=simd_width]( + x.words._data.store[width=simd_width]( i, - x.words.data.load[width=simd_width](i) - + y.words.data.load[width=simd_width](i + bounds_y[0]), + x.words._data.load[width=simd_width](i) + + y.words._data.load[width=simd_width](i + bounds_y[0]), ) vectorize[vector_add, BigUInt.VECTOR_WIDTH](n_words_y_slice) @@ -607,19 +605,19 @@ fn subtract_simd(x: BigUInt, y: BigUInt) raises -> BigUInt: # but we will take advantage of that. @parameter fn vector_subtract[simd_width: Int](i: Int): - words.data.store[width=simd_width]( + words._data.store[width=simd_width]( i, - x.words.data.load[width=simd_width](i) - - y.words.data.load[width=simd_width](i), + x.words._data.load[width=simd_width](i) + - y.words._data.load[width=simd_width](i), ) vectorize[vector_subtract, BigUInt.VECTOR_WIDTH](len(y.words)) @parameter fn vector_copy_rest[simd_width: Int](i: Int): - words.data.store[width=simd_width]( + words._data.store[width=simd_width]( len(y.words) + i, - x.words.data.load[width=simd_width](len(y.words) + i), + x.words._data.load[width=simd_width](len(y.words) + i), ) vectorize[vector_copy_rest, BigUInt.VECTOR_WIDTH]( @@ -664,10 +662,10 @@ fn subtract_inplace(mut x: BigUInt, y: BigUInt) raises -> None: # Use SIMD operations to subtract the words in parallel. @parameter fn vector_subtract[simd_width: Int](i: Int): - x.words.data.store[width=simd_width]( + x.words._data.store[width=simd_width]( i, - x.words.data.load[width=simd_width](i) - - y.words.data.load[width=simd_width](i), + x.words._data.load[width=simd_width](i) + - y.words._data.load[width=simd_width](i), ) vectorize[vector_subtract, BigUInt.VECTOR_WIDTH](len(y.words)) @@ -701,10 +699,10 @@ fn subtract_inplace_no_check(mut x: BigUInt, y: BigUInt) -> None: @parameter fn vector_subtract[simd_width: Int](i: Int): - x.words.data.store[width=simd_width]( + x.words._data.store[width=simd_width]( i, - x.words.data.load[width=simd_width](i) - - y.words.data.load[width=simd_width](i), + x.words._data.load[width=simd_width](i) + - y.words._data.load[width=simd_width](i), ) vectorize[vector_subtract, BigUInt.VECTOR_WIDTH](len(y.words)) @@ -1201,8 +1199,8 @@ fn multiply_inplace_by_uint32_le_4(mut x: BigUInt, y: UInt32): @parameter fn vector_multiply_by_2[simd_width: Int](i: Int): """Shifts the digits of each word to the left by 1.""" - x.words.data.store[width=simd_width]( - i, x.words.data.load[width=simd_width](i) << 1 + x.words._data.store[width=simd_width]( + i, x.words._data.load[width=simd_width](i) << 1 ) if y == 2: @@ -1214,8 +1212,8 @@ fn multiply_inplace_by_uint32_le_4(mut x: BigUInt, y: UInt32): @parameter fn vector_multiply_by_3[simd_width: Int](i: Int): """Multiplies the digits of each word by 3.""" - x.words.data.store[width=simd_width]( - i, x.words.data.load[width=simd_width](i) * 3 + x.words._data.store[width=simd_width]( + i, x.words._data.load[width=simd_width](i) * 3 ) if y == 3: @@ -1227,8 +1225,8 @@ fn multiply_inplace_by_uint32_le_4(mut x: BigUInt, y: UInt32): @parameter fn vector_multiply_by_4[simd_width: Int](i: Int): """Shifts the digits of each word to the left by 2.""" - x.words.data.store[width=simd_width]( - i, x.words.data.load[width=simd_width](i) << 2 + x.words._data.store[width=simd_width]( + i, x.words._data.load[width=simd_width](i) << 2 ) if y == 4: @@ -1403,9 +1401,9 @@ fn multiply_by_power_of_billion(x: BigUInt, n: Int) -> BigUInt: var words = List[UInt32](unsafe_uninit_length=len(x.words) + n) # Fill the first n words with zeros - memset_zero(ptr=words.data, count=n) + memset_zero(ptr=words._data, count=n) # Copy the original words to the end of the new list - memcpy(dest=words.data + n, src=x.words.data, count=len(x.words)) + memcpy(dest=words._data + n, src=x.words._data, count=len(x.words)) return BigUInt(words=words^) @@ -1701,7 +1699,7 @@ fn floor_divide_estimate_quotient( if base_index + 2 < len(dividend.words): # We can safely load 3 words: r0, r1, r2 numerator = ( - dividend.words.data.load[width=4](base_index).cast[DType.uint128]() + dividend.words._data.load[width=4](base_index).cast[DType.uint128]() * SIMD[DType.uint128, 4]( 1, 1_000_000_000, 1_000_000_000_000_000_000, 0 ) @@ -1709,7 +1707,7 @@ fn floor_divide_estimate_quotient( elif base_index + 1 < len(dividend.words): # We can safely load 2 words: r0, r1 (r2 = 0) numerator = ( - dividend.words.data.load[width=2](base_index).cast[DType.uint128]() + dividend.words._data.load[width=2](base_index).cast[DType.uint128]() * SIMD[DType.uint128, 2](1, 1_000_000_000) ).reduce_add() elif base_index < len(dividend.words): @@ -1727,7 +1725,7 @@ fn floor_divide_estimate_quotient( "Divisor must have at least 2 words by design.", ) denominator = ( - divisor.words.data.load[width=2](len(divisor.words) - 2).cast[ + divisor.words._data.load[width=2](len(divisor.words) - 2).cast[ DType.uint128 ]() * SIMD[DType.uint128, 2](1, 1_000_000_000) @@ -1836,7 +1834,7 @@ fn floor_divide_by_uint64(x: BigUInt, y: UInt64) -> BigUInt: var dividend = ( carry * UInt128(1_000_000_000_000_000_000) + ( - x.words.data.load[width=2](i - 1).cast[DType.uint128]() + x.words._data.load[width=2](i - 1).cast[DType.uint128]() * SIMD[DType.uint128, 2](1, 1_000_000_000) ).reduce_add() ) @@ -1872,7 +1870,7 @@ fn floor_divide_inplace_by_uint64(mut x: BigUInt, y: UInt64) -> None: var dividend = ( carry * UInt128(1_000_000_000_000_000_000) + ( - x.words.data.load[width=2](i - 1).cast[DType.uint128]() + x.words._data.load[width=2](i - 1).cast[DType.uint128]() * SIMD[DType.uint128, 2](1, 1_000_000_000) ).reduce_add() ) @@ -1907,7 +1905,7 @@ fn floor_divide_by_uint128(x: BigUInt, y: UInt128) -> BigUInt: elif len(x.words) % 4 == 2: carry = UInt256( ( - x.words.data.load[width=2](len(x.words) - 2).cast[ + x.words._data.load[width=2](len(x.words) - 2).cast[ DType.uint64 ]() * SIMD[DType.uint64, 2](1, 1_000_000_000) @@ -1917,7 +1915,7 @@ fn floor_divide_by_uint128(x: BigUInt, y: UInt128) -> BigUInt: elif len(x.words) % 4 == 3: carry = UInt256( ( - x.words.data.load[width=4](len(x.words) - 3).cast[ + x.words._data.load[width=4](len(x.words) - 3).cast[ DType.uint128 ]() * SIMD[DType.uint128, 4]( @@ -1933,7 +1931,7 @@ fn floor_divide_by_uint128(x: BigUInt, y: UInt128) -> BigUInt: var dividend = ( carry * UInt256(1_000_000_000_000_000_000_000_000_000_000_000_000) + ( - x.words.data.load[width=4](i - 3).cast[DType.uint256]() + x.words._data.load[width=4](i - 3).cast[DType.uint256]() * SIMD[DType.uint256, 4]( 1, 1_000_000_000, @@ -2795,8 +2793,7 @@ fn floor_divide_modulo( # ===----------------------------------------------------------------------=== # -# Division Helper Functions -# power_of_10 +# Helper Functions # ===----------------------------------------------------------------------=== # @@ -3039,10 +3036,10 @@ fn to_uint64_with_2_words(a: BigUInt, bounds_x: Tuple[Int, Int]) -> UInt64: """Convert two words at given index of the BigUInt to UInt64.""" var n_words = bounds_x[1] - bounds_x[0] if n_words == 1: - return a.words.data.load[width=1](bounds_x[0]).cast[DType.uint64]() + return a.words._data.load[width=1](bounds_x[0]).cast[DType.uint64]() else: return ( - a.words.data.load[width=2](bounds_x[0]).cast[DType.uint64]() + a.words._data.load[width=2](bounds_x[0]).cast[DType.uint64]() * SIMD[DType.uint64, 2](1, 1_000_000_000) ).reduce_add() @@ -3051,10 +3048,10 @@ fn to_uint128_with_2_words(a: BigUInt, bounds_x: Tuple[Int, Int]) -> UInt128: """Convert two words at given index of the BigUInt to UInt128.""" var n_words = bounds_x[1] - bounds_x[0] if n_words == 1: - return a.words.data.load[width=1](bounds_x[0]).cast[DType.uint128]() + return a.words._data.load[width=1](bounds_x[0]).cast[DType.uint128]() else: return ( - a.words.data.load[width=2](bounds_x[0]).cast[DType.uint128]() + a.words._data.load[width=2](bounds_x[0]).cast[DType.uint128]() * SIMD[DType.uint128, 2](1, 1_000_000_000) ).reduce_add() @@ -3063,22 +3060,22 @@ fn to_uint128_with_4_words(a: BigUInt, bounds_x: Tuple[Int, Int]) -> UInt128: """Convert four words at given index of the BigUInt to UInt128.""" var n_words = bounds_x[1] - bounds_x[0] if n_words == 1: - return a.words.data.load[width=1](bounds_x[0]).cast[DType.uint128]() + return a.words._data.load[width=1](bounds_x[0]).cast[DType.uint128]() elif n_words == 2: return ( - a.words.data.load[width=2](bounds_x[0]).cast[DType.uint128]() + a.words._data.load[width=2](bounds_x[0]).cast[DType.uint128]() * SIMD[DType.uint128, 2](1, 1_000_000_000) ).reduce_add() elif n_words == 3: return ( - a.words.data.load[width=4](bounds_x[0]).cast[DType.uint128]() + a.words._data.load[width=4](bounds_x[0]).cast[DType.uint128]() * SIMD[DType.uint128, 4]( 1, 1_000_000_000, 1_000_000_000_000_000_000, 0 ) ).reduce_add() else: # len(self.words) == 4 return ( - a.words.data.load[width=4](bounds_x[0]).cast[DType.uint128]() + a.words._data.load[width=4](bounds_x[0]).cast[DType.uint128]() * SIMD[DType.uint128, 4]( 1, 1_000_000_000, diff --git a/src/decimojo/biguint/biguint.mojo b/src/decimojo/biguint/biguint.mojo index 2d6cdc1..3b4c9e2 100644 --- a/src/decimojo/biguint/biguint.mojo +++ b/src/decimojo/biguint/biguint.mojo @@ -24,8 +24,6 @@ mathematical methods that do not implement a trait. """ from memory import UnsafePointer, memcpy -import testing -import time import decimojo.biguint.arithmetics import decimojo.biguint.comparison @@ -36,8 +34,9 @@ alias BUInt = BigUInt alias BigUInt10 = BigUInt -@value -struct BigUInt(Absable, IntableRaising, Stringable, Writable): +struct BigUInt( + Absable, Copyable, IntableRaising, Movable, Stringable, Writable +): """Represents a base-10 arbitrary-precision unsigned integer. Notes: @@ -106,8 +105,8 @@ struct BigUInt(Absable, IntableRaising, Stringable, Writable): # Constructors and life time dunder methods # # __init__(out self) - # __init__(out self, owned words: List[UInt32]) - # __init__(out self, owned *words: UInt32) + # __init__(out self, var words: List[UInt32]) + # __init__(out self, var *words: UInt32) # __init__(out self, value: Int) raises # __init__(out self, value: Scalar) raises # __init__(out self, value: String, ignore_sign: Bool = False) raises @@ -143,7 +142,7 @@ struct BigUInt(Absable, IntableRaising, Stringable, Writable): """ self.words = List[UInt32](unsafe_uninit_length=unsafe_uninit_length) - fn __init__(out self, owned words: List[UInt32]): + fn __init__(out self, var words: List[UInt32]): """Initializes a BigUInt from a list of UInt32 words. It does not verify whether the words are within the valid range See `from_list()` for safer initialization. @@ -163,7 +162,7 @@ struct BigUInt(Absable, IntableRaising, Stringable, Writable): else: self.words = words^ - fn __init__(out self, owned *words: UInt32): + fn __init__(out self, var *words: UInt32): """Initializes a BigUInt from raw words without validating the words. See `from_words()` for safer initialization. @@ -232,7 +231,7 @@ struct BigUInt(Absable, IntableRaising, Stringable, Writable): # ===------------------------------------------------------------------=== # # Constructing methods that are not dunders # - # from_list(owned words: List[UInt32]) -> Self + # from_list(var words: List[UInt32]) -> Self # from_words(*words: UInt32) -> Self # from_int(value: Int) -> Self # from_unsigned_integral_scalar[dtype: DType](value: Scalar[dtype]) -> Self @@ -240,7 +239,7 @@ struct BigUInt(Absable, IntableRaising, Stringable, Writable): # ===------------------------------------------------------------------=== # @staticmethod - fn from_list(owned words: List[UInt32]) raises -> Self: + fn from_list(var words: List[UInt32]) raises -> Self: """Initializes a BigUInt from a list of UInt32 words safely. If the list is empty, the BigUInt is initialized with value 0. The words are validated to ensure they are smaller than `999_999_999`. @@ -333,8 +332,8 @@ struct BigUInt(Absable, IntableRaising, Stringable, Writable): # Now we can safely copy the words result = BigUInt(words=List[UInt32](unsafe_uninit_length=n_words)) memcpy( - dest=result.words.data, - src=value.words.data + start_index, + dest=result.words._data, + src=value.words._data + start_index, count=n_words, ) result.remove_leading_empty_words() @@ -687,15 +686,15 @@ struct BigUInt(Absable, IntableRaising, Stringable, Writable): ) if len(self.words) == 1: - return self.words.data.load[width=1]().cast[DType.uint64]() + return self.words._data.load[width=1]().cast[DType.uint64]() elif len(self.words) == 2: return ( - self.words.data.load[width=2]().cast[DType.uint64]() + self.words._data.load[width=2]().cast[DType.uint64]() * SIMD[DType.uint64, 2](1, 1_000_000_000) ).reduce_add() else: return ( - self.words.data.load[width=4]().cast[DType.uint64]() + self.words._data.load[width=4]().cast[DType.uint64]() * SIMD[DType.uint64, 4]( 1, 1_000_000_000, @@ -711,10 +710,10 @@ struct BigUInt(Absable, IntableRaising, Stringable, Writable): This method quickly convert BigUInt with 2 words into UInt64. """ if len(self.words) == 1: - return self.words.data.load[width=1]().cast[DType.uint64]() + return self.words._data.load[width=1]().cast[DType.uint64]() else: # len(self.words) == 2 return ( - self.words.data.load[width=2]().cast[DType.uint64]() + self.words._data.load[width=2]().cast[DType.uint64]() * SIMD[DType.uint64, 2](1, 1_000_000_000) ).reduce_add() @@ -740,22 +739,22 @@ struct BigUInt(Absable, IntableRaising, Stringable, Writable): var result: UInt128 = 0 if len(self.words) == 1: - result = self.words.data.load[width=1]().cast[DType.uint128]() + result = self.words._data.load[width=1]().cast[DType.uint128]() elif len(self.words) == 2: result = ( - self.words.data.load[width=2]().cast[DType.uint128]() + self.words._data.load[width=2]().cast[DType.uint128]() * SIMD[DType.uint128, 2](1, 1_000_000_000) ).reduce_add() elif len(self.words) == 3: result = ( - self.words.data.load[width=4]().cast[DType.uint128]() + self.words._data.load[width=4]().cast[DType.uint128]() * SIMD[DType.uint128, 4]( 1, 1_000_000_000, 1_000_000_000_000_000_000, 0 ) ).reduce_add() elif len(self.words) == 4: result = ( - self.words.data.load[width=4]().cast[DType.uint128]() + self.words._data.load[width=4]().cast[DType.uint128]() * SIMD[DType.uint128, 4]( 1, 1_000_000_000, @@ -765,7 +764,7 @@ struct BigUInt(Absable, IntableRaising, Stringable, Writable): ).reduce_add() else: result = ( - self.words.data.load[width=8]().cast[DType.uint128]() + self.words._data.load[width=8]().cast[DType.uint128]() * SIMD[DType.uint128, 8]( 1, 1_000_000_000, @@ -788,22 +787,22 @@ struct BigUInt(Absable, IntableRaising, Stringable, Writable): """ if len(self.words) == 1: - return self.words.data.load[width=1]().cast[DType.uint128]() + return self.words._data.load[width=1]().cast[DType.uint128]() elif len(self.words) == 2: return ( - self.words.data.load[width=2]().cast[DType.uint128]() + self.words._data.load[width=2]().cast[DType.uint128]() * SIMD[DType.uint128, 2](1, 1_000_000_000) ).reduce_add() elif len(self.words) == 3: return ( - self.words.data.load[width=4]().cast[DType.uint128]() + self.words._data.load[width=4]().cast[DType.uint128]() * SIMD[DType.uint128, 4]( 1, 1_000_000_000, 1_000_000_000_000_000_000, 0 ) ).reduce_add() else: # len(self.words) == 4 return ( - self.words.data.load[width=4]().cast[DType.uint128]() + self.words._data.load[width=4]().cast[DType.uint128]() * SIMD[DType.uint128, 4]( 1, 1_000_000_000, diff --git a/src/decimojo/biguint/comparison.mojo b/src/decimojo/biguint/comparison.mojo index 398f8a5..5117bb9 100644 --- a/src/decimojo/biguint/comparison.mojo +++ b/src/decimojo/biguint/comparison.mojo @@ -18,8 +18,6 @@ Implements functions for comparison operations on BigUInt objects. """ -import testing - from decimojo.biguint.biguint import BigUInt diff --git a/src/decimojo/biguint/exponential.mojo b/src/decimojo/biguint/exponential.mojo index 1382487..0645f10 100644 --- a/src/decimojo/biguint/exponential.mojo +++ b/src/decimojo/biguint/exponential.mojo @@ -55,7 +55,7 @@ fn sqrt(x: BigUInt) -> BigUInt: var res = UInt32( math.sqrt( ( - x.words.data.load[width=2]().cast[DType.uint64]() + x.words._data.load[width=2]().cast[DType.uint64]() * SIMD[DType.uint64, 2](1, 1_000_000_000) ).reduce_add() ) @@ -161,7 +161,7 @@ fn sqrt_initial_guess(x: BigUInt) -> BigUInt: msw_sqrt = UInt32( math.sqrt( ( - x.words.data.load[width=2](len(x.words) - 2).cast[ + x.words._data.load[width=2](len(x.words) - 2).cast[ DType.uint64 ]() * SIMD[DType.uint64, 2](1, 1_000_000_000) diff --git a/src/decimojo/decimal128/decimal128.mojo b/src/decimojo/decimal128/decimal128.mojo index fdbbaf0..4117e1c 100644 --- a/src/decimojo/decimal128/decimal128.mojo +++ b/src/decimojo/decimal128/decimal128.mojo @@ -1502,7 +1502,7 @@ struct Decimal128( # | UInt128(self.low) # ) - fn extend_precision(self, owned precision_diff: Int) raises -> Decimal128: + fn extend_precision(self, var precision_diff: Int) raises -> Decimal128: """Returns a number with additional decimal128 places (trailing zeros). This multiplies the coefficient by 10^precision_diff and increases the scale accordingly, preserving the numeric value. diff --git a/src/decimojo/decimal128/utility.mojo b/src/decimojo/decimal128/utility.mojo index 73d246a..a976098 100644 --- a/src/decimojo/decimal128/utility.mojo +++ b/src/decimojo/decimal128/utility.mojo @@ -532,7 +532,7 @@ fn number_of_digits[dtype: DType, //](value: Scalar[dtype]) -> Int: return 59 -fn number_of_bits[dtype: DType, //](owned value: Scalar[dtype]) -> Int: +fn number_of_bits[dtype: DType, //](var value: Scalar[dtype]) -> Int: """ Returns the number of significant bits in an integer value. diff --git a/src/decimojo/errors.mojo b/src/decimojo/errors.mojo index 4513a7b..97d870e 100644 --- a/src/decimojo/errors.mojo +++ b/src/decimojo/errors.mojo @@ -19,7 +19,7 @@ Implement error handling for DeciMojo. """ -struct DeciError: +struct DeciError(Stringable): var error_type: String var message: String var function: String diff --git a/src/decimojo/tests.mojo b/src/decimojo/tests.mojo index 62c90ff..6e785c2 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, owned other: Self): + fn __moveinit__(out self, var other: Self): self.a = other.a^ self.b = other.b^ self.expected = other.expected^ diff --git a/src/tomlmojo/parser.mojo b/src/tomlmojo/parser.mojo index 8acded0..9ba7008 100644 --- a/src/tomlmojo/parser.mojo +++ b/src/tomlmojo/parser.mojo @@ -24,8 +24,7 @@ from collections import Dict from .tokenizer import Token, TokenType, Tokenizer -@value -struct TOMLValue: +struct TOMLValue(Copyable, Movable): """Represents a value in the TOML document.""" var type: TOMLValueType @@ -123,8 +122,7 @@ struct TOMLValue: return False -@value -struct TOMLValueType: +struct TOMLValueType(Copyable, Movable): """Types of values in TOML.""" # Aliases to mimic enum constants @@ -198,8 +196,7 @@ struct TOMLValueType: return "UNKNOWN" -@value -struct TOMLDocument: +struct TOMLDocument(Copyable, Movable): """Represents a parsed TOML document.""" var root: Dict[String, TOMLValue] diff --git a/src/tomlmojo/tokenizer.mojo b/src/tomlmojo/tokenizer.mojo index b043cd5..10a1962 100644 --- a/src/tomlmojo/tokenizer.mojo +++ b/src/tomlmojo/tokenizer.mojo @@ -27,8 +27,7 @@ alias QUOTE = '"' alias LITERAL_QUOTE = "'" -@value -struct Token: +struct Token(Copyable, Movable): """Represents a token in the TOML document.""" var type: TokenType @@ -45,7 +44,6 @@ struct Token: self.column = column -@value struct SourcePosition: """Tracks position in the source text.""" @@ -68,8 +66,7 @@ struct SourcePosition: self.index += 1 -@value -struct TokenType: +struct TokenType(Copyable, Movable): """ TokenType mimics an enum for token types in TOML. """