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