diff --git a/benches/bench.mojo b/benches/bench.mojo index 73b9acf..d7a6c23 100644 --- a/benches/bench.mojo +++ b/benches/bench.mojo @@ -5,11 +5,13 @@ from bench_divide import main as bench_divide from bench_sqrt import main as bench_sqrt from bench_from_float import main as bench_from_float from bench_from_string import main as bench_from_string +from bench_from_int import main as bench_from_int from bench_round import main as bench_round from bench_comparison import main as bench_comparison from bench_exp import main as bench_exp from bench_ln import main as bench_ln from bench_power import main as bench_power +from bench_root import main as bench_root fn main() raises: @@ -20,8 +22,10 @@ fn main() raises: bench_sqrt() bench_from_float() bench_from_string() + bench_from_int() bench_round() bench_comparison() bench_exp() bench_ln() bench_power() + bench_root() diff --git a/benches/bench_from_int.mojo b/benches/bench_from_int.mojo new file mode 100644 index 0000000..5399ebe --- /dev/null +++ b/benches/bench_from_int.mojo @@ -0,0 +1,361 @@ +""" +Comprehensive benchmarks for Decimal.from_int() constructor. +Compares performance against Python's decimal module with 20 diverse test cases. +""" + +from decimojo.prelude import dm, Decimal, RoundingMode +from python import Python, PythonObject +from time import perf_counter_ns +import time +import os +from collections import List + + +fn open_log_file() raises -> PythonObject: + """ + Creates and opens a log file with a timestamp in the filename. + + Returns: + A file object opened for writing. + """ + var python = Python.import_module("builtins") + var datetime = Python.import_module("datetime") + + # Create logs directory if it doesn't exist + var log_dir = "./logs" + if not os.path.exists(log_dir): + os.makedirs(log_dir) + + # Generate a timestamp for the filename + var timestamp = String(datetime.datetime.now().isoformat()) + var log_filename = log_dir + "/benchmark_from_int_" + timestamp + ".log" + + print("Saving benchmark results to:", log_filename) + return python.open(log_filename, "w") + + +fn log_print(msg: String, log_file: PythonObject) raises: + """ + Prints a message to both the console and the log file. + + Args: + msg: The message to print. + log_file: The file object to write to. + """ + print(msg) + log_file.write(msg + "\n") + log_file.flush() # Ensure the message is written immediately + + +fn run_benchmark( + name: String, + input_value: Int, + iterations: Int, + log_file: PythonObject, + mut speedup_factors: List[Float64], +) raises: + """ + Run a benchmark comparing Mojo Decimal.from_int with Python Decimal constructor. + + Args: + name: Name of the benchmark case. + input_value: Integer value to convert. + iterations: Number of iterations to run. + log_file: File object for logging results. + speedup_factors: Mojo List to store speedup factors for averaging. + """ + log_print("\nBenchmark: " + name, log_file) + log_print("Input value: " + String(input_value), log_file) + + # Execute the operations once to verify correctness + var mojo_result = Decimal.from_int(input_value) + var pydecimal = Python.import_module("decimal") + var py_result = pydecimal.Decimal(input_value) + + # Display results for verification + log_print("Mojo result: " + String(mojo_result), log_file) + log_print("Python result: " + String(py_result), log_file) + + # Benchmark Mojo implementation + var t0 = perf_counter_ns() + for _ in range(iterations): + _ = Decimal.from_int(input_value) + var mojo_time = (perf_counter_ns() - t0) / iterations + if mojo_time == 0: + mojo_time = 1 # Prevent division by zero + + # Benchmark Python implementation + t0 = perf_counter_ns() + for _ in range(iterations): + _ = pydecimal.Decimal(input_value) + var python_time = (perf_counter_ns() - t0) / iterations + + # Calculate speedup factor + var speedup = python_time / mojo_time + speedup_factors.append(Float64(speedup)) + + # Print results with speedup comparison + log_print( + "Mojo from_int(): " + String(mojo_time) + " ns per iteration", + log_file, + ) + log_print( + "Python Decimal(): " + String(python_time) + " ns per iteration", + log_file, + ) + log_print("Speedup factor: " + String(speedup), log_file) + + +fn main() raises: + # Open log file + var log_file = open_log_file() + var datetime = Python.import_module("datetime") + + # Create a Mojo List to store speedup factors for averaging later + var speedup_factors = List[Float64]() + + # Display benchmark header with system information + log_print("=== DeciMojo from_int() Constructor Benchmark ===", log_file) + log_print("Time: " + String(datetime.datetime.now().isoformat()), log_file) + + # Try to get system info + try: + var platform = Python.import_module("platform") + log_print( + "System: " + + String(platform.system()) + + " " + + String(platform.release()), + log_file, + ) + log_print("Processor: " + String(platform.processor()), log_file) + log_print( + "Python version: " + String(platform.python_version()), log_file + ) + except: + log_print("Could not retrieve system information", log_file) + + var iterations = 10000 # More iterations since this is a fast operation + var pydecimal = Python().import_module("decimal") + + # Set Python decimal precision to match Mojo's + pydecimal.getcontext().prec = 28 + log_print( + "Python decimal precision: " + String(pydecimal.getcontext().prec), + log_file, + ) + log_print("Mojo decimal precision: " + String(Decimal.MAX_SCALE), log_file) + + # Define benchmark cases + log_print( + "\nRunning from_int() constructor benchmarks with " + + String(iterations) + + " iterations each", + log_file, + ) + + # Case 1: Zero + run_benchmark( + "Zero", + 0, + iterations, + log_file, + speedup_factors, + ) + + # Case 2: Small positive integer + run_benchmark( + "Small positive integer", + 1, + iterations, + log_file, + speedup_factors, + ) + + # Case 3: Medium positive integer + run_benchmark( + "Medium positive integer", + 1000, + iterations, + log_file, + speedup_factors, + ) + + # Case 4: Large positive integer + run_benchmark( + "Large positive integer", + 1000000000, + iterations, + log_file, + speedup_factors, + ) + + # Case 5: Small negative integer + run_benchmark( + "Small negative integer", + -1, + iterations, + log_file, + speedup_factors, + ) + + # Case 6: Medium negative integer + run_benchmark( + "Medium negative integer", + -1000, + iterations, + log_file, + speedup_factors, + ) + + # Case 7: Large negative integer + run_benchmark( + "Large negative integer", + -1000000000, + iterations, + log_file, + speedup_factors, + ) + + # Case 8: Power of 10 (small) + run_benchmark( + "Power of 10 (small)", + 10, + iterations, + log_file, + speedup_factors, + ) + + # Case 9: Power of 10 (medium) + run_benchmark( + "Power of 10 (medium)", + 100000, + iterations, + log_file, + speedup_factors, + ) + + # Case 10: Power of 10 (large) + run_benchmark( + "Power of 10 (large)", + 1000000000, + iterations, + log_file, + speedup_factors, + ) + + # Case 11: Power of 2 (small) + run_benchmark( + "Power of 2 (small)", + 1024, + iterations, + log_file, + speedup_factors, + ) + + # Case 12: Power of 2 (medium) + run_benchmark( + "Power of 2 (medium)", + 65536, + iterations, + log_file, + speedup_factors, + ) + + # Case 13: Integer with repeating digits (9s) + run_benchmark( + "Integer with repeating 9s", + 9999999, + iterations, + log_file, + speedup_factors, + ) + + # Case 14: Integer with repeating digits (8s) + run_benchmark( + "Integer with repeating 8s", + 88888888, + iterations, + log_file, + speedup_factors, + ) + + # Case 15: Integer with alternating digits (1s and 2s) + run_benchmark( + "Integer with alternating 1s and 2s", + 12121212, + iterations, + log_file, + speedup_factors, + ) + + # Case 16: Integer with alternating digits (9s and 0s) + run_benchmark( + "Integer with alternating 9s and 0s", + 9090909, + iterations, + log_file, + speedup_factors, + ) + + # Case 17: Close to INT32_MAX + run_benchmark( + "Close to INT32_MAX", + 2147483647, + iterations, + log_file, + speedup_factors, + ) + + # Case 18: Close to INT32_MIN + run_benchmark( + "Close to INT32_MIN", + -2147483648, + iterations, + log_file, + speedup_factors, + ) + + # Case 19: Very large positive integer (close to INT64_MAX) + run_benchmark( + "Very large positive integer", + 9223372036854775807, + iterations, + log_file, + speedup_factors, + ) + + # Case 20: Very large negative integer (close to INT64_MIN) + run_benchmark( + "Very large negative integer", + -9223372036854775807, + iterations, + log_file, + speedup_factors, + ) + + # Calculate average speedup factor + var sum_speedup: Float64 = 0.0 + for i in range(len(speedup_factors)): + sum_speedup += speedup_factors[i] + var average_speedup = sum_speedup / Float64(len(speedup_factors)) + + # Display summary + log_print("\n=== from_int() Constructor Benchmark Summary ===", log_file) + log_print("Benchmarked: 20 different from_int() cases", log_file) + log_print( + "Each case ran: " + String(iterations) + " iterations", log_file + ) + log_print("Average speedup: " + String(average_speedup) + "×", log_file) + + # List all speedup factors + log_print("\nIndividual speedup factors:", log_file) + for i in range(len(speedup_factors)): + log_print( + String("Case {}: {}×").format(i + 1, round(speedup_factors[i], 2)), + log_file, + ) + + # Close the log file + log_file.close() + print("Benchmark completed. Log file closed.") diff --git a/mojoproject.toml b/mojoproject.toml index 401fd32..96486be 100644 --- a/mojoproject.toml +++ b/mojoproject.toml @@ -38,9 +38,10 @@ test_divide = "magic run package && magic run mojo test tests/test_divide.mojo & test_sqrt = "magic run package && magic run mojo test tests/test_sqrt.mojo && magic run delete_package" test_root = "magic run package && magic run mojo test tests/test_root.mojo && magic run delete_package" test_round = "magic run package && magic run mojo test tests/test_round.mojo && magic run delete_package" -test_creation = "magic run package && magic run mojo test tests/test_creation.mojo && magic run delete_package" +test_from_components = "magic run package && magic run mojo test tests/test_from_components.mojo && magic run delete_package" test_from_float = "magic run package && magic run mojo test tests/test_from_float.mojo && magic run delete_package" test_from_string = "magic run package && magic run mojo test tests/test_from_string.mojo && magic run delete_package" +test_from_int = "magic run package && magic run mojo test tests/test_from_int.mojo && magic run delete_package" test_to_float = "magic run package && magic run mojo test tests/test_to_float.mojo && magic run delete_package" test_comparison = "magic run package && magic run mojo test tests/test_comparison.mojo && magic run delete_package" test_factorial = "magic run package && magic run mojo test tests/test_factorial.mojo && magic run delete_package" @@ -58,6 +59,7 @@ bench_root = "magic run package && cd benches && magic run mojo bench_root.mojo bench_round = "magic run package && cd benches && magic run mojo bench_round.mojo && cd .. && magic run delete_package" bench_from_float = "magic run package && cd benches && magic run mojo bench_from_float.mojo && cd .. && magic run delete_package" bench_from_string = "magic run package && cd benches && magic run mojo bench_from_string.mojo && cd .. && magic run delete_package" +bench_from_int = "magic run package && cd benches && magic run mojo bench_from_int.mojo && cd .. && magic run delete_package" bench_comparison = "magic run package && cd benches && magic run mojo bench_comparison.mojo && cd .. && magic run delete_package" bench_exp = "magic run package && cd benches && magic run mojo bench_exp.mojo && cd .. && magic run delete_package" bench_ln = "magic run package && cd benches && magic run mojo bench_ln.mojo && cd .. && magic run delete_package" diff --git a/src/decimojo/decimal.mojo b/src/decimojo/decimal.mojo index d4b06e3..3c57bee 100644 --- a/src/decimojo/decimal.mojo +++ b/src/decimojo/decimal.mojo @@ -138,61 +138,46 @@ struct Decimal( # TODO: Move these special values to top of the module # when Mojo support global variables in the future. - # + # Special values @staticmethod fn INFINITY() -> Decimal: - """ - Returns a Decimal representing positive infinity. + """Returns a Decimal representing positive infinity. Internal representation: `0b0000_0000_0000_0000_0000_0000_0001`. """ return Decimal(0, 0, 0, 0x00000001) @staticmethod fn NEGATIVE_INFINITY() -> Decimal: - """ - Returns a Decimal representing negative infinity. + """Returns a Decimal representing negative infinity. Internal representation: `0b1000_0000_0000_0000_0000_0000_0001`. """ return Decimal(0, 0, 0, 0x80000001) @staticmethod fn NAN() -> Decimal: - """ - Returns a Decimal representing Not a Number (NaN). + """Returns a Decimal representing Not a Number (NaN). Internal representation: `0b0000_0000_0000_0000_0000_0000_0010`. """ return Decimal(0, 0, 0, 0x00000010) @staticmethod fn NEGATIVE_NAN() -> Decimal: - """ - Returns a Decimal representing negative Not a Number. + """Returns a Decimal representing negative Not a Number. Internal representation: `0b1000_0000_0000_0000_0000_0000_0010`. """ return Decimal(0, 0, 0, 0x80000010) @staticmethod fn ZERO() -> Decimal: - """ - Returns a Decimal representing 0. - """ + """Returns a Decimal representing 0.""" return Decimal(0, 0, 0, 0) @staticmethod fn ONE() -> Decimal: - """ - Returns a Decimal representing 1. - """ + """Returns a Decimal representing 1.""" return Decimal(1, 0, 0, 0) - @staticmethod - fn NEGATIVE_ONE() -> Decimal: - """ - Returns a Decimal representing -1. - """ - return Decimal(1, 0, 0, Decimal.SIGN_MASK) - @staticmethod fn MAX() -> Decimal: """ @@ -223,9 +208,7 @@ struct Decimal( # ===------------------------------------------------------------------=== # fn __init__(out self): - """ - Initializes a decimal instance with value 0. - """ + """Initializes a decimal instance with value 0.""" self.low = 0x00000000 self.mid = 0x00000000 self.high = 0x00000000 @@ -234,8 +217,7 @@ struct Decimal( fn __init__( out self, low: UInt32, mid: UInt32, high: UInt32, flags: UInt32 ): - """ - Initializes a Decimal with four raw words of internal representation. + """Initializes a Decimal with four raw words of internal representation. ***WARNING***: This method does not check the flags. If you are not sure about the flags, use `Decimal.from_words()` instead. """ @@ -253,8 +235,7 @@ struct Decimal( scale: UInt32, sign: Bool, ) raises: - """ - Initializes a Decimal with five components. + """Initializes a Decimal with five components. See `Decimal.from_components()` for more information. """ @@ -265,9 +246,14 @@ struct Decimal( "Error in `Decimal.__init__()` with five components: ", e ) - fn __init__(out self, value: Int, scale: UInt32 = 0) raises: + fn __init__(out self, value: Int): + """Initializes a Decimal from an integer. + See `from_int()` for more information. """ - Initializes a Decimal from an integer. + self = Decimal.from_int(value) + + fn __init__(out self, value: Int, scale: UInt32) raises: + """Initializes a Decimal from an integer. See `from_int()` for more information. """ try: @@ -276,8 +262,7 @@ struct Decimal( raise Error("Error in `Decimal.__init__()` with Int: ", e) fn __init__(out self, value: String) raises: - """ - Initializes a Decimal from a string representation. + """Initializes a Decimal from a string representation. See `from_string()` for more information. """ try: @@ -286,8 +271,7 @@ struct Decimal( raise Error("Error in `Decimal__init__()` with String: ", e) fn __init__(out self, value: Float64) raises: - """ - Initializes a Decimal from a floating-point value. + """Initializes a Decimal from a floating-point value. See `from_float` for more information. """ @@ -297,9 +281,7 @@ struct Decimal( raise Error("Error in `Decimal__init__()` with Float64: ", e) fn __copyinit__(out self, other: Self): - """ - Initializes a Decimal by copying another Decimal. - """ + """Initializes a Decimal by copying another Decimal.""" self.low = other.low self.mid = other.mid self.high = other.high @@ -317,8 +299,7 @@ struct Decimal( scale: UInt32, sign: Bool, ) raises -> Self: - """ - Initializes a Decimal with five components. + """Initializes a Decimal with five components. Args: low: Least significant 32 bits of coefficient. @@ -352,8 +333,7 @@ struct Decimal( fn from_words( low: UInt32, mid: UInt32, high: UInt32, flags: UInt32 ) raises -> Self: - """ - Initializes a Decimal with four raw words of internal representation. + """Initializes a Decimal with four raw words of internal representation. Compared to `__init__()` with four words, this method checks the flags. Args: @@ -389,9 +369,47 @@ struct Decimal( return Decimal(low, mid, high, flags) @staticmethod - fn from_int(value: Int, scale: UInt32) raises -> Self: + fn from_int(value: Int) -> Self: + """Initializes a Decimal from an integer. + + Args: + value: The integer value to convert to Decimal. + + Returns: + The Decimal representation of the integer. + + Notes: + + Since Int is a 64-bit type in Mojo, the `high` field will always be 0. + + Examples: + ```mojo + from decimojo import Decimal + var dec1 = Decimal.from_int(-123) # -123 + var dec2 = Decimal.from_int(1) # 1 + ``` + End of examples. """ - Initializes a Decimal from an integer. + + var low: UInt32 + var mid: UInt32 + var flags: UInt32 + + if value >= 0: + flags = 0 + low = UInt32(value & 0xFFFFFFFF) + mid = UInt32((value >> 32) & 0xFFFFFFFF) + else: + var abs_value = -value + flags = Self.SIGN_MASK + low = UInt32(abs_value & 0xFFFFFFFF) + mid = UInt32((abs_value >> 32) & 0xFFFFFFFF) + + return Decimal(low, mid, 0, flags) + + @staticmethod + fn from_int(value: Int, scale: UInt32) raises -> Self: + """Initializes a Decimal from an integer and a scale. Args: value: The integer value to convert to Decimal. @@ -404,12 +422,20 @@ struct Decimal( Error: If the scale is greater than MAX_SCALE. Notes: + Since Int is a 64-bit type in Mojo, the `high` field will always be 0. + + Examples: + ```mojo + from decimojo import Decimal + var dec1 = Decimal.from_int(-123, scale=2) # -1.23 + var dec2 = Decimal.from_int(1, scale=5) # 0.00001 + ``` + End of examples. """ var low: UInt32 var mid: UInt32 - var high: UInt32 var flags: UInt32 if scale > Self.MAX_SCALE: @@ -424,25 +450,22 @@ struct Decimal( flags = 0 low = UInt32(value & 0xFFFFFFFF) mid = UInt32((value >> 32) & 0xFFFFFFFF) - high = 0 else: var abs_value = -value flags = Self.SIGN_MASK low = UInt32(abs_value & 0xFFFFFFFF) mid = UInt32((abs_value >> 32) & 0xFFFFFFFF) - high = 0 flags |= (scale << Self.SCALE_SHIFT) & Self.SCALE_MASK - return Decimal(low, mid, high, flags) + return Decimal(low, mid, 0, flags) @staticmethod fn from_uint128( value: UInt128, scale: UInt32 = 0, sign: Bool = False ) raises -> Decimal: - """ - Initializes a Decimal from a UInt128 value. + """Initializes a Decimal from a UInt128 value. Args: value: The UInt128 value to convert to Decimal. @@ -483,8 +506,7 @@ struct Decimal( @staticmethod fn from_string(value: String) raises -> Decimal: - """ - Initializes a Decimal from a string representation. + """Initializes a Decimal from a string representation. Args: value: The string representation of the Decimal. @@ -743,8 +765,7 @@ struct Decimal( @staticmethod fn from_float(value: Float64) raises -> Decimal: - """ - Initializes a Decimal from a floating-point value. + """Initializes a Decimal from a floating-point value. The reliability of this method is limited by the precision of Float64. Float64 is reliable up to 15 significant digits and marginally reliable up to 16 siginficant digits. Be careful when using this method. @@ -860,13 +881,20 @@ struct Decimal( # Return both the significant digits and the scale return Decimal(low, mid, high, scale, is_negative) + fn copy(self) -> Self: + """Returns a copy of the Decimal.""" + return Decimal(self.low, self.mid, self.high, self.flags) + + fn clone(self) -> Self: + """Returns a copy of the Decimal.""" + return Decimal(self.low, self.mid, self.high, self.flags) + # ===------------------------------------------------------------------=== # # Output dunders, type-transfer dunders # ===------------------------------------------------------------------=== # fn __float__(self) -> Float64: - """ - Converts this Decimal to a floating-point value. + """Converts this Decimal to a floating-point value. Because Decimal is fixed-point, this may lose precision. Returns: @@ -879,8 +907,7 @@ struct Decimal( return result fn __int__(self) raises -> Int: - """ - Returns the integral part of the Decimal as Int. + """Returns the integral part of the Decimal as Int. See `to_int()` for more information. """ try: @@ -889,8 +916,7 @@ struct Decimal( raise Error("Error in `Decimal.__int__()` with Int: ", e) fn __str__(self) -> String: - """ - Returns string representation of the Decimal. + """Returns string representation of the Decimal. Preserves trailing zeros after decimal point to match the scale. """ # Get the coefficient as a string (absolute value) @@ -932,9 +958,7 @@ struct Decimal( return result fn __repr__(self) -> String: - """ - Returns a string representation of the Decimal. - """ + """Returns a string representation of the Decimal.""" return 'Decimal("' + self.__str__() + '")' # ===------------------------------------------------------------------=== # @@ -1019,9 +1043,7 @@ struct Decimal( return Int64(result & 0xFFFF_FFFF_FFFF_FFFF) fn to_int128(self) -> Int128: - """ - Returns the signed integral part of the Decimal. - """ + """Returns the signed integral part of the Decimal.""" var res = Int128(self.to_uint128()) @@ -1055,8 +1077,7 @@ struct Decimal( # ===------------------------------------------------------------------=== # fn __abs__(self) -> Self: - """ - Returns the absolute value of this Decimal. + """Returns the absolute value of this Decimal. Returns: The absolute value of this Decimal. @@ -1065,8 +1086,7 @@ struct Decimal( return decimojo.arithmetics.absolute(self) fn __neg__(self) -> Self: - """ - Returns the negation of this Decimal. + """Returns the negation of this Decimal. Returns: The negation of this Decimal. @@ -1255,8 +1275,7 @@ struct Decimal( # ===------------------------------------------------------------------=== # fn __gt__(self, other: Decimal) -> Bool: - """ - Greater than comparison operator. + """Greater than comparison operator. Args: other: The Decimal to compare with. @@ -1267,8 +1286,7 @@ struct Decimal( return decimojo.comparison.greater(self, other) fn __lt__(self, other: Decimal) -> Bool: - """ - Less than comparison operator. + """Less than comparison operator. Args: other: The Decimal to compare with. @@ -1279,8 +1297,7 @@ struct Decimal( return decimojo.comparison.less(self, other) fn __ge__(self, other: Decimal) -> Bool: - """ - Greater than or equal comparison operator. + """Greater than or equal comparison operator. Args: other: The Decimal to compare with. @@ -1291,8 +1308,7 @@ struct Decimal( return decimojo.comparison.greater_equal(self, other) fn __le__(self, other: Decimal) -> Bool: - """ - Less than or equal comparison operator. + """Less than or equal comparison operator. Args: other: The Decimal to compare with. @@ -1303,8 +1319,7 @@ struct Decimal( return decimojo.comparison.less_equal(self, other) fn __eq__(self, other: Decimal) -> Bool: - """ - Equality comparison operator. + """Equality comparison operator. Args: other: The Decimal to compare with. @@ -1315,8 +1330,7 @@ struct Decimal( return decimojo.comparison.equal(self, other) fn __ne__(self, other: Decimal) -> Bool: - """ - Inequality comparison operator. + """Inequality comparison operator. Args: other: The Decimal to compare with. @@ -1332,8 +1346,7 @@ struct Decimal( # ===------------------------------------------------------------------=== # fn __round__(self, ndigits: Int) -> Self: - """ - Rounds this Decimal to the specified number of decimal places. + """Rounds this Decimal to the specified number of decimal places. If `ndigits` is not given, rounds to 0 decimal places. If rounding causes overflow, returns the value itself. @@ -1359,11 +1372,8 @@ struct Decimal( # ===------------------------------------------------------------------=== # fn exp(self) raises -> Self: - """ - Calculates the exponential of this Decimal. - - Returns: - The exponential of this Decimal. + """Calculates the exponential of this Decimal. + See `exp()` for more information. """ try: @@ -1372,6 +1382,9 @@ struct Decimal( raise Error("Error in `Decimal.exp()`: ", e) fn ln(self) raises -> Self: + """Calculates the natural logarithm of this Decimal. + See `ln()` for more information. + """ try: return decimojo.exponential.ln(self) except e: @@ -1382,8 +1395,7 @@ struct Decimal( ndigits: Int = 0, rounding_mode: RoundingMode = RoundingMode.ROUND_HALF_EVEN, ) raises -> Self: - """ - Rounds this Decimal to the specified number of decimal places. + """Rounds this Decimal to the specified number of decimal places. Compared to `__round__`, this method: (1) Allows specifying the rounding mode. (2) Raises an error if the operation would result in overflow. @@ -1431,8 +1443,7 @@ struct Decimal( # ===------------------------------------------------------------------=== # fn coefficient(self) -> UInt128: - """ - Returns the unscaled integer coefficient as an UInt128 value. + """Returns the unscaled integer coefficient as an UInt128 value. This is the absolute value of the decimal digits without considering the scale. The value of the coefficient is: `high * 2**64 + mid * 2**32 + low`. @@ -1535,8 +1546,7 @@ struct Decimal( return self.number_of_significant_digits() - 1 - self.scale() fn number_of_significant_digits(self) -> Int: - """ - Returns the number of significant digits in the Decimal. + """Returns the number of significant digits in the Decimal. The number of significant digits is the total number of digits in the coefficient, excluding leading zeros but including trailing zeros. @@ -1570,9 +1580,7 @@ struct Decimal( # ===------------------------------------------------------------------=== # fn internal_representation(value: Decimal): - """ - Prints the internal representation details of a Decimal. - """ + """Prints the internal representation details of a Decimal.""" print("\nInternal Representation Details:") print("--------------------------------") print("Decimal: ", value) diff --git a/src/decimojo/utility.mojo b/src/decimojo/utility.mojo index f7dcdbe..636d54d 100644 --- a/src/decimojo/utility.mojo +++ b/src/decimojo/utility.mojo @@ -428,7 +428,7 @@ fn round_to_keep_first_n_digits[ @always_inline -fn number_of_digits[dtype: DType](value: Scalar[dtype]) -> Int: +fn number_of_digits[dtype: DType, //](value: Scalar[dtype]) -> Int: """ Returns the number of (significant) digits in an integral value using binary search. This implementation is significantly faster than loop division. diff --git a/tests/test_arithmetics.mojo b/tests/test_arithmetics.mojo index 993f970..c43937a 100644 --- a/tests/test_arithmetics.mojo +++ b/tests/test_arithmetics.mojo @@ -11,60 +11,60 @@ fn test_add() raises: print("Testing decimal addition...") # Test case 1: Simple addition with same scale - var a1 = Decimal("123.45") - var b1 = Decimal("67.89") + var a1 = Decimal(12345, scale=2) # 123.45 + var b1 = Decimal(6789, scale=2) # 67.89 var result1 = a1 + b1 testing.assert_equal( String(result1), "191.34", "Simple addition with same scale" ) # Test case 2: Addition with different scales - var a2 = Decimal("123.4") - var b2 = Decimal("67.89") + var a2 = Decimal(1234, scale=1) + var b2 = Decimal(6789, scale=2) var result2 = a2 + b2 testing.assert_equal( String(result2), "191.29", "Addition with different scales" ) # Test case 3: Addition with negative numbers - var a3 = Decimal("123.45") - var b3 = Decimal("-67.89") + var a3 = Decimal(12345, scale=2) + var b3 = Decimal(-6789, scale=2) var result3 = a3 + b3 testing.assert_equal( String(result3), "55.56", "Addition with negative number" ) # Test case 4: Addition resulting in negative - var a4 = Decimal("-123.45") - var b4 = Decimal("67.89") + var a4 = Decimal(-12345, scale=2) + var b4 = Decimal(6789, scale=2) var result4 = a4 + b4 testing.assert_equal( String(result4), "-55.56", "Addition resulting in negative" ) # Test case 5: Addition with zero - var a5 = Decimal("123.45") - var b5 = Decimal("0.00") + var a5 = Decimal(12345, scale=2) + var b5 = Decimal(0, scale=2) var result5 = a5 + b5 testing.assert_equal(String(result5), "123.45", "Addition with zero") # Test case 6: Addition resulting in zero - var a6 = Decimal("123.45") - var b6 = Decimal("-123.45") + var a6 = Decimal(12345, scale=2) + var b6 = Decimal(-12345, scale=2) var result6 = a6 + b6 testing.assert_equal(String(result6), "0.00", "Addition resulting in zero") # Test case 7: Addition with large scales - var a7 = Decimal("0.0000001") - var b7 = Decimal("0.0000002") + var a7 = Decimal(1, scale=7) + var b7 = Decimal(2, scale=7) var result7 = a7 + b7 testing.assert_equal( String(result7), "0.0000003", "Addition with large scales" ) # Test case 8: Addition with different large scales - var a8 = Decimal("0.000001") - var b8 = Decimal("0.0000002") + var a8 = Decimal(1, scale=6) + var b8 = Decimal(2, scale=7) var result8 = a8 + b8 testing.assert_equal( String(result8), "0.0000012", "Addition with different large scales" @@ -73,8 +73,8 @@ fn test_add() raises: # Additional edge cases for addition # Test case 9: Addition with many decimal places - var a9 = Decimal("0.123456789012345678901234567") - var b9 = Decimal("0.987654321098765432109876543") + var a9 = Decimal.from_uint128(123456789012345678901234567, scale=27) + var b9 = Decimal.from_uint128(987654321098765432109876543, scale=27) var result9 = a9 + b9 testing.assert_equal( String(result9), @@ -83,8 +83,8 @@ fn test_add() raises: ) # Test case 10: Addition with extreme scale difference - var a10 = Decimal("123456789") - var b10 = Decimal("0.000000000123456789") + var a10 = Decimal(123456789) + var b10 = Decimal(123456789, scale=18) # 0.000000000123456789 var result10 = a10 + b10 testing.assert_equal( String(result10), @@ -93,8 +93,12 @@ fn test_add() raises: ) # Test case 11: Addition near maximum precision - var a11 = Decimal("0." + "1" * 28) # 0.1111...1 (28 digits) - var b11 = Decimal("0." + "9" * 28) # 0.9999...9 (28 digits) + var a11 = Decimal.from_uint128( + UInt128(1111111111111111111111111111), scale=28 + ) # 0.1111...1 (28 digits) + var b11 = Decimal.from_uint128( + UInt128(9999999999999999999999999999), scale=28 + ) # 0.9999...9 (28 digits) var result11 = a11 + b11 testing.assert_equal( String(result11), @@ -103,8 +107,12 @@ fn test_add() raises: ) # Test case 12: Addition causing scale truncation - var a12 = Decimal("0." + "1" * 27 + "1") # 0.1111...1 (28 digits) - var b12 = Decimal("0.0" + "9" * 27) # 0.09999...9 (28 digits) + var a12 = Decimal.from_uint128( + UInt128(1111111111111111111111111111), scale=28 + ) # 0.1111...1 (28 digits) + var b12 = Decimal.from_uint128( + UInt128(999999999999999999999999999), scale=28 + ) # 0.09999...9 (28 digits) var result12 = a12 + b12 testing.assert_equal( String(result12), @@ -113,8 +121,8 @@ fn test_add() raises: ) # Test case 13: Addition of very small numbers - var a13 = Decimal("0." + "0" * 27 + "1") # 0.0000...01 (1 at 28th place) - var b13 = Decimal("0." + "0" * 27 + "2") # 0.0000...02 (2 at 28th place) + var a13 = Decimal(1, scale=28) # 0.0000...01 (1 at 28th place) + var b13 = Decimal(2, scale=28) # 0.0000...02 (2 at 28th place) var result13 = a13 + b13 testing.assert_equal( String(result13), @@ -123,16 +131,18 @@ fn test_add() raises: ) # Test case 14: Addition with alternating signs and scales - var a14 = Decimal("1.01") - var b14 = Decimal("-0.101") + var a14 = Decimal(101, 2) + var b14 = Decimal(-101, 3) var result14 = a14 + b14 testing.assert_equal( String(result14), "0.909", "Addition with alternating signs and scales" ) # Test case 15: Addition with large numbers (near limits) - var a15 = Decimal("79228162514264337593543950334") # MAX() - 1 - var b15 = Decimal("1") + var a15 = Decimal.from_uint128( + UInt128(79228162514264337593543950334) + ) # MAX() - 1 + var b15 = Decimal(1) var result15 = a15 + b15 testing.assert_equal( String(result15), @@ -141,14 +151,14 @@ fn test_add() raises: ) # Test case 16: Repeated addition to test cumulative errors - var acc = Decimal("0") + var acc = Decimal(0) for _ in range(10): - acc = acc + Decimal("0.1") + acc = acc + Decimal(1, scale=1) testing.assert_equal(String(acc), "1.0", "Repeated addition of 0.1") # Test case 17: Edge case with alternating very large and very small values - var a17 = Decimal("1234567890123456789.0123456789") - var b17 = Decimal("0.0000000000000000009876543211") + var a17 = Decimal.from_uint128(12345678901234567890123456789, scale=10) + var b17 = Decimal(9876543211, scale=28) var result17 = a17 + b17 # 1234567890123456789.0123456789000000009876543211 testing.assert_equal( @@ -160,8 +170,10 @@ fn test_add() raises: print("Decimal addition tests passed!") # Test case 18: Edge case with one equals 0 - var a18 = Decimal("4563117171088016.3026696499898") - var b18 = Decimal("0.0000000000000000000000000000") + var a18 = Decimal.from_uint128( + UInt128(45631171710880163026696499898), scale=13 + ) + var b18 = Decimal(0, scale=28) var result18 = a18 + b18 # 1234567890123456789.0123456789 testing.assert_equal( @@ -178,43 +190,45 @@ fn test_negation() raises: print("Testing decimal negation...") # Test case 1: Negate positive number - var a1 = Decimal("123.45") + var a1 = Decimal(12345, 2) var result1 = -a1 testing.assert_equal(String(result1), "-123.45", "Negating positive number") # Test case 2: Negate negative number - var a2 = Decimal("-67.89") + var a2 = Decimal(-6789, 2) var result2 = -a2 testing.assert_equal(String(result2), "67.89", "Negating negative number") # Test case 3: Negate zero - var a3 = Decimal("0") + var a3 = Decimal(0) var result3 = -a3 testing.assert_equal(String(result3), "0", "Negating zero") # Test case 4: Negate number with trailing zeros - var a4 = Decimal("123.4500") + var a4 = Decimal(1234500, 4) var result4 = -a4 testing.assert_equal( String(result4), "-123.4500", "Negating with trailing zeros" ) # Test case 5: Double negation - var a5 = Decimal("123.45") + var a5 = Decimal(12345, 2) var result5 = -(-a5) testing.assert_equal(String(result5), "123.45", "Double negation") # Additional edge cases for negation # Test case 6: Negate very small number - var a6 = Decimal("0." + "0" * 27 + "1") # 0.0000...01 (1 at 28th place) + var a6 = Decimal(1, scale=28) # 0.0000...01 (1 at 28th place) var result6 = -a6 testing.assert_equal( String(result6), "-0." + "0" * 27 + "1", "Negating very small number" ) # Test case 7: Negate very large number - var a7 = Decimal("79228162514264337593543950335") # MAX() + var a7 = Decimal.from_uint128( + UInt128(79228162514264337593543950335) + ) # MAX() var result7 = -a7 testing.assert_equal( String(result7), @@ -223,21 +237,18 @@ fn test_negation() raises: ) # Test case 8: Triple negation - var a8 = Decimal("123.45") + var a8 = Decimal(12345, 2) var result8 = -(-(-a8)) testing.assert_equal(String(result8), "-123.45", "Triple negation") - # Test case 9: Negate number with scientific notation (if supported) - try: - var a9 = Decimal("1.23e5") # 123000 - var result9 = -a9 - testing.assert_equal( - String(result9), - "-123000", - "Negating number from scientific notation", - ) - except: - print("Scientific notation not supported in this implementation") + # Test case 9: Negate number with scientific notation + var a9 = Decimal("1.23e5") # 123000 + var result9 = -a9 + testing.assert_equal( + String(result9), + "-123000", + "Negating number from scientific notation", + ) # Test case 10: Negate number with maximum precision var a10 = Decimal("0." + "1" * 28) # 0.1111...1 (28 digits) @@ -256,33 +267,33 @@ fn test_abs() raises: print("Testing decimal absolute value...") # Test case 1: Absolute value of positive number - var a1 = Decimal("123.45") + var a1 = Decimal(12345, 2) var result1 = abs(a1) testing.assert_equal( String(result1), "123.45", "Absolute value of positive number" ) # Test case 2: Absolute value of negative number - var a2 = Decimal("-67.89") + var a2 = Decimal(-6789, 2) var result2 = abs(a2) testing.assert_equal( String(result2), "67.89", "Absolute value of negative number" ) # Test case 3: Absolute value of zero - var a3 = Decimal("0") + var a3 = Decimal(0) var result3 = abs(a3) testing.assert_equal(String(result3), "0", "Absolute value of zero") # Test case 4: Absolute value of negative zero (if supported) - var a4 = Decimal("-0.00") + var a4 = Decimal(-0, 2) var result4 = abs(a4) testing.assert_equal( String(result4), "0.00", "Absolute value of negative zero" ) # Test case 5: Absolute value with large number of decimal places - var a5 = Decimal("-0.0000000001") + var a5 = Decimal(-1, 10) var result5 = abs(a5) testing.assert_equal( String(result5), @@ -310,7 +321,9 @@ fn test_abs() raises: # Test case 8: Absolute value of maximum representable number try: - var a8 = Decimal("79228162514264337593543950335") # Maximum value + var a8 = Decimal.from_uint128( + UInt128(79228162514264337593543950335) + ) # Maximum value var result8 = abs(a8) testing.assert_equal( String(result8), @@ -338,70 +351,70 @@ fn test_subtract() raises: print("Testing decimal subtraction...") # Test case 1: Simple subtraction with same scale - var a1 = Decimal("123.45") - var b1 = Decimal("67.89") + var a1 = Decimal(12345, 2) + var b1 = Decimal(6789, 2) var result1 = a1 - b1 testing.assert_equal( String(result1), "55.56", "Simple subtraction with same scale" ) # Test case 2: Subtraction with different scales - var a2 = Decimal("123.4") - var b2 = Decimal("67.89") + var a2 = Decimal(1234, 1) + var b2 = Decimal(6789, 2) var result2 = a2 - b2 testing.assert_equal( String(result2), "55.51", "Subtraction with different scales" ) # Test case 3: Subtraction resulting in negative - var a3 = Decimal("67.89") - var b3 = Decimal("123.45") + var a3 = Decimal(6789, 2) + var b3 = Decimal(12345, 2) var result3 = a3 - b3 testing.assert_equal( String(result3), "-55.56", "Subtraction resulting in negative" ) # Test case 4: Subtraction of negative numbers - var a4 = Decimal("123.45") - var b4 = Decimal("-67.89") + var a4 = Decimal(12345, 2) + var b4 = Decimal(-6789, 2) var result4 = a4 - b4 testing.assert_equal( String(result4), "191.34", "Subtraction of negative number" ) # Test case 5: Subtraction with zero - var a5 = Decimal("123.45") - var b5 = Decimal("0.00") + var a5 = Decimal(12345, 2) + var b5 = Decimal(0, 2) var result5 = a5 - b5 testing.assert_equal(String(result5), "123.45", "Subtraction with zero") # Test case 6: Subtraction resulting in zero - var a6 = Decimal("123.45") - var b6 = Decimal("123.45") + var a6 = Decimal(12345, 2) + var b6 = Decimal(12345, 2) var result6 = a6 - b6 testing.assert_equal( String(result6), "0.00", "Subtraction resulting in zero" ) # Test case 7: Subtraction with large scales - var a7 = Decimal("0.0000003") - var b7 = Decimal("0.0000002") + var a7 = Decimal(3, 7) + var b7 = Decimal(2, 7) var result7 = a7 - b7 testing.assert_equal( String(result7), "0.0000001", "Subtraction with large scales" ) # Test case 8: Subtraction with different large scales - var a8 = Decimal("0.000005") - var b8 = Decimal("0.0000002") + var a8 = Decimal(5, 6) + var b8 = Decimal(2, 7) var result8 = a8 - b8 testing.assert_equal( String(result8), "0.0000048", "Subtraction with different large scales" ) # Test case 9: Subtraction with small difference - var a9 = Decimal("1.0000001") - var b9 = Decimal("1.0000000") + var a9 = Decimal(10000001, 7) + var b9 = Decimal(10000000, 7) var result9 = a9 - b9 testing.assert_equal( String(result9), "0.0000001", "Subtraction with small difference" @@ -419,44 +432,44 @@ fn test_subtract() raises: # Test case 11: Self subtraction for various values (expanded from list) # Individual test cases instead of iterating over a list - var value1 = Decimal("0") + var value1 = Decimal(0) testing.assert_equal( String(value1 - value1), - String(round(Decimal("0"), value1.scale())), + String(round(Decimal(0), value1.scale())), "Self subtraction should yield zero (0)", ) - var value2 = Decimal("123.45") + var value2 = Decimal(12345, 2) testing.assert_equal( String(value2 - value2), - String(round(Decimal("0"), value2.scale())), + String(round(Decimal(0), value2.scale())), "Self subtraction should yield zero (123.45)", ) - var value3 = Decimal("-987.654") + var value3 = Decimal(-987654, 3) testing.assert_equal( String(value3 - value3), - String(round(Decimal("0"), value3.scale())), + String(round(Decimal(0), value3.scale())), "Self subtraction should yield zero (-987.654)", ) - var value4 = Decimal("0.0001") + var value4 = Decimal(1, 4) testing.assert_equal( String(value4 - value4), - String(round(Decimal("0"), value4.scale())), + String(round(Decimal(0), value4.scale())), "Self subtraction should yield zero (0.0001)", ) var value5 = Decimal("-99999.99999") testing.assert_equal( String(value5 - value5), - String(round(Decimal("0"), value5.scale())), + String(round(Decimal(0), value5.scale())), "Self subtraction should yield zero (-99999.99999)", ) # Test case 12: Verify that a - b = -(b - a) - var a12a = Decimal("123.456") - var b12a = Decimal("789.012") + var a12a = Decimal(123456, 3) + var b12a = Decimal(789012, 3) var result12a = a12a - b12a var result12b = -(b12a - a12a) testing.assert_equal( @@ -483,7 +496,7 @@ fn test_extreme_cases() raises: # Test case 2: Addition that should trigger overflow handling try: var a2 = Decimal("79228162514264337593543950335") # MAX() - var b2 = Decimal("1") + var b2 = Decimal(1) var _result2 = a2 + b2 print("WARNING: Addition beyond MAX() didn't raise an error") except: diff --git a/tests/test_comparison.mojo b/tests/test_comparison.mojo index 2512209..f7b655a 100644 --- a/tests/test_comparison.mojo +++ b/tests/test_comparison.mojo @@ -19,38 +19,38 @@ fn test_equality() raises: print("Testing decimal equality...") # Test case 1: Equal decimals - var a1 = Decimal("123.45") - var b1 = Decimal("123.45") + var a1 = Decimal(12345, 2) + var b1 = Decimal(12345, 2) testing.assert_true(equal(a1, b1), "Equal decimals should be equal") # Test case 2: Equal with different scales var a2 = Decimal("123.450") - var b2 = Decimal("123.45") + var b2 = Decimal(12345, 2) testing.assert_true( equal(a2, b2), "Equal decimals with different scales should be equal" ) # Test case 3: Different values - var a3 = Decimal("123.45") + var a3 = Decimal(12345, 2) var b3 = Decimal("123.46") testing.assert_false( equal(a3, b3), "Different decimals should not be equal" ) # Test case 4: Zeros with different scales - var a4 = Decimal("0") + var a4 = Decimal(0) var b4 = Decimal("0.00") testing.assert_true( equal(a4, b4), "Zeros with different scales should be equal" ) # Test case 5: Zero and negative zero - var a5 = Decimal("0") + var a5 = Decimal(0) var b5 = Decimal("-0") testing.assert_true(equal(a5, b5), "Zero and negative zero should be equal") # Test case 6: Same absolute value but different signs - var a6 = Decimal("123.45") + var a6 = Decimal(12345, 2) var b6 = Decimal("-123.45") testing.assert_false( equal(a6, b6), @@ -65,30 +65,30 @@ fn test_inequality() raises: print("Testing decimal inequality...") # Test case 1: Equal decimals - var a1 = Decimal("123.45") - var b1 = Decimal("123.45") + var a1 = Decimal(12345, 2) + var b1 = Decimal(12345, 2) testing.assert_false( not_equal(a1, b1), "Equal decimals should not be unequal" ) # Test case 2: Equal with different scales - var a2 = Decimal("123.450") - var b2 = Decimal("123.45") + var a2 = Decimal(123450, 3) + var b2 = Decimal(12345, 2) testing.assert_false( not_equal(a2, b2), "Equal decimals with different scales should not be unequal", ) # Test case 3: Different values - var a3 = Decimal("123.45") - var b3 = Decimal("123.46") + var a3 = Decimal(12345, 2) + var b3 = Decimal(12346, 2) testing.assert_true( not_equal(a3, b3), "Different decimals should be unequal" ) # Test case 4: Same absolute value but different signs - var a4 = Decimal("123.45") - var b4 = Decimal("-123.45") + var a4 = Decimal(12345, 2) + var b4 = Decimal(-12345, 2) testing.assert_true( not_equal(a4, b4), "Same absolute value but different signs should be unequal", @@ -101,23 +101,23 @@ fn test_greater() raises: print("Testing greater than comparison...") # Test case 1: Larger decimal - var a1 = Decimal("123.46") - var b1 = Decimal("123.45") + var a1 = Decimal(12346, 2) + var b1 = Decimal(12345, 2) testing.assert_true(greater(a1, b1), "123.46 should be greater than 123.45") testing.assert_false( greater(b1, a1), "123.45 should not be greater than 123.46" ) # Test case 2: Equal decimals - var a2 = Decimal("123.45") - var b2 = Decimal("123.45") + var a2 = Decimal(12345, 2) + var b2 = Decimal(12345, 2) testing.assert_false( greater(a2, b2), "Equal decimals should not be greater" ) # Test case 3: Positive vs. negative - var a3 = Decimal("123.45") - var b3 = Decimal("-123.45") + var a3 = Decimal(12345, 2) + var b3 = Decimal(-12345, 2) testing.assert_true( greater(a3, b3), "Positive should be greater than negative" ) @@ -133,20 +133,20 @@ fn test_greater() raises: ) # Test case 5: Zero vs. positive - var a5 = Decimal("0") - var b5 = Decimal("123.45") + var a5 = Decimal(0) + var b5 = Decimal(12345, 2) testing.assert_false( greater(a5, b5), "Zero should not be greater than positive" ) # Test case 6: Zero vs. negative - var a6 = Decimal("0") + var a6 = Decimal(0) var b6 = Decimal("-123.45") testing.assert_true(greater(a6, b6), "Zero should be greater than negative") # Test case 7: Different scales var a7 = Decimal("123.5") - var b7 = Decimal("123.45") + var b7 = Decimal(12345, 2) testing.assert_true(greater(a7, b7), "123.5 should be greater than 123.45") print("Greater than tests passed!") @@ -157,21 +157,21 @@ fn test_greater_equal() raises: # Test case 1: Larger decimal var a1 = Decimal("123.46") - var b1 = Decimal("123.45") + var b1 = Decimal(12345, 2) testing.assert_true( greater_equal(a1, b1), "123.46 should be greater than or equal to 123.45", ) # Test case 2: Equal decimals - var a2 = Decimal("123.45") - var b2 = Decimal("123.45") + var a2 = Decimal(12345, 2) + var b2 = Decimal(12345, 2) testing.assert_true( greater_equal(a2, b2), "Equal decimals should be greater than or equal" ) # Test case 3: Positive vs. negative - var a3 = Decimal("123.45") + var a3 = Decimal(12345, 2) var b3 = Decimal("-123.45") testing.assert_true( greater_equal(a3, b3), @@ -180,14 +180,14 @@ fn test_greater_equal() raises: # Test case 4: Equal values with different scales var a4 = Decimal("123.450") - var b4 = Decimal("123.45") + var b4 = Decimal(12345, 2) testing.assert_true( greater_equal(a4, b4), "Equal values with different scales should be greater than or equal", ) # Test case 5: Smaller decimal - var a5 = Decimal("123.45") + var a5 = Decimal(12345, 2) var b5 = Decimal("123.46") testing.assert_false( greater_equal(a5, b5), @@ -201,18 +201,18 @@ fn test_less() raises: print("Testing less than comparison...") # Test case 1: Smaller decimal - var a1 = Decimal("123.45") + var a1 = Decimal(12345, 2) var b1 = Decimal("123.46") testing.assert_true(less(a1, b1), "123.45 should be less than 123.46") # Test case 2: Equal decimals - var a2 = Decimal("123.45") - var b2 = Decimal("123.45") + var a2 = Decimal(12345, 2) + var b2 = Decimal(12345, 2) testing.assert_false(less(a2, b2), "Equal decimals should not be less") # Test case 3: Negative vs. positive var a3 = Decimal("-123.45") - var b3 = Decimal("123.45") + var b3 = Decimal(12345, 2) testing.assert_true(less(a3, b3), "Negative should be less than positive") # Test case 4: Negative with larger absolute value @@ -221,8 +221,8 @@ fn test_less() raises: testing.assert_true(less(a4, b4), "-123.46 should be less than -123.45") # Test case 5: Zero vs. positive - var a5 = Decimal("0") - var b5 = Decimal("123.45") + var a5 = Decimal(0) + var b5 = Decimal(12345, 2) testing.assert_true(less(a5, b5), "Zero should be less than positive") print("Less than tests passed!") @@ -232,29 +232,29 @@ fn test_less_equal() raises: print("Testing less than or equal comparison...") # Test case 1: Smaller decimal - var a1 = Decimal("123.45") + var a1 = Decimal(12345, 2) var b1 = Decimal("123.46") testing.assert_true( less_equal(a1, b1), "123.45 should be less than or equal to 123.46" ) # Test case 2: Equal decimals - var a2 = Decimal("123.45") - var b2 = Decimal("123.45") + var a2 = Decimal(12345, 2) + var b2 = Decimal(12345, 2) testing.assert_true( less_equal(a2, b2), "Equal decimals should be less than or equal" ) # Test case 3: Negative vs. positive var a3 = Decimal("-123.45") - var b3 = Decimal("123.45") + var b3 = Decimal(12345, 2) testing.assert_true( less_equal(a3, b3), "Negative should be less than or equal to positive" ) # Test case 4: Equal values with different scales var a4 = Decimal("123.450") - var b4 = Decimal("123.45") + var b4 = Decimal(12345, 2) testing.assert_true( less_equal(a4, b4), "Equal values with different scales should be less than or equal", @@ -262,7 +262,7 @@ fn test_less_equal() raises: # Test case 5: Larger decimal var a5 = Decimal("123.46") - var b5 = Decimal("123.45") + var b5 = Decimal(12345, 2) testing.assert_false( less_equal(a5, b5), "123.46 should not be less than or equal to 123.45" ) @@ -273,7 +273,7 @@ fn test_less_equal() raises: fn test_zero_comparison() raises: print("Testing zero comparison cases...") - var zero = Decimal("0") + var zero = Decimal(0) var pos = Decimal("0.0000000000000000001") # Very small positive var neg = Decimal("-0.0000000000000000001") # Very small negative var zero_scale = Decimal("0.00000") # Zero with different scale @@ -376,7 +376,7 @@ fn test_edge_cases() raises: var neg_large = Decimal("-1000") var neg_small = Decimal("-0.001") var pos_small = Decimal("0.001") - var pos_large = Decimal("1000") + var pos_large = Decimal(1000) # Transitivity: if a > b and b > c then a > c testing.assert_true(greater(pos_large, pos_small), "1000 > 0.001") @@ -393,7 +393,7 @@ fn test_exact_comparison() raises: print("Testing exact comparison with precision handling...") # Test case 1: Scale handling with zeros - var zero1 = Decimal("0") + var zero1 = Decimal(0) var zero2 = Decimal("0.0") var zero3 = Decimal("0.00000") @@ -424,12 +424,12 @@ fn test_comparison_operators() raises: print("Testing comparison operators...") # Create test values - var a = Decimal("123.45") + var a = Decimal(12345, 2) var b = Decimal("67.89") - var c = Decimal("123.45") # Equal to a + var c = Decimal(12345, 2) # Equal to a var d = Decimal("123.450") # Equal to a with different scale var e = Decimal("-50.0") # Negative number - var f = Decimal("0") # Zero + var f = Decimal(0) # Zero var g = Decimal("-0.0") # Negative zero (equal to zero) # Greater than diff --git a/tests/test_creation.mojo b/tests/test_creation.mojo deleted file mode 100644 index 97fad3c..0000000 --- a/tests/test_creation.mojo +++ /dev/null @@ -1,415 +0,0 @@ -""" -Test Decimal creation from integer, float, or string values. -""" - -# TODO: Split into separate test files for each type of constructor - -from decimojo.prelude import dm, Decimal, RoundingMode -import testing - - -fn test_decimal_from_int() raises: - print("------------------------------------------------------") - print("Testing Decimal Creation from Integer Values") - - # Basic integer constructors - var zero = Decimal(0) - var one = Decimal(1) - var neg_one = Decimal(-1) - var pos_int = Decimal(42) - var neg_int = Decimal(-100) - - # Verify basic string representations - testing.assert_equal( - String(zero), "0", "Integer 0 should be represented as '0'" - ) - testing.assert_equal( - String(one), "1", "Integer 1 should be represented as '1'" - ) - testing.assert_equal( - String(neg_one), "-1", "Integer -1 should be represented as '-1'" - ) - testing.assert_equal( - String(pos_int), "42", "Integer 42 should be represented as '42'" - ) - testing.assert_equal( - String(neg_int), "-100", "Integer -100 should be represented as '-100'" - ) - - # Integer edge cases - var int_min = Decimal(Int.MIN) - var int_max = Decimal(Int.MAX) - testing.assert_equal( - String(int_min), - "-9223372036854775808", - "Int.MIN should be represented correctly", - ) - testing.assert_equal( - String(int_max), - "9223372036854775807", - "Int.MAX should be represented correctly", - ) - - # Boundary values - var medium_int = Decimal(1000000) - var large_int = Decimal(1000000000) - testing.assert_equal( - String(medium_int), - "1000000", - "Medium integer should be represented correctly", - ) - testing.assert_equal( - String(large_int), - "1000000000", - "Large integer should be represented correctly", - ) - - -fn test_decimal_from_float() raises: - print("------------------------------------------------------") - print("Testing Decimal Creation from Float Values") - - # Basic float constructors - var zero_float = Decimal(0.0) - var one_float = Decimal(1.0) - var neg_one_float = Decimal(-1.0) - var pi = Decimal(3.1415926535979323) - var e = Decimal(2.718281828459045) - - # Verify basic exact representations for simple values - testing.assert_equal( - String(zero_float), "0", "Float 0.0 should be represented as '0'" - ) - testing.assert_equal( - String(one_float), "1", "Float 1.0 should be represented as '1'" - ) - testing.assert_equal( - String(neg_one_float), "-1", "Float -1.0 should be represented as '-1'" - ) - - # For irrational numbers, check only first few digits - var pi_str = String(pi) - var expected_pi = "3.14159" - testing.assert_equal( - pi_str[:7], - String(expected_pi)[:7], - "Pi should match expected value for the first 7 digits", - ) - - var e_str = String(e) - var expected_e = "2.71828" - testing.assert_equal( - e_str[:7], - String(expected_e)[:7], - "e should match expected value for the first 7 digits", - ) - - # Different precision levels - var high_precision = Decimal(0.0000000001) - var medium_precision = Decimal(0.1234) - var negative_precision = Decimal(-0.5678) - - # Check high precision approximately - var high_precision_str = String(high_precision) - testing.assert_true( - high_precision_str.startswith("0.0000000001") - or high_precision_str.startswith("0.00000000009"), - "High precision float should be approximately 0.0000000001", - ) - - # Check medium precision (should be more exact but still allow for slight variations) - var medium_str = String(medium_precision) - testing.assert_true( - medium_str.startswith("0.1234") or medium_str.startswith("0.1233"), - "Medium precision float should be approximately 0.1234", - ) - - # Check negative precision - var neg_precision_str = String(negative_precision) - testing.assert_true( - neg_precision_str.startswith("-0.5678") - or neg_precision_str.startswith("-0.5677") - or neg_precision_str.startswith("-0.5679"), - "Negative precision float should be approximately -0.5678", - ) - - # Float edge cases - var very_small = Decimal(1.23e-10) - var very_large = Decimal(1.23e10) - var neg_large = Decimal(-9.87e8) - - # For very small numbers, allow slight variations - var very_small_str = String(very_small) - testing.assert_true( - very_small_str.startswith("0.000000000123") - or very_small_str.startswith("0.000000000122") - or very_small_str.startswith("0.000000000124"), - "Very small float should be approximately 0.000000000123", - ) - - # For very large numbers, allow slight variations - var very_large_str = String(very_large) - testing.assert_true( - very_large_str.startswith("12300000000") - or very_large_str.startswith("12299999999") - or very_large_str.startswith("12300000001"), - "Very large float should be approximately 12300000000", - ) - - # For negative large numbers, allow slight variations - var neg_large_str = String(neg_large) - testing.assert_true( - neg_large_str.startswith("-987000000") - or neg_large_str.startswith("-986999999") - or neg_large_str.startswith("-987000001"), - "Negative large float should be approximately -987000000", - ) - - # Float precision tests - var problematic = Decimal( - 0.0001 + 0.0002 - ) # Not exactly 0.3 in binary floating point - var problematic_str = String(problematic) - - # Check that it's approximately 0.3 (should be close but not exactly 0.3) - testing.assert_true( - problematic_str.startswith("0.0003") - or problematic_str.startswith("0.00029"), - "Float binary approximation should be approximately 0.0003", - ) - - print("\nAll float tests passed!") - - -fn test_decimal_from_string() raises: - print("------------------------------------------------------") - print("Testing Decimal Creation from String Values") - - # Basic string constructors - var zero_str = Decimal("0") - var one_str = Decimal("1") - var neg_one_str = Decimal("-1") - var decimal_str = Decimal("123.456") - var neg_decimal_str = Decimal("-789.012") - - # Verify basic string representations - testing.assert_equal( - String(zero_str), "0", "String '0' should be represented as '0'" - ) - testing.assert_equal( - String(one_str), "1", "String '1' should be represented as '1'" - ) - testing.assert_equal( - String(neg_one_str), "-1", "String '-1' should be represented as '-1'" - ) - testing.assert_equal( - String(decimal_str), "123.456", "String '123.456' should be preserved" - ) - testing.assert_equal( - String(neg_decimal_str), - "-789.012", - "String '-789.012' should be preserved", - ) - - # Leading and trailing zeros - var leading_zeros = Decimal("00000123.456") - var trailing_zeros = Decimal("123.45600000") - var both_zeros = Decimal("00123.45600") - - testing.assert_equal( - String(leading_zeros), "123.456", "Leading zeros should be removed" - ) - testing.assert_equal( - String(trailing_zeros), - "123.45600000", - "Trailing zeros should not be removed", - ) - testing.assert_equal( - String(both_zeros), - "123.45600", - "Leading zeros should be removed", - ) - - # Very large and small numbers - var very_large = Decimal("999999999999999999999999999") - var very_small = Decimal("0." + "0" * 27 + "1") - var large_negative = Decimal("-" + "9" * 21) - - testing.assert_equal( - String(very_large), - "999999999999999999999999999", - "Large numbers should be preserved", - ) - testing.assert_equal( - String(very_small), - "0." + "0" * 27 + "1", - "Small numbers should be preserved", - ) - testing.assert_equal( - String(large_negative), - "-" + "9" * 21, - "Large negative numbers should be preserved", - ) - - # Special formats - # Underscores for readability (if supported) - try: - var with_underscores = Decimal("1_000_000.000_001") - testing.assert_equal( - String(with_underscores), - "1000000.000001", - "Underscores should be ignored in string representation", - ) - except: - print("Underscores in numbers not supported") - - # Scientific notation (if supported) - try: - var scientific_pos = Decimal("1.23e5") - var scientific_neg = Decimal("4.56e-7") - testing.assert_equal( - String(scientific_pos), - "123000", - "Positive scientific notation should be converted correctly", - ) - testing.assert_equal( - String(scientific_neg), - "0.000000456", - "Negative scientific notation should be converted correctly", - ) - except: - print("Scientific notation not supported") - - # Edge cases - try: - var just_dot = Decimal(".") - testing.assert_equal( - String(just_dot), "0", "Just dot should be represented as zero" - ) - except: - print("Decimal point without digits not supported") - - var only_zeros = Decimal("0.0000") - var MAX_SCALE = Decimal("0." + "9" * 28) - - testing.assert_equal( - String(only_zeros), - "0.0000", - "String of zeros should be represented as '0'", - ) - testing.assert_equal( - String(MAX_SCALE), - "0." + "9" * 28, - "Max precision should be preserved", - ) - - # Integer boundary values as strings - var boundary_32bit = Decimal("4294967295") # 2^32 - 1 - var boundary_64bit = Decimal("18446744073709551615") # 2^64 - 1 - var beyond_64bit = Decimal("18446744073709551616") # 2^64 - - testing.assert_equal( - String(boundary_32bit), - "4294967295", - "32-bit boundary should be represented correctly", - ) - testing.assert_equal( - String(boundary_64bit), - "18446744073709551615", - "64-bit boundary should be represented correctly", - ) - testing.assert_equal( - String(beyond_64bit), - "18446744073709551616", - "Beyond 64-bit should be represented correctly", - ) - - print("\nAll string tests passed!") - - -fn test_decimal_from_components() raises: - print("------------------------------------------------------") - print("Testing Decimal Creation from Components") - - # Test case 1: Zero with zero scale - var zero = Decimal(0, 0, 0, 0, False) - testing.assert_equal(String(zero), "0", "Zero with scale 0") - - # Test case 2: One with zero scale - var one = Decimal(1, 0, 0, 0, False) - testing.assert_equal(String(one), "1", "One with scale 0") - - # Test case 3: Negative one - var neg_one = Decimal(1, 0, 0, 0, True) - testing.assert_equal(String(neg_one), "-1", "Negative one") - - # Test case 4: Simple number with scale - var with_scale = Decimal(12345, 0, 0, 2, False) - testing.assert_equal( - String(with_scale), "123.45", "Simple number with scale 2" - ) - - # Test case 5: Negative number with scale - var neg_with_scale = Decimal(12345, 0, 0, 2, True) - testing.assert_equal( - String(neg_with_scale), "-123.45", "Negative number with scale 2" - ) - - # Test case 6: Larger number using mid - var large = Decimal(0xFFFFFFFF, 5, 0, 0, False) - var expected_large = Decimal(String(0xFFFFFFFF + 5 * 4294967296)) - testing.assert_equal( - String(large), String(expected_large), "Large number using mid field" - ) - - # Test case 7: Verify scale is correctly stored - var high_scale = Decimal(123, 0, 0, 10, False) - testing.assert_equal( - high_scale.scale(), 10, "Scale should be correctly stored" - ) - testing.assert_equal( - String(high_scale), "0.0000000123", "High scale correctly formatted" - ) - - # Test case 8: Test large scale with negative number - var neg_high_scale = Decimal(123, 0, 0, 10, True) - testing.assert_equal( - String(neg_high_scale), - "-0.0000000123", - "Negative high scale correctly formatted", - ) - - # Test case 9: Test sign flag - testing.assert_equal( - zero.is_negative(), False, "Zero should not be negative" - ) - testing.assert_equal(one.is_negative(), False, "One should not be negative") - testing.assert_equal( - neg_one.is_negative(), True, "Negative one should be negative" - ) - - # Test case 10: With high component - var with_high = Decimal(0, 0, 3, 0, False) - testing.assert_equal( - String(with_high), - "55340232221128654848", - "High component correctly handled", - ) - - # Test case 11: Maximum possible scale - var max_scale = Decimal(123, 0, 0, 28, False) - testing.assert_equal(max_scale.scale(), 28, "Maximum scale should be 28") - - # Test case 12: Overflow scale protection - try: - var _overflow_scale = Decimal(123, 0, 0, 100, False) - except: - print("Successfully caught overflow scale error") - - print("All component constructor tests passed!") - - -fn main() raises: - test_decimal_from_int() - test_decimal_from_string() - test_decimal_from_components() # Add the new test to the main function diff --git a/tests/test_divide.mojo b/tests/test_divide.mojo index 347b355..20e9ea9 100644 --- a/tests/test_divide.mojo +++ b/tests/test_divide.mojo @@ -13,50 +13,50 @@ fn test_basic_division() raises: # 1. Simple integer division testing.assert_equal( - String(Decimal("10") / Decimal("2")), "5", "Simple integer division" + String(Decimal(10) / Decimal(2)), "5", "Simple integer division" ) # 2. Division with no remainder testing.assert_equal( - String(Decimal("100") / Decimal("4")), + String(Decimal(100) / Decimal(4)), "25", "Division with no remainder", ) # 3. Division resulting in non-integer testing.assert_equal( - String(Decimal("10") / Decimal("4")), + String(Decimal(10) / Decimal(4)), "2.5", "Division resulting in non-integer", ) # 4. Division by one testing.assert_equal( - String(Decimal("123.45") / Decimal("1")), "123.45", "Division by one" + String(Decimal("123.45") / Decimal(1)), "123.45", "Division by one" ) # 5. Division of zero testing.assert_equal( - String(Decimal("0") / Decimal("42")), "0", "Division of zero" + String(Decimal(0) / Decimal(42)), "0", "Division of zero" ) # 6. Division with both negative numbers testing.assert_equal( - String(Decimal("-10") / Decimal("-5")), + String(Decimal("-10") / Decimal(-5)), "2", "Division with both negative numbers", ) # 7. Division with negative dividend testing.assert_equal( - String(Decimal("-10") / Decimal("5")), + String(Decimal("-10") / Decimal(5)), "-2", "Division with negative dividend", ) # 8. Division with negative divisor testing.assert_equal( - String(Decimal("10") / Decimal("-5")), + String(Decimal(10) / Decimal(-5)), "-2", "Division with negative divisor", ) @@ -83,70 +83,70 @@ fn test_repeating_decimals() raises: print("Testing division with repeating decimals...") # 11. Division resulting in 1/3 - var third = Decimal("1") / Decimal("3") + var third = Decimal(1) / Decimal(3) testing.assert_true( String(third).startswith("0.33333333333333"), "Case 11: Division resulting in 1/3 failed", ) # 12. Division resulting in 1/6 - var sixth = Decimal("1") / Decimal("6") + var sixth = Decimal(1) / Decimal(6) testing.assert_true( String(sixth).startswith("0.16666666666666"), "Case 12: Division resulting in 1/6 failed", ) # 13. Division resulting in 1/7 - var seventh = Decimal("1") / Decimal("7") + var seventh = Decimal(1) / Decimal(7) testing.assert_true( String(seventh).startswith("0.142857142857142857"), "Case 13: Division resulting in 1/7 failed", ) # 14. Division resulting in 2/3 - var two_thirds = Decimal("2") / Decimal("3") + var two_thirds = Decimal(2) / Decimal(3) testing.assert_true( String(two_thirds).startswith("0.66666666666666"), "Case 14: Division resulting in 2/3 failed", ) # 15. Division resulting in 5/6 - var five_sixths = Decimal("5") / Decimal("6") + var five_sixths = Decimal(5) / Decimal(6) testing.assert_true( String(five_sixths).startswith("0.83333333333333"), "Case 15: Division resulting in 5/6 failed", ) # 16. Division of 1 by 9 - var one_ninth = Decimal("1") / Decimal("9") + var one_ninth = Decimal(1) / Decimal(9) testing.assert_true( String(one_ninth).startswith("0.11111111111111"), "Case 16: Division of 1 by 9 failed", ) # 17. Division of 1 by 11 - var one_eleventh = Decimal("1") / Decimal("11") + var one_eleventh = Decimal(1) / Decimal(11) testing.assert_true( String(one_eleventh).startswith("0.0909090909090"), "Case 17: Division of 1 by 11 failed", ) # 18. Division of 1 by 12 - var one_twelfth = Decimal("1") / Decimal("12") + var one_twelfth = Decimal(1) / Decimal(12) testing.assert_true( String(one_twelfth).startswith("0.08333333333333"), "Case 18: Division of 1 by 12 failed", ) # 19. Division of 5 by 11 - var five_elevenths = Decimal("5") / Decimal("11") + var five_elevenths = Decimal(5) / Decimal(11) testing.assert_true( String(five_elevenths).startswith("0.4545454545454"), "Case 19: Division of 5 by 11 failed", ) # 20. Division of 10 by 3 - var ten_thirds = Decimal("10") / Decimal("3") + var ten_thirds = Decimal(10) / Decimal(3) testing.assert_true( String(ten_thirds).startswith("3.33333333333333"), "Case 20: Division of 10 by 3 failed", @@ -160,28 +160,28 @@ fn test_precision_rounding() raises: print("Testing division precision and rounding...") # 21. Rounding half even (banker's rounding) at precision limit - var a21 = Decimal("2") / Decimal("3") # Should be ~0.6666...67 + var a21 = Decimal(2) / Decimal(3) # Should be ~0.6666...67 var b21 = Decimal("0." + "6" * 27 + "7") # 0.6666...67 testing.assert_equal( String(a21), String(b21), "Rounding half even at precision limit" ) # 22. Another case of rounding half even - var a22 = Decimal("1") / Decimal("9") # Should be ~0.1111...11 + var a22 = Decimal(1) / Decimal(9) # Should be ~0.1111...11 var b22 = Decimal("0." + "1" * 28) # 0.1111...11 testing.assert_equal( String(a22), String(b22), "Another case of rounding half even" ) # 23. Rounding up at precision limit - var a23 = Decimal("10") / Decimal("3") # Should be ~3.3333...33 + var a23 = Decimal(10) / Decimal(3) # Should be ~3.3333...33 var b23 = Decimal("3." + "3" * 28) # 3.3333...33 testing.assert_equal( String(a23), String(b23), "Rounding up at precision limit" ) # 24. Division requiring rounding to precision limit - var a24 = Decimal("1") / Decimal("7") # ~0.142857... + var a24 = Decimal(1) / Decimal(7) # ~0.142857... var manually_calculated = Decimal("0.1428571428571428571428571429") testing.assert_equal( String(a24), @@ -190,19 +190,19 @@ fn test_precision_rounding() raises: ) # 25. Precision limit with repeating 9s - var a25 = Decimal("1") / Decimal("81") # ~0.01234... + var a25 = Decimal(1) / Decimal(81) # ~0.01234... var precision_reached = a25.scale() <= Decimal.MAX_SCALE testing.assert_true(precision_reached, "Scale should not exceed MAX_SCALE") # 26. Test precision with negative numbers - var a26 = Decimal("-1") / Decimal("3") + var a26 = Decimal(-1) / Decimal(3) var b26 = Decimal("-0." + "3" * 28) # -0.3333...33 testing.assert_equal( String(a26), String(b26), "Test precision with negative numbers" ) # 27. Division with result at exactly precision limit - var a27 = Decimal("1") / Decimal(String("1" + "0" * 28)) # 1/10^28 + var a27 = Decimal(1) / Decimal(String("1" + "0" * 28)) # 1/10^28 testing.assert_equal( String(a27), String(Decimal("0." + "0" * 27 + "1")), @@ -210,7 +210,7 @@ fn test_precision_rounding() raises: ) # 28. Division with result needing one more than precision limit - var a28 = Decimal("1") / Decimal(String("1" + "0" * 28)) # 1/10^29 + var a28 = Decimal(1) / Decimal(String("1" + "0" * 28)) # 1/10^29 testing.assert_equal( String(a28), String(Decimal("0." + "0" * 27 + "1")), @@ -218,7 +218,7 @@ fn test_precision_rounding() raises: ) # 29. Division where quotient has more digits than precision allows - var a29 = Decimal("12345678901234567890123456789") / Decimal("7") + var a29 = Decimal("12345678901234567890123456789") / Decimal(7) testing.assert_true( a29.scale() <= Decimal.MAX_SCALE, "Scale should not exceed MAX_SCALE", @@ -240,7 +240,7 @@ fn test_scale_handling() raises: # 31. Division by power of 10 testing.assert_equal( - String(Decimal("123.456") / Decimal("10")), + String(Decimal("123.456") / Decimal(10)), "12.3456", "Division by power of 10", ) @@ -261,35 +261,35 @@ fn test_scale_handling() raises: # 34. Division by 100 (divide by 100) testing.assert_equal( - String(Decimal("123.456") / Decimal("100")), + String(Decimal("123.456") / Decimal(100)), "1.23456", "Division by 100", ) # 35. Division resulting in loss of trailing zeros testing.assert_equal( - String(Decimal("10.000") / Decimal("2")), + String(Decimal("10.000") / Decimal(2)), "5.000", "Division resulting in loss of trailing zeros", ) # 36. Division where quotient needs more decimal places testing.assert_equal( - String(Decimal("1") / Decimal("8")), + String(Decimal(1) / Decimal(8)), "0.125", "Division where quotient needs more decimal places", ) # 37. Division where dividend has more scale than divisor testing.assert_equal( - String(Decimal("0.01") / Decimal("2")), + String(Decimal("0.01") / Decimal(2)), "0.005", "Division where dividend has more scale than divisor", ) # 38. Division where divisor has more scale than dividend testing.assert_equal( - String(Decimal("2") / Decimal("0.01")), + String(Decimal(2) / Decimal("0.01")), "200", "Division where divisor has more scale than dividend", ) @@ -316,16 +316,14 @@ fn test_edge_cases() raises: print("Testing division edge cases...") # 41. Division by very small number close to zero - var a41 = Decimal("1") / Decimal( - "0." + "0" * 27 + "1" - ) # Dividing by 10^-28 + var a41 = Decimal(1) / Decimal("0." + "0" * 27 + "1") # Dividing by 10^-28 testing.assert_true( a41 > Decimal(String("1" + "0" * 27)), "Case 41: Division by very small number failed", ) # 42. Division resulting in a number close to zero - var a42 = Decimal("0." + "0" * 27 + "1") / Decimal("10") # Very small / 10 + var a42 = Decimal("0." + "0" * 27 + "1") / Decimal(10) # Very small / 10 testing.assert_equal( a42, Decimal("0." + "0" * 28), @@ -347,23 +345,23 @@ fn test_edge_cases() raises: var min_positive = Decimal( "0." + "0" * 27 + "1" ) # Smallest positive decimal - var a44 = min_positive / Decimal("2") + var a44 = min_positive / Decimal(2) testing.assert_true(a44.scale() <= Decimal.MAX_SCALE) # 45. Division by power of 2 (binary divisions) testing.assert_equal( - String(Decimal("1") / Decimal("4")), "0.25", "Division by power of 2" + String(Decimal(1) / Decimal(4)), "0.25", "Division by power of 2" ) # 46. Division by 9's testing.assert_equal( - String(Decimal("100") / Decimal("9.9")), + String(Decimal(100) / Decimal("9.9")), "10.101010101010101010101010101", "Division by 9's", ) # 47. Division resulting in exactly MAX_SCALE digits - var a47 = Decimal("1") / Decimal("3") + var a47 = Decimal(1) / Decimal(3) testing.assert_true( a47.scale() == Decimal.MAX_SCALE, "Case 47: Division resulting in exactly MAX_SCALE digits failed", @@ -371,18 +369,18 @@ fn test_edge_cases() raises: # 48. Division of large integers resulting in max precision testing.assert_equal( - String(Decimal("9876543210") / Decimal("123456789")), + String(Decimal(9876543210) / Decimal(123456789)), "80.00000072900000663390006037", "Division of large integers resulting in max precision", ) # 49. Division of zero by one (edge case) testing.assert_equal( - String(Decimal("0") / Decimal("1")), "0", "Division of zero by one" + String(Decimal(0) / Decimal(1)), "0", "Division of zero by one" ) # 50. Division with value at maximum supported scale - var a50 = Decimal("0." + "0" * 27 + "5") / Decimal("1") + var a50 = Decimal("0." + "0" * 27 + "5") / Decimal(1) testing.assert_true( a50.scale() <= Decimal.MAX_SCALE, "Case 50: Division with value at maximum supported scale failed", @@ -404,7 +402,7 @@ fn test_large_numbers() raises: # 52. Division where dividend is at max capacity var max_value = Decimal.MAX() - var a52 = max_value / Decimal("1") + var a52 = max_value / Decimal(1) testing.assert_equal( a52, max_value, @@ -412,13 +410,13 @@ fn test_large_numbers() raises: ) # 53. Division where dividend is slightly below max - var near_max = Decimal.MAX() - Decimal("1") - var a53 = near_max / Decimal("10") + var near_max = Decimal.MAX() - Decimal(1) + var a53 = near_max / Decimal(10) testing.assert_equal(a53, Decimal("7922816251426433759354395033.4")) # 54. Division where result approaches max - var large_num = Decimal.MAX() / Decimal("3") - var a54 = large_num * Decimal("3") + var large_num = Decimal.MAX() / Decimal(3) + var a54 = large_num * Decimal(3) testing.assert_true( a54 <= Decimal.MAX(), "Case 54: Division where result approaches max failed", @@ -426,7 +424,7 @@ fn test_large_numbers() raises: # 55. Large negative divided by large positive var large_neg = -Decimal(String("1" + "0" * 15)) - var a55 = large_neg / Decimal("10000") + var a55 = large_neg / Decimal(10000) testing.assert_equal( a55, -Decimal(String("1" + "0" * 11)), @@ -435,7 +433,7 @@ fn test_large_numbers() raises: # 56. Large integer division with remainder testing.assert_equal( - String(Decimal("12345678901234567890") / Decimal("9876543210")), + String(Decimal("12345678901234567890") / Decimal(9876543210)), "1249999988.7343749990033203125", "Large integer division with many digits", ) @@ -493,14 +491,14 @@ fn test_special_cases() raises: # 63. Division that normalizes out trailing zeros testing.assert_equal( Decimal("1.000") / Decimal("1.000"), - Decimal("1"), + Decimal(1), "Case 63: Division that normalizes out trailing zeros failed", ) # 64. Division by 1 should leave number unchanged var special_value = Decimal("123.456789012345678901234567") testing.assert_equal( - special_value / Decimal("1"), + special_value / Decimal(1), special_value, "Case 64: Division by 1 should leave number unchanged failed", ) @@ -508,21 +506,21 @@ fn test_special_cases() raises: # 65. Division by self should be 1 for non-zero testing.assert_equal( Decimal("0.000123") / Decimal("0.000123"), - Decimal("1"), + Decimal(1), "Case 65: Division by self should be 1 for non-zero failed", ) # 66. Division of 1 by numbers close to 1 testing.assert_equal( - Decimal("1") / Decimal("0.999999"), + Decimal(1) / Decimal("0.999999"), Decimal("1.000001000001000001000001000"), "Case 66: Division of 1 by numbers close to 1 failed", ) # 67. Series of divisions that should cancel out var value = Decimal("123.456") - var divided = value / Decimal("7") - var result = divided * Decimal("7") + var divided = value / Decimal(7) + var result = divided * Decimal(7) testing.assert_true( abs(value - result) / value < Decimal("0.0001"), "Case 67: Series of divisions that should cancel out failed", @@ -537,7 +535,7 @@ fn test_special_cases() raises: # 69. Division causing exact shift in magnitude testing.assert_equal( - String(Decimal("1") / Decimal("1000")), + String(Decimal(1) / Decimal(1000)), "0.001", "Division causing exact shift in magnitude", ) @@ -545,7 +543,7 @@ fn test_special_cases() raises: # 70. Dividing number very close to zero by one var very_small = Decimal("0." + "0" * 27 + "1") testing.assert_equal( - very_small / Decimal("1"), + very_small / Decimal(1), very_small, "Case 70: Dividing number very close to zero by one failed", ) @@ -558,13 +556,13 @@ fn test_mixed_precision() raises: # 71. High precision / low precision testing.assert_equal( - String(Decimal("123.456789012345678901234567") / Decimal("2")), + String(Decimal("123.456789012345678901234567") / Decimal(2)), "61.7283945061728394506172835", "High precision / low precision", ) # 72. Low precision / high precision - var a72 = Decimal("1234") / Decimal("0.0000000000000000000000011") + var a72 = Decimal(1234) / Decimal("0.0000000000000000000000011") testing.assert_equal( a72, Decimal("1121818181818181818181818181.8"), @@ -580,16 +578,16 @@ fn test_mixed_precision() raises: ) # 74. Precision of result higher than either operand - var a74 = Decimal("0.1") / Decimal("3") + var a74 = Decimal("0.1") / Decimal(3) testing.assert_true( String(a74).startswith("0.0333333333333333"), "Case 74: Precision of result higher than either operand failed", ) # 75. Division where divisor has higher precision than dividend - var a75 = Decimal("1") / Decimal("0.0001234567890123456789") + var a75 = Decimal(1) / Decimal("0.0001234567890123456789") testing.assert_true( - a75 > Decimal("8000"), + a75 > Decimal(8000), ( "Case 75: Division where divisor has higher precision than dividend" " failed" @@ -600,7 +598,7 @@ fn test_mixed_precision() raises: var a76 = Decimal("0.000000001") / Decimal("0.000000000001") testing.assert_equal( a76, - Decimal("1000"), + Decimal(1000), "Case 76: Division where precision shifts dramatically failed", ) @@ -640,23 +638,21 @@ fn test_rounding_behavior() raises: print("Testing division rounding behavior...") # 81. Banker's rounding at boundary (round to even) - var a81 = Decimal("1") / Decimal( - String("3" + "0" * (Decimal.MAX_SCALE - 1)) - ) + var a81 = Decimal(1) / Decimal(String("3" + "0" * (Decimal.MAX_SCALE - 1))) var expected = "0." + "0" * (Decimal.MAX_SCALE - 1) + "3" testing.assert_equal( String(a81), expected, "Case 81: Banker's rounding at boundary failed" ) # 82. Banker's rounding up at precision limit - var a82 = Decimal("5") / Decimal("9") # ~0.55555... + var a82 = Decimal(5) / Decimal(9) # ~0.55555... var b82 = Decimal("0." + "5" * 27 + "6") # 0.5555...6 testing.assert_equal( a82, b82, "Case 82: Banker's rounding up at precision limit failed" ) # 83. Rounding that requires carry propagation - var a83 = Decimal("1") / Decimal("1.9999999999999999999999999") + var a83 = Decimal(1) / Decimal("1.9999999999999999999999999") var expected83 = Decimal("0.5000000000000000000000000250") testing.assert_equal( a83, @@ -665,7 +661,7 @@ fn test_rounding_behavior() raises: ) # 84. Division that results in exactly half a unit in last place - var a84 = Decimal("1") / Decimal("4" + "0" * Decimal.MAX_SCALE) + var a84 = Decimal(1) / Decimal("4" + "0" * Decimal.MAX_SCALE) var expected84 = Decimal("0." + "0" * (Decimal.MAX_SCALE)) testing.assert_equal( a84, @@ -677,7 +673,7 @@ fn test_rounding_behavior() raises: ) # 85. Rounding stress test: 1/7 at different precisions - var a85 = Decimal("1") / Decimal("7") + var a85 = Decimal(1) / Decimal(7) var expected85 = Decimal( "0.1428571428571428571428571429" ) # 28 decimal places @@ -689,7 +685,7 @@ fn test_rounding_behavior() raises: # 86. Division at the edge testing.assert_equal( - String(Decimal("9.999999999999999999999999999") / Decimal("10")), + String(Decimal("9.999999999999999999999999999") / Decimal(10)), "0.9999999999999999999999999999", "Division at the edge", ) @@ -703,21 +699,21 @@ fn test_rounding_behavior() raises: # 88. Half-even rounding with even digit before testing.assert_equal( - String(Decimal("24.5") / Decimal("10")), + String(Decimal("24.5") / Decimal(10)), "2.45", "Testing half-even rounding with even digit before", ) # 89. Half-even rounding with odd digit before testing.assert_equal( - String(Decimal("25.5") / Decimal("10")), + String(Decimal("25.5") / Decimal(10)), "2.55", "Testing half-even rounding with odd digit before", ) # 90. Division with MAX_SCALE-3 digits # 1 / 300000000000000000000000000 (26 zeros) - var a90 = Decimal("1") / Decimal(String("300000000000000000000000000")) + var a90 = Decimal(1) / Decimal(String("300000000000000000000000000")) testing.assert_equal( String(a90), "0.0000000000000000000000000033", @@ -733,7 +729,7 @@ fn test_error_cases() raises: # 91. Division by zero try: - var _result = Decimal("123") / Decimal("0") + var _result = Decimal(123) / Decimal(0) testing.assert_true( False, "Case 91: Expected division by zero to raise exception" ) @@ -799,7 +795,7 @@ fn test_error_cases() raises: testing.assert_true(True, "Overflow detected (acceptable)") # 99. Multiple operations that could cause cumulative error - var calc = (Decimal("1") / Decimal("3")) * Decimal("3") + var calc = (Decimal(1) / Decimal(3)) * Decimal(3) testing.assert_equal( String(calc), "0.9999999999999999999999999999", @@ -808,7 +804,7 @@ fn test_error_cases() raises: # 100. Division at the exact boundary of precision limit # 1 / 70000000000000000000000000000 (28 zeros) - var a100 = Decimal("1") / Decimal(String("7" + "0" * Decimal.MAX_SCALE)) + var a100 = Decimal(1) / Decimal(String("7" + "0" * Decimal.MAX_SCALE)) testing.assert_equal( String(a100), "0.0000000000000000000000000000", diff --git a/tests/test_from_components.mojo b/tests/test_from_components.mojo new file mode 100644 index 0000000..873d90a --- /dev/null +++ b/tests/test_from_components.mojo @@ -0,0 +1,94 @@ +""" +Test Decimal creation from integer, float, or string values. +""" + +# TODO: Split into separate test files for each type of constructor + +from decimojo.prelude import dm, Decimal, RoundingMode +import testing + + +fn test_decimal_from_components() raises: + print("------------------------------------------------------") + print("Testing Decimal Creation from Components") + + # Test case 1: Zero with zero scale + var zero = Decimal(0, 0, 0, 0, False) + testing.assert_equal(String(zero), "0", "Zero with scale 0") + + # Test case 2: One with zero scale + var one = Decimal(1, 0, 0, 0, False) + testing.assert_equal(String(one), "1", "One with scale 0") + + # Test case 3: Negative one + var neg_one = Decimal(1, 0, 0, 0, True) + testing.assert_equal(String(neg_one), "-1", "Negative one") + + # Test case 4: Simple number with scale + var with_scale = Decimal(12345, 0, 0, 2, False) + testing.assert_equal( + String(with_scale), "123.45", "Simple number with scale 2" + ) + + # Test case 5: Negative number with scale + var neg_with_scale = Decimal(12345, 0, 0, 2, True) + testing.assert_equal( + String(neg_with_scale), "-123.45", "Negative number with scale 2" + ) + + # Test case 6: Larger number using mid + var large = Decimal(0xFFFFFFFF, 5, 0, 0, False) + var expected_large = Decimal(String(0xFFFFFFFF + 5 * 4294967296)) + testing.assert_equal( + String(large), String(expected_large), "Large number using mid field" + ) + + # Test case 7: Verify scale is correctly stored + var high_scale = Decimal(123, 0, 0, 10, False) + testing.assert_equal( + high_scale.scale(), 10, "Scale should be correctly stored" + ) + testing.assert_equal( + String(high_scale), "0.0000000123", "High scale correctly formatted" + ) + + # Test case 8: Test large scale with negative number + var neg_high_scale = Decimal(123, 0, 0, 10, True) + testing.assert_equal( + String(neg_high_scale), + "-0.0000000123", + "Negative high scale correctly formatted", + ) + + # Test case 9: Test sign flag + testing.assert_equal( + zero.is_negative(), False, "Zero should not be negative" + ) + testing.assert_equal(one.is_negative(), False, "One should not be negative") + testing.assert_equal( + neg_one.is_negative(), True, "Negative one should be negative" + ) + + # Test case 10: With high component + var with_high = Decimal(0, 0, 3, 0, False) + testing.assert_equal( + String(with_high), + "55340232221128654848", + "High component correctly handled", + ) + + # Test case 11: Maximum possible scale + var max_scale = Decimal(123, 0, 0, 28, False) + testing.assert_equal(max_scale.scale(), 28, "Maximum scale should be 28") + + # Test case 12: Overflow scale protection + try: + var _overflow_scale = Decimal(123, 0, 0, 100, False) + except: + print("Successfully caught overflow scale error") + + print("All component constructor tests passed!") + + +fn main() raises: + test_decimal_from_components() diff --git a/tests/test_from_int.mojo b/tests/test_from_int.mojo new file mode 100644 index 0000000..4a6879c --- /dev/null +++ b/tests/test_from_int.mojo @@ -0,0 +1,385 @@ +""" +Comprehensive tests for the Decimal.from_int() method. +Tests various scenarios to ensure proper conversion from integer values to Decimal. +""" + +import testing +from decimojo.prelude import dm, Decimal, RoundingMode + + +fn test_basic_integers() raises: + """Test conversion of basic integers.""" + print("Testing basic integer conversions...") + + # Test case 1: Zero + var result1 = Decimal.from_int(0) + testing.assert_equal( + String(result1), + "0", + "from_int(0) should be '0', got " + String(result1), + ) + + # Test case 2: Positive integer + var result2 = Decimal.from_int(123) + testing.assert_equal( + String(result2), + "123", + "from_int(123) should be '123', got " + String(result2), + ) + + # Test case 3: Negative integer + var result3 = Decimal.from_int(-456) + testing.assert_equal( + String(result3), + "-456", + "from_int(-456) should be '-456', got " + String(result3), + ) + + # Test case 4: Simple arithmetic with from_int results + var a = Decimal.from_int(10) + var b = Decimal.from_int(5) + var sum_result = a + b + testing.assert_equal( + String(sum_result), + "15", + "10 + 5 should be 15, got " + String(sum_result), + ) + + print("✓ Basic integer conversion tests passed!") + + +fn test_large_integers() raises: + """Test conversion of large integers.""" + print("Testing large integer conversions...") + + # Test case 1: Large positive integer + var large_pos = Decimal.from_int(1000000000) # 1 billion + testing.assert_equal( + String(large_pos), + "1000000000", + "from_int(1000000000) should be '1000000000'", + ) + + # Test case 2: Large negative integer + var large_neg = Decimal.from_int(-2000000000) # -2 billion + testing.assert_equal( + String(large_neg), + "-2000000000", + "from_int(-2000000000) should be '-2000000000'", + ) + + # Test case 3: INT32_MAX + var int32_max = Decimal.from_int(2147483647) # 2^31 - 1 + testing.assert_equal( + String(int32_max), + "2147483647", + "from_int(INT32_MAX) should be '2147483647'", + ) + + # Test case 4: INT32_MIN + var int32_min = Decimal.from_int(-2147483648) # -2^31 + testing.assert_equal( + String(int32_min), + "-2147483648", + "from_int(INT32_MIN) should be '-2147483648'", + ) + + # Test case 5: VERY large integer (close to INT64_MAX) + var very_large = Decimal.from_int(9223372036854775807) # 2^63 - 1 + testing.assert_equal( + String(very_large), + "9223372036854775807", + "from_int(INT64_MAX) conversion failed", + ) + + print("✓ Large integer conversion tests passed!") + + +fn test_operations_with_from_int() raises: + """Test arithmetic operations using from_int results.""" + print("Testing operations with from_int results...") + + # Test case 1: Addition + var a1 = Decimal.from_int(100) + var b1 = Decimal.from_int(50) + var result1 = a1 + b1 + testing.assert_equal( + String(result1), "150", "100 + 50 should be 150, got " + String(result1) + ) + + # Test case 2: Subtraction + var a2 = Decimal.from_int(100) + var b2 = Decimal.from_int(30) + var result2 = a2 - b2 + testing.assert_equal( + String(result2), "70", "100 - 30 should be 70, got " + String(result2) + ) + + # Test case 3: Multiplication + var a3 = Decimal.from_int(25) + var b3 = Decimal.from_int(4) + var result3 = a3 * b3 + testing.assert_equal( + String(result3), "100", "25 * 4 should be 100, got " + String(result3) + ) + + # Test case 4: Division + var a4 = Decimal.from_int(100) + var b4 = Decimal.from_int(5) + var result4 = a4 / b4 + testing.assert_equal( + String(result4), "20", "100 / 5 should be 20, got " + String(result4) + ) + + # Test case 5: Operation with mixed types + var a5 = Decimal.from_int(10) + var b5 = Decimal("3.5") # String constructor + var result5 = a5 * b5 + testing.assert_equal( + String(result5), + "35.0", + "10 * 3.5 should be 35.0, got " + String(result5), + ) + + print("✓ Operations with from_int results tests passed!") + + +fn test_comparison_with_from_int() raises: + """Test comparison operations using from_int results.""" + print("Testing comparisons with from_int results...") + + # Test case 1: Equality with same value + var a1 = Decimal.from_int(100) + var b1 = Decimal.from_int(100) + testing.assert_true(a1 == b1, "from_int(100) should equal from_int(100)") + + # Test case 2: Equality with string constructor + var a2 = Decimal.from_int(123) + var b2 = Decimal("123") + testing.assert_true(a2 == b2, "from_int(123) should equal Decimal('123')") + + # Test case 3: Less than + var a3 = Decimal.from_int(50) + var b3 = Decimal.from_int(100) + testing.assert_true( + a3 < b3, "from_int(50) should be less than from_int(100)" + ) + + # Test case 4: Greater than + var a4 = Decimal.from_int(200) + var b4 = Decimal.from_int(100) + testing.assert_true( + a4 > b4, "from_int(200) should be greater than from_int(100)" + ) + + # Test case 5: Equality with negative values + var a5 = Decimal.from_int(-500) + var b5 = Decimal("-500") + testing.assert_true(a5 == b5, "from_int(-500) should equal Decimal('-500')") + + print("✓ Comparison with from_int results tests passed!") + + +fn test_properties() raises: + """Test properties of from_int results.""" + print("Testing properties of from_int results...") + + # Test case 1: Sign of positive + var pos = Decimal.from_int(100) + testing.assert_false( + pos.is_negative(), "from_int(100) should not be negative" + ) + + # Test case 2: Sign of negative + var neg = Decimal.from_int(-100) + testing.assert_true(neg.is_negative(), "from_int(-100) should be negative") + + # Test case 3: Scale of integer (should be 0) + var integer = Decimal.from_int(123) + testing.assert_equal( + integer.scale(), + 0, + "Scale of from_int integer should be 0, got " + String(integer.scale()), + ) + + # Test case 4: Is_integer test + var int_test = Decimal.from_int(42) + testing.assert_true( + int_test.is_integer(), "from_int result should satisfy is_integer()" + ) + + # Test case 5: Coefficient correctness + var coef_test = Decimal.from_int(9876) + testing.assert_equal( + coef_test.coefficient(), + UInt128(9876), + "Coefficient should match the input integer value", + ) + + print("✓ Properties of from_int results tests passed!") + + +fn test_edge_cases() raises: + """Test edge cases for from_int.""" + print("Testing edge cases for from_int...") + + # Test case 1: Zero remains zero + var zero = Decimal.from_int(0) + testing.assert_equal( + String(zero), "0", "from_int(0) should be '0', got " + String(zero) + ) + + # Test case 2: Result should preserve sign for negative zero + # Note: In most contexts, -0 becomes 0, but this tests the handling of negative zero + var neg_zero = -0 + var dec_neg_zero = Decimal.from_int(neg_zero) + var is_neg_zero = dec_neg_zero.is_negative() and dec_neg_zero.is_zero() + testing.assert_equal( + is_neg_zero, + False, + "Negative zero should not preserve negative sign in Decimal", + ) + + # Test case 3: INT64_MIN + # Note: Most extreme negative value representable in Int + var int64_min = Decimal.from_int(-9223372036854775807 - 1) + testing.assert_equal( + String(int64_min), + "-9223372036854775808", + "from_int(INT64_MIN) should be '-9223372036854775808'", + ) + + # Test case 4: Alternative ways to create same value + var from_int_val = Decimal.from_int(12345) + var from_string_val = Decimal("12345") + testing.assert_true( + from_int_val == from_string_val, + "from_int and from_string should create equal Decimals for same value", + ) + + # Test case 5: Powers of 10 + var power10 = Decimal.from_int(10**9) # 1 billion + testing.assert_equal(String(power10), "1000000000", "from_int(10^9) failed") + + print("✓ Edge cases for from_int tests passed!") + + +fn test_from_int_with_scale() raises: + """Test from_int with scale argument.""" + print("Testing from_int with scale argument...") + + # Test case 1: Positive integer with positive scale + var result1 = Decimal.from_int(123, 2) + testing.assert_equal( + String(result1), + "1.23", + "from_int(123, 2) should be '1.23', got " + String(result1), + ) + testing.assert_equal(result1.scale(), 2, "Scale should be set to 2") + + # Test case 2: Negative integer with positive scale + var result2 = Decimal.from_int(-456, 3) + testing.assert_equal( + String(result2), + "-0.456", + "from_int(-456, 3) should be '-0.456', got " + String(result2), + ) + testing.assert_equal(result2.scale(), 3, "Scale should be set to 3") + + # Test case 3: Zero with scale + var result3 = Decimal.from_int(0, 4) + testing.assert_equal( + String(result3), + "0.0000", + "from_int(0, 4) should be '0.0000', got " + String(result3), + ) + testing.assert_equal(result3.scale(), 4, "Scale should be set to 4") + + # Test case 4: Positive integer + var result4 = Decimal.from_int(123, 2) + testing.assert_equal( + String(result4), + "1.23", + "from_int(123, 2) should be '1.23', got " + String(result4), + ) + + # Test case 5: Large scale (close to maximum) + var result5 = Decimal.from_int(1, 25) + testing.assert_equal( + String(result5), + "0.0000000000000000000000001", + "from_int(1, 25) incorrect string representation", + ) + testing.assert_equal(result5.scale(), 25, "Scale should be set to 25") + + # Test case 6: Max scale + var result6 = Decimal.from_int(1, Decimal.MAX_SCALE) + testing.assert_equal( + result6.scale(), + Decimal.MAX_SCALE, + "Scale should be set to MAX_SCALE = " + String(Decimal.MAX_SCALE), + ) + + # Test case 7: Arithmetic with scaled value + var a7 = Decimal.from_int(10, 1) # 1.0 + var b7 = Decimal.from_int(3, 2) # 0.03 + var result7 = a7 / b7 + testing.assert_equal( + String(result7), + "33.333333333333333333333333333", + "1.0 / 0.03 should give correct result", + ) + + # Test case 8: Comparison with different scales but same value + var a8 = Decimal.from_int(123, 0) # 123 + var b8 = Decimal.from_int(123, 2) # 1.23 + testing.assert_true( + a8 != b8, "from_int(123, 0) should not equal from_int(123, 2)" + ) + + print("✓ from_int with scale tests passed!") + + +fn run_test_with_error_handling( + test_fn: fn () raises -> None, test_name: String +) raises: + """Helper function to run a test function with error handling and reporting. + """ + try: + print("\n" + "=" * 50) + print("RUNNING: " + test_name) + print("=" * 50) + test_fn() + print("\n✓ " + test_name + " passed\n") + except e: + print("\n✗ " + test_name + " FAILED!") + print("Error message: " + String(e)) + raise e + + +fn main() raises: + print("=========================================") + print("Running Decimal.from_int() Tests") + print("=========================================") + + run_test_with_error_handling( + test_basic_integers, "Basic integer conversion test" + ) + run_test_with_error_handling( + test_large_integers, "Large integer conversion test" + ) + run_test_with_error_handling( + test_operations_with_from_int, "Operations with from_int test" + ) + run_test_with_error_handling( + test_comparison_with_from_int, "Comparison with from_int test" + ) + run_test_with_error_handling( + test_properties, "Properties of from_int results test" + ) + run_test_with_error_handling(test_edge_cases, "Edge cases test") + run_test_with_error_handling( + test_from_int_with_scale, "from_int with scale test" + ) + + print("All Decimal.from_int() tests passed!") diff --git a/tests/test_ln.mojo b/tests/test_ln.mojo index a14515c..b493880 100644 --- a/tests/test_ln.mojo +++ b/tests/test_ln.mojo @@ -14,7 +14,7 @@ fn test_basic_ln_values() raises: print("Testing basic natural logarithm values...") # Test case 1: ln(1) = 0 - var one = Decimal("1") + var one = Decimal(1) var result1 = ln(one) testing.assert_equal( String(result1), "0", "ln(1) should be 0, got " + String(result1) @@ -29,7 +29,7 @@ fn test_basic_ln_values() raises: ) # Test case 3: ln(10) - var ten = Decimal("10") + var ten = Decimal(10) var result_ten = ln(ten) testing.assert_true( String(result_ten).startswith("2.30258509299404568401799145"), @@ -65,7 +65,7 @@ fn test_fractional_ln_values() raises: ) # Test case 6: ln(2) - var two = Decimal("2") + var two = Decimal(2) var result_two = ln(two) testing.assert_true( String(result_two).startswith("0.693147180559945309417232121"), @@ -74,7 +74,7 @@ fn test_fractional_ln_values() raises: ) # Test case 7: ln(5) - var five = Decimal("5") + var five = Decimal(5) var result_five = ln(five) testing.assert_true( String(result_five).startswith("1.609437912434100374600759333"), @@ -90,8 +90,8 @@ fn test_mathematical_identities() raises: print("Testing mathematical identities for natural logarithm...") # Test case 8: ln(a * b) = ln(a) + ln(b) - var a = Decimal("2") - var b = Decimal("3") + var a = Decimal(2) + var b = Decimal(3) var ln_a_times_b = ln(a * b) var ln_a_plus_ln_b = ln(a) + ln(b) testing.assert_true( @@ -108,7 +108,7 @@ fn test_mathematical_identities() raises: ) # Test case 10: ln(e^x) = x - var x = Decimal("5") + var x = Decimal(5) var ln_e_to_x = ln(dm.exponential.exp(x)) testing.assert_true( abs(ln_e_to_x - x) < Decimal("0.0000000001"), @@ -123,7 +123,7 @@ fn test_edge_cases() raises: print("Testing edge cases for natural logarithm function...") # Test case 11: ln(0) should raise an exception - var zero = Decimal("0") + var zero = Decimal(0) var exception_caught = False try: var _ln0 = ln(zero) @@ -133,7 +133,7 @@ fn test_edge_cases() raises: testing.assert_equal(exception_caught, True) # Test case 12: ln of a negative number should raise an exception - var neg_one = Decimal("-1") + var neg_one = Decimal(-1) exception_caught = False try: var _ln = ln(neg_one) @@ -171,7 +171,7 @@ fn test_precision() raises: print("Testing precision of natural logarithm calculations...") # Test case 15: ln(2) with high precision - var two = Decimal("2") + var two = Decimal(2) var result_two = ln(two) testing.assert_true( String(result_two).startswith("0.693147180559945309417232121"), @@ -179,7 +179,7 @@ fn test_precision() raises: ) # Test case 16: ln(10) with high precision - var ten = Decimal("10") + var ten = Decimal(10) var result_ten = ln(ten) testing.assert_true( String(result_ten).startswith("2.30258509299404568401"), @@ -220,7 +220,7 @@ fn test_special_cases() raises: print("Testing special cases for natural logarithm function...") # Test case 19: ln(1) = 0 (revisited) - var one = Decimal("1") + var one = Decimal(1) var result_one = ln(one) testing.assert_equal(String(result_one), "0", "ln(1) should be exactly 0") @@ -228,7 +228,7 @@ fn test_special_cases() raises: var e = Decimal("2.718281828459045235360287471") var result_e = ln(e) testing.assert_true( - abs(result_e - Decimal("1")) < Decimal("0.0000000001"), + abs(result_e - Decimal(1)) < Decimal("0.0000000001"), "ln(e) should be very close to 1", ) diff --git a/tests/test_multiply.mojo b/tests/test_multiply.mojo index 24d4b04..8954518 100644 --- a/tests/test_multiply.mojo +++ b/tests/test_multiply.mojo @@ -11,8 +11,8 @@ fn test_basic_multiplication() raises: print("Testing basic multiplication...") # Test case 1: Simple integer multiplication - var a1 = Decimal("5") - var b1 = Decimal("3") + var a1 = Decimal(5) + var b1 = Decimal(3) var result1 = a1 * b1 testing.assert_equal( String(result1), "15", "5 * 3 should equal 15, got " + String(result1) @@ -20,7 +20,7 @@ fn test_basic_multiplication() raises: # Test case 2: Simple decimal multiplication var a2 = Decimal("2.5") - var b2 = Decimal("4") + var b2 = Decimal(4) var result2 = a2 * b2 testing.assert_equal( String(result2), @@ -67,7 +67,7 @@ fn test_special_cases() raises: # Test case 1: Multiplication by zero var a1 = Decimal("123.45") - var zero = Decimal("0") + var zero = Decimal(0) var result1 = a1 * zero testing.assert_equal( String(result1), @@ -77,7 +77,7 @@ fn test_special_cases() raises: # Test case 2: Multiplication by one var a2 = Decimal("123.45") - var one = Decimal("1") + var one = Decimal(1) var result2 = a2 * one testing.assert_equal( String(result2), @@ -86,7 +86,7 @@ fn test_special_cases() raises: ) # Test case 3: Multiplication of zero by any number - var a3 = Decimal("0") + var a3 = Decimal(0) var b3 = Decimal("987.654") var result3 = a3 * b3 testing.assert_equal( @@ -97,7 +97,7 @@ fn test_special_cases() raises: # Test case 4: Multiplication by negative one var a4 = Decimal("123.45") - var neg_one = Decimal("-1") + var neg_one = Decimal(-1) var result4 = a4 * neg_one testing.assert_equal( String(result4), @@ -122,8 +122,8 @@ fn test_negative_multiplication() raises: print("Testing multiplication with negative numbers...") # Test case 1: Negative * positive - var a1 = Decimal("-5") - var b1 = Decimal("3") + var a1 = Decimal(-5) + var b1 = Decimal(3) var result1 = a1 * b1 testing.assert_equal( String(result1), @@ -132,8 +132,8 @@ fn test_negative_multiplication() raises: ) # Test case 2: Positive * negative - var a2 = Decimal("5") - var b2 = Decimal("-3") + var a2 = Decimal(5) + var b2 = Decimal(-3) var result2 = a2 * b2 testing.assert_equal( String(result2), @@ -142,8 +142,8 @@ fn test_negative_multiplication() raises: ) # Test case 3: Negative * negative - var a3 = Decimal("-5") - var b3 = Decimal("-3") + var a3 = Decimal(-5) + var b3 = Decimal(-3) var result3 = a3 * b3 testing.assert_equal( String(result3), "15", "-5 * -3 should equal 15, got " + String(result3) @@ -266,7 +266,7 @@ fn test_boundary_cases() raises: # Test case 5: Result has trailing zeros with integer var a5 = Decimal("1.25") - var b5 = Decimal("4") + var b5 = Decimal(4) var result5 = a5 * b5 testing.assert_equal( String(result5), @@ -283,8 +283,8 @@ fn test_commutative_property() raises: print("Testing commutative property of multiplication...") # Test pair 1: Integers - var a1 = Decimal("10") - var b1 = Decimal("20") + var a1 = Decimal(10) + var b1 = Decimal(20) var result1a = a1 * b1 var result1b = b1 * a1 testing.assert_equal( @@ -295,7 +295,7 @@ fn test_commutative_property() raises: # Test pair 2: Mixed decimal and integer var a2 = Decimal("3.5") - var b2 = Decimal("2") + var b2 = Decimal(2) var result2a = a2 * b2 var result2b = b2 * a2 testing.assert_equal( @@ -305,8 +305,8 @@ fn test_commutative_property() raises: ) # Test pair 3: Negative and positive - var a3 = Decimal("-5") - var b3 = Decimal("7") + var a3 = Decimal(-5) + var b3 = Decimal(7) var result3a = a3 * b3 var result3b = b3 * a3 testing.assert_equal( @@ -328,7 +328,7 @@ fn test_commutative_property() raises: # Test pair 5: Very small and very large var a5 = Decimal("0.0001") - var b5 = Decimal("10000") + var b5 = Decimal(10000) var result5a = a5 * b5 var result5b = b5 * a5 testing.assert_equal( diff --git a/tests/test_power.mojo b/tests/test_power.mojo index 522078c..9e1a237 100644 --- a/tests/test_power.mojo +++ b/tests/test_power.mojo @@ -12,7 +12,7 @@ fn test_integer_powers() raises: print("Testing integer powers...") # Test case 1: Positive base, positive exponent - var base1 = Decimal("2") + var base1 = Decimal(2) var exponent1 = 3 var result1 = power(base1, exponent1) testing.assert_equal( @@ -20,7 +20,7 @@ fn test_integer_powers() raises: ) # Test case 2: Positive base, zero exponent - var base2 = Decimal("5") + var base2 = Decimal(5) var exponent2 = 0 var result2 = power(base2, exponent2) testing.assert_equal( @@ -28,7 +28,7 @@ fn test_integer_powers() raises: ) # Test case 3: Positive base, negative exponent - var base3 = Decimal("2") + var base3 = Decimal(2) var exponent3 = -2 var result3 = power(base3, exponent3) testing.assert_equal( @@ -59,7 +59,7 @@ fn test_decimal_powers() raises: print("Testing decimal powers...") # Test case 1: Positive base, simple fractional exponent (0.5) - var base1 = Decimal("9") + var base1 = Decimal(9) var exponent1 = Decimal("0.5") var result1 = power(base1, exponent1) testing.assert_equal( @@ -67,7 +67,7 @@ fn test_decimal_powers() raises: ) # Test case 2: Positive base, more complex fractional exponent - var base2 = Decimal("2") + var base2 = Decimal(2) var exponent2 = Decimal("1.5") var result2 = power(base2, exponent2) testing.assert_true( @@ -87,7 +87,7 @@ fn test_decimal_powers() raises: ) # Test case 4: Base > 1, exponent < 0 - var base4 = Decimal("4") + var base4 = Decimal(4) var exponent4 = Decimal("-0.5") var result4 = power(base4, exponent4) testing.assert_equal( @@ -102,16 +102,16 @@ fn test_edge_cases() raises: print("Testing power edge cases...") # Test case 1: Zero base, positive exponent - var base1 = Decimal("0") - var exponent1 = Decimal("2") + var base1 = Decimal(0) + var exponent1 = Decimal(2) var result1 = power(base1, exponent1) testing.assert_equal( String(result1), "0", "0^2 should be 0, got " + String(result1) ) # Test case 2: Zero base, negative exponent (should raise error) - var base2 = Decimal("0") - var exponent2 = Decimal("-2") + var base2 = Decimal(0) + var exponent2 = Decimal(-2) var exception_caught = False try: var _result = power(base2, exponent2) @@ -125,15 +125,15 @@ fn test_edge_cases() raises: ) # Test case 3: Negative base, integer exponent - var base3 = Decimal("-2") - var exponent3 = Decimal("3") + var base3 = Decimal(-2) + var exponent3 = Decimal(3) var result3 = power(base3, exponent3) testing.assert_equal( String(result3), "-8", "(-2)^3 should be -8, got " + String(result3) ) # Test case 4: Negative base, non-integer exponent (should raise error) - var base4 = Decimal("-2") + var base4 = Decimal(-2) var exponent4 = Decimal("0.5") exception_caught = False try: diff --git a/tests/test_sqrt.mojo b/tests/test_sqrt.mojo index 35b660d..f793ce8 100644 --- a/tests/test_sqrt.mojo +++ b/tests/test_sqrt.mojo @@ -11,7 +11,7 @@ fn test_perfect_squares() raises: # Test case 1: sqrt(1) = 1 try: - var d1 = Decimal("1") + var d1 = Decimal(1) print(" Testing sqrt(1)...") var result1 = sqrt(d1) print(" Got result: " + String(result1)) @@ -28,7 +28,7 @@ fn test_perfect_squares() raises: # Test case 2: sqrt(4) = 2 try: - var d2 = Decimal("4") + var d2 = Decimal(4) print(" Testing sqrt(4)...") var result2 = sqrt(d2) print(" Got result: " + String(result2)) @@ -45,7 +45,7 @@ fn test_perfect_squares() raises: # Test case 3: sqrt(9) = 3 try: - var d3 = Decimal("9") + var d3 = Decimal(9) print(" Testing sqrt(9)...") var result3 = sqrt(d3) print(" Got result: " + String(result3)) @@ -62,7 +62,7 @@ fn test_perfect_squares() raises: # Test case 4: sqrt(16) = 4 try: - var d4 = Decimal("16") + var d4 = Decimal(16) print(" Testing sqrt(16)...") var result4 = sqrt(d4) print(" Got result: " + String(result4)) @@ -79,7 +79,7 @@ fn test_perfect_squares() raises: # Test case 5: sqrt(25) = 5 try: - var d5 = Decimal("25") + var d5 = Decimal(25) print(" Testing sqrt(25)...") var result5 = sqrt(d5) print(" Got result: " + String(result5)) @@ -96,7 +96,7 @@ fn test_perfect_squares() raises: # Test case 6: sqrt(36) = 6 try: - var d6 = Decimal("36") + var d6 = Decimal(36) print(" Testing sqrt(36)...") var result6 = sqrt(d6) print(" Got result: " + String(result6)) @@ -113,7 +113,7 @@ fn test_perfect_squares() raises: # Test case 7: sqrt(49) = 7 try: - var d7 = Decimal("49") + var d7 = Decimal(49) print(" Testing sqrt(49)...") var result7 = sqrt(d7) print(" Got result: " + String(result7)) @@ -130,7 +130,7 @@ fn test_perfect_squares() raises: # Test case 8: sqrt(64) = 8 try: - var d8 = Decimal("64") + var d8 = Decimal(64) print(" Testing sqrt(64)...") var result8 = sqrt(d8) print(" Got result: " + String(result8)) @@ -147,7 +147,7 @@ fn test_perfect_squares() raises: # Test case 9: sqrt(81) = 9 try: - var d9 = Decimal("81") + var d9 = Decimal(81) print(" Testing sqrt(81)...") var result9 = sqrt(d9) print(" Got result: " + String(result9)) @@ -164,7 +164,7 @@ fn test_perfect_squares() raises: # Test case 10: sqrt(100) = 10 try: - var d10 = Decimal("100") + var d10 = Decimal(100) print(" Testing sqrt(100)...") var result10 = sqrt(d10) print(" Got result: " + String(result10)) @@ -181,7 +181,7 @@ fn test_perfect_squares() raises: # Test case 11: sqrt(10000) = 100 try: - var d11 = Decimal("10000") + var d11 = Decimal(10000) print(" Testing sqrt(10000)...") var result11 = sqrt(d11) print(" Got result: " + String(result11)) @@ -198,7 +198,7 @@ fn test_perfect_squares() raises: # Test case 12: sqrt(1000000) = 1000 try: - var d12 = Decimal("1000000") + var d12 = Decimal(1000000) print(" Testing sqrt(1000000)...") var result12 = sqrt(d12) print(" Got result: " + String(result12)) @@ -221,7 +221,7 @@ fn test_non_perfect_squares() raises: # Test case 1 try: - var d1 = Decimal("2") + var d1 = Decimal(2) var expected_prefix1 = "1.414213562373095048801688724" var result1 = sqrt(d1) var result_str1 = String(result1) @@ -239,7 +239,7 @@ fn test_non_perfect_squares() raises: raise e # Test case 2 - var d2 = Decimal("3") + var d2 = Decimal(3) var expected_prefix2 = "1.73205080756887729352744634" var result2 = sqrt(d2) var result_str2 = String(result2) @@ -254,7 +254,7 @@ fn test_non_perfect_squares() raises: ) # Test case 3 - var d3 = Decimal("5") + var d3 = Decimal(5) var expected_prefix3 = "2.23606797749978969640917366" var result3 = sqrt(d3) var result_str3 = String(result3) @@ -269,7 +269,7 @@ fn test_non_perfect_squares() raises: ) # Test case 4 - var d4 = Decimal("10") + var d4 = Decimal(10) var expected_prefix4 = "3.162277660168379331998893544" var result4 = sqrt(d4) var result_str4 = String(result4) @@ -284,7 +284,7 @@ fn test_non_perfect_squares() raises: ) # Test case 5 - var d5 = Decimal("50") + var d5 = Decimal(50) var expected_prefix5 = "7.071067811865475244008443621" var result5 = sqrt(d5) var result_str5 = String(result5) @@ -299,7 +299,7 @@ fn test_non_perfect_squares() raises: ) # Test case 6 - var d6 = Decimal("99") + var d6 = Decimal(99) var expected_prefix6 = "9.949874371066199547344798210" var result6 = sqrt(d6) var result_str6 = String(result6) @@ -314,7 +314,7 @@ fn test_non_perfect_squares() raises: ) # Test case 7 - var d7 = Decimal("999") + var d7 = Decimal(999) var expected_prefix7 = "31.6069612585582165452042139" var result7 = sqrt(d7) var result_str7 = String(result7) @@ -416,7 +416,7 @@ fn test_edge_cases() raises: # Test sqrt(0) = 0 try: - var zero = Decimal("0") + var zero = Decimal(0) var result_zero = sqrt(zero) testing.assert_equal(String(result_zero), "0", "sqrt(0) should be 0") except e: @@ -425,7 +425,7 @@ fn test_edge_cases() raises: # Test sqrt(1) = 1 try: - var one = Decimal("1") + var one = Decimal(1) var result_one = sqrt(one) testing.assert_equal(String(result_one), "1", "sqrt(1) should be 1") except e: @@ -434,9 +434,7 @@ fn test_edge_cases() raises: # Test very small positive number try: - var very_small = Decimal( - "0." + "0" * 27 + "1" - ) # Smallest possible positive decimal + var very_small = Decimal(1, 28) # Smallest possible positive decimal var result_small = sqrt(very_small) testing.assert_equal( String(result_small), @@ -452,7 +450,9 @@ fn test_edge_cases() raises: # Test very large number try: - var very_large = Decimal("1" + "0" * 27) # Large decimal + var very_large = Decimal.from_uint128( + decimojo.utility.power_of_10[DType.uint128](27) + ) # Large decimal var result_large = sqrt(very_large) testing.assert_true( String(result_large).startswith("31622776601683.79331998893544"), @@ -465,7 +465,7 @@ fn test_edge_cases() raises: # Test negative number exception var negative_exception_caught = False try: - var negative = Decimal("-1") + var negative = Decimal(-1) var _result_negative = sqrt(negative) testing.assert_equal( True, False, "sqrt() of negative should raise exception" @@ -494,7 +494,7 @@ fn test_precision() raises: var expected_sqrt2 = "1.414213562373095048801688724" # First 10 decimal places of sqrt(2) # Test precision for irrational numbers - var two = Decimal("2") + var two = Decimal(2) var result = sqrt(two) # Check at least 10 decimal places (should be enough for most applications) @@ -504,7 +504,9 @@ fn test_precision() raises: ) # Test high precision values - var precise_value = Decimal("2.0000000000000000000000000") + var precise_value = Decimal.from_uint128( + UInt128(20000000000000000000000000), 25 + ) var precise_result = sqrt(precise_value) testing.assert_true( String(precise_result).startswith(expected_sqrt2), @@ -512,7 +514,7 @@ fn test_precision() raises: ) # Check that results are appropriately rounded - var d = Decimal("1894128.128951235") + var d = Decimal(1894128128951235, 9) var sqrt_d = sqrt(d) testing.assert_true( String(sqrt_d).startswith("1376.27327553478091940498131"), @@ -531,7 +533,7 @@ fn test_mathematical_identities() raises: # Test that sqrt(x)² = x - Expanded for each test number # Test number 1 - var num1 = Decimal("2") + var num1 = Decimal(2) var sqrt_num1 = sqrt(num1) var squared1 = sqrt_num1 * sqrt_num1 var original_rounded1 = round(num1, 10) @@ -547,7 +549,7 @@ fn test_mathematical_identities() raises: ) # Test number 2 - var num2 = Decimal("3") + var num2 = Decimal(3) var sqrt_num2 = sqrt(num2) var squared2 = sqrt_num2 * sqrt_num2 var original_rounded2 = round(num2, 10) @@ -561,7 +563,7 @@ fn test_mathematical_identities() raises: ) # Test number 3 - var num3 = Decimal("5") + var num3 = Decimal(5) var sqrt_num3 = sqrt(num3) var squared3 = sqrt_num3 * sqrt_num3 var original_rounded3 = round(num3, 10) @@ -575,7 +577,7 @@ fn test_mathematical_identities() raises: ) # Test number 4 - var num4 = Decimal("7") + var num4 = Decimal(7) var sqrt_num4 = sqrt(num4) var squared4 = sqrt_num4 * sqrt_num4 var original_rounded4 = round(num4, 10) @@ -589,7 +591,7 @@ fn test_mathematical_identities() raises: ) # Test number 5 - var num5 = Decimal("10") + var num5 = Decimal(10) var sqrt_num5 = sqrt(num5) var squared5 = sqrt_num5 * sqrt_num5 var original_rounded5 = round(num5, 10) @@ -603,7 +605,7 @@ fn test_mathematical_identities() raises: ) # Test number 6 - var num6 = Decimal("0.5") + var num6 = Decimal(5, 1) var sqrt_num6 = sqrt(num6) var squared6 = sqrt_num6 * sqrt_num6 var original_rounded6 = round(num6, 10) @@ -617,7 +619,7 @@ fn test_mathematical_identities() raises: ) # Test number 7 - var num7 = Decimal("0.25") + var num7 = Decimal(25, 2) var sqrt_num7 = sqrt(num7) var squared7 = sqrt_num7 * sqrt_num7 var original_rounded7 = round(num7, 10) @@ -631,7 +633,7 @@ fn test_mathematical_identities() raises: ) # Test number 8 - var num8 = Decimal("1.44") + var num8 = Decimal(144, 2) var sqrt_num8 = sqrt(num8) var squared8 = sqrt_num8 * sqrt_num8 var original_rounded8 = round(num8, 10) @@ -647,8 +649,8 @@ fn test_mathematical_identities() raises: # Test that sqrt(x*y) = sqrt(x) * sqrt(y) - Expanded for each pair # Pair 1: 4 and 9 try: - var x1 = Decimal("4") - var y1 = Decimal("9") + var x1 = Decimal(4) + var y1 = Decimal(9) var product1 = x1 * y1 var sqrt_product1 = sqrt(product1) var sqrt_x1 = sqrt(x1) @@ -676,8 +678,8 @@ fn test_mathematical_identities() raises: raise e # Pair 2: 16 and 25 - var x2 = Decimal("16") - var y2 = Decimal("25") + var x2 = Decimal(16) + var y2 = Decimal(25) var product2 = x2 * y2 var sqrt_product2 = sqrt(product2) var sqrt_x2 = sqrt(x2) @@ -699,8 +701,8 @@ fn test_mathematical_identities() raises: ) # Pair 3: 2 and 8 - var x3 = Decimal("2") - var y3 = Decimal("8") + var x3 = Decimal(2) + var y3 = Decimal(8) var product3 = x3 * y3 var sqrt_product3 = sqrt(product3) var sqrt_x3 = sqrt(x3) @@ -762,7 +764,7 @@ fn test_sqrt_performance() raises: ) # Test case 3 - var num3 = Decimal("1") + var num3 = Decimal(1) var result3 = sqrt(num3) var squared3 = result3 * result3 var diff3 = squared3 - num3 @@ -777,7 +779,7 @@ fn test_sqrt_performance() raises: ) # Test case 4 - var num4 = Decimal("10") + var num4 = Decimal(10) var result4 = sqrt(num4) var squared4 = result4 * result4 var diff4 = squared4 - num4 @@ -792,7 +794,7 @@ fn test_sqrt_performance() raises: ) # Test case 5 - var num5 = Decimal("10000") + var num5 = Decimal(10000) var result5 = sqrt(num5) var squared5 = result5 * result5 var diff5 = squared5 - num5 diff --git a/tests/test_to_float.mojo b/tests/test_to_float.mojo index bbff71c..b9af040 100644 --- a/tests/test_to_float.mojo +++ b/tests/test_to_float.mojo @@ -12,28 +12,28 @@ fn test_basic_integer_conversions() raises: print("Testing basic integer conversions to float...") # Test case 1: Zero - var zero = Decimal("0") + var zero = Decimal(0) var zero_float = Float64(zero) testing.assert_equal( zero_float, 0.0, "Decimal('0') should convert to float 0.0" ) # Test case 2: One - var one = Decimal("1") + var one = Decimal(1) var one_float = Float64(one) testing.assert_equal( one_float, 1.0, "Decimal('1') should convert to float 1.0" ) # Test case 3: Ten - var ten = Decimal("10") + var ten = Decimal(10) var ten_float = Float64(ten) testing.assert_equal( ten_float, 10.0, "Decimal('10') should convert to float 10.0" ) # Test case 4: Large integer - var large_int = Decimal("123456") + var large_int = Decimal(123456) var large_int_float = Float64(large_int) testing.assert_equal(large_int_float, 123456.0) diff --git a/tests/test_to_int.mojo b/tests/test_to_int.mojo index be9f8cf..57e6cbd 100644 --- a/tests/test_to_int.mojo +++ b/tests/test_to_int.mojo @@ -13,37 +13,37 @@ fn test_int_conversion() raises: print("--- Testing Int Conversion ---") # Test positive integer - var d1 = Decimal("123") + var d1 = Decimal(123) var i1 = Int(d1) print("Int(123) =", i1) testing.assert_equal(i1, 123) # Test negative integer - var d2 = Decimal("-456") + var d2 = Decimal(-456) var i2 = Int(d2) print("Int(-456) =", i2) testing.assert_equal(i2, -456) # Test zero - var d3 = Decimal("0") + var d3 = Decimal(0) var i3 = Int(d3) print("Int(0) =", i3) testing.assert_equal(i3, 0) # Test decimal truncation - var d4 = Decimal("789.987") + var d4 = Decimal(789987, 3) var i4 = Int(d4) print("Int(789.987) =", i4) testing.assert_equal(i4, 789) # Test negative decimal truncation - var d5 = Decimal("-123.456") + var d5 = Decimal(-123456, 3) var i5 = Int(d5) print("Int(-123.456) =", i5) testing.assert_equal(i5, -123) # Test large number - var d6 = Decimal("9999999999") + var d6 = Decimal(9999999999) var i6 = Int(d6) print("Int(9999999999) =", i6) testing.assert_equal(i6, 9999999999) diff --git a/tests/test_to_string.mojo b/tests/test_to_string.mojo index c885ed5..9c5b03a 100644 --- a/tests/test_to_string.mojo +++ b/tests/test_to_string.mojo @@ -25,7 +25,7 @@ fn test_str_conversion() raises: testing.assert_equal(s2, "-789.012") # Test zero - var d3 = Decimal("0") + var d3 = Decimal(0) var s3 = String(d3) print("String(0) =", s3) testing.assert_equal(s3, "0")