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