Skip to content

Commit 6b55bc0

Browse files
committed
Add more tests to cover function
1 parent 9f930a9 commit 6b55bc0

File tree

3 files changed

+197
-8
lines changed

3 files changed

+197
-8
lines changed

dpnp/dpnp_iface_statistics.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -782,13 +782,17 @@ def cov(
782782
fweights : {None, dpnp.ndarray, usm_ndarray}, optional
783783
1-D array of integer frequency weights; the number of times each
784784
observation vector should be repeated.
785+
It is required that ``fweights >= 0``. However, the function will not
786+
error when ``fweights < 0`` for performance reasons.
785787
786788
Default: ``None``.
787789
aweights : {None, dpnp.ndarray, usm_ndarray}, optional
788790
1-D array of observation vector weights. These relative weights are
789791
typically large for observations considered "important" and smaller for
790792
observations considered less "important". If ``ddof=0`` the array of
791793
weights can be used to assign probabilities to observation vectors.
794+
It is required that ``aweights >= 0``. However, the function will not
795+
error when ``aweights < 0`` for performance reasons.
792796
793797
Default: ``None``.
794798
dtype : data-type, optional
@@ -895,7 +899,7 @@ def cov(
895899
fweights = dpnp.astype(fweights, dtype=def_float)
896900

897901
if aweights is not None:
898-
dpnp.check_supported_arrays_type(fweights)
902+
dpnp.check_supported_arrays_type(aweights)
899903
if aweights.ndim > 1:
900904
raise ValueError("cannot handle multidimensional aweights")
901905

dpnp/dpnp_utils/dpnp_utils_statistics.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,8 +141,7 @@ def _get_2dmin_array(x):
141141
x = dpnp.reshape(x, (1, 1))
142142
elif x.ndim == 1:
143143
x = x[dpnp.newaxis, :]
144-
145-
if not rowvar and x.ndim != 1:
144+
elif not rowvar:
146145
x = x.T
147146

148147
if x.dtype != dtype:

dpnp/tests/test_statistics.py

Lines changed: 191 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from numpy.testing import (
66
assert_allclose,
77
assert_array_equal,
8+
assert_raises,
89
assert_raises_regex,
910
)
1011

@@ -14,7 +15,9 @@
1415
assert_dtype_allclose,
1516
generate_random_numpy_array,
1617
get_all_dtypes,
18+
get_complex_dtypes,
1719
get_float_complex_dtypes,
20+
get_float_dtypes,
1821
has_support_aspect64,
1922
numpy_version,
2023
)
@@ -337,14 +340,197 @@ def test_correlate_unkown_method(self):
337340

338341
class TestCov:
339342
@pytest.mark.parametrize(
340-
"dtype", get_all_dtypes(no_bool=True, no_none=True, no_complex=True)
343+
"dt", get_all_dtypes(no_none=True, no_complex=True)
341344
)
342-
def test_false_rowvar_dtype(self, dtype):
343-
a = numpy.array([[0, 2], [1, 1], [2, 0]], dtype=dtype)
345+
def test_basic(self, dt):
346+
a = numpy.array([[0, 2], [1, 1], [2, 0]], dtype=dt)
344347
ia = dpnp.array(a)
345348

346-
assert_allclose(dpnp.cov(ia.T), dpnp.cov(ia, rowvar=False))
347-
assert_allclose(dpnp.cov(ia, rowvar=False), numpy.cov(a, rowvar=False))
349+
expected = numpy.cov(a.T)
350+
result = dpnp.cov(ia.T)
351+
assert_allclose(result, expected)
352+
353+
@pytest.mark.parametrize("dt", get_complex_dtypes())
354+
def test_complex(self, dt):
355+
a = numpy.array([[1, 2, 3], [1j, 2j, 3j]], dtype=dt)
356+
ia = dpnp.array(a)
357+
358+
expected = numpy.cov(a)
359+
result = dpnp.cov(ia)
360+
assert_allclose(result, expected)
361+
362+
expected = numpy.cov(a, aweights=numpy.ones(3))
363+
result = dpnp.cov(ia, aweights=dpnp.ones(3))
364+
assert_allclose(result, expected)
365+
366+
@pytest.mark.parametrize(
367+
"dt", get_all_dtypes(no_none=True, no_complex=True)
368+
)
369+
@pytest.mark.parametrize("y_dt", get_complex_dtypes())
370+
def test_y(self, dt, y_dt):
371+
a = numpy.array([[1, 2, 3]], dtype=dt)
372+
y = numpy.array([[1j, 2j, 3j]], dtype=y_dt)
373+
ia, iy = dpnp.array(a), dpnp.array(y)
374+
375+
expected = numpy.cov(a, y)
376+
result = dpnp.cov(ia, iy)
377+
assert_allclose(result, expected)
378+
379+
@pytest.mark.filterwarnings("ignore::RuntimeWarning")
380+
@pytest.mark.parametrize("sh", [None, (0, 2), (2, 0)])
381+
def test_empty(self, sh):
382+
a = numpy.array([]).reshape(sh)
383+
ia = dpnp.array(a)
384+
385+
expected = numpy.cov(a)
386+
result = dpnp.cov(ia)
387+
assert_allclose(result, expected)
388+
389+
@pytest.mark.filterwarnings("ignore::RuntimeWarning")
390+
def test_wrong_ddof(self):
391+
a = numpy.array([[0, 2], [1, 1], [2, 0]])
392+
ia = dpnp.array(a)
393+
394+
expected = numpy.cov(a.T, ddof=5)
395+
result = dpnp.cov(ia.T, ddof=5)
396+
assert_allclose(result, expected)
397+
398+
@pytest.mark.parametrize("dt", get_float_dtypes())
399+
@pytest.mark.parametrize("rowvar", [True, False])
400+
def test_1D_rowvar(self, dt, rowvar):
401+
a = numpy.array([0.3942, 0.5969, 0.7730, 0.9918, 0.7964], dtype=dt)
402+
y = numpy.array([0.0780, 0.3107, 0.2111, 0.0334, 0.8501])
403+
ia, iy = dpnp.array(a), dpnp.array(y)
404+
405+
expected = numpy.cov(a, rowvar=rowvar)
406+
result = dpnp.cov(ia, rowvar=rowvar)
407+
assert_allclose(result, expected)
408+
409+
expected = numpy.cov(a, y, rowvar=rowvar)
410+
result = dpnp.cov(ia, iy, rowvar=rowvar)
411+
assert_allclose(result, expected)
412+
413+
def test_1D_variance(self):
414+
a = numpy.array([0.3942, 0.5969, 0.7730, 0.9918, 0.7964])
415+
ia = dpnp.array(a)
416+
417+
expected = numpy.cov(a, ddof=1)
418+
result = dpnp.cov(ia, ddof=1)
419+
assert_allclose(result, expected)
420+
421+
@pytest.mark.parametrize("freq_data", [[1, 4, 1], [1, 1, 1]])
422+
def test_fweights(self, freq_data):
423+
a = numpy.array([0.0, 1.0, 2.0], ndmin=2)
424+
freq = numpy.array(freq_data)
425+
ia, ifreq = dpnp.array(a), dpnp.array(freq_data)
426+
427+
expected = numpy.cov(a, fweights=freq)
428+
result = dpnp.cov(ia, fweights=ifreq)
429+
assert_allclose(result, expected)
430+
431+
a = numpy.array([[0, 2], [1, 1], [2, 0]])
432+
ia = dpnp.array(a)
433+
434+
expected = numpy.cov(a.T, fweights=freq)
435+
result = dpnp.cov(ia.T, fweights=ifreq)
436+
assert_allclose(result, expected)
437+
438+
@pytest.mark.parametrize("xp", [dpnp, numpy])
439+
def test_float_fweights(self, xp):
440+
a = xp.array([[0, 2], [1, 1], [2, 0]])
441+
freq = xp.array([1, 4, 1]) + 0.5
442+
assert_raises(TypeError, xp.cov, a, fweights=freq)
443+
444+
@pytest.mark.parametrize("xp", [dpnp, numpy])
445+
@pytest.mark.parametrize("sh", [(2, 3), 2])
446+
def test_fweights_wrong_shapes(self, xp, sh):
447+
a = xp.array([[0, 2], [1, 1], [2, 0]])
448+
freq = xp.ones(sh, dtype=xp.int_)
449+
assert_raises((ValueError, RuntimeError), xp.cov, a.T, fweights=freq)
450+
451+
@pytest.mark.parametrize("freq", [numpy.array([1, 4, 1]), 2])
452+
def test_fweights_wrong_type(self, freq):
453+
a = dpnp.array([[0, 2], [1, 1], [2, 0]]).T
454+
assert_raises(TypeError, dpnp.cov, a, fweights=freq)
455+
456+
@pytest.mark.parametrize("weights_data", [[1.0, 4.0, 1.0], [1.0, 1.0, 1.0]])
457+
def test_aweights(self, weights_data):
458+
a = numpy.array([[0, 2], [1, 1], [2, 0]])
459+
weights = numpy.array(weights_data)
460+
ia, iweights = dpnp.array(a), dpnp.array(weights_data)
461+
462+
expected = numpy.cov(a.T, aweights=weights)
463+
result = dpnp.cov(ia.T, aweights=iweights)
464+
assert_allclose(result, expected)
465+
466+
expected = numpy.cov(a.T, aweights=3.0 * weights)
467+
result = dpnp.cov(ia.T, aweights=3.0 * iweights)
468+
assert_allclose(result, expected)
469+
470+
@pytest.mark.parametrize("xp", [dpnp, numpy])
471+
@pytest.mark.parametrize("sh", [(2, 3), 2])
472+
def test_aweights_wrong_shapes(self, xp, sh):
473+
a = xp.array([[0, 2], [1, 1], [2, 0]])
474+
weights = xp.ones(sh)
475+
assert_raises((ValueError, RuntimeError), xp.cov, a.T, aweights=weights)
476+
477+
@pytest.mark.parametrize("weights", [numpy.array([1.0, 4.0, 1.0]), 2.0])
478+
def test_aweights_wrong_type(self, weights):
479+
a = dpnp.array([[0, 2], [1, 1], [2, 0]]).T
480+
assert_raises(TypeError, dpnp.cov, a, aweights=weights)
481+
482+
def test_unit_fweights_and_aweights(self):
483+
a = numpy.array([0.0, 1.0, 2.0], ndmin=2)
484+
freq = numpy.array([1, 4, 1])
485+
weights = numpy.ones(3)
486+
ia, ifreq, iweights = (
487+
dpnp.array(a),
488+
dpnp.array(freq),
489+
dpnp.array(weights),
490+
)
491+
492+
# unit weights
493+
expected = numpy.cov(a, fweights=freq, aweights=weights)
494+
result = dpnp.cov(ia, fweights=ifreq, aweights=iweights)
495+
assert_allclose(result, expected)
496+
497+
a = numpy.array([[0, 2], [1, 1], [2, 0]])
498+
ia = dpnp.array(a)
499+
500+
# unit weights
501+
expected = numpy.cov(a.T, fweights=freq, aweights=weights)
502+
result = dpnp.cov(ia.T, fweights=ifreq, aweights=iweights)
503+
assert_allclose(result, expected)
504+
505+
freq = numpy.ones(3, dtype=numpy.int_)
506+
ifreq = dpnp.array(freq)
507+
508+
# unit frequencies and weights
509+
expected = numpy.cov(a.T, fweights=freq, aweights=weights)
510+
result = dpnp.cov(ia.T, fweights=ifreq, aweights=iweights)
511+
assert_allclose(result, expected)
512+
513+
weights = numpy.array([1.0, 4.0, 1.0])
514+
iweights = dpnp.array(weights)
515+
516+
# unit frequencies
517+
expected = numpy.cov(a.T, fweights=freq, aweights=weights)
518+
result = dpnp.cov(ia.T, fweights=ifreq, aweights=iweights)
519+
assert_allclose(result, expected)
520+
521+
expected = numpy.cov(a.T, fweights=freq, aweights=3.0 * weights)
522+
result = dpnp.cov(ia.T, fweights=ifreq, aweights=3.0 * iweights)
523+
assert_allclose(result, expected)
524+
525+
@pytest.mark.parametrize("dt", get_float_complex_dtypes())
526+
def test_dtype(self, dt):
527+
a = numpy.array([[0, 2], [1, 1], [2, 0]])
528+
ia = dpnp.array(a)
529+
530+
expected = numpy.cov(a.T, dtype=dt)
531+
result = dpnp.cov(ia.T, dtype=dt)
532+
assert_allclose(result, expected)
533+
assert result.dtype == dt
348534

349535
# numpy 2.2 properly transposes 2d array when rowvar=False
350536
@with_requires("numpy>=2.2")

0 commit comments

Comments
 (0)