@@ -45,6 +45,30 @@ def py_factorial(n):
45
45
outer *= inner
46
46
return outer << (n - count_set_bits (n ))
47
47
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
+
48
72
def to_ulps (x ):
49
73
"""Convert a non-NaN float x to an integer, in such a way that
50
74
adjacent floats are converted to adjacent integers. Then
@@ -264,6 +288,7 @@ def testLog(self):
264
288
math .log (MyFloat (), 7.4 )
265
289
self .ftest ('log(MyFloat(), MyFloat())' , math .log (MyFloat (), MyFloat ()), 1 )
266
290
math .log (10 , MyFloat ())
291
+ self .assertRaises (ValueError , math .log , 0 )
267
292
268
293
def testIsfinite (self ):
269
294
self .assertTrue (math .isfinite (0.0 ))
@@ -643,6 +668,153 @@ def testAtan2(self):
643
668
self .ftest ('atan2(MyFloat(),MyFloat())' , math .atan2 (MyFloat (),MyFloat ()), 0.7853981633974483 )
644
669
self .ftest ('atan2(BIG_INT,MyFloat())' , math .atan2 (BIG_INT ,MyFloat ()), 1.5707963267948966 )
645
670
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
+
646
818
def test_fabs (self ):
647
819
self .assertEqual (math .fabs (- 1 ), 1 )
648
820
self .assertEqual (math .fabs (0 ), 0 )
0 commit comments