3
3
"""
4
4
from __future__ import division , absolute_import , print_function
5
5
6
+ import os
6
7
import fractions
8
+ import platform
9
+
10
+ import pytest
7
11
import numpy as np
8
12
9
13
from numpy .testing import (
12
16
dec
13
17
)
14
18
15
- float_types = [np .half , np .single , np .double , np .longdouble ]
16
-
17
- def test_float_as_integer_ratio ():
18
- # derived from the cpython test "test_floatasratio"
19
- for ftype in float_types :
20
- for f , ratio in [
21
- (0.875 , (7 , 8 )),
22
- (- 0.875 , (- 7 , 8 )),
23
- (0.0 , (0 , 1 )),
24
- (11.5 , (23 , 2 )),
25
- ]:
26
- assert_equal (ftype (f ).as_integer_ratio (), ratio )
27
-
28
- rstate = np .random .RandomState (0 )
29
- fi = np .finfo (ftype )
30
- for i in range (1000 ):
31
- exp = rstate .randint (fi .minexp , fi .maxexp - 1 )
32
- frac = rstate .rand ()
33
- f = np .ldexp (frac , exp , dtype = ftype )
34
-
35
- n , d = f .as_integer_ratio ()
36
-
37
- try :
38
- dn = np .longdouble (str (n ))
39
- df = np .longdouble (str (d ))
40
- except (OverflowError , RuntimeWarning ):
41
- # the values may not fit in any float type
42
- continue
19
+ class TestAsIntegerRatio (object ):
20
+ # derived in part from the cpython test "test_floatasratio"
43
21
44
- assert_equal (
45
- dn / df , f ,
46
- "{}/{} (dtype={})" .format (n , d , ftype .__name__ ))
22
+ @pytest .mark .parametrize ("ftype" , [
23
+ np .half , np .single , np .double , np .longdouble ])
24
+ @pytest .mark .parametrize ("f, ratio" , [
25
+ (0.875 , (7 , 8 )),
26
+ (- 0.875 , (- 7 , 8 )),
27
+ (0.0 , (0 , 1 )),
28
+ (11.5 , (23 , 2 )),
29
+ ])
30
+ def test_small (self , ftype , f , ratio ):
31
+ assert_equal (ftype (f ).as_integer_ratio (), ratio )
47
32
33
+ @pytest .mark .parametrize ("ftype" , [
34
+ np .half , np .single , np .double , np .longdouble ])
35
+ def test_simple_fractions (self , ftype ):
48
36
R = fractions .Fraction
49
37
assert_equal (R (0 , 1 ),
50
38
R (* ftype (0.0 ).as_integer_ratio ()))
@@ -55,25 +43,67 @@ def test_float_as_integer_ratio():
55
43
assert_equal (R (- 2100 , 1 ),
56
44
R (* ftype (- 2100.0 ).as_integer_ratio ()))
57
45
46
+ @pytest .mark .parametrize ("ftype" , [
47
+ np .half , np .single , np .double , np .longdouble ])
48
+ def test_errors (self , ftype ):
58
49
assert_raises (OverflowError , ftype ('inf' ).as_integer_ratio )
59
50
assert_raises (OverflowError , ftype ('-inf' ).as_integer_ratio )
60
51
assert_raises (ValueError , ftype ('nan' ).as_integer_ratio )
61
52
53
+ def test_against_known_values (self ):
54
+ R = fractions .Fraction
55
+ assert_equal (R (1075 , 512 ),
56
+ R (* np .half (2.1 ).as_integer_ratio ()))
57
+ assert_equal (R (- 1075 , 512 ),
58
+ R (* np .half (- 2.1 ).as_integer_ratio ()))
59
+ assert_equal (R (4404019 , 2097152 ),
60
+ R (* np .single (2.1 ).as_integer_ratio ()))
61
+ assert_equal (R (- 4404019 , 2097152 ),
62
+ R (* np .single (- 2.1 ).as_integer_ratio ()))
63
+ assert_equal (R (4728779608739021 , 2251799813685248 ),
64
+ R (* np .double (2.1 ).as_integer_ratio ()))
65
+ assert_equal (R (- 4728779608739021 , 2251799813685248 ),
66
+ R (* np .double (- 2.1 ).as_integer_ratio ()))
67
+ # longdouble is platform depedent
62
68
63
- assert_equal (R (1075 , 512 ),
64
- R (* np .half (2.1 ).as_integer_ratio ()))
65
- assert_equal (R (- 1075 , 512 ),
66
- R (* np .half (- 2.1 ).as_integer_ratio ()))
67
- assert_equal (R (4404019 , 2097152 ),
68
- R (* np .single (2.1 ).as_integer_ratio ()))
69
- assert_equal (R (- 4404019 , 2097152 ),
70
- R (* np .single (- 2.1 ).as_integer_ratio ()))
71
- assert_equal (R (4728779608739021 , 2251799813685248 ),
72
- R (* np .double (2.1 ).as_integer_ratio ()))
73
- assert_equal (R (- 4728779608739021 , 2251799813685248 ),
74
- R (* np .double (- 2.1 ).as_integer_ratio ()))
75
- # longdouble is platform depedent
69
+ @pytest .mark .parametrize ("ftype, frac_vals, exp_vals" , [
70
+ # dtype test cases generated using hypothesis
71
+ # first five generated cases per dtype
72
+ (np .half , [0.0 , 0.01154830649280303 , 0.31082276347447274 ,
73
+ 0.527350517124794 , 0.8308562335072596 ],
74
+ [0 , 1 , 0 , - 8 , 12 ]),
75
+ (np .single , [0.0 , 0.09248576989263226 , 0.8160498218131407 ,
76
+ 0.17389442853722373 , 0.7956044195067877 ],
77
+ [0 , 12 , 10 , 17 , - 26 ]),
78
+ (np .double , [0.0 , 0.031066908499895136 , 0.5214135908877832 ,
79
+ 0.45780736035689296 , 0.5906586745934036 ],
80
+ [0 , - 801 , 51 , 194 , - 653 ]),
81
+ pytest .param (
82
+ np .longdouble ,
83
+ [0.0 , 0.20492557202724854 , 0.4277180662199366 , 0.9888085019891495 ,
84
+ 0.9620175814461964 ],
85
+ [0 , - 7400 , 14266 , - 7822 , - 8721 ],
86
+ marks = [
87
+ pytest .mark .skipif (
88
+ np .finfo (np .double ) == np .finfo (np .longdouble ),
89
+ reason = "long double is same as double" ),
90
+ pytest .mark .skipif (
91
+ platform .machine ().startswith ("ppc" ),
92
+ reason = "IBM double double" ),
93
+ ]
94
+ )
95
+ ])
96
+ def test_roundtrip (self , ftype , frac_vals , exp_vals ):
97
+ for frac , exp in zip (frac_vals , exp_vals ):
98
+ f = np .ldexp (frac , exp , dtype = ftype )
99
+ n , d = f .as_integer_ratio ()
76
100
101
+ try :
102
+ # workaround for gh-9968
103
+ nf = np .longdouble (str (n ))
104
+ df = np .longdouble (str (d ))
105
+ except (OverflowError , RuntimeWarning ):
106
+ # the values may not fit in any float type
107
+ pytest .skip ("longdouble too small on this platform" )
77
108
78
- if __name__ == "__main__" :
79
- run_module_suite ()
109
+ assert_equal (nf / df , f , "{}/{}" .format (n , d ))
0 commit comments