circuitpython/tests/float/math_domain.py
Damien George 2e4dda3c20 py/modmath: Fix two-argument math function domain check.
Prior to this fix, pow(1.5, inf) and pow(0.5, -inf) (among other things)
would incorrectly raise a ValueError, because the result is inf with the
first argument being finite.  This commit fixes this by allowing the result
to be infinite if the first or second (or both) argument is infinite.

This fix doesn't affect the other three math functions that have two
arguments:
- atan2 never returns inf, so always fails isinf(ans)
- copysign returns inf only if the first argument x is inf, so will never
  reach the isinf(y) check
- fmod never returns inf, so always fails isinf(ans)

Signed-off-by: Damien George <damien@micropython.org>
2023-02-24 15:55:12 +11:00

73 lines
1.9 KiB
Python

# Tests domain errors in math functions
try:
import math
except ImportError:
print("SKIP")
raise SystemExit
inf = float("inf")
nan = float("nan")
# single argument functions
for name, f, args in (
("fabs", math.fabs, ()),
("ceil", math.ceil, ()),
("floor", math.floor, ()),
("trunc", math.trunc, ()),
("sqrt", math.sqrt, (-1, 0)),
("exp", math.exp, ()),
("log", math.log, ()),
("sin", math.sin, ()),
("cos", math.cos, ()),
("tan", math.tan, ()),
("asin", math.asin, (-1.1, 1, 1.1)),
("acos", math.acos, (-1.1, 1, 1.1)),
("atan", math.atan, ()),
("ldexp", lambda x: math.ldexp(x, 0), ()),
("radians", math.radians, ()),
("degrees", math.degrees, ()),
):
for x in args + (inf, -inf, nan):
try:
ans = "%.4f" % f(x)
except ValueError:
ans = "ValueError"
except OverflowError:
ans = "OverflowError"
print("%s(%.4f) = %s" % (name, x, ans))
# double argument functions
for name, f, args in (
(
"pow",
math.pow,
(
(0, 2),
(-1, 2),
(0, -1),
(-1, 2.3),
(0.5, inf),
(-0.5, inf),
(0.5, -inf),
(-0.5, -inf),
(1.5, inf),
(-1.5, inf),
(1.5, -inf),
(-1.5, -inf),
(nan, 0),
(1, nan),
),
),
("log", math.log, ()),
("fmod", math.fmod, ((1.2, inf), (1.2, -inf), (1.2, 0), (inf, 1.2))),
("atan2", math.atan2, ((0, 0), (-inf, inf), (-inf, -inf), (inf, -inf))),
("copysign", math.copysign, ()),
):
for x in args + ((0, inf), (inf, 0), (inf, inf), (inf, nan), (nan, inf), (nan, nan)):
try:
ans = "%.4f" % f(*x)
except ValueError:
ans = "ValueError"
print("%s(%.4f, %.4f) = %s" % (name, x[0], x[1], ans))