diff --git a/README.md b/README.md index 54ceb98..8421e7a 100644 --- a/README.md +++ b/README.md @@ -30,8 +30,8 @@ This repository includes [TOMLMojo](https://github.com/forfudan/decimojo/tree/ma | ------------ | ------- | ------------------------------------ | ----------------------------------- | | `BigUInt` | `BUInt` | arbitrary-precision unsigned integer | `List[UInt32]` | | `BigInt` | `BInt` | arbitrary-precision integer | `BigUInt`, `Bool` | -| `Decimal` | `Dec` | 128-bit fixed-precision decimal | `UInt32`,`UInt32`,`UInt32`,`UInt32` | | `BigDecimal` | `BDec` | arbitrary-precision decimal | `BigUInt`, `Int`, `Bool` | +| `Decimal` | `Dec` | 128-bit fixed-precision decimal | `UInt32`,`UInt32`,`UInt32`,`UInt32` | ## Installation @@ -39,7 +39,7 @@ DeciMojo is available in the [modular-community](https://repo.prefix.dev/modular From the `pixi` CLI, simply run ```pixi add decimojo```. This fetches the latest version and makes it immediately available for import. -For projects with a `mojoproject.toml`file, add the dependency ```decimojo = ">=0.3.1"```. Then run `pixi install` to download and install the package. +For projects with a `mojoproject.toml`file, add the dependency ```decimojo = "==0.4.0"```. Then run `pixi install` to download and install the package. For the latest development version, clone the [GitHub repository](https://github.com/forfudan/decimojo) and build the package locally. @@ -49,6 +49,7 @@ For the latest development version, clone the [GitHub repository](https://github | v0.2.0 | ==25.2 | magic | | v0.3.0 | ==25.2 | magic | | v0.3.1 | >=25.2, <25.4 | pixi | +| v0.4.0 | ==25.4 | pixi | ## Quick start @@ -217,7 +218,7 @@ If you find DeciMojo useful for your research, consider listing it in your citat year = {2025}, title = {An arbitrary-precision decimal and integer mathematics library for Mojo}, url = {https://github.com/forfudan/decimojo}, - version = {0.3.1}, + version = {0.4.0}, note = {Computer Software} } ``` diff --git a/benches/bigdecimal/bench_bigdecimal_add.mojo b/benches/bigdecimal/bench_bigdecimal_add.mojo index 6d28aa4..2ae4751 100644 --- a/benches/bigdecimal/bench_bigdecimal_add.mojo +++ b/benches/bigdecimal/bench_bigdecimal_add.mojo @@ -28,7 +28,9 @@ fn open_log_file() raises -> PythonObject: # Generate a timestamp for the filename var timestamp = String(datetime.datetime.now().isoformat()) - var log_filename = log_dir + "/benchmark_bigdecimal_add_" + timestamp + ".log" + var log_filename = ( + log_dir + "/benchmark_bigdecimal_add_" + timestamp + ".log" + ) print("Saving benchmark results to:", log_filename) return python.open(log_filename, "w") diff --git a/benches/bigdecimal/bench_bigdecimal_divide.mojo b/benches/bigdecimal/bench_bigdecimal_divide.mojo index 5c01e88..399255d 100644 --- a/benches/bigdecimal/bench_bigdecimal_divide.mojo +++ b/benches/bigdecimal/bench_bigdecimal_divide.mojo @@ -28,7 +28,9 @@ fn open_log_file() raises -> PythonObject: # Generate a timestamp for the filename var timestamp = String(datetime.datetime.now().isoformat()) - var log_filename = log_dir + "/benchmark_bigdecimal_divide_" + timestamp + ".log" + var log_filename = ( + log_dir + "/benchmark_bigdecimal_divide_" + timestamp + ".log" + ) print("Saving benchmark results to:", log_filename) return python.open(log_filename, "w") diff --git a/benches/bigdecimal/bench_bigdecimal_exp.mojo b/benches/bigdecimal/bench_bigdecimal_exp.mojo index 7104e3c..fef8cf9 100644 --- a/benches/bigdecimal/bench_bigdecimal_exp.mojo +++ b/benches/bigdecimal/bench_bigdecimal_exp.mojo @@ -28,7 +28,9 @@ fn open_log_file() raises -> PythonObject: # Generate a timestamp for the filename var timestamp = String(datetime.datetime.now().isoformat()) - var log_filename = log_dir + "/benchmark_bigdecimal_exp_" + timestamp + ".log" + var log_filename = ( + log_dir + "/benchmark_bigdecimal_exp_" + timestamp + ".log" + ) print("Saving benchmark results to:", log_filename) return python.open(log_filename, "w") diff --git a/benches/bigdecimal/bench_bigdecimal_ln.mojo b/benches/bigdecimal/bench_bigdecimal_ln.mojo index 79d738c..8d3f20d 100644 --- a/benches/bigdecimal/bench_bigdecimal_ln.mojo +++ b/benches/bigdecimal/bench_bigdecimal_ln.mojo @@ -28,7 +28,9 @@ fn open_log_file() raises -> PythonObject: # Generate a timestamp for the filename var timestamp = String(datetime.datetime.now().isoformat()) - var log_filename = log_dir + "/benchmark_bigdecimal_ln_" + timestamp + ".log" + var log_filename = ( + log_dir + "/benchmark_bigdecimal_ln_" + timestamp + ".log" + ) print("Saving benchmark results to:", log_filename) return python.open(log_filename, "w") diff --git a/benches/bigdecimal/bench_bigdecimal_multiply.mojo b/benches/bigdecimal/bench_bigdecimal_multiply.mojo index 36ce00e..5afa303 100644 --- a/benches/bigdecimal/bench_bigdecimal_multiply.mojo +++ b/benches/bigdecimal/bench_bigdecimal_multiply.mojo @@ -28,7 +28,9 @@ fn open_log_file() raises -> PythonObject: # Generate a timestamp for the filename var timestamp = String(datetime.datetime.now().isoformat()) - var log_filename = log_dir + "/benchmark_bigdecimal_multiply_" + timestamp + ".log" + var log_filename = ( + log_dir + "/benchmark_bigdecimal_multiply_" + timestamp + ".log" + ) print("Saving benchmark results to:", log_filename) return python.open(log_filename, "w") diff --git a/benches/bigdecimal/bench_bigdecimal_root.mojo b/benches/bigdecimal/bench_bigdecimal_root.mojo index 5b5b727..1f5270b 100644 --- a/benches/bigdecimal/bench_bigdecimal_root.mojo +++ b/benches/bigdecimal/bench_bigdecimal_root.mojo @@ -28,7 +28,9 @@ fn open_log_file() raises -> PythonObject: # Generate a timestamp for the filename var timestamp = String(datetime.datetime.now().isoformat()) - var log_filename = log_dir + "/benchmark_bigdecimal_root_" + timestamp + ".log" + var log_filename = ( + log_dir + "/benchmark_bigdecimal_root_" + timestamp + ".log" + ) print("Saving benchmark results to:", log_filename) return python.open(log_filename, "w") diff --git a/benches/bigdecimal/bench_bigdecimal_round.mojo b/benches/bigdecimal/bench_bigdecimal_round.mojo index e184173..b73a53c 100644 --- a/benches/bigdecimal/bench_bigdecimal_round.mojo +++ b/benches/bigdecimal/bench_bigdecimal_round.mojo @@ -28,7 +28,9 @@ fn open_log_file() raises -> PythonObject: # Generate a timestamp for the filename var timestamp = String(datetime.datetime.now().isoformat()) - var log_filename = log_dir + "/benchmark_bigdecimal_round_" + timestamp + ".log" + var log_filename = ( + log_dir + "/benchmark_bigdecimal_round_" + timestamp + ".log" + ) print("Saving benchmark results to:", log_filename) return python.open(log_filename, "w") diff --git a/benches/bigdecimal/bench_bigdecimal_scale_up_by_power_of_10.mojo b/benches/bigdecimal/bench_bigdecimal_scale_up_by_power_of_10.mojo index 2637738..19f6eda 100644 --- a/benches/bigdecimal/bench_bigdecimal_scale_up_by_power_of_10.mojo +++ b/benches/bigdecimal/bench_bigdecimal_scale_up_by_power_of_10.mojo @@ -26,7 +26,9 @@ fn open_log_file() raises -> PythonObject: # Generate a timestamp for the filename var timestamp = String(datetime.datetime.now().isoformat()) - var log_filename = log_dir + "/benchmark_biguint_scale_up_" + timestamp + ".log" + var log_filename = ( + log_dir + "/benchmark_biguint_scale_up_" + timestamp + ".log" + ) print("Saving benchmark results to:", log_filename) return python.open(log_filename, "w") diff --git a/benches/bigdecimal/bench_bigdecimal_sqrt.mojo b/benches/bigdecimal/bench_bigdecimal_sqrt.mojo index 92a2004..3872ac3 100644 --- a/benches/bigdecimal/bench_bigdecimal_sqrt.mojo +++ b/benches/bigdecimal/bench_bigdecimal_sqrt.mojo @@ -28,7 +28,9 @@ fn open_log_file() raises -> PythonObject: # Generate a timestamp for the filename var timestamp = String(datetime.datetime.now().isoformat()) - var log_filename = log_dir + "/benchmark_bigdecimal_sqrt_" + timestamp + ".log" + var log_filename = ( + log_dir + "/benchmark_bigdecimal_sqrt_" + timestamp + ".log" + ) print("Saving benchmark results to:", log_filename) return python.open(log_filename, "w") diff --git a/benches/bigdecimal/bench_bigdecimal_subtract.mojo b/benches/bigdecimal/bench_bigdecimal_subtract.mojo index 1ea8468..bc42695 100644 --- a/benches/bigdecimal/bench_bigdecimal_subtract.mojo +++ b/benches/bigdecimal/bench_bigdecimal_subtract.mojo @@ -28,7 +28,9 @@ fn open_log_file() raises -> PythonObject: # Generate a timestamp for the filename var timestamp = String(datetime.datetime.now().isoformat()) - var log_filename = log_dir + "/benchmark_bigdecimal_subtract_" + timestamp + ".log" + var log_filename = ( + log_dir + "/benchmark_bigdecimal_subtract_" + timestamp + ".log" + ) print("Saving benchmark results to:", log_filename) return python.open(log_filename, "w") diff --git a/benches/bigdecimal/bench_scale_up_by_power_of_10.mojo b/benches/bigdecimal/bench_scale_up_by_power_of_10.mojo index 2637738..19f6eda 100644 --- a/benches/bigdecimal/bench_scale_up_by_power_of_10.mojo +++ b/benches/bigdecimal/bench_scale_up_by_power_of_10.mojo @@ -26,7 +26,9 @@ fn open_log_file() raises -> PythonObject: # Generate a timestamp for the filename var timestamp = String(datetime.datetime.now().isoformat()) - var log_filename = log_dir + "/benchmark_biguint_scale_up_" + timestamp + ".log" + var log_filename = ( + log_dir + "/benchmark_biguint_scale_up_" + timestamp + ".log" + ) print("Saving benchmark results to:", log_filename) return python.open(log_filename, "w") diff --git a/benches/bigint/bench_bigint_floor_divide.mojo b/benches/bigint/bench_bigint_floor_divide.mojo index 6384f66..71186ba 100644 --- a/benches/bigint/bench_bigint_floor_divide.mojo +++ b/benches/bigint/bench_bigint_floor_divide.mojo @@ -29,7 +29,9 @@ fn open_log_file() raises -> PythonObject: # Generate a timestamp for the filename var timestamp = String(datetime.datetime.now().isoformat()) - var log_filename = log_dir + "/benchmark_bigint_floor_divide_" + timestamp + ".log" + var log_filename = ( + log_dir + "/benchmark_bigint_floor_divide_" + timestamp + ".log" + ) print("Saving benchmark results to:", log_filename) return python.open(log_filename, "w") diff --git a/benches/bigint/bench_bigint_multiply.mojo b/benches/bigint/bench_bigint_multiply.mojo index 88c393d..e2bba66 100644 --- a/benches/bigint/bench_bigint_multiply.mojo +++ b/benches/bigint/bench_bigint_multiply.mojo @@ -29,7 +29,9 @@ fn open_log_file() raises -> PythonObject: # Generate a timestamp for the filename var timestamp = String(datetime.datetime.now().isoformat()) - var log_filename = log_dir + "/benchmark_bigint_multiply_" + timestamp + ".log" + var log_filename = ( + log_dir + "/benchmark_bigint_multiply_" + timestamp + ".log" + ) print("Saving benchmark results to:", log_filename) return python.open(log_filename, "w") diff --git a/benches/bigint/bench_bigint_truncate_divide.mojo b/benches/bigint/bench_bigint_truncate_divide.mojo index 369559a..4922218 100644 --- a/benches/bigint/bench_bigint_truncate_divide.mojo +++ b/benches/bigint/bench_bigint_truncate_divide.mojo @@ -29,7 +29,9 @@ fn open_log_file() raises -> PythonObject: # Generate a timestamp for the filename var timestamp = String(datetime.datetime.now().isoformat()) - var log_filename = log_dir + "/benchmark_bigint_truncate_divide_" + timestamp + ".log" + var log_filename = ( + log_dir + "/benchmark_bigint_truncate_divide_" + timestamp + ".log" + ) print("Saving benchmark results to:", log_filename) return python.open(log_filename, "w") diff --git a/benches/biguint/bench_biguint_from_string.mojo b/benches/biguint/bench_biguint_from_string.mojo index 514df64..d30f02e 100644 --- a/benches/biguint/bench_biguint_from_string.mojo +++ b/benches/biguint/bench_biguint_from_string.mojo @@ -29,7 +29,9 @@ fn open_log_file() raises -> PythonObject: # Generate a timestamp for the filename var timestamp = String(datetime.datetime.now().isoformat()) - var log_filename = log_dir + "/benchmark_biguint_from_string_" + timestamp + ".log" + var log_filename = ( + log_dir + "/benchmark_biguint_from_string_" + timestamp + ".log" + ) print("Saving benchmark results to:", log_filename) return python.open(log_filename, "w") diff --git a/benches/biguint/bench_biguint_multiply.mojo b/benches/biguint/bench_biguint_multiply.mojo index 6d50884..38baa94 100644 --- a/benches/biguint/bench_biguint_multiply.mojo +++ b/benches/biguint/bench_biguint_multiply.mojo @@ -29,7 +29,9 @@ fn open_log_file() raises -> PythonObject: # Generate a timestamp for the filename var timestamp = String(datetime.datetime.now().isoformat()) - var log_filename = log_dir + "/benchmark_biguint_multiply_" + timestamp + ".log" + var log_filename = ( + log_dir + "/benchmark_biguint_multiply_" + timestamp + ".log" + ) print("Saving benchmark results to:", log_filename) return python.open(log_filename, "w") diff --git a/benches/biguint/bench_biguint_truncate_divide.mojo b/benches/biguint/bench_biguint_truncate_divide.mojo index 3655b08..a0f20b9 100644 --- a/benches/biguint/bench_biguint_truncate_divide.mojo +++ b/benches/biguint/bench_biguint_truncate_divide.mojo @@ -30,7 +30,9 @@ fn open_log_file() raises -> PythonObject: # Generate a timestamp for the filename var timestamp = String(datetime.datetime.now().isoformat()) - var log_filename = log_dir + "/benchmark_biguint_truncate_divide_" + timestamp + ".log" + var log_filename = ( + log_dir + "/benchmark_biguint_truncate_divide_" + timestamp + ".log" + ) print("Saving benchmark results to:", log_filename) return python.open(log_filename, "w") diff --git a/benches/decimal/bench_truncate_divide.mojo b/benches/decimal/bench_truncate_divide.mojo index c80fe9f..e8b2ec2 100644 --- a/benches/decimal/bench_truncate_divide.mojo +++ b/benches/decimal/bench_truncate_divide.mojo @@ -28,7 +28,9 @@ fn open_log_file() raises -> PythonObject: # Generate a timestamp for the filename var timestamp = String(datetime.datetime.now().isoformat()) - var log_filename = log_dir + "/benchmark_truncate_divide_" + timestamp + ".log" + var log_filename = ( + log_dir + "/benchmark_truncate_divide_" + timestamp + ".log" + ) print("Saving benchmark results to:", log_filename) return python.open(log_filename, "w") diff --git a/docs/changelog.md b/docs/changelog.md index a755fe4..a8371de 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -2,9 +2,13 @@ This is a list of RELEASED changes for the DeciMojo Package. For the unreleased changes, please refer to **[changelog_unreleased](https://zhuyuhao.com/decimojo/docs/changelog_unreleased.html)**. +## 25/06/2025 (v0.4.0) + +DeciMojo v0.4.0 updates the codebase to Mojo v25.4. This release enables you to use DeciMojo with the latest Mojo features. + ## 06/06/2025 (v0.3.1) -DeciMojo v0.3.1 updates the codebase to Mojo 25.3 and replaces the `magic` package manager with `pixi`. This release enables you to use DeciMojo with the latest Mojo features and the new package manager. +DeciMojo v0.3.1 updates the codebase to Mojo v25.3 and replaces the `magic` package manager with `pixi`. This release enables you to use DeciMojo with the latest Mojo features and the new package manager. ## 15/04/2025 (v0.3.0) diff --git a/docs/readme_zht.md b/docs/readme_zht.md index d0a3c0e..0051d53 100644 --- a/docs/readme_zht.md +++ b/docs/readme_zht.md @@ -20,7 +20,7 @@ DeciMojo 可在 [modular-community](https://repo.prefix.dev/modular-community) 從 `pixi` CLI,只需運行 ```pixi add decimojo```。這會獲取最新版本並使其立即可用於導入。 -對於帶有 `mojoproject.toml` 文件的項目,添加依賴 ```decimojo = ">=0.3.1"```。然後運行 `pixi install` 來下載並安裝包。 +對於帶有 `mojoproject.toml` 文件的項目,添加依賴 ```decimojo = "==0.4.0"```。然後運行 `pixi install` 來下載並安裝包。 如需最新的開發版本,請克隆 [GitHub 倉庫](https://github.com/forfudan/decimojo) 並在本地構建包。 @@ -30,6 +30,7 @@ DeciMojo 可在 [modular-community](https://repo.prefix.dev/modular-community) | v0.2.0 | >=25.2 | magic | | v0.3.0 | >=25.2 | magic | | v0.3.1 | >=25.2, <25.4 | pixi | +| v0.4.0 | ==25.4 | pixi | ## 快速入門 @@ -217,7 +218,7 @@ DeciMojo 相較於 Python 的 `decimal` 模塊提供了卓越的性能,同時 year = {2025}, title = {DeciMojo: A fixed-point decimal arithmetic library in Mojo}, url = {https://github.com/forfudan/decimojo}, - version = {0.3.1}, + version = {0.4.0}, note = {Computer Software} } ``` diff --git a/pixi.toml b/pixi.toml index ee6656b..e64af3c 100644 --- a/pixi.toml +++ b/pixi.toml @@ -7,10 +7,10 @@ license = "Apache-2.0" name = "decimojo" platforms = ["osx-arm64", "linux-64"] readme = "README.md" -version = "0.3.1" +version = "0.4.0" [dependencies] -max = ">=25.2, <25.4" +max = "==25.4" [tasks] # format the code diff --git a/src/decimojo/bigdecimal/bigdecimal.mojo b/src/decimojo/bigdecimal/bigdecimal.mojo index cf79f40..39c9f24 100644 --- a/src/decimojo/bigdecimal/bigdecimal.mojo +++ b/src/decimojo/bigdecimal/bigdecimal.mojo @@ -34,7 +34,9 @@ alias BDec = BigDecimal @value -struct BigDecimal(Absable, Comparable, IntableRaising, Roundable, Writable): +struct BigDecimal( + Absable, Comparable, IntableRaising, Roundable, Stringable, Writable +): """Represents a arbitrary-precision decimal. Notes: @@ -257,13 +259,13 @@ struct BigDecimal(Absable, Comparable, IntableRaising, Roundable, Writable): start = end - 9 var word: UInt32 = 0 for digit in coef[start:end]: - word = word * 10 + UInt32(digit[]) + word = word * 10 + UInt32(digit) coefficient_words.append(word) end = start if end > 0: var word: UInt32 = 0 for digit in coef[0:end]: - word = word * 10 + UInt32(digit[]) + word = word * 10 + UInt32(digit) coefficient_words.append(word) coefficient = BigUInt(coefficient_words^) @@ -871,7 +873,9 @@ struct BigDecimal(Absable, Comparable, IntableRaising, Roundable, Writable): var number_of_digits_to_remove = self.number_of_trailing_zeros() var number_of_words_to_remove = number_of_digits_to_remove // 9 - var number_of_remaining_digits_to_remove = number_of_digits_to_remove % 9 + var number_of_remaining_digits_to_remove = ( + number_of_digits_to_remove % 9 + ) words = self.coefficient.words[number_of_words_to_remove:] var coefficient = BigUInt(words^) diff --git a/src/decimojo/bigdecimal/exponential.mojo b/src/decimojo/bigdecimal/exponential.mojo index 80434d2..3f1f0ed 100644 --- a/src/decimojo/bigdecimal/exponential.mojo +++ b/src/decimojo/bigdecimal/exponential.mojo @@ -551,15 +551,19 @@ fn sqrt(x: BigDecimal, precision: Int) raises -> BigDecimal: # TODO: This can be done even earlier in the process # TODO: Implement a method that remove trailing zeros if guess.coefficient.ith_digit(0) == 0: - var guess_coefficient_without_trailing_zeros = guess.coefficient.remove_trailing_digits_with_rounding( - guess.coefficient.number_of_trailing_zeros(), - rounding_mode=RoundingMode.ROUND_DOWN, - remove_extra_digit_due_to_rounding=False, + var guess_coefficient_without_trailing_zeros = ( + guess.coefficient.remove_trailing_digits_with_rounding( + guess.coefficient.number_of_trailing_zeros(), + rounding_mode=RoundingMode.ROUND_DOWN, + remove_extra_digit_due_to_rounding=False, + ) ) - var x_coefficient_without_trailing_zeros = x.coefficient.remove_trailing_digits_with_rounding( - x.coefficient.number_of_trailing_zeros(), - rounding_mode=RoundingMode.ROUND_DOWN, - remove_extra_digit_due_to_rounding=False, + var x_coefficient_without_trailing_zeros = ( + x.coefficient.remove_trailing_digits_with_rounding( + x.coefficient.number_of_trailing_zeros(), + rounding_mode=RoundingMode.ROUND_DOWN, + remove_extra_digit_due_to_rounding=False, + ) ) if ( guess_coefficient_without_trailing_zeros @@ -1036,7 +1040,7 @@ fn ln_series_expansion( k += BigUInt.ONE # Alternate sign: -1^(k+1) = -1 when k is even, 1 when k is odd - var sign = (k % BigUInt(2) == BigUInt.ZERO) + var sign = k % BigUInt(2) == BigUInt.ZERO var next_term = term.true_divide_inexact( BigDecimal(k, 0, False), working_precision ) diff --git a/src/decimojo/bigint/bigint.mojo b/src/decimojo/bigint/bigint.mojo index 15b28af..65bbc23 100644 --- a/src/decimojo/bigint/bigint.mojo +++ b/src/decimojo/bigint/bigint.mojo @@ -37,7 +37,7 @@ alias BInt = BigInt @value -struct BigInt(Absable, IntableRaising, Writable): +struct BigInt(Absable, IntableRaising, Representable, Stringable, Writable): """Represents a base-10 arbitrary-precision signed integer. Notes: diff --git a/src/decimojo/biguint/arithmetics.mojo b/src/decimojo/biguint/arithmetics.mojo index e75925e..91c3b45 100644 --- a/src/decimojo/biguint/arithmetics.mojo +++ b/src/decimojo/biguint/arithmetics.mojo @@ -334,9 +334,11 @@ fn multiply(x1: BigUInt, x2: BigUInt) raises -> BigUInt: # Calculate the product of the current words # plus the carry from the previous multiplication # plus the value already at this position in the result - var product = UInt64(x1.words[i]) * UInt64( - x2.words[j] - ) + carry + UInt64(words[i + j]) + var product = ( + UInt64(x1.words[i]) * UInt64(x2.words[j]) + + carry + + UInt64(words[i + j]) + ) # The lower 9 digits (base 10^9) go into the current word # The upper digits become the carry for the next position @@ -881,9 +883,11 @@ fn floor_divide_inplace_by_double_words( x1.words.resize(len(x1.words) - 1, UInt32(0)) for i in range(len(x1.words) - 1, -1, -2): - var dividend = carry * UInt128(1_000_000_000_000_000_000) + UInt128( - x1.words[i] - ) * UInt128(1_000_000_000) + UInt128(x1.words[i - 1]) + var dividend = ( + carry * UInt128(1_000_000_000_000_000_000) + + UInt128(x1.words[i]) * UInt128(1_000_000_000) + + UInt128(x1.words[i - 1]) + ) var quotient = dividend // x2_value x1.words[i] = UInt32(quotient // UInt128(1_000_000_000)) x1.words[i - 1] = UInt32(quotient % UInt128(1_000_000_000)) diff --git a/src/decimojo/biguint/biguint.mojo b/src/decimojo/biguint/biguint.mojo index 747365f..8a22a39 100644 --- a/src/decimojo/biguint/biguint.mojo +++ b/src/decimojo/biguint/biguint.mojo @@ -36,7 +36,7 @@ alias BUInt = BigUInt @value -struct BigUInt(Absable, IntableRaising, Writable): +struct BigUInt(Absable, IntableRaising, Stringable, Writable): """Represents a base-10 arbitrary-precision unsigned integer. Notes: @@ -178,7 +178,7 @@ struct BigUInt(Absable, IntableRaising, Writable): # Check if the words are valid for word in words: - if word[] > UInt32(999_999_999): + if word > UInt32(999_999_999): raise Error( "Error in `BigUInt.from_list()`: Word value exceeds maximum" " value of 999_999_999" @@ -345,13 +345,13 @@ struct BigUInt(Absable, IntableRaising, Writable): start = end - 9 var word: UInt32 = 0 for digit in coef[start:end]: - word = word * 10 + UInt32(digit[]) + word = word * 10 + UInt32(digit) result_words.append(word) end = start if end > 0: var word: UInt32 = 0 for digit in coef[0:end]: - word = word * 10 + UInt32(digit[]) + word = word * 10 + UInt32(digit) result_words.append(word) return Self(result_words^) @@ -367,19 +367,21 @@ struct BigUInt(Absable, IntableRaising, Writable): for _ in range(remaining_trailing_zero_digits): coef.append(UInt8(0)) - var end: Int = number_of_digits + scale + remaining_trailing_zero_digits + var end: Int = ( + number_of_digits + scale + remaining_trailing_zero_digits + ) var start: Int while end >= 9: start = end - 9 var word: UInt32 = 0 for digit in coef[start:end]: - word = word * 10 + UInt32(digit[]) + word = word * 10 + UInt32(digit) result_words.append(word) end = start if end > 0: var word: UInt32 = 0 for digit in coef[0:end]: - word = word * 10 + UInt32(digit[]) + word = word * 10 + UInt32(digit) result_words.append(word) return Self(result_words^) diff --git a/src/decimojo/decimal/arithmetics.mojo b/src/decimojo/decimal/arithmetics.mojo index c9f44e9..64456e3 100644 --- a/src/decimojo/decimal/arithmetics.mojo +++ b/src/decimojo/decimal/arithmetics.mojo @@ -221,8 +221,10 @@ fn add(x1: Decimal, x2: Decimal) raises -> Decimal: var ndigits_int_summation = ndigits_summation - x1_scale var final_scale = Decimal.MAX_NUM_DIGITS - ndigits_int_summation - var truncated_summation = decimojo.utility.round_to_keep_first_n_digits( - summation, Decimal.MAX_NUM_DIGITS + var truncated_summation = ( + decimojo.utility.round_to_keep_first_n_digits( + summation, Decimal.MAX_NUM_DIGITS + ) ) if truncated_summation > Decimal.MAX_AS_UINT128: truncated_summation = ( @@ -610,15 +612,17 @@ fn multiply(x1: Decimal, x2: Decimal) raises -> Decimal: if combined_num_bits <= 128: var prod: UInt128 = x1_coef * x2_coef # Truncated first 29 digits - var truncated_prod_at_max_length = decimojo.utility.round_to_keep_first_n_digits( - prod, Decimal.MAX_NUM_DIGITS + var truncated_prod_at_max_length = ( + decimojo.utility.round_to_keep_first_n_digits( + prod, Decimal.MAX_NUM_DIGITS + ) ) # Check outflow # The number of digits of the integral part - var num_digits_of_integral_part = decimojo.utility.number_of_digits( - prod - ) - combined_scale + var num_digits_of_integral_part = ( + decimojo.utility.number_of_digits(prod) - combined_scale + ) if (num_digits_of_integral_part >= Decimal.MAX_NUM_DIGITS) & ( truncated_prod_at_max_length > Decimal.MAX_AS_UINT128 ): @@ -629,7 +633,9 @@ fn multiply(x1: Decimal, x2: Decimal) raises -> Decimal: # If the first 29 digits does not exceed the limit, # the final coefficient can be of 29 digits. # The final scale can be 29 - num_digits_of_integral_part. - var num_digits_of_decimal_part = Decimal.MAX_NUM_DIGITS - num_digits_of_integral_part + var num_digits_of_decimal_part = ( + Decimal.MAX_NUM_DIGITS - num_digits_of_integral_part + ) # If the first 29 digits exceed the limit, # we need to adjust the num_digits_of_decimal_part by -1 # so that the final coefficient will be of 28 digits. @@ -663,15 +669,17 @@ fn multiply(x1: Decimal, x2: Decimal) raises -> Decimal: var prod: UInt256 = UInt256(x1_coef) * UInt256(x2_coef) # Truncated first 29 digits - var truncated_prod_at_max_length = decimojo.utility.round_to_keep_first_n_digits( - prod, Decimal.MAX_NUM_DIGITS + var truncated_prod_at_max_length = ( + decimojo.utility.round_to_keep_first_n_digits( + prod, Decimal.MAX_NUM_DIGITS + ) ) # Check outflow # The number of digits of the integral part - var num_digits_of_integral_part = decimojo.utility.number_of_digits( - prod - ) - combined_scale + var num_digits_of_integral_part = ( + decimojo.utility.number_of_digits(prod) - combined_scale + ) # Check for overflow of the integral part after rounding if (num_digits_of_integral_part >= Decimal.MAX_NUM_DIGITS) & ( @@ -684,7 +692,9 @@ fn multiply(x1: Decimal, x2: Decimal) raises -> Decimal: # If the first 29 digits does not exceed the limit, # the final coefficient can be of 29 digits. # The final scale can be 29 - num_digits_of_integral_part. - var num_digits_of_decimal_part = Decimal.MAX_NUM_DIGITS - num_digits_of_integral_part + var num_digits_of_decimal_part = ( + Decimal.MAX_NUM_DIGITS - num_digits_of_integral_part + ) # If the first 29 digits exceed the limit, # we need to adjust the num_digits_of_decimal_part by -1 # so that the final coefficient will be of 28 digits. @@ -979,11 +989,11 @@ fn divide(x1: Decimal, x2: Decimal) raises -> Decimal: var ndigits_quot = decimojo.utility.number_of_digits(quot) var ndigits_quot_int_part = ndigits_quot - scale_of_quot - print( - String( - "quot: {}, rem: {}, step_counter: {}, scale_of_quot: {}" - ).format(quot, rem, step_counter, scale_of_quot) - ) + # print( + # String( + # "quot: {}, rem: {}, step_counter: {}, scale_of_quot: {}" + # ).format(quot, rem, step_counter, scale_of_quot) + # ) # TODO: 可以考慮先降 scale 再判斷是否超出最大值. # TODO: 爲降 scale 引入 round_to_remove_last_n_digits 函數 @@ -1014,8 +1024,8 @@ fn divide(x1: Decimal, x2: Decimal) raises -> Decimal: scale_of_truncated_quot -= 1 if scale_of_truncated_quot > Decimal.MAX_SCALE: - var num_digits_truncated_quot = decimojo.utility.number_of_digits( - truncated_quot + var num_digits_truncated_quot = ( + decimojo.utility.number_of_digits(truncated_quot) ) truncated_quot = decimojo.utility.round_to_keep_first_n_digits( truncated_quot, @@ -1120,8 +1130,8 @@ fn divide(x1: Decimal, x2: Decimal) raises -> Decimal: scale_of_truncated_quot -= 1 if scale_of_truncated_quot > Decimal.MAX_SCALE: - var num_digits_truncated_quot = decimojo.utility.number_of_digits( - truncated_quot + var num_digits_truncated_quot = ( + decimojo.utility.number_of_digits(truncated_quot) ) truncated_quot = decimojo.utility.round_to_keep_first_n_digits( truncated_quot, diff --git a/src/decimojo/decimal/decimal.mojo b/src/decimojo/decimal/decimal.mojo index 7178e42..fcb93b2 100644 --- a/src/decimojo/decimal/decimal.mojo +++ b/src/decimojo/decimal/decimal.mojo @@ -43,7 +43,9 @@ struct Decimal( Comparable, Floatable, IntableRaising, + Representable, Roundable, + Stringable, Writable, ): """Represents a 128-bit fixed-point decimal number. @@ -553,13 +555,13 @@ struct Decimal( for code in value_bytes: # If the char is " ", skip it - if code[] == 32: + if code == 32: pass # If the char is "," or "_", skip it - elif code[] == 44 or code[] == 95: + elif code == 44 or code == 95: unexpected_end_char = True # If the char is "-" - elif code[] == 45: + elif code == 45: unexpected_end_char = True if exponent_sign_read: raise Error("Minus sign cannot appear twice in exponent.") @@ -574,7 +576,7 @@ struct Decimal( mantissa_sign = True mantissa_sign_read = True # If the char is "+" - elif code[] == 43: + elif code == 43: unexpected_end_char = True if exponent_sign_read: raise Error("Plus sign cannot appear twice in exponent.") @@ -587,7 +589,7 @@ struct Decimal( else: mantissa_sign_read = True # If the char is "." - elif code[] == 46: + elif code == 46: unexpected_end_char = False if decimal_point_read: raise Error("Decimal point can only appear once.") @@ -595,7 +597,7 @@ struct Decimal( decimal_point_read = True mantissa_sign_read = True # If the char is "e" or "E" - elif code[] == 101 or code[] == 69: + elif code == 101 or code == 69: unexpected_end_char = True if exponent_notation_read: raise Error("Exponential notation can only appear once.") @@ -604,7 +606,7 @@ struct Decimal( else: exponent_notation_read = True # If the char is a digit 0 - elif code[] == 48: + elif code == 48: unexpected_end_char = False # Exponent part @@ -630,7 +632,7 @@ struct Decimal( scale += 1 # If the char is a digit 1 - 9 - elif code[] >= 49 and code[] <= 57: + elif code >= 49 and code <= 57: unexpected_end_char = False # Exponent part @@ -653,7 +655,7 @@ struct Decimal( else: # exponent_start = True - raw_exponent = raw_exponent * 10 + UInt32(code[] - 48) + raw_exponent = raw_exponent * 10 + UInt32(code - 48) # Mantissa part else: @@ -665,7 +667,7 @@ struct Decimal( mantissa_start = True num_mantissa_digits += 1 - coef = coef * 10 + UInt128(code[] - 48) + coef = coef * 10 + UInt128(code - 48) if decimal_point_read: scale += 1 @@ -673,7 +675,7 @@ struct Decimal( else: raise Error( String("Invalid character in decimal string: {}").format( - chr(Int(code[])) + chr(Int(code)) ) ) @@ -736,8 +738,8 @@ struct Decimal( scale_of_truncated_coef -= 1 if scale_of_truncated_coef > Decimal.MAX_SCALE: - var num_digits_truncated_coef = decimojo.utility.number_of_digits( - truncated_coef + var num_digits_truncated_coef = ( + decimojo.utility.number_of_digits(truncated_coef) ) truncated_coef = decimojo.utility.round_to_keep_first_n_digits( truncated_coef, @@ -1544,9 +1546,11 @@ struct Decimal( new_scale = Decimal.MAX_SCALE + 1 # With UInt128, we can represent the coefficient as a single value - var coefficient = UInt128(self.high) << 64 | UInt128( - self.mid - ) << 32 | UInt128(self.low) + var coefficient = ( + UInt128(self.high) << 64 + | UInt128(self.mid) << 32 + | UInt128(self.low) + ) # TODO: Check if multiplication by 10^level would cause overflow # If yes, then raise an error diff --git a/src/decimojo/decimal/exponential.mojo b/src/decimojo/decimal/exponential.mojo index 967b7d6..1bf7086 100644 --- a/src/decimojo/decimal/exponential.mojo +++ b/src/decimojo/decimal/exponential.mojo @@ -204,23 +204,23 @@ fn root(x: Decimal, n: Int) raises -> Decimal: # For numbers with zero scale (true integers) if x_scale == 0: if n <= 8: # 3<=n<=8 - var float_root = pow(Float64(x_coef), 1 / Float64(n)) * Float64( - 10 - ) ** 8 + var float_root = ( + pow(Float64(x_coef), 1 / Float64(n)) * Float64(10) ** 8 + ) guess = Decimal.from_uint128( UInt128(round(float_root)), scale=8, sign=False ) elif n <= 16: - var float_root = pow(Float64(x_coef), 1 / Float64(n)) * Float64( - 10 - ) ** 16 + var float_root = ( + pow(Float64(x_coef), 1 / Float64(n)) * Float64(10) ** 16 + ) guess = Decimal.from_uint128( UInt128(round(float_root)), scale=16, sign=False ) else: - var float_root = pow(Float64(x_coef), 1 / Float64(n)) * Float64( - 10 - ) ** 26 + var float_root = ( + pow(Float64(x_coef), 1 / Float64(n)) * Float64(10) ** 26 + ) guess = Decimal.from_uint128( UInt128(round(float_root)), scale=26, sign=False ) @@ -237,10 +237,9 @@ fn root(x: Decimal, n: Int) raises -> Decimal: else: var dividend = x_scale // n var remainder = x_scale % n - var float_root = ( - Float64(x_coef) ** (Float64(1) / Float64(n)) - / Float64(10) ** (Float64(remainder) / Float64(n) - 1) - ) + var float_root = Float64(x_coef) ** (Float64(1) / Float64(n)) / Float64( + 10 + ) ** (Float64(remainder) / Float64(n) - 1) guess = Decimal.from_uint128( UInt128(float_root), scale=dividend + 1, sign=False ) @@ -278,7 +277,9 @@ fn root(x: Decimal, n: Int) raises -> Decimal: var num_digits_guess_coef = decimojo.utility.number_of_digits( guess_coef ) - var num_digits_to_decrease = num_digits_guess_coef - num_digits_x_root_coef + var num_digits_to_decrease = ( + num_digits_guess_coef - num_digits_x_root_coef + ) # testing.assert_true( # num_digits_to_decrease >= 0, @@ -403,7 +404,9 @@ fn sqrt(x: Decimal) raises -> Decimal: var num_digits_guess_coef = decimojo.utility.number_of_digits( guess_coef ) - var num_digits_to_decrease = num_digits_guess_coef - num_digits_x_sqrt_coef + var num_digits_to_decrease = ( + num_digits_guess_coef - num_digits_x_sqrt_coef + ) # testing.assert_true( # num_digits_to_decrease >= 0, diff --git a/src/decimojo/decimal/rounding.mojo b/src/decimojo/decimal/rounding.mojo index b904e4d..e5dbe22 100644 --- a/src/decimojo/decimal/rounding.mojo +++ b/src/decimojo/decimal/rounding.mojo @@ -159,10 +159,6 @@ fn round( else: return Decimal.ZERO() - # Add a fallback raise even if it seems unreachable - testing.assert_true(False, "Unreachable code path reached") - return number - fn quantize( value: Decimal, diff --git a/src/decimojo/prelude.mojo b/src/decimojo/prelude.mojo index fda9518..910dd26 100644 --- a/src/decimojo/prelude.mojo +++ b/src/decimojo/prelude.mojo @@ -16,7 +16,7 @@ """ Provides a list of things that can be imported at one time. -The list contains the functions or types that are the most essential for a user. +The list contains the functions or types that are the most essential for a user. You can use the following code to import them: @@ -26,8 +26,8 @@ from decimojo.prelude import * """ import decimojo as dm -from decimojo.decimal.decimal import Decimal -from decimojo.bigdecimal.bigdecimal import BigDecimal -from decimojo.biguint.biguint import BigUInt -from decimojo.bigint.bigint import BigInt -from decimojo.rounding_mode import RoundingMode +from decimojo.decimal.decimal import Decimal, Dec +from decimojo.bigdecimal.bigdecimal import BigDecimal, BDec +from decimojo.biguint.biguint import BigUInt, BUInt +from decimojo.bigint.bigint import BigInt, BInt +from decimojo.rounding_mode import RoundingMode, RM diff --git a/src/decimojo/rounding_mode.mojo b/src/decimojo/rounding_mode.mojo index b972bd8..d9ff0e0 100644 --- a/src/decimojo/rounding_mode.mojo +++ b/src/decimojo/rounding_mode.mojo @@ -20,7 +20,7 @@ alias RM = RoundingMode -struct RoundingMode: +struct RoundingMode(Stringable): """ Represents different rounding modes for decimal operations. diff --git a/src/decimojo/str.mojo b/src/decimojo/str.mojo index 8064f26..ca5a68f 100644 --- a/src/decimojo/str.mojo +++ b/src/decimojo/str.mojo @@ -92,7 +92,7 @@ fn parse_numeric_string( var raw_exponent: Int = 0 for code_ptr in value_bytes: - var code = code_ptr[] + ref code = code_ptr # If the char is " ", skip it if code == 32: pass diff --git a/src/decimojo/tests.mojo b/src/decimojo/tests.mojo index 19ffd43..c7f9aed 100644 --- a/src/decimojo/tests.mojo +++ b/src/decimojo/tests.mojo @@ -19,7 +19,7 @@ Implement structs and functions for tests. """ -struct TestCase: +struct TestCase(Copyable, Movable): """Structure to hold test case data. Attributes: diff --git a/src/tomlmojo/parser.mojo b/src/tomlmojo/parser.mojo index b4edf61..8acded0 100644 --- a/src/tomlmojo/parser.mojo +++ b/src/tomlmojo/parser.mojo @@ -238,8 +238,8 @@ struct TOMLDocument: var value = self.root[key] if value.type == TOMLValueType.ARRAY: for table_value in value.array_values: - if table_value[].type == TOMLValueType.TABLE: - result.append(table_value[].table_values) + if table_value.type == TOMLValueType.TABLE: + result.append(table_value.table_values) return result diff --git a/tests/bigdecimal/test_bigdecimal_arithmetics.mojo b/tests/bigdecimal/test_bigdecimal_arithmetics.mojo index 7768390..6061a56 100644 --- a/tests/bigdecimal/test_bigdecimal_arithmetics.mojo +++ b/tests/bigdecimal/test_bigdecimal_arithmetics.mojo @@ -106,7 +106,7 @@ fn test_subtract() raises: # Check what root keys are available print("Available root keys:") for key in toml.root.keys(): - print(" - " + key[]) + print(" - " + key) # Try to access the specific section try: diff --git a/tests/decimal/test_sqrt.mojo b/tests/decimal/test_sqrt.mojo index f793ce8..8b1a3b3 100644 --- a/tests/decimal/test_sqrt.mojo +++ b/tests/decimal/test_sqrt.mojo @@ -491,7 +491,9 @@ fn test_edge_cases() raises: fn test_precision() raises: print("Testing precision of square root calculations...") - var expected_sqrt2 = "1.414213562373095048801688724" # First 10 decimal places of sqrt(2) + var expected_sqrt2 = ( + "1.414213562373095048801688724" # First 10 decimal places of sqrt(2) + ) # Test precision for irrational numbers var two = Decimal(2) @@ -749,125 +751,162 @@ fn test_sqrt_performance() raises: raise e # Test case 2 - var num2 = Decimal("0.01") - var result2 = sqrt(num2) - var squared2 = result2 * result2 - var diff2 = squared2 - num2 - diff2 = -diff2 if diff2.is_negative() else diff2 - var rel_diff2 = diff2 / num2 - var diff_float2 = Float64(String(rel_diff2)) - testing.assert_true( - diff_float2 < 0.00001, - "Square root calculation for " - + String(num2) - + " should be accurate within 0.001%", - ) + try: + var num2 = Decimal("0.01") + var result2 = sqrt(num2) + var squared2 = result2 * result2 + var diff2 = squared2 - num2 + diff2 = -diff2 if diff2.is_negative() else diff2 + var rel_diff2 = diff2 / num2 + var diff_float2 = Float64(String(rel_diff2)) + testing.assert_true( + diff_float2 < 0.00001, + "Square root calculation for " + + String(num2) + + " should be accurate within 0.001%", + ) + except e: + print("ERROR in test_sqrt_performance case 2: small number 0.01") + raise e # Test case 3 - var num3 = Decimal(1) - var result3 = sqrt(num3) - var squared3 = result3 * result3 - var diff3 = squared3 - num3 - diff3 = -diff3 if diff3.is_negative() else diff3 - var rel_diff3 = diff3 / num3 - var diff_float3 = Float64(String(rel_diff3)) - testing.assert_true( - diff_float3 < 0.00001, - "Square root calculation for " - + String(num3) - + " should be accurate within 0.001%", - ) + try: + var num3 = Decimal(1) + var result3 = sqrt(num3) + var squared3 = result3 * result3 + var diff3 = squared3 - num3 + diff3 = -diff3 if diff3.is_negative() else diff3 + var rel_diff3 = diff3 / num3 + var diff_float3 = Float64(String(rel_diff3)) + testing.assert_true( + diff_float3 < 0.00001, + "Square root calculation for " + + String(num3) + + " should be accurate within 0.001%", + ) + except e: + print("ERROR in test_sqrt_performance case 3: small number 1") + raise e # Test case 4 - var num4 = Decimal(10) - var result4 = sqrt(num4) - var squared4 = result4 * result4 - var diff4 = squared4 - num4 - diff4 = -diff4 if diff4.is_negative() else diff4 - var rel_diff4 = diff4 / num4 - var diff_float4 = Float64(String(rel_diff4)) - testing.assert_true( - diff_float4 < 0.00001, - "Square root calculation for " - + String(num4) - + " should be accurate within 0.001%", - ) + try: + var num4 = Decimal(10) + var result4 = sqrt(num4) + var squared4 = result4 * result4 + var diff4 = squared4 - num4 + diff4 = -diff4 if diff4.is_negative() else diff4 + var rel_diff4 = diff4 / num4 + testing.assert_true( + rel_diff4 < Decimal(0.00001), + "Square root calculation for " + + String(num4) + + " should be accurate within 0.001%", + ) + except e: + print("ERROR in test_sqrt_performance case 4: small number 10") + raise e # Test case 5 - var num5 = Decimal(10000) - var result5 = sqrt(num5) - var squared5 = result5 * result5 - var diff5 = squared5 - num5 - diff5 = -diff5 if diff5.is_negative() else diff5 - var rel_diff5 = diff5 / num5 - var diff_float5 = Float64(String(rel_diff5)) - testing.assert_true( - diff_float5 < 0.00001, - "Square root calculation for " - + String(num5) - + " should be accurate within 0.001%", - ) + try: + var num5 = Decimal(10000) + var result5 = sqrt(num5) + var squared5 = result5 * result5 + var diff5 = squared5 - num5 + diff5 = -diff5 if diff5.is_negative() else diff5 + var rel_diff5 = diff5 / num5 + var diff_float5 = Float64(String(rel_diff5)) + testing.assert_true( + diff_float5 < 0.00001, + "Square root calculation for " + + String(num5) + + " should be accurate within 0.001%", + ) + except e: + print("ERROR in test_sqrt_performance case 5: small number 10000") + raise e # Test case 6 - var num6 = Decimal("10000000000") - var result6 = sqrt(num6) - var squared6 = result6 * result6 - var diff6 = squared6 - num6 - diff6 = -diff6 if diff6.is_negative() else diff6 - var rel_diff6 = diff6 / num6 - var diff_float6 = Float64(String(rel_diff6)) - testing.assert_true( - diff_float6 < 0.00001, - "Square root calculation for " - + String(num6) - + " should be accurate within 0.001%", - ) + try: + var num6 = Decimal("10000000000") + var result6 = sqrt(num6) + var squared6 = result6 * result6 + var diff6 = squared6 - num6 + diff6 = -diff6 if diff6.is_negative() else diff6 + var rel_diff6 = diff6 / num6 + var diff_float6 = Float64(String(rel_diff6)) + testing.assert_true( + diff_float6 < 0.00001, + "Square root calculation for " + + String(num6) + + " should be accurate within 0.001%", + ) + except e: + print("ERROR in test_sqrt_performance case 6: small number 10000000000") + raise e # Test case 7 - var num7 = Decimal("0.999999999") - var result7 = String(sqrt(num7)) - var expected_result7 = String("0.99999999949999999987") - testing.assert_true( - result7.startswith(expected_result7), "sqrt(0.999999999)" - ) + try: + var num7 = Decimal("0.999999999") + var result7 = String(sqrt(num7)) + var expected_result7 = String("0.99999999949999999987") + testing.assert_true( + result7.startswith(expected_result7), "sqrt(0.999999999)" + ) + except e: + print("ERROR in test_sqrt_performance case 7: sqrt(0.9999999999)") + raise e # Test case 8 - var num8 = Decimal("1.000000001") - var result8 = String(sqrt(num8)) - var expected_result8 = String("1.000000000499999999875") - testing.assert_true( - result8.startswith(expected_result8), "sqrt(1.000000001)" - ) + try: + var num8 = Decimal("1.000000001") + var result8 = String(sqrt(num8)) + var expected_result8 = String("1.000000000499999999875") + testing.assert_true( + result8.startswith(expected_result8), "sqrt(1.000000001)" + ) + except e: + print("ERROR in test_sqrt_performance case 8: sqrt(1.000000001)") + raise e # Test case 9 - var num9 = Decimal("3.999999999") - var result9 = sqrt(num9) - var squared9 = result9 * result9 - var diff9 = squared9 - num9 - diff9 = -diff9 if diff9.is_negative() else diff9 - var rel_diff9 = diff9 / num9 - var diff_float9 = Float64(String(rel_diff9)) - testing.assert_true( - diff_float9 < 0.00001, - "Square root calculation for " - + String(num9) - + " should be accurate within 0.001%", - ) + try: + var num9 = Decimal("3.999999999") + var result9 = sqrt(num9) + var squared9 = result9 * result9 + var diff9 = squared9 - num9 + diff9 = -diff9 if diff9.is_negative() else diff9 + var rel_diff9 = diff9 / num9 + var diff_float9 = Float64(String(rel_diff9)) + testing.assert_true( + diff_float9 < 0.00001, + "Square root calculation for " + + String(num9) + + " should be accurate within 0.001%", + ) + except e: + print("ERROR in test_sqrt_performance case 9: small number 3.999999999") + raise e # Test case 10 - var num10 = Decimal("4.000000001") - var result10 = sqrt(num10) - var squared10 = result10 * result10 - # Using manual absolute difference calculation - var diff10 = squared10 - num10 - diff10 = -diff10 if diff10.is_negative() else diff10 - var rel_diff10 = diff10 / num10 - testing.assert_true( - rel_diff10 < Decimal("0.00001"), - "Square root calculation for " - + String(num10) - + " should be accurate within 0.001%", - ) + try: + var num10 = Decimal("4.000000001") + var result10 = sqrt(num10) + var squared10 = result10 * result10 + # Using manual absolute difference calculation + var diff10 = squared10 - num10 + diff10 = -diff10 if diff10.is_negative() else diff10 + var rel_diff10 = diff10 / num10 + testing.assert_true( + rel_diff10 < Decimal("0.00001"), + "Square root calculation for " + + String(num10) + + " should be accurate within 0.001%", + ) + except e: + print( + "ERROR in test_sqrt_performance case 10: small number 4.000000001" + ) + raise e print("Performance and convergence tests passed!")