31
31
)
32
32
33
33
34
+ def parametrize_scipy_fmt_with_arg (name : str ) -> pytest .MarkDecorator :
35
+ return pytest .mark .parametrize (
36
+ name ,
37
+ ["csr" , "csc" , "coo" ],
38
+ )
39
+
40
+
41
+ parametrize_scipy_fmt = parametrize_scipy_fmt_with_arg ("format" )
42
+
43
+
34
44
def assert_sps_equal (
35
45
expected : sps .csr_array | sps .csc_array | sps .coo_array ,
36
46
actual : sps .csr_array | sps .csc_array | sps .coo_array ,
47
+ / ,
48
+ * ,
49
+ check_canonical = False ,
50
+ check_dtype = True ,
37
51
) -> None :
52
+ assert expected .shape == actual .shape
38
53
assert expected .format == actual .format
39
- expected .eliminate_zeros ()
40
- expected .sum_duplicates ()
41
54
42
- actual .eliminate_zeros ()
43
- actual .sum_duplicates ()
55
+ if check_dtype :
56
+ assert expected .dtype == actual .dtype
57
+
58
+ if check_canonical :
59
+ expected .eliminate_zeros ()
60
+ expected .sum_duplicates ()
61
+
62
+ actual .eliminate_zeros ()
63
+ actual .sum_duplicates ()
44
64
45
65
if expected .format != "coo" :
46
66
np .testing .assert_array_equal (expected .indptr , actual .indptr )
@@ -108,93 +128,136 @@ def test_dense_format(dtype, shape):
108
128
np .testing .assert_equal (actual , data )
109
129
110
130
131
+ def assert_array_equal (
132
+ expected : sparse .Array ,
133
+ actual : sparse .Array ,
134
+ / ,
135
+ * ,
136
+ same_format : bool = True ,
137
+ same_dtype : bool = True ,
138
+ data_test_fn : typing .Callable [[np .ndarray , np .ndarray ], None ] = np .testing .assert_array_equal ,
139
+ ) -> None :
140
+ if same_format :
141
+ assert expected .format == actual .format
142
+
143
+ if same_dtype :
144
+ assert expected .dtype == actual .dtype
145
+
146
+ assert expected .shape == actual .shape
147
+ actual = actual .asformat (expected .format )
148
+
149
+ carrs_expected = expected .get_constituent_arrays ()
150
+ carrs_actual = actual .get_constituent_arrays ()
151
+
152
+ for e , a in zip (carrs_expected [:- 1 ], carrs_actual [:- 1 ], strict = True ):
153
+ assert e .dtype == a .dtype
154
+ np .testing .assert_equal (e , a )
155
+
156
+ data_test_fn (carrs_expected [- 1 ], carrs_actual [- 1 ])
157
+
158
+
111
159
@parametrize_dtypes
112
- def test_2d_constructors (rng , dtype ):
160
+ @parametrize_scipy_fmt
161
+ def test_roundtrip (rng , dtype , format ):
113
162
SHAPE = (80 , 100 )
114
163
DENSITY = 0.6
115
164
sampler = generate_sampler (dtype , rng )
116
- csr = sps .random_array (SHAPE , density = DENSITY , format = "csr" , dtype = dtype , random_state = rng , data_sampler = sampler )
117
- csc = sps .random_array (SHAPE , density = DENSITY , format = "csc" , dtype = dtype , random_state = rng , data_sampler = sampler )
118
- dense = np .arange (math .prod (SHAPE ), dtype = dtype ).reshape (SHAPE )
119
- coo = sps .random_array (SHAPE , density = DENSITY , format = "coo" , dtype = dtype , random_state = rng , data_sampler = sampler )
120
- coo .sum_duplicates ()
165
+ sps_arr = sps .random_array (
166
+ SHAPE , density = DENSITY , format = format , dtype = dtype , random_state = rng , data_sampler = sampler
167
+ )
168
+
169
+ sp_arr = sparse .asarray (sps_arr )
170
+ sps_roundtripped = sparse .to_scipy (sp_arr )
171
+ assert_sps_equal (sps_arr , sps_roundtripped )
121
172
122
- csr_tensor = sparse .asarray (csr )
123
- csc_tensor = sparse .asarray (csc )
124
- dense_tensor = sparse .asarray (dense )
125
- coo_tensor = sparse .asarray (coo )
126
- dense_2_tensor = sparse .asarray (np .arange (100 , dtype = dtype ).reshape ((25 , 4 )) + 10 )
173
+ sp_arr_roundtripped = sparse .asarray (sps_roundtripped )
127
174
128
- csr_retured = sparse .to_scipy (csr_tensor )
129
- assert_sps_equal (csr_retured , csr )
175
+ assert_array_equal (sp_arr , sp_arr_roundtripped )
130
176
131
- csc_retured = sparse .to_scipy (csc_tensor )
132
- assert_sps_equal (csc_retured , csc )
133
177
134
- dense_returned = sparse .to_numpy (dense_tensor )
135
- np .testing .assert_equal (dense_returned , dense )
178
+ @parametrize_dtypes
179
+ @pytest .mark .parametrize ("shape" , [(80 , 100 ), (200 ,), (10 , 20 , 30 )])
180
+ def test_roundtrip_dense (rng , dtype , shape ):
181
+ sampler = generate_sampler (dtype , rng )
182
+ np_arr = sampler (shape )
183
+
184
+ sp_arr = sparse .asarray (np_arr )
185
+ np_roundtripped = sparse .to_numpy (sp_arr )
186
+ assert np_arr .dtype == np_roundtripped .dtype
187
+ np .testing .assert_array_equal (np_arr , np_roundtripped )
136
188
137
- coo_returned = sparse .to_scipy (coo_tensor )
138
- np .testing .assert_equal (coo_returned .todense (), coo .todense ())
189
+ sp_arr_roundtripped = sparse .asarray (np_roundtripped )
139
190
140
- dense_2_returned = sparse .to_numpy (dense_2_tensor )
141
- np .testing .assert_equal (dense_2_returned , np .arange (100 , dtype = dtype ).reshape ((25 , 4 )) + 10 )
191
+ assert_array_equal (sp_arr , sp_arr_roundtripped )
142
192
143
193
144
194
@parametrize_dtypes
145
- def test_add (rng , dtype ):
195
+ @parametrize_scipy_fmt_with_arg ("format1" )
196
+ @parametrize_scipy_fmt_with_arg ("format2" )
197
+ def test_add (rng , dtype , format1 , format2 ):
198
+ if format1 == "coo" or format2 == "coo" :
199
+ pytest .xfail (reason = "https://github.com/llvm/llvm-project/issues/116012" )
200
+
146
201
SHAPE = (100 , 50 )
147
202
DENSITY = 0.5
148
203
sampler = generate_sampler (dtype , rng )
204
+ sps_arr1 = sps .random_array (
205
+ SHAPE , density = DENSITY , format = format1 , dtype = dtype , random_state = rng , data_sampler = sampler
206
+ )
207
+ sps_arr2 = sps .random_array (
208
+ SHAPE , density = DENSITY , format = format2 , dtype = dtype , random_state = rng , data_sampler = sampler
209
+ )
149
210
150
- csr = sps .random_array (SHAPE , density = DENSITY , format = "csr" , dtype = dtype , random_state = rng , data_sampler = sampler )
151
- csr_2 = sps .random_array (SHAPE , density = DENSITY , format = "csr" , dtype = dtype , random_state = rng , data_sampler = sampler )
152
- csc = sps .random_array (SHAPE , density = DENSITY , format = "csc" , dtype = dtype , random_state = rng , data_sampler = sampler )
153
- dense = np .arange (math .prod (SHAPE ), dtype = dtype ).reshape (SHAPE )
154
- coo = sps .random_array (SHAPE , density = DENSITY , format = "coo" , dtype = dtype , random_state = rng )
155
- coo .sum_duplicates ()
211
+ sp_arr1 = sparse .asarray (sps_arr1 )
212
+ sp_arr2 = sparse .asarray (sps_arr2 )
156
213
157
- csr_tensor = sparse .asarray (csr )
158
- csr_2_tensor = sparse .asarray (csr_2 )
159
- csc_tensor = sparse .asarray (csc )
160
- dense_tensor = sparse .asarray (dense )
161
- coo_tensor = sparse .asarray (coo )
214
+ expected = sps_arr1 + sps_arr2
215
+ actual = sparse .add (sp_arr1 , sp_arr2 )
216
+ actual_sps = sparse .to_scipy (actual .asformat (sparse .asarray (expected ).format ))
162
217
163
- actual = sparse .to_scipy (sparse .add (csr_tensor , csr_2_tensor ))
164
- expected = csr + csr_2
165
- assert_sps_equal (expected , actual )
218
+ assert_sps_equal (expected , actual_sps , check_canonical = True )
166
219
167
- actual = sparse .to_scipy (sparse .add (csc_tensor , csc_tensor ))
168
- expected = csc + csc
169
- assert_sps_equal (expected , actual )
170
220
171
- actual = sparse .to_scipy (sparse .add (csc_tensor , csr_tensor ))
172
- expected = (csc + csr ).asformat ("csr" )
173
- assert_sps_equal (expected , actual )
221
+ @parametrize_dtypes
222
+ @pytest .mark .parametrize ("shape" , [(80 , 100 ), (200 ,), (10 , 20 , 30 )])
223
+ def test_add_dense (rng , dtype , shape ):
224
+ sampler = generate_sampler (dtype , rng )
225
+ np_arr1 = sampler (shape )
226
+ np_arr2 = sampler (shape )
174
227
175
- actual = sparse .to_numpy (sparse .add (csr_tensor , dense_tensor ))
176
- expected = csr + dense
177
- np .testing .assert_array_equal (actual , expected )
228
+ sp_arr1 = sparse .asarray (np_arr1 )
229
+ sp_arr2 = sparse .asarray (np_arr2 )
178
230
179
- actual = sparse .to_numpy (sparse .add (dense_tensor , csr_tensor ))
180
- expected = csr + dense
181
- assert isinstance (actual , np .ndarray )
182
- np .testing .assert_array_equal (actual , expected )
231
+ expected = np_arr1 + np_arr2
232
+ actual = sparse .add (sp_arr1 , sp_arr2 )
233
+ actual_np = sparse .to_numpy (actual )
183
234
184
- actual = sparse .to_numpy (sparse .add (dense_tensor , dense_tensor ))
185
- expected = dense + dense
186
- assert isinstance (actual , np .ndarray )
187
- np .testing .assert_array_equal (actual , expected )
235
+ np .testing .assert_array_equal (expected , actual_np )
188
236
189
- actual = sparse .to_scipy (sparse .add (csr_2_tensor , coo_tensor ))
190
- expected = csr_2 + coo
191
- assert_sps_equal (expected , actual )
192
237
193
- # This ends up being DCSR, not COO
194
- actual_tensor = sparse .add (coo_tensor , coo_tensor )
195
- actual = sparse .to_scipy (actual_tensor .asformat (coo_tensor .format ))
196
- expected = coo + coo
197
- np .testing .assert_array_equal (actual .todense (), expected .todense ())
238
+ @parametrize_dtypes
239
+ @parametrize_scipy_fmt
240
+ def test_add_dense_sparse (rng , dtype , format ):
241
+ if format == "coo" :
242
+ pytest .xfail (reason = "https://github.com/llvm/llvm-project/issues/116012" )
243
+ sampler = generate_sampler (dtype , rng )
244
+
245
+ SHAPE = (100 , 50 )
246
+ DENSITY = 0.5
247
+
248
+ np_arr1 = sampler (SHAPE )
249
+ sps_arr2 = sps .random_array (
250
+ SHAPE , density = DENSITY , format = format , dtype = dtype , random_state = rng , data_sampler = sampler
251
+ )
252
+
253
+ sp_arr1 = sparse .asarray (np_arr1 )
254
+ sp_arr2 = sparse .asarray (sps_arr2 )
255
+
256
+ expected = np_arr1 + sps_arr2
257
+ actual = sparse .add (sp_arr1 , sp_arr2 )
258
+ actual_np = sparse .to_numpy (actual .asformat (sp_arr1 .format ))
259
+
260
+ np .testing .assert_array_equal (expected , actual_np )
198
261
199
262
200
263
@parametrize_dtypes
@@ -220,10 +283,9 @@ def test_csf_format(dtype):
220
283
for actual , expected in zip (result_arrays , constituent_arrays , strict = True ):
221
284
np .testing .assert_array_equal (actual , expected )
222
285
223
- res_arrays = sparse .add (csf_array , csf_array ).get_constituent_arrays ()
224
- expected_arrays = (pos_1 , crd_1 , pos_2 , crd_2 , data * 2 )
225
- for actual , expected in zip (res_arrays , expected_arrays , strict = True ):
226
- np .testing .assert_array_equal (actual , expected )
286
+ actual = sparse .add (csf_array , csf_array )
287
+ expected = sparse .from_constituent_arrays (format = format , arrays = (pos_1 , crd_1 , pos_2 , crd_2 , data * 2 ), shape = SHAPE )
288
+ assert_array_equal (expected , actual )
227
289
228
290
229
291
@parametrize_dtypes
@@ -254,10 +316,9 @@ def test_coo_3d_format(dtype):
254
316
for actual , expected in zip (result , carrs , strict = True ):
255
317
np .testing .assert_array_equal (actual , expected )
256
318
257
- result_arrays = sparse .add (coo_array , coo_array ).asformat (coo_array .format ).get_constituent_arrays ()
258
- constituent_arrays = (pos , * crd , data * 2 )
259
- for actual , expected in zip (result_arrays , constituent_arrays , strict = True ):
260
- np .testing .assert_array_equal (actual , expected )
319
+ actual = sparse .add (coo_array , coo_array ).asformat (coo_array .format )
320
+ expected = sparse .from_constituent_arrays (format = actual .format , arrays = (pos , * crd , data * 2 ), shape = SHAPE )
321
+ assert_array_equal (expected , actual )
261
322
262
323
263
324
@parametrize_dtypes
@@ -281,10 +342,9 @@ def test_sparse_vector_format(dtype):
281
342
for actual , expected in zip (result , carrs , strict = True ):
282
343
np .testing .assert_array_equal (actual , expected )
283
344
284
- res_arrs = sparse .add (sv_array , sv_array ).get_constituent_arrays ()
285
- sv2_expected = (pos , crd , data * 2 )
286
- for actual , expected in zip (res_arrs , sv2_expected , strict = True ):
287
- np .testing .assert_array_equal (actual , expected )
345
+ actual = sparse .add (sv_array , sv_array )
346
+ expected = sparse .from_constituent_arrays (format = actual .format , arrays = (pos , crd , data * 2 ), shape = SHAPE )
347
+ assert_array_equal (expected , actual )
288
348
289
349
dense = np .array ([1 , 2 , 3 , 0 , 0 , 0 , 4 , 0 , 5 , 6 ], dtype = dtype )
290
350
dense_array = sparse .asarray (dense )
0 commit comments