From 89b3be844a07e36d69093d68f18b3a74ad416af1 Mon Sep 17 00:00:00 2001 From: ZHU Yuhao Date: Thu, 9 Apr 2026 20:37:45 +0200 Subject: [PATCH 1/3] Try to remove redundant error wrapper --- src/decimo/bigint/arithmetics.mojo | 8 +++----- src/decimo/bigint10/arithmetics.mojo | 10 ++++------ src/decimo/errors.mojo | 2 +- 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/decimo/bigint/arithmetics.mojo b/src/decimo/bigint/arithmetics.mojo index 06515c70..774693fe 100644 --- a/src/decimo/bigint/arithmetics.mojo +++ b/src/decimo/bigint/arithmetics.mojo @@ -715,11 +715,9 @@ def _divmod_magnitudes( divisor_is_zero = False break if divisor_is_zero: - raise Error( - ZeroDivisionError( - function="_divmod_magnitudes()", - message="Division by zero", - ) + raise ZeroDivisionError( + function="_divmod_magnitudes()", + message="Division by zero.", ) # Compare magnitudes to handle trivial cases diff --git a/src/decimo/bigint10/arithmetics.mojo b/src/decimo/bigint10/arithmetics.mojo index 0446a292..481c58eb 100644 --- a/src/decimo/bigint10/arithmetics.mojo +++ b/src/decimo/bigint10/arithmetics.mojo @@ -355,11 +355,9 @@ def truncate_modulo(x1: BigInt10, x2: BigInt10) raises -> BigInt10: x1.magnitude, x2.magnitude ) except e: - raise Error( - DecimoError( - message="See the above exception.", - function="truncate_modulo()", - previous_error=e^, - ), + raise DecimoError( + message="See the above exception.", + function="truncate_modulo()", + previous_error=e^, ) return BigInt10(magnitude^, sign=x1.sign) diff --git a/src/decimo/errors.mojo b/src/decimo/errors.mojo index 57fabb6e..8fed6a83 100644 --- a/src/decimo/errors.mojo +++ b/src/decimo/errors.mojo @@ -76,7 +76,7 @@ comptime ConversionError = DecimoError[error_type="ConversionError"] """Type for conversion errors in Decimo.""" -struct DecimoError[error_type: String = "DecimoError"](Writable): +struct DecimoError[error_type: StringLiteral = "DecimoError"](Writable): """Base type for all Decimo errors. The error message format mimics Python's traceback: From b40254708346554dcbc5d08df66767932d935f56 Mon Sep 17 00:00:00 2001 From: ZHU Yuhao Date: Thu, 9 Apr 2026 21:17:02 +0200 Subject: [PATCH 2/3] Add runtimeerror and replace decimoerror with specific error types --- src/decimo/bigdecimal/arithmetics.mojo | 32 +- src/decimo/bigdecimal/bigdecimal.mojo | 30 +- src/decimo/bigdecimal/constants.mojo | 6 +- src/decimo/bigdecimal/exponential.mojo | 179 ++++-------- src/decimo/bigdecimal/trigonometric.mojo | 8 +- src/decimo/bigfloat/bigfloat.mojo | 182 +++++------- src/decimo/bigint/arithmetics.mojo | 46 ++- src/decimo/bigint/bigint.mojo | 104 +++---- src/decimo/bigint/exponential.mojo | 10 +- src/decimo/bigint/number_theory.mojo | 34 +-- src/decimo/bigint10/arithmetics.mojo | 54 ++-- src/decimo/bigint10/bigint10.mojo | 105 +++---- src/decimo/biguint/arithmetics.mojo | 181 +++++------- src/decimo/biguint/biguint.mojo | 358 ++++++++++------------- src/decimo/decimal128/arithmetics.mojo | 127 ++++---- src/decimo/decimal128/constants.mojo | 8 +- src/decimo/decimal128/decimal128.mojo | 265 +++++++---------- src/decimo/decimal128/exponential.mojo | 152 ++++------ src/decimo/decimal128/rounding.mojo | 36 +-- src/decimo/decimal128/special.mojo | 30 +- src/decimo/errors.mojo | 4 + src/decimo/str.mojo | 124 +++----- src/decimo/tests.mojo | 12 +- src/decimo/toml/parser.mojo | 113 +++---- 24 files changed, 869 insertions(+), 1331 deletions(-) diff --git a/src/decimo/bigdecimal/arithmetics.mojo b/src/decimo/bigdecimal/arithmetics.mojo index e3463fb2..055e3100 100644 --- a/src/decimo/bigdecimal/arithmetics.mojo +++ b/src/decimo/bigdecimal/arithmetics.mojo @@ -320,11 +320,9 @@ def true_divide( """ # Check for division by zero if y.coefficient.is_zero(): - raise Error( - ZeroDivisionError( - message="Division by zero.", - function="true_divide()", - ) + raise ZeroDivisionError( + message="Division by zero.", + function="true_divide()", ) # Handle dividend of zero @@ -698,11 +696,9 @@ def true_divide_inexact( # Check for division by zero if x2.coefficient.is_zero(): - raise Error( - ZeroDivisionError( - message="Division by zero.", - function="true_divide_inexact()", - ) + raise ZeroDivisionError( + message="Division by zero.", + function="true_divide_inexact()", ) # Handle dividend of zero @@ -916,11 +912,9 @@ def truncate_divide(x1: BigDecimal, x2: BigDecimal) raises -> BigDecimal: """ # Check for division by zero if x2.coefficient.is_zero(): - raise Error( - ZeroDivisionError( - message="Division by zero.", - function="truncate_divide()", - ) + raise ZeroDivisionError( + message="Division by zero.", + function="truncate_divide()", ) # Handle dividend of zero @@ -961,11 +955,9 @@ def truncate_modulo( """ # Check for division by zero if x2.coefficient.is_zero(): - raise Error( - ZeroDivisionError( - message="Division by zero.", - function="truncate_modulo()", - ) + raise ZeroDivisionError( + message="Division by zero.", + function="truncate_modulo()", ) return subtract( diff --git a/src/decimo/bigdecimal/bigdecimal.mojo b/src/decimo/bigdecimal/bigdecimal.mojo index 2da23b7a..250773f5 100644 --- a/src/decimo/bigdecimal/bigdecimal.mojo +++ b/src/decimo/bigdecimal/bigdecimal.mojo @@ -27,7 +27,7 @@ from std.memory import UnsafePointer from std.python import PythonObject from std import testing -from decimo.errors import DecimoError, ConversionError, ValueError +from decimo.errors import ConversionError, ValueError from decimo.rounding_mode import RoundingMode from decimo.bigdecimal.rounding import round_to_precision from decimo.bigint10.bigint10 import BigInt10 @@ -362,22 +362,18 @@ struct BigDecimal( return Self(coefficient=BigUInt.zero(), scale=0, sign=False) if value != value: # Check for NaN - raise Error( - ValueError( - message="Cannot convert NaN to BigDecimal.", - function="BigDecimal.from_scalar()", - ) + raise ValueError( + message="Cannot convert NaN to BigDecimal.", + function="BigDecimal.from_scalar()", ) # Convert to string with full precision try: return Self.from_string(String(value)) except e: - raise Error( - ConversionError( - message="Cannot convert scalar to BigDecimal.", - function="BigDecimal.from_scalar()", - previous_error=e^, - ) + raise ConversionError( + message="Cannot convert scalar to BigDecimal.", + function="BigDecimal.from_scalar()", + previous_error=e^, ) @staticmethod @@ -544,12 +540,10 @@ struct BigDecimal( return Self(coefficient=coefficient^, scale=scale, sign=sign) except e: - raise Error( - ConversionError( - message="Failed to convert Python Decimal to BigDecimal.", - function="BigDecimal.from_python_decimal()", - previous_error=e^, - ), + raise ConversionError( + message="Failed to convert Python Decimal to BigDecimal.", + function="BigDecimal.from_python_decimal()", + previous_error=e^, ) # ===------------------------------------------------------------------=== # diff --git a/src/decimo/bigdecimal/constants.mojo b/src/decimo/bigdecimal/constants.mojo index f2b5536b..ac67c48a 100644 --- a/src/decimo/bigdecimal/constants.mojo +++ b/src/decimo/bigdecimal/constants.mojo @@ -165,10 +165,8 @@ def pi(precision: Int) raises -> BigDecimal: """ if precision < 0: - raise Error( - ValueError( - message="Precision must be non-negative", function="pi()" - ) + raise ValueError( + message="Precision must be non-negative", function="pi()" ) # TODO: When global variables are supported, diff --git a/src/decimo/bigdecimal/exponential.mojo b/src/decimo/bigdecimal/exponential.mojo index b63de430..44777d5e 100644 --- a/src/decimo/bigdecimal/exponential.mojo +++ b/src/decimo/bigdecimal/exponential.mojo @@ -236,20 +236,14 @@ def power( # Special cases if base.coefficient.is_zero(): if exponent.coefficient.is_zero(): - raise Error( - ValueError( - message="0^0 is undefined.", - function="power()", - ) + raise ValueError( + message="0^0 is undefined.", + function="power()", ) elif exponent.sign: - raise Error( - ZeroDivisionError( - message=( - "Division by zero (negative exponent with zero base)." - ), - function="power()", - ) + raise ZeroDivisionError( + message="Division by zero (negative exponent with zero base).", + function="power()", ) else: return BigDecimal(BigUInt.zero(), 0, False) @@ -273,14 +267,12 @@ def power( # Check for negative base with non-integer exponent if base.sign and not exponent.is_integer(): - raise Error( - ValueError( - message=( - "Negative base with non-integer exponent would produce" - " a complex result." - ), - function="power()", - ) + raise ValueError( + message=( + "Negative base with non-integer exponent would produce" + " a complex result." + ), + function="power()", ) # Optimization for integer exponents @@ -449,11 +441,9 @@ def root(x: BigDecimal, n: BigDecimal, precision: Int) raises -> BigDecimal: # Check for n = 0 if n.coefficient.is_zero(): - raise Error( - ValueError( - message="Cannot compute zeroth root.", - function="root()", - ) + raise ValueError( + message="Cannot compute zeroth root.", + function="root()", ) # Special case for integer roots - use more efficient implementation @@ -512,14 +502,11 @@ def root(x: BigDecimal, n: BigDecimal, precision: Int) raises -> BigDecimal: var n_is_integer = n.is_integer() var n_is_odd_reciprocal = is_odd_reciprocal(n) if not n_is_integer and not n_is_odd_reciprocal: - raise Error( - ValueError( - message=( - "Cannot compute non-odd-integer root of a negative" - " number." - ), - function="root()", - ) + raise ValueError( + message=( + "Cannot compute non-odd-integer root of a negative number." + ), + function="root()", ) elif n_is_integer: var result = integer_root(x, n, precision) @@ -574,27 +561,21 @@ def integer_root( # Handle special case: n must be a positive integer if n.sign: - raise Error( - ValueError( - message="Root value must be positive.", - function="integer_root()", - ) + raise ValueError( + message="Root value must be positive.", + function="integer_root()", ) if not n.is_integer(): - raise Error( - ValueError( - message="Root value must be an integer.", - function="integer_root()", - ) + raise ValueError( + message="Root value must be an integer.", + function="integer_root()", ) if n.coefficient.is_zero(): - raise Error( - ValueError( - message="Cannot compute zeroth root.", - function="integer_root()", - ) + raise ValueError( + message="Cannot compute zeroth root.", + function="integer_root()", ) # Special case: n = 1 (1st root is just the number itself) @@ -633,11 +614,9 @@ def integer_root( if n_uint.words[0] % 2 == 1: # Odd root result_sign = True else: # n_uint.words[0] % 2 == 0: # Even root - raise Error( - ValueError( - message="Cannot compute even root of a negative number.", - function="integer_root()", - ) + raise ValueError( + message="Cannot compute even root of a negative number.", + function="integer_root()", ) # Extract n as Int for Newton's method @@ -1225,11 +1204,9 @@ def sqrt_exact(x: BigDecimal, precision: Int) raises -> BigDecimal: # Handle special cases if x.sign: - raise Error( - ValueError( - message="Cannot compute square root of a negative number.", - function="sqrt_exact()", - ) + raise ValueError( + message="Cannot compute square root of a negative number.", + function="sqrt_exact()", ) if x.coefficient.is_zero(): @@ -1361,11 +1338,9 @@ def sqrt_reciprocal(x: BigDecimal, precision: Int) raises -> BigDecimal: # Handle special cases if x.sign: - raise Error( - ValueError( - message="Cannot compute square root of a negative number.", - function="sqrt_reciprocal()", - ) + raise ValueError( + message="Cannot compute square root of a negative number.", + function="sqrt_reciprocal()", ) if x.coefficient.is_zero(): @@ -1546,11 +1521,9 @@ def sqrt_newton(x: BigDecimal, precision: Int) raises -> BigDecimal: # Handle special cases if x.sign: - raise Error( - ValueError( - message="Cannot compute square root of a negative number.", - function="sqrt_newton()", - ) + raise ValueError( + message="Cannot compute square root of a negative number.", + function="sqrt_newton()", ) if x.coefficient.is_zero(): @@ -1634,11 +1607,9 @@ def sqrt_decimal_approach(x: BigDecimal, precision: Int) raises -> BigDecimal: # Handle special cases if x.sign: - raise Error( - ValueError( - message="Cannot compute square root of a negative number.", - function="sqrt_decimal_approach()", - ) + raise ValueError( + message="Cannot compute square root of a negative number.", + function="sqrt_decimal_approach()", ) if x.coefficient.is_zero(): @@ -1820,10 +1791,8 @@ def exp(x: BigDecimal, precision: Int) raises -> BigDecimal: # For very large positive values, result will overflow BigDecimal capacity # TODO: Use BigInt10 as scale can avoid overflow in this case if not x.sign and x.adjusted() >= 20: # x > 10^20 - raise Error( - OverflowError( - message="Result too large to represent", function="exp()" - ) + raise OverflowError( + message="Result too large to represent", function="exp()" ) # For very large negative values, result will be effectively zero @@ -2031,17 +2000,13 @@ def ln( # Handle special cases if x.sign: - raise Error( - ValueError( - message="Cannot compute logarithm of negative number", - function="ln()", - ) + raise ValueError( + message="Cannot compute logarithm of negative number", + function="ln()", ) if x.coefficient.is_zero(): - raise Error( - ValueError( - message="Cannot compute logarithm of zero", function="ln()" - ) + raise ValueError( + message="Cannot compute logarithm of zero", function="ln()" ) if x == BigDecimal(BigUInt.one(), 0, False): return BigDecimal(BigUInt.zero(), 0, False) # ln(1) = 0 @@ -2131,36 +2096,26 @@ def log(x: BigDecimal, base: BigDecimal, precision: Int) raises -> BigDecimal: # Special cases if x.sign: - raise Error( - ValueError( - message="Cannot compute logarithm of a negative number", - function="log()", - ) + raise ValueError( + message="Cannot compute logarithm of a negative number", + function="log()", ) if x.coefficient.is_zero(): - raise Error( - ValueError( - message="Cannot compute logarithm of zero", function="log()" - ) + raise ValueError( + message="Cannot compute logarithm of zero", function="log()" ) # Base validation if base.sign: - raise Error( - ValueError(message="Cannot use a negative base", function="log()") - ) + raise ValueError(message="Cannot use a negative base", function="log()") if base.coefficient.is_zero(): - raise Error( - ValueError(message="Cannot use zero as a base", function="log()") - ) + raise ValueError(message="Cannot use zero as a base", function="log()") if ( base.coefficient.number_of_digits() == base.scale + 1 and base.coefficient.words[-1] == 1 ): - raise Error( - ValueError( - message="Cannot use base 1 for logarithm", function="log()" - ) + raise ValueError( + message="Cannot use base 1 for logarithm", function="log()" ) # Special cases @@ -2209,17 +2164,13 @@ def log10(x: BigDecimal, precision: Int) raises -> BigDecimal: # Special cases if x.sign: - raise Error( - ValueError( - message="Cannot compute logarithm of a negative number", - function="log10()", - ) + raise ValueError( + message="Cannot compute logarithm of a negative number", + function="log10()", ) if x.coefficient.is_zero(): - raise Error( - ValueError( - message="Cannot compute logarithm of zero", function="log10()" - ) + raise ValueError( + message="Cannot compute logarithm of zero", function="log10()" ) # Fast path: Powers of 10 are handled directly diff --git a/src/decimo/bigdecimal/trigonometric.mojo b/src/decimo/bigdecimal/trigonometric.mojo index 10f1f79d..eb2166b5 100644 --- a/src/decimo/bigdecimal/trigonometric.mojo +++ b/src/decimo/bigdecimal/trigonometric.mojo @@ -364,8 +364,8 @@ def tan_cot(x: BigDecimal, precision: Int, is_tan: Bool) raises -> BigDecimal: # since tan(0) is defined as 0. # This is a design choice, not a mathematical one. # In practice, cot(0) should raise an error. - raise Error( - ValueError(message="cot(nπ) is undefined", function="tan_cot()") + raise ValueError( + message="cot(nπ) is undefined", function="tan_cot()" ) var pi = decimo.bigdecimal.constants.pi(precision=working_precision_pi) @@ -430,9 +430,7 @@ def csc(x: BigDecimal, precision: Int) raises -> BigDecimal: This function calculates csc(x) = 1 / sin(x). """ if x.is_zero(): - raise Error( - ValueError(message="csc(nπ) is undefined", function="csc()") - ) + raise ValueError(message="csc(nπ) is undefined", function="csc()") comptime BUFFER_DIGITS = 9 var working_precision = precision + BUFFER_DIGITS diff --git a/src/decimo/bigfloat/bigfloat.mojo b/src/decimo/bigfloat/bigfloat.mojo index 76fee07e..d3d468cd 100644 --- a/src/decimo/bigfloat/bigfloat.mojo +++ b/src/decimo/bigfloat/bigfloat.mojo @@ -38,7 +38,7 @@ from std.memory import UnsafePointer from decimo.bigdecimal.bigdecimal import BigDecimal from decimo.biguint.biguint import BigUInt -from decimo.errors import DecimoError, ConversionError +from decimo.errors import ConversionError, RuntimeError from decimo.bigfloat.mpfr_wrapper import ( mpfrw_available, mpfrw_init, @@ -146,23 +146,19 @@ struct BigFloat(Comparable, Movable, Writable): precision: Number of significant decimal digits. """ if not mpfrw_available(): - raise Error( - DecimoError( - message=( - "BigFloat requires MPFR (brew install mpfr / apt" - " install libmpfr-dev)" - ), - function="BigFloat.__init__()", - ) + raise RuntimeError( + message=( + "BigFloat requires MPFR (brew install mpfr / apt" + " install libmpfr-dev)" + ), + function="BigFloat.__init__()", ) var bits = _dps_to_bits(precision) self.handle = mpfrw_init(bits) if self.handle < 0: - raise Error( - DecimoError( - message="MPFR handle pool exhausted", - function="BigFloat.__init__()", - ) + raise RuntimeError( + message="MPFR handle pool exhausted", + function="BigFloat.__init__()", ) self.precision = precision var s_bytes = value.as_bytes() @@ -173,11 +169,9 @@ struct BigFloat(Comparable, Movable, Writable): ) if result_code != 0: mpfrw_clear(self.handle) - raise Error( - ConversionError( - message="Invalid number string: " + value, - function="BigFloat.__init__()", - ) + raise ConversionError( + message="Invalid number string: " + value, + function="BigFloat.__init__()", ) def __init__(out self, value: Int, precision: Int = PRECISION) raises: @@ -245,11 +239,9 @@ struct BigFloat(Comparable, Movable, Writable): var d = digits if digits > 0 else self.precision var address = mpfrw_get_str(self.handle, Int32(d)) if address == 0: - raise Error( - ConversionError( - message="Failed to export string", - function="BigFloat.to_string()", - ) + raise ConversionError( + message="Failed to export string", + function="BigFloat.to_string()", ) var result = _read_c_string(address) mpfrw_free_str(address) @@ -330,11 +322,9 @@ struct BigFloat(Comparable, Movable, Writable): self.handle, Int32(d), UnsafePointer(to=exp) ) if address == 0: - raise Error( - ConversionError( - message="mpfr_get_str failed", - function="BigFloat.to_bigdecimal()", - ) + raise ConversionError( + message="mpfr_get_str failed", + function="BigFloat.to_bigdecimal()", ) # 2. Single memcpy into a Mojo-owned buffer @@ -469,11 +459,9 @@ struct BigFloat(Comparable, Movable, Writable): """ var h = mpfrw_init(_dps_to_bits(self.precision)) if h < 0: - raise Error( - DecimoError( - message="Handle allocation failed.", - function="BigFloat.__neg__()", - ) + raise RuntimeError( + message="Handle allocation failed.", + function="BigFloat.__neg__()", ) mpfrw_neg(h, self.handle) return Self(_handle=h, _precision=self.precision) @@ -486,11 +474,9 @@ struct BigFloat(Comparable, Movable, Writable): """ var h = mpfrw_init(_dps_to_bits(self.precision)) if h < 0: - raise Error( - DecimoError( - message="Handle allocation failed.", - function="BigFloat.__abs__()", - ) + raise RuntimeError( + message="Handle allocation failed.", + function="BigFloat.__abs__()", ) mpfrw_abs(h, self.handle) return Self(_handle=h, _precision=self.precision) @@ -511,11 +497,9 @@ struct BigFloat(Comparable, Movable, Writable): var prec = max(self.precision, other.precision) var h = mpfrw_init(_dps_to_bits(prec)) if h < 0: - raise Error( - DecimoError( - message="Handle allocation failed.", - function="BigFloat.__add__()", - ) + raise RuntimeError( + message="Handle allocation failed.", + function="BigFloat.__add__()", ) mpfrw_add(h, self.handle, other.handle) return Self(_handle=h, _precision=prec) @@ -532,11 +516,9 @@ struct BigFloat(Comparable, Movable, Writable): var prec = max(self.precision, other.precision) var h = mpfrw_init(_dps_to_bits(prec)) if h < 0: - raise Error( - DecimoError( - message="Handle allocation failed.", - function="BigFloat.__sub__()", - ) + raise RuntimeError( + message="Handle allocation failed.", + function="BigFloat.__sub__()", ) mpfrw_sub(h, self.handle, other.handle) return Self(_handle=h, _precision=prec) @@ -553,11 +535,9 @@ struct BigFloat(Comparable, Movable, Writable): var prec = max(self.precision, other.precision) var h = mpfrw_init(_dps_to_bits(prec)) if h < 0: - raise Error( - DecimoError( - message="Handle allocation failed.", - function="BigFloat.__mul__()", - ) + raise RuntimeError( + message="Handle allocation failed.", + function="BigFloat.__mul__()", ) mpfrw_mul(h, self.handle, other.handle) return Self(_handle=h, _precision=prec) @@ -574,11 +554,9 @@ struct BigFloat(Comparable, Movable, Writable): var prec = max(self.precision, other.precision) var h = mpfrw_init(_dps_to_bits(prec)) if h < 0: - raise Error( - DecimoError( - message="Handle allocation failed.", - function="BigFloat.__truediv__()", - ) + raise RuntimeError( + message="Handle allocation failed.", + function="BigFloat.__truediv__()", ) mpfrw_div(h, self.handle, other.handle) return Self(_handle=h, _precision=prec) @@ -606,11 +584,9 @@ struct BigFloat(Comparable, Movable, Writable): """ var h = mpfrw_init(_dps_to_bits(self.precision)) if h < 0: - raise Error( - DecimoError( - message="Handle allocation failed.", - function="BigFloat.sqrt()", - ) + raise RuntimeError( + message="Handle allocation failed.", + function="BigFloat.sqrt()", ) mpfrw_sqrt(h, self.handle) return Self(_handle=h, _precision=self.precision) @@ -623,11 +599,9 @@ struct BigFloat(Comparable, Movable, Writable): """ var h = mpfrw_init(_dps_to_bits(self.precision)) if h < 0: - raise Error( - DecimoError( - message="Handle allocation failed.", - function="BigFloat.exp()", - ) + raise RuntimeError( + message="Handle allocation failed.", + function="BigFloat.exp()", ) mpfrw_exp(h, self.handle) return Self(_handle=h, _precision=self.precision) @@ -640,11 +614,9 @@ struct BigFloat(Comparable, Movable, Writable): """ var h = mpfrw_init(_dps_to_bits(self.precision)) if h < 0: - raise Error( - DecimoError( - message="Handle allocation failed.", - function="BigFloat.ln()", - ) + raise RuntimeError( + message="Handle allocation failed.", + function="BigFloat.ln()", ) mpfrw_log(h, self.handle) return Self(_handle=h, _precision=self.precision) @@ -657,11 +629,9 @@ struct BigFloat(Comparable, Movable, Writable): """ var h = mpfrw_init(_dps_to_bits(self.precision)) if h < 0: - raise Error( - DecimoError( - message="Handle allocation failed.", - function="BigFloat.sin()", - ) + raise RuntimeError( + message="Handle allocation failed.", + function="BigFloat.sin()", ) mpfrw_sin(h, self.handle) return Self(_handle=h, _precision=self.precision) @@ -674,11 +644,9 @@ struct BigFloat(Comparable, Movable, Writable): """ var h = mpfrw_init(_dps_to_bits(self.precision)) if h < 0: - raise Error( - DecimoError( - message="Handle allocation failed.", - function="BigFloat.cos()", - ) + raise RuntimeError( + message="Handle allocation failed.", + function="BigFloat.cos()", ) mpfrw_cos(h, self.handle) return Self(_handle=h, _precision=self.precision) @@ -691,11 +659,9 @@ struct BigFloat(Comparable, Movable, Writable): """ var h = mpfrw_init(_dps_to_bits(self.precision)) if h < 0: - raise Error( - DecimoError( - message="Handle allocation failed.", - function="BigFloat.tan()", - ) + raise RuntimeError( + message="Handle allocation failed.", + function="BigFloat.tan()", ) mpfrw_tan(h, self.handle) return Self(_handle=h, _precision=self.precision) @@ -712,11 +678,9 @@ struct BigFloat(Comparable, Movable, Writable): var prec = max(self.precision, exponent.precision) var h = mpfrw_init(_dps_to_bits(prec)) if h < 0: - raise Error( - DecimoError( - message="Handle allocation failed.", - function="BigFloat.power()", - ) + raise RuntimeError( + message="Handle allocation failed.", + function="BigFloat.power()", ) mpfrw_pow(h, self.handle, exponent.handle) return Self(_handle=h, _precision=prec) @@ -732,11 +696,9 @@ struct BigFloat(Comparable, Movable, Writable): """ var h = mpfrw_init(_dps_to_bits(self.precision)) if h < 0: - raise Error( - DecimoError( - message="Handle allocation failed.", - function="BigFloat.root()", - ) + raise RuntimeError( + message="Handle allocation failed.", + function="BigFloat.root()", ) mpfrw_rootn_ui(h, self.handle, n) return Self(_handle=h, _precision=self.precision) @@ -752,22 +714,18 @@ struct BigFloat(Comparable, Movable, Writable): A `BigFloat` containing π at the requested precision. """ if not mpfrw_available(): - raise Error( - DecimoError( - message=( - "BigFloat requires MPFR (brew install mpfr / apt" - " install libmpfr-dev)" - ), - function="BigFloat.pi()", - ) + raise RuntimeError( + message=( + "BigFloat requires MPFR (brew install mpfr / apt" + " install libmpfr-dev)" + ), + function="BigFloat.pi()", ) var h = mpfrw_init(_dps_to_bits(precision)) if h < 0: - raise Error( - DecimoError( - message="Handle allocation failed.", - function="BigFloat.pi()", - ) + raise RuntimeError( + message="Handle allocation failed.", + function="BigFloat.pi()", ) mpfrw_const_pi(h) return BigFloat(_handle=h, _precision=precision) diff --git a/src/decimo/bigint/arithmetics.mojo b/src/decimo/bigint/arithmetics.mojo index 774693fe..6536d4ec 100644 --- a/src/decimo/bigint/arithmetics.mojo +++ b/src/decimo/bigint/arithmetics.mojo @@ -37,7 +37,7 @@ from std.memory import memcpy, memset_zero from decimo.bigint.bigint import BigInt from decimo.bigint.comparison import compare_magnitudes -from decimo.errors import DecimoError, ZeroDivisionError +from decimo.errors import ValueError, ZeroDivisionError # Karatsuba cutoff: operands with this many words or fewer use schoolbook. @@ -1149,11 +1149,9 @@ def _divmod_knuth_d_from_slices( if len_a_eff <= 0: return ([UInt32(0)], [UInt32(0)]) if len_b_eff <= 0: - raise Error( - DecimoError( - function="_divmod_knuth_d_from_slices()", - message="Division by zero in B-Z base case", - ) + raise ZeroDivisionError( + function="_divmod_knuth_d_from_slices()", + message="Division by zero in B-Z base case", ) # Single-word divisor fast path @@ -2335,32 +2333,28 @@ def power(base: BigInt, exponent: Int) raises -> BigInt: Error: If the exponent is too large (>= 1_000_000_000). """ if exponent < 0: - raise Error( - DecimoError( - function="power()", - message=( - "The exponent " - + String(exponent) - + " is negative.\n" - + "Consider using a non-negative exponent." - ), - ) + raise ValueError( + function="power()", + message=( + "The exponent " + + String(exponent) + + " is negative.\n" + + "Consider using a non-negative exponent." + ), ) if exponent == 0: return BigInt(1) if exponent >= 1_000_000_000: - raise Error( - DecimoError( - function="power()", - message=( - "The exponent " - + String(exponent) - + " is too large.\n" - + "Consider using an exponent below 1_000_000_000." - ), - ) + raise ValueError( + function="power()", + message=( + "The exponent " + + String(exponent) + + " is too large.\n" + + "Consider using an exponent below 1_000_000_000." + ), ) if base.is_zero(): diff --git a/src/decimo/bigint/bigint.mojo b/src/decimo/bigint/bigint.mojo index efc4ab7c..d5e050e6 100644 --- a/src/decimo/bigint/bigint.mojo +++ b/src/decimo/bigint/bigint.mojo @@ -39,10 +39,10 @@ import decimo.str from decimo.bigint10.bigint10 import BigInt10 from decimo.biguint.biguint import BigUInt from decimo.errors import ( - DecimoError, ConversionError, OverflowError, ValueError, + ZeroDivisionError, ) # Type aliases @@ -468,31 +468,27 @@ struct BigInt( # For BigInt (integer type), the fractional part must be zero. if scale > 0: if scale >= len(coef): - raise Error( - ConversionError( + raise ConversionError( + function="BigInt.from_string(value: String)", + message=( + 'The input value "' + + value + + '" is not an integer.\n' + + "The scale is larger than the number of digits." + ), + ) + # Check that the fractional digits are all zero + for i in range(1, scale + 1): + if coef[-i] != 0: + raise ConversionError( function="BigInt.from_string(value: String)", message=( 'The input value "' + value + '" is not an integer.\n' - + "The scale is larger than the number of digits." + + "The fractional part is not zero." ), ) - ) - # Check that the fractional digits are all zero - for i in range(1, scale + 1): - if coef[-i] != 0: - raise Error( - ConversionError( - function="BigInt.from_string(value: String)", - message=( - 'The input value "' - + value - + '" is not an integer.\n' - + "The fractional part is not zero." - ), - ) - ) # Remove fractional zeros from coefficient coef.resize(len(coef) - scale, UInt8(0)) @@ -629,11 +625,9 @@ struct BigInt( # Int is 64-bit, so we need at most 2 words to represent it. # Int.MAX = 9_223_372_036_854_775_807 = 0x7FFF_FFFF_FFFF_FFFF if len(self.words) > 2: - raise Error( - OverflowError( - message="The number exceeds the size of Int", - function="BigInt.to_int()", - ) + raise OverflowError( + message="The number exceeds the size of Int", + function="BigInt.to_int()", ) var magnitude: UInt64 = UInt64(self.words[0]) @@ -643,11 +637,9 @@ struct BigInt( if self.sign: # Negative: check against Int.MIN magnitude (2^63) if magnitude > UInt64(9_223_372_036_854_775_808): - raise Error( - OverflowError( - message="The number exceeds the size of Int", - function="BigInt.to_int()", - ) + raise OverflowError( + message="The number exceeds the size of Int", + function="BigInt.to_int()", ) if magnitude == UInt64(9_223_372_036_854_775_808): return Int.MIN @@ -655,11 +647,9 @@ struct BigInt( else: # Positive: check against Int.MAX (2^63 - 1) if magnitude > UInt64(9_223_372_036_854_775_807): - raise Error( - OverflowError( - message="The number exceeds the size of Int", - function="BigInt.to_int()", - ) + raise OverflowError( + message="The number exceeds the size of Int", + function="BigInt.to_int()", ) return Int(magnitude) @@ -984,12 +974,10 @@ struct BigInt( try: return decimo.bigint.arithmetics.floor_divide(self, other) except e: - raise Error( - DecimoError( - message="See the above exception.", - function="BigInt.__floordiv__()", - previous_error=e^, - ) + raise ZeroDivisionError( + message="See the above exception.", + function="BigInt.__floordiv__()", + previous_error=e^, ) @always_inline @@ -1005,12 +993,10 @@ struct BigInt( try: return decimo.bigint.arithmetics.floor_modulo(self, other) except e: - raise Error( - DecimoError( - message="See the above exception.", - function="BigInt.__mod__()", - previous_error=e^, - ) + raise ZeroDivisionError( + message="See the above exception.", + function="BigInt.__mod__()", + previous_error=e^, ) @always_inline @@ -1026,12 +1012,10 @@ struct BigInt( try: return decimo.bigint.arithmetics.floor_divmod(self, other) except e: - raise Error( - DecimoError( - message="See the above exception.", - function="BigInt.__divmod__()", - previous_error=e^, - ) + raise ZeroDivisionError( + message="See the above exception.", + function="BigInt.__divmod__()", + previous_error=e^, ) @always_inline @@ -1468,21 +1452,17 @@ struct BigInt( Error: If the exponent is negative or too large. """ if exponent.is_negative(): - raise Error( - ValueError( - message="Exponent must be non-negative", - function="BigInt.power()", - ) + raise ValueError( + message="Exponent must be non-negative", + function="BigInt.power()", ) var exp_int: Int try: exp_int = exponent.to_int() except e: - raise Error( - OverflowError( - message="Exponent too large to fit in Int", - function="BigInt.power()", - ) + raise OverflowError( + message="Exponent too large to fit in Int", + function="BigInt.power()", ) return self.power(exp_int) diff --git a/src/decimo/bigint/exponential.mojo b/src/decimo/bigint/exponential.mojo index ab50c511..7c04cd30 100644 --- a/src/decimo/bigint/exponential.mojo +++ b/src/decimo/bigint/exponential.mojo @@ -25,7 +25,7 @@ from std import math from decimo.bigint.bigint import BigInt import decimo.bigint.arithmetics -from decimo.errors import DecimoError +from decimo.errors import ValueError # ===----------------------------------------------------------------------=== # @@ -281,11 +281,9 @@ def sqrt(x: BigInt) raises -> BigInt: native 64-bit arithmetic (no heap allocation, O(1) per iteration). """ if x.is_negative(): - raise Error( - DecimoError( - function="sqrt()", - message="Cannot compute square root of a negative number", - ) + raise ValueError( + function="sqrt()", + message="Cannot compute square root of a negative number", ) if x.is_zero(): diff --git a/src/decimo/bigint/number_theory.mojo b/src/decimo/bigint/number_theory.mojo index a2115677..2c8c184d 100644 --- a/src/decimo/bigint/number_theory.mojo +++ b/src/decimo/bigint/number_theory.mojo @@ -34,7 +34,7 @@ from decimo.bigint.arithmetics import ( subtract_inplace, right_shift_inplace, ) -from decimo.errors import DecimoError +from decimo.errors import ValueError # ===----------------------------------------------------------------------=== # @@ -245,19 +245,15 @@ def mod_pow(base: BigInt, exponent: BigInt, modulus: BigInt) raises -> BigInt: If exponent < 0 or modulus <= 0. """ if exponent.is_negative(): - raise Error( - DecimoError( - function="mod_pow()", - message="Exponent must be non-negative", - ) + raise ValueError( + function="mod_pow()", + message="Exponent must be non-negative", ) if not modulus.is_positive(): - raise Error( - DecimoError( - function="mod_pow()", - message="Modulus must be positive", - ) + raise ValueError( + function="mod_pow()", + message="Modulus must be positive", ) # x mod 1 = 0 for all x @@ -326,11 +322,9 @@ def mod_inverse(a: BigInt, modulus: BigInt) raises -> BigInt: If modulus <= 0 or the inverse does not exist (gcd(a, modulus) != 1). """ if not modulus.is_positive(): - raise Error( - DecimoError( - function="mod_inverse()", - message="Modulus must be positive", - ) + raise ValueError( + function="mod_inverse()", + message="Modulus must be positive", ) var result = extended_gcd(a, modulus) @@ -338,11 +332,9 @@ def mod_inverse(a: BigInt, modulus: BigInt) raises -> BigInt: var x = result[1].copy() if not g.is_one(): - raise Error( - DecimoError( - function="mod_inverse()", - message="Modular inverse does not exist (gcd != 1)", - ) + raise ValueError( + function="mod_inverse()", + message="Modular inverse does not exist (gcd != 1)", ) # Ensure result is in [0, modulus) diff --git a/src/decimo/bigint10/arithmetics.mojo b/src/decimo/bigint10/arithmetics.mojo index 481c58eb..ed69548b 100644 --- a/src/decimo/bigint10/arithmetics.mojo +++ b/src/decimo/bigint10/arithmetics.mojo @@ -20,7 +20,7 @@ Implements basic arithmetic functions for the BigInt10 type. from decimo.bigint10.bigint10 import BigInt10 from decimo.biguint.biguint import BigUInt -from decimo.errors import DecimoError +from decimo.errors import ZeroDivisionError from decimo.rounding_mode import RoundingMode @@ -225,12 +225,10 @@ def floor_divide(x1: BigInt10, x2: BigInt10) raises -> BigInt10: x1.magnitude, x2.magnitude ) except e: - raise Error( - DecimoError( - message="See the above exception.", - function="floor_divide()", - previous_error=e^, - ), + raise ZeroDivisionError( + message="See the above exception.", + function="floor_divide()", + previous_error=e^, ) return BigInt10(magnitude^, sign=False) @@ -241,12 +239,10 @@ def floor_divide(x1: BigInt10, x2: BigInt10) raises -> BigInt10: x1.magnitude, x2.magnitude ) except e: - raise Error( - DecimoError( - message="See the above exception.", - function="floor_divide()", - previous_error=e^, - ), + raise ZeroDivisionError( + message="See the above exception.", + function="floor_divide()", + previous_error=e^, ) return BigInt10(magnitude^, sign=True) @@ -272,12 +268,10 @@ def truncate_divide(x1: BigInt10, x2: BigInt10) raises -> BigInt10: x1.magnitude, x2.magnitude ) except e: - raise Error( - DecimoError( - message="See the above exception.", - function="truncate_divide()", - previous_error=e^, - ), + raise ZeroDivisionError( + message="See the above exception.", + function="truncate_divide()", + previous_error=e^, ) return BigInt10(magnitude^, sign=x1.sign != x2.sign) @@ -308,12 +302,10 @@ def floor_modulo(x1: BigInt10, x2: BigInt10) raises -> BigInt10: x1.magnitude, x2.magnitude ) except e: - raise Error( - DecimoError( - message="See the above exception.", - function="floor_modulo()", - previous_error=e^, - ), + raise ZeroDivisionError( + message="See the above exception.", + function="floor_modulo()", + previous_error=e^, ) return BigInt10(magnitude^, sign=x2.sign) @@ -324,12 +316,10 @@ def floor_modulo(x1: BigInt10, x2: BigInt10) raises -> BigInt10: x1.magnitude, x2.magnitude ) except e: - raise Error( - DecimoError( - message="See the above exception.", - function="floor_modulo()", - previous_error=e^, - ), + raise ZeroDivisionError( + message="See the above exception.", + function="floor_modulo()", + previous_error=e^, ) return BigInt10(magnitude^, sign=x2.sign) @@ -355,7 +345,7 @@ def truncate_modulo(x1: BigInt10, x2: BigInt10) raises -> BigInt10: x1.magnitude, x2.magnitude ) except e: - raise DecimoError( + raise ZeroDivisionError( message="See the above exception.", function="truncate_modulo()", previous_error=e^, diff --git a/src/decimo/bigint10/bigint10.mojo b/src/decimo/bigint10/bigint10.mojo index c8dc3e2a..89d45572 100644 --- a/src/decimo/bigint10/bigint10.mojo +++ b/src/decimo/bigint10/bigint10.mojo @@ -31,10 +31,10 @@ import decimo.bigint10.comparison from decimo.bigdecimal.bigdecimal import BigDecimal from decimo.biguint.biguint import BigUInt from decimo.errors import ( - DecimoError, ValueError, OverflowError, ConversionError, + ZeroDivisionError, ) import decimo.str @@ -117,14 +117,12 @@ struct BigInt10( try: self = Self.from_list(words^, sign=sign) except e: - raise Error( - DecimoError( - message="See the above exception.", - function=( - "BigInt10.__init__(var words: List[UInt32], sign: Bool)" - ), - previous_error=e^, - ) + raise ConversionError( + message="See the above exception.", + function=( + "BigInt10.__init__(var words: List[UInt32], sign: Bool)" + ), + previous_error=e^, ) def __init__(out self, *, var raw_words: List[UInt32], sign: Bool): @@ -159,12 +157,10 @@ struct BigInt10( try: self = Self.from_string(value) except e: - raise Error( - ConversionError( - message="Cannot initialize BigInt10 from String.", - function="BigInt10.__init__()", - previous_error=e^, - ) + raise ConversionError( + message="Cannot initialize BigInt10 from String.", + function="BigInt10.__init__()", + previous_error=e^, ) # TODO: If Mojo makes Int type an alias of SIMD[DType.index, 1], @@ -230,15 +226,12 @@ struct BigInt10( try: return Self(BigUInt.from_list(words^), sign) except e: - raise Error( - DecimoError( - message="See the above exception.", - function=( - "BigInt10.from_list(var words: List[UInt32], sign:" - " Bool)" - ), - previous_error=e^, - ) + raise ConversionError( + message="See the above exception.", + function=( + "BigInt10.from_list(var words: List[UInt32], sign: Bool)" + ), + previous_error=e^, ) @staticmethod @@ -264,13 +257,9 @@ struct BigInt10( # Check if the words are valid for word in words: if word > UInt32(999_999_999): - raise Error( - ValueError( - message=( - "Word value exceeds maximum value of 999_999_999" - ), - function="BigInt10.__init__()", - ) + raise ValueError( + message="Word value exceeds maximum value of 999_999_999", + function="BigInt10.__init__()", ) else: list_of_words.append(word) @@ -408,12 +397,10 @@ struct BigInt10( # Use the existing from_string() method to parse the string return Self.from_string(py_str) except e: - raise Error( - ConversionError( - message="Failed to convert Python int to BigInt10.", - function="BigInt10.from_python_int()", - previous_error=e^, - ) + raise ConversionError( + message="Failed to convert Python int to BigInt10.", + function="BigInt10.from_python_int()", + previous_error=e^, ) # ===------------------------------------------------------------------=== # @@ -470,11 +457,9 @@ struct BigInt10( # is larger than 10^18 -1 but smaller than 10^27 - 1 if len(self.magnitude.words) > 3: - raise Error( - OverflowError( - message="The number exceeds the size of Int.", - function="BigInt10.to_int()", - ) + raise OverflowError( + message="The number exceeds the size of Int.", + function="BigInt10.to_int()", ) var value: Int128 = 0 @@ -491,11 +476,9 @@ struct BigInt10( var int_min = Int.MIN var int_max = Int.MAX if value < Int128(int_min) or value > Int128(int_max): - raise Error( - OverflowError( - message="The number exceeds the size of Int.", - function="BigInt10.to_int()", - ) + raise OverflowError( + message="The number exceeds the size of Int.", + function="BigInt10.to_int()", ) return Int(value) @@ -636,12 +619,10 @@ struct BigInt10( try: return decimo.bigint10.arithmetics.floor_divide(self, other) except e: - raise Error( - DecimoError( - message="See the above exception.", - function="BigInt10.__floordiv__()", - previous_error=e^, - ) + raise ZeroDivisionError( + message="See the above exception.", + function="BigInt10.__floordiv__()", + previous_error=e^, ) @always_inline @@ -657,12 +638,10 @@ struct BigInt10( try: return decimo.bigint10.arithmetics.floor_modulo(self, other) except e: - raise Error( - DecimoError( - message="See the above exception.", - function="BigInt10.__mod__()", - previous_error=e^, - ) + raise ZeroDivisionError( + message="See the above exception.", + function="BigInt10.__mod__()", + previous_error=e^, ) @always_inline @@ -1071,11 +1050,9 @@ struct BigInt10( The result of raising to the given power. """ if exponent > Self(BigUInt(raw_words=[0, 1]), sign=False): - raise Error( - OverflowError( - message="The exponent is too large.", - function="BigInt10.power()", - ) + raise OverflowError( + message="The exponent is too large.", + function="BigInt10.power()", ) var exponent_as_int = exponent.to_int() return self.power(exponent_as_int) diff --git a/src/decimo/biguint/arithmetics.mojo b/src/decimo/biguint/arithmetics.mojo index 715c7f94..ecec0e42 100644 --- a/src/decimo/biguint/arithmetics.mojo +++ b/src/decimo/biguint/arithmetics.mojo @@ -25,7 +25,6 @@ from std.memory import memcpy, memset_zero from decimo.biguint.biguint import BigUInt import decimo.biguint.comparison from decimo.errors import ( - DecimoError, OverflowError, ValueError, ZeroDivisionError, @@ -108,11 +107,9 @@ def negative(x: BigUInt) raises -> BigUInt: debug_assert[assert_mode="none"]( len(x.words) == 1, "negative(): leading zero words" ) - raise Error( - OverflowError( - function="negative()", - message="Negative of non-zero unsigned integer is undefined", - ) + raise OverflowError( + function="negative()", + message="Negative of non-zero unsigned integer is undefined", ) return BigUInt.zero() # Return zero @@ -538,14 +535,12 @@ def subtract_school(x: BigUInt, y: BigUInt) raises -> BigUInt: # |x| = |y| return BigUInt.zero() # Return zero if comparison_result < 0: - raise Error( - OverflowError( - function="subtract_school()", - message=( - "biguint.arithmetics.subtract(): Result is negative due to" - " x < y" - ), - ) + raise OverflowError( + function="subtract_school()", + message=( + "biguint.arithmetics.subtract(): Result is negative due to" + " x < y" + ), ) # Now it is safe to subtract the smaller number from the larger one @@ -632,14 +627,12 @@ def subtract_simd(x: BigUInt, y: BigUInt) raises -> BigUInt: # |x| = |y| return BigUInt.zero() # Return zero if comparison_result < 0: - raise Error( - OverflowError( - function="subtract()", - message=( - "biguint.arithmetics.subtract(): Result is negative due to" - " x < y" - ), - ) + raise OverflowError( + function="subtract()", + message=( + "biguint.arithmetics.subtract(): Result is negative due to" + " x < y" + ), ) # Now it is safe to subtract the smaller number from the larger one @@ -703,14 +696,12 @@ def subtract_inplace(mut x: BigUInt, y: BigUInt) raises -> None: x.words.resize(unsafe_uninit_length=1) x.words[0] = UInt32(0) # Result is zero elif comparison_result < 0: - raise Error( - OverflowError( - function="subtract_inplace()", - message=( - "biguint.arithmetics.subtract(): Result is negative due to" - " x < y" - ), - ) + raise OverflowError( + function="subtract_inplace()", + message=( + "biguint.arithmetics.subtract(): Result is negative due to" + " x < y" + ), ) # Now it is safe to subtract the smaller number from the larger one @@ -1977,11 +1968,9 @@ def floor_divide(x: BigUInt, y: BigUInt) raises -> BigUInt: # CASE: y is zero if y.is_zero(): - raise Error( - ZeroDivisionError( - function="floor_divide()", - message="Division by zero", - ) + raise ZeroDivisionError( + function="floor_divide()", + message="Division by zero", ) # CASE: Dividend is zero @@ -2078,10 +2067,8 @@ def floor_divide_school(x: BigUInt, y: BigUInt) raises -> BigUInt: # handled properly to improve performance. # CASE: y is zero if y.is_zero(): - raise Error( - ZeroDivisionError( - message="Division by zero", function="floor_divide()" - ) + raise ZeroDivisionError( + message="Division by zero", function="floor_divide()" ) # CASE: Dividend is zero @@ -3142,11 +3129,9 @@ def floor_divide_three_by_two_uint32( b = b1 * BASE + b0. """ if b1 < 500_000_000: - raise Error( - ValueError( - message="b1 must be at least 500_000_000", - function="floor_divide_three_by_two_uint32()", - ) + raise ValueError( + message="b1 must be at least 500_000_000", + function="floor_divide_three_by_two_uint32()", ) var a2a1 = UInt64(a2) * 1_000_000_000 + UInt64(a1) @@ -3198,42 +3183,32 @@ def floor_divide_four_by_two_uint32( """ if b1 < 500_000_000: - raise Error( - ValueError( - message="b1 must be at least 500_000_000", - function="floor_divide_four_by_two_uint32()", - ) + raise ValueError( + message="b1 must be at least 500_000_000", + function="floor_divide_four_by_two_uint32()", ) if a3 > b1: - raise Error( - ValueError( - message="a must be less than b * 10^18", - function="floor_divide_four_by_two_uint32()", - ) + raise ValueError( + message="a must be less than b * 10^18", + function="floor_divide_four_by_two_uint32()", ) elif a3 == b1: if a2 > b0: - raise Error( - ValueError( - message="a must be less than b * 10^18", - function="floor_divide_four_by_two_uint32()", - ) + raise ValueError( + message="a must be less than b * 10^18", + function="floor_divide_four_by_two_uint32()", ) elif a2 == b0: if a1 > 0: - raise Error( - ValueError( - message="a must be less than b * 10^18", - function="floor_divide_four_by_two_uint32()", - ) + raise ValueError( + message="a must be less than b * 10^18", + function="floor_divide_four_by_two_uint32()", ) elif a1 == 0: if a0 >= 0: - raise Error( - ValueError( - message="a must be less than b * 10^18", - function="floor_divide_four_by_two_uint32()", - ) + raise ValueError( + message="a must be less than b * 10^18", + function="floor_divide_four_by_two_uint32()", ) var q1, r1, r0 = floor_divide_three_by_two_uint32(a3, a2, a1, b1, b0) @@ -3277,10 +3252,8 @@ def ceil_divide(x1: BigUInt, x2: BigUInt) raises -> BigUInt: len(x2.words) == 1, "ceil_divide(): leading zero words", ) - raise Error( - ZeroDivisionError( - message="Division by zero", function="ceil_divide()" - ) + raise ZeroDivisionError( + message="Division by zero", function="ceil_divide()" ) # Apply floor division and check if there is a remainder @@ -3316,11 +3289,9 @@ def floor_modulo(x1: BigUInt, x2: BigUInt) raises -> BigUInt: len(x2.words) == 1, "truncate_modulo(): leading zero words", ) - raise Error( - ZeroDivisionError( - function="floor_modulo()", - message="Division by zero", - ) + raise ZeroDivisionError( + function="floor_modulo()", + message="Division by zero", ) # CASE: Dividend is zero @@ -3343,12 +3314,10 @@ def floor_modulo(x1: BigUInt, x2: BigUInt) raises -> BigUInt: try: quotient = floor_divide(x1, x2) except e: - raise Error( - DecimoError( - message="See the above exception.", - function="floor_modulo()", - previous_error=e^, - ) + raise ZeroDivisionError( + message="See the above exception.", + function="floor_modulo()", + previous_error=e^, ) # Calculate remainder: dividend - (divisor * quotient) @@ -3356,12 +3325,10 @@ def floor_modulo(x1: BigUInt, x2: BigUInt) raises -> BigUInt: try: remainder = subtract(x1, multiply(x2, quotient)) except e: - raise Error( - DecimoError( - message="See the above exception.", - function="floor_modulo()", - previous_error=e^, - ) + raise ZeroDivisionError( + message="See the above exception.", + function="floor_modulo()", + previous_error=e^, ) return remainder^ @@ -3386,12 +3353,10 @@ def truncate_modulo(x1: BigUInt, x2: BigUInt) raises -> BigUInt: try: return floor_modulo(x1, x2) except e: - raise Error( - DecimoError( - message="See the above exception.", - function="truncate_modulo()", - previous_error=e^, - ) + raise ZeroDivisionError( + message="See the above exception.", + function="truncate_modulo()", + previous_error=e^, ) @@ -3415,10 +3380,8 @@ def ceil_modulo(x1: BigUInt, x2: BigUInt) raises -> BigUInt: debug_assert[assert_mode="none"]( len(x2.words) == 1, "ceil_modulo(): leading zero words" ) - raise Error( - ZeroDivisionError( - message="Division by zero", function="ceil_modulo()" - ) + raise ZeroDivisionError( + message="Division by zero", function="ceil_modulo()" ) # CASE: Dividend is zero @@ -3475,12 +3438,10 @@ def floor_divide_modulo( var remainder = subtract(x1, multiply(x2, quotient)) return (quotient^, remainder^) except e: - raise Error( - DecimoError( - message="See the above exception.", - function="floor_divide_modulo()", - previous_error=e^, - ) + raise ZeroDivisionError( + message="See the above exception.", + function="floor_divide_modulo()", + previous_error=e^, ) @@ -3661,11 +3622,9 @@ def power_of_10(n: Int) raises -> BigUInt: DecimoError: If n is negative. """ if n < 0: - raise Error( - DecimoError( - function="power_of_10()", - message="Negative exponent not supported", - ) + raise ValueError( + function="power_of_10()", + message="Negative exponent not supported", ) if n == 0: diff --git a/src/decimo/biguint/biguint.mojo b/src/decimo/biguint/biguint.mojo index 195fcd48..bb924d81 100644 --- a/src/decimo/biguint/biguint.mojo +++ b/src/decimo/biguint/biguint.mojo @@ -29,11 +29,11 @@ from decimo.bigint10.bigint10 import BigInt10 import decimo.biguint.arithmetics import decimo.biguint.comparison from decimo.errors import ( - DecimoError, ConversionError, ValueError, IndexError, OverflowError, + ZeroDivisionError, ) import decimo.str @@ -203,12 +203,10 @@ struct BigUInt(Absable, Copyable, IntableRaising, Movable, Writable): try: self = Self.from_list(words^) except e: - raise Error( - DecimoError( - message="See the above exception.", - function="BigUInt.__init__(var words: List[UInt32])", - previous_error=e^, - ) + raise ConversionError( + message="See the above exception.", + function="BigUInt.__init__(var words: List[UInt32])", + previous_error=e^, ) def __init__(out self, *, var raw_words: List[UInt32]): @@ -249,12 +247,10 @@ struct BigUInt(Absable, Copyable, IntableRaising, Movable, Writable): try: self = Self.from_int(value) except e: - raise Error( - DecimoError( - message="See the above exception.", - function="BigUInt.__init__(value: Int)", - previous_error=e^, - ) + raise ConversionError( + message="See the above exception.", + function="BigUInt.__init__(value: Int)", + previous_error=e^, ) @implicit @@ -285,12 +281,10 @@ struct BigUInt(Absable, Copyable, IntableRaising, Movable, Writable): try: self = Self.from_string(value, ignore_sign=ignore_sign) except e: - raise Error( - DecimoError( - message="See the above exception.", - function="BigUInt.__init__(value: String)", - previous_error=e^, - ) + raise ConversionError( + message="See the above exception.", + function="BigUInt.__init__(value: String)", + previous_error=e^, ) # ===------------------------------------------------------------------=== # @@ -328,15 +322,13 @@ struct BigUInt(Absable, Copyable, IntableRaising, Movable, Writable): # Check if the words are valid for word in words: if word > UInt32(999_999_999): - raise Error( - OverflowError( - message=( - "Word value " - + String(word) - + " exceeds maximum value of 999_999_999" - ), - function="BigUInt.from_list()", - ) + raise OverflowError( + message=( + "Word value " + + String(word) + + " exceeds maximum value of 999_999_999" + ), + function="BigUInt.from_list()", ) var res = Self(raw_words=words^) @@ -394,15 +386,13 @@ struct BigUInt(Absable, Copyable, IntableRaising, Movable, Writable): # Check if the words are valid for word in words: if word > UInt32(999_999_999): - raise Error( - OverflowError( - message=( - "Word value " - + String(word) - + " exceeds maximum value of 999_999_999" - ), - function="BigUInt.from_words()", - ) + raise OverflowError( + message=( + "Word value " + + String(word) + + " exceeds maximum value of 999_999_999" + ), + function="BigUInt.from_words()", ) else: list_of_words.append(word) @@ -468,15 +458,13 @@ struct BigUInt(Absable, Copyable, IntableRaising, Movable, Writable): return Self() if value < 0: - raise Error( - OverflowError( - function="BigUInt.from_int(value: Int)", - message=( - "The input value " - + String(value) - + " is negative and is not compatible with BigUInt." - ), - ) + raise OverflowError( + function="BigUInt.from_int(value: Int)", + message=( + "The input value " + + String(value) + + " is negative and is not compatible with BigUInt." + ), ) var list_of_words = List[UInt32]() @@ -668,17 +656,14 @@ struct BigUInt(Absable, Copyable, IntableRaising, Movable, Writable): var sign: Bool = _tuple[2] if (not ignore_sign) and sign: - raise Error( - OverflowError( - function="BigUInt.from_string(value: String)", - message=( - 'The input value "' - + value - + '" is negative but `ignore_sign` is False.\n' - + "Consider using `ignore_sign=True` to ignore the" - " sign." - ), - ) + raise OverflowError( + function="BigUInt.from_string(value: String)", + message=( + 'The input value "' + + value + + '" is negative but `ignore_sign` is False.\n' + + "Consider using `ignore_sign=True` to ignore the sign." + ), ) # Check if the number is zero @@ -690,30 +675,26 @@ struct BigUInt(Absable, Copyable, IntableRaising, Movable, Writable): # If the fractional part is zero, remove the fractional part if scale > 0: if scale >= len(coef): - raise Error( - ConversionError( + raise ConversionError( + function="BigUInt.from_string(value: String)", + message=( + 'The input value "' + + value + + '" is not an integer.\n' + + "The scale is larger than the number of digits." + ), + ) + for i in range(1, scale + 1): + if coef[-i] != 0: + raise ConversionError( function="BigUInt.from_string(value: String)", message=( 'The input value "' + value + '" is not an integer.\n' - + "The scale is larger than the number of digits." + + "The fractional part is not zero." ), ) - ) - for i in range(1, scale + 1): - if coef[-i] != 0: - raise Error( - ConversionError( - function="BigUInt.from_string(value: String)", - message=( - 'The input value "' - + value - + '" is not an integer.\n' - + "The fractional part is not zero." - ), - ) - ) coef.resize(len(coef) - scale, UInt8(0)) scale = 0 @@ -789,12 +770,10 @@ struct BigUInt(Absable, Copyable, IntableRaising, Movable, Writable): try: return self.to_int() except e: - raise Error( - DecimoError( - message="See the above exception.", - function="BigUInt.__int__()", - previous_error=e^, - ) + raise ConversionError( + message="See the above exception.", + function="BigUInt.__int__()", + previous_error=e^, ) def write_repr_to[W: Writer](self, mut writer: W): @@ -837,23 +816,24 @@ struct BigUInt(Absable, Copyable, IntableRaising, Movable, Writable): # 2^63-1 = 9_223_372_036_854_775_807 # is larger than 10^18 -1 but smaller than 10^27 - 1 - var overflow_error: Error = Error( - OverflowError( - function="BigUInt.to_int()", - message="The number exceeds the size of Int (" - + String(Int.MAX) - + ")", - ) + var overflow_msg = ( + "The number exceeds the size of Int (" + String(Int.MAX) + ")" ) if len(self.words) > 3: - raise overflow_error^ + raise OverflowError( + function="BigUInt.to_int()", + message=overflow_msg, + ) var value: Int128 = 0 for i in range(len(self.words)): value += Int128(self.words[i]) * Int128(1_000_000_000) ** i if value > Int128(Int.MAX): - raise overflow_error^ + raise OverflowError( + function="BigUInt.to_int()", + message=overflow_msg, + ) return Int(value) @@ -867,15 +847,13 @@ struct BigUInt(Absable, Copyable, IntableRaising, Movable, Writable): Error: If the number exceeds the size of UInt64. """ if self.is_uint64_overflow(): - raise Error( - OverflowError( - function="BigUInt.to_uint64()", - message=( - "The number exceeds the size of UInt64 (" - + String(UInt64.MAX) - + ")" - ), - ) + raise OverflowError( + function="BigUInt.to_uint64()", + message=( + "The number exceeds the size of UInt64 (" + + String(UInt64.MAX) + + ")" + ), ) if len(self.words) == 1: @@ -1152,12 +1130,10 @@ struct BigUInt(Absable, Copyable, IntableRaising, Movable, Writable): try: return decimo.biguint.arithmetics.subtract(self, other) except e: - raise Error( - DecimoError( - message="See the above exception.", - function="BigUInt.__sub__(other: Self)", - previous_error=e^, - ) + raise ZeroDivisionError( + message="See the above exception.", + function="BigUInt.__sub__(other: Self)", + previous_error=e^, ) @always_inline @@ -1185,12 +1161,10 @@ struct BigUInt(Absable, Copyable, IntableRaising, Movable, Writable): try: return decimo.biguint.arithmetics.floor_divide(self, other) except e: - raise Error( - DecimoError( - message="See the above exception.", - function="BigUInt.__floordiv__(other: Self)", - previous_error=e^, - ) + raise ZeroDivisionError( + message="See the above exception.", + function="BigUInt.__floordiv__(other: Self)", + previous_error=e^, ) @always_inline @@ -1206,12 +1180,10 @@ struct BigUInt(Absable, Copyable, IntableRaising, Movable, Writable): try: return decimo.biguint.arithmetics.ceil_divide(self, other) except e: - raise Error( - DecimoError( - message="See the above exception.", - function="BigUInt.__ceildiv__(other: Self)", - previous_error=e^, - ) + raise ZeroDivisionError( + message="See the above exception.", + function="BigUInt.__ceildiv__(other: Self)", + previous_error=e^, ) @always_inline @@ -1227,12 +1199,10 @@ struct BigUInt(Absable, Copyable, IntableRaising, Movable, Writable): try: return decimo.biguint.arithmetics.floor_modulo(self, other) except e: - raise Error( - DecimoError( - message="See the above exception.", - function="BigUInt.__mod__(other: Self)", - previous_error=e^, - ) + raise ZeroDivisionError( + message="See the above exception.", + function="BigUInt.__mod__(other: Self)", + previous_error=e^, ) @always_inline @@ -1248,12 +1218,10 @@ struct BigUInt(Absable, Copyable, IntableRaising, Movable, Writable): try: return decimo.biguint.arithmetics.floor_divide_modulo(self, other) except e: - raise Error( - DecimoError( - message="See the above exception.", - function="BigUInt.__divmod__(other: Self)", - previous_error=e^, - ) + raise ValueError( + message="See the above exception.", + function="BigUInt.__divmod__(other: Self)", + previous_error=e^, ) @always_inline @@ -1269,12 +1237,10 @@ struct BigUInt(Absable, Copyable, IntableRaising, Movable, Writable): try: return self.power(exponent) except e: - raise Error( - DecimoError( - message="See the above exception.", - function="BigUInt.__pow__(exponent: Self)", - previous_error=e^, - ) + raise ValueError( + message="See the above exception.", + function="BigUInt.__pow__(exponent: Self)", + previous_error=e^, ) @always_inline @@ -1290,12 +1256,10 @@ struct BigUInt(Absable, Copyable, IntableRaising, Movable, Writable): try: return self.power(exponent) except e: - raise Error( - DecimoError( - message="See the above exception.", - function="BigUInt.__pow__(exponent: Int)", - previous_error=e^, - ) + raise ValueError( + message="See the above exception.", + function="BigUInt.__pow__(exponent: Int)", + previous_error=e^, ) # ===------------------------------------------------------------------=== # @@ -1721,32 +1685,28 @@ struct BigUInt(Absable, Copyable, IntableRaising, Movable, Writable): Error: If the exponent is too large, e.g., larger than 1_000_000_000. """ if exponent < 0: - raise Error( - ValueError( - function="BigUInt.power(exponent: Int)", - message=( - "The exponent " - + String(exponent) - + " is negative.\n" - + "Consider using a non-negative exponent." - ), - ) + raise ValueError( + function="BigUInt.power(exponent: Int)", + message=( + "The exponent " + + String(exponent) + + " is negative.\n" + + "Consider using a non-negative exponent." + ), ) if exponent == 0: return Self(raw_words=[1]) if exponent >= 1_000_000_000: - raise Error( - ValueError( - function="BigUInt.power(exponent: Int)", - message=( - "The exponent " - + String(exponent) - + " is too large.\n" - + "Consider using an exponent below 1_000_000_000." - ), - ) + raise ValueError( + function="BigUInt.power(exponent: Int)", + message=( + "The exponent " + + String(exponent) + + " is too large.\n" + + "Consider using an exponent below 1_000_000_000." + ), ) var result = Self(raw_words=[1]) @@ -1773,16 +1733,14 @@ struct BigUInt(Absable, Copyable, IntableRaising, Movable, Writable): The result of raising this number to the power of `exponent`. """ if len(exponent.words) > 1: - raise Error( - ValueError( - function="BigUInt.power(exponent: BigUInt)", - message=( - "The exponent " - + String(exponent) - + " is too large.\n" - + "Consider using an exponent below 1_000_000_000." - ), - ) + raise ValueError( + function="BigUInt.power(exponent: BigUInt)", + message=( + "The exponent " + + String(exponent) + + " is too large.\n" + + "Consider using an exponent below 1_000_000_000." + ), ) var exponent_as_int = exponent.to_int() return self.power(exponent_as_int) @@ -2062,16 +2020,14 @@ struct BigUInt(Absable, Copyable, IntableRaising, Movable, Writable): IndexError: If the index is negative. """ if i < 0: - raise Error( - IndexError( - function="BigUInt.ith_digit(i: Int)", - message=( - "The index " - + String(i) - + " is negative.\n" - + "Consider using a non-negative index." - ), - ) + raise IndexError( + function="BigUInt.ith_digit(i: Int)", + message=( + "The index " + + String(i) + + " is negative.\n" + + "Consider using a non-negative index." + ), ) if i >= len(self.words) * 9: return 0 @@ -2202,29 +2158,25 @@ struct BigUInt(Absable, Copyable, IntableRaising, Movable, Writable): `remove_extra_digit_due_to_rounding` is True, the result will be 10. """ if ndigits < 0: - raise Error( - ValueError( - function="BigUInt.remove_trailing_digits_with_rounding()", - message=( - "The number of digits to remove is negative: " - + String(ndigits) - ), - ) + raise ValueError( + function="BigUInt.remove_trailing_digits_with_rounding()", + message=( + "The number of digits to remove is negative: " + + String(ndigits) + ), ) if ndigits == 0: return self.copy() if ndigits > self.number_of_digits(): - raise Error( - ValueError( - function="BigUInt.remove_trailing_digits_with_rounding()", - message=( - "The number of digits to remove is larger than the " - "number of digits in the BigUInt: " - + String(ndigits) - + " > " - + String(self.number_of_digits()) - ), - ) + raise ValueError( + function="BigUInt.remove_trailing_digits_with_rounding()", + message=( + "The number of digits to remove is larger than the " + "number of digits in the BigUInt: " + + String(ndigits) + + " > " + + String(self.number_of_digits()) + ), ) # floor_divide_by_power_of_ten is the same as removing the last n digits @@ -2276,11 +2228,9 @@ struct BigUInt(Absable, Copyable, IntableRaising, Movable, Writable): # TODO: Remove this fallback once Mojo has proper enum support, # which will make exhaustive matching a compile-time guarantee. else: - raise Error( - ValueError( - function="BigUInt.remove_trailing_digits_with_rounding()", - message=("Unknown rounding mode: " + String(rounding_mode)), - ) + raise ValueError( + function="BigUInt.remove_trailing_digits_with_rounding()", + message=("Unknown rounding mode: " + String(rounding_mode)), ) if round_up: diff --git a/src/decimo/decimal128/arithmetics.mojo b/src/decimo/decimal128/arithmetics.mojo index 9c0cabaa..f10c784c 100644 --- a/src/decimo/decimal128/arithmetics.mojo +++ b/src/decimo/decimal128/arithmetics.mojo @@ -37,7 +37,6 @@ from std import testing from decimo.decimal128.decimal128 import Decimal128 from decimo.rounding_mode import RoundingMode from decimo.errors import ( - DecimoError, OverflowError, ZeroDivisionError, ) @@ -129,11 +128,9 @@ def add(x1: Decimal128, x2: Decimal128) raises -> Decimal128: # Check for overflow (UInt128 can store values beyond our 96-bit limit) # We need to make sure the sum fits in 96 bits (our Decimal128 capacity) if summation > Decimal128.MAX_AS_UINT128: # 2^96-1 - raise Error( - OverflowError( - message="Decimal128 overflow in addition.", - function="add()", - ) + raise OverflowError( + message="Decimal128 overflow in addition.", + function="add()", ) return Decimal128.from_uint128(summation, 0, x1.is_negative()) @@ -164,11 +161,9 @@ def add(x1: Decimal128, x2: Decimal128) raises -> Decimal128: # Check for overflow (UInt128 can store values beyond our 96-bit limit) # We need to make sure the sum fits in 96 bits (our Decimal128 capacity) if summation > Decimal128.MAX_AS_UINT128: # 2^96-1 - raise Error( - OverflowError( - message="Decimal128 overflow in addition.", - function="add()", - ) + raise OverflowError( + message="Decimal128 overflow in addition.", + function="add()", ) # Determine the scale for the result @@ -389,12 +384,10 @@ def subtract(x1: Decimal128, x2: Decimal128) raises -> Decimal128: try: return x1 + (-x2) except e: - raise Error( - DecimoError( - message="Subtraction failed.", - function="subtract()", - previous_error=e^, - ) + raise OverflowError( + message="Subtraction failed.", + function="subtract()", + previous_error=e^, ) @@ -565,13 +558,11 @@ def multiply(x1: Decimal128, x2: Decimal128) raises -> Decimal128: elif combined_num_bits <= 128: var prod: UInt128 = UInt128(x1_coef) * UInt128(x2_coef) if prod > Decimal128.MAX_AS_UINT128: - raise Error( - OverflowError( - message=String( - "The product {} exceeds Decimal128 capacity." - ).format(prod), - function="multiply()", - ) + raise OverflowError( + message=String( + "The product {} exceeds Decimal128 capacity." + ).format(prod), + function="multiply()", ) else: return Decimal128.from_uint128(prod, 0, is_negative) @@ -579,13 +570,11 @@ def multiply(x1: Decimal128, x2: Decimal128) raises -> Decimal128: # Large integers, it will definitely overflow else: var prod: UInt256 = UInt256(x1_coef) * UInt256(x2_coef) - raise Error( - OverflowError( - message=String( - "The product {} exceeds Decimal128 capacity." - ).format(prod), - function="multiply()", - ) + raise OverflowError( + message=String( + "The product {} exceeds Decimal128 capacity." + ).format(prod), + function="multiply()", ) # SPECIAL CASE: Both operands are integers but with scales @@ -601,11 +590,9 @@ def multiply(x1: Decimal128, x2: Decimal128) raises -> Decimal128: x2_integral_part ) if prod > Decimal128.MAX_AS_UINT256: - raise Error( - OverflowError( - message="Decimal128 overflow in multiplication.", - function="multiply()", - ) + raise OverflowError( + message="Decimal128 overflow in multiplication.", + function="multiply()", ) else: var num_digits = decimo.decimal128.utility.number_of_digits(prod) @@ -698,11 +685,9 @@ def multiply(x1: Decimal128, x2: Decimal128) raises -> Decimal128: if (num_digits_of_integral_part >= Decimal128.MAX_NUM_DIGITS) & ( truncated_prod_at_max_length > Decimal128.MAX_AS_UINT128 ): - raise Error( - OverflowError( - message="Decimal128 overflow in multiplication.", - function="multiply()", - ) + raise OverflowError( + message="Decimal128 overflow in multiplication.", + function="multiply()", ) # Otherwise, the value will not overflow even after rounding @@ -764,11 +749,9 @@ def multiply(x1: Decimal128, x2: Decimal128) raises -> Decimal128: if (num_digits_of_integral_part >= Decimal128.MAX_NUM_DIGITS) & ( truncated_prod_at_max_length > Decimal128.MAX_AS_UINT256 ): - raise Error( - OverflowError( - message="Decimal128 overflow in multiplication.", - function="multiply()", - ) + raise OverflowError( + message="Decimal128 overflow in multiplication.", + function="multiply()", ) # Otherwise, the value will not overflow even after rounding @@ -831,11 +814,9 @@ def divide(x1: Decimal128, x2: Decimal128) raises -> Decimal128: # 特例: 除數爲零 # Check for division by zero if x2.is_zero(): - raise Error( - ZeroDivisionError( - message="Division by zero.", - function="divide()", - ) + raise ZeroDivisionError( + message="Division by zero.", + function="divide()", ) # SPECIAL CASE: zero dividend @@ -893,11 +874,9 @@ def divide(x1: Decimal128, x2: Decimal128) raises -> Decimal128: else: var quot = UInt256(x1_coef) * UInt256(10) ** (-diff_scale) if quot > Decimal128.MAX_AS_UINT256: - raise Error( - OverflowError( - message="Decimal128 overflow in division.", - function="divide()", - ) + raise OverflowError( + message="Decimal128 overflow in division.", + function="divide()", ) else: var low = UInt32(quot & 0xFFFFFFFF) @@ -963,11 +942,9 @@ def divide(x1: Decimal128, x2: Decimal128) raises -> Decimal128: else: var quot = UInt256(quot) * UInt256(10) ** (-diff_scale) if quot > Decimal128.MAX_AS_UINT256: - raise Error( - OverflowError( - message="Decimal128 overflow in division.", - function="divide()", - ) + raise OverflowError( + message="Decimal128 overflow in division.", + function="divide()", ) else: var low = UInt32(quot & 0xFFFFFFFF) @@ -1245,11 +1222,9 @@ def divide(x1: Decimal128, x2: Decimal128) raises -> Decimal128: (ndigits_quot_int_part == Decimal128.MAX_NUM_DIGITS) and (truncated_quot > Decimal128.MAX_AS_UINT256) ): - raise Error( - OverflowError( - message="Decimal128 overflow in division.", - function="divide()", - ) + raise OverflowError( + message="Decimal128 overflow in division.", + function="divide()", ) var scale_of_truncated_quot = ( @@ -1301,12 +1276,10 @@ def truncate_divide(x1: Decimal128, x2: Decimal128) raises -> Decimal128: try: return divide(x1, x2).round(0, RoundingMode.down()) except e: - raise Error( - DecimoError( - message="Division failed.", - function="truncate_divide()", - previous_error=e^, - ) + raise ZeroDivisionError( + message="Division failed.", + function="truncate_divide()", + previous_error=e^, ) @@ -1324,10 +1297,8 @@ def modulo(x1: Decimal128, x2: Decimal128) raises -> Decimal128: try: return x1 - (truncate_divide(x1, x2) * x2) except e: - raise Error( - DecimoError( - message="Modulo failed.", - function="modulo()", - previous_error=e^, - ) + raise ZeroDivisionError( + message="Modulo failed.", + function="modulo()", + previous_error=e^, ) diff --git a/src/decimo/decimal128/constants.mojo b/src/decimo/decimal128/constants.mojo index c634d94e..a8e2cbca 100644 --- a/src/decimo/decimal128/constants.mojo +++ b/src/decimo/decimal128/constants.mojo @@ -462,11 +462,9 @@ def N_DIVIDE_NEXT(n: Int) raises -> Decimal128: # 20/21 = 0.95238095238095238095238095238095... return Decimal128(0x33CF3CF4, 0xCD78948D, 0x1EC5E91C, 0x1C0000) else: - raise Error( - ValueError( - message="n must be between 1 and 20, inclusive.", - function="N_DIVIDE_NEXT()", - ) + raise ValueError( + message="n must be between 1 and 20, inclusive.", + function="N_DIVIDE_NEXT()", ) diff --git a/src/decimo/decimal128/decimal128.mojo b/src/decimo/decimal128/decimal128.mojo index 168d907d..5154693f 100644 --- a/src/decimo/decimal128/decimal128.mojo +++ b/src/decimo/decimal128/decimal128.mojo @@ -33,7 +33,6 @@ import decimo.decimal128.exponential import decimo.decimal128.rounding from decimo.rounding_mode import RoundingMode from decimo.errors import ( - DecimoError, ValueError, OverflowError, ConversionError, @@ -297,12 +296,10 @@ struct Decimal128( try: self = Decimal128.from_components(low, mid, high, scale, sign) except e: - raise Error( - DecimoError( - message="Cannot initialize with five components.", - function="Decimal128.__init__()", - previous_error=e^, - ) + raise ConversionError( + message="Cannot initialize with five components.", + function="Decimal128.__init__()", + previous_error=e^, ) def __init__(out self, value: Int): @@ -325,12 +322,10 @@ struct Decimal128( try: self = Decimal128.from_int(value, scale) except e: - raise Error( - ConversionError( - message="Cannot initialize Decimal128 from Int.", - function="Decimal128.__init__()", - previous_error=e^, - ) + raise ConversionError( + message="Cannot initialize Decimal128 from Int.", + function="Decimal128.__init__()", + previous_error=e^, ) def __init__(out self, value: String) raises: @@ -343,12 +338,10 @@ struct Decimal128( try: self = Decimal128.from_string(value) except e: - raise Error( - ConversionError( - message="Cannot initialize Decimal128 from String.", - function="Decimal128.__init__()", - previous_error=e^, - ) + raise ConversionError( + message="Cannot initialize Decimal128 from String.", + function="Decimal128.__init__()", + previous_error=e^, ) def __init__(out self, value: Float64) raises: @@ -362,12 +355,10 @@ struct Decimal128( try: self = Decimal128.from_float(value) except e: - raise Error( - ConversionError( - message="Cannot initialize Decimal128 from Float64.", - function="Decimal128.__init__()", - previous_error=e^, - ) + raise ConversionError( + message="Cannot initialize Decimal128 from Float64.", + function="Decimal128.__init__()", + previous_error=e^, ) # ===------------------------------------------------------------------=== # @@ -399,13 +390,11 @@ struct Decimal128( """ if scale > UInt32(Self.MAX_SCALE): - raise Error( - ValueError( - message=String( - "Scale must be between 0 and 28, but got {}." - ).format(scale), - function="Decimal128.from_components()", - ) + raise ValueError( + message=String( + "Scale must be between 0 and 28, but got {}." + ).format(scale), + function="Decimal128.from_components()", ) var flags: UInt32 = 0 @@ -525,13 +514,11 @@ struct Decimal128( var flags: UInt32 if scale > UInt32(Self.MAX_SCALE): - raise Error( - ValueError( - message=String( - "Scale must be between 0 and 28, but got {}" - ).format(scale), - function="Decimal128.from_int()", - ) + raise ValueError( + message=String( + "Scale must be between 0 and 28, but got {}" + ).format(scale), + function="Decimal128.from_int()", ) if value >= 0: @@ -569,23 +556,19 @@ struct Decimal128( """ if value >> 96 != 0: - raise Error( - ValueError( - message=String( - "Value must fit in 96 bits, but got {}" - ).format(value), - function="Decimal128.from_uint128()", - ) + raise ValueError( + message=String("Value must fit in 96 bits, but got {}").format( + value + ), + function="Decimal128.from_uint128()", ) if scale > UInt32(Self.MAX_SCALE): - raise Error( - ValueError( - message=String( - "Scale must be between 0 and 28, but got {}" - ).format(scale), - function="Decimal128.from_uint128()", - ) + raise ValueError( + message=String( + "Scale must be between 0 and 28, but got {}" + ).format(scale), + function="Decimal128.from_uint128()", ) var result = UnsafePointer(to=value).bitcast[Decimal128]()[] @@ -632,13 +615,11 @@ struct Decimal128( # Check for non-ASCII characters (each non-ASCII char is multi-byte) for byte in value_bytes: if byte > 127: - raise Error( - ValueError( - message=String( - "Invalid characters in decimal128 string: {}" - ).format(value), - function="Decimal128.from_string()", - ) + raise ValueError( + message=String( + "Invalid characters in decimal128 string: {}" + ).format(value), + function="Decimal128.from_string()", ) # Yuhao's notes: @@ -670,26 +651,19 @@ struct Decimal128( elif code == 45: unexpected_end_char = True if exponent_sign_read: - raise Error( - ValueError( - message=( - "Minus sign cannot appear twice in exponent." - ), - function="Decimal128.from_string()", - ) + raise ValueError( + message="Minus sign cannot appear twice in exponent.", + function="Decimal128.from_string()", ) elif exponent_notation_read: exponent_sign = True exponent_sign_read = True elif mantissa_sign_read: - raise Error( - ValueError( - message=( - "Minus sign can only appear once at the" - " beginning." - ), - function="Decimal128.from_string()", - ) + raise ValueError( + message=( + "Minus sign can only appear once at the beginning." + ), + function="Decimal128.from_string()", ) else: mantissa_sign = True @@ -698,25 +672,18 @@ struct Decimal128( elif code == 43: unexpected_end_char = True if exponent_sign_read: - raise Error( - ValueError( - message=( - "Plus sign cannot appear twice in exponent." - ), - function="Decimal128.from_string()", - ) + raise ValueError( + message="Plus sign cannot appear twice in exponent.", + function="Decimal128.from_string()", ) elif exponent_notation_read: exponent_sign_read = True elif mantissa_sign_read: - raise Error( - ValueError( - message=( - "Plus sign can only appear once at the" - " beginning." - ), - function="Decimal128.from_string()", - ) + raise ValueError( + message=( + "Plus sign can only appear once at the beginning." + ), + function="Decimal128.from_string()", ) else: mantissa_sign_read = True @@ -724,11 +691,9 @@ struct Decimal128( elif code == 46: unexpected_end_char = False if decimal_point_read: - raise Error( - ValueError( - message="Decimal point can only appear once.", - function="Decimal128.from_string()", - ) + raise ValueError( + message="Decimal point can only appear once.", + function="Decimal128.from_string()", ) else: decimal_point_read = True @@ -737,22 +702,14 @@ struct Decimal128( elif code == 101 or code == 69: unexpected_end_char = True if exponent_notation_read: - raise Error( - ValueError( - message=( - "Exponential notation can only appear once." - ), - function="Decimal128.from_string()", - ) + raise ValueError( + message="Exponential notation can only appear once.", + function="Decimal128.from_string()", ) if not mantissa_start: - raise Error( - ValueError( - message=( - "Exponential notation must follow a number." - ), - function="Decimal128.from_string()", - ) + raise ValueError( + message="Exponential notation must follow a number.", + function="Decimal128.from_string()", ) else: exponent_notation_read = True @@ -794,13 +751,11 @@ struct Decimal128( if (not exponent_sign) and ( raw_exponent > Decimal128.MAX_NUM_DIGITS * 2 ): - raise Error( - OverflowError( - message=String( - "Exponent part is too large: {}" - ).format(raw_exponent), - function="Decimal128.from_string()", - ) + raise OverflowError( + message=String( + "Exponent part is too large: {}" + ).format(raw_exponent), + function="Decimal128.from_string()", ) # Skip the digit if exponent is negatively too large @@ -831,21 +786,17 @@ struct Decimal128( scale += 1 else: - raise Error( - ValueError( - message=String( - "Invalid character in decimal128 string: {}" - ).format(chr(Int(code))), - function="Decimal128.from_string()", - ) + raise ValueError( + message=String( + "Invalid character in decimal128 string: {}" + ).format(chr(Int(code))), + function="Decimal128.from_string()", ) if unexpected_end_char: - raise Error( - ValueError( - message="Unexpected end character in decimal128 string.", - function="Decimal128.from_string()", - ) + raise ValueError( + message="Unexpected end character in decimal128 string.", + function="Decimal128.from_string()", ) # print("DEBUG: coef = ", coef) @@ -967,14 +918,12 @@ struct Decimal128( # Early exit if the value is too large if UInt128(abs_value) > Decimal128.MAX_AS_UINT128: - raise Error( - OverflowError( - message=String( - "The float value {} is too large (>=2^96) to be" - " transformed into Decimal128." - ).format(value), - function="Decimal128.from_float()", - ) + raise OverflowError( + message=String( + "The float value {} is too large (>=2^96) to be" + " transformed into Decimal128." + ).format(value), + function="Decimal128.from_float()", ) # Extract binary exponent using IEEE 754 bit manipulation @@ -989,11 +938,9 @@ struct Decimal128( # CASE: Infinity or NaN if biased_exponent == 0x7FF: - raise Error( - ValueError( - message="Cannot convert infinity or NaN to Decimal128.", - function="Decimal128.from_float()", - ) + raise ValueError( + message="Cannot convert infinity or NaN to Decimal128.", + function="Decimal128.from_float()", ) # Get unbias exponent @@ -1175,12 +1122,10 @@ struct Decimal128( try: return Int(self.to_int64()) except e: - raise Error( - ConversionError( - message="Cannot convert Decimal128 to Int.", - function="Decimal128.to_int()", - previous_error=e^, - ) + raise ConversionError( + message="Cannot convert Decimal128 to Int.", + function="Decimal128.to_int()", + previous_error=e^, ) def to_int64(self) raises -> Int64: @@ -1196,19 +1141,15 @@ struct Decimal128( var result = self.to_int128() if result > Int128(Int64.MAX): - raise Error( - OverflowError( - message="Decimal128 is too large to fit in Int64.", - function="Decimal128.to_int64()", - ) + raise OverflowError( + message="Decimal128 is too large to fit in Int64.", + function="Decimal128.to_int64()", ) if result < Int128(Int64.MIN): - raise Error( - OverflowError( - message="Decimal128 is too small to fit in Int64.", - function="Decimal128.to_int64()", - ) + raise OverflowError( + message="Decimal128 is too small to fit in Int64.", + function="Decimal128.to_int64()", ) return Int64(result & 0xFFFF_FFFF_FFFF_FFFF) @@ -2064,13 +2005,9 @@ struct Decimal128( End of examples. """ if precision_diff < 0: - raise Error( - ValueError( - message=( - "precision_diff must be greater than or equal to 0." - ), - function="Decimal128.extend_precision()", - ) + raise ValueError( + message="precision_diff must be greater than or equal to 0.", + function="Decimal128.extend_precision()", ) if precision_diff == 0: diff --git a/src/decimo/decimal128/exponential.mojo b/src/decimo/decimal128/exponential.mojo index f95e890d..8aa145da 100644 --- a/src/decimo/decimal128/exponential.mojo +++ b/src/decimo/decimal128/exponential.mojo @@ -20,7 +20,7 @@ import std.math from std import testing from std import time -from decimo.errors import DecimoError, ValueError, OverflowError +from decimo.errors import ValueError, OverflowError, ZeroDivisionError import decimo.decimal128.constants import decimo.decimal128.special import decimo.decimal128.utility @@ -56,24 +56,20 @@ def power(base: Decimal128, exponent: Decimal128) raises -> Decimal128: try: return power(base, Int(exponent)) except e: - raise Error( - DecimoError( - message="Failed to compute power with Decimal128 exponent.", - function="power()", - previous_error=e^, - ) + raise ValueError( + message="Failed to compute power with Decimal128 exponent.", + function="power()", + previous_error=e^, ) # CASE: For negative bases, only integer exponents are supported if base.is_negative(): - raise Error( - ValueError( - message=( - "Negative base with non-integer exponent results in a" - " complex number." - ), - function="power()", - ) + raise ValueError( + message=( + "Negative base with non-integer exponent results in a" + " complex number." + ), + function="power()", ) # CASE: If the exponent is simple fractions @@ -82,24 +78,20 @@ def power(base: Decimal128, exponent: Decimal128) raises -> Decimal128: try: return sqrt(base) except e: - raise Error( - DecimoError( - message="See the above exception.", - function="power()", - previous_error=e^, - ) + raise ValueError( + message="See the above exception.", + function="power()", + previous_error=e^, ) # -0.5 if exponent == Decimal128(5, 0, 0, 0x80010000): try: return Decimal128.ONE() / sqrt(base) except e: - raise Error( - DecimoError( - message="See the above exception.", - function="power()", - previous_error=e^, - ) + raise ZeroDivisionError( + message="See the above exception.", + function="power()", + previous_error=e^, ) # GENERAL CASE @@ -109,12 +101,10 @@ def power(base: Decimal128, exponent: Decimal128) raises -> Decimal128: var product = exponent * ln_base return exp(product) except e: - raise Error( - DecimoError( - message="See the above exception.", - function="power()", - previous_error=e^, - ) + raise ValueError( + message="See the above exception.", + function="power()", + previous_error=e^, ) @@ -144,11 +134,9 @@ def power(base: Decimal128, exponent: Int) raises -> Decimal128: return Decimal128.ZERO() else: # 0^n is undefined for n < 0 - raise Error( - ValueError( - message="Zero cannot be raised to a negative power.", - function="power()", - ) + raise ValueError( + message="Zero cannot be raised to a negative power.", + function="power()", ) if base.coefficient() == 1 and base.scale() == 0: @@ -200,11 +188,9 @@ def root(x: Decimal128, n: Int) raises -> Decimal128: # Special cases for n if n <= 0: - raise Error( - ValueError( - message="Cannot compute non-positive root.", - function="root()", - ) + raise ValueError( + message="Cannot compute non-positive root.", + function="root()", ) if n == 1: return x @@ -218,11 +204,9 @@ def root(x: Decimal128, n: Int) raises -> Decimal128: return Decimal128.ONE() if x.is_negative(): if n % 2 == 0: - raise Error( - ValueError( - message="Cannot compute even root of a negative number.", - function="root()", - ) + raise ValueError( + message="Cannot compute even root of a negative number.", + function="root()", ) # For odd roots of negative numbers, compute |x|^(1/n) and negate return -root(-x, n) @@ -235,12 +219,10 @@ def root(x: Decimal128, n: Int) raises -> Decimal128: # Direct calculation: x^n = e^(ln(x)/n) return exp(ln(x) / Decimal128(n)) except e: - raise Error( - DecimoError( - message="Root computation failed.", - function="root()", - previous_error=e^, - ) + raise ValueError( + message="Root computation failed.", + function="root()", + previous_error=e^, ) # Initial guess @@ -382,11 +364,9 @@ def sqrt(x: Decimal128) raises -> Decimal128: """ # Special cases if x.is_negative(): - raise Error( - ValueError( - message="Cannot compute square root of a negative number.", - function="sqrt()", - ) + raise ValueError( + message="Cannot compute square root of a negative number.", + function="sqrt()", ) if x.is_zero(): @@ -514,14 +494,12 @@ def exp(x: Decimal128) raises -> Decimal128: """ if x > Decimal128.from_int(value=6654, scale=UInt32(2)): - raise Error( - OverflowError( - message=( - "x is too large (must be <= 66.54). Consider using" - " BigDecimal type." - ), - function="exp()", - ) + raise OverflowError( + message=( + "x is too large (must be <= 66.54). Consider using" + " BigDecimal type." + ), + function="exp()", ) # Handle special cases @@ -728,11 +706,9 @@ def ln(x: Decimal128) raises -> Decimal128: # Handle special cases if x.is_negative() or x.is_zero(): - raise Error( - ValueError( - message="Cannot compute logarithm of a non-positive number.", - function="ln()", - ) + raise ValueError( + message="Cannot compute logarithm of a non-positive number.", + function="ln()", ) if x.is_one(): @@ -994,29 +970,23 @@ def log(x: Decimal128, base: Decimal128) raises -> Decimal128: """ # Special cases: x <= 0 if x.is_negative() or x.is_zero(): - raise Error( - ValueError( - message="Cannot compute logarithm of a non-positive number.", - function="log()", - ) + raise ValueError( + message="Cannot compute logarithm of a non-positive number.", + function="log()", ) # Special cases: base <= 0 if base.is_negative() or base.is_zero(): - raise Error( - ValueError( - message="Cannot use non-positive base for logarithm.", - function="log()", - ) + raise ValueError( + message="Cannot use non-positive base for logarithm.", + function="log()", ) # Special case: base = 1 if base.is_one(): - raise Error( - ValueError( - message="Cannot use base 1 for logarithm.", - function="log()", - ) + raise ValueError( + message="Cannot use base 1 for logarithm.", + function="log()", ) # Special case: x = 1 @@ -1057,11 +1027,9 @@ def log10(x: Decimal128) raises -> Decimal128: """ # Special cases: x <= 0 if x.is_negative() or x.is_zero(): - raise Error( - ValueError( - message="Cannot compute logarithm of a non-positive number.", - function="log10()", - ) + raise ValueError( + message="Cannot compute logarithm of a non-positive number.", + function="log10()", ) var x_scale = x.scale() diff --git a/src/decimo/decimal128/rounding.mojo b/src/decimo/decimal128/rounding.mojo index 4ed4cba7..61a5dba1 100644 --- a/src/decimo/decimal128/rounding.mojo +++ b/src/decimo/decimal128/rounding.mojo @@ -95,18 +95,16 @@ def round( if scale_diff > 0: # If the digits of result > 29, directly raise an error if ndigits_of_x + scale_diff > Decimal128.MAX_NUM_DIGITS: - raise Error( - OverflowError( - message=String( - "ndigits={} causes the number of significant figures" - " ({}) to exceed the maximum capacity ({})." - ).format( - ndigits, - ndigits_of_x + scale_diff, - Decimal128.MAX_NUM_DIGITS, - ), - function="round()", - ) + raise OverflowError( + message=String( + "ndigits={} causes the number of significant figures" + " ({}) to exceed the maximum capacity ({})." + ).format( + ndigits, + ndigits_of_x + scale_diff, + Decimal128.MAX_NUM_DIGITS, + ), + function="round()", ) # If the digits of result <= 29, calculate the result by scaling up @@ -117,14 +115,12 @@ def round( if (ndigits_of_x + scale_diff == Decimal128.MAX_NUM_DIGITS) and ( res_coef > Decimal128.MAX_AS_UINT128 ): - raise Error( - OverflowError( - message=String( - "ndigits={} causes the significant digits ({})" - " to exceed the maximum capacity ({})." - ).format(ndigits, res_coef, Decimal128.MAX_AS_UINT128), - function="round()", - ) + raise OverflowError( + message=String( + "ndigits={} causes the significant digits ({})" + " to exceed the maximum capacity ({})." + ).format(ndigits, res_coef, Decimal128.MAX_AS_UINT128), + function="round()", ) # In other cases, return the result diff --git a/src/decimo/decimal128/special.mojo b/src/decimo/decimal128/special.mojo index 8a7c6675..0c6556bf 100644 --- a/src/decimo/decimal128/special.mojo +++ b/src/decimo/decimal128/special.mojo @@ -39,21 +39,17 @@ def factorial(n: Int) raises -> Decimal128: """ if n < 0: - raise Error( - ValueError( - message="Factorial is not defined for negative numbers.", - function="factorial()", - ) + raise ValueError( + message="Factorial is not defined for negative numbers.", + function="factorial()", ) if n > 27: - raise Error( - OverflowError( - message=String( - "{}! is too large to be represented by Decimal128." - ).format(n), - function="factorial()", - ) + raise OverflowError( + message=String( + "{}! is too large to be represented by Decimal128." + ).format(n), + function="factorial()", ) # Directly return the factorial for n = 0 to 27 @@ -178,13 +174,9 @@ def factorial_reciprocal(n: Int) raises -> Decimal128: # 1/27! = 0.0000000000000000000000000001, Decimal128.from_words(0x1, 0x0, 0x0, 0x1c0000) if n < 0: - raise Error( - ValueError( - message=( - "Factorial reciprocal is not defined for negative numbers." - ), - function="factorial_reciprocal()", - ) + raise ValueError( + message="Factorial reciprocal is not defined for negative numbers.", + function="factorial_reciprocal()", ) # For n > 27, 1/n! is essentially 0 at Decimal128 precision diff --git a/src/decimo/errors.mojo b/src/decimo/errors.mojo index 8fed6a83..0ba4c596 100644 --- a/src/decimo/errors.mojo +++ b/src/decimo/errors.mojo @@ -75,6 +75,10 @@ comptime ZeroDivisionError = DecimoError[error_type="ZeroDivisionError"] comptime ConversionError = DecimoError[error_type="ConversionError"] """Type for conversion errors in Decimo.""" +comptime RuntimeError = DecimoError[error_type="RuntimeError"] +"""Type for runtime infrastructure errors in Decimo (e.g., resource allocation +failures, missing native libraries).""" + struct DecimoError[error_type: StringLiteral = "DecimoError"](Writable): """Base type for all Decimo errors. diff --git a/src/decimo/str.mojo b/src/decimo/str.mojo index 877ef6c3..a00a3421 100644 --- a/src/decimo/str.mojo +++ b/src/decimo/str.mojo @@ -126,11 +126,9 @@ def parse_numeric_string( var n = len(value_bytes) if n == 0: - raise Error( - ValueError( - message="Empty string.", - function="parse_numeric_string()", - ) + raise ValueError( + message="Empty string.", + function="parse_numeric_string()", ) var ptr = value_bytes.unsafe_ptr() @@ -195,20 +193,14 @@ def parse_numeric_string( elif c == 46: last_was_separator = False if in_exponent: - raise Error( - ValueError( - message=( - "Decimal point cannot appear in the exponent part." - ), - function="parse_numeric_string()", - ) + raise ValueError( + message="Decimal point cannot appear in the exponent part.", + function="parse_numeric_string()", ) if decimal_point_pos != -1: - raise Error( - ValueError( - message="Decimal point can only appear once.", - function="parse_numeric_string()", - ) + raise ValueError( + message="Decimal point can only appear once.", + function="parse_numeric_string()", ) decimal_point_pos = i sign_read = True @@ -217,18 +209,14 @@ def parse_numeric_string( elif c == 101 or c == 69: last_was_separator = True if in_exponent: - raise Error( - ValueError( - message="Exponential notation can only appear once.", - function="parse_numeric_string()", - ) + raise ValueError( + message="Exponential notation can only appear once.", + function="parse_numeric_string()", ) if total_mantissa_digits == 0: - raise Error( - ValueError( - message="Exponential notation must follow a number.", - function="parse_numeric_string()", - ) + raise ValueError( + message="Exponential notation must follow a number.", + function="parse_numeric_string()", ) exponent_pos = i in_exponent = True @@ -238,26 +226,21 @@ def parse_numeric_string( last_was_separator = True if in_exponent: if exponent_sign_read: - raise Error( - ValueError( - message=( - "Exponent sign can only appear once," - " before exponent digits." - ), - function="parse_numeric_string()", - ) + raise ValueError( + message=( + "Exponent sign can only appear once," + " before exponent digits." + ), + function="parse_numeric_string()", ) exponent_sign_read = True else: if sign_read: - raise Error( - ValueError( - message=( - "Minus sign can only appear once at the" - " beginning." - ), - function="parse_numeric_string()", - ) + raise ValueError( + message=( + "Minus sign can only appear once at the beginning." + ), + function="parse_numeric_string()", ) sign = True sign_read = True @@ -267,53 +250,42 @@ def parse_numeric_string( last_was_separator = True if in_exponent: if exponent_sign_read: - raise Error( - ValueError( - message=( - "Exponent sign can only appear once," - " before exponent digits." - ), - function="parse_numeric_string()", - ) + raise ValueError( + message=( + "Exponent sign can only appear once," + " before exponent digits." + ), + function="parse_numeric_string()", ) exponent_sign_read = True else: if sign_read: - raise Error( - ValueError( - message=( - "Plus sign can only appear once at the" - " beginning." - ), - function="parse_numeric_string()", - ) + raise ValueError( + message=( + "Plus sign can only appear once at the beginning." + ), + function="parse_numeric_string()", ) sign_read = True else: - raise Error( - ValueError( - message=String( - "Invalid character in the string of the number: {}" - ).format(chr(Int(c))), - function="parse_numeric_string()", - ) + raise ValueError( + message=String( + "Invalid character in the string of the number: {}" + ).format(chr(Int(c))), + function="parse_numeric_string()", ) if last_was_separator: - raise Error( - ValueError( - message="Unexpected end character in the string of the number.", - function="parse_numeric_string()", - ) + raise ValueError( + message="Unexpected end character in the string of the number.", + function="parse_numeric_string()", ) if total_mantissa_digits == 0: - raise Error( - ValueError( - message="No digits found in the string of the number.", - function="parse_numeric_string()", - ) + raise ValueError( + message="No digits found in the string of the number.", + function="parse_numeric_string()", ) # ================================================================== diff --git a/src/decimo/tests.mojo b/src/decimo/tests.mojo index 3258e5f1..7dc17478 100644 --- a/src/decimo/tests.mojo +++ b/src/decimo/tests.mojo @@ -52,7 +52,7 @@ Pattern expansion in string values: from .toml import parse_file as parse_toml_file from .toml.parser import TOMLDocument -from .errors import DecimoError +from .errors import ValueError from std.python import Python, PythonObject from std.collections import List from std import os @@ -303,12 +303,10 @@ def parse_file(file_path: String) raises -> TOMLDocument: try: return parse_toml_file(file_path) except e: - raise Error( - DecimoError( - message="Failed to parse TOML file: " + file_path, - function="parse_file()", - previous_error=e^, - ) + raise ValueError( + message="Failed to parse TOML file: " + file_path, + function="parse_file()", + previous_error=e^, ) diff --git a/src/decimo/toml/parser.mojo b/src/decimo/toml/parser.mojo index 27f2e14e..5bc99c1c 100644 --- a/src/decimo/toml/parser.mojo +++ b/src/decimo/toml/parser.mojo @@ -472,20 +472,15 @@ def _set_value( var existing = root[key].table_values.copy() for entry in value.table_values.items(): if entry.key in existing: - raise Error( - ValueError( - message="Duplicate key: " - + key - + "." - + entry.key, - function="parse()", - ) + raise ValueError( + message="Duplicate key: " + key + "." + entry.key, + function="parse()", ) existing[entry.key] = entry.value.copy() root[key] = _make_table(existing^) return - raise Error( - ValueError(message="Duplicate key: " + key, function="parse()") + raise ValueError( + message="Duplicate key: " + key, function="parse()" ) root[key] = value^ return @@ -507,11 +502,9 @@ def _set_value( arr[len(arr) - 1] = _make_table(last_tbl^) root[first].array_values = arr^ return - raise Error( - ValueError( - message="Key exists but is not a table: " + first, - function="parse()", - ) + raise ValueError( + message="Key exists but is not a table: " + first, + function="parse()", ) var table = root[first].table_values.copy() @@ -549,11 +542,9 @@ def _ensure_table_path( root[first].array_values = arr^ return elif root[first].type != TOMLValueType.TABLE: - raise Error( - ValueError( - message="Key exists but is not a table: " + first, - function="parse()", - ) + raise ValueError( + message="Key exists but is not a table: " + first, + function="parse()", ) if len(path) > 1: @@ -574,11 +565,9 @@ def _append_array_of_tables( ) raises: """Append a new empty table to the array-of-tables at `path`.""" if len(path) == 0: - raise Error( - ValueError( - message="Array of tables path cannot be empty", - function="parse()", - ) + raise ValueError( + message="Array of tables path cannot be empty", + function="parse()", ) if len(path) == 1: @@ -595,11 +584,9 @@ def _append_array_of_tables( _make_table(Dict[String, TOMLValue]()) ) else: - raise Error( - ValueError( - message="Cannot redefine as array of tables: " + key, - function="parse()", - ) + raise ValueError( + message="Cannot redefine as array of tables: " + key, + function="parse()", ) return @@ -627,11 +614,9 @@ def _append_array_of_tables( arr[len(arr) - 1] = _make_table(last_tbl^) root[first].array_values = arr^ else: - raise Error( - ValueError( - message="Key exists but is not a table or array: " + first, - function="parse()", - ) + raise ValueError( + message="Key exists but is not a table or array: " + first, + function="parse()", ) @@ -705,7 +690,7 @@ struct TOMLParser: var parts = List[String]() if not self._is_key_token(): - raise Error(ValueError(message="Expected key", function="parse()")) + raise ValueError(message="Expected key", function="parse()") parts.append(self._tok().value) self._advance() @@ -714,10 +699,8 @@ struct TOMLParser: while self._tok().type == TokenType.DOT: self._advance() # skip dot if not self._is_key_token(): - raise Error( - ValueError( - message="Expected key after dot", function="parse()" - ) + raise ValueError( + message="Expected key after dot", function="parse()" ) parts.append(self._tok().value) self._advance() @@ -856,11 +839,9 @@ struct TOMLParser: # Expect equals if self._tok().type != TokenType.EQUAL: - raise Error( - ValueError( - message="Expected '=' in inline table", - function="parse()", - ) + raise ValueError( + message="Expected '=' in inline table", + function="parse()", ) self._advance() @@ -870,12 +851,10 @@ struct TOMLParser: # Set value at potentially nested path if len(key_parts) == 1: if key_parts[0] in table: - raise Error( - ValueError( - message="Duplicate key in inline table: " - + key_parts[0], - function="TOMLParser._parse_inline_table()", - ) + raise ValueError( + message="Duplicate key in inline table: " + + key_parts[0], + function="TOMLParser._parse_inline_table()", ) table[key_parts[0]] = value^ else: @@ -893,11 +872,9 @@ struct TOMLParser: self._advance() break else: - raise Error( - ValueError( - message="Expected ',' or '}' in inline table", - function="parse()", - ) + raise ValueError( + message="Expected ',' or '}' in inline table", + function="parse()", ) return _make_table(table^) @@ -912,11 +889,9 @@ struct TOMLParser: if self._tok().type == TokenType.ARRAY_END: self._advance() else: - raise Error( - ValueError( - message="Expected ']' after table header", - function="parse()", - ) + raise ValueError( + message="Expected ']' after table header", + function="parse()", ) return path^ @@ -929,20 +904,16 @@ struct TOMLParser: if self._tok().type == TokenType.ARRAY_END: self._advance() else: - raise Error( - ValueError( - message="Expected ']]' after array of tables header", - function="parse()", - ) + raise ValueError( + message="Expected ']]' after array of tables header", + function="parse()", ) if self._tok().type == TokenType.ARRAY_END: self._advance() else: - raise Error( - ValueError( - message="Expected ']]' after array of tables header", - function="parse()", - ) + raise ValueError( + message="Expected ']]' after array of tables header", + function="parse()", ) return path^ From 9e1d63788ab35ff65e625d1c67dc59db3e0bbfe3 Mon Sep 17 00:00:00 2001 From: ZHU Yuhao Date: Thu, 9 Apr 2026 22:07:26 +0200 Subject: [PATCH 3/3] Fix comments --- docs/plans/gmp_integration.md | 2 +- src/decimo/biguint/arithmetics.mojo | 10 +++------- src/decimo/biguint/biguint.mojo | 12 ++---------- src/decimo/decimal128/arithmetics.mojo | 12 ++---------- src/decimo/decimal128/exponential.mojo | 12 ++---------- 5 files changed, 10 insertions(+), 38 deletions(-) diff --git a/docs/plans/gmp_integration.md b/docs/plans/gmp_integration.md index 37af4251..a0c32452 100644 --- a/docs/plans/gmp_integration.md +++ b/docs/plans/gmp_integration.md @@ -1321,7 +1321,7 @@ LD_LIBRARY_PATH=./src/decimo/gmp ./myprogram ```bash bash src/decimo/gmp/build_gmp_wrapper.sh \ -&& mojo build -I src \ +&& pixi run mojo build -I src \ -Xlinker -L./src/decimo/gmp -Xlinker -ldecimo_gmp_wrapper \ -o /tmp/myprogram myprogram.mojo \ && DYLD_LIBRARY_PATH=./src/decimo/gmp /tmp/myprogram diff --git a/src/decimo/biguint/arithmetics.mojo b/src/decimo/biguint/arithmetics.mojo index ecec0e42..9005502a 100644 --- a/src/decimo/biguint/arithmetics.mojo +++ b/src/decimo/biguint/arithmetics.mojo @@ -3348,16 +3348,12 @@ def truncate_modulo(x1: BigUInt, x2: BigUInt) raises -> BigUInt: The remainder of x1 being divided by x2. Raises: - Error: If `floor_modulo()` raises an OverflowError. + ZeroDivisionError: If the divisor is zero. """ try: return floor_modulo(x1, x2) except e: - raise ZeroDivisionError( - message="See the above exception.", - function="truncate_modulo()", - previous_error=e^, - ) + raise e^ def ceil_modulo(x1: BigUInt, x2: BigUInt) raises -> BigUInt: @@ -3373,7 +3369,7 @@ def ceil_modulo(x1: BigUInt, x2: BigUInt) raises -> BigUInt: The remainder of x1 being ceil-divided by x2. Raises: - ValueError: If the divisor is zero. + ZeroDivisionError: If the divisor is zero. """ # CASE: Division by zero if x2.is_zero(): diff --git a/src/decimo/biguint/biguint.mojo b/src/decimo/biguint/biguint.mojo index bb924d81..d74c3ee1 100644 --- a/src/decimo/biguint/biguint.mojo +++ b/src/decimo/biguint/biguint.mojo @@ -1130,11 +1130,7 @@ struct BigUInt(Absable, Copyable, IntableRaising, Movable, Writable): try: return decimo.biguint.arithmetics.subtract(self, other) except e: - raise ZeroDivisionError( - message="See the above exception.", - function="BigUInt.__sub__(other: Self)", - previous_error=e^, - ) + raise e^ @always_inline def __mul__(self, other: Self) -> Self: @@ -1218,11 +1214,7 @@ struct BigUInt(Absable, Copyable, IntableRaising, Movable, Writable): try: return decimo.biguint.arithmetics.floor_divide_modulo(self, other) except e: - raise ValueError( - message="See the above exception.", - function="BigUInt.__divmod__(other: Self)", - previous_error=e^, - ) + raise e^ @always_inline def __pow__(self, exponent: Self) raises -> Self: diff --git a/src/decimo/decimal128/arithmetics.mojo b/src/decimo/decimal128/arithmetics.mojo index f10c784c..de3e2fb3 100644 --- a/src/decimo/decimal128/arithmetics.mojo +++ b/src/decimo/decimal128/arithmetics.mojo @@ -1276,11 +1276,7 @@ def truncate_divide(x1: Decimal128, x2: Decimal128) raises -> Decimal128: try: return divide(x1, x2).round(0, RoundingMode.down()) except e: - raise ZeroDivisionError( - message="Division failed.", - function="truncate_divide()", - previous_error=e^, - ) + raise e^ def modulo(x1: Decimal128, x2: Decimal128) raises -> Decimal128: @@ -1297,8 +1293,4 @@ def modulo(x1: Decimal128, x2: Decimal128) raises -> Decimal128: try: return x1 - (truncate_divide(x1, x2) * x2) except e: - raise ZeroDivisionError( - message="Modulo failed.", - function="modulo()", - previous_error=e^, - ) + raise e^ diff --git a/src/decimo/decimal128/exponential.mojo b/src/decimo/decimal128/exponential.mojo index 8aa145da..a8dbf482 100644 --- a/src/decimo/decimal128/exponential.mojo +++ b/src/decimo/decimal128/exponential.mojo @@ -56,11 +56,7 @@ def power(base: Decimal128, exponent: Decimal128) raises -> Decimal128: try: return power(base, Int(exponent)) except e: - raise ValueError( - message="Failed to compute power with Decimal128 exponent.", - function="power()", - previous_error=e^, - ) + raise e^ # CASE: For negative bases, only integer exponents are supported if base.is_negative(): @@ -101,11 +97,7 @@ def power(base: Decimal128, exponent: Decimal128) raises -> Decimal128: var product = exponent * ln_base return exp(product) except e: - raise ValueError( - message="See the above exception.", - function="power()", - previous_error=e^, - ) + raise e^ def power(base: Decimal128, exponent: Int) raises -> Decimal128: