1919from std import math
2020
2121from decimo.bigdecimal.bigdecimal import BigDecimal
22+ from decimo.errors import ValueError , OverflowError , ZeroDivisionError
2223from decimo.rounding_mode import RoundingMode
2324
2425# ===----------------------------------------------------------------------=== #
@@ -235,11 +236,20 @@ def power(
235236 # Special cases
236237 if base.coefficient.is_zero():
237238 if exponent.coefficient.is_zero():
238- raise Error(" Error in power: 0^0 is undefined" )
239+ raise Error(
240+ ValueError (
241+ message = " 0^0 is undefined." ,
242+ function = " power()" ,
243+ )
244+ )
239245 elif exponent.sign:
240246 raise Error(
241- " Error in power: Division by zero (negative exponent with zero"
242- " base)"
247+ ZeroDivisionError (
248+ message = (
249+ " Division by zero (negative exponent with zero base)."
250+ ),
251+ function = " power()" ,
252+ )
243253 )
244254 else :
245255 return BigDecimal(BigUInt.zero(), 0 , False )
@@ -264,8 +274,13 @@ def power(
264274 # Check for negative base with non-integer exponent
265275 if base.sign and not exponent.is_integer():
266276 raise Error(
267- " Error in power: Negative base with non-integer exponent would"
268- " produce a complex result"
277+ ValueError (
278+ message = (
279+ " Negative base with non-integer exponent would produce"
280+ " a complex result."
281+ ),
282+ function = " power()" ,
283+ )
269284 )
270285
271286 # Optimization for integer exponents
@@ -434,7 +449,12 @@ def root(x: BigDecimal, n: BigDecimal, precision: Int) raises -> BigDecimal:
434449
435450 # Check for n = 0
436451 if n.coefficient.is_zero():
437- raise Error(" Error in `root`: Cannot compute zeroth root" )
452+ raise Error(
453+ ValueError (
454+ message = " Cannot compute zeroth root." ,
455+ function = " root()" ,
456+ )
457+ )
438458
439459 # Special case for integer roots - use more efficient implementation
440460 if not n.sign:
@@ -493,8 +513,13 @@ def root(x: BigDecimal, n: BigDecimal, precision: Int) raises -> BigDecimal:
493513 var n_is_odd_reciprocal = is_odd_reciprocal(n)
494514 if not n_is_integer and not n_is_odd_reciprocal:
495515 raise Error(
496- " Error in `root`: Cannot compute non-odd-integer root of a"
497- " negative number"
516+ ValueError (
517+ message = (
518+ " Cannot compute non-odd-integer root of a negative"
519+ " number."
520+ ),
521+ function = " root()" ,
522+ )
498523 )
499524 elif n_is_integer:
500525 var result = integer_root(x, n, precision)
@@ -549,13 +574,28 @@ def integer_root(
549574
550575 # Handle special case: n must be a positive integer
551576 if n.sign:
552- raise Error(" Error in `root`: Root value must be positive" )
577+ raise Error(
578+ ValueError (
579+ message = " Root value must be positive." ,
580+ function = " integer_root()" ,
581+ )
582+ )
553583
554584 if not n.is_integer():
555- raise Error(" Error in `root`: Root value must be an integer" )
585+ raise Error(
586+ ValueError (
587+ message = " Root value must be an integer." ,
588+ function = " integer_root()" ,
589+ )
590+ )
556591
557592 if n.coefficient.is_zero():
558- raise Error(" Error in `root`: Cannot compute zeroth root" )
593+ raise Error(
594+ ValueError (
595+ message = " Cannot compute zeroth root." ,
596+ function = " integer_root()" ,
597+ )
598+ )
559599
560600 # Special case: n = 1 (1st root is just the number itself)
561601 if n.is_one():
@@ -594,7 +634,10 @@ def integer_root(
594634 result_sign = True
595635 else : # n_uint.words[0] % 2 == 0: # Even root
596636 raise Error(
597- " Error in `root`: Cannot compute even root of a negative number"
637+ ValueError (
638+ message = " Cannot compute even root of a negative number." ,
639+ function = " integer_root()" ,
640+ )
598641 )
599642
600643 # Extract n as Int for Newton's method
@@ -1183,7 +1226,10 @@ def sqrt_exact(x: BigDecimal, precision: Int) raises -> BigDecimal:
11831226 # Handle special cases
11841227 if x.sign:
11851228 raise Error(
1186- " Error in `sqrt`: Cannot compute square root of negative number"
1229+ ValueError (
1230+ message = " Cannot compute square root of a negative number." ,
1231+ function = " sqrt_exact()" ,
1232+ )
11871233 )
11881234
11891235 if x.coefficient.is_zero():
@@ -1316,7 +1362,10 @@ def sqrt_reciprocal(x: BigDecimal, precision: Int) raises -> BigDecimal:
13161362 # Handle special cases
13171363 if x.sign:
13181364 raise Error(
1319- " Error in `sqrt`: Cannot compute square root of negative number"
1365+ ValueError (
1366+ message = " Cannot compute square root of a negative number." ,
1367+ function = " sqrt_reciprocal()" ,
1368+ )
13201369 )
13211370
13221371 if x.coefficient.is_zero():
@@ -1498,7 +1547,10 @@ def sqrt_newton(x: BigDecimal, precision: Int) raises -> BigDecimal:
14981547 # Handle special cases
14991548 if x.sign:
15001549 raise Error(
1501- " Error in `sqrt`: Cannot compute square root of negative number"
1550+ ValueError (
1551+ message = " Cannot compute square root of a negative number." ,
1552+ function = " sqrt_newton()" ,
1553+ )
15021554 )
15031555
15041556 if x.coefficient.is_zero():
@@ -1583,7 +1635,10 @@ def sqrt_decimal_approach(x: BigDecimal, precision: Int) raises -> BigDecimal:
15831635 # Handle special cases
15841636 if x.sign:
15851637 raise Error(
1586- " Error in `sqrt`: Cannot compute square root of negative number"
1638+ ValueError (
1639+ message = " Cannot compute square root of a negative number." ,
1640+ function = " sqrt_decimal_approach()" ,
1641+ )
15871642 )
15881643
15891644 if x.coefficient.is_zero():
@@ -1765,7 +1820,11 @@ def exp(x: BigDecimal, precision: Int) raises -> BigDecimal:
17651820 # For very large positive values, result will overflow BigDecimal capacity
17661821 # TODO : Use BigInt10 as scale can avoid overflow in this case
17671822 if not x.sign and x.adjusted() >= 20 : # x > 10^20
1768- raise Error(" Error in `exp`: Result too large to represent" )
1823+ raise Error(
1824+ OverflowError (
1825+ message = " Result too large to represent" , function = " exp()"
1826+ )
1827+ )
17691828
17701829 # For very large negative values, result will be effectively zero
17711830 if x.sign and x.adjusted() >= 20 : # x < -10^20
@@ -1973,10 +2032,17 @@ def ln(
19732032 # Handle special cases
19742033 if x.sign:
19752034 raise Error(
1976- " Error in `ln`: Cannot compute logarithm of negative number"
2035+ ValueError (
2036+ message = " Cannot compute logarithm of negative number" ,
2037+ function = " ln()" ,
2038+ )
19772039 )
19782040 if x.coefficient.is_zero():
1979- raise Error(" Error in `ln`: Cannot compute logarithm of zero" )
2041+ raise Error(
2042+ ValueError (
2043+ message = " Cannot compute logarithm of zero" , function = " ln()"
2044+ )
2045+ )
19802046 if x == BigDecimal(BigUInt.one(), 0 , False ):
19812047 return BigDecimal(BigUInt.zero(), 0 , False ) # ln(1) = 0
19822048
@@ -2066,21 +2132,36 @@ def log(x: BigDecimal, base: BigDecimal, precision: Int) raises -> BigDecimal:
20662132 # Special cases
20672133 if x.sign:
20682134 raise Error(
2069- " Error in log(): Cannot compute logarithm of a negative number"
2135+ ValueError (
2136+ message = " Cannot compute logarithm of a negative number" ,
2137+ function = " log()" ,
2138+ )
20702139 )
20712140 if x.coefficient.is_zero():
2072- raise Error(" Error in log(): Cannot compute logarithm of zero" )
2141+ raise Error(
2142+ ValueError (
2143+ message = " Cannot compute logarithm of zero" , function = " log()"
2144+ )
2145+ )
20732146
20742147 # Base validation
20752148 if base.sign:
2076- raise Error(" Error in log(): Cannot use a negative base" )
2149+ raise Error(
2150+ ValueError (message = " Cannot use a negative base" , function = " log()" )
2151+ )
20772152 if base.coefficient.is_zero():
2078- raise Error(" Error in log(): Cannot use zero as a base" )
2153+ raise Error(
2154+ ValueError (message = " Cannot use zero as a base" , function = " log()" )
2155+ )
20792156 if (
20802157 base.coefficient.number_of_digits() == base.scale + 1
20812158 and base.coefficient.words[- 1 ] == 1
20822159 ):
2083- raise Error(" Error in log(): Cannot use base 1 for logarithm" )
2160+ raise Error(
2161+ ValueError (
2162+ message = " Cannot use base 1 for logarithm" , function = " log()"
2163+ )
2164+ )
20842165
20852166 # Special cases
20862167 if (
@@ -2129,10 +2210,17 @@ def log10(x: BigDecimal, precision: Int) raises -> BigDecimal:
21292210 # Special cases
21302211 if x.sign:
21312212 raise Error(
2132- " Error in log10(): Cannot compute logarithm of a negative number"
2213+ ValueError (
2214+ message = " Cannot compute logarithm of a negative number" ,
2215+ function = " log10()" ,
2216+ )
21332217 )
21342218 if x.coefficient.is_zero():
2135- raise Error(" Error in log10(): Cannot compute logarithm of zero" )
2219+ raise Error(
2220+ ValueError (
2221+ message = " Cannot compute logarithm of zero" , function = " log10()"
2222+ )
2223+ )
21362224
21372225 # Fast path: Powers of 10 are handled directly
21382226 if x.coefficient.is_power_of_10():
0 commit comments