codekingpro/portable-devtools
114k
1from decimal import Decimal
2
3# For testing polynomial printing with object arrays
4from fractions import Fraction
5from math import inf, nan
6
7import pytest
8
9import numpy.polynomial as poly
10from numpy._core import arange, array, printoptions
11from numpy.testing import assert_, assert_equal
12
13
14class TestStrUnicodeSuperSubscripts:
15
16 @pytest.fixture(scope='class', autouse=True)
17 def use_unicode(self):
18 poly.set_default_printstyle('unicode')
19
20 @pytest.mark.parametrize(('inp', 'tgt'), (
21 ([1, 2, 3], "1.0 + 2.0·x + 3.0·x²"),
22 ([-1, 0, 3, -1], "-1.0 + 0.0·x + 3.0·x² - 1.0·x³"),
23 (arange(12), ("0.0 + 1.0·x + 2.0·x² + 3.0·x³ + 4.0·x⁴ + 5.0·x⁵ + "
24 "6.0·x⁶ + 7.0·x⁷ +\n8.0·x⁸ + 9.0·x⁹ + 10.0·x¹⁰ + "
25 "11.0·x¹¹")),
26 ))
27 def test_polynomial_str(self, inp, tgt):
28 p = poly.Polynomial(inp)
29 res = str(p)
30 assert_equal(res, tgt)
31
32 @pytest.mark.parametrize(('inp', 'tgt'), (
33 ([1, 2, 3], "1.0 + 2.0·T₁(x) + 3.0·T₂(x)"),
34 ([-1, 0, 3, -1], "-1.0 + 0.0·T₁(x) + 3.0·T₂(x) - 1.0·T₃(x)"),
35 (arange(12), ("0.0 + 1.0·T₁(x) + 2.0·T₂(x) + 3.0·T₃(x) + 4.0·T₄(x) + "
36 "5.0·T₅(x) +\n6.0·T₆(x) + 7.0·T₇(x) + 8.0·T₈(x) + "
37 "9.0·T₉(x) + 10.0·T₁₀(x) + 11.0·T₁₁(x)")),
38 ))
39 def test_chebyshev_str(self, inp, tgt):
40 res = str(poly.Chebyshev(inp))
41 assert_equal(res, tgt)
42
43 @pytest.mark.parametrize(('inp', 'tgt'), (
44 ([1, 2, 3], "1.0 + 2.0·P₁(x) + 3.0·P₂(x)"),
45 ([-1, 0, 3, -1], "-1.0 + 0.0·P₁(x) + 3.0·P₂(x) - 1.0·P₃(x)"),
46 (arange(12), ("0.0 + 1.0·P₁(x) + 2.0·P₂(x) + 3.0·P₃(x) + 4.0·P₄(x) + "
47 "5.0·P₅(x) +\n6.0·P₆(x) + 7.0·P₇(x) + 8.0·P₈(x) + "
48 "9.0·P₉(x) + 10.0·P₁₀(x) + 11.0·P₁₁(x)")),
49 ))
50 def test_legendre_str(self, inp, tgt):
51 res = str(poly.Legendre(inp))
52 assert_equal(res, tgt)
53
54 @pytest.mark.parametrize(('inp', 'tgt'), (
55 ([1, 2, 3], "1.0 + 2.0·H₁(x) + 3.0·H₂(x)"),
56 ([-1, 0, 3, -1], "-1.0 + 0.0·H₁(x) + 3.0·H₂(x) - 1.0·H₃(x)"),
57 (arange(12), ("0.0 + 1.0·H₁(x) + 2.0·H₂(x) + 3.0·H₃(x) + 4.0·H₄(x) + "
58 "5.0·H₅(x) +\n6.0·H₆(x) + 7.0·H₇(x) + 8.0·H₈(x) + "
59 "9.0·H₉(x) + 10.0·H₁₀(x) + 11.0·H₁₁(x)")),
60 ))
61 def test_hermite_str(self, inp, tgt):
62 res = str(poly.Hermite(inp))
63 assert_equal(res, tgt)
64
65 @pytest.mark.parametrize(('inp', 'tgt'), (
66 ([1, 2, 3], "1.0 + 2.0·He₁(x) + 3.0·He₂(x)"),
67 ([-1, 0, 3, -1], "-1.0 + 0.0·He₁(x) + 3.0·He₂(x) - 1.0·He₃(x)"),
68 (arange(12), ("0.0 + 1.0·He₁(x) + 2.0·He₂(x) + 3.0·He₃(x) + "
69 "4.0·He₄(x) + 5.0·He₅(x) +\n6.0·He₆(x) + 7.0·He₇(x) + "
70 "8.0·He₈(x) + 9.0·He₉(x) + 10.0·He₁₀(x) +\n"
71 "11.0·He₁₁(x)")),
72 ))
73 def test_hermiteE_str(self, inp, tgt):
74 res = str(poly.HermiteE(inp))
75 assert_equal(res, tgt)
76
77 @pytest.mark.parametrize(('inp', 'tgt'), (
78 ([1, 2, 3], "1.0 + 2.0·L₁(x) + 3.0·L₂(x)"),
79 ([-1, 0, 3, -1], "-1.0 + 0.0·L₁(x) + 3.0·L₂(x) - 1.0·L₃(x)"),
80 (arange(12), ("0.0 + 1.0·L₁(x) + 2.0·L₂(x) + 3.0·L₃(x) + 4.0·L₄(x) + "
81 "5.0·L₅(x) +\n6.0·L₆(x) + 7.0·L₇(x) + 8.0·L₈(x) + "
82 "9.0·L₉(x) + 10.0·L₁₀(x) + 11.0·L₁₁(x)")),
83 ))
84 def test_laguerre_str(self, inp, tgt):
85 res = str(poly.Laguerre(inp))
86 assert_equal(res, tgt)
87
88 def test_polynomial_str_domains(self):
89 res = str(poly.Polynomial([0, 1]))
90 tgt = '0.0 + 1.0·x'
91 assert_equal(res, tgt)
92
93 res = str(poly.Polynomial([0, 1], domain=[1, 2]))
94 tgt = '0.0 + 1.0·(-3.0 + 2.0x)'
95 assert_equal(res, tgt)
96
97class TestStrAscii:
98
99 @pytest.fixture(scope='class', autouse=True)
100 def use_ascii(self):
101 poly.set_default_printstyle('ascii')
102
103 @pytest.mark.parametrize(('inp', 'tgt'), (
104 ([1, 2, 3], "1.0 + 2.0 x + 3.0 x**2"),
105 ([-1, 0, 3, -1], "-1.0 + 0.0 x + 3.0 x**2 - 1.0 x**3"),
106 (arange(12), ("0.0 + 1.0 x + 2.0 x**2 + 3.0 x**3 + 4.0 x**4 + "
107 "5.0 x**5 + 6.0 x**6 +\n7.0 x**7 + 8.0 x**8 + "
108 "9.0 x**9 + 10.0 x**10 + 11.0 x**11")),
109 ))
110 def test_polynomial_str(self, inp, tgt):
111 res = str(poly.Polynomial(inp))
112 assert_equal(res, tgt)
113
114 @pytest.mark.parametrize(('inp', 'tgt'), (
115 ([1, 2, 3], "1.0 + 2.0 T_1(x) + 3.0 T_2(x)"),
116 ([-1, 0, 3, -1], "-1.0 + 0.0 T_1(x) + 3.0 T_2(x) - 1.0 T_3(x)"),
117 (arange(12), ("0.0 + 1.0 T_1(x) + 2.0 T_2(x) + 3.0 T_3(x) + "
118 "4.0 T_4(x) + 5.0 T_5(x) +\n6.0 T_6(x) + 7.0 T_7(x) + "
119 "8.0 T_8(x) + 9.0 T_9(x) + 10.0 T_10(x) +\n"
120 "11.0 T_11(x)")),
121 ))
122 def test_chebyshev_str(self, inp, tgt):
123 res = str(poly.Chebyshev(inp))
124 assert_equal(res, tgt)
125
126 @pytest.mark.parametrize(('inp', 'tgt'), (
127 ([1, 2, 3], "1.0 + 2.0 P_1(x) + 3.0 P_2(x)"),
128 ([-1, 0, 3, -1], "-1.0 + 0.0 P_1(x) + 3.0 P_2(x) - 1.0 P_3(x)"),
129 (arange(12), ("0.0 + 1.0 P_1(x) + 2.0 P_2(x) + 3.0 P_3(x) + "
130 "4.0 P_4(x) + 5.0 P_5(x) +\n6.0 P_6(x) + 7.0 P_7(x) + "
131 "8.0 P_8(x) + 9.0 P_9(x) + 10.0 P_10(x) +\n"
132 "11.0 P_11(x)")),
133 ))
134 def test_legendre_str(self, inp, tgt):
135 res = str(poly.Legendre(inp))
136 assert_equal(res, tgt)
137
138 @pytest.mark.parametrize(('inp', 'tgt'), (
139 ([1, 2, 3], "1.0 + 2.0 H_1(x) + 3.0 H_2(x)"),
140 ([-1, 0, 3, -1], "-1.0 + 0.0 H_1(x) + 3.0 H_2(x) - 1.0 H_3(x)"),
141 (arange(12), ("0.0 + 1.0 H_1(x) + 2.0 H_2(x) + 3.0 H_3(x) + "
142 "4.0 H_4(x) + 5.0 H_5(x) +\n6.0 H_6(x) + 7.0 H_7(x) + "
143 "8.0 H_8(x) + 9.0 H_9(x) + 10.0 H_10(x) +\n"
144 "11.0 H_11(x)")),
145 ))
146 def test_hermite_str(self, inp, tgt):
147 res = str(poly.Hermite(inp))
148 assert_equal(res, tgt)
149
150 @pytest.mark.parametrize(('inp', 'tgt'), (
151 ([1, 2, 3], "1.0 + 2.0 He_1(x) + 3.0 He_2(x)"),
152 ([-1, 0, 3, -1], "-1.0 + 0.0 He_1(x) + 3.0 He_2(x) - 1.0 He_3(x)"),
153 (arange(12), ("0.0 + 1.0 He_1(x) + 2.0 He_2(x) + 3.0 He_3(x) + "
154 "4.0 He_4(x) +\n5.0 He_5(x) + 6.0 He_6(x) + "
155 "7.0 He_7(x) + 8.0 He_8(x) + 9.0 He_9(x) +\n"
156 "10.0 He_10(x) + 11.0 He_11(x)")),
157 ))
158 def test_hermiteE_str(self, inp, tgt):
159 res = str(poly.HermiteE(inp))
160 assert_equal(res, tgt)
161
162 @pytest.mark.parametrize(('inp', 'tgt'), (
163 ([1, 2, 3], "1.0 + 2.0 L_1(x) + 3.0 L_2(x)"),
164 ([-1, 0, 3, -1], "-1.0 + 0.0 L_1(x) + 3.0 L_2(x) - 1.0 L_3(x)"),
165 (arange(12), ("0.0 + 1.0 L_1(x) + 2.0 L_2(x) + 3.0 L_3(x) + "
166 "4.0 L_4(x) + 5.0 L_5(x) +\n6.0 L_6(x) + 7.0 L_7(x) + "
167 "8.0 L_8(x) + 9.0 L_9(x) + 10.0 L_10(x) +\n"
168 "11.0 L_11(x)")),
169 ))
170 def test_laguerre_str(self, inp, tgt):
171 res = str(poly.Laguerre(inp))
172 assert_equal(res, tgt)
173
174 def test_polynomial_str_domains(self):
175 res = str(poly.Polynomial([0, 1]))
176 tgt = '0.0 + 1.0 x'
177 assert_equal(res, tgt)
178
179 res = str(poly.Polynomial([0, 1], domain=[1, 2]))
180 tgt = '0.0 + 1.0 (-3.0 + 2.0x)'
181 assert_equal(res, tgt)
182
183class TestLinebreaking:
184
185 @pytest.fixture(scope='class', autouse=True)
186 def use_ascii(self):
187 poly.set_default_printstyle('ascii')
188
189 def test_single_line_one_less(self):
190 # With 'ascii' style, len(str(p)) is default linewidth - 1 (i.e. 74)
191 p = poly.Polynomial([12345678, 12345678, 12345678, 12345678, 123])
192 assert_equal(len(str(p)), 74)
193 assert_equal(str(p), (
194 '12345678.0 + 12345678.0 x + 12345678.0 x**2 + '
195 '12345678.0 x**3 + 123.0 x**4'
196 ))
197
198 def test_num_chars_is_linewidth(self):
199 # len(str(p)) == default linewidth == 75
200 p = poly.Polynomial([12345678, 12345678, 12345678, 12345678, 1234])
201 assert_equal(len(str(p)), 75)
202 assert_equal(str(p), (
203 '12345678.0 + 12345678.0 x + 12345678.0 x**2 + '
204 '12345678.0 x**3 +\n1234.0 x**4'
205 ))
206
207 def test_first_linebreak_multiline_one_less_than_linewidth(self):
208 # Multiline str where len(first_line) + len(next_term) == lw - 1 == 74
209 p = poly.Polynomial(
210 [12345678, 12345678, 12345678, 12345678, 1, 12345678]
211 )
212 assert_equal(len(str(p).split('\n')[0]), 74)
213 assert_equal(str(p), (
214 '12345678.0 + 12345678.0 x + 12345678.0 x**2 + '
215 '12345678.0 x**3 + 1.0 x**4 +\n12345678.0 x**5'
216 ))
217
218 def test_first_linebreak_multiline_on_linewidth(self):
219 # First line is one character longer than previous test
220 p = poly.Polynomial(
221 [12345678, 12345678, 12345678, 12345678.12, 1, 12345678]
222 )
223 assert_equal(str(p), (
224 '12345678.0 + 12345678.0 x + 12345678.0 x**2 + '
225 '12345678.12 x**3 +\n1.0 x**4 + 12345678.0 x**5'
226 ))
227
228 @pytest.mark.parametrize(('lw', 'tgt'), (
229 (75, ('0.0 + 10.0 x + 200.0 x**2 + 3000.0 x**3 + 40000.0 x**4 + '
230 '500000.0 x**5 +\n600000.0 x**6 + 70000.0 x**7 + 8000.0 x**8 + '
231 '900.0 x**9')),
232 (45, ('0.0 + 10.0 x + 200.0 x**2 + 3000.0 x**3 +\n40000.0 x**4 + '
233 '500000.0 x**5 +\n600000.0 x**6 + 70000.0 x**7 + 8000.0 x**8 +\n'
234 '900.0 x**9')),
235 (132, ('0.0 + 10.0 x + 200.0 x**2 + 3000.0 x**3 + 40000.0 x**4 + '
236 '500000.0 x**5 + 600000.0 x**6 + 70000.0 x**7 + 8000.0 x**8 + '
237 '900.0 x**9')),
238 ))
239 def test_linewidth_printoption(self, lw, tgt):
240 p = poly.Polynomial(
241 [0, 10, 200, 3000, 40000, 500000, 600000, 70000, 8000, 900]
242 )
243 with printoptions(linewidth=lw):
244 assert_equal(str(p), tgt)
245 for line in str(p).split('\n'):
246 assert_(len(line) < lw)
247
248
249@pytest.mark.thread_unsafe(reason="set_default_printstyle() is global state")
250def test_set_default_printoptions():
251 p = poly.Polynomial([1, 2, 3])
252 c = poly.Chebyshev([1, 2, 3])
253 poly.set_default_printstyle('ascii')
254 assert_equal(str(p), "1.0 + 2.0 x + 3.0 x**2")
255 assert_equal(str(c), "1.0 + 2.0 T_1(x) + 3.0 T_2(x)")
256 poly.set_default_printstyle('unicode')
257 assert_equal(str(p), "1.0 + 2.0·x + 3.0·x²")
258 assert_equal(str(c), "1.0 + 2.0·T₁(x) + 3.0·T₂(x)")
259 with pytest.raises(ValueError):
260 poly.set_default_printstyle('invalid_input')
261
262
263@pytest.mark.thread_unsafe(reason="set_default_printstyle() is global state")
264def test_complex_coefficients():
265 """Test both numpy and built-in complex."""
266 coefs = [0 + 1j, 1 + 1j, -2 + 2j, 3 + 0j]
267 # numpy complex
268 p1 = poly.Polynomial(coefs)
269 # Python complex
270 p2 = poly.Polynomial(array(coefs, dtype=object))
271 poly.set_default_printstyle('unicode')
272 assert_equal(str(p1), "1j + (1+1j)·x - (2-2j)·x² + (3+0j)·x³")
273 assert_equal(str(p2), "1j + (1+1j)·x + (-2+2j)·x² + (3+0j)·x³")
274 poly.set_default_printstyle('ascii')
275 assert_equal(str(p1), "1j + (1+1j) x - (2-2j) x**2 + (3+0j) x**3")
276 assert_equal(str(p2), "1j + (1+1j) x + (-2+2j) x**2 + (3+0j) x**3")
277
278
279@pytest.mark.parametrize(('coefs', 'tgt'), (
280 (array([Fraction(1, 2), Fraction(3, 4)], dtype=object), (
281 "1/2 + 3/4·x"
282 )),
283 (array([1, 2, Fraction(5, 7)], dtype=object), (
284 "1 + 2·x + 5/7·x²"
285 )),
286 (array([Decimal('1.00'), Decimal('2.2'), 3], dtype=object), (
287 "1.00 + 2.2·x + 3·x²"
288 )),
289))
290def test_numeric_object_coefficients(coefs, tgt):
291 p = poly.Polynomial(coefs)
292 poly.set_default_printstyle('unicode')
293 assert_equal(str(p), tgt)
294
295
296@pytest.mark.parametrize(('coefs', 'tgt'), (
297 (array([1, 2, 'f'], dtype=object), '1 + 2·x + f·x²'),
298 (array([1, 2, [3, 4]], dtype=object), '1 + 2·x + [3, 4]·x²'),
299))
300def test_nonnumeric_object_coefficients(coefs, tgt):
301 """
302 Test coef fallback for object arrays of non-numeric coefficients.
303 """
304 p = poly.Polynomial(coefs)
305 poly.set_default_printstyle('unicode')
306 assert_equal(str(p), tgt)
307
308
309class TestFormat:
310 def test_format_unicode(self):
311 poly.set_default_printstyle('ascii')
312 p = poly.Polynomial([1, 2, 0, -1])
313 assert_equal(format(p, 'unicode'), "1.0 + 2.0·x + 0.0·x² - 1.0·x³")
314
315 def test_format_ascii(self):
316 poly.set_default_printstyle('unicode')
317 p = poly.Polynomial([1, 2, 0, -1])
318 assert_equal(
319 format(p, 'ascii'), "1.0 + 2.0 x + 0.0 x**2 - 1.0 x**3"
320 )
321
322 def test_empty_formatstr(self):
323 poly.set_default_printstyle('ascii')
324 p = poly.Polynomial([1, 2, 3])
325 assert_equal(format(p), "1.0 + 2.0 x + 3.0 x**2")
326 assert_equal(f"{p}", "1.0 + 2.0 x + 3.0 x**2")
327
328 def test_bad_formatstr(self):
329 p = poly.Polynomial([1, 2, 0, -1])
330 with pytest.raises(ValueError):
331 format(p, '.2f')
332
333
334@pytest.mark.parametrize(('poly', 'tgt'), (
335 (poly.Polynomial, '1.0 + 2.0·z + 3.0·z²'),
336 (poly.Chebyshev, '1.0 + 2.0·T₁(z) + 3.0·T₂(z)'),
337 (poly.Hermite, '1.0 + 2.0·H₁(z) + 3.0·H₂(z)'),
338 (poly.HermiteE, '1.0 + 2.0·He₁(z) + 3.0·He₂(z)'),
339 (poly.Laguerre, '1.0 + 2.0·L₁(z) + 3.0·L₂(z)'),
340 (poly.Legendre, '1.0 + 2.0·P₁(z) + 3.0·P₂(z)'),
341))
342def test_symbol(poly, tgt):
343 p = poly([1, 2, 3], symbol='z')
344 assert_equal(f"{p:unicode}", tgt)
345
346
347class TestRepr:
348 def test_polynomial_repr(self):
349 res = repr(poly.Polynomial([0, 1]))
350 tgt = (
351 "Polynomial([0., 1.], domain=[-1., 1.], window=[-1., 1.], "
352 "symbol='x')"
353 )
354 assert_equal(res, tgt)
355
356 def test_chebyshev_repr(self):
357 res = repr(poly.Chebyshev([0, 1]))
358 tgt = (
359 "Chebyshev([0., 1.], domain=[-1., 1.], window=[-1., 1.], "
360 "symbol='x')"
361 )
362 assert_equal(res, tgt)
363
364 def test_legendre_repr(self):
365 res = repr(poly.Legendre([0, 1]))
366 tgt = (
367 "Legendre([0., 1.], domain=[-1., 1.], window=[-1., 1.], "
368 "symbol='x')"
369 )
370 assert_equal(res, tgt)
371
372 def test_hermite_repr(self):
373 res = repr(poly.Hermite([0, 1]))
374 tgt = (
375 "Hermite([0., 1.], domain=[-1., 1.], window=[-1., 1.], "
376 "symbol='x')"
377 )
378 assert_equal(res, tgt)
379
380 def test_hermiteE_repr(self):
381 res = repr(poly.HermiteE([0, 1]))
382 tgt = (
383 "HermiteE([0., 1.], domain=[-1., 1.], window=[-1., 1.], "
384 "symbol='x')"
385 )
386 assert_equal(res, tgt)
387
388 def test_laguerre_repr(self):
389 res = repr(poly.Laguerre([0, 1]))
390 tgt = (
391 "Laguerre([0., 1.], domain=[0., 1.], window=[0., 1.], "
392 "symbol='x')"
393 )
394 assert_equal(res, tgt)
395
396
397class TestLatexRepr:
398 """Test the latex repr used by Jupyter"""
399
400 @staticmethod
401 def as_latex(obj):
402 # right now we ignore the formatting of scalars in our tests, since
403 # it makes them too verbose. Ideally, the formatting of scalars will
404 # be fixed such that tests below continue to pass
405 obj._repr_latex_scalar = lambda x, parens=False: str(x)
406 try:
407 return obj._repr_latex_()
408 finally:
409 del obj._repr_latex_scalar
410
411 def test_simple_polynomial(self):
412 # default input
413 p = poly.Polynomial([1, 2, 3])
414 assert_equal(self.as_latex(p),
415 r'$x \mapsto 1.0 + 2.0\,x + 3.0\,x^{2}$')
416
417 # translated input
418 p = poly.Polynomial([1, 2, 3], domain=[-2, 0])
419 assert_equal(self.as_latex(p),
420 r'$x \mapsto 1.0 + 2.0\,\left(1.0 + x\right) + 3.0\,\left(1.0 + x\right)^{2}$') # noqa: E501
421
422 # scaled input
423 p = poly.Polynomial([1, 2, 3], domain=[-0.5, 0.5])
424 assert_equal(self.as_latex(p),
425 r'$x \mapsto 1.0 + 2.0\,\left(2.0x\right) + 3.0\,\left(2.0x\right)^{2}$')
426
427 # affine input
428 p = poly.Polynomial([1, 2, 3], domain=[-1, 0])
429 assert_equal(self.as_latex(p),
430 r'$x \mapsto 1.0 + 2.0\,\left(1.0 + 2.0x\right) + 3.0\,\left(1.0 + 2.0x\right)^{2}$') # noqa: E501
431
432 def test_basis_func(self):
433 p = poly.Chebyshev([1, 2, 3])
434 assert_equal(self.as_latex(p),
435 r'$x \mapsto 1.0\,{T}_{0}(x) + 2.0\,{T}_{1}(x) + 3.0\,{T}_{2}(x)$')
436 # affine input - check no surplus parens are added
437 p = poly.Chebyshev([1, 2, 3], domain=[-1, 0])
438 assert_equal(self.as_latex(p),
439 r'$x \mapsto 1.0\,{T}_{0}(1.0 + 2.0x) + 2.0\,{T}_{1}(1.0 + 2.0x) + 3.0\,{T}_{2}(1.0 + 2.0x)$') # noqa: E501
440
441 def test_multichar_basis_func(self):
442 p = poly.HermiteE([1, 2, 3])
443 assert_equal(self.as_latex(p),
444 r'$x \mapsto 1.0\,{He}_{0}(x) + 2.0\,{He}_{1}(x) + 3.0\,{He}_{2}(x)$')
445
446 def test_symbol_basic(self):
447 # default input
448 p = poly.Polynomial([1, 2, 3], symbol='z')
449 assert_equal(self.as_latex(p),
450 r'$z \mapsto 1.0 + 2.0\,z + 3.0\,z^{2}$')
451
452 # translated input
453 p = poly.Polynomial([1, 2, 3], domain=[-2, 0], symbol='z')
454 assert_equal(
455 self.as_latex(p),
456 (
457 r'$z \mapsto 1.0 + 2.0\,\left(1.0 + z\right) + 3.0\,'
458 r'\left(1.0 + z\right)^{2}$'
459 ),
460 )
461
462 # scaled input
463 p = poly.Polynomial([1, 2, 3], domain=[-0.5, 0.5], symbol='z')
464 assert_equal(
465 self.as_latex(p),
466 (
467 r'$z \mapsto 1.0 + 2.0\,\left(2.0z\right) + 3.0\,'
468 r'\left(2.0z\right)^{2}$'
469 ),
470 )
471
472 # affine input
473 p = poly.Polynomial([1, 2, 3], domain=[-1, 0], symbol='z')
474 assert_equal(
475 self.as_latex(p),
476 (
477 r'$z \mapsto 1.0 + 2.0\,\left(1.0 + 2.0z\right) + 3.0\,'
478 r'\left(1.0 + 2.0z\right)^{2}$'
479 ),
480 )
481
482 def test_numeric_object_coefficients(self):
483 coefs = array([Fraction(1, 2), Fraction(1)])
484 p = poly.Polynomial(coefs)
485 assert_equal(self.as_latex(p), '$x \\mapsto 1/2 + 1\\,x$')
486
487
488SWITCH_TO_EXP = (
489 '1.0 + (1.0e-01) x + (1.0e-02) x**2',
490 '1.2 + (1.2e-01) x + (1.2e-02) x**2',
491 '1.23 + 0.12 x + (1.23e-02) x**2 + (1.23e-03) x**3',
492 '1.235 + 0.123 x + (1.235e-02) x**2 + (1.235e-03) x**3',
493 '1.2346 + 0.1235 x + 0.0123 x**2 + (1.2346e-03) x**3 + (1.2346e-04) x**4',
494 '1.23457 + 0.12346 x + 0.01235 x**2 + (1.23457e-03) x**3 + '
495 '(1.23457e-04) x**4',
496 '1.234568 + 0.123457 x + 0.012346 x**2 + 0.001235 x**3 + '
497 '(1.234568e-04) x**4 + (1.234568e-05) x**5',
498 '1.2345679 + 0.1234568 x + 0.0123457 x**2 + 0.0012346 x**3 + '
499 '(1.2345679e-04) x**4 + (1.2345679e-05) x**5')
500
501class TestPrintOptions:
502 """
503 Test the output is properly configured via printoptions.
504 The exponential notation is enabled automatically when the values
505 are too small or too large.
506 """
507
508 @pytest.fixture(scope='class', autouse=True)
509 def use_ascii(self):
510 poly.set_default_printstyle('ascii')
511
512 def test_str(self):
513 p = poly.Polynomial([1 / 2, 1 / 7, 1 / 7 * 10**8, 1 / 7 * 10**9])
514 assert_equal(str(p), '0.5 + 0.14285714 x + 14285714.28571429 x**2 '
515 '+ (1.42857143e+08) x**3')
516
517 with printoptions(precision=3):
518 assert_equal(str(p), '0.5 + 0.143 x + 14285714.286 x**2 '
519 '+ (1.429e+08) x**3')
520
521 def test_latex(self):
522 p = poly.Polynomial([1 / 2, 1 / 7, 1 / 7 * 10**8, 1 / 7 * 10**9])
523 assert_equal(p._repr_latex_(),
524 r'$x \mapsto \text{0.5} + \text{0.14285714}\,x + '
525 r'\text{14285714.28571429}\,x^{2} + '
526 r'\text{(1.42857143e+08)}\,x^{3}$')
527
528 with printoptions(precision=3):
529 assert_equal(p._repr_latex_(),
530 r'$x \mapsto \text{0.5} + \text{0.143}\,x + '
531 r'\text{14285714.286}\,x^{2} + \text{(1.429e+08)}\,x^{3}$')
532
533 def test_fixed(self):
534 p = poly.Polynomial([1 / 2])
535 assert_equal(str(p), '0.5')
536
537 with printoptions(floatmode='fixed'):
538 assert_equal(str(p), '0.50000000')
539
540 with printoptions(floatmode='fixed', precision=4):
541 assert_equal(str(p), '0.5000')
542
543 def test_switch_to_exp(self):
544 for i, s in enumerate(SWITCH_TO_EXP):
545 with printoptions(precision=i):
546 p = poly.Polynomial([1.23456789 * 10**-i
547 for i in range(i // 2 + 3)])
548 assert str(p).replace('\n', ' ') == s
549
550 def test_non_finite(self):
551 p = poly.Polynomial([nan, inf])
552 assert str(p) == 'nan + inf x'
553 assert p._repr_latex_() == r'$x \mapsto \text{nan} + \text{inf}\,x$' # noqa: RUF027
554 with printoptions(nanstr='NAN', infstr='INF'):
555 assert str(p) == 'NAN + INF x'
556 assert p._repr_latex_() == \
557 r'$x \mapsto \text{NAN} + \text{INF}\,x$'
558 