Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
test_scalarprint.py404 linesDownload Raw Back to tests
1""" Test printing of scalar types.
2
3"""
4import platform
5
6import pytest
7
8import numpy as np
9from numpy.testing import IS_MUSL, assert_, assert_equal, assert_raises
10
11
12class TestRealScalars:
13    def test_str(self):
14        svals = [0.0, -0.0, 1, -1, np.inf, -np.inf, np.nan]
15        styps = [np.float16, np.float32, np.float64, np.longdouble]
16        wanted = [
17             ['0.0',  '0.0',  '0.0',  '0.0' ],  # noqa: E202
18             ['-0.0', '-0.0', '-0.0', '-0.0'],
19             ['1.0',  '1.0',  '1.0',  '1.0' ],  # noqa: E202
20             ['-1.0', '-1.0', '-1.0', '-1.0'],
21             ['inf',  'inf',  'inf',  'inf' ],  # noqa: E202
22             ['-inf', '-inf', '-inf', '-inf'],
23             ['nan',  'nan',  'nan',  'nan' ]]  # noqa: E202
24
25        for wants, val in zip(wanted, svals):
26            for want, styp in zip(wants, styps):
27                msg = f'for str({np.dtype(styp).name}({val!r}))'
28                assert_equal(str(styp(val)), want, err_msg=msg)
29
30    def test_scalar_cutoffs(self):
31        # test that both the str and repr of np.float64 behaves
32        # like python floats in python3.
33        def check(v):
34            assert_equal(str(np.float64(v)), str(v))
35            assert_equal(str(np.float64(v)), repr(v))
36            assert_equal(repr(np.float64(v)), f"np.float64({v!r})")
37            assert_equal(repr(np.float64(v)), f"np.float64({v})")
38
39        # check we use the same number of significant digits
40        check(1.12345678901234567890)
41        check(0.0112345678901234567890)
42
43        # check switch from scientific output to positional and back
44        check(1e-5)
45        check(1e-4)
46        check(1e15)
47        check(1e16)
48
49    test_cases_gh_28679 = [
50        (np.half, -0.000099, "-9.9e-05"),
51        (np.half, 0.0001, "0.0001"),
52        (np.half, 999, "999.0"),
53        (np.half, -1000, "-1e+03"),
54        (np.single, 0.000099, "9.9e-05"),
55        (np.single, -0.000100001, "-0.000100001"),
56        (np.single, 999999, "999999.0"),
57        (np.single, -1000000, "-1e+06")
58    ]
59
60    @pytest.mark.parametrize("dtype, input_val, expected_str", test_cases_gh_28679)
61    def test_gh_28679(self, dtype, input_val, expected_str):
62        # test cutoff to exponent notation for half and single
63        assert_equal(str(dtype(input_val)), expected_str)
64
65    test_cases_legacy_2_2 = [
66        (np.half(65504), "65500.0"),
67        (np.single(1.e15), "1000000000000000.0"),
68        (np.single(1.e16), "1e+16"),
69    ]
70
71    @pytest.mark.parametrize("input_val, expected_str", test_cases_legacy_2_2)
72    def test_legacy_2_2_mode(self, input_val, expected_str):
73        # test legacy cutoff to exponent notation for half and single
74        with np.printoptions(legacy='2.2'):
75            assert_equal(str(input_val), expected_str)
76
77    def test_dragon4(self):
78        # these tests are adapted from Ryan Juckett's dragon4 implementation,
79        # see dragon4.c for details.
80
81        fpos32 = lambda x, **k: np.format_float_positional(np.float32(x), **k)
82        fsci32 = lambda x, **k: np.format_float_scientific(np.float32(x), **k)
83        fpos64 = lambda x, **k: np.format_float_positional(np.float64(x), **k)
84        fsci64 = lambda x, **k: np.format_float_scientific(np.float64(x), **k)
85
86        preckwd = lambda prec: {'unique': False, 'precision': prec}
87
88        assert_equal(fpos32('1.0'), "1.")
89        assert_equal(fsci32('1.0'), "1.e+00")
90        assert_equal(fpos32('10.234'), "10.234")
91        assert_equal(fpos32('-10.234'), "-10.234")
92        assert_equal(fsci32('10.234'), "1.0234e+01")
93        assert_equal(fsci32('-10.234'), "-1.0234e+01")
94        assert_equal(fpos32('1000.0'), "1000.")
95        assert_equal(fpos32('1.0', precision=0), "1.")
96        assert_equal(fsci32('1.0', precision=0), "1.e+00")
97        assert_equal(fpos32('10.234', precision=0), "10.")
98        assert_equal(fpos32('-10.234', precision=0), "-10.")
99        assert_equal(fsci32('10.234', precision=0), "1.e+01")
100        assert_equal(fsci32('-10.234', precision=0), "-1.e+01")
101        assert_equal(fpos32('10.234', precision=2), "10.23")
102        assert_equal(fsci32('-10.234', precision=2), "-1.02e+01")
103        assert_equal(fsci64('9.9999999999999995e-08', **preckwd(16)),
104                            '9.9999999999999995e-08')
105        assert_equal(fsci64('9.8813129168249309e-324', **preckwd(16)),
106                            '9.8813129168249309e-324')
107        assert_equal(fsci64('9.9999999999999694e-311', **preckwd(16)),
108                            '9.9999999999999694e-311')
109
110        # test rounding
111        # 3.1415927410 is closest float32 to np.pi
112        assert_equal(fpos32('3.14159265358979323846', **preckwd(10)),
113                            "3.1415927410")
114        assert_equal(fsci32('3.14159265358979323846', **preckwd(10)),
115                            "3.1415927410e+00")
116        assert_equal(fpos64('3.14159265358979323846', **preckwd(10)),
117                            "3.1415926536")
118        assert_equal(fsci64('3.14159265358979323846', **preckwd(10)),
119                            "3.1415926536e+00")
120        # 299792448 is closest float32 to 299792458
121        assert_equal(fpos32('299792458.0', **preckwd(5)), "299792448.00000")
122        assert_equal(fsci32('299792458.0', **preckwd(5)), "2.99792e+08")
123        assert_equal(fpos64('299792458.0', **preckwd(5)), "299792458.00000")
124        assert_equal(fsci64('299792458.0', **preckwd(5)), "2.99792e+08")
125
126        assert_equal(fpos32('3.14159265358979323846', **preckwd(25)),
127                            "3.1415927410125732421875000")
128        assert_equal(fpos64('3.14159265358979323846', **preckwd(50)),
129                         "3.14159265358979311599796346854418516159057617187500")
130        assert_equal(fpos64('3.14159265358979323846'), "3.141592653589793")
131
132        # smallest numbers
133        assert_equal(fpos32(0.5**(126 + 23), unique=False, precision=149),
134                    "0.00000000000000000000000000000000000000000000140129846432"
135                    "4817070923729583289916131280261941876515771757068283889791"
136                    "08268586060148663818836212158203125")
137
138        assert_equal(fpos64(5e-324, unique=False, precision=1074),
139                    "0.00000000000000000000000000000000000000000000000000000000"
140                    "0000000000000000000000000000000000000000000000000000000000"
141                    "0000000000000000000000000000000000000000000000000000000000"
142                    "0000000000000000000000000000000000000000000000000000000000"
143                    "0000000000000000000000000000000000000000000000000000000000"
144                    "0000000000000000000000000000000000049406564584124654417656"
145                    "8792868221372365059802614324764425585682500675507270208751"
146                    "8652998363616359923797965646954457177309266567103559397963"
147                    "9877479601078187812630071319031140452784581716784898210368"
148                    "8718636056998730723050006387409153564984387312473397273169"
149                    "6151400317153853980741262385655911710266585566867681870395"
150                    "6031062493194527159149245532930545654440112748012970999954"
151                    "1931989409080416563324524757147869014726780159355238611550"
152                    "1348035264934720193790268107107491703332226844753335720832"
153                    "4319360923828934583680601060115061698097530783422773183292"
154                    "4790498252473077637592724787465608477820373446969953364701"
155                    "7972677717585125660551199131504891101451037862738167250955"
156                    "8373897335989936648099411642057026370902792427675445652290"
157                    "87538682506419718265533447265625")
158
159        # largest numbers
160        f32x = np.finfo(np.float32).max
161        assert_equal(fpos32(f32x, **preckwd(0)),
162                    "340282346638528859811704183484516925440.")
163        assert_equal(fpos64(np.finfo(np.float64).max, **preckwd(0)),
164                    "1797693134862315708145274237317043567980705675258449965989"
165                    "1747680315726078002853876058955863276687817154045895351438"
166                    "2464234321326889464182768467546703537516986049910576551282"
167                    "0762454900903893289440758685084551339423045832369032229481"
168                    "6580855933212334827479782620414472316873817718091929988125"
169                    "0404026184124858368.")
170        # Warning: In unique mode only the integer digits necessary for
171        # uniqueness are computed, the rest are 0.
172        assert_equal(fpos32(f32x),
173                    "340282350000000000000000000000000000000.")
174
175        # Further tests of zero-padding vs rounding in different combinations
176        # of unique, fractional, precision, min_digits
177        # precision can only reduce digits, not add them.
178        # min_digits can only extend digits, not reduce them.
179        assert_equal(fpos32(f32x, unique=True, fractional=True, precision=0),
180                    "340282350000000000000000000000000000000.")
181        assert_equal(fpos32(f32x, unique=True, fractional=True, precision=4),
182                    "340282350000000000000000000000000000000.")
183        assert_equal(fpos32(f32x, unique=True, fractional=True, min_digits=0),
184                    "340282346638528859811704183484516925440.")
185        assert_equal(fpos32(f32x, unique=True, fractional=True, min_digits=4),
186                    "340282346638528859811704183484516925440.0000")
187        assert_equal(fpos32(f32x, unique=True, fractional=True,
188                                    min_digits=4, precision=4),
189                    "340282346638528859811704183484516925440.0000")
190        assert_raises(ValueError, fpos32, f32x, unique=True, fractional=False,
191                                          precision=0)
192        assert_equal(fpos32(f32x, unique=True, fractional=False, precision=4),
193                    "340300000000000000000000000000000000000.")
194        assert_equal(fpos32(f32x, unique=True, fractional=False, precision=20),
195                    "340282350000000000000000000000000000000.")
196        assert_equal(fpos32(f32x, unique=True, fractional=False, min_digits=4),
197                    "340282350000000000000000000000000000000.")
198        assert_equal(fpos32(f32x, unique=True, fractional=False,
199                                  min_digits=20),
200                    "340282346638528859810000000000000000000.")
201        assert_equal(fpos32(f32x, unique=True, fractional=False,
202                                  min_digits=15),
203                    "340282346638529000000000000000000000000.")
204        assert_equal(fpos32(f32x, unique=False, fractional=False, precision=4),
205                    "340300000000000000000000000000000000000.")
206        # test that unique rounding is preserved when precision is supplied
207        # but no extra digits need to be printed (gh-18609)
208        a = np.float64.fromhex('-1p-97')
209        assert_equal(fsci64(a, unique=True), '-6.310887241768095e-30')
210        assert_equal(fsci64(a, unique=False, precision=15),
211                     '-6.310887241768094e-30')
212        assert_equal(fsci64(a, unique=True, precision=15),
213                     '-6.310887241768095e-30')
214        assert_equal(fsci64(a, unique=True, min_digits=15),
215                     '-6.310887241768095e-30')
216        assert_equal(fsci64(a, unique=True, precision=15, min_digits=15),
217                     '-6.310887241768095e-30')
218        # adds/remove digits in unique mode with unbiased rnding
219        assert_equal(fsci64(a, unique=True, precision=14),
220                     '-6.31088724176809e-30')
221        assert_equal(fsci64(a, unique=True, min_digits=16),
222                     '-6.3108872417680944e-30')
223        assert_equal(fsci64(a, unique=True, precision=16),
224                     '-6.310887241768095e-30')
225        assert_equal(fsci64(a, unique=True, min_digits=14),
226                     '-6.310887241768095e-30')
227        # test min_digits in unique mode with different rounding cases
228        assert_equal(fsci64('1e120', min_digits=3), '1.000e+120')
229        assert_equal(fsci64('1e100', min_digits=3), '1.000e+100')
230
231        # test trailing zeros
232        assert_equal(fpos32('1.0', unique=False, precision=3), "1.000")
233        assert_equal(fpos64('1.0', unique=False, precision=3), "1.000")
234        assert_equal(fsci32('1.0', unique=False, precision=3), "1.000e+00")
235        assert_equal(fsci64('1.0', unique=False, precision=3), "1.000e+00")
236        assert_equal(fpos32('1.5', unique=False, precision=3), "1.500")
237        assert_equal(fpos64('1.5', unique=False, precision=3), "1.500")
238        assert_equal(fsci32('1.5', unique=False, precision=3), "1.500e+00")
239        assert_equal(fsci64('1.5', unique=False, precision=3), "1.500e+00")
240        # gh-10713
241        assert_equal(fpos64('324', unique=False, precision=5,
242                                   fractional=False), "324.00")
243
244    available_float_dtypes = [np.float16, np.float32, np.float64, np.float128]\
245        if hasattr(np, 'float128') else [np.float16, np.float32, np.float64]
246
247    @pytest.mark.parametrize("tp", available_float_dtypes)
248    def test_dragon4_positional_interface(self, tp):
249        # test is flaky for musllinux on np.float128
250        if IS_MUSL and tp == np.float128:
251            pytest.skip("Skipping flaky test of float128 on musllinux")
252
253        fpos = np.format_float_positional
254
255        # test padding
256        assert_equal(fpos(tp('1.0'), pad_left=4, pad_right=4), "   1.    ")
257        assert_equal(fpos(tp('-1.0'), pad_left=4, pad_right=4), "  -1.    ")
258        assert_equal(fpos(tp('-10.2'),
259                        pad_left=4, pad_right=4), " -10.2   ")
260
261        # test fixed (non-unique) mode
262        assert_equal(fpos(tp('1.0'), unique=False, precision=4), "1.0000")
263
264    @pytest.mark.parametrize("tp", available_float_dtypes)
265    def test_dragon4_positional_interface_trim(self, tp):
266        # test is flaky for musllinux on np.float128
267        if IS_MUSL and tp == np.float128:
268            pytest.skip("Skipping flaky test of float128 on musllinux")
269
270        fpos = np.format_float_positional
271        # test trimming
272        # trim of 'k' or '.' only affects non-unique mode, since unique
273        # mode will not output trailing 0s.
274        assert_equal(fpos(tp('1.'), unique=False, precision=4, trim='k'),
275                        "1.0000")
276
277        assert_equal(fpos(tp('1.'), unique=False, precision=4, trim='.'),
278                        "1.")
279        assert_equal(fpos(tp('1.2'), unique=False, precision=4, trim='.'),
280                        "1.2" if tp != np.float16 else "1.2002")
281
282        assert_equal(fpos(tp('1.'), unique=False, precision=4, trim='0'),
283                        "1.0")
284        assert_equal(fpos(tp('1.2'), unique=False, precision=4, trim='0'),
285                        "1.2" if tp != np.float16 else "1.2002")
286        assert_equal(fpos(tp('1.'), trim='0'), "1.0")
287
288        assert_equal(fpos(tp('1.'), unique=False, precision=4, trim='-'),
289                        "1")
290        assert_equal(fpos(tp('1.2'), unique=False, precision=4, trim='-'),
291                        "1.2" if tp != np.float16 else "1.2002")
292        assert_equal(fpos(tp('1.'), trim='-'), "1")
293        assert_equal(fpos(tp('1.001'), precision=1, trim='-'), "1")
294
295    @pytest.mark.parametrize("tp", available_float_dtypes)
296    @pytest.mark.parametrize("pad_val", [10**5, np.iinfo("int32").max])
297    def test_dragon4_positional_interface_overflow(self, tp, pad_val):
298        # test is flaky for musllinux on np.float128
299        if IS_MUSL and tp == np.float128:
300            pytest.skip("Skipping flaky test of float128 on musllinux")
301
302        fpos = np.format_float_positional
303
304        # gh-28068
305        with pytest.raises(RuntimeError,
306                           match="Float formatting result too large"):
307            fpos(tp('1.047'), unique=False, precision=pad_val)
308
309        with pytest.raises(RuntimeError,
310                           match="Float formatting result too large"):
311            fpos(tp('1.047'), precision=2, pad_left=pad_val)
312
313        with pytest.raises(RuntimeError,
314                           match="Float formatting result too large"):
315            fpos(tp('1.047'), precision=2, pad_right=pad_val)
316
317    @pytest.mark.parametrize("tp", available_float_dtypes)
318    def test_dragon4_scientific_interface(self, tp):
319        # test is flaky for musllinux on np.float128
320        if IS_MUSL and tp == np.float128:
321            pytest.skip("Skipping flaky test of float128 on musllinux")
322
323        fsci = np.format_float_scientific
324
325        # test exp_digits
326        assert_equal(fsci(tp('1.23e1'), exp_digits=5), "1.23e+00001")
327
328        # test fixed (non-unique) mode
329        assert_equal(fsci(tp('1.0'), unique=False, precision=4),
330                        "1.0000e+00")
331
332    @pytest.mark.skipif(not platform.machine().startswith("ppc64"),
333                        reason="only applies to ppc float128 values")
334    def test_ppc64_ibm_double_double128(self):
335        # check that the precision decreases once we get into the subnormal
336        # range. Unlike float64, this starts around 1e-292 instead of 1e-308,
337        # which happens when the first double is normal and the second is
338        # subnormal.
339        x = np.float128('2.123123123123123123123123123123123e-286')
340        got = [str(x / np.float128('2e' + str(i))) for i in range(40)]
341        expected = [
342            "1.06156156156156156156156156156157e-286",
343            "1.06156156156156156156156156156158e-287",
344            "1.06156156156156156156156156156159e-288",
345            "1.0615615615615615615615615615616e-289",
346            "1.06156156156156156156156156156157e-290",
347            "1.06156156156156156156156156156156e-291",
348            "1.0615615615615615615615615615616e-292",
349            "1.0615615615615615615615615615615e-293",
350            "1.061561561561561561561561561562e-294",
351            "1.06156156156156156156156156155e-295",
352            "1.0615615615615615615615615616e-296",
353            "1.06156156156156156156156156e-297",
354            "1.06156156156156156156156157e-298",
355            "1.0615615615615615615615616e-299",
356            "1.06156156156156156156156e-300",
357            "1.06156156156156156156155e-301",
358            "1.0615615615615615615616e-302",
359            "1.061561561561561561562e-303",
360            "1.06156156156156156156e-304",
361            "1.0615615615615615618e-305",
362            "1.06156156156156156e-306",
363            "1.06156156156156157e-307",
364            "1.0615615615615616e-308",
365            "1.06156156156156e-309",
366            "1.06156156156157e-310",
367            "1.0615615615616e-311",
368            "1.06156156156e-312",
369            "1.06156156154e-313",
370            "1.0615615616e-314",
371            "1.06156156e-315",
372            "1.06156155e-316",
373            "1.061562e-317",
374            "1.06156e-318",
375            "1.06155e-319",
376            "1.0617e-320",
377            "1.06e-321",
378            "1.04e-322",
379            "1e-323",
380            "0.0",
381            "0.0"]
382        assert_equal(got, expected)
383
384        # Note: we follow glibc behavior, but it (or gcc) might not be right.
385        # In particular we can get two values that print the same but are not
386        # equal:
387        a = np.float128('2') / np.float128('3')
388        b = np.float128(str(a))
389        assert_equal(str(a), str(b))
390        assert_(a != b)
391
392    def float32_roundtrip(self):
393        # gh-9360
394        x = np.float32(1024 - 2**-14)
395        y = np.float32(1024 - 2**-13)
396        assert_(repr(x) != repr(y))
397        assert_equal(np.float32(repr(x)), x)
398        assert_equal(np.float32(repr(y)), y)
399
400    def float64_vs_python(self):
401        # gh-2643, gh-6136, gh-6908
402        assert_equal(repr(np.float64(0.1)), repr(0.1))
403        assert_(repr(np.float64(0.20000000000000004)) != repr(0.2))
404 
codekingpro/portable-devtools · Team Ai