Skip to content

Commit 55293b9

Browse files
committed
[GR-10330][GR-10340][GR-10334][GR-10368] Implementatin of isinf, isfinite, isnan, acos, acosh, asin, sqrt and log in Math.
PullRequest: graalpython/78
2 parents 1951ef9 + dbaa043 commit 55293b9

File tree

2 files changed

+696
-35
lines changed

2 files changed

+696
-35
lines changed

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

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,14 @@
55
import math
66
import unittest
77
import sys
8+
import struct
89

910
eps = 1E-05
1011
INF = float('inf')
1112
NINF = float('-inf')
1213
NAN = float('nan')
14+
LONG_INT = 6227020800
15+
BIG_INT = 9999992432902008176640000999999
1316

1417
""" The next three methods are needed for testing factorials
1518
"""
@@ -42,6 +45,40 @@ def py_factorial(n):
4245
outer *= inner
4346
return outer << (n - count_set_bits(n))
4447

48+
def to_ulps(x):
49+
"""Convert a non-NaN float x to an integer, in such a way that
50+
adjacent floats are converted to adjacent integers. Then
51+
abs(ulps(x) - ulps(y)) gives the difference in ulps between two
52+
floats.
53+
54+
The results from this function will only make sense on platforms
55+
where native doubles are represented in IEEE 754 binary64 format.
56+
57+
Note: 0.0 and -0.0 are converted to 0 and -1, respectively.
58+
"""
59+
n = struct.unpack('<q', struct.pack('<d', x))[0]
60+
if n < 0:
61+
n = ~(n+2**63)
62+
return n
63+
64+
def ulp_abs_check(expected, got, ulp_tol, abs_tol):
65+
"""Given finite floats `expected` and `got`, check that they're
66+
approximately equal to within the given number of ulps or the
67+
given absolute tolerance, whichever is bigger.
68+
69+
Returns None on success and an error message on failure.
70+
"""
71+
ulp_error = abs(to_ulps(expected) - to_ulps(got))
72+
abs_error = abs(expected - got)
73+
74+
# Succeed if either abs_error <= abs_tol or ulp_error <= ulp_tol.
75+
if abs_error <= abs_tol or ulp_error <= ulp_tol:
76+
return None
77+
else:
78+
fmt = ("error = {:.3g} ({:d} ulps); "
79+
"permitted error = {:.3g} or {:d} ulps")
80+
return fmt.format(abs_error, ulp_error, abs_tol, ulp_tol)
81+
4582
def result_check(expected, got, ulp_tol=5, abs_tol=0.0):
4683
# Common logic of MathTests.(ftest, test_testcases, test_mtestcases)
4784
"""Compare arguments expected and got, as floats, if either
@@ -87,6 +124,10 @@ def result_check(expected, got, ulp_tol=5, abs_tol=0.0):
87124
else:
88125
return None
89126

127+
class MyFloat:
128+
def __float__(self):
129+
return 0.6
130+
90131
class MathTests(unittest.TestCase):
91132

92133
def ftest(self, name, got, expected, ulp_tol=5, abs_tol=0.0):
@@ -110,6 +151,150 @@ def testConstants(self):
110151
# math.tau since 3.6
111152
self.assertEqual(math.tau, 2*math.pi)
112153

154+
def testAcos(self):
155+
self.assertRaises(TypeError, math.acos)
156+
self.ftest('acos(-1)', math.acos(-1), math.pi)
157+
self.ftest('acos(0)', math.acos(0), math.pi/2)
158+
self.ftest('acos(1)', math.acos(1), 0)
159+
self.assertRaises(ValueError, math.acos, INF)
160+
self.assertRaises(ValueError, math.acos, NINF)
161+
self.assertRaises(ValueError, math.acos, 1 + eps)
162+
self.assertRaises(ValueError, math.acos, -1 - eps)
163+
self.assertTrue(math.isnan(math.acos(NAN)))
164+
165+
self.assertEqual(math.acos(True), 0.0)
166+
self.assertRaises(ValueError, math.acos, 10)
167+
self.assertRaises(ValueError, math.acos, -10)
168+
self.assertRaises(ValueError, math.acos, LONG_INT)
169+
self.assertRaises(ValueError, math.acos, BIG_INT)
170+
self.assertRaises(TypeError, math.acos, 'ahoj')
171+
172+
self.assertRaises(ValueError, math.acos, 9999992432902008176640000999999)
173+
174+
self.ftest('acos(MyFloat())', math.acos(MyFloat()), 0.9272952180016123)
175+
176+
class MyFloat2:
177+
def __float__(self):
178+
return 1.6
179+
self.assertRaises(ValueError, math.acos, MyFloat2())
180+
181+
class MyFloat3:
182+
def __float__(self):
183+
return 'ahoj'
184+
self.assertRaises(TypeError, math.acos, MyFloat3())
185+
186+
def testAcosh(self):
187+
self.assertRaises(TypeError, math.acosh)
188+
self.ftest('acosh(1)', math.acosh(1), 0)
189+
# TODO uncomment when GR-10346 will be fixed
190+
#self.ftest('acosh(2)', math.acosh(2), 1.3169578969248168)
191+
self.assertRaises(ValueError, math.acosh, 0)
192+
self.assertRaises(ValueError, math.acosh, -1)
193+
self.assertEqual(math.acosh(INF), INF)
194+
self.assertRaises(ValueError, math.acosh, NINF)
195+
self.assertTrue(math.isnan(math.acosh(NAN)))
196+
197+
class MyFF:
198+
def __float__(self):
199+
return 6
200+
# TODO uncomment when GR-10346 will be fixed
201+
#self.ftest('acos(MyFloat())', math.acosh(MyFF()), 0.9272952180016123)
202+
self.assertRaises(ValueError, math.acosh, MyFloat())
203+
math.acosh(BIG_INT)
204+
self.assertRaises(TypeError, math.acosh, 'ahoj')
205+
206+
def testAsin(self):
207+
self.assertRaises(TypeError, math.asin)
208+
self.ftest('asin(-1)', math.asin(-1), -math.pi/2)
209+
self.ftest('asin(0)', math.asin(0), 0)
210+
self.ftest('asin(1)', math.asin(1), math.pi/2)
211+
self.assertRaises(ValueError, math.asin, INF)
212+
self.assertRaises(ValueError, math.asin, NINF)
213+
self.assertRaises(ValueError, math.asin, 1 + eps)
214+
self.assertRaises(ValueError, math.asin, -1 - eps)
215+
self.assertTrue(math.isnan(math.asin(NAN)))
216+
217+
self.assertRaises(ValueError, math.asin, 10)
218+
self.assertRaises(ValueError, math.asin, -10)
219+
self.assertRaises(ValueError, math.asin, LONG_INT)
220+
self.assertRaises(ValueError, math.asin, BIG_INT)
221+
self.assertRaises(TypeError, math.asin, 'ahoj')
222+
223+
def testSqrt(self):
224+
self.assertRaises(TypeError, math.sqrt)
225+
self.ftest('sqrt(0)', math.sqrt(0), 0)
226+
self.ftest('sqrt(1)', math.sqrt(1), 1)
227+
self.ftest('sqrt(4)', math.sqrt(4), 2)
228+
self.assertEqual(math.sqrt(INF), INF)
229+
self.assertRaises(ValueError, math.sqrt, -1)
230+
self.assertRaises(ValueError, math.sqrt, NINF)
231+
self.assertTrue(math.isnan(math.sqrt(NAN)))
232+
233+
math.sqrt(MyFloat())
234+
math.sqrt(BIG_INT)
235+
self.assertRaises(TypeError, math.asin, 'ahoj')
236+
237+
def testLog(self):
238+
self.assertRaises(TypeError, math.log)
239+
self.ftest('log(1/e)', math.log(1/math.e), -1)
240+
self.ftest('log(1)', math.log(1), 0)
241+
self.ftest('log(e)', math.log(math.e), 1)
242+
self.ftest('log(32,2)', math.log(32,2), 5)
243+
self.ftest('log(10**40, 10)', math.log(10**40, 10), 40)
244+
self.ftest('log(10**40, 10**20)', math.log(10**40, 10**20), 2)
245+
# TODO uncomment when GR-10346 will be fixed
246+
#self.ftest('log(10**1000)', math.log(10**1000), 2302.5850929940457)
247+
self.assertRaises(ValueError, math.log, -1.5)
248+
self.assertRaises(ValueError, math.log, -10**1000)
249+
self.assertRaises(ValueError, math.log, NINF)
250+
self.assertEqual(math.log(INF), INF)
251+
self.assertTrue(math.isnan(math.log(NAN)))
252+
253+
math.log(MyFloat())
254+
self.assertRaises(ZeroDivisionError, math.log, MyFloat(), True)
255+
self.ftest('log(True, 1.1)', math.log(True, 1.1), 0)
256+
math.log(BIG_INT)
257+
math.log(BIG_INT, 4.6)
258+
self.ftest('log(BIG_INT, BIG_INT)', math.log(BIG_INT, BIG_INT), 1)
259+
self.assertRaises(ZeroDivisionError, math.log, BIG_INT, True)
260+
self.assertRaises(TypeError, math.asin, 'ahoj')
261+
262+
math.log(MyFloat(), 10)
263+
math.log(MyFloat(), BIG_INT)
264+
math.log(MyFloat(), 7.4)
265+
self.ftest('log(MyFloat(), MyFloat())', math.log(MyFloat(), MyFloat()), 1)
266+
math.log(10, MyFloat())
267+
268+
def testIsfinite(self):
269+
self.assertTrue(math.isfinite(0.0))
270+
self.assertTrue(math.isfinite(-0.0))
271+
self.assertTrue(math.isfinite(1.0))
272+
self.assertTrue(math.isfinite(-1.0))
273+
self.assertFalse(math.isfinite(float("nan")))
274+
self.assertFalse(math.isfinite(float("inf")))
275+
self.assertFalse(math.isfinite(float("-inf")))
276+
277+
self.assertTrue(math.isfinite(True))
278+
self.assertTrue(math.isfinite(LONG_INT))
279+
self.assertTrue(math.isfinite(BIG_INT))
280+
self.assertRaises(TypeError, math.isfinite, 'ahoj')
281+
self.assertTrue(math.isfinite(MyFloat()))
282+
283+
def testIsinf(self):
284+
self.assertTrue(math.isinf(float("inf")))
285+
self.assertTrue(math.isinf(float("-inf")))
286+
self.assertTrue(math.isinf(1E400))
287+
self.assertTrue(math.isinf(-1E400))
288+
self.assertFalse(math.isinf(float("nan")))
289+
self.assertFalse(math.isinf(0.))
290+
self.assertFalse(math.isinf(1.))
291+
292+
self.assertFalse(math.isinf(True))
293+
self.assertFalse(math.isinf(LONG_INT))
294+
self.assertFalse(math.isinf(BIG_INT))
295+
self.assertRaises(TypeError, math.isinf, 'ahoj')
296+
self.assertFalse(math.isinf(MyFloat()))
297+
113298
def test_ceil_basic(self):
114299
self.assertEqual(math.ceil(10), 10)
115300
self.assertEqual(math.ceil(-10), -10)
@@ -236,6 +421,7 @@ def test_isnan(self):
236421
self.assertRaises(TypeError, math.isnan, 'hello')
237422

238423
self.assertFalse(math.isnan(False))
424+
self.assertFalse(math.isnan(MyFloat()))
239425

240426
def test_fabs(self):
241427
self.assertEqual(math.fabs(-1), 1)

0 commit comments

Comments
 (0)