Skip to content

Commit 5cf1716

Browse files
committed
[GR-10462] Math module doesn't have implemented cosh, sinh, tan, tanh asinh, atan and atanh.
PullRequest: graalpython/85
2 parents ecef6d8 + ee3896d commit 5cf1716

File tree

2 files changed

+530
-7
lines changed

2 files changed

+530
-7
lines changed

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

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,30 @@ def py_factorial(n):
4545
outer *= inner
4646
return outer << (n - count_set_bits(n))
4747

48+
def ulp(x):
49+
"""Return the value of the least significant bit of a
50+
float x, such that the first float bigger than x is x+ulp(x).
51+
Then, given an expected result x and a tolerance of n ulps,
52+
the result y should be such that abs(y-x) <= n * ulp(x).
53+
The results from this function will only make sense on platforms
54+
where native doubles are represented in IEEE 754 binary64 format.
55+
"""
56+
x = abs(float(x))
57+
if math.isnan(x) or math.isinf(x):
58+
return x
59+
60+
# Find next float up from x.
61+
n = struct.unpack('<q', struct.pack('<d', x))[0]
62+
x_next = struct.unpack('<d', struct.pack('<q', n + 1))[0]
63+
if math.isinf(x_next):
64+
# Corner case: x was the largest finite float. Then it's
65+
# not an exact power of two, so we can take the difference
66+
# between x and the previous float.
67+
x_prev = struct.unpack('<d', struct.pack('<q', n - 1))[0]
68+
return x - x_prev
69+
else:
70+
return x_next - x
71+
4872
def to_ulps(x):
4973
"""Convert a non-NaN float x to an integer, in such a way that
5074
adjacent floats are converted to adjacent integers. Then
@@ -264,6 +288,7 @@ def testLog(self):
264288
math.log(MyFloat(), 7.4)
265289
self.ftest('log(MyFloat(), MyFloat())', math.log(MyFloat(), MyFloat()), 1)
266290
math.log(10, MyFloat())
291+
self.assertRaises(ValueError, math.log, 0)
267292

268293
def testIsfinite(self):
269294
self.assertTrue(math.isfinite(0.0))
@@ -643,6 +668,153 @@ def testAtan2(self):
643668
self.ftest('atan2(MyFloat(),MyFloat())', math.atan2(MyFloat(),MyFloat()), 0.7853981633974483)
644669
self.ftest('atan2(BIG_INT,MyFloat())', math.atan2(BIG_INT,MyFloat()), 1.5707963267948966)
645670

671+
def testCos(self):
672+
self.assertRaises(TypeError, math.cos)
673+
# TODO uncomment when GR-10346 will be fixed
674+
#self.ftest('cos(-pi/2)', math.cos(-math.pi/2), 0, abs_tol=ulp(1))
675+
self.ftest('cos(0)', math.cos(0), 1)
676+
# TODO uncomment when GR-10346 will be fixed
677+
#self.ftest('cos(pi/2)', math.cos(math.pi/2), 0, abs_tol=ulp(1))
678+
self.ftest('cos(pi)', math.cos(math.pi), -1)
679+
try:
680+
self.assertTrue(math.isnan(math.cos(INF)))
681+
self.assertTrue(math.isnan(math.cos(NINF)))
682+
except ValueError:
683+
self.assertRaises(ValueError, math.cos, INF)
684+
self.assertRaises(ValueError, math.cos, NINF)
685+
self.assertTrue(math.isnan(math.cos(NAN)))
686+
687+
#test of specializations
688+
self.ftest('cos(BIG_INT)', math.cos(BIG_INT), 0.4145587418469303)
689+
self.ftest('cos(MyFloat())', math.cos(MyFloat()), 0.8253356149096783)
690+
self.assertRaises(TypeError, math.cos, 'ahoj')
691+
692+
def testCosh(self):
693+
self.assertRaises(TypeError, math.cosh)
694+
self.ftest('cosh(0)', math.cosh(0), 1)
695+
# TODO uncomment when GR-10346 will be fixed
696+
#self.ftest('cosh(2)-2*cosh(1)**2', math.cosh(2)-2*math.cosh(1)**2, -1) # Thanks to Lambert
697+
self.assertEqual(math.cosh(INF), INF)
698+
self.assertEqual(math.cosh(NINF), INF)
699+
self.assertTrue(math.isnan(math.cosh(NAN)))
700+
701+
# test of specializations
702+
self.ftest('cosh(MyFloat())', math.cosh(MyFloat()), 1.1854652182422676)
703+
self.assertRaises(TypeError, math.cosh, 'ahoj')
704+
self.assertRaises(OverflowError, math.cosh, BIG_INT)
705+
706+
def testSin(self):
707+
self.assertRaises(TypeError, math.sin)
708+
self.ftest('sin(0)', math.sin(0), 0)
709+
self.ftest('sin(pi/2)', math.sin(math.pi/2), 1)
710+
self.ftest('sin(-pi/2)', math.sin(-math.pi/2), -1)
711+
try:
712+
self.assertTrue(math.isnan(math.sin(INF)))
713+
self.assertTrue(math.isnan(math.sin(NINF)))
714+
except ValueError:
715+
self.assertRaises(ValueError, math.sin, INF)
716+
self.assertRaises(ValueError, math.sin, NINF)
717+
self.assertTrue(math.isnan(math.sin(NAN)))
718+
719+
# test of specializations
720+
self.ftest('sin(MyFloat())', math.sin(MyFloat()), 0.5646424733950354)
721+
self.assertRaises(TypeError, math.sin, 'ahoj')
722+
self.ftest('sin(MyFloat())', math.sin(BIG_INT), -0.9100225544228506)
723+
724+
def testSinh(self):
725+
self.assertRaises(TypeError, math.sinh)
726+
self.ftest('sinh(0)', math.sinh(0), 0)
727+
# TODO uncomment when GR-10346 will be fixed
728+
#self.ftest('sinh(1)**2-cosh(1)**2', math.sinh(1)**2-math.cosh(1)**2, -1)
729+
self.ftest('sinh(1)+sinh(-1)', math.sinh(1)+math.sinh(-1), 0)
730+
self.assertEqual(math.sinh(INF), INF)
731+
self.assertEqual(math.sinh(NINF), NINF)
732+
self.assertTrue(math.isnan(math.sinh(NAN)))
733+
734+
# test of specializations
735+
self.ftest('sinh(MyFloat())', math.sinh(MyFloat()), 0.6366535821482412)
736+
self.assertRaises(TypeError, math.sinh, 'ahoj')
737+
self.assertRaises(OverflowError, math.sinh, BIG_INT)
738+
739+
def testTan(self):
740+
self.assertRaises(TypeError, math.tan)
741+
self.ftest('tan(0)', math.tan(0), 0)
742+
# TODO uncomment when GR-10346 will be fixed
743+
#self.ftest('tan(pi/4)', math.tan(math.pi/4), 1)
744+
#self.ftest('tan(-pi/4)', math.tan(-math.pi/4), -1)
745+
try:
746+
self.assertTrue(math.isnan(math.tan(INF)))
747+
self.assertTrue(math.isnan(math.tan(NINF)))
748+
except:
749+
self.assertRaises(ValueError, math.tan, INF)
750+
self.assertRaises(ValueError, math.tan, NINF)
751+
self.assertTrue(math.isnan(math.tan(NAN)))
752+
753+
# test of specializations
754+
self.ftest('tan(MyFloat())', math.tan(MyFloat()), 0.6841368083416923)
755+
self.assertRaises(TypeError, math.tan, 'ahoj')
756+
self.ftest('tan(BIG_INT)', math.tan(BIG_INT), -2.1951594854049974)
757+
758+
def testTanh(self):
759+
self.assertRaises(TypeError, math.tanh)
760+
self.ftest('tanh(0)', math.tanh(0), 0)
761+
# TODO uncomment when GR-10346 will be fixed
762+
#self.ftest('tanh(1)+tanh(-1)', math.tanh(1)+math.tanh(-1), 0, abs_tol=ulp(1))
763+
self.ftest('tanh(inf)', math.tanh(INF), 1)
764+
self.ftest('tanh(-inf)', math.tanh(NINF), -1)
765+
self.assertTrue(math.isnan(math.tanh(NAN)))
766+
767+
# test of specializations
768+
self.ftest('tanh(MyFloat())', math.tanh(MyFloat()), 0.5370495669980353)
769+
self.assertRaises(TypeError, math.tanh, 'ahoj')
770+
self.ftest('tanh(BIG_INT)', math.tanh(BIG_INT), 1.0)
771+
772+
def testAsinh(self):
773+
self.assertRaises(TypeError, math.asinh)
774+
self.ftest('asinh(0)', math.asinh(0), 0)
775+
# TODO uncomment when GR-10346 will be fixed
776+
#self.ftest('asinh(1)', math.asinh(1), 0.88137358701954305)
777+
#self.ftest('asinh(-1)', math.asinh(-1), -0.88137358701954305)
778+
self.assertEqual(math.asinh(INF), INF)
779+
self.assertEqual(math.asinh(NINF), NINF)
780+
self.assertTrue(math.isnan(math.asinh(NAN)))
781+
782+
# test of specializations
783+
self.ftest('asinh(MyFloat())', math.asinh(MyFloat()), 0.5688248987322475)
784+
self.assertRaises(TypeError, math.asinh, 'ahoj')
785+
self.ftest('asinh(BIG_INT)', math.asinh(BIG_INT), 72.07328430666527)
786+
787+
def testAtan(self):
788+
self.assertRaises(TypeError, math.atan)
789+
self.ftest('atan(-1)', math.atan(-1), -math.pi/4)
790+
self.ftest('atan(0)', math.atan(0), 0)
791+
self.ftest('atan(1)', math.atan(1), math.pi/4)
792+
self.ftest('atan(inf)', math.atan(INF), math.pi/2)
793+
self.ftest('atan(-inf)', math.atan(NINF), -math.pi/2)
794+
self.assertTrue(math.isnan(math.atan(NAN)))
795+
796+
# test of specializations
797+
self.ftest('atan(MyFloat())', math.atan(MyFloat()), 0.5404195002705842)
798+
self.assertRaises(TypeError, math.atan, 'ahoj')
799+
self.ftest('atan(BIG_INT)', math.atan(BIG_INT), 1.5707963267948966)
800+
801+
def testAtanh(self):
802+
self.assertRaises(TypeError, math.atan)
803+
self.ftest('atanh(0)', math.atanh(0), 0)
804+
# TODO uncomment when GR-10346 will be fixed
805+
#self.ftest('atanh(0.5)', math.atanh(0.5), 0.54930614433405489)
806+
#self.ftest('atanh(-0.5)', math.atanh(-0.5), -0.54930614433405489)
807+
self.assertRaises(ValueError, math.atanh, 1)
808+
self.assertRaises(ValueError, math.atanh, -1)
809+
self.assertRaises(ValueError, math.atanh, INF)
810+
self.assertRaises(ValueError, math.atanh, NINF)
811+
self.assertTrue(math.isnan(math.atanh(NAN)))
812+
813+
# test of specializations
814+
self.ftest('atanh(MyFloat())', math.atanh(MyFloat()), 0.6931471805599453)
815+
self.assertRaises(TypeError, math.atanh, 'ahoj')
816+
self.assertRaises(ValueError, math.atanh, BIG_INT)
817+
646818
def test_fabs(self):
647819
self.assertEqual(math.fabs(-1), 1)
648820
self.assertEqual(math.fabs(0), 0)

0 commit comments

Comments
 (0)