Skip to content

Commit 0c77112

Browse files
authored
[integer][decimal] Improve error messages and remove unnecessary raises (#92)
Improve error messages and remove unnecessary `raises`.
1 parent 60a597d commit 0c77112

File tree

5 files changed

+75
-18
lines changed

5 files changed

+75
-18
lines changed

src/decimojo/bigdecimal/arithmetics.mojo

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ fn subtract(x1: BigDecimal, x2: BigDecimal) raises -> BigDecimal:
162162
return BigDecimal(coefficient=BigUInt.ZERO, scale=max_scale, sign=False)
163163

164164

165-
fn multiply(x1: BigDecimal, x2: BigDecimal) raises -> BigDecimal:
165+
fn multiply(x1: BigDecimal, x2: BigDecimal) -> BigDecimal:
166166
"""Returns the product of two numbers.
167167
168168
Args:

src/decimojo/bigdecimal/bigdecimal.mojo

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,13 +122,27 @@ struct BigDecimal(
122122
self = Self.from_uint(value)
123123

124124
@implicit
125-
fn __init__(out self, value: Scalar):
125+
fn __init__[dtype: DType, //](out self, value: SIMD[dtype, 1]):
126126
"""Constructs a BigDecimal from an integral scalar.
127127
This includes all SIMD integral types, such as Int8, Int16, UInt32, etc.
128128
129129
Constraints:
130130
The dtype of the scalar must be integral.
131131
"""
132+
constrained[
133+
dtype.is_integral(),
134+
(
135+
"\n***********************************************************\n"
136+
"BigDecimal does not allow floating-point numbers as input to"
137+
" avoid unintentional loss of precision. If you want to create"
138+
" a BigDecimal from a floating-point number, please consider"
139+
" wrapping it with quotation marks or using the"
140+
" `BigDecimal.from_float()` (or `BDec.from_float()`) method"
141+
" instead."
142+
"\n***********************************************************"
143+
),
144+
]()
145+
132146
self = Self.from_integral_scalar(value)
133147

134148
# ===------------------------------------------------------------------=== #
@@ -474,7 +488,7 @@ struct BigDecimal(
474488
return decimojo.bigdecimal.arithmetics.subtract(self, other)
475489

476490
@always_inline
477-
fn __mul__(self, other: Self) raises -> Self:
491+
fn __mul__(self, other: Self) -> Self:
478492
return decimojo.bigdecimal.arithmetics.multiply(self, other)
479493

480494
@always_inline
@@ -776,6 +790,9 @@ struct BigDecimal(
776790
Returns:
777791
A new BigDecimal with increased precision.
778792
793+
Raises:
794+
Error: If `precision_diff` is negative.
795+
779796
Examples:
780797
```
781798
print(BigDecimal("123.456).scale_up(5)) # Output: 123.45600000
@@ -786,7 +803,7 @@ struct BigDecimal(
786803
"""
787804
if precision_diff < 0:
788805
raise Error(
789-
"Error in `extend_precision()`: "
806+
"`extend_precision()`: "
790807
"Cannot extend precision with negative value"
791808
)
792809

src/decimojo/biguint/arithmetics.mojo

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,9 @@ fn subtract(x1: BigUInt, x2: BigUInt) raises -> BigUInt:
198198
x1: The first unsigned integer (minuend).
199199
x2: The second unsigned integer (subtrahend).
200200
201+
Raises:
202+
Error: If x2 is greater than x1, resulting in an underflow.
203+
201204
Returns:
202205
The result of subtracting x2 from x1.
203206
"""
@@ -206,7 +209,7 @@ fn subtract(x1: BigUInt, x2: BigUInt) raises -> BigUInt:
206209
return x1
207210
if x1.is_zero():
208211
# x2 is not zero, so the result is negative, raise an error
209-
raise Error("Error in `subtract`: Underflow due to x1 < x2")
212+
raise Error("biguint.arithmetics.subtract(): Underflow due to x1 < x2")
210213

211214
# We need to determine which number has the larger magnitude
212215
var comparison_result = x1.compare(x2)
@@ -216,7 +219,7 @@ fn subtract(x1: BigUInt, x2: BigUInt) raises -> BigUInt:
216219
return BigUInt() # Return zero
217220

218221
if comparison_result < 0:
219-
raise Error("Error in `subtract`: Underflow due to x1 < x2")
222+
raise Error("biguint.arithmetics.subtract(): Underflow due to x1 < x2")
220223

221224
# Now it is safe to subtract the smaller number from the larger one
222225
# The result will have no more words than the larger operand
@@ -251,13 +254,16 @@ fn negative(x: BigUInt) raises -> BigUInt:
251254
Args:
252255
x: The BigUInt value to compute the negative of.
253256
257+
Raises:
258+
Error: If x is not zero, as negative of non-zero unsigned integer is undefined.
259+
254260
Returns:
255261
A new BigUInt containing the negative of x.
256262
"""
257263
if not x.is_zero():
258264
raise Error(
259-
"Error in `negative`: Negative of non-zero unsigned integer is"
260-
" undefined"
265+
"biguint.arithmetics.negative(): Negative of non-zero unsigned"
266+
" integer is undefined"
261267
)
262268
return BigUInt() # Return zero
263269

@@ -274,7 +280,7 @@ fn absolute(x: BigUInt) -> BigUInt:
274280
return x
275281

276282

277-
fn multiply(x1: BigUInt, x2: BigUInt) raises -> BigUInt:
283+
fn multiply(x1: BigUInt, x2: BigUInt) -> BigUInt:
278284
"""Returns the product of two BigUInt numbers.
279285
280286
Args:
@@ -359,7 +365,7 @@ fn floor_divide(x1: BigUInt, x2: BigUInt) raises -> BigUInt:
359365
if len(x2.words) == 1:
360366
# SUB-CASE: Division by zero
361367
if x2.words[0] == 0:
362-
raise Error("Error in `truncate_divide`: Division by zero")
368+
raise Error("biguint.arithmetics.floor_divide(): Division by zero")
363369

364370
# SUB-CASE: Division by one
365371
if x2.words[0] == 1:
@@ -488,7 +494,7 @@ fn ceil_divide(x1: BigUInt, x2: BigUInt) raises -> BigUInt:
488494

489495
# CASE: Division by zero
490496
if x2.is_zero():
491-
raise Error("Error in `ceil_divide`: Division by zero")
497+
raise Error("biguint.arithmetics.ceil_divide(): Division by zero")
492498

493499
# Apply floor division and check if there is a remainder
494500
var quotient = floor_divide(x1, x2)
@@ -850,10 +856,14 @@ fn floor_divide_inplace_by_double_words(
850856
Args:
851857
x1: The BigUInt value to divide by the divisor.
852858
x2: The double-word divisor.
859+
860+
Raises:
861+
Error: If the divisor is zero.
853862
"""
854863
if x2.is_zero():
855864
raise Error(
856-
"Error in `floor_divide_inplace_by_double_words`: Division by zero"
865+
"biguint.arithmetics.floor_divide_inplace_by_double_words():"
866+
" Division by zero"
857867
)
858868

859869
# CASE: all other situations
@@ -911,12 +921,16 @@ fn scale_down_by_power_of_10(x: BigUInt, n: Int) raises -> BigUInt:
911921
x: The BigUInt value to multiply.
912922
n: The power of 10 to multiply by.
913923
924+
Raises:
925+
Error: If n is negative.
926+
914927
Returns:
915928
A new BigUInt containing the result of the multiplication.
916929
"""
917930
if n < 0:
918931
raise Error(
919-
"Error in `scale_down_by_power_of_10`: n must be non-negative"
932+
"biguint.arithmetics.scale_down_by_power_of_10(): "
933+
"n must be non-negative"
920934
)
921935
if n == 0:
922936
return x
@@ -1038,7 +1052,9 @@ fn shift_words_left(num: BigUInt, positions: Int) -> BigUInt:
10381052
fn power_of_10(n: Int) raises -> BigUInt:
10391053
"""Calculates 10^n efficiently."""
10401054
if n < 0:
1041-
raise Error("Error in `power_of_10`: Negative exponent not supported")
1055+
raise Error(
1056+
"biguint.arithmetics.power_of_10(): Negative exponent not supported"
1057+
)
10421058

10431059
if n == 0:
10441060
return BigUInt(1)

src/decimojo/biguint/biguint.mojo

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,18 @@ struct BigUInt(Absable, IntableRaising, Stringable, Writable):
136136
fn __init__(out self, value: Int) raises:
137137
"""Initializes a BigUInt from an Int.
138138
See `from_int()` for more information.
139+
140+
Raises:
141+
Error: Calling `BigUInt.from_int()`.
139142
"""
140-
self = Self.from_int(value)
143+
try:
144+
self = Self.from_int(value)
145+
except e:
146+
raise Error(
147+
"`BigUInt.__init__()`: Error calling"
148+
" `BigUInt.from_int()`.\nTrace back:"
149+
+ String(e)
150+
)
141151

142152
@implicit
143153
fn __init__(out self, value: UInt):
@@ -245,7 +255,12 @@ struct BigUInt(Absable, IntableRaising, Stringable, Writable):
245255
return Self()
246256

247257
if value < 0:
248-
raise Error("Error in `BigUInt.from_int()`: The value is negative")
258+
raise Error(
259+
"`BigUInt.from_int()`: The input value ",
260+
value,
261+
" is negative and is not compatible with BigUInt.",
262+
sep="",
263+
)
249264

250265
var list_of_words = List[UInt32]()
251266
var remainder: Int = value
@@ -806,15 +821,15 @@ struct BigUInt(Absable, IntableRaising, Stringable, Writable):
806821
# ===------------------------------------------------------------------=== #
807822

808823
@always_inline
809-
fn __add__(self, other: Self) raises -> Self:
824+
fn __add__(self, other: Self) -> Self:
810825
return decimojo.biguint.arithmetics.add(self, other)
811826

812827
@always_inline
813828
fn __sub__(self, other: Self) raises -> Self:
814829
return decimojo.biguint.arithmetics.subtract(self, other)
815830

816831
@always_inline
817-
fn __mul__(self, other: Self) raises -> Self:
832+
fn __mul__(self, other: Self) -> Self:
818833
return decimojo.biguint.arithmetics.multiply(self, other)
819834

820835
@always_inline

src/decimojo/decimal/exponential.mojo

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,11 +448,20 @@ fn exp(x: Decimal) raises -> Decimal:
448448
Returns:
449449
A Decimal approximation of e^x.
450450
451+
Raises:
452+
Error: If x is greater than 66.54.
453+
451454
Notes:
452455
Because ln(2^96-1) ~= 66.54212933375474970405428366,
453456
the x value should be no greater than 66 to avoid overflow.
454457
"""
455458

459+
if x > Decimal.from_int(value=6654, scale=UInt32(2)):
460+
raise Error(
461+
"decimal.exponential.exp(): x is too large. It must be no greater"
462+
" than 66.54 to avoid overflow. Consider using `BigDecimal` type."
463+
)
464+
456465
# Handle special cases
457466
if x.is_zero():
458467
return Decimal.ONE()

0 commit comments

Comments
 (0)