blob: b9ad8c5ce7c5c684504bd06a992053427567740e [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
Eric Smith8c663262007-08-25 02:26:07 +0000136
137 self.assertEqual(format(1.0, 'f'), '1.000000')
Eric Smith8c663262007-08-25 02:26:07 +0000138
139 self.assertEqual(format(-1.0, 'f'), '-1.000000')
Eric Smith8c663262007-08-25 02:26:07 +0000140
141 self.assertEqual(format( 1.0, ' f'), ' 1.000000')
142 self.assertEqual(format(-1.0, ' f'), '-1.000000')
143 self.assertEqual(format( 1.0, '+f'), '+1.000000')
144 self.assertEqual(format(-1.0, '+f'), '-1.000000')
145
146 # % formatting
147 self.assertEqual(format(-1.0, '%'), '-100.000000%')
148
149 # conversion to string should fail
150 self.assertRaises(ValueError, format, 3.0, "s")
151
Eric Smith7b69c6c2008-01-27 21:07:59 +0000152 # other format specifiers shouldn't work on floats,
153 # in particular int specifiers
154 for format_spec in ([chr(x) for x in range(ord('a'), ord('z')+1)] +
155 [chr(x) for x in range(ord('A'), ord('Z')+1)]):
156 if not format_spec in 'eEfFgGn%':
157 self.assertRaises(ValueError, format, 0.0, format_spec)
158 self.assertRaises(ValueError, format, 1.0, format_spec)
159 self.assertRaises(ValueError, format, -1.0, format_spec)
160 self.assertRaises(ValueError, format, 1e100, format_spec)
161 self.assertRaises(ValueError, format, -1e100, format_spec)
162 self.assertRaises(ValueError, format, 1e-100, format_spec)
163 self.assertRaises(ValueError, format, -1e-100, format_spec)
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000164
Christian Heimes827b35c2007-12-10 22:19:17 +0000165class ReprTestCase(unittest.TestCase):
166 def test_repr(self):
167 floats_file = open(os.path.join(os.path.split(__file__)[0],
168 'floating_points.txt'))
169 for line in floats_file:
170 line = line.strip()
171 if not line or line.startswith('#'):
172 continue
173 v = eval(line)
174 self.assertEqual(v, eval(repr(v)))
175 floats_file.close()
176
Christian Heimes99170a52007-12-19 02:07:34 +0000177# Beginning with Python 2.6 float has cross platform compatible
178# ways to create and representate inf and nan
179class InfNanTest(unittest.TestCase):
180 def test_inf_from_str(self):
181 self.assert_(isinf(float("inf")))
182 self.assert_(isinf(float("+inf")))
183 self.assert_(isinf(float("-inf")))
184
185 self.assertEqual(repr(float("inf")), "inf")
186 self.assertEqual(repr(float("+inf")), "inf")
187 self.assertEqual(repr(float("-inf")), "-inf")
188
189 self.assertEqual(repr(float("INF")), "inf")
190 self.assertEqual(repr(float("+Inf")), "inf")
191 self.assertEqual(repr(float("-iNF")), "-inf")
192
193 self.assertEqual(str(float("inf")), "inf")
194 self.assertEqual(str(float("+inf")), "inf")
195 self.assertEqual(str(float("-inf")), "-inf")
196
197 self.assertRaises(ValueError, float, "info")
198 self.assertRaises(ValueError, float, "+info")
199 self.assertRaises(ValueError, float, "-info")
200 self.assertRaises(ValueError, float, "in")
201 self.assertRaises(ValueError, float, "+in")
202 self.assertRaises(ValueError, float, "-in")
203
204 def test_inf_as_str(self):
205 self.assertEqual(repr(1e300 * 1e300), "inf")
206 self.assertEqual(repr(-1e300 * 1e300), "-inf")
207
208 self.assertEqual(str(1e300 * 1e300), "inf")
209 self.assertEqual(str(-1e300 * 1e300), "-inf")
210
211 def test_nan_from_str(self):
212 self.assert_(isnan(float("nan")))
213 self.assert_(isnan(float("+nan")))
214 self.assert_(isnan(float("-nan")))
215
216 self.assertEqual(repr(float("nan")), "nan")
217 self.assertEqual(repr(float("+nan")), "nan")
218 self.assertEqual(repr(float("-nan")), "nan")
219
220 self.assertEqual(repr(float("NAN")), "nan")
221 self.assertEqual(repr(float("+NAn")), "nan")
222 self.assertEqual(repr(float("-NaN")), "nan")
223
224 self.assertEqual(str(float("nan")), "nan")
225 self.assertEqual(str(float("+nan")), "nan")
226 self.assertEqual(str(float("-nan")), "nan")
227
228 self.assertRaises(ValueError, float, "nana")
229 self.assertRaises(ValueError, float, "+nana")
230 self.assertRaises(ValueError, float, "-nana")
231 self.assertRaises(ValueError, float, "na")
232 self.assertRaises(ValueError, float, "+na")
233 self.assertRaises(ValueError, float, "-na")
234
235 def test_nan_as_str(self):
236 self.assertEqual(repr(1e300 * 1e300 * 0), "nan")
237 self.assertEqual(repr(-1e300 * 1e300 * 0), "nan")
238
239 self.assertEqual(str(1e300 * 1e300 * 0), "nan")
240 self.assertEqual(str(-1e300 * 1e300 * 0), "nan")
Christian Heimes827b35c2007-12-10 22:19:17 +0000241
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000242def test_main():
243 test_support.run_unittest(
244 FormatFunctionsTestCase,
245 UnknownFormatTestCase,
Eric Smith8c663262007-08-25 02:26:07 +0000246 IEEEFormatTestCase,
Christian Heimes827b35c2007-12-10 22:19:17 +0000247 FormatTestCase,
Christian Heimes99170a52007-12-19 02:07:34 +0000248 ReprTestCase,
249 InfNanTest,
Christian Heimesb76922a2007-12-11 01:06:40 +0000250 )
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000251
252if __name__ == '__main__':
253 test_main()