Skip to content

Commit 7ab7858

Browse files
AzeezIshsyurkevi
AzeezIsh
authored andcommitted
Wrapped up multiplication/divison unit tests, ensured that all cases were covered and currently exploring division by 0 case
1 parent 4058f86 commit 7ab7858

File tree

1 file changed

+266
-0
lines changed

1 file changed

+266
-0
lines changed

tests/test_muldiv.py

+266
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,266 @@
1+
import numpy as np
2+
import pytest
3+
4+
import arrayfire_wrapper.dtypes as dtype
5+
import arrayfire_wrapper.lib as wrapper
6+
import arrayfire_wrapper.lib.mathematical_functions as ops
7+
from arrayfire_wrapper.lib.create_and_modify_array.helper_functions import array_to_string
8+
9+
10+
import random
11+
12+
dtype_map = {
13+
'int16': dtype.s16,
14+
'int32': dtype.s32,
15+
'int64': dtype.s64,
16+
'uint8': dtype.u8,
17+
'uint16': dtype.u16,
18+
'uint32': dtype.u32,
19+
'uint64': dtype.u64,
20+
'float16': dtype.f16,
21+
'float32': dtype.f32,
22+
# 'float64': dtype.f64,
23+
# 'complex64': dtype.c64,
24+
'complex32': dtype.c32,
25+
'bool': dtype.b8,
26+
's16': dtype.s16,
27+
's32': dtype.s32,
28+
's64': dtype.s64,
29+
'u8': dtype.u8,
30+
'u16': dtype.u16,
31+
'u32': dtype.u32,
32+
'u64': dtype.u64,
33+
'f16': dtype.f16,
34+
'f32': dtype.f32,
35+
# 'f64': dtype.f64,
36+
'c32': dtype.c32,
37+
# 'c64': dtype.c64,
38+
'b8': dtype.b8,
39+
}
40+
41+
@pytest.mark.parametrize(
42+
"shape",
43+
[
44+
(),
45+
(random.randint(1, 10), ),
46+
(random.randint(1, 10), random.randint(1, 10)),
47+
(random.randint(1, 10), random.randint(1, 10), random.randint(1, 10)),
48+
(random.randint(1, 10), random.randint(1, 10), random.randint(1, 10), random.randint(1, 10)),
49+
],
50+
)
51+
def test_multiply_shapes(shape: tuple) -> None:
52+
"""Test multiplication operation between two arrays of the same shape"""
53+
lhs = wrapper.randu(shape, dtype.f16)
54+
rhs = wrapper.randu(shape, dtype.f16)
55+
56+
result = wrapper.mul(lhs, rhs)
57+
58+
assert wrapper.get_dims(result)[0 : len(shape)] == shape
59+
60+
def test_multiply_different_shapes() -> None:
61+
"""Test if multiplication handles arrays of different shapes"""
62+
with pytest.raises(RuntimeError):
63+
lhs_shape = (2, 3)
64+
rhs_shape = (3, 2)
65+
dtypes = dtype.f16
66+
lhs = wrapper.randu(lhs_shape, dtypes)
67+
rhs = wrapper.randu(rhs_shape, dtypes)
68+
result = wrapper.mul(lhs, rhs)
69+
expected_shape = np.broadcast(np.empty(lhs), np.empty(rhs)).shape
70+
assert wrapper.get_dims(result)[0 : len(expected_shape)] == expected_shape, f"Failed for shapes {lhs_shape} and {rhs_shape}"
71+
72+
def test_multiply_negative_shapes() -> None:
73+
"""Test if multiplication handles arrays of negative shapes"""
74+
with pytest.raises(RuntimeError):
75+
lhs_shape = (2, -2)
76+
rhs_shape = (-2, 2)
77+
dtypes = dtype.f16
78+
lhs = wrapper.randu(lhs_shape, dtypes)
79+
rhs = wrapper.randu(rhs_shape, dtypes)
80+
result = wrapper.mul(lhs, rhs)
81+
expected_shape = np.broadcast(np.empty(lhs), np.empty(rhs)).shape
82+
assert wrapper.get_dims(result)[0 : len(expected_shape)] == expected_shape, f"Failed for shapes {lhs_shape} and {rhs_shape}"
83+
84+
@pytest.mark.parametrize("dtype_name", dtype_map.values())
85+
def test_multiply_supported_dtypes(dtype_name: str) -> None:
86+
"""Test multiplication operation across all supported data types."""
87+
shape = (5, 5)
88+
lhs = wrapper.randu(shape, dtype_name)
89+
rhs = wrapper.randu(shape, dtype_name)
90+
result = wrapper.mul(lhs, rhs)
91+
assert dtype.c_api_value_to_dtype(wrapper.get_type(result)) == dtype_name, f"Failed for dtype: {dtype_name}"
92+
93+
@pytest.mark.parametrize(
94+
"invdtypes",
95+
[
96+
dtype.c64,
97+
dtype.f64,
98+
],
99+
)
100+
def test_multiply_unsupported_dtypes(invdtypes: dtype.Dtype) -> None:
101+
"""Test multiplication operation for unsupported data types."""
102+
with pytest.raises(RuntimeError):
103+
shape = (5, 5)
104+
lhs = wrapper.randu(shape, invdtypes)
105+
rhs = wrapper.randu(shape, invdtypes)
106+
wrapper.mul(lhs, rhs)
107+
108+
def test_multiply_zero_sized_arrays() -> None:
109+
"""Test multiplication with arrays where at least one array has zero size."""
110+
with pytest.raises(RuntimeError):
111+
zero_shape = (0, 5)
112+
normal_shape = (5, 5)
113+
zero_array = wrapper.randu(zero_shape, dtype.f32)
114+
normal_array = wrapper.randu(normal_shape, dtype.f32)
115+
116+
result_rhs_zero = wrapper.mul(normal_array, zero_array)
117+
assert wrapper.get_dims(result_rhs_zero) == normal_shape
118+
119+
result_lhs_zero = wrapper.mul(zero_array, normal_array)
120+
assert wrapper.get_dims(result_lhs_zero) == zero_shape
121+
122+
@pytest.mark.parametrize(
123+
"shape_a, shape_b",
124+
[
125+
((1, 5), (5, 1)), # 2D with 2D inverse
126+
((5, 5), (5, 1)), # 2D with 2D
127+
((5, 5), (1, 1)), # 2D with 2D
128+
((1, 1, 1), (5, 5, 5)), # 3D with 3D
129+
((5,), (5,)), # 1D with 1D broadcast
130+
],
131+
)
132+
def test_multiply_varying_dimensionality(shape_a: tuple, shape_b: tuple) -> None:
133+
"""Test multiplication with arrays of varying dimensionality."""
134+
lhs = wrapper.randu(shape_a, dtype.f32)
135+
rhs = wrapper.randu(shape_b, dtype.f32)
136+
137+
result = wrapper.mul(lhs, rhs)
138+
expected_shape = np.broadcast(np.empty(shape_a), np.empty(shape_b)).shape
139+
assert wrapper.get_dims(result)[0 : len(expected_shape)] == expected_shape, f"Failed for shapes {shape_a} and {shape_b}"
140+
141+
@pytest.mark.parametrize(
142+
"shape",
143+
[
144+
(),
145+
(random.randint(1, 10), ),
146+
(random.randint(1, 10), random.randint(1, 10)),
147+
(random.randint(1, 10), random.randint(1, 10), random.randint(1, 10)),
148+
(random.randint(1, 10), random.randint(1, 10), random.randint(1, 10), random.randint(1, 10)),
149+
],
150+
)
151+
def test_divide_shapes(shape: tuple) -> None:
152+
"""Test division operation between two arrays of the same shape"""
153+
lhs = wrapper.randu(shape, dtype.f16)
154+
rhs = wrapper.randu(shape, dtype.f16)
155+
# Ensure no division by zero for test integrity
156+
rhs = wrapper.add(rhs, wrapper.constant(0.001, shape, dtype.f16))
157+
158+
result = wrapper.div(lhs, rhs)
159+
160+
assert wrapper.get_dims(result)[0 : len(shape)] == shape
161+
162+
def test_divide_different_shapes() -> None:
163+
"""Test if division handles arrays of different shapes"""
164+
with pytest.raises(RuntimeError):
165+
lhs_shape = (2, 3)
166+
rhs_shape = (3, 2)
167+
dtypes = dtype.f16
168+
lhs = wrapper.randu(lhs_shape, dtypes)
169+
rhs = wrapper.randu(rhs_shape, dtypes)
170+
result = wrapper.div(lhs, rhs)
171+
expected_shape = np.broadcast(np.empty(lhs_shape), np.empty(rhs_shape)).shape
172+
assert wrapper.get_dims(result)[0 : len(expected_shape)] == expected_shape, f"Failed for shapes {lhs_shape} and {rhs_shape}"
173+
174+
def test_divide_negative_shapes() -> None:
175+
"""Test if division handles arrays of negative shapes"""
176+
with pytest.raises(RuntimeError):
177+
lhs_shape = (2, -2)
178+
rhs_shape = (-2, 2)
179+
dtypes = dtype.f16
180+
lhs = wrapper.randu(lhs_shape, dtypes)
181+
rhs = wrapper.randu(rhs_shape, dtypes)
182+
result = wrapper.div(lhs, rhs)
183+
expected_shape = np.broadcast(np.empty(lhs_shape), np.empty(rhs_shape)).shape
184+
assert wrapper.get_dims(result)[0 : len(expected_shape)] == expected_shape, f"Failed for shapes {lhs_shape} and {rhs_shape}"
185+
186+
@pytest.mark.parametrize("dtype_name", dtype_map.values())
187+
def test_divide_supported_dtypes(dtype_name: str) -> None:
188+
"""Test division operation across all supported data types."""
189+
shape = (5, 5)
190+
lhs = wrapper.randu(shape, dtype_name)
191+
rhs = wrapper.randu(shape, dtype_name)
192+
# Ensure no division by zero for test integrity
193+
rhs = wrapper.add(rhs, wrapper.constant(0.001, shape, dtype_name))
194+
195+
result = wrapper.div(lhs, rhs)
196+
assert dtype.c_api_value_to_dtype(wrapper.get_type(result)) == dtype_name, f"Failed for dtype: {dtype_name}"
197+
198+
def test_divide_by0() -> None:
199+
"""Test division operation for undefined error type."""
200+
shape = (2, 2)
201+
lhs = wrapper.constant(5, shape, dtype.f16)
202+
rhs = wrapper.constant(0, shape, dtype.f16)
203+
lhsnp = np.full(shape, 5)
204+
rhsnp = np.zeros(shape)
205+
out = np.divide(lhsnp, rhsnp)
206+
print(out)
207+
with pytest.raises(RuntimeError):
208+
divOut = wrapper.div(lhs, rhs)
209+
print(array_to_string("", divOut, 3, False))
210+
wrapper.div(lhs, rhs)
211+
212+
# result = wrapper.div(lhs, rhs)
213+
# assert dtype.c_api_value_to_dtype(wrapper.get_type(result)) == dtype_name, f"Failed for dtype: {dtype_name}"
214+
215+
@pytest.mark.parametrize(
216+
"invdtypes",
217+
[
218+
dtype.c64,
219+
dtype.f64,
220+
],
221+
)
222+
def test_divide_unsupported_dtypes(invdtypes: dtype.Dtype) -> None:
223+
"""Test division operation for unsupported data types."""
224+
with pytest.raises(RuntimeError):
225+
shape = (5, 5)
226+
lhs = wrapper.randu(shape, invdtypes)
227+
rhs = wrapper.randu(shape, invdtypes)
228+
# Prevent division by zero in unsupported dtype test
229+
rhs = wrapper.add(rhs, wrapper.constant(0.001, shape, invdtypes))
230+
231+
wrapper.div(lhs, rhs)
232+
233+
def test_divide_zero_sized_arrays() -> None:
234+
"""Test division with arrays where at least one array has zero size."""
235+
with pytest.raises(RuntimeError):
236+
zero_shape = (0, 5)
237+
normal_shape = (5, 5)
238+
zero_array = wrapper.randu(zero_shape, dtype.f32)
239+
normal_array = wrapper.randu(normal_shape, dtype.f32)
240+
241+
result_rhs_zero = wrapper.div(normal_array, zero_array)
242+
assert wrapper.get_dims(result_rhs_zero) == normal_shape
243+
244+
result_lhs_zero = wrapper.div(zero_array, normal_array)
245+
assert wrapper.get_dims(result_lhs_zero) == zero_shape
246+
247+
@pytest.mark.parametrize(
248+
"shape_a, shape_b",
249+
[
250+
((1, 5), (5, 1)), # 2D with 2D inverse
251+
((5, 5), (5, 1)), # 2D with 2D
252+
((5, 5), (1, 1)), # 2D with 2D
253+
((1, 1, 1), (5, 5, 5)), # 3D with 3D
254+
((5,), (5,)), # 1D with 1D broadcast
255+
],
256+
)
257+
def test_divide_varying_dimensionality(shape_a: tuple, shape_b: tuple) -> None:
258+
"""Test division with arrays of varying dimensionality."""
259+
lhs = wrapper.randu(shape_a, dtype.f32)
260+
rhs = wrapper.randu(shape_b, dtype.f32)
261+
# Prevent division by zero for dimensional test
262+
rhs = wrapper.add(rhs, wrapper.constant(0.001, shape_b, dtype.f32))
263+
264+
result = wrapper.div(lhs, rhs)
265+
expected_shape = np.broadcast(np.empty(shape_a), np.empty(shape_b)).shape
266+
assert wrapper.get_dims(result)[0 : len(expected_shape)] == expected_shape, f"Failed for shapes {shape_a} and {shape_b}"

0 commit comments

Comments
 (0)