Skip to content

Commit 2bb3dab

Browse files
committed
[GR-10614] Missing implementation of special functions from Math module.
1 parent 3213913 commit 2bb3dab

File tree

2 files changed

+540
-0
lines changed

2 files changed

+540
-0
lines changed

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

Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1295,6 +1295,217 @@ def testmodf(name, result, expected):
12951295
self.assertRaises(TypeError, math.modf, 'ahoj')
12961296
testmodf('modf(BIG_INT)', math.modf(BIG_INT), (0.0, 9.999992432902008e+30))
12971297

1298+
def executeFnTest(self, values, fn, fnName):
1299+
for value in values:
1300+
result = fn(value[0])
1301+
expected = value[1]
1302+
if math.isnan(expected):
1303+
self.assertTrue(math.isnan(result), "Test2 fail: {}({}) = {}, but was {}".format(fnName, value[0], expected, result))
1304+
else :
1305+
if result != expected:
1306+
self.assertTrue(math.isclose(result, expected, rel_tol=1e-14), "Test3 fail: {}({}) = {}, but was {}".format(fnName, value[0], expected, result))
1307+
1308+
def test_erf(self):
1309+
erfValues = [(0.0, 0.0), (-0.0, -0.0), (INF, 1.0), (NINF, -1.0), (NAN, NAN),
1310+
# tiny values
1311+
(1e-308, 1.1283791670955125e-308), (5e-324, 4.9406564584124654e-324),
1312+
(1e-10, 1.1283791670955126e-10),
1313+
# small integers
1314+
(1, 0.842700792949715), (2, 0.99532226501895271), (3, 0.99997790950300136),
1315+
(4, 0.99999998458274209), (5, 0.99999999999846256), (6, 1.0),
1316+
(-1, -0.842700792949715), (-2, -0.99532226501895271), (-3, -0.99997790950300136),
1317+
(-4, -0.99999998458274209), (-5, -0.99999999999846256), (-6, -1.0),
1318+
# huge values should all go to +/-1, depending on sign
1319+
(-40, -1.0), (1e16, 1.0), (-1e150, -1.0), (1.7e308, 1.0),
1320+
#incorrectly signalled overflow on some platforms.
1321+
(26.2, 1.0), (26.4, 1.0), (26.6, 1.0), (26.8, 1.0), (27.0, 1.0), (27.2, 1.0),
1322+
(27.4, 1.0), (27.6, 1.0), (-26.2, -1.0), (-26.4, -1.0), (-26.6, -1.0),
1323+
(-26.8, -1.0), (-27.0, -1.0), (-27.2, -1.0), (-27.4, -1.0), (-27.6, -1.0)
1324+
]
1325+
self.executeFnTest(erfValues, math.erf, 'math.erf')
1326+
1327+
def test_erfc(self):
1328+
values = [(0.0, 1.0), (-0.0, 1.0), (INF, 0.0), (NINF, 2.0), (NAN, NAN),
1329+
# tiny values
1330+
(1e-308, 1.0), (5e-324, 1.0), (1e-10, 0.99999999988716204),
1331+
# small integers
1332+
(1, 0.157299207050285), (2, 0.004677734981047268), (3, 2.2090496998585482e-05),
1333+
(4, 1.541725790028002e-08), (5, 1.5374597944280341e-12),
1334+
# this number needs to be rounded
1335+
(6, 2.1519736712498925e-17),
1336+
(-1, 1.842700792949715), (-2, 1.9953222650189528), (-3, 1.9999779095030015),
1337+
(-4, 1.9999999845827421), (-5, 1.9999999999984626), (-6, 2.0),
1338+
# as x -> infinity, erfc(x) behaves like exp(-x*x)/x/sqrt(pi)
1339+
(20, 5.395865611607906e-176), (25, 8.300172571196514e-274), (27, 5.2370464393526292e-319), (28, 0.0),
1340+
# huge values
1341+
(-40, 2.0), (1e16, 0.0), (-1e150, 2.0), (1.7e308, 0.0),
1342+
# incorrectly signalled overflow on some platforms.
1343+
(26.2, 1.6432507924389793e-300), (26.4, 4.4017768588035507e-305), (26.6, 1.08851258854424e-309),
1344+
(26.8, 2.4849621571966629e-314), (27.0, 5.2370464393526292e-319), (27.2, 9.8813129168249309e-324),
1345+
(27.4, 0.0), (27.6, 0.0), (-26.2, 2.0), (-26.4, 2.0), (-26.6, 2.0),
1346+
(-26.8, 2.0), (-27.0, 2.0), (-27.2, 2.0), (-27.4, 2.0), (-27.6, 2.0)
1347+
]
1348+
1349+
self.executeFnTest(values, math.erfc, 'math.erfc')
1350+
1351+
def test_gamma(self):
1352+
self.assertRaises(ValueError, math.gamma, 0.)
1353+
self.assertRaises(ValueError, math.gamma, -0.0)
1354+
self.assertRaises(ValueError, math.gamma, NINF)
1355+
self.assertRaises(ValueError, math.gamma, -1)
1356+
self.assertRaises(ValueError, math.gamma, -2)
1357+
self.assertRaises(ValueError, math.gamma, -1e16)
1358+
self.assertRaises(ValueError, math.gamma, -1e300)
1359+
self.assertRaises(OverflowError, math.gamma, 5.5e-309)
1360+
self.assertRaises(OverflowError, math.gamma, 1e-309)
1361+
self.assertRaises(OverflowError, math.gamma, 1e-323)
1362+
self.assertRaises(OverflowError, math.gamma, 5e-324)
1363+
self.assertRaises(OverflowError, math.gamma, 171.625)
1364+
self.assertRaises(OverflowError, math.gamma, 172)
1365+
self.assertRaises(OverflowError, math.gamma, 2000)
1366+
self.assertRaises(OverflowError, math.gamma, 1.7e308)
1367+
1368+
1369+
values = [
1370+
# special values
1371+
(INF, INF), (NAN, NAN),
1372+
# small positive integers give factorials
1373+
(1, 1), (2, 1), (3, 2), (4, 6), (5, 24), (6, 120),
1374+
# half integers
1375+
(0.5, 1.7724538509055159), (1.5, 0.88622692545275805), (2.5, 1.3293403881791372),
1376+
(3.5, 3.323350970447842), (-0.5, -3.5449077018110322), (-1.5, 2.3632718012073544),
1377+
(-2.5, -0.94530872048294170), (-3.5, 0.27008820585226917),
1378+
# values near 0
1379+
(0.1, 9.5135076986687306),
1380+
(0.01, 99.432585119150602),
1381+
(1e-8, 99999999.422784343),
1382+
#(1e-16, 10000000000000000),
1383+
(1e-30, 9.9999999999999988e+29), (1e-160, 1.0000000000000000e+160),
1384+
(1e-308, 1.0000000000000000e+308),
1385+
(5.6e-309, 1.7857142857142848e+308),
1386+
(-0.1, -10.686287021193193),
1387+
(-0.01, -100.58719796441078),
1388+
(-1e-8, -100000000.57721567),
1389+
(-1e-16, -10000000000000000),
1390+
(-1e-30, -9.9999999999999988e+29), (-1e-160, -1.0000000000000000e+160),
1391+
(-1e-308, -1.0000000000000000e+308),
1392+
(-5.6e-309, -1.7857142857142848e+308),
1393+
# values near negative integers
1394+
(-0.99999999999999989, -9007199254740992.0),
1395+
(-1.0000000000000002, 4503599627370495.5),
1396+
(-1.9999999999999998, 2251799813685248.5),
1397+
(-2.0000000000000004, -1125899906842623.5),
1398+
(-100.00000000000001, -7.5400833348831090e-145),
1399+
(-99.999999999999986, 7.5400833348840962e-145),
1400+
# large inputs
1401+
(170, 4.2690680090047051e+304),
1402+
(171, 7.2574156153079990e+306),
1403+
(171.624, 1.7942117599248104e+308),
1404+
# inputs for which gamma(x) is tiny
1405+
(-100.5, -3.3536908198076787e-159),
1406+
(-160.5, -5.2555464470078293e-286),
1407+
(-170.5, -3.3127395215386074e-308),
1408+
(-171.5, 1.9316265431711902e-310), (-176.5, -1.1956388629358166e-321), (-177.5, 4.9406564584124654e-324),
1409+
(-178.5, -0.0), (-179.5, 0.0), (-201.0001, 0.0), (-202.9999, -0.0), (-1000.5, -0.0),
1410+
(-1000000000.3, -0.0), (-4503599627370495.5, 0.0),
1411+
# inputs that cause problems for the standard reflection formula,
1412+
# thanks to loss of accuracy in 1-x
1413+
(-63.349078729022985, 4.1777971677761880e-88),
1414+
(-127.45117632943295, 1.1831110896236810e-214)
1415+
]
1416+
self.executeFnTest(values, math.gamma, 'math.gamma')
1417+
1418+
def test_lgamma(self):
1419+
self.assertRaises(ValueError, math.lgamma, 0.)
1420+
self.assertRaises(ValueError, math.lgamma, -0.0)
1421+
self.assertRaises(ValueError, math.lgamma, -1)
1422+
self.assertRaises(ValueError, math.lgamma, -2)
1423+
self.assertRaises(ValueError, math.lgamma, -1)
1424+
self.assertRaises(ValueError, math.lgamma, -1e300)
1425+
self.assertRaises(ValueError, math.lgamma, -1.79e308)
1426+
self.assertRaises(OverflowError, math.lgamma, 2.55998332785164e305)
1427+
self.assertRaises(OverflowError, math.lgamma, 1.7e308)
1428+
1429+
1430+
values = [(INF, INF), (-INF, INF), (NAN, NAN),
1431+
# small positive integers give factorials
1432+
(1, 0.0), (2, 0.0),
1433+
(3, 0.69314718055994529),
1434+
(4, 1.791759469228055),
1435+
(5, 3.1780538303479458),
1436+
(6, 4.7874917427820458),
1437+
# half integers
1438+
(0.5, 0.57236494292470008),
1439+
(1.5, -0.12078223763524522),
1440+
(2.5, 0.28468287047291918),
1441+
(3.5, 1.2009736023470743),
1442+
(-0.5, 1.2655121234846454),
1443+
(-1.5, 0.86004701537648098),
1444+
(-2.5, -0.056243716497674054),
1445+
(-3.5, -1.309006684993042),
1446+
# values near 0
1447+
(0.1, 2.252712651734206),
1448+
(0.01, 4.5994798780420219),
1449+
(1e-8, 18.420680738180209),
1450+
(1e-16, 36.841361487904734),
1451+
(1e-30, 69.077552789821368),
1452+
(1e-160, 368.41361487904732),
1453+
(1e-308, 709.19620864216608),
1454+
(5.6e-309, 709.77602713741896),
1455+
(5.5e-309, 709.79404564292167),
1456+
(1e-309, 711.49879373516012),
1457+
(1e-323, 743.74692474082133),
1458+
(5e-324, 744.44007192138122),
1459+
(-0.1, 2.3689613327287886),
1460+
(-0.01, 4.6110249927528013),
1461+
(-1e-8, 18.420680749724522),
1462+
(-1e-16, 36.841361487904734),
1463+
(-1e-30, 69.077552789821368),
1464+
(-1e-160, 368.41361487904732),
1465+
(-1e-308, 709.19620864216608),
1466+
(-5.6e-309, 709.77602713741896),
1467+
(-5.5e-309, 709.79404564292167),
1468+
(-1e-309, 711.49879373516012),
1469+
(-1e-323, 743.74692474082133),
1470+
(-5e-324, 744.44007192138122),
1471+
# values near negative integers
1472+
(-0.99999999999999989, 36.736800569677101),
1473+
(-1.0000000000000002, 36.043653389117154),
1474+
(-1.9999999999999998, 35.350506208557213),
1475+
(-2.0000000000000004, 34.657359027997266),
1476+
(-100.00000000000001, -331.85460524980607),
1477+
(-99.999999999999986, -331.85460524980596),
1478+
# large inputs
1479+
(170, 701.43726380873704),
1480+
(171, 706.57306224578736),
1481+
(171.624, 709.78077443669895),
1482+
(171.625, 709.78591682948365),
1483+
(172, 711.71472580228999),
1484+
(2000, 13198.923448054265),
1485+
(2.55998332785163e305, 1.7976931348623099e+308),
1486+
# inputs for which gamma(x) is tiny
1487+
(-100.5, -364.90096830942736),
1488+
(-160.5, -656.88005261126432),
1489+
(-170.5, -707.99843314507882),
1490+
(-171.5, -713.14301641168481),
1491+
(-176.5, -738.95247590846486),
1492+
(-177.5, -744.13144651738037),
1493+
(-178.5, -749.3160351186001),
1494+
(-1000.5, -5914.4377011168517),
1495+
(-30000.5, -279278.6629959144),
1496+
(-4503599627370495.5, -1.5782258434492883e+17),
1497+
# results close to 0: positive argument ...
1498+
(0.99999999999999989, 2.220446049250313e-16),
1499+
(1.0000000000000002, -3.3306690738754696e-16),
1500+
(1.9999999999999998, 0.0),
1501+
(2.0000000000000004, 6.661338147750939e-16),
1502+
# ... and negative argument
1503+
(-2.7476826467, -5.24771337495622e-11),
1504+
(-2.457024738, 3.346471988407984e-10)
1505+
]
1506+
self.executeFnTest(values, math.lgamma, 'math.lgamma')
1507+
1508+
12981509
def testFsum(self):
12991510
# math.fsum relies on exact rounding for correct operation.
13001511
# There's a known problem with IA32 floating-point that causes

0 commit comments

Comments
 (0)