Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pytest.ini
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ testpaths =
tests/numpy/dtypes_test.py
tests/numpy/err_test.py
tests/numpy/manipulation_functions_test.py
tests/numpy/alignment_verification/manipulation_functions_alignment.py
tests/numpy/alignment_verification/operators_alignment.py
tests/numpy/numeric_test.py
tests/numpy/numpy_test.py
Expand Down
241 changes: 241 additions & 0 deletions tests/numpy/alignment_verification/manipulation_functions_alignment.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,241 @@
import numpy as np
import pytest

import arkouda as ak

from arkouda.numpy.manipulation_functions import flip, repeat, squeeze, tile


@pytest.mark.skip_if_rank_not_compiled([2, 3])
@pytest.mark.parametrize(
"shape",
[
(0,),
(1,),
(5,),
(2, 3),
(3, 1, 4),
],
)
def test_flip_matches_numpy_axis_none(shape):
# NumPy uses views when possible; Arkouda copies. Values must match.
np_a = np.arange(np.prod(shape), dtype=np.int64).reshape(shape)
ak_a = ak.array(np_a)

got = flip(ak_a, axis=None).to_ndarray()
exp = np.flip(np_a, axis=None)

assert np.array_equal(got, exp)


@pytest.mark.skip_if_rank_not_compiled([2, 3])
@pytest.mark.parametrize(
"shape,axis",
[
((5,), 0),
((2, 3), 0),
((2, 3), 1),
((3, 1, 4), 0),
((3, 1, 4), 2),
],
)
def test_flip_matches_numpy_single_axis(shape, axis):
np_a = np.arange(np.prod(shape), dtype=np.int64).reshape(shape)
ak_a = ak.array(np_a)

got = flip(ak_a, axis=axis).to_ndarray()
exp = np.flip(np_a, axis=axis)

assert np.array_equal(got, exp)


@pytest.mark.skip_if_rank_not_compiled([2, 3])
@pytest.mark.parametrize(
"shape,axes",
[
((2, 3), (0, 1)),
((3, 1, 4), (0, 2)),
],
)
def test_flip_matches_numpy_multi_axis(shape, axes):
np_a = np.arange(np.prod(shape), dtype=np.int64).reshape(shape)
ak_a = ak.array(np_a)

got = flip(ak_a, axis=axes).to_ndarray()
exp = np.flip(np_a, axis=axes)

assert np.array_equal(got, exp)


@pytest.mark.skip_if_rank_not_compiled([2, 3])
@pytest.mark.parametrize(
"a,reps",
[
([1, 2, 3], 0),
([1, 2, 3], 1),
([1, 2, 3], 2),
([1, 2, 3], [1, 2, 1]),
([1, 2, 3, 4], [2, 0, 1, 3]),
],
)
def test_repeat_matches_numpy_axis_none(a, reps):
np_a = np.array(a, dtype=np.int64)
ak_a = ak.array(np_a)

got = repeat(ak_a, reps, axis=None).to_ndarray()
exp = np.repeat(np_a, reps, axis=None)

assert np.array_equal(got, exp)


@pytest.mark.skip_if_rank_not_compiled([2, 3])
@pytest.mark.parametrize(
"shape,axis,reps",
[
((2, 3), 0, 2), # scalar reps broadcast along axis
((2, 3), 1, 3),
((2, 3), 0, [1, 2]), # per-row repeats
((2, 3), 1, [1, 0, 2]), # per-col repeats (including 0)
((3, 1, 4), 1, 2), # axis with size-1
((3, 1, 4), 1, [0]), # size-1 axis, list length 1 ok (constant-like)
],
)
def test_repeat_matches_numpy_axis_int(shape, axis, reps):
np_a = np.arange(np.prod(shape), dtype=np.int64).reshape(shape)
ak_a = ak.array(np_a)

got = repeat(ak_a, reps, axis=axis).to_ndarray()
exp = np.repeat(np_a, reps, axis=axis)

assert np.array_equal(got, exp)
assert got.shape == exp.shape


@pytest.mark.skip_if_rank_not_compiled([2, 3])
@pytest.mark.parametrize(
"shape,axis",
[
((2, 3), 2),
((2, 3), -3),
((3, 1, 4), 3),
],
)
def test_repeat_axis_out_of_range_raises(shape, axis):
np_a = np.arange(np.prod(shape), dtype=np.int64).reshape(shape)
ak_a = ak.array(np_a)

with pytest.raises(IndexError):
repeat(ak_a, 2, axis=axis)


def test_repeat_negative_repeats_raises_valueerror():
ak_a = ak.array(np.array([1, 2, 3], dtype=np.int64))

with pytest.raises(ValueError):
repeat(ak_a, [-1, 1, 1], axis=None)

# NumPy also raises for negative repeats
with pytest.raises(ValueError):
np.repeat(np.array([1, 2, 3]), [-1, 1, 1])


@pytest.mark.skip_if_rank_not_compiled([2])
def test_repeat_repeats_ndim_gt_1_raises_valueerror():
ak_a = ak.array(np.array([1, 2, 3], dtype=np.int64))
ak_reps = ak.array(np.array([[1, 2, 3]], dtype=np.int64)) # ndim=2

with pytest.raises(ValueError):
repeat(ak_a, ak_reps, axis=None)


@pytest.mark.skip_if_rank_not_compiled([2])
def test_repeat_repeats_size_mismatch_axis_raises_valueerror():
np_a = np.arange(6, dtype=np.int64).reshape(2, 3)
ak_a = ak.array(np_a)

# axis=1 requires repeats length 3 or scalar; length 2 should fail
with pytest.raises(ValueError):
repeat(ak_a, [1, 2], axis=1)

# NumPy also errors for mismatch
with pytest.raises(ValueError):
np.repeat(np_a, [1, 2], axis=1)


@pytest.mark.skip_if_rank_not_compiled([2, 3])
@pytest.mark.parametrize(
"shape,axis",
[
((1, 10, 1), None),
((1, 10, 1), 0),
((1, 10, 1), 2),
],
)
def test_squeeze_matches_numpy(shape, axis):
np_a = np.arange(np.prod(shape), dtype=np.int64).reshape(shape)
ak_a = ak.array(np_a)

got = squeeze(ak_a, axis=axis).to_ndarray()
exp = np.squeeze(np_a, axis=axis)

assert np.array_equal(got, exp)
assert got.shape == exp.shape


@pytest.mark.skip_if_rank_not_compiled([2, 3])
@pytest.mark.parametrize(
"shape,axis",
[
((2, 3), 0), # axis=0 is not size-1
((2, 1, 3), 0),
((2, 1, 3), 2),
((1, 2), 1), # axis=1 is not size-1
],
)
def test_squeeze_invalid_axis_raises_like_numpy(shape, axis):
np_a = np.arange(np.prod(shape), dtype=np.int64).reshape(shape)
ak_a = ak.array(np_a)

# NumPy raises ValueError if a selected axis is not of size 1
with pytest.raises(ValueError):
np.squeeze(np_a, axis=axis)

# Arkouda implementation should also reject (server may raise -> ValueError here)
with pytest.raises(ValueError):
squeeze(ak_a, axis=axis)


@pytest.mark.skip_if_rank_not_compiled([2, 3])
@pytest.mark.parametrize(
"shape,reps",
[
((3,), 2),
((3,), (2, 2)),
((3,), (2, 1, 2)),
((2, 2), 2),
((2, 2), (2, 1)),
((4,), (4, 1)),
((2, 3, 1), (1, 2, 3)),
],
)
def test_tile_matches_numpy(shape, reps):
np_a = np.arange(np.prod(shape), dtype=np.int64).reshape(shape)
ak_a = ak.array(np_a)

got = tile(ak_a, reps).to_ndarray()
exp = np.tile(np_a, reps)

assert np.array_equal(got, exp)
assert got.shape == exp.shape


@pytest.mark.skip_if_rank_not_compiled([2])
def test_tile_accepts_list_reps_like_numpy():
np_a = np.array([1, 2, 3], dtype=np.int64)
ak_a = ak.array(np_a)

got = tile(ak_a, [2, 2]).to_ndarray()
exp = np.tile(np_a, [2, 2])

assert np.array_equal(got, exp)
assert got.shape == exp.shape