blob: 0de65cb1a58b4a40d6c161914653f192ea5e0c7f [file] [log] [blame]
Michael W. Hudsonba283e22005-05-27 15:23:20 +00001
2import unittest, struct
Christian Heimes827b35c2007-12-10 22:19:17 +00003import os
Michael W. Hudsonba283e22005-05-27 15:23:20 +00004from test import test_support
5
Christian Heimes99170a52007-12-19 02:07:34 +00006def isinf(x):
7 return x * 0.5 == x
8
9def isnan(x):
10 return x != x
11
Michael W. Hudsonba283e22005-05-27 15:23:20 +000012class FormatFunctionsTestCase(unittest.TestCase):
13
14 def setUp(self):
15 self.save_formats = {'double':float.__getformat__('double'),
16 'float':float.__getformat__('float')}
17
18 def tearDown(self):
19 float.__setformat__('double', self.save_formats['double'])
20 float.__setformat__('float', self.save_formats['float'])
21
22 def test_getformat(self):
23 self.assert_(float.__getformat__('double') in
24 ['unknown', 'IEEE, big-endian', 'IEEE, little-endian'])
25 self.assert_(float.__getformat__('float') in
26 ['unknown', 'IEEE, big-endian', 'IEEE, little-endian'])
27 self.assertRaises(ValueError, float.__getformat__, 'chicken')
28 self.assertRaises(TypeError, float.__getformat__, 1)
29
30 def test_setformat(self):
31 for t in 'double', 'float':
32 float.__setformat__(t, 'unknown')
33 if self.save_formats[t] == 'IEEE, big-endian':
34 self.assertRaises(ValueError, float.__setformat__,
35 t, 'IEEE, little-endian')
36 elif self.save_formats[t] == 'IEEE, little-endian':
37 self.assertRaises(ValueError, float.__setformat__,
38 t, 'IEEE, big-endian')
39 else:
40 self.assertRaises(ValueError, float.__setformat__,
41 t, 'IEEE, big-endian')
42 self.assertRaises(ValueError, float.__setformat__,
43 t, 'IEEE, little-endian')
44 self.assertRaises(ValueError, float.__setformat__,
45 t, 'chicken')
46 self.assertRaises(ValueError, float.__setformat__,
47 'chicken', 'unknown')
48
Guido van Rossum2be161d2007-05-15 20:43:51 +000049BE_DOUBLE_INF = b'\x7f\xf0\x00\x00\x00\x00\x00\x00'
Guido van Rossum254348e2007-11-21 19:29:53 +000050LE_DOUBLE_INF = bytes(reversed(BE_DOUBLE_INF))
Guido van Rossum2be161d2007-05-15 20:43:51 +000051BE_DOUBLE_NAN = b'\x7f\xf8\x00\x00\x00\x00\x00\x00'
Guido van Rossum254348e2007-11-21 19:29:53 +000052LE_DOUBLE_NAN = bytes(reversed(BE_DOUBLE_NAN))
Michael W. Hudsonba283e22005-05-27 15:23:20 +000053
Guido van Rossum2be161d2007-05-15 20:43:51 +000054BE_FLOAT_INF = b'\x7f\x80\x00\x00'
Guido van Rossum254348e2007-11-21 19:29:53 +000055LE_FLOAT_INF = bytes(reversed(BE_FLOAT_INF))
Guido van Rossum2be161d2007-05-15 20:43:51 +000056BE_FLOAT_NAN = b'\x7f\xc0\x00\x00'
Guido van Rossum254348e2007-11-21 19:29:53 +000057LE_FLOAT_NAN = bytes(reversed(BE_FLOAT_NAN))
Michael W. Hudsonba283e22005-05-27 15:23:20 +000058
59# on non-IEEE platforms, attempting to unpack a bit pattern
60# representing an infinity or a NaN should raise an exception.
61
62class UnknownFormatTestCase(unittest.TestCase):
63 def setUp(self):
64 self.save_formats = {'double':float.__getformat__('double'),
65 'float':float.__getformat__('float')}
66 float.__setformat__('double', 'unknown')
67 float.__setformat__('float', 'unknown')
Tim Peters5d36a552005-06-03 22:40:27 +000068
Michael W. Hudsonba283e22005-05-27 15:23:20 +000069 def tearDown(self):
70 float.__setformat__('double', self.save_formats['double'])
71 float.__setformat__('float', self.save_formats['float'])
72
73 def test_double_specials_dont_unpack(self):
74 for fmt, data in [('>d', BE_DOUBLE_INF),
75 ('>d', BE_DOUBLE_NAN),
76 ('<d', LE_DOUBLE_INF),
77 ('<d', LE_DOUBLE_NAN)]:
78 self.assertRaises(ValueError, struct.unpack, fmt, data)
79
80 def test_float_specials_dont_unpack(self):
81 for fmt, data in [('>f', BE_FLOAT_INF),
82 ('>f', BE_FLOAT_NAN),
83 ('<f', LE_FLOAT_INF),
84 ('<f', LE_FLOAT_NAN)]:
85 self.assertRaises(ValueError, struct.unpack, fmt, data)
86
87
88# on an IEEE platform, all we guarantee is that bit patterns
89# representing infinities or NaNs do not raise an exception; all else
90# is accident (today).
Guido van Rossum04110fb2007-08-24 16:32:05 +000091# let's also try to guarantee that -0.0 and 0.0 don't get confused.
Michael W. Hudsonba283e22005-05-27 15:23:20 +000092
93class IEEEFormatTestCase(unittest.TestCase):
94 if float.__getformat__("double").startswith("IEEE"):
95 def test_double_specials_do_unpack(self):
96 for fmt, data in [('>d', BE_DOUBLE_INF),
97 ('>d', BE_DOUBLE_NAN),
98 ('<d', LE_DOUBLE_INF),
99 ('<d', LE_DOUBLE_NAN)]:
100 struct.unpack(fmt, data)
101
102 if float.__getformat__("float").startswith("IEEE"):
103 def test_float_specials_do_unpack(self):
104 for fmt, data in [('>f', BE_FLOAT_INF),
105 ('>f', BE_FLOAT_NAN),
106 ('<f', LE_FLOAT_INF),
107 ('<f', LE_FLOAT_NAN)]:
108 struct.unpack(fmt, data)
109
Guido van Rossum04110fb2007-08-24 16:32:05 +0000110 if float.__getformat__("double").startswith("IEEE"):
111 def test_negative_zero(self):
112 import math
113 def pos_pos():
114 return 0.0, math.atan2(0.0, -1)
115 def pos_neg():
116 return 0.0, math.atan2(-0.0, -1)
117 def neg_pos():
118 return -0.0, math.atan2(0.0, -1)
119 def neg_neg():
120 return -0.0, math.atan2(-0.0, -1)
121 self.assertEquals(pos_pos(), neg_pos())
122 self.assertEquals(pos_neg(), neg_neg())
123
Eric Smith8c663262007-08-25 02:26:07 +0000124class FormatTestCase(unittest.TestCase):
Eric Smith11fe3e02007-08-31 01:33:06 +0000125 def test_format(self):
Eric Smith8c663262007-08-25 02:26:07 +0000126 # these should be rewritten to use both format(x, spec) and
127 # x.__format__(spec)
128
129 self.assertEqual(format(0.0, 'f'), '0.000000')
130
131 # the default is 'g', except for empty format spec
132 self.assertEqual(format(0.0, ''), '0.0')
133 self.assertEqual(format(0.01, ''), '0.01')
134 self.assertEqual(format(0.01, 'g'), '0.01')
135
136 self.assertEqual(format(0, 'f'), '0.000000')
137
138 self.assertEqual(format(1.0, 'f'), '1.000000')
139 self.assertEqual(format(1, 'f'), '1.000000')
140
141 self.assertEqual(format(-1.0, 'f'), '-1.000000')
142 self.assertEqual(format(-1, 'f'), '-1.000000')
143
144 self.assertEqual(format( 1.0, ' f'), ' 1.000000')
145 self.assertEqual(format(-1.0, ' f'), '-1.000000')
146 self.assertEqual(format( 1.0, '+f'), '+1.000000')
147 self.assertEqual(format(-1.0, '+f'), '-1.000000')
148
149 # % formatting
150 self.assertEqual(format(-1.0, '%'), '-100.000000%')
151
152 # conversion to string should fail
153 self.assertRaises(ValueError, format, 3.0, "s")
154
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000155
Christian Heimes827b35c2007-12-10 22:19:17 +0000156class ReprTestCase(unittest.TestCase):
157 def test_repr(self):
158 floats_file = open(os.path.join(os.path.split(__file__)[0],
159 'floating_points.txt'))
160 for line in floats_file:
161 line = line.strip()
162 if not line or line.startswith('#'):
163 continue
164 v = eval(line)
165 self.assertEqual(v, eval(repr(v)))
166 floats_file.close()
167
Christian Heimes99170a52007-12-19 02:07:34 +0000168# Beginning with Python 2.6 float has cross platform compatible
169# ways to create and representate inf and nan
170class InfNanTest(unittest.TestCase):
171 def test_inf_from_str(self):
172 self.assert_(isinf(float("inf")))
173 self.assert_(isinf(float("+inf")))
174 self.assert_(isinf(float("-inf")))
175
176 self.assertEqual(repr(float("inf")), "inf")
177 self.assertEqual(repr(float("+inf")), "inf")
178 self.assertEqual(repr(float("-inf")), "-inf")
179
180 self.assertEqual(repr(float("INF")), "inf")
181 self.assertEqual(repr(float("+Inf")), "inf")
182 self.assertEqual(repr(float("-iNF")), "-inf")
183
184 self.assertEqual(str(float("inf")), "inf")
185 self.assertEqual(str(float("+inf")), "inf")
186 self.assertEqual(str(float("-inf")), "-inf")
187
188 self.assertRaises(ValueError, float, "info")
189 self.assertRaises(ValueError, float, "+info")
190 self.assertRaises(ValueError, float, "-info")
191 self.assertRaises(ValueError, float, "in")
192 self.assertRaises(ValueError, float, "+in")
193 self.assertRaises(ValueError, float, "-in")
194
195 def test_inf_as_str(self):
196 self.assertEqual(repr(1e300 * 1e300), "inf")
197 self.assertEqual(repr(-1e300 * 1e300), "-inf")
198
199 self.assertEqual(str(1e300 * 1e300), "inf")
200 self.assertEqual(str(-1e300 * 1e300), "-inf")
201
202 def test_nan_from_str(self):
203 self.assert_(isnan(float("nan")))
204 self.assert_(isnan(float("+nan")))
205 self.assert_(isnan(float("-nan")))
206
207 self.assertEqual(repr(float("nan")), "nan")
208 self.assertEqual(repr(float("+nan")), "nan")
209 self.assertEqual(repr(float("-nan")), "nan")
210
211 self.assertEqual(repr(float("NAN")), "nan")
212 self.assertEqual(repr(float("+NAn")), "nan")
213 self.assertEqual(repr(float("-NaN")), "nan")
214
215 self.assertEqual(str(float("nan")), "nan")
216 self.assertEqual(str(float("+nan")), "nan")
217 self.assertEqual(str(float("-nan")), "nan")
218
219 self.assertRaises(ValueError, float, "nana")
220 self.assertRaises(ValueError, float, "+nana")
221 self.assertRaises(ValueError, float, "-nana")
222 self.assertRaises(ValueError, float, "na")
223 self.assertRaises(ValueError, float, "+na")
224 self.assertRaises(ValueError, float, "-na")
225
226 def test_nan_as_str(self):
227 self.assertEqual(repr(1e300 * 1e300 * 0), "nan")
228 self.assertEqual(repr(-1e300 * 1e300 * 0), "nan")
229
230 self.assertEqual(str(1e300 * 1e300 * 0), "nan")
231 self.assertEqual(str(-1e300 * 1e300 * 0), "nan")
Christian Heimes827b35c2007-12-10 22:19:17 +0000232
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000233def test_main():
234 test_support.run_unittest(
235 FormatFunctionsTestCase,
236 UnknownFormatTestCase,
Eric Smith8c663262007-08-25 02:26:07 +0000237 IEEEFormatTestCase,
Christian Heimes827b35c2007-12-10 22:19:17 +0000238 FormatTestCase,
Christian Heimes99170a52007-12-19 02:07:34 +0000239 ReprTestCase,
240 InfNanTest,
Christian Heimesb76922a2007-12-11 01:06:40 +0000241 )
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000242
243if __name__ == '__main__':
244 test_main()