xref: /aosp_15_r20/external/pytorch/test/torch_np/numpy_tests/lib/test_function_base.py (revision da0073e96a02ea20f0ac840b70461e3646d07c45)
1# Owner(s): ["module: dynamo"]
2
3import functools
4import math
5import operator
6import sys
7import warnings
8from fractions import Fraction
9from unittest import expectedFailure as xfail, skipIf as skipif
10
11import hypothesis
12import hypothesis.strategies as st
13import numpy
14import pytest
15from hypothesis.extra.numpy import arrays
16from pytest import raises as assert_raises
17
18from torch.testing._internal.common_utils import (
19    instantiate_parametrized_tests,
20    parametrize,
21    run_tests,
22    skipIfTorchDynamo,
23    subtest,
24    TEST_WITH_TORCHDYNAMO,
25    TestCase,
26    xpassIfTorchDynamo,
27)
28
29
30skip = functools.partial(skipif, True)
31
32HAS_REFCOUNT = True
33IS_WASM = False
34IS_PYPY = False
35
36# FIXME: make from torch._numpy
37# These are commented, as if they are imported, some of the tests pass for the wrong reasons
38# from numpy lib import digitize, piecewise, trapz, select, trim_zeros, interp
39from numpy.lib import delete, extract, insert, msort, place, setxor1d, unwrap, vectorize
40
41
42# If we are going to trace through these, we should use NumPy
43# If testing on eager mode, we use torch._numpy
44if TEST_WITH_TORCHDYNAMO:
45    import numpy as np
46    from numpy import (
47        angle,
48        bartlett,
49        blackman,
50        corrcoef,
51        cov,
52        diff,
53        digitize,
54        flipud,
55        gradient,
56        hamming,
57        hanning,
58        i0,
59        interp,
60        kaiser,
61        meshgrid,
62        sinc,
63        trapz,
64        trim_zeros,
65        unique,
66    )
67    from numpy.core.numeric import normalize_axis_tuple
68    from numpy.random import rand
69    from numpy.testing import (
70        assert_,
71        assert_allclose,
72        assert_almost_equal,
73        assert_array_almost_equal,
74        assert_array_equal,
75        assert_equal,
76        assert_raises_regex,
77        assert_warns,
78        suppress_warnings,
79    )
80else:
81    import torch._numpy as np
82    from torch._numpy import (
83        angle,
84        bartlett,
85        blackman,
86        corrcoef,
87        cov,
88        diff,
89        flipud,
90        gradient,
91        hamming,
92        hanning,
93        i0,
94        kaiser,
95        meshgrid,
96        sinc,
97        unique,
98    )
99    from torch._numpy._util import normalize_axis_tuple
100    from torch._numpy.random import rand
101    from torch._numpy.testing import (
102        assert_,
103        assert_allclose,
104        assert_almost_equal,
105        assert_array_almost_equal,
106        assert_array_equal,
107        assert_equal,
108        assert_raises_regex,
109        assert_warns,
110        suppress_warnings,
111    )
112
113
114def get_mat(n):
115    data = np.arange(n)
116    #    data = np.add.outer(data, data)
117    data = data[:, None] + data[None, :]
118    return data
119
120
121def _make_complex(real, imag):
122    """
123    Like real + 1j * imag, but behaves as expected when imag contains non-finite
124    values
125    """
126    ret = np.zeros(np.broadcast(real, imag).shape, np.complex128)
127    ret.real = real
128    ret.imag = imag
129    return ret
130
131
132class TestRot90(TestCase):
133    def test_basic(self):
134        assert_raises(ValueError, np.rot90, np.ones(4))
135        assert_raises(
136            (ValueError, RuntimeError), np.rot90, np.ones((2, 2, 2)), axes=(0, 1, 2)
137        )
138        assert_raises(ValueError, np.rot90, np.ones((2, 2)), axes=(0, 2))
139        assert_raises(ValueError, np.rot90, np.ones((2, 2)), axes=(1, 1))
140        assert_raises(ValueError, np.rot90, np.ones((2, 2, 2)), axes=(-2, 1))
141
142        a = [[0, 1, 2], [3, 4, 5]]
143        b1 = [[2, 5], [1, 4], [0, 3]]
144        b2 = [[5, 4, 3], [2, 1, 0]]
145        b3 = [[3, 0], [4, 1], [5, 2]]
146        b4 = [[0, 1, 2], [3, 4, 5]]
147
148        for k in range(-3, 13, 4):
149            assert_equal(np.rot90(a, k=k), b1)
150        for k in range(-2, 13, 4):
151            assert_equal(np.rot90(a, k=k), b2)
152        for k in range(-1, 13, 4):
153            assert_equal(np.rot90(a, k=k), b3)
154        for k in range(0, 13, 4):
155            assert_equal(np.rot90(a, k=k), b4)
156
157        assert_equal(np.rot90(np.rot90(a, axes=(0, 1)), axes=(1, 0)), a)
158        assert_equal(np.rot90(a, k=1, axes=(1, 0)), np.rot90(a, k=-1, axes=(0, 1)))
159
160    def test_axes(self):
161        a = np.ones((50, 40, 3))
162        assert_equal(np.rot90(a).shape, (40, 50, 3))
163        assert_equal(np.rot90(a, axes=(0, 2)), np.rot90(a, axes=(0, -1)))
164        assert_equal(np.rot90(a, axes=(1, 2)), np.rot90(a, axes=(-2, -1)))
165
166    def test_rotation_axes(self):
167        a = np.arange(8).reshape((2, 2, 2))
168
169        a_rot90_01 = [[[2, 3], [6, 7]], [[0, 1], [4, 5]]]
170        a_rot90_12 = [[[1, 3], [0, 2]], [[5, 7], [4, 6]]]
171        a_rot90_20 = [[[4, 0], [6, 2]], [[5, 1], [7, 3]]]
172        a_rot90_10 = [[[4, 5], [0, 1]], [[6, 7], [2, 3]]]
173
174        assert_equal(np.rot90(a, axes=(0, 1)), a_rot90_01)
175        assert_equal(np.rot90(a, axes=(1, 0)), a_rot90_10)
176        assert_equal(np.rot90(a, axes=(1, 2)), a_rot90_12)
177
178        for k in range(1, 5):
179            assert_equal(
180                np.rot90(a, k=k, axes=(2, 0)),
181                np.rot90(a_rot90_20, k=k - 1, axes=(2, 0)),
182            )
183
184
185class TestFlip(TestCase):
186    def test_axes(self):
187        assert_raises(np.AxisError, np.flip, np.ones(4), axis=1)
188        assert_raises(np.AxisError, np.flip, np.ones((4, 4)), axis=2)
189        assert_raises(np.AxisError, np.flip, np.ones((4, 4)), axis=-3)
190        assert_raises(np.AxisError, np.flip, np.ones((4, 4)), axis=(0, 3))
191
192    @skip(reason="no [::-1] indexing")
193    def test_basic_lr(self):
194        a = get_mat(4)
195        b = a[:, ::-1]
196        assert_equal(np.flip(a, 1), b)
197        a = [[0, 1, 2], [3, 4, 5]]
198        b = [[2, 1, 0], [5, 4, 3]]
199        assert_equal(np.flip(a, 1), b)
200
201    @skip(reason="no [::-1] indexing")
202    def test_basic_ud(self):
203        a = get_mat(4)
204        b = a[::-1, :]
205        assert_equal(np.flip(a, 0), b)
206        a = [[0, 1, 2], [3, 4, 5]]
207        b = [[3, 4, 5], [0, 1, 2]]
208        assert_equal(np.flip(a, 0), b)
209
210    def test_3d_swap_axis0(self):
211        a = np.array([[[0, 1], [2, 3]], [[4, 5], [6, 7]]])
212
213        b = np.array([[[4, 5], [6, 7]], [[0, 1], [2, 3]]])
214
215        assert_equal(np.flip(a, 0), b)
216
217    def test_3d_swap_axis1(self):
218        a = np.array([[[0, 1], [2, 3]], [[4, 5], [6, 7]]])
219
220        b = np.array([[[2, 3], [0, 1]], [[6, 7], [4, 5]]])
221
222        assert_equal(np.flip(a, 1), b)
223
224    def test_3d_swap_axis2(self):
225        a = np.array([[[0, 1], [2, 3]], [[4, 5], [6, 7]]])
226
227        b = np.array([[[1, 0], [3, 2]], [[5, 4], [7, 6]]])
228
229        assert_equal(np.flip(a, 2), b)
230
231    def test_4d(self):
232        a = np.arange(2 * 3 * 4 * 5).reshape(2, 3, 4, 5)
233        for i in range(a.ndim):
234            assert_equal(np.flip(a, i), np.flipud(a.swapaxes(0, i)).swapaxes(i, 0))
235
236    def test_default_axis(self):
237        a = np.array([[1, 2, 3], [4, 5, 6]])
238        b = np.array([[6, 5, 4], [3, 2, 1]])
239        assert_equal(np.flip(a), b)
240
241    def test_multiple_axes(self):
242        a = np.array([[[0, 1], [2, 3]], [[4, 5], [6, 7]]])
243
244        assert_equal(np.flip(a, axis=()), a)
245
246        b = np.array([[[5, 4], [7, 6]], [[1, 0], [3, 2]]])
247
248        assert_equal(np.flip(a, axis=(0, 2)), b)
249
250        c = np.array([[[3, 2], [1, 0]], [[7, 6], [5, 4]]])
251
252        assert_equal(np.flip(a, axis=(1, 2)), c)
253
254
255class TestAny(TestCase):
256    def test_basic(self):
257        y1 = [0, 0, 1, 0]
258        y2 = [0, 0, 0, 0]
259        y3 = [1, 0, 1, 0]
260        assert_(np.any(y1))
261        assert_(np.any(y3))
262        assert_(not np.any(y2))
263
264    def test_nd(self):
265        y1 = [[0, 0, 0], [0, 1, 0], [1, 1, 0]]
266        assert_(np.any(y1))
267        assert_array_equal(np.any(y1, axis=0), [1, 1, 0])
268        assert_array_equal(np.any(y1, axis=1), [0, 1, 1])
269
270
271class TestAll(TestCase):
272    def test_basic(self):
273        y1 = [0, 1, 1, 0]
274        y2 = [0, 0, 0, 0]
275        y3 = [1, 1, 1, 1]
276        assert_(not np.all(y1))
277        assert_(np.all(y3))
278        assert_(not np.all(y2))
279        assert_(np.all(~np.array(y2)))
280
281    def test_nd(self):
282        y1 = [[0, 0, 1], [0, 1, 1], [1, 1, 1]]
283        assert_(not np.all(y1))
284        assert_array_equal(np.all(y1, axis=0), [0, 0, 1])
285        assert_array_equal(np.all(y1, axis=1), [0, 0, 1])
286
287
288class TestCopy(TestCase):
289    def test_basic(self):
290        a = np.array([[1, 2], [3, 4]])
291        a_copy = np.copy(a)
292        assert_array_equal(a, a_copy)
293        a_copy[0, 0] = 10
294        assert_equal(a[0, 0], 1)
295        assert_equal(a_copy[0, 0], 10)
296
297    @xpassIfTorchDynamo  # (reason="order='F' not implemented")
298    def test_order(self):
299        # It turns out that people rely on np.copy() preserving order by
300        # default; changing this broke scikit-learn:
301        # github.com/scikit-learn/scikit-learn/commit/7842748cf777412c506
302        a = np.array([[1, 2], [3, 4]])
303        assert_(a.flags.c_contiguous)
304        assert_(not a.flags.f_contiguous)
305        a_fort = np.array([[1, 2], [3, 4]], order="F")
306        assert_(not a_fort.flags.c_contiguous)
307        assert_(a_fort.flags.f_contiguous)
308        a_copy = np.copy(a)
309        assert_(a_copy.flags.c_contiguous)
310        assert_(not a_copy.flags.f_contiguous)
311        a_fort_copy = np.copy(a_fort)
312        assert_(not a_fort_copy.flags.c_contiguous)
313        assert_(a_fort_copy.flags.f_contiguous)
314
315
316@instantiate_parametrized_tests
317class TestAverage(TestCase):
318    def test_basic(self):
319        y1 = np.array([1, 2, 3])
320        assert_(np.average(y1, axis=0) == 2.0)
321        y2 = np.array([1.0, 2.0, 3.0])
322        assert_(np.average(y2, axis=0) == 2.0)
323        y3 = [0.0, 0.0, 0.0]
324        assert_(np.average(y3, axis=0) == 0.0)
325
326        y4 = np.ones((4, 4))
327        y4[0, 1] = 0
328        y4[1, 0] = 2
329        assert_almost_equal(y4.mean(0), np.average(y4, 0))
330        assert_almost_equal(y4.mean(1), np.average(y4, 1))
331
332        y5 = rand(5, 5)
333        assert_almost_equal(y5.mean(0), np.average(y5, 0))
334        assert_almost_equal(y5.mean(1), np.average(y5, 1))
335
336    @skip(reason="NP_VER: fails on CI")
337    @parametrize(
338        "x, axis, expected_avg, weights, expected_wavg, expected_wsum",
339        [
340            ([1, 2, 3], None, [2.0], [3, 4, 1], [1.75], [8.0]),
341            (
342                [[1, 2, 5], [1, 6, 11]],
343                0,
344                [[1.0, 4.0, 8.0]],
345                [1, 3],
346                [[1.0, 5.0, 9.5]],
347                [[4, 4, 4]],
348            ),
349        ],
350    )
351    def test_basic_keepdims(
352        self, x, axis, expected_avg, weights, expected_wavg, expected_wsum
353    ):
354        avg = np.average(x, axis=axis, keepdims=True)
355        assert avg.shape == np.shape(expected_avg)
356        assert_array_equal(avg, expected_avg)
357
358        wavg = np.average(x, axis=axis, weights=weights, keepdims=True)
359        assert wavg.shape == np.shape(expected_wavg)
360        assert_array_equal(wavg, expected_wavg)
361
362        wavg, wsum = np.average(
363            x, axis=axis, weights=weights, returned=True, keepdims=True
364        )
365        assert wavg.shape == np.shape(expected_wavg)
366        assert_array_equal(wavg, expected_wavg)
367        assert wsum.shape == np.shape(expected_wsum)
368        assert_array_equal(wsum, expected_wsum)
369
370    @skip(reason="NP_VER: fails on CI")
371    def test_weights(self):
372        y = np.arange(10)
373        w = np.arange(10)
374        actual = np.average(y, weights=w)
375        desired = (np.arange(10) ** 2).sum() * 1.0 / np.arange(10).sum()
376        assert_almost_equal(actual, desired)
377
378        y1 = np.array([[1, 2, 3], [4, 5, 6]])
379        w0 = [1, 2]
380        actual = np.average(y1, weights=w0, axis=0)
381        desired = np.array([3.0, 4.0, 5.0])
382        assert_almost_equal(actual, desired)
383
384        w1 = [0, 0, 1]
385        actual = np.average(y1, weights=w1, axis=1)
386        desired = np.array([3.0, 6.0])
387        assert_almost_equal(actual, desired)
388
389        # This should raise an error. Can we test for that ?
390        # assert_equal(average(y1, weights=w1), 9./2.)
391
392        # 2D Case
393        w2 = [[0, 0, 1], [0, 0, 2]]
394        desired = np.array([3.0, 6.0])
395        assert_array_equal(np.average(y1, weights=w2, axis=1), desired)
396        assert_equal(np.average(y1, weights=w2), 5.0)
397
398        y3 = rand(5).astype(np.float32)
399        w3 = rand(5).astype(np.float64)
400
401        assert_(np.average(y3, weights=w3).dtype == np.result_type(y3, w3))
402
403        # test weights with `keepdims=False` and `keepdims=True`
404        x = np.array([2, 3, 4]).reshape(3, 1)
405        w = np.array([4, 5, 6]).reshape(3, 1)
406
407        actual = np.average(x, weights=w, axis=1, keepdims=False)
408        desired = np.array([2.0, 3.0, 4.0])
409        assert_array_equal(actual, desired)
410
411        actual = np.average(x, weights=w, axis=1, keepdims=True)
412        desired = np.array([[2.0], [3.0], [4.0]])
413        assert_array_equal(actual, desired)
414
415    def test_returned(self):
416        y = np.array([[1, 2, 3], [4, 5, 6]])
417
418        # No weights
419        avg, scl = np.average(y, returned=True)
420        assert_equal(scl, 6.0)
421
422        avg, scl = np.average(y, 0, returned=True)
423        assert_array_equal(scl, np.array([2.0, 2.0, 2.0]))
424
425        avg, scl = np.average(y, 1, returned=True)
426        assert_array_equal(scl, np.array([3.0, 3.0]))
427
428        # With weights
429        w0 = [1, 2]
430        avg, scl = np.average(y, weights=w0, axis=0, returned=True)
431        assert_array_equal(scl, np.array([3.0, 3.0, 3.0]))
432
433        w1 = [1, 2, 3]
434        avg, scl = np.average(y, weights=w1, axis=1, returned=True)
435        assert_array_equal(scl, np.array([6.0, 6.0]))
436
437        w2 = [[0, 0, 1], [1, 2, 3]]
438        avg, scl = np.average(y, weights=w2, axis=1, returned=True)
439        assert_array_equal(scl, np.array([1.0, 6.0]))
440
441    def test_upcasting(self):
442        typs = [
443            ("i4", "i4", "f8"),
444            ("i4", "f4", "f8"),
445            ("f4", "i4", "f8"),
446            ("f4", "f4", "f4"),
447            ("f4", "f8", "f8"),
448        ]
449        for at, wt, rt in typs:
450            a = np.array([[1, 2], [3, 4]], dtype=at)
451            w = np.array([[1, 2], [3, 4]], dtype=wt)
452            assert_equal(np.average(a, weights=w).dtype, np.dtype(rt))
453
454    @skip(reason="support Fraction objects?")
455    def test_average_class_without_dtype(self):
456        # see gh-21988
457        a = np.array([Fraction(1, 5), Fraction(3, 5)])
458        assert_equal(np.average(a), Fraction(2, 5))
459
460
461@xfail  # (reason="TODO: implement")
462class TestSelect(TestCase):
463    choices = [np.array([1, 2, 3]), np.array([4, 5, 6]), np.array([7, 8, 9])]
464    conditions = [
465        np.array([False, False, False]),
466        np.array([False, True, False]),
467        np.array([False, False, True]),
468    ]
469
470    def _select(self, cond, values, default=0):
471        output = []
472        for m in range(len(cond)):
473            output += [V[m] for V, C in zip(values, cond) if C[m]] or [default]
474        return output
475
476    def test_basic(self):
477        choices = self.choices
478        conditions = self.conditions
479        assert_array_equal(
480            select(conditions, choices, default=15),
481            self._select(conditions, choices, default=15),
482        )
483
484        assert_equal(len(choices), 3)
485        assert_equal(len(conditions), 3)
486
487    def test_broadcasting(self):
488        conditions = [np.array(True), np.array([False, True, False])]
489        choices = [1, np.arange(12).reshape(4, 3)]
490        assert_array_equal(select(conditions, choices), np.ones((4, 3)))
491        # default can broadcast too:
492        assert_equal(select([True], [0], default=[0]).shape, (1,))
493
494    def test_return_dtype(self):
495        assert_equal(select(self.conditions, self.choices, 1j).dtype, np.complex128)
496        # But the conditions need to be stronger then the scalar default
497        # if it is scalar.
498        choices = [choice.astype(np.int8) for choice in self.choices]
499        assert_equal(select(self.conditions, choices).dtype, np.int8)
500
501        d = np.array([1, 2, 3, np.nan, 5, 7])
502        m = np.isnan(d)
503        assert_equal(select([m], [d]), [0, 0, 0, np.nan, 0, 0])
504
505    def test_deprecated_empty(self):
506        assert_raises(ValueError, select, [], [], 3j)
507        assert_raises(ValueError, select, [], [])
508
509    def test_non_bool_deprecation(self):
510        choices = self.choices
511        conditions = self.conditions[:]
512        conditions[0] = conditions[0].astype(np.int_)
513        assert_raises(TypeError, select, conditions, choices)
514        conditions[0] = conditions[0].astype(np.uint8)
515        assert_raises(TypeError, select, conditions, choices)
516        assert_raises(TypeError, select, conditions, choices)
517
518    def test_many_arguments(self):
519        # This used to be limited by NPY_MAXARGS == 32
520        conditions = [np.array([False])] * 100
521        choices = [np.array([1])] * 100
522        select(conditions, choices)
523
524
525@xpassIfTorchDynamo  # (reason="TODO: implement")
526@instantiate_parametrized_tests
527class TestInsert(TestCase):
528    def test_basic(self):
529        a = [1, 2, 3]
530        assert_equal(insert(a, 0, 1), [1, 1, 2, 3])
531        assert_equal(insert(a, 3, 1), [1, 2, 3, 1])
532        assert_equal(insert(a, [1, 1, 1], [1, 2, 3]), [1, 1, 2, 3, 2, 3])
533        assert_equal(insert(a, 1, [1, 2, 3]), [1, 1, 2, 3, 2, 3])
534        assert_equal(insert(a, [1, -1, 3], 9), [1, 9, 2, 9, 3, 9])
535        assert_equal(insert(a, slice(-1, None, -1), 9), [9, 1, 9, 2, 9, 3])
536        assert_equal(insert(a, [-1, 1, 3], [7, 8, 9]), [1, 8, 2, 7, 3, 9])
537        b = np.array([0, 1], dtype=np.float64)
538        assert_equal(insert(b, 0, b[0]), [0.0, 0.0, 1.0])
539        assert_equal(insert(b, [], []), b)
540        # Bools will be treated differently in the future:
541        # assert_equal(insert(a, np.array([True]*4), 9), [9, 1, 9, 2, 9, 3, 9])
542        with warnings.catch_warnings(record=True) as w:
543            warnings.filterwarnings("always", "", FutureWarning)
544            assert_equal(insert(a, np.array([True] * 4), 9), [1, 9, 9, 9, 9, 2, 3])
545            assert_(w[0].category is FutureWarning)
546
547    def test_multidim(self):
548        a = [[1, 1, 1]]
549        r = [[2, 2, 2], [1, 1, 1]]
550        assert_equal(insert(a, 0, [1]), [1, 1, 1, 1])
551        assert_equal(insert(a, 0, [2, 2, 2], axis=0), r)
552        assert_equal(insert(a, 0, 2, axis=0), r)
553        assert_equal(insert(a, 2, 2, axis=1), [[1, 1, 2, 1]])
554
555        a = np.array([[1, 1], [2, 2], [3, 3]])
556        b = np.arange(1, 4).repeat(3).reshape(3, 3)
557        c = np.concatenate(
558            (a[:, 0:1], np.arange(1, 4).repeat(3).reshape(3, 3).T, a[:, 1:2]), axis=1
559        )
560        assert_equal(insert(a, [1], [[1], [2], [3]], axis=1), b)
561        assert_equal(insert(a, [1], [1, 2, 3], axis=1), c)
562        # scalars behave differently, in this case exactly opposite:
563        assert_equal(insert(a, 1, [1, 2, 3], axis=1), b)
564        assert_equal(insert(a, 1, [[1], [2], [3]], axis=1), c)
565
566        a = np.arange(4).reshape(2, 2)
567        assert_equal(insert(a[:, :1], 1, a[:, 1], axis=1), a)
568        assert_equal(insert(a[:1, :], 1, a[1, :], axis=0), a)
569
570        # negative axis value
571        a = np.arange(24).reshape((2, 3, 4))
572        assert_equal(
573            insert(a, 1, a[:, :, 3], axis=-1), insert(a, 1, a[:, :, 3], axis=2)
574        )
575        assert_equal(
576            insert(a, 1, a[:, 2, :], axis=-2), insert(a, 1, a[:, 2, :], axis=1)
577        )
578
579        # invalid axis value
580        assert_raises(np.AxisError, insert, a, 1, a[:, 2, :], axis=3)
581        assert_raises(np.AxisError, insert, a, 1, a[:, 2, :], axis=-4)
582
583        # negative axis value
584        a = np.arange(24).reshape((2, 3, 4))
585        assert_equal(
586            insert(a, 1, a[:, :, 3], axis=-1), insert(a, 1, a[:, :, 3], axis=2)
587        )
588        assert_equal(
589            insert(a, 1, a[:, 2, :], axis=-2), insert(a, 1, a[:, 2, :], axis=1)
590        )
591
592    def test_0d(self):
593        a = np.array(1)
594        with pytest.raises(np.AxisError):
595            insert(a, [], 2, axis=0)
596        with pytest.raises(TypeError):
597            insert(a, [], 2, axis="nonsense")
598
599    def test_index_array_copied(self):
600        x = np.array([1, 1, 1])
601        np.insert([0, 1, 2], x, [3, 4, 5])
602        assert_equal(x, np.array([1, 1, 1]))
603
604    def test_index_floats(self):
605        with pytest.raises(IndexError):
606            np.insert([0, 1, 2], np.array([1.0, 2.0]), [10, 20])
607        with pytest.raises(IndexError):
608            np.insert([0, 1, 2], np.array([], dtype=float), [])
609
610    @skip(reason="NP_VER: fails on CI")
611    @parametrize("idx", [4, -4])
612    def test_index_out_of_bounds(self, idx):
613        with pytest.raises(IndexError, match="out of bounds"):
614            np.insert([0, 1, 2], [idx], [3, 4])
615
616
617class TestAmax(TestCase):
618    def test_basic(self):
619        a = [3, 4, 5, 10, -3, -5, 6.0]
620        assert_equal(np.amax(a), 10.0)
621        b = [[3, 6.0, 9.0], [4, 10.0, 5.0], [8, 3.0, 2.0]]
622        assert_equal(np.amax(b, axis=0), [8.0, 10.0, 9.0])
623        assert_equal(np.amax(b, axis=1), [9.0, 10.0, 8.0])
624
625
626class TestAmin(TestCase):
627    def test_basic(self):
628        a = [3, 4, 5, 10, -3, -5, 6.0]
629        assert_equal(np.amin(a), -5.0)
630        b = [[3, 6.0, 9.0], [4, 10.0, 5.0], [8, 3.0, 2.0]]
631        assert_equal(np.amin(b, axis=0), [3.0, 3.0, 2.0])
632        assert_equal(np.amin(b, axis=1), [3.0, 4.0, 2.0])
633
634
635class TestPtp(TestCase):
636    def test_basic(self):
637        a = np.array([3, 4, 5, 10, -3, -5, 6.0])
638        assert_equal(a.ptp(axis=0), 15.0)
639        b = np.array([[3, 6.0, 9.0], [4, 10.0, 5.0], [8, 3.0, 2.0]])
640        assert_equal(b.ptp(axis=0), [5.0, 7.0, 7.0])
641        assert_equal(b.ptp(axis=-1), [6.0, 6.0, 6.0])
642
643        assert_equal(b.ptp(axis=0, keepdims=True), [[5.0, 7.0, 7.0]])
644        assert_equal(b.ptp(axis=(0, 1), keepdims=True), [[8.0]])
645
646
647class TestCumsum(TestCase):
648    def test_basic(self):
649        ba = [1, 2, 10, 11, 6, 5, 4]
650        ba2 = [[1, 2, 3, 4], [5, 6, 7, 9], [10, 3, 4, 5]]
651        for ctype in [
652            np.int8,
653            np.uint8,
654            np.int16,
655            np.int32,
656            np.float32,
657            np.float64,
658            np.complex64,
659            np.complex128,
660        ]:
661            a = np.array(ba, ctype)
662            a2 = np.array(ba2, ctype)
663
664            tgt = np.array([1, 3, 13, 24, 30, 35, 39], ctype)
665            assert_array_equal(np.cumsum(a, axis=0), tgt)
666
667            tgt = np.array([[1, 2, 3, 4], [6, 8, 10, 13], [16, 11, 14, 18]], ctype)
668            assert_array_equal(np.cumsum(a2, axis=0), tgt)
669
670            tgt = np.array([[1, 3, 6, 10], [5, 11, 18, 27], [10, 13, 17, 22]], ctype)
671            assert_array_equal(np.cumsum(a2, axis=1), tgt)
672
673
674class TestProd(TestCase):
675    def test_basic(self):
676        ba = [1, 2, 10, 11, 6, 5, 4]
677        ba2 = [[1, 2, 3, 4], [5, 6, 7, 9], [10, 3, 4, 5]]
678        for ctype in [
679            np.int16,
680            np.int32,
681            np.float32,
682            np.float64,
683            np.complex64,
684            np.complex128,
685        ]:
686            a = np.array(ba, ctype)
687            a2 = np.array(ba2, ctype)
688            if ctype in ["1", "b"]:
689                assert_raises(ArithmeticError, np.prod, a)
690                assert_raises(ArithmeticError, np.prod, a2, 1)
691            else:
692                assert_equal(a.prod(axis=0), 26400)
693                assert_array_equal(a2.prod(axis=0), np.array([50, 36, 84, 180], ctype))
694                assert_array_equal(a2.prod(axis=-1), np.array([24, 1890, 600], ctype))
695
696
697class TestCumprod(TestCase):
698    def test_basic(self):
699        ba = [1, 2, 10, 11, 6, 5, 4]
700        ba2 = [[1, 2, 3, 4], [5, 6, 7, 9], [10, 3, 4, 5]]
701        for ctype in [
702            np.int16,
703            np.int32,
704            np.float32,
705            np.float64,
706            np.complex64,
707            np.complex128,
708        ]:
709            a = np.array(ba, ctype)
710            a2 = np.array(ba2, ctype)
711            if ctype in ["1", "b"]:
712                assert_raises(ArithmeticError, np.cumprod, a)
713                assert_raises(ArithmeticError, np.cumprod, a2, 1)
714                assert_raises(ArithmeticError, np.cumprod, a)
715            else:
716                assert_array_equal(
717                    np.cumprod(a, axis=-1),
718                    np.array([1, 2, 20, 220, 1320, 6600, 26400], ctype),
719                )
720                assert_array_equal(
721                    np.cumprod(a2, axis=0),
722                    np.array([[1, 2, 3, 4], [5, 12, 21, 36], [50, 36, 84, 180]], ctype),
723                )
724                assert_array_equal(
725                    np.cumprod(a2, axis=-1),
726                    np.array(
727                        [[1, 2, 6, 24], [5, 30, 210, 1890], [10, 30, 120, 600]], ctype
728                    ),
729                )
730
731
732class TestDiff(TestCase):
733    def test_basic(self):
734        x = [1, 4, 6, 7, 12]
735        out = np.array([3, 2, 1, 5])
736        out2 = np.array([-1, -1, 4])
737        out3 = np.array([0, 5])
738        assert_array_equal(diff(x), out)
739        assert_array_equal(diff(x, n=2), out2)
740        assert_array_equal(diff(x, n=3), out3)
741
742        x = [1.1, 2.2, 3.0, -0.2, -0.1]
743        out = np.array([1.1, 0.8, -3.2, 0.1])
744        assert_almost_equal(diff(x), out)
745
746        x = [True, True, False, False]
747        out = np.array([False, True, False])
748        out2 = np.array([True, True])
749        assert_array_equal(diff(x), out)
750        assert_array_equal(diff(x, n=2), out2)
751
752    def test_axis(self):
753        x = np.zeros((10, 20, 30))
754        x[:, 1::2, :] = 1
755        exp = np.ones((10, 19, 30))
756        exp[:, 1::2, :] = -1
757        assert_array_equal(diff(x), np.zeros((10, 20, 29)))
758        assert_array_equal(diff(x, axis=-1), np.zeros((10, 20, 29)))
759        assert_array_equal(diff(x, axis=0), np.zeros((9, 20, 30)))
760        assert_array_equal(diff(x, axis=1), exp)
761        assert_array_equal(diff(x, axis=-2), exp)
762        assert_raises(np.AxisError, diff, x, axis=3)
763        assert_raises(np.AxisError, diff, x, axis=-4)
764
765        x = np.array(1.11111111111, np.float64)
766        assert_raises(ValueError, diff, x)
767
768    def test_nd(self):
769        x = 20 * rand(10, 20, 30)
770        out1 = x[:, :, 1:] - x[:, :, :-1]
771        out2 = out1[:, :, 1:] - out1[:, :, :-1]
772        out3 = x[1:, :, :] - x[:-1, :, :]
773        out4 = out3[1:, :, :] - out3[:-1, :, :]
774        assert_array_equal(diff(x), out1)
775        assert_array_equal(diff(x, n=2), out2)
776        assert_array_equal(diff(x, axis=0), out3)
777        assert_array_equal(diff(x, n=2, axis=0), out4)
778
779    def test_n(self):
780        x = list(range(3))
781        assert_raises(ValueError, diff, x, n=-1)
782        output = [diff(x, n=n) for n in range(1, 5)]
783        expected_output = [[1, 1], [0], [], []]
784        # assert_(diff(x, n=0) is x)
785        for n, (expected, out) in enumerate(zip(expected_output, output), start=1):
786            assert_(type(out) is np.ndarray)
787            assert_array_equal(out, expected)
788            assert_equal(out.dtype, np.int_)
789            assert_equal(len(out), max(0, len(x) - n))
790
791    def test_prepend(self):
792        x = np.arange(5) + 1
793        assert_array_equal(diff(x, prepend=0), np.ones(5))
794        assert_array_equal(diff(x, prepend=[0]), np.ones(5))
795        assert_array_equal(np.cumsum(np.diff(x, prepend=0)), x)
796        assert_array_equal(diff(x, prepend=[-1, 0]), np.ones(6))
797
798        x = np.arange(4).reshape(2, 2)
799        result = np.diff(x, axis=1, prepend=0)
800        expected = [[0, 1], [2, 1]]
801        assert_array_equal(result, expected)
802        result = np.diff(x, axis=1, prepend=[[0], [0]])
803        assert_array_equal(result, expected)
804
805        result = np.diff(x, axis=0, prepend=0)
806        expected = [[0, 1], [2, 2]]
807        assert_array_equal(result, expected)
808        result = np.diff(x, axis=0, prepend=[[0, 0]])
809        assert_array_equal(result, expected)
810
811        assert_raises((ValueError, RuntimeError), np.diff, x, prepend=np.zeros((3, 3)))
812
813        assert_raises(np.AxisError, diff, x, prepend=0, axis=3)
814
815    def test_append(self):
816        x = np.arange(5)
817        result = diff(x, append=0)
818        expected = [1, 1, 1, 1, -4]
819        assert_array_equal(result, expected)
820        result = diff(x, append=[0])
821        assert_array_equal(result, expected)
822        result = diff(x, append=[0, 2])
823        expected = expected + [2]
824        assert_array_equal(result, expected)
825
826        x = np.arange(4).reshape(2, 2)
827        result = np.diff(x, axis=1, append=0)
828        expected = [[1, -1], [1, -3]]
829        assert_array_equal(result, expected)
830        result = np.diff(x, axis=1, append=[[0], [0]])
831        assert_array_equal(result, expected)
832
833        result = np.diff(x, axis=0, append=0)
834        expected = [[2, 2], [-2, -3]]
835        assert_array_equal(result, expected)
836        result = np.diff(x, axis=0, append=[[0, 0]])
837        assert_array_equal(result, expected)
838
839        assert_raises((ValueError, RuntimeError), np.diff, x, append=np.zeros((3, 3)))
840
841        assert_raises(np.AxisError, diff, x, append=0, axis=3)
842
843
844@xpassIfTorchDynamo  # (reason="TODO: implement")
845@instantiate_parametrized_tests
846class TestDelete(TestCase):
847    def setUp(self):
848        self.a = np.arange(5)
849        self.nd_a = np.arange(5).repeat(2).reshape(1, 5, 2)
850
851    def _check_inverse_of_slicing(self, indices):
852        a_del = delete(self.a, indices)
853        nd_a_del = delete(self.nd_a, indices, axis=1)
854        msg = f"Delete failed for obj: {indices!r}"
855        assert_array_equal(setxor1d(a_del, self.a[indices,]), self.a, err_msg=msg)
856        xor = setxor1d(nd_a_del[0, :, 0], self.nd_a[0, indices, 0])
857        assert_array_equal(xor, self.nd_a[0, :, 0], err_msg=msg)
858
859    def test_slices(self):
860        lims = [-6, -2, 0, 1, 2, 4, 5]
861        steps = [-3, -1, 1, 3]
862        for start in lims:
863            for stop in lims:
864                for step in steps:
865                    s = slice(start, stop, step)
866                    self._check_inverse_of_slicing(s)
867
868    def test_fancy(self):
869        self._check_inverse_of_slicing(np.array([[0, 1], [2, 1]]))
870        with pytest.raises(IndexError):
871            delete(self.a, [100])
872        with pytest.raises(IndexError):
873            delete(self.a, [-100])
874
875        self._check_inverse_of_slicing([0, -1, 2, 2])
876
877        self._check_inverse_of_slicing([True, False, False, True, False])
878
879        # not legal, indexing with these would change the dimension
880        with pytest.raises(ValueError):
881            delete(self.a, True)
882        with pytest.raises(ValueError):
883            delete(self.a, False)
884
885        # not enough items
886        with pytest.raises(ValueError):
887            delete(self.a, [False] * 4)
888
889    def test_single(self):
890        self._check_inverse_of_slicing(0)
891        self._check_inverse_of_slicing(-4)
892
893    def test_0d(self):
894        a = np.array(1)
895        with pytest.raises(np.AxisError):
896            delete(a, [], axis=0)
897        with pytest.raises(TypeError):
898            delete(a, [], axis="nonsense")
899
900    def test_array_order_preserve(self):
901        # See gh-7113
902        k = np.arange(10).reshape(2, 5, order="F")
903        m = delete(k, slice(60, None), axis=1)
904
905        # 'k' is Fortran ordered, and 'm' should have the
906        # same ordering as 'k' and NOT become C ordered
907        assert_equal(m.flags.c_contiguous, k.flags.c_contiguous)
908        assert_equal(m.flags.f_contiguous, k.flags.f_contiguous)
909
910    def test_index_floats(self):
911        with pytest.raises(IndexError):
912            np.delete([0, 1, 2], np.array([1.0, 2.0]))
913        with pytest.raises(IndexError):
914            np.delete([0, 1, 2], np.array([], dtype=float))
915
916    @parametrize(
917        "indexer", [subtest(np.array([1]), name="array([1])"), subtest([1], name="[1]")]
918    )
919    def test_single_item_array(self, indexer):
920        a_del_int = delete(self.a, 1)
921        a_del = delete(self.a, indexer)
922        assert_equal(a_del_int, a_del)
923
924        nd_a_del_int = delete(self.nd_a, 1, axis=1)
925        nd_a_del = delete(self.nd_a, np.array([1]), axis=1)
926        assert_equal(nd_a_del_int, nd_a_del)
927
928    def test_single_item_array_non_int(self):
929        # Special handling for integer arrays must not affect non-integer ones.
930        # If `False` was cast to `0` it would delete the element:
931        res = delete(np.ones(1), np.array([False]))
932        assert_array_equal(res, np.ones(1))
933
934        # Test the more complicated (with axis) case from gh-21840
935        x = np.ones((3, 1))
936        false_mask = np.array([False], dtype=bool)
937        true_mask = np.array([True], dtype=bool)
938
939        res = delete(x, false_mask, axis=-1)
940        assert_array_equal(res, x)
941        res = delete(x, true_mask, axis=-1)
942        assert_array_equal(res, x[:, :0])
943
944
945@instantiate_parametrized_tests
946class TestGradient(TestCase):
947    def test_basic(self):
948        v = [[1, 1], [3, 4]]
949        x = np.array(v)
950        dx = [np.array([[2.0, 3.0], [2.0, 3.0]]), np.array([[0.0, 0.0], [1.0, 1.0]])]
951        assert_array_equal(gradient(x), dx)
952        assert_array_equal(gradient(v), dx)
953
954    def test_args(self):
955        dx = np.cumsum(np.ones(5))
956        dx_uneven = [1.0, 2.0, 5.0, 9.0, 11.0]
957        f_2d = np.arange(25).reshape(5, 5)
958
959        # distances must be scalars or have size equal to gradient[axis]
960        gradient(np.arange(5), 3.0)
961        gradient(np.arange(5), np.array(3.0))
962        gradient(np.arange(5), dx)
963        # dy is set equal to dx because scalar
964        gradient(f_2d, 1.5)
965        gradient(f_2d, np.array(1.5))
966
967        gradient(f_2d, dx_uneven, dx_uneven)
968        # mix between even and uneven spaces and
969        # mix between scalar and vector
970        gradient(f_2d, dx, 2)
971
972        # 2D but axis specified
973        gradient(f_2d, dx, axis=1)
974
975        # 2d coordinate arguments are not yet allowed
976        assert_raises_regex(
977            ValueError,
978            ".*scalars or 1d",
979            gradient,
980            f_2d,
981            np.stack([dx] * 2, axis=-1),
982            1,
983        )
984
985    def test_badargs(self):
986        f_2d = np.arange(25).reshape(5, 5)
987        x = np.cumsum(np.ones(5))
988
989        # wrong sizes
990        assert_raises(ValueError, gradient, f_2d, x, np.ones(2))
991        assert_raises(ValueError, gradient, f_2d, 1, np.ones(2))
992        assert_raises(ValueError, gradient, f_2d, np.ones(2), np.ones(2))
993        # wrong number of arguments
994        assert_raises(TypeError, gradient, f_2d, x)
995        assert_raises(TypeError, gradient, f_2d, x, axis=(0, 1))
996        assert_raises(TypeError, gradient, f_2d, x, x, x)
997        assert_raises(TypeError, gradient, f_2d, 1, 1, 1)
998        assert_raises(TypeError, gradient, f_2d, x, x, axis=1)
999        assert_raises(TypeError, gradient, f_2d, 1, 1, axis=1)
1000
1001    def test_second_order_accurate(self):
1002        # Testing that the relative numerical error is less that 3% for
1003        # this example problem. This corresponds to second order
1004        # accurate finite differences for all interior and boundary
1005        # points.
1006        x = np.linspace(0, 1, 10)
1007        dx = x[1] - x[0]
1008        y = 2 * x**3 + 4 * x**2 + 2 * x
1009        analytical = 6 * x**2 + 8 * x + 2
1010        num_error = np.abs((np.gradient(y, dx, edge_order=2) / analytical) - 1)
1011        assert_(np.all(num_error < 0.03).item() is True)
1012
1013        # test with unevenly spaced
1014        np.random.seed(0)
1015        x = np.sort(np.random.random(10))
1016        y = 2 * x**3 + 4 * x**2 + 2 * x
1017        analytical = 6 * x**2 + 8 * x + 2
1018        num_error = np.abs((np.gradient(y, x, edge_order=2) / analytical) - 1)
1019        assert_(np.all(num_error < 0.03).item() is True)
1020
1021    def test_spacing(self):
1022        f = np.array([0, 2.0, 3.0, 4.0, 5.0, 5.0])
1023        f = np.tile(f, (6, 1)) + f.reshape(-1, 1)
1024        x_uneven = np.array([0.0, 0.5, 1.0, 3.0, 5.0, 7.0])
1025        x_even = np.arange(6.0)
1026
1027        fdx_even_ord1 = np.tile([2.0, 1.5, 1.0, 1.0, 0.5, 0.0], (6, 1))
1028        fdx_even_ord2 = np.tile([2.5, 1.5, 1.0, 1.0, 0.5, -0.5], (6, 1))
1029        fdx_uneven_ord1 = np.tile([4.0, 3.0, 1.7, 0.5, 0.25, 0.0], (6, 1))
1030        fdx_uneven_ord2 = np.tile([5.0, 3.0, 1.7, 0.5, 0.25, -0.25], (6, 1))
1031
1032        # evenly spaced
1033        for edge_order, exp_res in [(1, fdx_even_ord1), (2, fdx_even_ord2)]:
1034            res1 = gradient(f, 1.0, axis=(0, 1), edge_order=edge_order)
1035            res2 = gradient(f, x_even, x_even, axis=(0, 1), edge_order=edge_order)
1036            res3 = gradient(f, x_even, x_even, axis=None, edge_order=edge_order)
1037            assert_array_equal(res1, res2)
1038            assert_array_equal(res2, res3)
1039            assert_almost_equal(res1[0], exp_res.T)
1040            assert_almost_equal(res1[1], exp_res)
1041
1042            res1 = gradient(f, 1.0, axis=0, edge_order=edge_order)
1043            res2 = gradient(f, x_even, axis=0, edge_order=edge_order)
1044            assert_(res1.shape == res2.shape)
1045            assert_almost_equal(res2, exp_res.T)
1046
1047            res1 = gradient(f, 1.0, axis=1, edge_order=edge_order)
1048            res2 = gradient(f, x_even, axis=1, edge_order=edge_order)
1049            assert_(res1.shape == res2.shape)
1050            assert_array_equal(res2, exp_res)
1051
1052        # unevenly spaced
1053        for edge_order, exp_res in [(1, fdx_uneven_ord1), (2, fdx_uneven_ord2)]:
1054            res1 = gradient(f, x_uneven, x_uneven, axis=(0, 1), edge_order=edge_order)
1055            res2 = gradient(f, x_uneven, x_uneven, axis=None, edge_order=edge_order)
1056            assert_array_equal(res1, res2)
1057            assert_almost_equal(res1[0], exp_res.T)
1058            assert_almost_equal(res1[1], exp_res)
1059
1060            res1 = gradient(f, x_uneven, axis=0, edge_order=edge_order)
1061            assert_almost_equal(res1, exp_res.T)
1062
1063            res1 = gradient(f, x_uneven, axis=1, edge_order=edge_order)
1064            assert_almost_equal(res1, exp_res)
1065
1066        # mixed
1067        res1 = gradient(f, x_even, x_uneven, axis=(0, 1), edge_order=1)
1068        res2 = gradient(f, x_uneven, x_even, axis=(1, 0), edge_order=1)
1069        assert_array_equal(res1[0], res2[1])
1070        assert_array_equal(res1[1], res2[0])
1071        assert_almost_equal(res1[0], fdx_even_ord1.T)
1072        assert_almost_equal(res1[1], fdx_uneven_ord1)
1073
1074        res1 = gradient(f, x_even, x_uneven, axis=(0, 1), edge_order=2)
1075        res2 = gradient(f, x_uneven, x_even, axis=(1, 0), edge_order=2)
1076        assert_array_equal(res1[0], res2[1])
1077        assert_array_equal(res1[1], res2[0])
1078        assert_almost_equal(res1[0], fdx_even_ord2.T)
1079        assert_almost_equal(res1[1], fdx_uneven_ord2)
1080
1081    def test_specific_axes(self):
1082        # Testing that gradient can work on a given axis only
1083        v = [[1, 1], [3, 4]]
1084        x = np.array(v)
1085        dx = [np.array([[2.0, 3.0], [2.0, 3.0]]), np.array([[0.0, 0.0], [1.0, 1.0]])]
1086        assert_array_equal(gradient(x, axis=0), dx[0])
1087        assert_array_equal(gradient(x, axis=1), dx[1])
1088        assert_array_equal(gradient(x, axis=-1), dx[1])
1089        assert_array_equal(gradient(x, axis=(1, 0)), [dx[1], dx[0]])
1090
1091        # test axis=None which means all axes
1092        assert_almost_equal(gradient(x, axis=None), [dx[0], dx[1]])
1093        # and is the same as no axis keyword given
1094        assert_almost_equal(gradient(x, axis=None), gradient(x))
1095
1096        # test vararg order
1097        assert_array_equal(gradient(x, 2, 3, axis=(1, 0)), [dx[1] / 2.0, dx[0] / 3.0])
1098        # test maximal number of varargs
1099        assert_raises(TypeError, gradient, x, 1, 2, axis=1)
1100
1101        assert_raises(np.AxisError, gradient, x, axis=3)
1102        assert_raises(np.AxisError, gradient, x, axis=-3)
1103        # assert_raises(TypeError, gradient, x, axis=[1,])
1104
1105    def test_inexact_dtypes(self):
1106        for dt in [np.float16, np.float32, np.float64]:
1107            # dtypes should not be promoted in a different way to what diff does
1108            x = np.array([1, 2, 3], dtype=dt)
1109            assert_equal(gradient(x).dtype, np.diff(x).dtype)
1110
1111    def test_values(self):
1112        # needs at least 2 points for edge_order ==1
1113        gradient(np.arange(2), edge_order=1)
1114        # needs at least 3 points for edge_order ==1
1115        gradient(np.arange(3), edge_order=2)
1116
1117        assert_raises(ValueError, gradient, np.arange(0), edge_order=1)
1118        assert_raises(ValueError, gradient, np.arange(0), edge_order=2)
1119        assert_raises(ValueError, gradient, np.arange(1), edge_order=1)
1120        assert_raises(ValueError, gradient, np.arange(1), edge_order=2)
1121        assert_raises(ValueError, gradient, np.arange(2), edge_order=2)
1122
1123    @parametrize(
1124        "f_dtype",
1125        [
1126            np.uint8,
1127        ],
1128    )
1129    def test_f_decreasing_unsigned_int(self, f_dtype):
1130        f = np.array([5, 4, 3, 2, 1], dtype=f_dtype)
1131        g = gradient(f)
1132        assert_array_equal(g, [-1] * len(f))
1133
1134    @parametrize("f_dtype", [np.int8, np.int16, np.int32, np.int64])
1135    def test_f_signed_int_big_jump(self, f_dtype):
1136        maxint = np.iinfo(f_dtype).max
1137        x = np.array([1, 3])
1138        f = np.array([-1, maxint], dtype=f_dtype)
1139        dfdx = gradient(f, x)
1140        assert_array_equal(dfdx, [(maxint + 1) // 2] * 2)
1141
1142    @parametrize(
1143        "x_dtype",
1144        [
1145            np.uint8,
1146        ],
1147    )
1148    def test_x_decreasing_unsigned(self, x_dtype):
1149        x = np.array([3, 2, 1], dtype=x_dtype)
1150        f = np.array([0, 2, 4])
1151        dfdx = gradient(f, x)
1152        assert_array_equal(dfdx, [-2] * len(x))
1153
1154    @parametrize("x_dtype", [np.int8, np.int16, np.int32, np.int64])
1155    def test_x_signed_int_big_jump(self, x_dtype):
1156        minint = np.iinfo(x_dtype).min
1157        maxint = np.iinfo(x_dtype).max
1158        x = np.array([-1, maxint], dtype=x_dtype)
1159        f = np.array([minint // 2, 0])
1160        dfdx = gradient(f, x)
1161        assert_array_equal(dfdx, [0.5, 0.5])
1162
1163
1164class TestAngle(TestCase):
1165    def test_basic(self):
1166        x = [
1167            1 + 3j,
1168            np.sqrt(2) / 2.0 + 1j * np.sqrt(2) / 2,
1169            1,
1170            1j,
1171            -1,
1172            -1j,
1173            1 - 3j,
1174            -1 + 3j,
1175        ]
1176        y = angle(x)
1177        yo = [
1178            np.arctan(3.0 / 1.0),
1179            np.arctan(1.0),
1180            0,
1181            np.pi / 2,
1182            np.pi,
1183            -np.pi / 2.0,
1184            -np.arctan(3.0 / 1.0),
1185            np.pi - np.arctan(3.0 / 1.0),
1186        ]
1187        z = angle(x, deg=True)
1188        zo = np.array(yo) * 180 / np.pi
1189        assert_array_almost_equal(y, yo, 11)
1190        assert_array_almost_equal(z, zo, 11)
1191
1192
1193@xpassIfTorchDynamo
1194@instantiate_parametrized_tests
1195class TestTrimZeros(TestCase):
1196    a = np.array([0, 0, 1, 0, 2, 3, 4, 0])
1197    b = a.astype(float)
1198    c = a.astype(complex)
1199    #    d = a.astype(object)
1200
1201    def values(self):
1202        attr_names = (
1203            "a",
1204            "b",
1205            "c",
1206        )  # "d")
1207        return (getattr(self, name) for name in attr_names)
1208
1209    def test_basic(self):
1210        slc = np.s_[2:-1]
1211        for arr in self.values():
1212            res = trim_zeros(arr)
1213            assert_array_equal(res, arr[slc])
1214
1215    def test_leading_skip(self):
1216        slc = np.s_[:-1]
1217        for arr in self.values():
1218            res = trim_zeros(arr, trim="b")
1219            assert_array_equal(res, arr[slc])
1220
1221    def test_trailing_skip(self):
1222        slc = np.s_[2:]
1223        for arr in self.values():
1224            res = trim_zeros(arr, trim="F")
1225            assert_array_equal(res, arr[slc])
1226
1227    def test_all_zero(self):
1228        for _arr in self.values():
1229            arr = np.zeros_like(_arr, dtype=_arr.dtype)
1230
1231            res1 = trim_zeros(arr, trim="B")
1232            assert len(res1) == 0
1233
1234            res2 = trim_zeros(arr, trim="f")
1235            assert len(res2) == 0
1236
1237    def test_size_zero(self):
1238        arr = np.zeros(0)
1239        res = trim_zeros(arr)
1240        assert_array_equal(arr, res)
1241
1242    @parametrize(
1243        "arr",
1244        [
1245            np.array([0, 2**62, 0]),
1246            #         np.array([0, 2**63, 0]),     # FIXME
1247            #         np.array([0, 2**64, 0])
1248        ],
1249    )
1250    def test_overflow(self, arr):
1251        slc = np.s_[1:2]
1252        res = trim_zeros(arr)
1253        assert_array_equal(res, arr[slc])
1254
1255    def test_no_trim(self):
1256        arr = np.array([None, 1, None])
1257        res = trim_zeros(arr)
1258        assert_array_equal(arr, res)
1259
1260    def test_list_to_list(self):
1261        res = trim_zeros(self.a.tolist())
1262        assert isinstance(res, list)
1263
1264
1265@xpassIfTorchDynamo  # (reason="TODO: implement")
1266class TestExtins(TestCase):
1267    def test_basic(self):
1268        a = np.array([1, 3, 2, 1, 2, 3, 3])
1269        b = extract(a > 1, a)
1270        assert_array_equal(b, [3, 2, 2, 3, 3])
1271
1272    def test_place(self):
1273        # Make sure that non-np.ndarray objects
1274        # raise an error instead of doing nothing
1275        assert_raises(TypeError, place, [1, 2, 3], [True, False], [0, 1])
1276
1277        a = np.array([1, 4, 3, 2, 5, 8, 7])
1278        place(a, [0, 1, 0, 1, 0, 1, 0], [2, 4, 6])
1279        assert_array_equal(a, [1, 2, 3, 4, 5, 6, 7])
1280
1281        place(a, np.zeros(7), [])
1282        assert_array_equal(a, np.arange(1, 8))
1283
1284        place(a, [1, 0, 1, 0, 1, 0, 1], [8, 9])
1285        assert_array_equal(a, [8, 2, 9, 4, 8, 6, 9])
1286        assert_raises_regex(
1287            ValueError,
1288            "Cannot insert from an empty array",
1289            lambda: place(a, [0, 0, 0, 0, 0, 1, 0], []),
1290        )
1291
1292        # See Issue #6974
1293        a = np.array(["12", "34"])
1294        place(a, [0, 1], "9")
1295        assert_array_equal(a, ["12", "9"])
1296
1297    def test_both(self):
1298        a = rand(10)
1299        mask = a > 0.5
1300        ac = a.copy()
1301        c = extract(mask, a)
1302        place(a, mask, 0)
1303        place(a, mask, c)
1304        assert_array_equal(a, ac)
1305
1306
1307# _foo1 and _foo2 are used in some tests in TestVectorize.
1308
1309
1310def _foo1(x, y=1.0):
1311    return y * math.floor(x)
1312
1313
1314def _foo2(x, y=1.0, z=0.0):
1315    return y * math.floor(x) + z
1316
1317
1318@skip  # (reason="vectorize not implemented")
1319class TestVectorize(TestCase):
1320    def test_simple(self):
1321        def addsubtract(a, b):
1322            if a > b:
1323                return a - b
1324            else:
1325                return a + b
1326
1327        f = vectorize(addsubtract)
1328        r = f([0, 3, 6, 9], [1, 3, 5, 7])
1329        assert_array_equal(r, [1, 6, 1, 2])
1330
1331    def test_scalar(self):
1332        def addsubtract(a, b):
1333            if a > b:
1334                return a - b
1335            else:
1336                return a + b
1337
1338        f = vectorize(addsubtract)
1339        r = f([0, 3, 6, 9], 5)
1340        assert_array_equal(r, [5, 8, 1, 4])
1341
1342    def test_large(self):
1343        x = np.linspace(-3, 2, 10000)
1344        f = vectorize(lambda x: x)
1345        y = f(x)
1346        assert_array_equal(y, x)
1347
1348    def test_ufunc(self):
1349        f = vectorize(math.cos)
1350        args = np.array([0, 0.5 * np.pi, np.pi, 1.5 * np.pi, 2 * np.pi])
1351        r1 = f(args)
1352        r2 = np.cos(args)
1353        assert_array_almost_equal(r1, r2)
1354
1355    def test_keywords(self):
1356        def foo(a, b=1):
1357            return a + b
1358
1359        f = vectorize(foo)
1360        args = np.array([1, 2, 3])
1361        r1 = f(args)
1362        r2 = np.array([2, 3, 4])
1363        assert_array_equal(r1, r2)
1364        r1 = f(args, 2)
1365        r2 = np.array([3, 4, 5])
1366        assert_array_equal(r1, r2)
1367
1368    def test_keywords_with_otypes_order1(self):
1369        # gh-1620: The second call of f would crash with
1370        # `ValueError: invalid number of arguments`.
1371        f = vectorize(_foo1, otypes=[float])
1372        # We're testing the caching of ufuncs by vectorize, so the order
1373        # of these function calls is an important part of the test.
1374        r1 = f(np.arange(3.0), 1.0)
1375        r2 = f(np.arange(3.0))
1376        assert_array_equal(r1, r2)
1377
1378    def test_keywords_with_otypes_order2(self):
1379        # gh-1620: The second call of f would crash with
1380        # `ValueError: non-broadcastable output operand with shape ()
1381        # doesn't match the broadcast shape (3,)`.
1382        f = vectorize(_foo1, otypes=[float])
1383        # We're testing the caching of ufuncs by vectorize, so the order
1384        # of these function calls is an important part of the test.
1385        r1 = f(np.arange(3.0))
1386        r2 = f(np.arange(3.0), 1.0)
1387        assert_array_equal(r1, r2)
1388
1389    def test_keywords_with_otypes_order3(self):
1390        # gh-1620: The third call of f would crash with
1391        # `ValueError: invalid number of arguments`.
1392        f = vectorize(_foo1, otypes=[float])
1393        # We're testing the caching of ufuncs by vectorize, so the order
1394        # of these function calls is an important part of the test.
1395        r1 = f(np.arange(3.0))
1396        r2 = f(np.arange(3.0), y=1.0)
1397        r3 = f(np.arange(3.0))
1398        assert_array_equal(r1, r2)
1399        assert_array_equal(r1, r3)
1400
1401    def test_keywords_with_otypes_several_kwd_args1(self):
1402        # gh-1620 Make sure different uses of keyword arguments
1403        # don't break the vectorized function.
1404        f = vectorize(_foo2, otypes=[float])
1405        # We're testing the caching of ufuncs by vectorize, so the order
1406        # of these function calls is an important part of the test.
1407        r1 = f(10.4, z=100)
1408        r2 = f(10.4, y=-1)
1409        r3 = f(10.4)
1410        assert_equal(r1, _foo2(10.4, z=100))
1411        assert_equal(r2, _foo2(10.4, y=-1))
1412        assert_equal(r3, _foo2(10.4))
1413
1414    def test_keywords_with_otypes_several_kwd_args2(self):
1415        # gh-1620 Make sure different uses of keyword arguments
1416        # don't break the vectorized function.
1417        f = vectorize(_foo2, otypes=[float])
1418        # We're testing the caching of ufuncs by vectorize, so the order
1419        # of these function calls is an important part of the test.
1420        r1 = f(z=100, x=10.4, y=-1)
1421        r2 = f(1, 2, 3)
1422        assert_equal(r1, _foo2(z=100, x=10.4, y=-1))
1423        assert_equal(r2, _foo2(1, 2, 3))
1424
1425    def test_keywords_no_func_code(self):
1426        # This needs to test a function that has keywords but
1427        # no func_code attribute, since otherwise vectorize will
1428        # inspect the func_code.
1429        import random
1430
1431        try:
1432            vectorize(random.randrange)  # Should succeed
1433        except Exception:
1434            raise AssertionError  # noqa: B904
1435
1436    def test_keywords2_ticket_2100(self):
1437        # Test kwarg support: enhancement ticket 2100
1438
1439        def foo(a, b=1):
1440            return a + b
1441
1442        f = vectorize(foo)
1443        args = np.array([1, 2, 3])
1444        r1 = f(a=args)
1445        r2 = np.array([2, 3, 4])
1446        assert_array_equal(r1, r2)
1447        r1 = f(b=1, a=args)
1448        assert_array_equal(r1, r2)
1449        r1 = f(args, b=2)
1450        r2 = np.array([3, 4, 5])
1451        assert_array_equal(r1, r2)
1452
1453    def test_keywords3_ticket_2100(self):
1454        # Test excluded with mixed positional and kwargs: ticket 2100
1455        def mypolyval(x, p):
1456            _p = list(p)
1457            res = _p.pop(0)
1458            while _p:
1459                res = res * x + _p.pop(0)
1460            return res
1461
1462        vpolyval = np.vectorize(mypolyval, excluded=["p", 1])
1463        ans = [3, 6]
1464        assert_array_equal(ans, vpolyval(x=[0, 1], p=[1, 2, 3]))
1465        assert_array_equal(ans, vpolyval([0, 1], p=[1, 2, 3]))
1466        assert_array_equal(ans, vpolyval([0, 1], [1, 2, 3]))
1467
1468    def test_keywords4_ticket_2100(self):
1469        # Test vectorizing function with no positional args.
1470        @vectorize
1471        def f(**kw):
1472            res = 1.0
1473            for _k in kw:
1474                res *= kw[_k]
1475            return res
1476
1477        assert_array_equal(f(a=[1, 2], b=[3, 4]), [3, 8])
1478
1479    def test_keywords5_ticket_2100(self):
1480        # Test vectorizing function with no kwargs args.
1481        @vectorize
1482        def f(*v):
1483            return np.prod(v)
1484
1485        assert_array_equal(f([1, 2], [3, 4]), [3, 8])
1486
1487    def test_coverage1_ticket_2100(self):
1488        def foo():
1489            return 1
1490
1491        f = vectorize(foo)
1492        assert_array_equal(f(), 1)
1493
1494    def test_assigning_docstring(self):
1495        def foo(x):
1496            """Original documentation"""
1497            return x
1498
1499        f = vectorize(foo)
1500        assert_equal(f.__doc__, foo.__doc__)
1501
1502        doc = "Provided documentation"
1503        f = vectorize(foo, doc=doc)
1504        assert_equal(f.__doc__, doc)
1505
1506    def test_UnboundMethod_ticket_1156(self):
1507        # Regression test for issue 1156
1508        class Foo:
1509            b = 2
1510
1511            def bar(self, a):
1512                return a**self.b
1513
1514        assert_array_equal(vectorize(Foo().bar)(np.arange(9)), np.arange(9) ** 2)
1515        assert_array_equal(vectorize(Foo.bar)(Foo(), np.arange(9)), np.arange(9) ** 2)
1516
1517    def test_execution_order_ticket_1487(self):
1518        # Regression test for dependence on execution order: issue 1487
1519        f1 = vectorize(lambda x: x)
1520        res1a = f1(np.arange(3))
1521        res1b = f1(np.arange(0.1, 3))
1522        f2 = vectorize(lambda x: x)
1523        res2b = f2(np.arange(0.1, 3))
1524        res2a = f2(np.arange(3))
1525        assert_equal(res1a, res2a)
1526        assert_equal(res1b, res2b)
1527
1528    def test_string_ticket_1892(self):
1529        # Test vectorization over strings: issue 1892.
1530        f = np.vectorize(lambda x: x)
1531        s = "0123456789" * 10
1532        assert_equal(s, f(s))
1533
1534    def test_cache(self):
1535        # Ensure that vectorized func called exactly once per argument.
1536        _calls = [0]
1537
1538        @vectorize
1539        def f(x):
1540            _calls[0] += 1
1541            return x**2
1542
1543        f.cache = True
1544        x = np.arange(5)
1545        assert_array_equal(f(x), x * x)
1546        assert_equal(_calls[0], len(x))
1547
1548    def test_otypes(self):
1549        f = np.vectorize(lambda x: x)
1550        f.otypes = "i"
1551        x = np.arange(5)
1552        assert_array_equal(f(x), x)
1553
1554    def test_signature_mean_last(self):
1555        def mean(a):
1556            return a.mean()
1557
1558        f = vectorize(mean, signature="(n)->()")
1559        r = f([[1, 3], [2, 4]])
1560        assert_array_equal(r, [2, 3])
1561
1562    def test_signature_center(self):
1563        def center(a):
1564            return a - a.mean()
1565
1566        f = vectorize(center, signature="(n)->(n)")
1567        r = f([[1, 3], [2, 4]])
1568        assert_array_equal(r, [[-1, 1], [-1, 1]])
1569
1570    def test_signature_two_outputs(self):
1571        f = vectorize(lambda x: (x, x), signature="()->(),()")
1572        r = f([1, 2, 3])
1573        assert_(isinstance(r, tuple) and len(r) == 2)
1574        assert_array_equal(r[0], [1, 2, 3])
1575        assert_array_equal(r[1], [1, 2, 3])
1576
1577    def test_signature_outer(self):
1578        f = vectorize(np.outer, signature="(a),(b)->(a,b)")
1579        r = f([1, 2], [1, 2, 3])
1580        assert_array_equal(r, [[1, 2, 3], [2, 4, 6]])
1581
1582        r = f([[[1, 2]]], [1, 2, 3])
1583        assert_array_equal(r, [[[[1, 2, 3], [2, 4, 6]]]])
1584
1585        r = f([[1, 0], [2, 0]], [1, 2, 3])
1586        assert_array_equal(r, [[[1, 2, 3], [0, 0, 0]], [[2, 4, 6], [0, 0, 0]]])
1587
1588        r = f([1, 2], [[1, 2, 3], [0, 0, 0]])
1589        assert_array_equal(r, [[[1, 2, 3], [2, 4, 6]], [[0, 0, 0], [0, 0, 0]]])
1590
1591    def test_signature_computed_size(self):
1592        f = vectorize(lambda x: x[:-1], signature="(n)->(m)")
1593        r = f([1, 2, 3])
1594        assert_array_equal(r, [1, 2])
1595
1596        r = f([[1, 2, 3], [2, 3, 4]])
1597        assert_array_equal(r, [[1, 2], [2, 3]])
1598
1599    def test_signature_excluded(self):
1600        def foo(a, b=1):
1601            return a + b
1602
1603        f = vectorize(foo, signature="()->()", excluded={"b"})
1604        assert_array_equal(f([1, 2, 3]), [2, 3, 4])
1605        assert_array_equal(f([1, 2, 3], b=0), [1, 2, 3])
1606
1607    def test_signature_otypes(self):
1608        f = vectorize(lambda x: x, signature="(n)->(n)", otypes=["float64"])
1609        r = f([1, 2, 3])
1610        assert_equal(r.dtype, np.dtype("float64"))
1611        assert_array_equal(r, [1, 2, 3])
1612
1613    def test_signature_invalid_inputs(self):
1614        f = vectorize(operator.add, signature="(n),(n)->(n)")
1615        with assert_raises_regex(TypeError, "wrong number of positional"):
1616            f([1, 2])
1617        with assert_raises_regex(ValueError, "does not have enough dimensions"):
1618            f(1, 2)
1619        with assert_raises_regex(ValueError, "inconsistent size for core dimension"):
1620            f([1, 2], [1, 2, 3])
1621
1622        f = vectorize(operator.add, signature="()->()")
1623        with assert_raises_regex(TypeError, "wrong number of positional"):
1624            f(1, 2)
1625
1626    def test_signature_invalid_outputs(self):
1627        f = vectorize(lambda x: x[:-1], signature="(n)->(n)")
1628        with assert_raises_regex(ValueError, "inconsistent size for core dimension"):
1629            f([1, 2, 3])
1630
1631        f = vectorize(lambda x: x, signature="()->(),()")
1632        with assert_raises_regex(ValueError, "wrong number of outputs"):
1633            f(1)
1634
1635        f = vectorize(lambda x: (x, x), signature="()->()")
1636        with assert_raises_regex(ValueError, "wrong number of outputs"):
1637            f([1, 2])
1638
1639    def test_size_zero_output(self):
1640        # see issue 5868
1641        f = np.vectorize(lambda x: x)
1642        x = np.zeros([0, 5], dtype=int)
1643        with assert_raises_regex(ValueError, "otypes"):
1644            f(x)
1645
1646        f.otypes = "i"
1647        assert_array_equal(f(x), x)
1648
1649        f = np.vectorize(lambda x: x, signature="()->()")
1650        with assert_raises_regex(ValueError, "otypes"):
1651            f(x)
1652
1653        f = np.vectorize(lambda x: x, signature="()->()", otypes="i")
1654        assert_array_equal(f(x), x)
1655
1656        f = np.vectorize(lambda x: x, signature="(n)->(n)", otypes="i")
1657        assert_array_equal(f(x), x)
1658
1659        f = np.vectorize(lambda x: x, signature="(n)->(n)")
1660        assert_array_equal(f(x.T), x.T)
1661
1662        f = np.vectorize(lambda x: [x], signature="()->(n)", otypes="i")
1663        with assert_raises_regex(ValueError, "new output dimensions"):
1664            f(x)
1665
1666
1667@xpassIfTorchDynamo  # (reason="TODO: implement")
1668class TestDigitize(TestCase):
1669    def test_forward(self):
1670        x = np.arange(-6, 5)
1671        bins = np.arange(-5, 5)
1672        assert_array_equal(digitize(x, bins), np.arange(11))
1673
1674    def test_reverse(self):
1675        x = np.arange(5, -6, -1)
1676        bins = np.arange(5, -5, -1)
1677        assert_array_equal(digitize(x, bins), np.arange(11))
1678
1679    def test_random(self):
1680        x = rand(10)
1681        bin = np.linspace(x.min(), x.max(), 10)
1682        assert_(np.all(digitize(x, bin) != 0))
1683
1684    def test_right_basic(self):
1685        x = [1, 5, 4, 10, 8, 11, 0]
1686        bins = [1, 5, 10]
1687        default_answer = [1, 2, 1, 3, 2, 3, 0]
1688        assert_array_equal(digitize(x, bins), default_answer)
1689        right_answer = [0, 1, 1, 2, 2, 3, 0]
1690        assert_array_equal(digitize(x, bins, True), right_answer)
1691
1692    def test_right_open(self):
1693        x = np.arange(-6, 5)
1694        bins = np.arange(-6, 4)
1695        assert_array_equal(digitize(x, bins, True), np.arange(11))
1696
1697    def test_right_open_reverse(self):
1698        x = np.arange(5, -6, -1)
1699        bins = np.arange(4, -6, -1)
1700        assert_array_equal(digitize(x, bins, True), np.arange(11))
1701
1702    def test_right_open_random(self):
1703        x = rand(10)
1704        bins = np.linspace(x.min(), x.max(), 10)
1705        assert_(np.all(digitize(x, bins, True) != 10))
1706
1707    def test_monotonic(self):
1708        x = [-1, 0, 1, 2]
1709        bins = [0, 0, 1]
1710        assert_array_equal(digitize(x, bins, False), [0, 2, 3, 3])
1711        assert_array_equal(digitize(x, bins, True), [0, 0, 2, 3])
1712        bins = [1, 1, 0]
1713        assert_array_equal(digitize(x, bins, False), [3, 2, 0, 0])
1714        assert_array_equal(digitize(x, bins, True), [3, 3, 2, 0])
1715        bins = [1, 1, 1, 1]
1716        assert_array_equal(digitize(x, bins, False), [0, 0, 4, 4])
1717        assert_array_equal(digitize(x, bins, True), [0, 0, 0, 4])
1718        bins = [0, 0, 1, 0]
1719        assert_raises(ValueError, digitize, x, bins)
1720        bins = [1, 1, 0, 1]
1721        assert_raises(ValueError, digitize, x, bins)
1722
1723    def test_casting_error(self):
1724        x = [1, 2, 3 + 1.0j]
1725        bins = [1, 2, 3]
1726        assert_raises(TypeError, digitize, x, bins)
1727        x, bins = bins, x
1728        assert_raises(TypeError, digitize, x, bins)
1729
1730    def test_large_integers_increasing(self):
1731        # gh-11022
1732        x = 2**54  # loses precision in a float
1733        assert_equal(np.digitize(x, [x - 1, x + 1]), 1)
1734
1735    @xfail  # "gh-11022: np.core.multiarray._monoticity loses precision"
1736    def test_large_integers_decreasing(self):
1737        # gh-11022
1738        x = 2**54  # loses precision in a float
1739        assert_equal(np.digitize(x, [x + 1, x - 1]), 1)
1740
1741
1742@skip  # (reason="TODO: implement; here unwrap if from numpy")
1743class TestUnwrap(TestCase):
1744    def test_simple(self):
1745        # check that unwrap removes jumps greater that 2*pi
1746        assert_array_equal(unwrap([1, 1 + 2 * np.pi]), [1, 1])
1747        # check that unwrap maintains continuity
1748        assert_(np.all(diff(unwrap(rand(10) * 100)) < np.pi))
1749
1750    def test_period(self):
1751        # check that unwrap removes jumps greater that 255
1752        assert_array_equal(unwrap([1, 1 + 256], period=255), [1, 2])
1753        # check that unwrap maintains continuity
1754        assert_(np.all(diff(unwrap(rand(10) * 1000, period=255)) < 255))
1755        # check simple case
1756        simple_seq = np.array([0, 75, 150, 225, 300])
1757        wrap_seq = np.mod(simple_seq, 255)
1758        assert_array_equal(unwrap(wrap_seq, period=255), simple_seq)
1759        # check custom discont value
1760        uneven_seq = np.array([0, 75, 150, 225, 300, 430])
1761        wrap_uneven = np.mod(uneven_seq, 250)
1762        no_discont = unwrap(wrap_uneven, period=250)
1763        assert_array_equal(no_discont, [0, 75, 150, 225, 300, 180])
1764        sm_discont = unwrap(wrap_uneven, period=250, discont=140)
1765        assert_array_equal(sm_discont, [0, 75, 150, 225, 300, 430])
1766        assert sm_discont.dtype == wrap_uneven.dtype
1767
1768
1769@instantiate_parametrized_tests
1770class TestFilterwindows(TestCase):
1771    @parametrize(
1772        "dtype", "Bbhil" + "efd"
1773    )  # np.typecodes["AllInteger"] + np.typecodes["Float"])
1774    @parametrize("M", [0, 1, 10])
1775    def test_hanning(self, dtype: str, M: int) -> None:
1776        scalar = M
1777
1778        w = hanning(scalar)
1779        ref_dtype = np.result_type(dtype, np.float64)
1780        assert w.dtype == ref_dtype
1781
1782        # check symmetry
1783        assert_allclose(w, flipud(w), atol=1e-15)
1784
1785        # check known value
1786        if scalar < 1:
1787            assert_array_equal(w, np.array([]))
1788        elif scalar == 1:
1789            assert_array_equal(w, np.ones(1))
1790        else:
1791            assert_almost_equal(np.sum(w, axis=0), 4.500, 4)
1792
1793    @parametrize(
1794        "dtype", "Bbhil" + "efd"
1795    )  # np.typecodes["AllInteger"] + np.typecodes["Float"])
1796    @parametrize("M", [0, 1, 10])
1797    def test_hamming(self, dtype: str, M: int) -> None:
1798        scalar = M
1799
1800        w = hamming(scalar)
1801        ref_dtype = np.result_type(dtype, np.float64)
1802        assert w.dtype == ref_dtype
1803
1804        # check symmetry
1805        assert_allclose(w, flipud(w), atol=1e-15)
1806
1807        # check known value
1808        if scalar < 1:
1809            assert_array_equal(w, np.array([]))
1810        elif scalar == 1:
1811            assert_array_equal(w, np.ones(1))
1812        else:
1813            assert_almost_equal(np.sum(w, axis=0), 4.9400, 4)
1814
1815    @parametrize(
1816        "dtype", "Bbhil" + "efd"
1817    )  # np.typecodes["AllInteger"] + np.typecodes["Float"])
1818    @parametrize("M", [0, 1, 10])
1819    def test_bartlett(self, dtype: str, M: int) -> None:
1820        scalar = M
1821
1822        w = bartlett(scalar)
1823        ref_dtype = np.result_type(dtype, np.float64)
1824        assert w.dtype == ref_dtype
1825
1826        # check symmetry
1827        assert_allclose(w, flipud(w), atol=1e-15)
1828
1829        # check known value
1830        if scalar < 1:
1831            assert_array_equal(w, np.array([]))
1832        elif scalar == 1:
1833            assert_array_equal(w, np.ones(1))
1834        else:
1835            assert_almost_equal(np.sum(w, axis=0), 4.4444, 4)
1836
1837    @parametrize(
1838        "dtype", "Bbhil" + "efd"
1839    )  # np.typecodes["AllInteger"] + np.typecodes["Float"])
1840    @parametrize("M", [0, 1, 10])
1841    def test_blackman(self, dtype: str, M: int) -> None:
1842        scalar = M
1843
1844        w = blackman(scalar)
1845        ref_dtype = np.result_type(dtype, np.float64)
1846        assert w.dtype == ref_dtype
1847
1848        # check symmetry
1849        assert_allclose(w, flipud(w), atol=1e-15)
1850
1851        # check known value
1852        if scalar < 1:
1853            assert_array_equal(w, np.array([]))
1854        elif scalar == 1:
1855            assert_array_equal(w, np.ones(1))
1856        else:
1857            assert_almost_equal(np.sum(w, axis=0), 3.7800, 4)
1858
1859    @parametrize(
1860        "dtype", "Bbhil" + "efd"
1861    )  # np.typecodes["AllInteger"] + np.typecodes["Float"])
1862    @parametrize("M", [0, 1, 10])
1863    def test_kaiser(self, dtype: str, M: int) -> None:
1864        scalar = M
1865
1866        w = kaiser(scalar, 0)
1867        ref_dtype = np.result_type(dtype, np.float64)
1868        assert w.dtype == ref_dtype
1869
1870        # check symmetry
1871        assert_equal(w, flipud(w))
1872
1873        # check known value
1874        if scalar < 1:
1875            assert_array_equal(w, np.array([]))
1876        elif scalar == 1:
1877            assert_array_equal(w, np.ones(1))
1878        else:
1879            assert_almost_equal(np.sum(w, axis=0), 10, 15)
1880
1881
1882@xpassIfTorchDynamo  # (reason="TODO: implement")
1883class TestTrapz(TestCase):
1884    def test_simple(self):
1885        x = np.arange(-10, 10, 0.1)
1886        r = trapz(np.exp(-0.5 * x**2) / np.sqrt(2 * np.pi), dx=0.1)
1887        # check integral of normal equals 1
1888        assert_almost_equal(r, 1, 7)
1889
1890    def test_ndim(self):
1891        x = np.linspace(0, 1, 3)
1892        y = np.linspace(0, 2, 8)
1893        z = np.linspace(0, 3, 13)
1894
1895        wx = np.ones_like(x) * (x[1] - x[0])
1896        wx[0] /= 2
1897        wx[-1] /= 2
1898        wy = np.ones_like(y) * (y[1] - y[0])
1899        wy[0] /= 2
1900        wy[-1] /= 2
1901        wz = np.ones_like(z) * (z[1] - z[0])
1902        wz[0] /= 2
1903        wz[-1] /= 2
1904
1905        q = x[:, None, None] + y[None, :, None] + z[None, None, :]
1906
1907        qx = (q * wx[:, None, None]).sum(axis=0)
1908        qy = (q * wy[None, :, None]).sum(axis=1)
1909        qz = (q * wz[None, None, :]).sum(axis=2)
1910
1911        # n-d `x`
1912        r = trapz(q, x=x[:, None, None], axis=0)
1913        assert_almost_equal(r, qx)
1914        r = trapz(q, x=y[None, :, None], axis=1)
1915        assert_almost_equal(r, qy)
1916        r = trapz(q, x=z[None, None, :], axis=2)
1917        assert_almost_equal(r, qz)
1918
1919        # 1-d `x`
1920        r = trapz(q, x=x, axis=0)
1921        assert_almost_equal(r, qx)
1922        r = trapz(q, x=y, axis=1)
1923        assert_almost_equal(r, qy)
1924        r = trapz(q, x=z, axis=2)
1925        assert_almost_equal(r, qz)
1926
1927
1928class TestSinc(TestCase):
1929    def test_simple(self):
1930        assert_(sinc(0) == 1)
1931        w = sinc(np.linspace(-1, 1, 100))
1932        # check symmetry
1933        assert_array_almost_equal(w, np.flipud(w), 7)
1934
1935    def test_array_like(self):
1936        x = [0, 0.5]
1937        y1 = sinc(np.array(x))
1938        y2 = sinc(list(x))
1939        y3 = sinc(tuple(x))
1940        assert_array_equal(y1, y2)
1941        assert_array_equal(y1, y3)
1942
1943
1944class TestUnique(TestCase):
1945    def test_simple(self):
1946        x = np.array([4, 3, 2, 1, 1, 2, 3, 4, 0])
1947        assert_(np.all(unique(x) == [0, 1, 2, 3, 4]))
1948
1949        assert_(unique(np.array([1, 1, 1, 1, 1])) == np.array([1]))
1950
1951    @xpassIfTorchDynamo  # (reason="unique not implemented for 'ComplexDouble'")
1952    def test_simple_complex(self):
1953        x = np.array([5 + 6j, 1 + 1j, 1 + 10j, 10, 5 + 6j])
1954        assert_(np.all(unique(x) == [1 + 1j, 1 + 10j, 5 + 6j, 10]))
1955
1956
1957@xpassIfTorchDynamo  # (reason="TODO: implement")
1958class TestCheckFinite(TestCase):
1959    def test_simple(self):
1960        a = [1, 2, 3]
1961        b = [1, 2, np.inf]
1962        c = [1, 2, np.nan]
1963        np.lib.asarray_chkfinite(a)
1964        assert_raises(ValueError, np.lib.asarray_chkfinite, b)
1965        assert_raises(ValueError, np.lib.asarray_chkfinite, c)
1966
1967    def test_dtype_order(self):
1968        # Regression test for missing dtype and order arguments
1969        a = [1, 2, 3]
1970        a = np.lib.asarray_chkfinite(a, order="F", dtype=np.float64)
1971        assert_(a.dtype == np.float64)
1972
1973
1974@instantiate_parametrized_tests
1975class TestCorrCoef(TestCase):
1976    A = np.array(
1977        [
1978            [0.15391142, 0.18045767, 0.14197213],
1979            [0.70461506, 0.96474128, 0.27906989],
1980            [0.9297531, 0.32296769, 0.19267156],
1981        ]
1982    )
1983    B = np.array(
1984        [
1985            [0.10377691, 0.5417086, 0.49807457],
1986            [0.82872117, 0.77801674, 0.39226705],
1987            [0.9314666, 0.66800209, 0.03538394],
1988        ]
1989    )
1990    res1 = np.array(
1991        [
1992            [1.0, 0.9379533, -0.04931983],
1993            [0.9379533, 1.0, 0.30007991],
1994            [-0.04931983, 0.30007991, 1.0],
1995        ]
1996    )
1997    res2 = np.array(
1998        [
1999            [1.0, 0.9379533, -0.04931983, 0.30151751, 0.66318558, 0.51532523],
2000            [0.9379533, 1.0, 0.30007991, -0.04781421, 0.88157256, 0.78052386],
2001            [-0.04931983, 0.30007991, 1.0, -0.96717111, 0.71483595, 0.83053601],
2002            [0.30151751, -0.04781421, -0.96717111, 1.0, -0.51366032, -0.66173113],
2003            [0.66318558, 0.88157256, 0.71483595, -0.51366032, 1.0, 0.98317823],
2004            [0.51532523, 0.78052386, 0.83053601, -0.66173113, 0.98317823, 1.0],
2005        ]
2006    )
2007
2008    def test_non_array(self):
2009        assert_almost_equal(
2010            np.corrcoef([0, 1, 0], [1, 0, 1]), [[1.0, -1.0], [-1.0, 1.0]]
2011        )
2012
2013    def test_simple(self):
2014        tgt1 = corrcoef(self.A)
2015        assert_almost_equal(tgt1, self.res1)
2016        assert_(np.all(np.abs(tgt1) <= 1.0))
2017
2018        tgt2 = corrcoef(self.A, self.B)
2019        assert_almost_equal(tgt2, self.res2)
2020        assert_(np.all(np.abs(tgt2) <= 1.0))
2021
2022    @skip(reason="deprecated in numpy, ignore")
2023    def test_ddof(self):
2024        # ddof raises DeprecationWarning
2025        with suppress_warnings() as sup:
2026            warnings.simplefilter("always")
2027            assert_warns(DeprecationWarning, corrcoef, self.A, ddof=-1)
2028            sup.filter(DeprecationWarning)
2029            # ddof has no or negligible effect on the function
2030            assert_almost_equal(corrcoef(self.A, ddof=-1), self.res1)
2031            assert_almost_equal(corrcoef(self.A, self.B, ddof=-1), self.res2)
2032            assert_almost_equal(corrcoef(self.A, ddof=3), self.res1)
2033            assert_almost_equal(corrcoef(self.A, self.B, ddof=3), self.res2)
2034
2035    @skip(reason="deprecated in numpy, ignore")
2036    def test_bias(self):
2037        # bias raises DeprecationWarning
2038        with suppress_warnings() as sup:
2039            warnings.simplefilter("always")
2040            assert_warns(DeprecationWarning, corrcoef, self.A, self.B, 1, 0)
2041            assert_warns(DeprecationWarning, corrcoef, self.A, bias=0)
2042            sup.filter(DeprecationWarning)
2043            # bias has no or negligible effect on the function
2044            assert_almost_equal(corrcoef(self.A, bias=1), self.res1)
2045
2046    def test_complex(self):
2047        x = np.array([[1, 2, 3], [1j, 2j, 3j]])
2048        res = corrcoef(x)
2049        tgt = np.array([[1.0, -1.0j], [1.0j, 1.0]])
2050        assert_allclose(res, tgt)
2051        assert_(np.all(np.abs(res) <= 1.0))
2052
2053    def test_xy(self):
2054        x = np.array([[1, 2, 3]])
2055        y = np.array([[1j, 2j, 3j]])
2056        assert_allclose(np.corrcoef(x, y), np.array([[1.0, -1.0j], [1.0j, 1.0]]))
2057
2058    def test_empty(self):
2059        with warnings.catch_warnings(record=True):
2060            warnings.simplefilter("always", RuntimeWarning)
2061            assert_array_equal(corrcoef(np.array([])), np.nan)
2062            assert_array_equal(
2063                corrcoef(np.array([]).reshape(0, 2)), np.array([]).reshape(0, 0)
2064            )
2065            assert_array_equal(
2066                corrcoef(np.array([]).reshape(2, 0)),
2067                np.array([[np.nan, np.nan], [np.nan, np.nan]]),
2068            )
2069
2070    def test_extreme(self):
2071        x = [[1e-100, 1e100], [1e100, 1e-100]]
2072        c = corrcoef(x)
2073        assert_array_almost_equal(c, np.array([[1.0, -1.0], [-1.0, 1.0]]))
2074        assert_(np.all(np.abs(c) <= 1.0))
2075
2076    @parametrize("test_type", [np.half, np.single, np.double])
2077    def test_corrcoef_dtype(self, test_type):
2078        cast_A = self.A.astype(test_type)
2079        res = corrcoef(cast_A, dtype=test_type)
2080        assert test_type == res.dtype
2081
2082
2083@instantiate_parametrized_tests
2084class TestCov(TestCase):
2085    x1 = np.array([[0, 2], [1, 1], [2, 0]]).T
2086    res1 = np.array([[1.0, -1.0], [-1.0, 1.0]])
2087    x2 = np.array([0.0, 1.0, 2.0], ndmin=2)
2088    frequencies = np.array([1, 4, 1])
2089    x2_repeats = np.array([[0.0], [1.0], [1.0], [1.0], [1.0], [2.0]]).T
2090    res2 = np.array([[0.4, -0.4], [-0.4, 0.4]])
2091    unit_frequencies = np.ones(3, dtype=np.int_)
2092    weights = np.array([1.0, 4.0, 1.0])
2093    res3 = np.array([[2.0 / 3.0, -2.0 / 3.0], [-2.0 / 3.0, 2.0 / 3.0]])
2094    unit_weights = np.ones(3)
2095    x3 = np.array([0.3942, 0.5969, 0.7730, 0.9918, 0.7964])
2096
2097    def test_basic(self):
2098        assert_allclose(cov(self.x1), self.res1)
2099
2100    def test_complex(self):
2101        x = np.array([[1, 2, 3], [1j, 2j, 3j]])
2102        res = np.array([[1.0, -1.0j], [1.0j, 1.0]])
2103        assert_allclose(cov(x), res)
2104        assert_allclose(cov(x, aweights=np.ones(3)), res)
2105
2106    def test_xy(self):
2107        x = np.array([[1, 2, 3]])
2108        y = np.array([[1j, 2j, 3j]])
2109        assert_allclose(cov(x, y), np.array([[1.0, -1.0j], [1.0j, 1.0]]))
2110
2111    def test_empty(self):
2112        with warnings.catch_warnings(record=True):
2113            warnings.simplefilter("always", RuntimeWarning)
2114            assert_array_equal(cov(np.array([])), np.nan)
2115            assert_array_equal(
2116                cov(np.array([]).reshape(0, 2)), np.array([]).reshape(0, 0)
2117            )
2118            assert_array_equal(
2119                cov(np.array([]).reshape(2, 0)),
2120                np.array([[np.nan, np.nan], [np.nan, np.nan]]),
2121            )
2122
2123    def test_wrong_ddof(self):
2124        with warnings.catch_warnings(record=True):
2125            warnings.simplefilter("always", RuntimeWarning)
2126            assert_array_equal(
2127                cov(self.x1, ddof=5), np.array([[np.inf, -np.inf], [-np.inf, np.inf]])
2128            )
2129
2130    def test_1D_rowvar(self):
2131        assert_allclose(cov(self.x3), cov(self.x3, rowvar=False))
2132        y = np.array([0.0780, 0.3107, 0.2111, 0.0334, 0.8501])
2133        assert_allclose(cov(self.x3, y), cov(self.x3, y, rowvar=False))
2134
2135    def test_1D_variance(self):
2136        assert_allclose(cov(self.x3, ddof=1), np.var(self.x3, ddof=1))
2137
2138    def test_fweights(self):
2139        assert_allclose(cov(self.x2, fweights=self.frequencies), cov(self.x2_repeats))
2140        assert_allclose(cov(self.x1, fweights=self.frequencies), self.res2)
2141        assert_allclose(cov(self.x1, fweights=self.unit_frequencies), self.res1)
2142        nonint = self.frequencies + 0.5
2143        assert_raises((TypeError, RuntimeError), cov, self.x1, fweights=nonint)
2144        f = np.ones((2, 3), dtype=np.int_)
2145        assert_raises(RuntimeError, cov, self.x1, fweights=f)
2146        f = np.ones(2, dtype=np.int_)
2147        assert_raises(RuntimeError, cov, self.x1, fweights=f)
2148        f = -1 * np.ones(3, dtype=np.int_)
2149        assert_raises((ValueError, RuntimeError), cov, self.x1, fweights=f)
2150
2151    def test_aweights(self):
2152        assert_allclose(cov(self.x1, aweights=self.weights), self.res3)
2153        assert_allclose(
2154            cov(self.x1, aweights=3.0 * self.weights),
2155            cov(self.x1, aweights=self.weights),
2156        )
2157        assert_allclose(cov(self.x1, aweights=self.unit_weights), self.res1)
2158        w = np.ones((2, 3))
2159        assert_raises(RuntimeError, cov, self.x1, aweights=w)
2160        w = np.ones(2)
2161        assert_raises(RuntimeError, cov, self.x1, aweights=w)
2162        w = -1.0 * np.ones(3)
2163        assert_raises((ValueError, RuntimeError), cov, self.x1, aweights=w)
2164
2165    def test_unit_fweights_and_aweights(self):
2166        assert_allclose(
2167            cov(self.x2, fweights=self.frequencies, aweights=self.unit_weights),
2168            cov(self.x2_repeats),
2169        )
2170        assert_allclose(
2171            cov(self.x1, fweights=self.frequencies, aweights=self.unit_weights),
2172            self.res2,
2173        )
2174        assert_allclose(
2175            cov(self.x1, fweights=self.unit_frequencies, aweights=self.unit_weights),
2176            self.res1,
2177        )
2178        assert_allclose(
2179            cov(self.x1, fweights=self.unit_frequencies, aweights=self.weights),
2180            self.res3,
2181        )
2182        assert_allclose(
2183            cov(self.x1, fweights=self.unit_frequencies, aweights=3.0 * self.weights),
2184            cov(self.x1, aweights=self.weights),
2185        )
2186        assert_allclose(
2187            cov(self.x1, fweights=self.unit_frequencies, aweights=self.unit_weights),
2188            self.res1,
2189        )
2190
2191    @parametrize("test_type", [np.half, np.single, np.double])
2192    def test_cov_dtype(self, test_type):
2193        cast_x1 = self.x1.astype(test_type)
2194        res = cov(cast_x1, dtype=test_type)
2195        assert test_type == res.dtype
2196
2197
2198class Test_I0(TestCase):
2199    def test_simple(self):
2200        assert_almost_equal(i0(0.5), np.array(1.0634833707413234))
2201
2202        # need at least one test above 8, as the implementation is piecewise
2203        A = np.array([0.49842636, 0.6969809, 0.22011976, 0.0155549, 10.0])
2204        expected = np.array(
2205            [1.06307822, 1.12518299, 1.01214991, 1.00006049, 2815.71662847]
2206        )
2207        assert_almost_equal(i0(A), expected)
2208        assert_almost_equal(i0(-A), expected)
2209
2210        B = np.array(
2211            [
2212                [0.827002, 0.99959078],
2213                [0.89694769, 0.39298162],
2214                [0.37954418, 0.05206293],
2215                [0.36465447, 0.72446427],
2216                [0.48164949, 0.50324519],
2217            ]
2218        )
2219        assert_almost_equal(
2220            i0(B),
2221            np.array(
2222                [
2223                    [1.17843223, 1.26583466],
2224                    [1.21147086, 1.03898290],
2225                    [1.03633899, 1.00067775],
2226                    [1.03352052, 1.13557954],
2227                    [1.05884290, 1.06432317],
2228                ]
2229            ),
2230        )
2231        # Regression test for gh-11205
2232        i0_0 = np.i0([0.0])
2233        assert_equal(i0_0.shape, (1,))
2234        assert_array_equal(np.i0([0.0]), np.array([1.0]))
2235
2236    def test_complex(self):
2237        a = np.array([0, 1 + 2j])
2238        with pytest.raises(
2239            (TypeError, RuntimeError),
2240            # match="i0 not supported for complex values"
2241        ):
2242            res = i0(a)
2243
2244
2245class TestKaiser(TestCase):
2246    def test_simple(self):
2247        assert_(np.isfinite(kaiser(1, 1.0)))
2248        assert_almost_equal(kaiser(0, 1.0), np.array([]))
2249        assert_almost_equal(kaiser(2, 1.0), np.array([0.78984831, 0.78984831]))
2250        assert_almost_equal(
2251            kaiser(5, 1.0),
2252            np.array([0.78984831, 0.94503323, 1.0, 0.94503323, 0.78984831]),
2253        )
2254        assert_almost_equal(
2255            kaiser(5, 1.56789),
2256            np.array([0.58285404, 0.88409679, 1.0, 0.88409679, 0.58285404]),
2257        )
2258
2259    def test_int_beta(self):
2260        kaiser(3, 4)
2261
2262
2263@skip(reason="msort is deprecated, do not bother")
2264class TestMsort(TestCase):
2265    def test_simple(self):
2266        A = np.array(
2267            [
2268                [0.44567325, 0.79115165, 0.54900530],
2269                [0.36844147, 0.37325583, 0.96098397],
2270                [0.64864341, 0.52929049, 0.39172155],
2271            ]
2272        )
2273        with pytest.warns(DeprecationWarning, match="msort is deprecated"):
2274            assert_almost_equal(
2275                msort(A),
2276                np.array(
2277                    [
2278                        [0.36844147, 0.37325583, 0.39172155],
2279                        [0.44567325, 0.52929049, 0.54900530],
2280                        [0.64864341, 0.79115165, 0.96098397],
2281                    ]
2282                ),
2283            )
2284
2285
2286class TestMeshgrid(TestCase):
2287    def test_simple(self):
2288        [X, Y] = meshgrid([1, 2, 3], [4, 5, 6, 7])
2289        assert_array_equal(X, np.array([[1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3]]))
2290        assert_array_equal(Y, np.array([[4, 4, 4], [5, 5, 5], [6, 6, 6], [7, 7, 7]]))
2291
2292    def test_single_input(self):
2293        [X] = meshgrid([1, 2, 3, 4])
2294        assert_array_equal(X, np.array([1, 2, 3, 4]))
2295
2296    def test_no_input(self):
2297        args = []
2298        assert_array_equal([], meshgrid(*args))
2299        assert_array_equal([], meshgrid(*args, copy=False))
2300
2301    def test_indexing(self):
2302        x = [1, 2, 3]
2303        y = [4, 5, 6, 7]
2304        [X, Y] = meshgrid(x, y, indexing="ij")
2305        assert_array_equal(X, np.array([[1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3]]))
2306        assert_array_equal(Y, np.array([[4, 5, 6, 7], [4, 5, 6, 7], [4, 5, 6, 7]]))
2307
2308        # Test expected shapes:
2309        z = [8, 9]
2310        assert_(meshgrid(x, y)[0].shape == (4, 3))
2311        assert_(meshgrid(x, y, indexing="ij")[0].shape == (3, 4))
2312        assert_(meshgrid(x, y, z)[0].shape == (4, 3, 2))
2313        assert_(meshgrid(x, y, z, indexing="ij")[0].shape == (3, 4, 2))
2314
2315        assert_raises(ValueError, meshgrid, x, y, indexing="notvalid")
2316
2317    def test_sparse(self):
2318        [X, Y] = meshgrid([1, 2, 3], [4, 5, 6, 7], sparse=True)
2319        assert_array_equal(X, np.array([[1, 2, 3]]))
2320        assert_array_equal(Y, np.array([[4], [5], [6], [7]]))
2321
2322    def test_invalid_arguments(self):
2323        # Test that meshgrid complains about invalid arguments
2324        # Regression test for issue #4755:
2325        # https://github.com/numpy/numpy/issues/4755
2326        assert_raises(TypeError, meshgrid, [1, 2, 3], [4, 5, 6, 7], indices="ij")
2327
2328    def test_return_type(self):
2329        # Test for appropriate dtype in returned arrays.
2330        # Regression test for issue #5297
2331        # https://github.com/numpy/numpy/issues/5297
2332        x = np.arange(0, 10, dtype=np.float32)
2333        y = np.arange(10, 20, dtype=np.float64)
2334
2335        X, Y = np.meshgrid(x, y)
2336
2337        assert_(X.dtype == x.dtype)
2338        assert_(Y.dtype == y.dtype)
2339
2340        # copy
2341        X, Y = np.meshgrid(x, y, copy=True)
2342
2343        assert_(X.dtype == x.dtype)
2344        assert_(Y.dtype == y.dtype)
2345
2346        # sparse
2347        X, Y = np.meshgrid(x, y, sparse=True)
2348
2349        assert_(X.dtype == x.dtype)
2350        assert_(Y.dtype == y.dtype)
2351
2352    def test_writeback(self):
2353        # Issue 8561
2354        X = np.array([1.1, 2.2])
2355        Y = np.array([3.3, 4.4])
2356        x, y = np.meshgrid(X, Y, sparse=False, copy=True)
2357
2358        x[0, :] = 0
2359        assert_equal(x[0, :], 0)
2360        assert_equal(x[1, :], X)
2361
2362    def test_nd_shape(self):
2363        a, b, c, d, e = np.meshgrid(*([0] * i for i in range(1, 6)))
2364        expected_shape = (2, 1, 3, 4, 5)
2365        assert_equal(a.shape, expected_shape)
2366        assert_equal(b.shape, expected_shape)
2367        assert_equal(c.shape, expected_shape)
2368        assert_equal(d.shape, expected_shape)
2369        assert_equal(e.shape, expected_shape)
2370
2371    def test_nd_values(self):
2372        a, b, c = np.meshgrid([0], [1, 2], [3, 4, 5])
2373        assert_equal(a, [[[0, 0, 0]], [[0, 0, 0]]])
2374        assert_equal(b, [[[1, 1, 1]], [[2, 2, 2]]])
2375        assert_equal(c, [[[3, 4, 5]], [[3, 4, 5]]])
2376
2377    def test_nd_indexing(self):
2378        a, b, c = np.meshgrid([0], [1, 2], [3, 4, 5], indexing="ij")
2379        assert_equal(a, [[[0, 0, 0], [0, 0, 0]]])
2380        assert_equal(b, [[[1, 1, 1], [2, 2, 2]]])
2381        assert_equal(c, [[[3, 4, 5], [3, 4, 5]]])
2382
2383
2384@xfail  # (reason="TODO: implement")
2385class TestPiecewise(TestCase):
2386    def test_simple(self):
2387        # Condition is single bool list
2388        x = piecewise([0, 0], [True, False], [1])
2389        assert_array_equal(x, [1, 0])
2390
2391        # List of conditions: single bool list
2392        x = piecewise([0, 0], [[True, False]], [1])
2393        assert_array_equal(x, [1, 0])
2394
2395        # Conditions is single bool array
2396        x = piecewise([0, 0], np.array([True, False]), [1])
2397        assert_array_equal(x, [1, 0])
2398
2399        # Condition is single int array
2400        x = piecewise([0, 0], np.array([1, 0]), [1])
2401        assert_array_equal(x, [1, 0])
2402
2403        # List of conditions: int array
2404        x = piecewise([0, 0], [np.array([1, 0])], [1])
2405        assert_array_equal(x, [1, 0])
2406
2407        x = piecewise([0, 0], [[False, True]], [lambda x: -1])
2408        assert_array_equal(x, [0, -1])
2409
2410        assert_raises_regex(
2411            ValueError,
2412            "1 or 2 functions are expected",
2413            piecewise,
2414            [0, 0],
2415            [[False, True]],
2416            [],
2417        )
2418        assert_raises_regex(
2419            ValueError,
2420            "1 or 2 functions are expected",
2421            piecewise,
2422            [0, 0],
2423            [[False, True]],
2424            [1, 2, 3],
2425        )
2426
2427    def test_two_conditions(self):
2428        x = piecewise([1, 2], [[True, False], [False, True]], [3, 4])
2429        assert_array_equal(x, [3, 4])
2430
2431    def test_scalar_domains_three_conditions(self):
2432        x = piecewise(3, [True, False, False], [4, 2, 0])
2433        assert_equal(x, 4)
2434
2435    def test_default(self):
2436        # No value specified for x[1], should be 0
2437        x = piecewise([1, 2], [True, False], [2])
2438        assert_array_equal(x, [2, 0])
2439
2440        # Should set x[1] to 3
2441        x = piecewise([1, 2], [True, False], [2, 3])
2442        assert_array_equal(x, [2, 3])
2443
2444    def test_0d(self):
2445        x = np.array(3)
2446        y = piecewise(x, x > 3, [4, 0])
2447        assert_(y.ndim == 0)
2448        assert_(y == 0)
2449
2450        x = 5
2451        y = piecewise(x, [True, False], [1, 0])
2452        assert_(y.ndim == 0)
2453        assert_(y == 1)
2454
2455        # With 3 ranges (It was failing, before)
2456        y = piecewise(x, [False, False, True], [1, 2, 3])
2457        assert_array_equal(y, 3)
2458
2459    def test_0d_comparison(self):
2460        x = 3
2461        y = piecewise(x, [x <= 3, x > 3], [4, 0])  # Should succeed.
2462        assert_equal(y, 4)
2463
2464        # With 3 ranges (It was failing, before)
2465        x = 4
2466        y = piecewise(x, [x <= 3, (x > 3) * (x <= 5), x > 5], [1, 2, 3])
2467        assert_array_equal(y, 2)
2468
2469        assert_raises_regex(
2470            ValueError,
2471            "2 or 3 functions are expected",
2472            piecewise,
2473            x,
2474            [x <= 3, x > 3],
2475            [1],
2476        )
2477        assert_raises_regex(
2478            ValueError,
2479            "2 or 3 functions are expected",
2480            piecewise,
2481            x,
2482            [x <= 3, x > 3],
2483            [1, 1, 1, 1],
2484        )
2485
2486    def test_0d_0d_condition(self):
2487        x = np.array(3)
2488        c = np.array(x > 3)
2489        y = piecewise(x, [c], [1, 2])
2490        assert_equal(y, 2)
2491
2492    def test_multidimensional_extrafunc(self):
2493        x = np.array([[-2.5, -1.5, -0.5], [0.5, 1.5, 2.5]])
2494        y = piecewise(x, [x < 0, x >= 2], [-1, 1, 3])
2495        assert_array_equal(y, np.array([[-1.0, -1.0, -1.0], [3.0, 3.0, 1.0]]))
2496
2497
2498@instantiate_parametrized_tests
2499class TestBincount(TestCase):
2500    def test_simple(self):
2501        y = np.bincount(np.arange(4))
2502        assert_array_equal(y, np.ones(4))
2503
2504    def test_simple2(self):
2505        y = np.bincount(np.array([1, 5, 2, 4, 1]))
2506        assert_array_equal(y, np.array([0, 2, 1, 0, 1, 1]))
2507
2508    def test_simple_weight(self):
2509        x = np.arange(4)
2510        w = np.array([0.2, 0.3, 0.5, 0.1])
2511        y = np.bincount(x, w)
2512        assert_array_equal(y, w)
2513
2514    def test_simple_weight2(self):
2515        x = np.array([1, 2, 4, 5, 2])
2516        w = np.array([0.2, 0.3, 0.5, 0.1, 0.2])
2517        y = np.bincount(x, w)
2518        assert_array_equal(y, np.array([0, 0.2, 0.5, 0, 0.5, 0.1]))
2519
2520    def test_with_minlength(self):
2521        x = np.array([0, 1, 0, 1, 1])
2522        y = np.bincount(x, minlength=3)
2523        assert_array_equal(y, np.array([2, 3, 0]))
2524        x = []
2525        y = np.bincount(x, minlength=0)
2526        assert_array_equal(y, np.array([]))
2527
2528    def test_with_minlength_smaller_than_maxvalue(self):
2529        x = np.array([0, 1, 1, 2, 2, 3, 3])
2530        y = np.bincount(x, minlength=2)
2531        assert_array_equal(y, np.array([1, 2, 2, 2]))
2532        y = np.bincount(x, minlength=0)
2533        assert_array_equal(y, np.array([1, 2, 2, 2]))
2534
2535    def test_with_minlength_and_weights(self):
2536        x = np.array([1, 2, 4, 5, 2])
2537        w = np.array([0.2, 0.3, 0.5, 0.1, 0.2])
2538        y = np.bincount(x, w, 8)
2539        assert_array_equal(y, np.array([0, 0.2, 0.5, 0, 0.5, 0.1, 0, 0]))
2540
2541    def test_empty(self):
2542        x = np.array([], dtype=int)
2543        y = np.bincount(x)
2544        assert_array_equal(x, y)
2545
2546    def test_empty_with_minlength(self):
2547        x = np.array([], dtype=int)
2548        y = np.bincount(x, minlength=5)
2549        assert_array_equal(y, np.zeros(5, dtype=int))
2550
2551    def test_with_incorrect_minlength(self):
2552        x = np.array([], dtype=int)
2553        assert_raises(
2554            TypeError,
2555            #       "'str' object cannot be interpreted",
2556            lambda: np.bincount(x, minlength="foobar"),
2557        )
2558        assert_raises(
2559            (ValueError, RuntimeError),
2560            #       "must not be negative",
2561            lambda: np.bincount(x, minlength=-1),
2562        )
2563
2564        x = np.arange(5)
2565        assert_raises(
2566            TypeError,
2567            #       "'str' object cannot be interpreted",
2568            lambda: np.bincount(x, minlength="foobar"),
2569        )
2570        assert_raises(
2571            (ValueError, RuntimeError),
2572            #      "must not be negative",
2573            lambda: np.bincount(x, minlength=-1),
2574        )
2575
2576    @skipIfTorchDynamo()  # flaky test
2577    @skipif(not HAS_REFCOUNT, reason="Python lacks refcounts")
2578    def test_dtype_reference_leaks(self):
2579        # gh-6805
2580        intp_refcount = sys.getrefcount(np.dtype(np.intp))
2581        double_refcount = sys.getrefcount(np.dtype(np.double))
2582
2583        for j in range(10):
2584            np.bincount([1, 2, 3])
2585        assert_equal(sys.getrefcount(np.dtype(np.intp)), intp_refcount)
2586        assert_equal(sys.getrefcount(np.dtype(np.double)), double_refcount)
2587
2588        for j in range(10):
2589            np.bincount([1, 2, 3], [4, 5, 6])
2590        assert_equal(sys.getrefcount(np.dtype(np.intp)), intp_refcount)
2591        assert_equal(sys.getrefcount(np.dtype(np.double)), double_refcount)
2592
2593    @parametrize("vals", [[[2, 2]], 2])
2594    def test_error_not_1d(self, vals):
2595        # Test that values has to be 1-D (both as array and nested list)
2596        vals_arr = np.asarray(vals)
2597        with assert_raises((ValueError, RuntimeError)):
2598            np.bincount(vals_arr)
2599        with assert_raises((ValueError, RuntimeError)):
2600            np.bincount(vals)
2601
2602
2603parametrize_interp_sc = parametrize(
2604    "sc",
2605    [
2606        subtest(lambda x: np.float64(x), name="real"),
2607        subtest(lambda x: _make_complex(x, 0), name="complex-real"),
2608        subtest(lambda x: _make_complex(0, x), name="complex-imag"),
2609        subtest(lambda x: _make_complex(x, np.multiply(x, -2)), name="complex-both"),
2610    ],
2611)
2612
2613
2614@xpassIfTorchDynamo  # (reason="TODO: implement")
2615@instantiate_parametrized_tests
2616class TestInterp(TestCase):
2617    def test_exceptions(self):
2618        assert_raises(ValueError, interp, 0, [], [])
2619        assert_raises(ValueError, interp, 0, [0], [1, 2])
2620        assert_raises(ValueError, interp, 0, [0, 1], [1, 2], period=0)
2621        assert_raises(ValueError, interp, 0, [], [], period=360)
2622        assert_raises(ValueError, interp, 0, [0], [1, 2], period=360)
2623
2624    def test_basic(self):
2625        x = np.linspace(0, 1, 5)
2626        y = np.linspace(0, 1, 5)
2627        x0 = np.linspace(0, 1, 50)
2628        assert_almost_equal(np.interp(x0, x, y), x0)
2629
2630    def test_right_left_behavior(self):
2631        # Needs range of sizes to test different code paths.
2632        # size ==1 is special cased, 1 < size < 5 is linear search, and
2633        # size >= 5 goes through local search and possibly binary search.
2634        for size in range(1, 10):
2635            xp = np.arange(size, dtype=np.double)
2636            yp = np.ones(size, dtype=np.double)
2637            incpts = np.array([-1, 0, size - 1, size], dtype=np.double)
2638            decpts = incpts[::-1]
2639
2640            incres = interp(incpts, xp, yp)
2641            decres = interp(decpts, xp, yp)
2642            inctgt = np.array([1, 1, 1, 1], dtype=float)
2643            dectgt = inctgt[::-1]
2644            assert_equal(incres, inctgt)
2645            assert_equal(decres, dectgt)
2646
2647            incres = interp(incpts, xp, yp, left=0)
2648            decres = interp(decpts, xp, yp, left=0)
2649            inctgt = np.array([0, 1, 1, 1], dtype=float)
2650            dectgt = inctgt[::-1]
2651            assert_equal(incres, inctgt)
2652            assert_equal(decres, dectgt)
2653
2654            incres = interp(incpts, xp, yp, right=2)
2655            decres = interp(decpts, xp, yp, right=2)
2656            inctgt = np.array([1, 1, 1, 2], dtype=float)
2657            dectgt = inctgt[::-1]
2658            assert_equal(incres, inctgt)
2659            assert_equal(decres, dectgt)
2660
2661            incres = interp(incpts, xp, yp, left=0, right=2)
2662            decres = interp(decpts, xp, yp, left=0, right=2)
2663            inctgt = np.array([0, 1, 1, 2], dtype=float)
2664            dectgt = inctgt[::-1]
2665            assert_equal(incres, inctgt)
2666            assert_equal(decres, dectgt)
2667
2668    def test_scalar_interpolation_point(self):
2669        x = np.linspace(0, 1, 5)
2670        y = np.linspace(0, 1, 5)
2671        x0 = 0
2672        assert_almost_equal(np.interp(x0, x, y), x0)
2673        x0 = 0.3
2674        assert_almost_equal(np.interp(x0, x, y), x0)
2675        x0 = np.float32(0.3)
2676        assert_almost_equal(np.interp(x0, x, y), x0)
2677        x0 = np.float64(0.3)
2678        assert_almost_equal(np.interp(x0, x, y), x0)
2679        x0 = np.nan
2680        assert_almost_equal(np.interp(x0, x, y), x0)
2681
2682    def test_non_finite_behavior_exact_x(self):
2683        x = [1, 2, 2.5, 3, 4]
2684        xp = [1, 2, 3, 4]
2685        fp = [1, 2, np.inf, 4]
2686        assert_almost_equal(np.interp(x, xp, fp), [1, 2, np.inf, np.inf, 4])
2687        fp = [1, 2, np.nan, 4]
2688        assert_almost_equal(np.interp(x, xp, fp), [1, 2, np.nan, np.nan, 4])
2689
2690    @parametrize_interp_sc
2691    def test_non_finite_any_nan(self, sc):
2692        """test that nans are propagated"""
2693        assert_equal(np.interp(0.5, [np.nan, 1], sc([0, 10])), sc(np.nan))
2694        assert_equal(np.interp(0.5, [0, np.nan], sc([0, 10])), sc(np.nan))
2695        assert_equal(np.interp(0.5, [0, 1], sc([np.nan, 10])), sc(np.nan))
2696        assert_equal(np.interp(0.5, [0, 1], sc([0, np.nan])), sc(np.nan))
2697
2698    @parametrize_interp_sc
2699    def test_non_finite_inf(self, sc):
2700        """Test that interp between opposite infs gives nan"""
2701        assert_equal(np.interp(0.5, [-np.inf, +np.inf], sc([0, 10])), sc(np.nan))
2702        assert_equal(np.interp(0.5, [0, 1], sc([-np.inf, +np.inf])), sc(np.nan))
2703        assert_equal(np.interp(0.5, [0, 1], sc([+np.inf, -np.inf])), sc(np.nan))
2704
2705        # unless the y values are equal
2706        assert_equal(np.interp(0.5, [-np.inf, +np.inf], sc([10, 10])), sc(10))
2707
2708    @parametrize_interp_sc
2709    def test_non_finite_half_inf_xf(self, sc):
2710        """Test that interp where both axes have a bound at inf gives nan"""
2711        assert_equal(np.interp(0.5, [-np.inf, 1], sc([-np.inf, 10])), sc(np.nan))
2712        assert_equal(np.interp(0.5, [-np.inf, 1], sc([+np.inf, 10])), sc(np.nan))
2713        assert_equal(np.interp(0.5, [-np.inf, 1], sc([0, -np.inf])), sc(np.nan))
2714        assert_equal(np.interp(0.5, [-np.inf, 1], sc([0, +np.inf])), sc(np.nan))
2715        assert_equal(np.interp(0.5, [0, +np.inf], sc([-np.inf, 10])), sc(np.nan))
2716        assert_equal(np.interp(0.5, [0, +np.inf], sc([+np.inf, 10])), sc(np.nan))
2717        assert_equal(np.interp(0.5, [0, +np.inf], sc([0, -np.inf])), sc(np.nan))
2718        assert_equal(np.interp(0.5, [0, +np.inf], sc([0, +np.inf])), sc(np.nan))
2719
2720    @parametrize_interp_sc
2721    def test_non_finite_half_inf_x(self, sc):
2722        """Test interp where the x axis has a bound at inf"""
2723        assert_equal(np.interp(0.5, [-np.inf, -np.inf], sc([0, 10])), sc(10))
2724        assert_equal(np.interp(0.5, [-np.inf, 1], sc([0, 10])), sc(10))
2725        assert_equal(np.interp(0.5, [0, +np.inf], sc([0, 10])), sc(0))
2726        assert_equal(np.interp(0.5, [+np.inf, +np.inf], sc([0, 10])), sc(0))
2727
2728    @parametrize_interp_sc
2729    def test_non_finite_half_inf_f(self, sc):
2730        """Test interp where the f axis has a bound at inf"""
2731        assert_equal(np.interp(0.5, [0, 1], sc([0, -np.inf])), sc(-np.inf))
2732        assert_equal(np.interp(0.5, [0, 1], sc([0, +np.inf])), sc(+np.inf))
2733        assert_equal(np.interp(0.5, [0, 1], sc([-np.inf, 10])), sc(-np.inf))
2734        assert_equal(np.interp(0.5, [0, 1], sc([+np.inf, 10])), sc(+np.inf))
2735        assert_equal(np.interp(0.5, [0, 1], sc([-np.inf, -np.inf])), sc(-np.inf))
2736        assert_equal(np.interp(0.5, [0, 1], sc([+np.inf, +np.inf])), sc(+np.inf))
2737
2738    def test_complex_interp(self):
2739        # test complex interpolation
2740        x = np.linspace(0, 1, 5)
2741        y = np.linspace(0, 1, 5) + (1 + np.linspace(0, 1, 5)) * 1.0j
2742        x0 = 0.3
2743        y0 = x0 + (1 + x0) * 1.0j
2744        assert_almost_equal(np.interp(x0, x, y), y0)
2745        # test complex left and right
2746        x0 = -1
2747        left = 2 + 3.0j
2748        assert_almost_equal(np.interp(x0, x, y, left=left), left)
2749        x0 = 2.0
2750        right = 2 + 3.0j
2751        assert_almost_equal(np.interp(x0, x, y, right=right), right)
2752        # test complex non finite
2753        x = [1, 2, 2.5, 3, 4]
2754        xp = [1, 2, 3, 4]
2755        fp = [1, 2 + 1j, np.inf, 4]
2756        y = [1, 2 + 1j, np.inf + 0.5j, np.inf, 4]
2757        assert_almost_equal(np.interp(x, xp, fp), y)
2758        # test complex periodic
2759        x = [-180, -170, -185, 185, -10, -5, 0, 365]
2760        xp = [190, -190, 350, -350]
2761        fp = [5 + 1.0j, 10 + 2j, 3 + 3j, 4 + 4j]
2762        y = [
2763            7.5 + 1.5j,
2764            5.0 + 1.0j,
2765            8.75 + 1.75j,
2766            6.25 + 1.25j,
2767            3.0 + 3j,
2768            3.25 + 3.25j,
2769            3.5 + 3.5j,
2770            3.75 + 3.75j,
2771        ]
2772        assert_almost_equal(np.interp(x, xp, fp, period=360), y)
2773
2774    def test_zero_dimensional_interpolation_point(self):
2775        x = np.linspace(0, 1, 5)
2776        y = np.linspace(0, 1, 5)
2777        x0 = np.array(0.3)
2778        assert_almost_equal(np.interp(x0, x, y), x0.item())
2779
2780        xp = np.array([0, 2, 4])
2781        fp = np.array([1, -1, 1])
2782
2783        actual = np.interp(np.array(1), xp, fp)
2784        assert_equal(actual, 0)
2785        assert_(isinstance(actual, (np.float64, np.ndarray)))
2786
2787        actual = np.interp(np.array(4.5), xp, fp, period=4)
2788        assert_equal(actual, 0.5)
2789        assert_(isinstance(actual, (np.float64, np.ndarray)))
2790
2791    def test_if_len_x_is_small(self):
2792        xp = np.arange(0, 10, 0.0001)
2793        fp = np.sin(xp)
2794        assert_almost_equal(np.interp(np.pi, xp, fp), 0.0)
2795
2796    def test_period(self):
2797        x = [-180, -170, -185, 185, -10, -5, 0, 365]
2798        xp = [190, -190, 350, -350]
2799        fp = [5, 10, 3, 4]
2800        y = [7.5, 5.0, 8.75, 6.25, 3.0, 3.25, 3.5, 3.75]
2801        assert_almost_equal(np.interp(x, xp, fp, period=360), y)
2802        x = np.array(x, order="F").reshape(2, -1)
2803        y = np.array(y, order="C").reshape(2, -1)
2804        assert_almost_equal(np.interp(x, xp, fp, period=360), y)
2805
2806
2807@instantiate_parametrized_tests
2808class TestPercentile(TestCase):
2809    @skip(reason="NP_VER: fails on CI; no method=")
2810    def test_basic(self):
2811        x = np.arange(8) * 0.5
2812        assert_equal(np.percentile(x, 0), 0.0)
2813        assert_equal(np.percentile(x, 100), 3.5)
2814        assert_equal(np.percentile(x, 50), 1.75)
2815        x[1] = np.nan
2816        assert_equal(np.percentile(x, 0), np.nan)
2817        assert_equal(np.percentile(x, 0, method="nearest"), np.nan)
2818
2819    @skip(reason="support Fraction objects?")
2820    def test_fraction(self):
2821        x = [Fraction(i, 2) for i in range(8)]
2822
2823        p = np.percentile(x, Fraction(0))
2824        assert_equal(p, Fraction(0))
2825        assert_equal(type(p), Fraction)
2826
2827        p = np.percentile(x, Fraction(100))
2828        assert_equal(p, Fraction(7, 2))
2829        assert_equal(type(p), Fraction)
2830
2831        p = np.percentile(x, Fraction(50))
2832        assert_equal(p, Fraction(7, 4))
2833        assert_equal(type(p), Fraction)
2834
2835        p = np.percentile(x, [Fraction(50)])
2836        assert_equal(p, np.array([Fraction(7, 4)]))
2837        assert_equal(type(p), np.ndarray)
2838
2839    def test_api(self):
2840        d = np.ones(5)
2841        np.percentile(d, 5, None, None, False)
2842        np.percentile(d, 5, None, None, False, "linear")
2843        o = np.ones((1,))
2844        np.percentile(d, 5, None, o, False, "linear")
2845
2846    @xfail  # (reason="TODO: implement")
2847    def test_complex(self):
2848        arr_c = np.array([0.5 + 3.0j, 2.1 + 0.5j, 1.6 + 2.3j], dtype="D")
2849        assert_raises(TypeError, np.percentile, arr_c, 0.5)
2850        arr_c = np.array([0.5 + 3.0j, 2.1 + 0.5j, 1.6 + 2.3j], dtype="F")
2851        assert_raises(TypeError, np.percentile, arr_c, 0.5)
2852
2853    def test_2D(self):
2854        x = np.array([[1, 1, 1], [1, 1, 1], [4, 4, 3], [1, 1, 1], [1, 1, 1]])
2855        assert_array_equal(np.percentile(x, 50, axis=0), [1, 1, 1])
2856
2857    @skip(reason="NP_VER: fails on CI; no method=")
2858    @xpassIfTorchDynamo  # (reason="TODO: implement")
2859    @parametrize("dtype", np.typecodes["Float"])
2860    def test_linear_nan_1D(self, dtype):
2861        # METHOD 1 of H&F
2862        arr = np.asarray([15.0, np.nan, 35.0, 40.0, 50.0], dtype=dtype)
2863        res = np.percentile(arr, 40.0, method="linear")
2864        np.testing.assert_equal(res, np.nan)
2865        np.testing.assert_equal(res.dtype, arr.dtype)
2866
2867    H_F_TYPE_CODES = [
2868        (int_type, np.float64) for int_type in "Bbhil"  # np.typecodes["AllInteger"]
2869    ] + [
2870        (np.float16, np.float16),
2871        (np.float32, np.float32),
2872        (np.float64, np.float64),
2873    ]
2874
2875    @skip(reason="NEP 50 is new in 1.24")
2876    @parametrize("input_dtype, expected_dtype", H_F_TYPE_CODES)
2877    @parametrize(
2878        "method, expected",
2879        [
2880            ("inverted_cdf", 20),
2881            ("averaged_inverted_cdf", 27.5),
2882            ("closest_observation", 20),
2883            ("interpolated_inverted_cdf", 20),
2884            ("hazen", 27.5),
2885            ("weibull", 26),
2886            ("linear", 29),
2887            ("median_unbiased", 27),
2888            ("normal_unbiased", 27.125),
2889        ],
2890    )
2891    def test_linear_interpolation(self, method, expected, input_dtype, expected_dtype):
2892        expected_dtype = np.dtype(expected_dtype)
2893
2894        if (
2895            hasattr(np, "_get_promotion_state")
2896            and np._get_promotion_state() == "legacy"
2897        ):
2898            expected_dtype = np.promote_types(expected_dtype, np.float64)
2899
2900        arr = np.asarray([15.0, 20.0, 35.0, 40.0, 50.0], dtype=input_dtype)
2901        actual = np.percentile(arr, 40.0, method=method)
2902
2903        np.testing.assert_almost_equal(actual, expected_dtype.type(expected), 14)
2904
2905        if method in ["inverted_cdf", "closest_observation"]:
2906            np.testing.assert_equal(np.asarray(actual).dtype, np.dtype(input_dtype))
2907        else:
2908            np.testing.assert_equal(np.asarray(actual).dtype, np.dtype(expected_dtype))
2909
2910    TYPE_CODES = np.typecodes["AllInteger"] + np.typecodes["Float"]
2911
2912    @skip(reason="NP_VER: fails on CI; no method=")
2913    @parametrize("dtype", TYPE_CODES)
2914    def test_lower_higher(self, dtype):
2915        assert_equal(np.percentile(np.arange(10, dtype=dtype), 50, method="lower"), 4)
2916        assert_equal(np.percentile(np.arange(10, dtype=dtype), 50, method="higher"), 5)
2917
2918    @skip(reason="NP_VER: fails on CI; no method=")
2919    @parametrize("dtype", TYPE_CODES)
2920    def test_midpoint(self, dtype):
2921        assert_equal(
2922            np.percentile(np.arange(10, dtype=dtype), 51, method="midpoint"), 4.5
2923        )
2924        assert_equal(
2925            np.percentile(np.arange(9, dtype=dtype) + 1, 50, method="midpoint"), 5
2926        )
2927        assert_equal(
2928            np.percentile(np.arange(11, dtype=dtype), 51, method="midpoint"), 5.5
2929        )
2930        assert_equal(
2931            np.percentile(np.arange(11, dtype=dtype), 50, method="midpoint"), 5
2932        )
2933
2934    @skip(reason="NP_VER: fails on CI; no method=")
2935    @parametrize("dtype", TYPE_CODES)
2936    def test_nearest(self, dtype):
2937        assert_equal(np.percentile(np.arange(10, dtype=dtype), 51, method="nearest"), 5)
2938        assert_equal(np.percentile(np.arange(10, dtype=dtype), 49, method="nearest"), 4)
2939
2940    def test_linear_interpolation_extrapolation(self):
2941        arr = np.random.rand(5)
2942
2943        actual = np.percentile(arr, 100)
2944        np.testing.assert_equal(actual, arr.max())
2945
2946        actual = np.percentile(arr, 0)
2947        np.testing.assert_equal(actual, arr.min())
2948
2949    def test_sequence(self):
2950        x = np.arange(8) * 0.5
2951        assert_equal(np.percentile(x, [0, 100, 50]), [0, 3.5, 1.75])
2952
2953    @skip(reason="NP_VER: fails on CI")
2954    def test_axis(self):
2955        x = np.arange(12).reshape(3, 4)
2956
2957        assert_equal(np.percentile(x, (25, 50, 100)), [2.75, 5.5, 11.0])
2958
2959        r0 = [[2, 3, 4, 5], [4, 5, 6, 7], [8, 9, 10, 11]]
2960        assert_equal(np.percentile(x, (25, 50, 100), axis=0), r0)
2961
2962        r1 = [[0.75, 1.5, 3], [4.75, 5.5, 7], [8.75, 9.5, 11]]
2963        assert_equal(np.percentile(x, (25, 50, 100), axis=1), np.array(r1).T)
2964
2965        # ensure qth axis is always first as with np.array(old_percentile(..))
2966        x = np.arange(3 * 4 * 5 * 6).reshape(3, 4, 5, 6)
2967        assert_equal(np.percentile(x, (25, 50)).shape, (2,))
2968        assert_equal(np.percentile(x, (25, 50, 75)).shape, (3,))
2969        assert_equal(np.percentile(x, (25, 50), axis=0).shape, (2, 4, 5, 6))
2970        assert_equal(np.percentile(x, (25, 50), axis=1).shape, (2, 3, 5, 6))
2971        assert_equal(np.percentile(x, (25, 50), axis=2).shape, (2, 3, 4, 6))
2972        assert_equal(np.percentile(x, (25, 50), axis=3).shape, (2, 3, 4, 5))
2973        assert_equal(np.percentile(x, (25, 50, 75), axis=1).shape, (3, 3, 5, 6))
2974        assert_equal(np.percentile(x, (25, 50), method="higher").shape, (2,))
2975        assert_equal(np.percentile(x, (25, 50, 75), method="higher").shape, (3,))
2976        assert_equal(
2977            np.percentile(x, (25, 50), axis=0, method="higher").shape, (2, 4, 5, 6)
2978        )
2979        assert_equal(
2980            np.percentile(x, (25, 50), axis=1, method="higher").shape, (2, 3, 5, 6)
2981        )
2982        assert_equal(
2983            np.percentile(x, (25, 50), axis=2, method="higher").shape, (2, 3, 4, 6)
2984        )
2985        assert_equal(
2986            np.percentile(x, (25, 50), axis=3, method="higher").shape, (2, 3, 4, 5)
2987        )
2988        assert_equal(
2989            np.percentile(x, (25, 50, 75), axis=1, method="higher").shape, (3, 3, 5, 6)
2990        )
2991
2992    @skipif(numpy.__version__ < "1.22", reason="NP_VER: fails with NumPy 1.21.2 on CI")
2993    def test_scalar_q(self):
2994        # test for no empty dimensions for compatibility with old percentile
2995        x = np.arange(12).reshape(3, 4)
2996        assert_equal(np.percentile(x, 50), 5.5)
2997        # assert_(np.isscalar(np.percentile(x, 50)))  # XXX: our isscalar differs
2998        r0 = np.array([4.0, 5.0, 6.0, 7.0])
2999        assert_equal(np.percentile(x, 50, axis=0), r0)
3000        assert_equal(np.percentile(x, 50, axis=0).shape, r0.shape)
3001        r1 = np.array([1.5, 5.5, 9.5])
3002        assert_almost_equal(np.percentile(x, 50, axis=1), r1)
3003        assert_equal(np.percentile(x, 50, axis=1).shape, r1.shape)
3004
3005        out = np.empty(1)
3006        assert_equal(np.percentile(x, 50, out=out), 5.5)
3007        assert_equal(out, 5.5)
3008        out = np.empty(4)
3009        assert_equal(np.percentile(x, 50, axis=0, out=out), r0)
3010        assert_equal(out, r0)
3011        out = np.empty(3)
3012        assert_equal(np.percentile(x, 50, axis=1, out=out), r1)
3013        assert_equal(out, r1)
3014
3015        # test for no empty dimensions for compatibility with old percentile
3016        x = np.arange(12).reshape(3, 4)
3017        assert_equal(np.percentile(x, 50, method="lower"), 5.0)
3018        assert_(np.isscalar(np.percentile(x, 50)))
3019        r0 = np.array([4.0, 5.0, 6.0, 7.0])
3020        c0 = np.percentile(x, 50, method="lower", axis=0)
3021        assert_equal(c0, r0)
3022        assert_equal(c0.shape, r0.shape)
3023        r1 = np.array([1.0, 5.0, 9.0])
3024        c1 = np.percentile(x, 50, method="lower", axis=1)
3025        assert_almost_equal(c1, r1)
3026        assert_equal(c1.shape, r1.shape)
3027
3028    @xfail  # (reason="numpy: x.dtype is int, out is int; torch: result is float")
3029    def test_scalar_q_2(self):
3030        x = np.arange(12).reshape(3, 4)
3031        out = np.empty((), dtype=x.dtype)
3032        c = np.percentile(x, 50, method="lower", out=out)
3033        assert_equal(c, 5)
3034        assert_equal(out, 5)
3035        out = np.empty(4, dtype=x.dtype)
3036        c = np.percentile(x, 50, method="lower", axis=0, out=out)
3037        assert_equal(c, r0)
3038        assert_equal(out, r0)
3039        out = np.empty(3, dtype=x.dtype)
3040        c = np.percentile(x, 50, method="lower", axis=1, out=out)
3041        assert_equal(c, r1)
3042        assert_equal(out, r1)
3043
3044    @skip(reason="NP_VER: fails on CI; no method=")
3045    def test_exception(self):
3046        assert_raises(
3047            (RuntimeError, ValueError), np.percentile, [1, 2], 56, method="foobar"
3048        )
3049        assert_raises((RuntimeError, ValueError), np.percentile, [1], 101)
3050        assert_raises((RuntimeError, ValueError), np.percentile, [1], -1)
3051        assert_raises(
3052            (RuntimeError, ValueError), np.percentile, [1], list(range(50)) + [101]
3053        )
3054        assert_raises(
3055            (RuntimeError, ValueError), np.percentile, [1], list(range(50)) + [-0.1]
3056        )
3057
3058    def test_percentile_list(self):
3059        assert_equal(np.percentile([1, 2, 3], 0), 1)
3060
3061    @skip(reason="NP_VER: fails on CI; no method=")
3062    def test_percentile_out(self):
3063        x = np.array([1, 2, 3])
3064        y = np.zeros((3,))
3065        p = (1, 2, 3)
3066        np.percentile(x, p, out=y)
3067        assert_equal(np.percentile(x, p), y)
3068
3069        x = np.array([[1, 2, 3], [4, 5, 6]])
3070
3071        y = np.zeros((3, 3))
3072        np.percentile(x, p, axis=0, out=y)
3073        assert_equal(np.percentile(x, p, axis=0), y)
3074
3075        y = np.zeros((3, 2))
3076        np.percentile(x, p, axis=1, out=y)
3077        assert_equal(np.percentile(x, p, axis=1), y)
3078
3079        x = np.arange(12).reshape(3, 4)
3080        # q.dim > 1, float
3081        r0 = np.array([[2.0, 3.0, 4.0, 5.0], [4.0, 5.0, 6.0, 7.0]])
3082        out = np.empty((2, 4))
3083        assert_equal(np.percentile(x, (25, 50), axis=0, out=out), r0)
3084        assert_equal(out, r0)
3085        r1 = np.array([[0.75, 4.75, 8.75], [1.5, 5.5, 9.5]])
3086        out = np.empty((2, 3))
3087        assert_equal(np.percentile(x, (25, 50), axis=1, out=out), r1)
3088        assert_equal(out, r1)
3089
3090        # q.dim > 1, int
3091        r0 = np.array([[0, 1, 2, 3], [4, 5, 6, 7]])
3092        out = np.empty((2, 4), dtype=x.dtype)
3093        c = np.percentile(x, (25, 50), method="lower", axis=0, out=out)
3094        assert_equal(c, r0)
3095        assert_equal(out, r0)
3096        r1 = np.array([[0, 4, 8], [1, 5, 9]])
3097        out = np.empty((2, 3), dtype=x.dtype)
3098        c = np.percentile(x, (25, 50), method="lower", axis=1, out=out)
3099        assert_equal(c, r1)
3100        assert_equal(out, r1)
3101
3102    @skip(reason="NP_VER: fails on CI; no method=")
3103    def test_percentile_empty_dim(self):
3104        # empty dims are preserved
3105        d = np.arange(11 * 2).reshape(11, 1, 2, 1)
3106        assert_array_equal(np.percentile(d, 50, axis=0).shape, (1, 2, 1))
3107        assert_array_equal(np.percentile(d, 50, axis=1).shape, (11, 2, 1))
3108        assert_array_equal(np.percentile(d, 50, axis=2).shape, (11, 1, 1))
3109        assert_array_equal(np.percentile(d, 50, axis=3).shape, (11, 1, 2))
3110        assert_array_equal(np.percentile(d, 50, axis=-1).shape, (11, 1, 2))
3111        assert_array_equal(np.percentile(d, 50, axis=-2).shape, (11, 1, 1))
3112        assert_array_equal(np.percentile(d, 50, axis=-3).shape, (11, 2, 1))
3113        assert_array_equal(np.percentile(d, 50, axis=-4).shape, (1, 2, 1))
3114
3115        assert_array_equal(
3116            np.percentile(d, 50, axis=2, method="midpoint").shape, (11, 1, 1)
3117        )
3118        assert_array_equal(
3119            np.percentile(d, 50, axis=-2, method="midpoint").shape, (11, 1, 1)
3120        )
3121
3122        assert_array_equal(
3123            np.array(np.percentile(d, [10, 50], axis=0)).shape, (2, 1, 2, 1)
3124        )
3125        assert_array_equal(
3126            np.array(np.percentile(d, [10, 50], axis=1)).shape, (2, 11, 2, 1)
3127        )
3128        assert_array_equal(
3129            np.array(np.percentile(d, [10, 50], axis=2)).shape, (2, 11, 1, 1)
3130        )
3131        assert_array_equal(
3132            np.array(np.percentile(d, [10, 50], axis=3)).shape, (2, 11, 1, 2)
3133        )
3134
3135    def test_percentile_no_overwrite(self):
3136        a = np.array([2, 3, 4, 1])
3137        np.percentile(a, [50], overwrite_input=False)
3138        assert_equal(a, np.array([2, 3, 4, 1]))
3139
3140        a = np.array([2, 3, 4, 1])
3141        np.percentile(a, [50])
3142        assert_equal(a, np.array([2, 3, 4, 1]))
3143
3144    @skip(reason="NP_VER: fails on CI; no method=")
3145    def test_no_p_overwrite(self):
3146        p = np.linspace(0.0, 100.0, num=5)
3147        np.percentile(np.arange(100.0), p, method="midpoint")
3148        assert_array_equal(p, np.linspace(0.0, 100.0, num=5))
3149        p = np.linspace(0.0, 100.0, num=5).tolist()
3150        np.percentile(np.arange(100.0), p, method="midpoint")
3151        assert_array_equal(p, np.linspace(0.0, 100.0, num=5).tolist())
3152
3153    def test_percentile_overwrite(self):
3154        a = np.array([2, 3, 4, 1])
3155        b = np.percentile(a, [50], overwrite_input=True)
3156        assert_equal(b, np.array([2.5]))
3157
3158        b = np.percentile([2, 3, 4, 1], [50], overwrite_input=True)
3159        assert_equal(b, np.array([2.5]))
3160
3161    @xpassIfTorchDynamo  # (reason="pytorch percentile does not support tuple axes.")
3162    def test_extended_axis(self):
3163        o = np.random.normal(size=(71, 23))
3164        x = np.dstack([o] * 10)
3165        assert_equal(np.percentile(x, 30, axis=(0, 1)), np.percentile(o, 30).item())
3166        x = np.moveaxis(x, -1, 0)
3167        assert_equal(np.percentile(x, 30, axis=(-2, -1)), np.percentile(o, 30).item())
3168        x = x.swapaxes(0, 1).copy()
3169        assert_equal(np.percentile(x, 30, axis=(0, -1)), np.percentile(o, 30).item())
3170        x = x.swapaxes(0, 1).copy()
3171
3172        assert_equal(
3173            np.percentile(x, [25, 60], axis=(0, 1, 2)),
3174            np.percentile(x, [25, 60], axis=None),
3175        )
3176        assert_equal(
3177            np.percentile(x, [25, 60], axis=(0,)), np.percentile(x, [25, 60], axis=0)
3178        )
3179
3180        d = np.arange(3 * 5 * 7 * 11).reshape((3, 5, 7, 11))
3181        np.random.shuffle(d.ravel())
3182        assert_equal(
3183            np.percentile(d, 25, axis=(0, 1, 2))[0],
3184            np.percentile(d[:, :, :, 0].flatten(), 25),
3185        )
3186        assert_equal(
3187            np.percentile(d, [10, 90], axis=(0, 1, 3))[:, 1],
3188            np.percentile(d[:, :, 1, :].flatten(), [10, 90]),
3189        )
3190        assert_equal(
3191            np.percentile(d, 25, axis=(3, 1, -4))[2],
3192            np.percentile(d[:, :, 2, :].flatten(), 25),
3193        )
3194        assert_equal(
3195            np.percentile(d, 25, axis=(3, 1, 2))[2],
3196            np.percentile(d[2, :, :, :].flatten(), 25),
3197        )
3198        assert_equal(
3199            np.percentile(d, 25, axis=(3, 2))[2, 1],
3200            np.percentile(d[2, 1, :, :].flatten(), 25),
3201        )
3202        assert_equal(
3203            np.percentile(d, 25, axis=(1, -2))[2, 1],
3204            np.percentile(d[2, :, :, 1].flatten(), 25),
3205        )
3206        assert_equal(
3207            np.percentile(d, 25, axis=(1, 3))[2, 2],
3208            np.percentile(d[2, :, 2, :].flatten(), 25),
3209        )
3210
3211    def test_extended_axis_invalid(self):
3212        d = np.ones((3, 5, 7, 11))
3213        assert_raises(np.AxisError, np.percentile, d, axis=-5, q=25)
3214        assert_raises(np.AxisError, np.percentile, d, axis=(0, -5), q=25)
3215        assert_raises(np.AxisError, np.percentile, d, axis=4, q=25)
3216        assert_raises(np.AxisError, np.percentile, d, axis=(0, 4), q=25)
3217        # each of these refers to the same axis twice
3218        assert_raises(ValueError, np.percentile, d, axis=(1, 1), q=25)
3219        assert_raises(ValueError, np.percentile, d, axis=(-1, -1), q=25)
3220        assert_raises(ValueError, np.percentile, d, axis=(3, -1), q=25)
3221
3222    def test_keepdims(self):
3223        d = np.ones((3, 5, 7, 11))
3224        assert_equal(np.percentile(d, 7, axis=None, keepdims=True).shape, (1, 1, 1, 1))
3225
3226    @xfail  # (reason="pytorch percentile does not support tuple axes.")
3227    def test_keepdims_2(self):
3228        assert_equal(
3229            np.percentile(d, 7, axis=(0, 1), keepdims=True).shape, (1, 1, 7, 11)
3230        )
3231        assert_equal(
3232            np.percentile(d, 7, axis=(0, 3), keepdims=True).shape, (1, 5, 7, 1)
3233        )
3234        assert_equal(np.percentile(d, 7, axis=(1,), keepdims=True).shape, (3, 1, 7, 11))
3235        assert_equal(
3236            np.percentile(d, 7, (0, 1, 2, 3), keepdims=True).shape, (1, 1, 1, 1)
3237        )
3238        assert_equal(
3239            np.percentile(d, 7, axis=(0, 1, 3), keepdims=True).shape, (1, 1, 7, 1)
3240        )
3241
3242        assert_equal(
3243            np.percentile(d, [1, 7], axis=(0, 1, 3), keepdims=True).shape,
3244            (2, 1, 1, 7, 1),
3245        )
3246        assert_equal(
3247            np.percentile(d, [1, 7], axis=(0, 3), keepdims=True).shape, (2, 1, 5, 7, 1)
3248        )
3249
3250    @skipif(numpy.__version__ < "1.24", reason="NP_VER: fails on NumPy 1.23.x")
3251    @parametrize(
3252        "q",
3253        [
3254            7,
3255            subtest(
3256                [1, 7],
3257                decorators=[
3258                    skip(reason="Keepdims wrapper incorrect for multiple q"),
3259                ],
3260            ),
3261        ],
3262    )
3263    @parametrize(
3264        "axis",
3265        [
3266            None,
3267            1,
3268            subtest((1,)),
3269            subtest(
3270                (0, 1),
3271                decorators=[
3272                    skip(reason="Tuple axes"),
3273                ],
3274            ),
3275            subtest(
3276                (-3, -1),
3277                decorators=[
3278                    skip(reason="Tuple axes"),
3279                ],
3280            ),
3281        ],
3282    )
3283    def test_keepdims_out(self, q, axis):
3284        d = np.ones((3, 5, 7, 11))
3285        if axis is None:
3286            shape_out = (1,) * d.ndim
3287        else:
3288            axis_norm = normalize_axis_tuple(axis, d.ndim)
3289            shape_out = tuple(
3290                1 if i in axis_norm else d.shape[i] for i in range(d.ndim)
3291            )
3292        shape_out = np.shape(q) + shape_out
3293
3294        out = np.empty(shape_out)
3295        result = np.percentile(d, q, axis=axis, keepdims=True, out=out)
3296        assert result is out
3297        assert_equal(result.shape, shape_out)
3298
3299    @skip(reason="NP_VER: fails on CI; no method=")
3300    def test_out(self):
3301        o = np.zeros((4,))
3302        d = np.ones((3, 4))
3303        assert_equal(np.percentile(d, 0, 0, out=o), o)
3304        assert_equal(np.percentile(d, 0, 0, method="nearest", out=o), o)
3305        o = np.zeros((3,))
3306        assert_equal(np.percentile(d, 1, 1, out=o), o)
3307        assert_equal(np.percentile(d, 1, 1, method="nearest", out=o), o)
3308
3309        o = np.zeros(())
3310        d = np.ones((3, 4))
3311        assert_equal(np.percentile(d, 2, out=o), o)
3312        assert_equal(np.percentile(d, 2, method="nearest", out=o), o)
3313
3314    @skip(reason="NP_VER: fails on CI; no method=")
3315    def test_out_nan(self):
3316        with warnings.catch_warnings(record=True):
3317            warnings.filterwarnings("always", "", RuntimeWarning)
3318            o = np.zeros((4,))
3319            d = np.ones((3, 4))
3320            d[2, 1] = np.nan
3321            assert_equal(np.percentile(d, 0, 0, out=o), o)
3322            assert_equal(np.percentile(d, 0, 0, method="nearest", out=o), o)
3323            o = np.zeros((3,))
3324            assert_equal(np.percentile(d, 1, 1, out=o), o)
3325            assert_equal(np.percentile(d, 1, 1, method="nearest", out=o), o)
3326            o = np.zeros(())
3327            assert_equal(np.percentile(d, 1, out=o), o)
3328            assert_equal(np.percentile(d, 1, method="nearest", out=o), o)
3329
3330    @skip(reason="NP_VER: fails on CI; no method=")
3331    @xpassIfTorchDynamo  # (reason="np.percentile undocumented nan weirdness")
3332    def test_nan_behavior(self):
3333        a = np.arange(24, dtype=float)
3334        a[2] = np.nan
3335        assert_equal(np.percentile(a, 0.3), np.nan)
3336        assert_equal(np.percentile(a, 0.3, axis=0), np.nan)
3337        assert_equal(np.percentile(a, [0.3, 0.6], axis=0), np.array([np.nan] * 2))
3338
3339        a = np.arange(24, dtype=float).reshape(2, 3, 4)
3340        a[1, 2, 3] = np.nan
3341        a[1, 1, 2] = np.nan
3342
3343        # no axis
3344        assert_equal(np.percentile(a, 0.3), np.nan)
3345        assert_equal(np.percentile(a, 0.3).ndim, 0)
3346
3347        # axis0 zerod
3348        b = np.percentile(np.arange(24, dtype=float).reshape(2, 3, 4), 0.3, 0)
3349        b[2, 3] = np.nan
3350        b[1, 2] = np.nan
3351        assert_equal(np.percentile(a, 0.3, 0), b)
3352
3353        # axis0 not zerod
3354        b = np.percentile(np.arange(24, dtype=float).reshape(2, 3, 4), [0.3, 0.6], 0)
3355        b[:, 2, 3] = np.nan
3356        b[:, 1, 2] = np.nan
3357        assert_equal(np.percentile(a, [0.3, 0.6], 0), b)
3358
3359        # axis1 zerod
3360        b = np.percentile(np.arange(24, dtype=float).reshape(2, 3, 4), 0.3, 1)
3361        b[1, 3] = np.nan
3362        b[1, 2] = np.nan
3363        assert_equal(np.percentile(a, 0.3, 1), b)
3364        # axis1 not zerod
3365        b = np.percentile(np.arange(24, dtype=float).reshape(2, 3, 4), [0.3, 0.6], 1)
3366        b[:, 1, 3] = np.nan
3367        b[:, 1, 2] = np.nan
3368        assert_equal(np.percentile(a, [0.3, 0.6], 1), b)
3369
3370        # axis02 zerod
3371        b = np.percentile(np.arange(24, dtype=float).reshape(2, 3, 4), 0.3, (0, 2))
3372        b[1] = np.nan
3373        b[2] = np.nan
3374        assert_equal(np.percentile(a, 0.3, (0, 2)), b)
3375        # axis02 not zerod
3376        b = np.percentile(
3377            np.arange(24, dtype=float).reshape(2, 3, 4), [0.3, 0.6], (0, 2)
3378        )
3379        b[:, 1] = np.nan
3380        b[:, 2] = np.nan
3381        assert_equal(np.percentile(a, [0.3, 0.6], (0, 2)), b)
3382        # axis02 not zerod with method='nearest'
3383        b = np.percentile(
3384            np.arange(24, dtype=float).reshape(2, 3, 4),
3385            [0.3, 0.6],
3386            (0, 2),
3387            method="nearest",
3388        )
3389        b[:, 1] = np.nan
3390        b[:, 2] = np.nan
3391        assert_equal(np.percentile(a, [0.3, 0.6], (0, 2), method="nearest"), b)
3392
3393    def test_nan_q(self):
3394        # GH18830
3395        with pytest.raises((RuntimeError, ValueError)):
3396            np.percentile([1, 2, 3, 4.0], np.nan)
3397        with pytest.raises((RuntimeError, ValueError)):
3398            np.percentile([1, 2, 3, 4.0], [np.nan])
3399        q = np.linspace(1.0, 99.0, 16)
3400        q[0] = np.nan
3401        with pytest.raises((RuntimeError, ValueError)):
3402            np.percentile([1, 2, 3, 4.0], q)
3403
3404
3405@instantiate_parametrized_tests
3406class TestQuantile(TestCase):
3407    # most of this is already tested by TestPercentile
3408
3409    @skip(reason="do not chase 1ulp")
3410    def test_max_ulp(self):
3411        x = [0.0, 0.2, 0.4]
3412        a = np.quantile(x, 0.45)
3413        # The default linear method would result in 0 + 0.2 * (0.45/2) = 0.18.
3414        # 0.18 is not exactly representable and the formula leads to a 1 ULP
3415        # different result. Ensure it is this exact within 1 ULP, see gh-20331.
3416        np.testing.assert_array_max_ulp(a, 0.18, maxulp=1)
3417
3418    def test_basic(self):
3419        x = np.arange(8) * 0.5
3420        assert_equal(np.quantile(x, 0), 0.0)
3421        assert_equal(np.quantile(x, 1), 3.5)
3422        assert_equal(np.quantile(x, 0.5), 1.75)
3423
3424    @xfail  # (reason="quantile w/integers or bools")
3425    def test_correct_quantile_value(self):
3426        a = np.array([True])
3427        tf_quant = np.quantile(True, False)
3428        assert_equal(tf_quant, a[0])
3429        assert_equal(type(tf_quant), a.dtype)
3430        a = np.array([False, True, True])
3431        quant_res = np.quantile(a, a)
3432        assert_array_equal(quant_res, a)
3433        assert_equal(quant_res.dtype, a.dtype)
3434
3435    @skip(reason="support arrays of Fractions?")
3436    def test_fraction(self):
3437        # fractional input, integral quantile
3438        x = [Fraction(i, 2) for i in range(8)]
3439        q = np.quantile(x, 0)
3440        assert_equal(q, 0)
3441        assert_equal(type(q), Fraction)
3442
3443        q = np.quantile(x, 1)
3444        assert_equal(q, Fraction(7, 2))
3445        assert_equal(type(q), Fraction)
3446
3447        q = np.quantile(x, Fraction(1, 2))
3448        assert_equal(q, Fraction(7, 4))
3449        assert_equal(type(q), Fraction)
3450
3451        q = np.quantile(x, [Fraction(1, 2)])
3452        assert_equal(q, np.array([Fraction(7, 4)]))
3453        assert_equal(type(q), np.ndarray)
3454
3455        q = np.quantile(x, [[Fraction(1, 2)]])
3456        assert_equal(q, np.array([[Fraction(7, 4)]]))
3457        assert_equal(type(q), np.ndarray)
3458
3459        # repeat with integral input but fractional quantile
3460        x = np.arange(8)
3461        assert_equal(np.quantile(x, Fraction(1, 2)), Fraction(7, 2))
3462
3463    @skip(reason="does not raise in numpy?")
3464    def test_complex(self):
3465        # See gh-22652
3466        arr_c = np.array([0.5 + 3.0j, 2.1 + 0.5j, 1.6 + 2.3j], dtype="D")
3467        assert_raises(TypeError, np.quantile, arr_c, 0.5)
3468        arr_c = np.array([0.5 + 3.0j, 2.1 + 0.5j, 1.6 + 2.3j], dtype="F")
3469        assert_raises(TypeError, np.quantile, arr_c, 0.5)
3470
3471    @skipif(numpy.__version__ < "1.22", reason="NP_VER: fails with NumPy 1.21.2 on CI")
3472    def test_no_p_overwrite(self):
3473        # this is worth retesting, because quantile does not make a copy
3474        p0 = np.array([0, 0.75, 0.25, 0.5, 1.0])
3475        p = p0.copy()
3476        np.quantile(np.arange(100.0), p, method="midpoint")
3477        assert_array_equal(p, p0)
3478
3479        p0 = p0.tolist()
3480        p = p.tolist()
3481        np.quantile(np.arange(100.0), p, method="midpoint")
3482        assert_array_equal(p, p0)
3483
3484    @skip(reason="XXX: make quantile preserve integer dtypes")
3485    @parametrize("dtype", "Bbhil")  # np.typecodes["AllInteger"])
3486    def test_quantile_preserve_int_type(self, dtype):
3487        res = np.quantile(np.array([1, 2], dtype=dtype), [0.5], method="nearest")
3488        assert res.dtype == dtype
3489
3490    @skipif(numpy.__version__ < "1.22", reason="NP_VER: fails with NumPy 1.21.2 on CI")
3491    @parametrize(
3492        "method",
3493        [
3494            subtest(
3495                "inverted_cdf",
3496                decorators=[
3497                    xpassIfTorchDynamo,
3498                ],
3499            ),
3500            subtest(
3501                "averaged_inverted_cdf",
3502                decorators=[
3503                    xpassIfTorchDynamo,
3504                ],
3505            ),
3506            subtest(
3507                "closest_observation",
3508                decorators=[
3509                    xpassIfTorchDynamo,
3510                ],
3511            ),
3512            subtest(
3513                "interpolated_inverted_cdf",
3514                decorators=[
3515                    xpassIfTorchDynamo,
3516                ],
3517            ),
3518            subtest(
3519                "hazen",
3520                decorators=[
3521                    xpassIfTorchDynamo,
3522                ],
3523            ),
3524            subtest(
3525                "weibull",
3526                decorators=[
3527                    xpassIfTorchDynamo,
3528                ],
3529            ),
3530            "linear",
3531            subtest(
3532                "median_unbiased",
3533                decorators=[
3534                    xpassIfTorchDynamo,
3535                ],
3536            ),
3537            subtest(
3538                "normal_unbiased",
3539                decorators=[
3540                    xpassIfTorchDynamo,
3541                ],
3542            ),
3543            "nearest",
3544            "lower",
3545            "higher",
3546            "midpoint",
3547        ],
3548    )
3549    def test_quantile_monotonic(self, method):
3550        # GH 14685
3551        # test that the return value of quantile is monotonic if p0 is ordered
3552        # Also tests that the boundary values are not mishandled.
3553        p0 = np.linspace(0, 1, 101)
3554        quantile = np.quantile(
3555            np.array([0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 1, 1, 9, 9, 9, 8, 8, 7]) * 0.1,
3556            p0,
3557            method=method,
3558        )
3559        assert_equal(np.sort(quantile), quantile)
3560
3561        # Also test one where the number of data points is clearly divisible:
3562        quantile = np.quantile([0.0, 1.0, 2.0, 3.0], p0, method=method)
3563        assert_equal(np.sort(quantile), quantile)
3564
3565    @skip(reason="no hypothesis")
3566    @hypothesis.given(
3567        arr=arrays(
3568            dtype=np.float64,
3569            shape=st.integers(min_value=3, max_value=1000),
3570            elements=st.floats(
3571                allow_infinity=False, allow_nan=False, min_value=-1e300, max_value=1e300
3572            ),
3573        )
3574    )
3575    def test_quantile_monotonic_hypo(self, arr):
3576        p0 = np.arange(0, 1, 0.01)
3577        quantile = np.quantile(arr, p0)
3578        assert_equal(np.sort(quantile), quantile)
3579
3580    def test_quantile_scalar_nan(self):
3581        a = np.array([[10.0, 7.0, 4.0], [3.0, 2.0, 1.0]])
3582        a[0][1] = np.nan
3583        actual = np.quantile(a, 0.5)
3584        # assert np.isscalar(actual)    # XXX: our isscalar follows pytorch
3585        assert_equal(np.quantile(a, 0.5), np.nan)
3586
3587
3588@instantiate_parametrized_tests
3589class TestMedian(TestCase):
3590    def test_basic(self):
3591        a0 = np.array(1)
3592        a1 = np.arange(2)
3593        a2 = np.arange(6).reshape(2, 3)
3594        assert_equal(np.median(a0), 1)
3595        assert_allclose(np.median(a1), 0.5)
3596        assert_allclose(np.median(a2), 2.5)
3597        assert_allclose(np.median(a2, axis=0), [1.5, 2.5, 3.5])
3598        assert_equal(np.median(a2, axis=1), [1, 4])
3599        assert_allclose(np.median(a2, axis=None), 2.5)
3600
3601        a = np.array([0.0444502, 0.0463301, 0.141249, 0.0606775])
3602        assert_almost_equal((a[1] + a[3]) / 2.0, np.median(a))
3603        a = np.array([0.0463301, 0.0444502, 0.141249])
3604        assert_equal(a[0], np.median(a))
3605        a = np.array([0.0444502, 0.141249, 0.0463301])
3606        assert_equal(a[-1], np.median(a))
3607
3608    @xfail  # (reason="median: scalar output vs 0-dim")
3609    def test_basic_2(self):
3610        # check array scalar result
3611        a = np.array([0.0444502, 0.141249, 0.0463301])
3612        assert_equal(np.median(a).ndim, 0)
3613        a[1] = np.nan
3614        assert_equal(np.median(a).ndim, 0)
3615
3616    def test_axis_keyword(self):
3617        a3 = np.array([[2, 3], [0, 1], [6, 7], [4, 5]])
3618        for a in [a3, np.random.randint(0, 100, size=(2, 3, 4))]:
3619            orig = a.copy()
3620            np.median(a, axis=None)
3621            for ax in range(a.ndim):
3622                np.median(a, axis=ax)
3623            assert_array_equal(a, orig)
3624
3625        assert_allclose(np.median(a3, axis=0), [3, 4])
3626        assert_allclose(np.median(a3.T, axis=1), [3, 4])
3627        assert_allclose(np.median(a3), 3.5)
3628        assert_allclose(np.median(a3, axis=None), 3.5)
3629        assert_allclose(np.median(a3.T), 3.5)
3630
3631    def test_overwrite_keyword(self):
3632        a3 = np.array([[2, 3], [0, 1], [6, 7], [4, 5]])
3633        a0 = np.array(1)
3634        a1 = np.arange(2)
3635        a2 = np.arange(6).reshape(2, 3)
3636        assert_allclose(np.median(a0.copy(), overwrite_input=True), 1)
3637        assert_allclose(np.median(a1.copy(), overwrite_input=True), 0.5)
3638        assert_allclose(np.median(a2.copy(), overwrite_input=True), 2.5)
3639        assert_allclose(
3640            np.median(a2.copy(), overwrite_input=True, axis=0), [1.5, 2.5, 3.5]
3641        )
3642        assert_allclose(np.median(a2.copy(), overwrite_input=True, axis=1), [1, 4])
3643        assert_allclose(np.median(a2.copy(), overwrite_input=True, axis=None), 2.5)
3644        assert_allclose(np.median(a3.copy(), overwrite_input=True, axis=0), [3, 4])
3645        assert_allclose(np.median(a3.T.copy(), overwrite_input=True, axis=1), [3, 4])
3646
3647        a4 = np.arange(3 * 4 * 5, dtype=np.float32).reshape((3, 4, 5))
3648        np.random.shuffle(a4.ravel())
3649        assert_allclose(
3650            np.median(a4, axis=None),
3651            np.median(a4.copy(), axis=None, overwrite_input=True),
3652        )
3653        assert_allclose(
3654            np.median(a4, axis=0), np.median(a4.copy(), axis=0, overwrite_input=True)
3655        )
3656        assert_allclose(
3657            np.median(a4, axis=1), np.median(a4.copy(), axis=1, overwrite_input=True)
3658        )
3659        assert_allclose(
3660            np.median(a4, axis=2), np.median(a4.copy(), axis=2, overwrite_input=True)
3661        )
3662
3663    def test_array_like(self):
3664        x = [1, 2, 3]
3665        assert_almost_equal(np.median(x), 2)
3666        x2 = [x]
3667        assert_almost_equal(np.median(x2), 2)
3668        assert_allclose(np.median(x2, axis=0), x)
3669
3670    def test_out(self):
3671        o = np.zeros((4,))
3672        d = np.ones((3, 4))
3673        assert_equal(np.median(d, 0, out=o), o)
3674        o = np.zeros((3,))
3675        assert_equal(np.median(d, 1, out=o), o)
3676        o = np.zeros(())
3677        assert_equal(np.median(d, out=o), o)
3678
3679    def test_out_nan(self):
3680        with warnings.catch_warnings(record=True):
3681            warnings.filterwarnings("always", "", RuntimeWarning)
3682            o = np.zeros((4,))
3683            d = np.ones((3, 4))
3684            d[2, 1] = np.nan
3685            assert_equal(np.median(d, 0, out=o), o)
3686            o = np.zeros((3,))
3687            assert_equal(np.median(d, 1, out=o), o)
3688            o = np.zeros(())
3689            assert_equal(np.median(d, out=o), o)
3690
3691    def test_nan_behavior(self):
3692        a = np.arange(24, dtype=float)
3693        a[2] = np.nan
3694        assert_equal(np.median(a), np.nan)
3695        assert_equal(np.median(a, axis=0), np.nan)
3696
3697        a = np.arange(24, dtype=float).reshape(2, 3, 4)
3698        a[1, 2, 3] = np.nan
3699        a[1, 1, 2] = np.nan
3700
3701        # no axis
3702        assert_equal(np.median(a), np.nan)
3703        #      assert_equal(np.median(a).ndim, 0)
3704
3705        # axis0
3706        b = np.median(np.arange(24, dtype=float).reshape(2, 3, 4), 0)
3707        b[2, 3] = np.nan
3708        b[1, 2] = np.nan
3709        assert_equal(np.median(a, 0), b)
3710
3711        # axis1
3712        b = np.median(np.arange(24, dtype=float).reshape(2, 3, 4), 1)
3713        b[1, 3] = np.nan
3714        b[1, 2] = np.nan
3715        assert_equal(np.median(a, 1), b)
3716
3717    @xpassIfTorchDynamo  # (reason="median: does not support tuple axes")
3718    def test_nan_behavior_2(self):
3719        a = np.arange(24, dtype=float).reshape(2, 3, 4)
3720        a[1, 2, 3] = np.nan
3721        a[1, 1, 2] = np.nan
3722
3723        # axis02
3724        b = np.median(np.arange(24, dtype=float).reshape(2, 3, 4), (0, 2))
3725        b[1] = np.nan
3726        b[2] = np.nan
3727        assert_equal(np.median(a, (0, 2)), b)
3728
3729    @xfail  # (reason="median: scalar vs 0-dim")
3730    def test_nan_behavior_3(self):
3731        a = np.arange(24, dtype=float).reshape(2, 3, 4)
3732        a[1, 2, 3] = np.nan
3733        a[1, 1, 2] = np.nan
3734
3735        # no axis
3736        assert_equal(np.median(a).ndim, 0)
3737
3738    @xpassIfTorchDynamo  # (reason="median: torch.quantile does not handle empty tensors")
3739    @skipif(IS_WASM, reason="fp errors don't work correctly")
3740    def test_empty(self):
3741        # mean(empty array) emits two warnings: empty slice and divide by 0
3742        a = np.array([], dtype=float)
3743        with warnings.catch_warnings(record=True) as w:
3744            warnings.filterwarnings("always", "", RuntimeWarning)
3745            assert_equal(np.median(a), np.nan)
3746            assert_(w[0].category is RuntimeWarning)
3747            assert_equal(len(w), 2)
3748
3749        # multiple dimensions
3750        a = np.array([], dtype=float, ndmin=3)
3751        # no axis
3752        with warnings.catch_warnings(record=True) as w:
3753            warnings.filterwarnings("always", "", RuntimeWarning)
3754            assert_equal(np.median(a), np.nan)
3755            assert_(w[0].category is RuntimeWarning)
3756
3757        # axis 0 and 1
3758        b = np.array([], dtype=float, ndmin=2)
3759        assert_equal(np.median(a, axis=0), b)
3760        assert_equal(np.median(a, axis=1), b)
3761
3762        # axis 2
3763        b = np.array(np.nan, dtype=float, ndmin=2)
3764        with warnings.catch_warnings(record=True) as w:
3765            warnings.filterwarnings("always", "", RuntimeWarning)
3766            assert_equal(np.median(a, axis=2), b)
3767            assert_(w[0].category is RuntimeWarning)
3768
3769    @xpassIfTorchDynamo  # (reason="median: tuple axes not implemented")
3770    def test_extended_axis(self):
3771        o = np.random.normal(size=(71, 23))
3772        x = np.dstack([o] * 10)
3773        assert_equal(np.median(x, axis=(0, 1)), np.median(o).item())
3774        x = np.moveaxis(x, -1, 0)
3775        assert_equal(np.median(x, axis=(-2, -1)), np.median(o).item())
3776        x = x.swapaxes(0, 1).copy()
3777        assert_equal(np.median(x, axis=(0, -1)), np.median(o).item())
3778
3779        assert_equal(np.median(x, axis=(0, 1, 2)), np.median(x, axis=None))
3780        assert_equal(np.median(x, axis=(0,)), np.median(x, axis=0))
3781        assert_equal(np.median(x, axis=(-1,)), np.median(x, axis=-1))
3782
3783        d = np.arange(3 * 5 * 7 * 11).reshape((3, 5, 7, 11))
3784        np.random.shuffle(d.ravel())
3785        assert_equal(
3786            np.median(d, axis=(0, 1, 2))[0], np.median(d[:, :, :, 0].flatten())
3787        )
3788        assert_equal(
3789            np.median(d, axis=(0, 1, 3))[1], np.median(d[:, :, 1, :].flatten())
3790        )
3791        assert_equal(
3792            np.median(d, axis=(3, 1, -4))[2], np.median(d[:, :, 2, :].flatten())
3793        )
3794        assert_equal(
3795            np.median(d, axis=(3, 1, 2))[2], np.median(d[2, :, :, :].flatten())
3796        )
3797        assert_equal(
3798            np.median(d, axis=(3, 2))[2, 1], np.median(d[2, 1, :, :].flatten())
3799        )
3800        assert_equal(
3801            np.median(d, axis=(1, -2))[2, 1], np.median(d[2, :, :, 1].flatten())
3802        )
3803        assert_equal(
3804            np.median(d, axis=(1, 3))[2, 2], np.median(d[2, :, 2, :].flatten())
3805        )
3806
3807    def test_extended_axis_invalid(self):
3808        d = np.ones((3, 5, 7, 11))
3809        assert_raises(np.AxisError, np.median, d, axis=-5)
3810        assert_raises(np.AxisError, np.median, d, axis=(0, -5))
3811        assert_raises(np.AxisError, np.median, d, axis=4)
3812        assert_raises(np.AxisError, np.median, d, axis=(0, 4))
3813        assert_raises(ValueError, np.median, d, axis=(1, 1))
3814
3815    def test_keepdims(self):
3816        d = np.ones((3, 5, 7, 11))
3817        assert_equal(np.median(d, axis=None, keepdims=True).shape, (1, 1, 1, 1))
3818
3819    @xpassIfTorchDynamo  # (reason="median: tuple axis")
3820    def test_keepdims_2(self):
3821        d = np.ones((3, 5, 7, 11))
3822        assert_equal(np.median(d, axis=(0, 1), keepdims=True).shape, (1, 1, 7, 11))
3823        assert_equal(np.median(d, axis=(0, 3), keepdims=True).shape, (1, 5, 7, 1))
3824        assert_equal(np.median(d, axis=(1,), keepdims=True).shape, (3, 1, 7, 11))
3825        assert_equal(np.median(d, axis=(0, 1, 2, 3), keepdims=True).shape, (1, 1, 1, 1))
3826        assert_equal(np.median(d, axis=(0, 1, 3), keepdims=True).shape, (1, 1, 7, 1))
3827
3828    @skipif(numpy.__version__ < "1.24", reason="NP_VER: fails on NumPy 1.23.x")
3829    @parametrize(
3830        "axis",
3831        [
3832            None,
3833            1,
3834            subtest((1,)),
3835            subtest(
3836                (0, 1),
3837                decorators=[
3838                    skip(reason="Tuple axes"),
3839                ],
3840            ),
3841            subtest(
3842                (-3, -1),
3843                decorators=[
3844                    skip(reason="Tuple axes"),
3845                ],
3846            ),
3847        ],
3848    )
3849    def test_keepdims_out(self, axis):
3850        d = np.ones((3, 5, 7, 11))
3851        if axis is None:
3852            shape_out = (1,) * d.ndim
3853        else:
3854            axis_norm = normalize_axis_tuple(axis, d.ndim)
3855            shape_out = tuple(
3856                1 if i in axis_norm else d.shape[i] for i in range(d.ndim)
3857            )
3858        out = np.empty(shape_out)
3859        result = np.median(d, axis=axis, keepdims=True, out=out)
3860        assert result is out
3861        assert_equal(result.shape, shape_out)
3862
3863
3864@xpassIfTorchDynamo  # (reason="TODO: implement")
3865@instantiate_parametrized_tests
3866class TestSortComplex(TestCase):
3867    @parametrize(
3868        "type_in, type_out",
3869        [
3870            ("l", "D"),
3871            ("h", "F"),
3872            ("H", "F"),
3873            ("b", "F"),
3874            ("B", "F"),
3875            ("g", "G"),
3876        ],
3877    )
3878    def test_sort_real(self, type_in, type_out):
3879        # sort_complex() type casting for real input types
3880        a = np.array([5, 3, 6, 2, 1], dtype=type_in)
3881        actual = np.sort_complex(a)
3882        expected = np.sort(a).astype(type_out)
3883        assert_equal(actual, expected)
3884        assert_equal(actual.dtype, expected.dtype)
3885
3886    def test_sort_complex(self):
3887        # sort_complex() handling of complex input
3888        a = np.array([2 + 3j, 1 - 2j, 1 - 3j, 2 + 1j], dtype="D")
3889        expected = np.array([1 - 3j, 1 - 2j, 2 + 1j, 2 + 3j], dtype="D")
3890        actual = np.sort_complex(a)
3891        assert_equal(actual, expected)
3892        assert_equal(actual.dtype, expected.dtype)
3893
3894
3895if __name__ == "__main__":
3896    run_tests()
3897