diff --git a/dpnp/dpnp_iface_manipulation.py b/dpnp/dpnp_iface_manipulation.py index f67cc67cfcb..3d1aa7b0f0c 100644 --- a/dpnp/dpnp_iface_manipulation.py +++ b/dpnp/dpnp_iface_manipulation.py @@ -1548,20 +1548,61 @@ def unique(ar, **kwargs): return call_origin(numpy.unique, ar, **kwargs) -def vstack(tup): +def vstack(tup, *, dtype=None, casting="same_kind"): """ Stack arrays in sequence vertically (row wise). For full documentation refer to :obj:`numpy.vstack`. - """ + Returns + ------- + out : dpnp.ndarray + The array formed by stacking the given arrays, will be at least 2-D. + + Limitations + ----------- + Each array in `tup` is supported as either :class:`dpnp.ndarray` + or :class:`dpctl.tensor.usm_ndarray`. Otherwise ``TypeError`` exception + will be raised. + Parameters `dtype` and `casting` are supported with default value. + Otherwise the function will be executed sequentially on CPU. - # TODO: - # `call_origin` cannot convert sequence of array to sequence of - # nparray - tup_new = [] - for tp in tup: - tpx = dpnp.asnumpy(tp) if not isinstance(tp, numpy.ndarray) else tp - tup_new.append(tpx) + See Also + -------- + :obj:`dpnp.concatenate` : Join a sequence of arrays along an existing axis. + :obj:`dpnp.stack` : Join a sequence of arrays along a new axis. + :obj:`dpnp.hstack` : Stack arrays in sequence horizontally (column wise). + :obj:`dpnp.dstack` : Stack arrays in sequence depth wise (along third axis). + :obj:`dpnp.column_stack` : Stack 1-D arrays as columns into a 2-D array. + :obj:`dpnp.block` : Assemble an nd-array from nested lists of blocks. + :obj:`dpnp.split` : Split array into a list of multiple sub-arrays of equal size. - return call_origin(numpy.vstack, tup_new) + Examples + -------- + >>> import dpnp as np + >>> a = np.array([1, 2, 3]) + >>> b = np.array([4, 5, 6]) + >>> np.vstack((a, b)) + array([[1, 2, 3], + [4, 5, 6]]) + + >>> a = np.array([[1], [2], [3]]) + >>> b = np.array([[4], [5], [6]]) + >>> np.vstack((a, b)) + array([[1], + [2], + [3], + [4], + [5], + [6]]) + + """ + + if not hasattr(tup, "__getitem__"): + raise TypeError( + "Arrays to stack must be passed as a sequence type such as list or tuple." + ) + arrs = dpnp.atleast_2d(*tup) + if not isinstance(arrs, list): + arrs = [arrs] + return dpnp.concatenate(arrs, axis=0, dtype=dtype, casting=casting) diff --git a/tests/skipped_tests.tbl b/tests/skipped_tests.tbl index cc7ae4cdb63..6191dc6b962 100644 --- a/tests/skipped_tests.tbl +++ b/tests/skipped_tests.tbl @@ -34,8 +34,6 @@ tests/third_party/cupy/fft_tests/test_fft.py::TestFftn_param_23_{axes=None, norm tests/third_party/intel/test_zero_copy_test1.py::test_dpnp_interaction_with_dpctl_memory -tests/test_arraymanipulation.py::TestVstack::test_generator - tests/test_linalg.py::test_cond[-1-[[1, 2, 3], [4, 5, 6], [7, 8, 9]]] tests/test_linalg.py::test_cond[1-[[1, 2, 3], [4, 5, 6], [7, 8, 9]]] tests/test_linalg.py::test_cond[-2-[[1, 0, -1], [0, 1, 0], [1, 0, 1]]] @@ -450,7 +448,6 @@ tests/third_party/cupy/manipulation_tests/test_dims.py::TestBroadcast_param_8_{s tests/third_party/cupy/manipulation_tests/test_dims.py::TestBroadcast_param_8_{shapes=[(2, 0, 1, 1, 3), (2, 1, 0, 0, 3)]}::test_broadcast_arrays tests/third_party/cupy/manipulation_tests/test_dims.py::TestBroadcast_param_9_{shapes=[(0, 1, 1, 3), (2, 1, 0, 0, 3)]}::test_broadcast tests/third_party/cupy/manipulation_tests/test_dims.py::TestBroadcast_param_9_{shapes=[(0, 1, 1, 3), (2, 1, 0, 0, 3)]}::test_broadcast_arrays - tests/third_party/cupy/manipulation_tests/test_dims.py::TestInvalidBroadcast_param_0_{shapes=[(3,), (2,)]}::test_invalid_broadcast tests/third_party/cupy/manipulation_tests/test_dims.py::TestInvalidBroadcast_param_0_{shapes=[(3,), (2,)]}::test_invalid_broadcast_arrays tests/third_party/cupy/manipulation_tests/test_dims.py::TestInvalidBroadcast_param_1_{shapes=[(3, 2), (2, 3)]}::test_invalid_broadcast @@ -459,6 +456,7 @@ tests/third_party/cupy/manipulation_tests/test_dims.py::TestInvalidBroadcast_par tests/third_party/cupy/manipulation_tests/test_dims.py::TestInvalidBroadcast_param_2_{shapes=[(3, 2), (3, 4)]}::test_invalid_broadcast_arrays tests/third_party/cupy/manipulation_tests/test_dims.py::TestInvalidBroadcast_param_3_{shapes=[(0,), (2,)]}::test_invalid_broadcast tests/third_party/cupy/manipulation_tests/test_dims.py::TestInvalidBroadcast_param_3_{shapes=[(0,), (2,)]}::test_invalid_broadcast_arrays + tests/third_party/cupy/manipulation_tests/test_shape.py::TestRavel::test_ravel2 tests/third_party/cupy/manipulation_tests/test_shape.py::TestRavel::test_ravel3 tests/third_party/cupy/manipulation_tests/test_shape.py::TestRavel::test_external_ravel diff --git a/tests/skipped_tests_gpu.tbl b/tests/skipped_tests_gpu.tbl index 6a105b50cba..bf2aca12f56 100644 --- a/tests/skipped_tests_gpu.tbl +++ b/tests/skipped_tests_gpu.tbl @@ -210,7 +210,6 @@ tests/third_party/cupy/random_tests/test_distributions.py::TestDistributionsMult tests/third_party/cupy/random_tests/test_distributions.py::TestDistributionsMultivariateNormal_param_3_{d=4, shape=(3, 2)}::test_normal tests/third_party/intel/test_zero_copy_test1.py::test_dpnp_interaction_with_dpctl_memory -tests/test_arraymanipulation.py::TestVstack::test_generator tests/test_linalg.py::test_cond[-1-[[1, 2, 3], [4, 5, 6], [7, 8, 9]]] tests/test_linalg.py::test_cond[1-[[1, 2, 3], [4, 5, 6], [7, 8, 9]]] diff --git a/tests/test_arraymanipulation.py b/tests/test_arraymanipulation.py index efbb930661e..e08fe466068 100644 --- a/tests/test_arraymanipulation.py +++ b/tests/test_arraymanipulation.py @@ -583,11 +583,9 @@ class TestVstack: def test_non_iterable(self): assert_raises(TypeError, dpnp.vstack, 1) - @pytest.mark.usefixtures("allow_fall_back_on_numpy") def test_empty_input(self): - assert_raises(ValueError, dpnp.vstack, ()) + assert_raises(TypeError, dpnp.vstack, ()) - @pytest.mark.usefixtures("allow_fall_back_on_numpy") def test_0D_array(self): a = dpnp.array(1) b = dpnp.array(2) @@ -595,7 +593,6 @@ def test_0D_array(self): desired = dpnp.array([[1], [2]]) assert_array_equal(res, desired) - @pytest.mark.usefixtures("allow_fall_back_on_numpy") def test_1D_array(self): a = dpnp.array([1]) b = dpnp.array([2]) @@ -603,7 +600,6 @@ def test_1D_array(self): desired = dpnp.array([[1], [2]]) assert_array_equal(res, desired) - @pytest.mark.usefixtures("allow_fall_back_on_numpy") def test_2D_array(self): a = dpnp.array([[1], [2]]) b = dpnp.array([[1], [2]]) @@ -611,7 +607,6 @@ def test_2D_array(self): desired = dpnp.array([[1], [2], [1], [2]]) assert_array_equal(res, desired) - @pytest.mark.usefixtures("allow_fall_back_on_numpy") def test_2D_array2(self): a = dpnp.array([1, 2]) b = dpnp.array([1, 2]) @@ -620,8 +615,8 @@ def test_2D_array2(self): assert_array_equal(res, desired) def test_generator(self): - with assert_warns(FutureWarning): - dpnp.vstack((numpy.arange(3) for _ in range(2))) + with pytest.raises(TypeError): + dpnp.vstack((dpnp.arange(3) for _ in range(2))) class TestAtleast1d: diff --git a/tests/third_party/cupy/manipulation_tests/test_join.py b/tests/third_party/cupy/manipulation_tests/test_join.py index 8bffce98d87..e82258b84a5 100644 --- a/tests/third_party/cupy/manipulation_tests/test_join.py +++ b/tests/third_party/cupy/manipulation_tests/test_join.py @@ -312,27 +312,24 @@ def test_hstack_casting(self, xp, dtype1, dtype2, casting): # may raise TypeError or ComplexWarning return xp.hstack((a, b), dtype=dtype2, casting=casting) - @pytest.mark.skip("dpnp.vstack() is not implemented yet") @testing.numpy_cupy_array_equal() def test_vstack_vectors(self, xp): a = xp.arange(3) b = xp.arange(2, -1, -1) return xp.vstack((a, b)) - @pytest.mark.skip("dpnp.vstack() is not implemented yet") @testing.numpy_cupy_array_equal() def test_vstack_single_element(self, xp): a = xp.arange(3) return xp.vstack((a,)) - @pytest.mark.skip("dpnp.vstack() is not implemented yet") def test_vstack_wrong_ndim(self): a = cupy.empty((3,)) b = cupy.empty((3, 1)) with pytest.raises(ValueError): cupy.vstack((a, b)) - @pytest.mark.skip("dpnp.vstack() is not implemented yet") + @pytest.mark.usefixtures("allow_fall_back_on_numpy") @testing.with_requires("numpy>=1.24.0") @testing.for_all_dtypes_combination(names=["dtype1", "dtype2"]) @testing.numpy_cupy_array_equal(accept_error=TypeError) @@ -341,18 +338,9 @@ def test_vstack_dtype(self, xp, dtype1, dtype2): b = testing.shaped_arange((3, 4), xp, dtype1) return xp.vstack((a, b), dtype=dtype2) - @pytest.mark.skip("dpnp.vstack() is not implemented yet") + @pytest.mark.usefixtures("allow_fall_back_on_numpy") @testing.with_requires("numpy>=1.24.0") - @pytest.mark.parametrize( - "casting", - [ - "no", - "equiv", - "safe", - "same_kind", - "unsafe", - ], - ) + @testing.for_castings() @testing.for_all_dtypes_combination(names=["dtype1", "dtype2"]) @testing.numpy_cupy_array_equal( accept_error=(TypeError, numpy.ComplexWarning)