8000 TST: New tests for scalar/array reprs with dragon4 · numpy/numpy@9ab9e8b · GitHub
[go: up one dir, main page]

Skip to content 8000

Commit 9ab9e8b

Browse files
committed
TST: New tests for scalar/array reprs with dragon4
Fixes #9360 #2643 #6136 #9699 #6908 Closes #9919 #9932
1 parent 170cf10 commit 9ab9e8b

File tree

2 files changed

+247
-1
lines changed

2 files changed

+247
-1
lines changed

numpy/core/tests/test_arrayprint.py

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,86 @@ def test_sign_spacing_structured(self):
314314
" dtype=[('f0', '<f4'), ('f1', '<f4')])")
315315
assert_equal(repr(a[0]), "(1., 1.)")
316316

317+
def test_floatmode(self):
318+
x = np.array([0.6104, 0.922, 0.457, 0.0906, 0.3733, 0.007244,
319+
0.5933, 0.947, 0.2383, 0.4226], dtype=np.float16)
320+
y = np.array([0.2918820979355541, 0.5064172631089138,
321+
0.2848750619642916, 0.4342965294660567,
322+
0.7326538397312751, 0.3459503329096204,
323+
0.0862072768214508, 0.39112753029631175],
324+
dtype=np.float64)
325+
z = np.arange(6, dtype=np.float16)/10
326+
327+
# also make sure 1e23 is right (is between two fp numbers)
328+
w = np.array(['1e{}'.format(i) for i in range(25)], dtype=np.float64)
329+
# note: we construct w from the strings `1eXX` instead of doing
330+
# `10.**arange(24)` because it turns out the two are not equivalent in
331+
# python. On some architectures `1e23 != 10.**23`.
332+
wp = np.array([1.234e1, 1e2, 1e123])
333+
334+
# unique mode
335+
np.set_printoptions(floatmode='unique')
336+
assert_equal(repr(x),
337+
"array([0.6104 , 0.922 , 0.457 , 0.0906 , 0.3733 , 0.007244,\n"
338+
" 0.5933 , 0.947 , 0.2383 , 0.4226 ], dtype=float16)")
339+
assert_equal(repr(y),
340+
"array([0.2918820979355541 , 0.5064172631089138 , 0.2848750619642916 ,\n"
341+
" 0.4342965294660567 , 0.7326538397312751 , 0.3459503329096204 ,\n"
342+
" 0.0862072768214508 , 0.39112753029631175])")
343+
assert_equal(repr(z),
344+
"array([0. , 0.1, 0.2, 0.3, 0.4, 0.5], dtype=float16)")
345+
assert_equal(repr(w),
346+
"array([1.e+00, 1.e+01, 1.e+02, 1.e+03, 1.e+04, 1.e+05, 1.e+06, 1.e+07,\n"
347+
" 1.e+08, 1.e+09, 1.e+10, 1.e+11, 1.e+12, 1.e+13, 1.e+14, 1.e+15,\n"
348+
" 1.e+16, 1.e+17, 1.e+18, 1.e+19, 1.e+20, 1.e+21, 1.e+22, 1.e+23,\n"
349+
" 1.e+24])")
350+
assert_equal(repr(wp), "array([1.234e+001, 1.000e+002, 1.000e+123])")
351+
352+
# maxprec mode, precision=8
353+
np.set_printoptions(floatmode='maxprec', precision=8)
354+
assert_equal(repr(x),
355+
"array([0.6104 , 0.922 , 0.457 , 0.0906 , 0.3733 , 0.007244,\n"
356+
" 0.5933 , 0.947 , 0.2383 , 0.4226 ], dtype=float16)")
357+
assert_equal(repr(y),
358+
"array([0.2918821 , 0.50641726, 0.28487506, 0.43429653, 0.73265384,\n"
359+
" 0.34595033, 0.08620728, 0.39112753])")
360+
assert_equal(repr(z),
361+
"array([0. , 0.1, 0.2, 0.3, 0.4, 0.5], dtype=float16)")
362+
assert_equal(repr(w[::5]),
363+
"array([1.e+00, 1.e+05, 1.e+10, 1.e+15, 1.e+20])")
364+
assert_equal(repr(wp), "array([1.234e+001, 1.000e+002, 1.000e+123])")
365+
366+
# fixed mode, precision=4
367+
np.set_printoptions(floatmode='fixed', precision=4)
368+
assert_equal(repr(x),
369+
"array([0.6104, 0.9219, 0.4570, 0.0906, 0.3733, 0.0072, 0.5933, 0.9468,\n"
370+
" 0.2383, 0.4226], dtype=float16)")
371+
assert_equal(repr(y),
372+
"array([0.2919, 0.5064, 0.2849, 0.4343, 0.7327, 0.3460, 0.0862, 0.3911])")
373+
assert_equal(repr(z),
374+
"array([0.0000, 0.1000, 0.2000, 0.3000, 0.3999, 0.5000], dtype=float16)")
375+
assert_equal(repr(w[::5]),
376+
"array([1.0000e+00, 1.0000e+05, 1.0000e+10, 1.0000e+15, 1.0000e+20])")
377+
assert_equal(repr(wp), "array([1.2340e+001, 1.0000e+002, 1.0000e+123])")
378+
# for larger precision, representation error becomes more apparent:
379+
np.set_printoptions(floatmode='fixed', precision=8)
380+
assert_equal(repr(z),
381+
"array([0.00000000, 0.09997559, 0.19995117, 0.30004883, 0.39990234,\n"
382+
" 0.50000000], dtype=float16)")
383+
384+
# maxprec_equal mode, precision=8
385+
np.set_printoptions(floatmode='maxprec_equal', precision=8)
386+
assert_equal(repr(x),
387+
"array([0.610352, 0.921875, 0.457031, 0.090576, 0.373291, 0.007244,\n"
388+
" 0.593262, 0.946777, 0.238281, 0.422607], dtype=float16)")
389+
assert_equal(repr(y),
390+
"array([0.29188210, 0.50641726, 0.28487506, 0.43429653, 0.73265384,\n"
391+
" 0.34595033, 0.08620728, 0.39112753])")
392+
assert_equal(repr(z),
393+
"array([0.0, 0.1, 0.2, 0.3, 0.4, 0.5], dtype=float16)")
394+
assert_equal(repr(w[::5]),
395+
"array([1.e+00, 1.e+05, 1.e+10, 1.e+15, 1.e+20])")
396+
assert_equal(repr(wp), "array([1.234e+001, 1.000e+002, 1.000e+123])")
317397

318398
def test_unicode_object_array():
319399
import sys

numpy/core/tests/test_scalarprint.py

Lines changed: 167 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from __future__ import division, absolute_import, print_function
66

77
import numpy as np
8-
from numpy.testing import assert_equal, run_module_suite
8+
from numpy.testing import assert_, assert_equal, run_module_suite
99

1010

1111
class TestRealScalars(object):
@@ -26,6 +26,172 @@ def test_str(self):
2626
msg = 'for str({}({}))'.format(np.dtype(styp).name, repr(val))
2727
assert_equal(str(styp(val)), want, err_msg=msg)
2828

29+
def test_dragon4(self):
30+
# these tests are adapted from Ryan Juckett's dragon4 implementation,
31+
# see dragon4.c for details.
32+
33+
fpos32 = lambda x, **k: np.format_float_positional(np.float32(x), **k)
34+
fsci32 = lambda x, **k: np.format_float_scientific(np.float32(x), **k)
35+
fpos64 = lambda x, **k: np.format_float_positional(np.float64(x), **k)
36+
fsci64 = lambda x, **k: np.format_float_scientific(np.float64(x), **k)
37+
38+
preckwd = lambda prec: {'unique': False, 'precision': prec}
39+
40+
assert_equal(fpos32('1.0'), "1.")
41+
assert_equal(fsci32('1.0'), "1.e+00")
42+
assert_equal(fpos32('10.234'), "10.234")
43+
assert_equal(fpos32('-10.234'), "-10.234")
44+
assert_equal(fsci32('10.234'), "1.0234e+01")
45+
assert_equal(fsci32('-10.234'), "-1.0234e+01")
46+
assert_equal(fpos32('1000.0'), "1000.")
47+
assert_equal(fpos32('1.0', precision=0), "1.")
48+
assert_equal(fsci32('1.0', precision=0), "1.e+00")
49+
assert_equal(fpos32('10.234', precision=0), "10.")
50+
assert_equal(fpos32('-10.234', precision=0), "-10.")
51+
assert_equal(fsci32('10.234', precision=0), "1.e+01")
52+
assert_equal(fsci32('-10.234', precision=0), "-1.e+01")
53+
assert_equal(fpos32('10.234', precision=2), "10.23")
54+
assert_equal(fsci32('-10.234', precision=2), "-1.02e+01")
55+
assert_equal(fsci64('9.9999999999999995e-08', **preckwd(16)),
56+
'9.9999999999999995e-08')
57+
assert_equal(fsci64('9.8813129168249309e-324', **preckwd(16)),
58+
'9.8813129168249309e-324')
59+
assert_equal(fsci64('9.9999999999999694e-311', **preckwd(16)),
60+
'9.9999999999999694e-311')
61+
62+
63+
# test rounding
64+
# 3.1415927410 is closest float32 to np.pi
65+
assert_equal(fpos32('3.14159265358979323846', **preckwd(10)),
66+
"3.1415927410")
67+
assert_equal(fsci32('3.14159265358979323846', **preckwd(10)),
68+
"3.1415927410e+00")
69+
assert_equal(fpos64('3.14159265358979323846', **preckwd(10)),
70+
"3.1415926536")
71+
assert_equal(fsci64('3.14159265358979323846', **preckwd(10)),
72+
"3.1415926536e+00")
73+
# 299792448 is closest float32 to 299792458
74+
assert_equal(fpos32('299792458.0', **preckwd(5)), "299792448.00000")
75+
assert_equal(fsci32('299792458.0', **preckwd(5)), "2.99792e+08")
76+
assert_equal(fpos64('299792458.0', **preckwd(5)), "299792458.00000")
77+
assert_equal(fsci64('299792458.0', **preckwd(5)), "2.99792e+08")
78+
79+
assert_equal(fpos32('3.14159265358979323846', **preckwd(25)),
80+
"3.1415927410125732421875000")
81+
assert_equal(fpos64('3.14159265358979323846', **preckwd(50)),
82+
"3.14159265358979311599796346854418516159057617187500")
83+
assert_equal(fpos64('3.14159265358979323846'), "3.141592653589793")
84+
85+
86+
# smallest numbers
87+
assert_equal(fpos32(0.5**(126 + 23), unique=False, precision=149),
88+
"0.00000000000000000000000000000000000000000000140129846432"
89+
"4817070923729583289916131280261941876515771757068283889791"
90+
"08268586060148663818836212158203125")
91+
assert_equal(fpos64(0.5**(1022 + 52), unique=False, precision=1074),
92+
"0.00000000000000000000000000000000000000000000000000000000"
93+
"0000000000000000000000000000000000000000000000000000000000"
94+
"0000000000000000000000000000000000000000000000000000000000"
95+
"0000000000000000000000000000000000000000000000000000000000"
96+
"0000000000000000000000000000000000000000000000000000000000"
97+
"0000000000000000000000000000000000049406564584124654417656"
98+
"8792868221372365059802614324764425585682500675507270208751"
99+
"8652998363616359923797965646954457177309266567103559397963"
100+
"9877479601078187812630071319031140452784581716784898210368"
101+
"8718636056998730723050006387409153564984387312473397273169"
102+
"6151400317153853980741262385655911710266585566867681870395"
103+
"6031062493194527159149245532930545654440112748012970999954"
104+
"1931989409080416563324524757147869014726780159355238611550"
105+
"1348035264934720193790268107107491703332226844753335720832"
106+
"4319360923828934583680601060115061698097530783422773183292"
107+
"4790498252473077637592724787465608477820373446969953364701"
108+
"7972677717585125660551199131504891101451037862738167250955"
109+
"8373897335989936648099411642057026370902792427675445652290"
110+
"87538682506419718265533447265625")
111+
112+
# largest numbers
113+
assert_equal(fpos32(np.finfo(np.float32).max, **preckwd(0)),
114+
"340282346638528859811704183484516925440.")
115+
assert_equal(fpos64(np.finfo(np.float64).max, **preckwd(0)),
116+
"1797693134862315708145274237317043567980705675258449965989"
117+
"1747680315726078002853876058955863276687817154045895351438"
118+
"2464234321326889464182768467546703537516986049910576551282"
119+
"0762454900903893289440758685084551339423045832369032229481"
120+
"6580855933212334827479782620414472316873817718091929988125"
121+
"0404026184124858368.")
122+
# Warning: In unique mode only the integer digits necessary for
123+
# uniqueness are computed, the rest are 0. Should we change this?
124+
assert_equal(fpos32(np.finfo(np.float32).max, precision=0),
125+
"340282350000000000000000000000000000000.")
126+
127+
# test trailing zeros
128+
assert_equal(fpos32('1.0', unique=False, precision=3), "1.000")
129+
assert_equal(fpos64('1.0', unique=False, precision=3), "1.000")
130+
assert_equal(fsci32('1.0', unique=False, precision=3), "1.000e+00")
131+
assert_equal(fsci64('1.0', unique=False, precision=3), "1.000e+00")
132+
assert_equal(fpos32('1.5', unique=False, precision=3), "1.500")
133+
assert_equal(fpos64('1.5', unique=False, precision=3), "1.500")
134+
assert_equal(fsci32('1.5', unique=False, precision=3), "1.500e+00")
135+
assert_equal(fsci64('1.5', unique=False, precision=3), "1.500e+00")
136+
137+
def test_dragon4_interface(self):
138+
tps = [np.float16, np.float32, np.float64]
139+
if hasattr(np, 'float128'):
140+
tps.append(np.float128)
141+
142+
fpos = np.format_float_positional
143+
fsci = np.format_float_scientific
144+
145+
for tp in tps:
146+
# test padding
147+
assert_equal(fpos(tp('1.0'), pad_left=4, pad_right=4), " 1. ")
148+
assert_equal(fpos(tp('-1.0'), pad_left=4, pad_right=4), " -1. ")
149+
assert_equal(fpos(tp('-10.2'),
150+
pad_left=4, pad_right=4), " -10.2 ")
151+
152+
# test exp_digits
153+
assert_equal(fsci(tp('1.23e1'), exp_digits=5), "1.23e+00001")
154+
155+
# test fixed (non-unique) mode
156+
assert_equal(fpos(tp('1.0'), unique=False, precision=4), "1.0000")
157+
assert_equal(fsci(tp('1.0'), unique=False, precision=4),
158+
"1.0000e+00")
159+
160+
# test trimming
161+
# trim of 'k' or '.' only affects non-unique mode, since unique
162+
# mode will not output trailing 0s.
163+
assert_equal(fpos(tp('1.'), unique=False, precision=4, trim='k'),
164+
"1.0000")
165+
166+
assert_equal(fpos(tp('1.'), unique=False, precision=4, trim='.'),
167+
"1.")
168+
assert_equal(fpos(tp('1.2'), unique=False, precision=4, trim='.'),
169+
"1.2" if tp != np.float16 else "1.2002")
170+
171+
assert_equal(fpos(tp('1.'), unique=False, precision=4, trim='0'),
172+
C963 "1.0")
173+
assert_equal(fpos(tp('1.2'), unique=False, precision=4, trim='0'),
174+
"1.2" if tp != np.float16 else "1.2002")
175+
assert_equal(fpos(tp('1.'), trim='0'), "1.0")
176+
177+
assert_equal(fpos(tp('1.'), unique=False, precision=4, trim='-'),
178+
"1")
179+
assert_equal(fpos(tp('1.2'), unique=False, precision=4, trim='-'),
180+
"1.2" if tp != np.float16 else "1.2002")
181+
assert_equal(fpos(tp('1.'), trim='-'), "1")
182+
183+
def float32_roundtrip(self):
184+
# gh-9360
185+
x = np.float32(1024 - 2**-14)
186+
y = np.float32(1024 - 2**-13)
187+
assert_(repr(x) != repr(y))
188+
assert_equal(np.float32(repr(x)), x)
189+
assert_equal(np.float32(repr(y)), y)
190+
191+
def float64_vs_python(self):
192+
# gh-2643, gh-6136, gh-6908
193+
assert_equal(repr(np.float64(0.1)), repr(0.1))
194+
assert_(repr(np.float64(0.20000000000000004)) != repr(0.2))
29195

30196
if __name__ == "__main__":
31197
run_module_suite()

0 commit comments

Comments
 (0)
0