@@ -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+
4872def 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