Skip to content

Commit 0c1a24b

Browse files
committed
[GR-10340] No Math.isinf(), Math.isfinite() and Math.isnan() are not defined.
1 parent e3e5821 commit 0c1a24b

File tree

2 files changed

+135
-23
lines changed

2 files changed

+135
-23
lines changed

graalpython/com.oracle.graal.python.test/src/tests/test_math.py

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
INF = float('inf')
1111
NINF = float('-inf')
1212
NAN = float('nan')
13+
LONG_INT = 6227020800
14+
BIG_INT = 9999992432902008176640000999999
1315

1416
""" The next three methods are needed for testing factorials
1517
"""
@@ -87,6 +89,10 @@ def result_check(expected, got, ulp_tol=5, abs_tol=0.0):
8789
else:
8890
return None
8991

92+
class MyFloat:
93+
def __float__(self):
94+
return 0.6
95+
9096
class MathTests(unittest.TestCase):
9197

9298
def ftest(self, name, got, expected, ulp_tol=5, abs_tol=0.0):
@@ -116,13 +122,12 @@ def testAcos(self):
116122
self.assertEqual(math.acos(True), 0.0)
117123
self.assertRaises(ValueError, math.acos, 10)
118124
self.assertRaises(ValueError, math.acos, -10)
125+
self.assertRaises(ValueError, math.acos, LONG_INT)
126+
self.assertRaises(ValueError, math.acos, BIG_INT)
119127
self.assertRaises(TypeError, math.acos, 'ahoj')
120128

121129
self.assertRaises(ValueError, math.acos, 9999992432902008176640000999999)
122130

123-
class MyFloat:
124-
def __float__(self):
125-
return 0.6
126131
self.ftest('acos(MyFloat())', math.acos(MyFloat()), 0.9272952180016123)
127132

128133
class MyFloat2:
@@ -135,6 +140,36 @@ def __float__(self):
135140
return 'ahoj'
136141
self.assertRaises(TypeError, math.acos, MyFloat3())
137142

143+
def testIsfinite(self):
144+
self.assertTrue(math.isfinite(0.0))
145+
self.assertTrue(math.isfinite(-0.0))
146+
self.assertTrue(math.isfinite(1.0))
147+
self.assertTrue(math.isfinite(-1.0))
148+
self.assertFalse(math.isfinite(float("nan")))
149+
self.assertFalse(math.isfinite(float("inf")))
150+
self.assertFalse(math.isfinite(float("-inf")))
151+
152+
self.assertTrue(math.isfinite(True))
153+
self.assertTrue(math.isfinite(LONG_INT))
154+
self.assertTrue(math.isfinite(BIG_INT))
155+
self.assertRaises(TypeError, math.isfinite, 'ahoj')
156+
self.assertTrue(math.isfinite(MyFloat()))
157+
158+
def testIsinf(self):
159+
self.assertTrue(math.isinf(float("inf")))
160+
self.assertTrue(math.isinf(float("-inf")))
161+
self.assertTrue(math.isinf(1E400))
162+
self.assertTrue(math.isinf(-1E400))
163+
self.assertFalse(math.isinf(float("nan")))
164+
self.assertFalse(math.isinf(0.))
165+
self.assertFalse(math.isinf(1.))
166+
167+
self.assertFalse(math.isinf(True))
168+
self.assertFalse(math.isinf(LONG_INT))
169+
self.assertFalse(math.isinf(BIG_INT))
170+
self.assertRaises(TypeError, math.isinf, 'ahoj')
171+
self.assertFalse(math.isinf(MyFloat()))
172+
138173
def test_ceil_basic(self):
139174
self.assertEqual(math.ceil(10), 10)
140175
self.assertEqual(math.ceil(-10), -10)
@@ -261,6 +296,7 @@ def test_isnan(self):
261296
self.assertRaises(TypeError, math.isnan, 'hello')
262297

263298
self.assertFalse(math.isnan(False))
299+
self.assertFalse(math.isnan(MyFloat()))
264300

265301
def test_fabs(self):
266302
self.assertEqual(math.fabs(-1), 1)

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MathModuleBuiltins.java

Lines changed: 96 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -641,17 +641,20 @@ public PTuple frexpO(Object value) {
641641
}
642642

643643
@Builtin(name = "isnan", fixedNumOfArguments = 1)
644+
@TypeSystemReference(PythonArithmeticTypes.class)
645+
@ImportStatic(MathGuards.class)
644646
@GenerateNodeFactory
645-
@SuppressWarnings("unused")
646647
public abstract static class IsNanNode extends PythonBuiltinNode {
647648

649+
public abstract boolean execute(Object value);
650+
648651
@Specialization
649-
public boolean isNan(int value) {
652+
public boolean isNan(@SuppressWarnings("unused") long value) {
650653
return false;
651654
}
652655

653656
@Specialization
654-
public boolean isNan(long value) {
657+
public boolean isNan(@SuppressWarnings("unused") PInt value) {
655658
return false;
656659
}
657660

@@ -660,24 +663,19 @@ public boolean isNan(double value) {
660663
return Double.isNaN(value);
661664
}
662665

663-
@Specialization
664-
public boolean isNan(PInt value) {
665-
return false;
666-
}
667-
668-
@Specialization
669-
public boolean isNan(PFloat value) {
670-
return Double.isNaN(value.getValue());
666+
@Specialization(guards = "!isNumber(value)")
667+
public boolean isinf(Object value,
668+
@Cached("create(__FLOAT__)") LookupAndCallUnaryNode dispatchFloat,
669+
@Cached("create()") IsNanNode isNanNode) {
670+
Object result = dispatchFloat.executeObject(value);
671+
if (result == PNone.NO_VALUE) {
672+
throw raise(TypeError, "must be real number, not %p", value);
673+
}
674+
return isNanNode.execute(result);
671675
}
672676

673-
@Specialization
674-
public boolean isNan(boolean value) {
675-
return false;
676-
}
677-
678-
@Fallback
679-
public boolean isNan(Object value) {
680-
throw raise(TypeError, "must be real number, not %p", value);
677+
protected IsNanNode create() {
678+
return MathModuleBuiltinsFactory.IsNanNodeFactory.create(new PNode[0]);
681679
}
682680
}
683681

@@ -837,7 +835,7 @@ public abstract static class AcosNode extends PythonBuiltinNode {
837835
public abstract double execute(Object value);
838836

839837
@Specialization
840-
public double acos(int value,
838+
public double acos(long value,
841839
@Cached("createBinaryProfile()") ConditionProfile doNotFit) {
842840
if (doNotFit.profile(value > 1 || value < -1)) {
843841
throw raise(ValueError, "math domain error");
@@ -906,6 +904,84 @@ public double sin(double value) {
906904
}
907905
}
908906

907+
@Builtin(name = "isfinite", fixedNumOfArguments = 1)
908+
@TypeSystemReference(PythonArithmeticTypes.class)
909+
@ImportStatic(MathGuards.class)
910+
@GenerateNodeFactory
911+
public abstract static class IsFiniteNode extends PythonBuiltinNode {
912+
913+
public abstract boolean execute(Object value);
914+
915+
@Specialization
916+
public boolean isfinite(@SuppressWarnings("unused") long value) {
917+
return true;
918+
}
919+
920+
@Specialization
921+
public boolean isfinite(@SuppressWarnings("unused") PInt value) {
922+
return true;
923+
}
924+
925+
@Specialization
926+
public boolean isfinite(double value) {
927+
return Double.isFinite(value);
928+
}
929+
930+
@Specialization(guards = "!isNumber(value)")
931+
public boolean isinf(Object value,
932+
@Cached("create(__FLOAT__)") LookupAndCallUnaryNode dispatchFloat,
933+
@Cached("create()") IsFiniteNode isFiniteNode) {
934+
Object result = dispatchFloat.executeObject(value);
935+
if (result == PNone.NO_VALUE) {
936+
throw raise(TypeError, "must be real number, not %p", value);
937+
}
938+
return isFiniteNode.execute(result);
939+
}
940+
941+
protected IsFiniteNode create() {
942+
return MathModuleBuiltinsFactory.IsFiniteNodeFactory.create(new PNode[0]);
943+
}
944+
}
945+
946+
@Builtin(name = "isinf", fixedNumOfArguments = 1)
947+
@TypeSystemReference(PythonArithmeticTypes.class)
948+
@ImportStatic(MathGuards.class)
949+
@GenerateNodeFactory
950+
public abstract static class IsInfNode extends PythonBuiltinNode {
951+
952+
public abstract boolean execute(Object value);
953+
954+
@Specialization
955+
public boolean isinf(@SuppressWarnings("unused") long value) {
956+
return false;
957+
}
958+
959+
@Specialization
960+
public boolean isfinite(@SuppressWarnings("unused") PInt value) {
961+
return false;
962+
}
963+
964+
@Specialization
965+
public boolean isinf(double value) {
966+
return Double.isInfinite(value);
967+
}
968+
969+
@Specialization(guards = "!isNumber(value)")
970+
public boolean isinf(Object value,
971+
@Cached("create(__FLOAT__)") LookupAndCallUnaryNode dispatchFloat,
972+
@Cached("create()") IsInfNode isInfNode) {
973+
Object result = dispatchFloat.executeObject(value);
974+
if (result == PNone.NO_VALUE) {
975+
throw raise(TypeError, "must be real number, not %p", value);
976+
}
977+
return isInfNode.execute(result);
978+
}
979+
980+
protected IsInfNode create() {
981+
return MathModuleBuiltinsFactory.IsInfNodeFactory.create(new PNode[0]);
982+
}
983+
}
984+
909985
@Builtin(name = "log", minNumOfArguments = 1, maxNumOfArguments = 2)
910986
@GenerateNodeFactory
911987
public abstract static class LogNode extends PythonBuiltinNode {

0 commit comments

Comments
 (0)