5
5
import math
6
6
import unittest
7
7
import sys
8
+ import struct
8
9
9
10
eps = 1E-05
10
11
INF = float ('inf' )
11
12
NINF = float ('-inf' )
12
13
NAN = float ('nan' )
14
+ LONG_INT = 6227020800
15
+ BIG_INT = 9999992432902008176640000999999
13
16
14
17
""" The next three methods are needed for testing factorials
15
18
"""
@@ -42,6 +45,40 @@ def py_factorial(n):
42
45
outer *= inner
43
46
return outer << (n - count_set_bits (n ))
44
47
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
+
45
82
def result_check (expected , got , ulp_tol = 5 , abs_tol = 0.0 ):
46
83
# Common logic of MathTests.(ftest, test_testcases, test_mtestcases)
47
84
"""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):
87
124
else :
88
125
return None
89
126
127
+ class MyFloat :
128
+ def __float__ (self ):
129
+ return 0.6
130
+
90
131
class MathTests (unittest .TestCase ):
91
132
92
133
def ftest (self , name , got , expected , ulp_tol = 5 , abs_tol = 0.0 ):
@@ -110,6 +151,150 @@ def testConstants(self):
110
151
# math.tau since 3.6
111
152
self .assertEqual (math .tau , 2 * math .pi )
112
153
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
+
113
298
def test_ceil_basic (self ):
114
299
self .assertEqual (math .ceil (10 ), 10 )
115
300
self .assertEqual (math .ceil (- 10 ), - 10 )
@@ -236,6 +421,7 @@ def test_isnan(self):
236
421
self .assertRaises (TypeError , math .isnan , 'hello' )
237
422
238
423
self .assertFalse (math .isnan (False ))
424
+ self .assertFalse (math .isnan (MyFloat ()))
239
425
240
426
def test_fabs (self ):
241
427
self .assertEqual (math .fabs (- 1 ), 1 )
0 commit comments