1 //------------------------------------------------------------------------------
2 // GB_mex_about2: more basic tests
3 //------------------------------------------------------------------------------
4 
5 // SuiteSparse:GraphBLAS, Timothy A. Davis, (c) 2017-2021, All Rights Reserved.
6 // SPDX-License-Identifier: Apache-2.0
7 
8 //------------------------------------------------------------------------------
9 
10 // Test lots of random stuff.  The function otherwise serves no purpose.
11 
12 #include "GB_mex.h"
13 #include "GB_mex_errors.h"
14 #include "GB_ij.h"
15 
16 #define USAGE "GB_mex_about2"
17 
18 typedef struct
19 {
20     int gunk [16] ;
21 }
22 wild ;
23 
mexFunction(int nargout,mxArray * pargout[],int nargin,const mxArray * pargin[])24 void mexFunction
25 (
26     int nargout,
27     mxArray *pargout [ ],
28     int nargin,
29     const mxArray *pargin [ ]
30 )
31 {
32 
33     GrB_Info info ;
34     GrB_Matrix A = NULL, B = NULL, C = NULL ;
35     GxB_Scalar scalar = NULL ;
36     GrB_Vector victor = NULL ;
37     GrB_Descriptor desc = NULL ;
38     GrB_Type Wild = NULL ;
39     char *err ;
40 
41     //--------------------------------------------------------------------------
42     // startup GraphBLAS
43     //--------------------------------------------------------------------------
44 
45     bool malloc_debug = GB_mx_get_global (true) ;
46     FILE *f = fopen ("errlog3.txt", "w") ;
47     int expected = GrB_SUCCESS ;
48 
49     //--------------------------------------------------------------------------
50     // test removeElement/setElement when jumbled
51     //--------------------------------------------------------------------------
52 
53     OK (GrB_Matrix_new (&A, GrB_INT32, 10, 10)) ;
54     OK (GrB_Vector_new (&victor, GrB_INT32, 10)) ;
55     OK (GxB_Vector_Option_set_(victor, GxB_BITMAP_SWITCH, 2.0)) ;
56     OK (GxB_Scalar_new (&scalar, GrB_INT32)) ;
57 
58     OK (GxB_Matrix_fprint (A, "A before set", 3, NULL)) ;
59     OK (GrB_Matrix_setElement_INT32 (A, 314159, 0, 0)) ;
60     OK (GxB_Matrix_fprint (A, "A after set", 3, NULL)) ;
61     A->jumbled = true ;
62     OK (GrB_Matrix_removeElement (A, 0, 0)) ;
63     OK (GxB_Matrix_fprint (A, "A after remove", 3, NULL)) ;
64     A->jumbled = true ;
65     OK (GrB_Matrix_setElement_INT32 (A, 99099, 0, 0)) ;
66     OK (GxB_Matrix_fprint (A, "A after set again", 3, NULL)) ;
67 
68     OK (GxB_Vector_fprint (victor, "victor before set", 3, NULL)) ;
69     OK (GrB_Vector_setElement_INT32 (victor, 44, 0)) ;
70     OK (GxB_Vector_fprint (victor, "victor after set", 3, NULL)) ;
71     victor->jumbled = true ;
72     OK (GrB_Vector_removeElement (victor, 0)) ;
73     OK (GxB_Vector_fprint (victor, "victor remove set", 3, NULL)) ;
74     victor->jumbled = true ;
75     OK (GrB_Vector_setElement_INT32 (victor, 88, 0)) ;
76     OK (GxB_Vector_fprint (victor, "victor after set again", 3, NULL)) ;
77 
78     OK (GxB_Scalar_fprint (scalar, "scalar before set", 3, NULL)) ;
79     OK (GxB_Scalar_setElement_INT32 (scalar, 404)) ;
80     OK (GxB_Scalar_fprint (scalar, "scalar after set", 3, NULL)) ;
81     int i = 0 ;
82     OK (GxB_Scalar_extractElement_INT32 (&i, scalar)) ;
83     CHECK (i == 404) ;
84     OK (GxB_Scalar_fprint (scalar, "scalar after extract", 3, NULL)) ;
85     OK (GrB_Matrix_removeElement ((GrB_Matrix) scalar, 0, 0)) ;
86     OK (GxB_Scalar_fprint (scalar, "scalar after remove", 3, NULL)) ;
87     i = 777 ;
88     expected = GrB_NO_VALUE ;
89     ERR (GxB_Scalar_extractElement_INT32 (&i, scalar)) ;
90     CHECK (i == 777) ;
91 
92     // force a zombie into the scalar
93     OK (GxB_Scalar_setElement_INT32 (scalar, 707)) ;
94     OK (GxB_Scalar_wait (&scalar)) ;
95     OK (GxB_Scalar_fprint (scalar, "scalar after wait", 3, NULL)) ;
96     OK (GxB_Matrix_Option_set (scalar, GxB_SPARSITY_CONTROL, GxB_SPARSE)) ;
97     CHECK (scalar->i != NULL) ;
98     scalar->i [0] = GB_FLIP (0) ;
99     scalar->nzombies = 1 ;
100     OK (GxB_Scalar_fprint (scalar, "scalar with zombie", 3, NULL)) ;
101     expected = GrB_NO_VALUE ;
102     ERR (GxB_Scalar_extractElement_INT32 (&i, scalar)) ;
103     OK (GxB_Scalar_fprint (scalar, "scalar after extract", 3, NULL)) ;
104     CHECK (i == 777) ;
105 
106     GrB_Vector_free_(&victor) ;
107     GrB_Matrix_free_(&A) ;
108     GxB_Scalar_free_(&scalar) ;
109 
110     //--------------------------------------------------------------------------
111     // builtin comparators not defined for complex types
112     //--------------------------------------------------------------------------
113 
114     int n = 10 ;
115     OK (GrB_Matrix_new (&A, GxB_FC32, n, n)) ;
116     OK (GxB_Matrix_Option_set_(A, GxB_SPARSITY_CONTROL, GxB_SPARSE)) ;
117 
118     OK (GrB_Matrix_new (&C, GxB_FC32, n, n)) ;
119     OK (GxB_Scalar_new (&scalar, GxB_FC32)) ;
120     expected = GrB_DOMAIN_MISMATCH ;
121     ERR (GxB_Matrix_select (C, NULL, NULL, GxB_LT_THUNK, A, scalar, NULL)) ;
122     char *message = NULL ;
123     OK (GrB_Matrix_error (&message, C)) ;
124     printf ("expected error: %s\n", message) ;
125     GrB_Matrix_free_(&C) ;
126     GxB_Scalar_free_(&scalar) ;
127 
128     //--------------------------------------------------------------------------
129     // GB_pslice
130     //--------------------------------------------------------------------------
131 
132     int64_t Slice [30] ;
133     GB_pslice (Slice, A->p, n, 2, true) ;
134     CHECK (Slice [0] == 0) ;
135 
136     int64_t Ap [11] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } ;
137     GB_pslice (Slice, Ap, 10, 10, false) ;
138     printf ("Slice: ") ;
139     for (int k = 0 ; k <= 10 ; k++) printf (" %ld", Slice [k]) ;
140     printf ("\n") ;
141 
142     GrB_Matrix_free_(&A) ;
143 
144     //--------------------------------------------------------------------------
145     // GrB_Matrix_check
146     //--------------------------------------------------------------------------
147 
148     double bswitch = 1 ;
149     OK (GrB_Matrix_new (&A, GrB_INT32, n, n)) ;
150     OK (GxB_Matrix_Option_set_(A, GxB_BITMAP_SWITCH, 0.125)) ;
151     OK (GxB_Matrix_Option_get_(A, GxB_BITMAP_SWITCH, &bswitch)) ;
152     CHECK (fabsf (bswitch - 0.125) < 1e-5) ;
153 
154     OK (GxB_Matrix_Option_set_(A, GxB_SPARSITY_CONTROL, GxB_SPARSE)) ;
155     OK (GrB_Matrix_assign_INT32 (A, NULL, NULL, 3, GrB_ALL, n, GrB_ALL, n,
156         NULL)) ;
157     OK (GrB_Matrix_wait (&A)) ;
158     OK (GxB_Matrix_fprint (A, "valid matrix", GxB_SHORT, NULL)) ;
159     // mangle the matrix
160     GB_FREE (&(A->p), A->p_size) ;
161     GB_FREE (&(A->x), A->x_size) ;
162     expected = GrB_INVALID_OBJECT ;
163     ERR (GxB_Matrix_fprint (A, "invalid sparse matrix", GxB_SHORT, NULL)) ;
164     GrB_Matrix_free_(&A) ;
165 
166     OK (GrB_Matrix_new (&A, GrB_INT32, n, n)) ;
167     A->sparsity = 999 ;
168     ERR (GxB_Matrix_fprint (A, "invalid sparsity control", GxB_SHORT, NULL)) ;
169     GrB_Matrix_free_(&A) ;
170 
171     OK (GrB_Matrix_new (&A, GrB_INT32, n, n)) ;
172     OK (GrB_Matrix_assign_INT32 (A, NULL, NULL, 3, GrB_ALL, n, GrB_ALL, n,
173         NULL)) ;
174     OK (GrB_Matrix_wait (&A)) ;
175 
176     A->jumbled = true ;
177     ERR (GxB_Matrix_fprint (A, "full matrix cannot be jumbled", GxB_SHORT,
178         NULL)) ;
179 
180     A->jumbled = false ;
181     A->plen = 999 ;
182     ERR (GxB_Matrix_fprint (A, "invalid full matrix", GxB_SHORT, NULL)) ;
183 
184     A->plen = -1 ;
185     A->nzombies = 1 ;
186     ERR (GxB_Matrix_fprint (A, "full matrix cannot have zombies",
187         GxB_SHORT, NULL)) ;
188     A->nzombies = 0 ;
189     CHECK (GB_Pending_alloc (&(A->Pending), GrB_INT32, NULL, true, 4)) ;
190     ERR (GxB_Matrix_fprint (A, "full matrix cannot have pending tuples",
191         GxB_SHORT, NULL)) ;
192     GrB_Matrix_free_(&A) ;
193 
194     OK (GrB_Matrix_new (&A, GrB_INT32, n, n)) ;
195     OK (GxB_Matrix_Option_set_(A, GxB_SPARSITY_CONTROL, GxB_BITMAP)) ;
196     A->plen = 999 ;
197     ERR (GxB_Matrix_fprint (A, "invalid bitmap", GxB_SHORT, NULL)) ;
198 
199     A->plen = -1 ;
200     A->b [0] = 1 ;
201     ERR (GxB_Matrix_fprint (A, "invalid bitmap", GxB_SUMMARY, NULL)) ;
202     GrB_Matrix_free_(&A) ;
203 
204     OK (GrB_Matrix_new (&A, GrB_INT32, n, n)) ;
205     OK (GxB_Matrix_Option_set_(A, GxB_SPARSITY_CONTROL, GxB_BITMAP)) ;
206     OK (GrB_Matrix_setElement_INT32 (A, 12345, 0, 0)) ;
207     OK (GxB_Matrix_fprint (A, "valid matrix", GxB_SHORT, NULL)) ;
208     A->b [0] = 3 ;
209     ERR (GxB_Matrix_fprint (A, "invalid bitmap", GxB_SHORT, NULL)) ;
210     GrB_Matrix_free_(&A) ;
211 
212     OK (GrB_Matrix_new (&A, GrB_INT32, n, n)) ;
213     A->nvec_nonempty = 2 ;
214     ERR (GxB_Matrix_fprint (A, "invalid nvec_nonempty", GxB_SHORT, NULL)) ;
215     GrB_Matrix_free_(&A) ;
216 
217     OK (GrB_Matrix_new (&A, GrB_INT32, n, n)) ;
218     OK (GrB_Matrix_setElement_INT32 (A, 12345, 0, 0)) ;
219     OK (GxB_Matrix_fprint (A, "valid matrix with 1 pending", GxB_SHORT, NULL)) ;
220     A->Pending->size = 900 ;
221     ERR (GxB_Matrix_fprint (A, "invalid pending type", GxB_SHORT, NULL)) ;
222     GrB_Matrix_free_(&A) ;
223 
224     //--------------------------------------------------------------------------
225     // lo:stride:hi with stride of zero
226     //--------------------------------------------------------------------------
227 
228     OK (GxB_Global_Option_set_(GxB_BURBLE, true)) ;
229     OK (GrB_Matrix_new (&A, GrB_INT32, n, n)) ;
230     GrB_Index I [3] = { 1, 1, 0 } ;
231     OK (GrB_Matrix_new (&C, GrB_INT32, n, 0)) ;
232     OK (GrB_Matrix_extract_(C, NULL, NULL, A, GrB_ALL, n, I, GxB_STRIDE,
233         NULL)) ;
234     OK (GxB_Matrix_fprint (C, "C = A (:,1:0:1)", GxB_COMPLETE, NULL)) ;
235     GrB_Matrix_free_(&C) ;
236     OK (GrB_Matrix_new (&C, GrB_INT32, 0, n)) ;
237     OK (GrB_Matrix_extract_(C, NULL, NULL, A, I, GxB_STRIDE, GrB_ALL, n,
238         NULL)) ;
239     OK (GxB_Matrix_fprint (C, "C = A (1:0:1,:)", GxB_COMPLETE, NULL)) ;
240     GrB_Matrix_free_(&C) ;
241     GrB_Matrix_free_(&A) ;
242     OK (GxB_Global_Option_set_(GxB_BURBLE, false)) ;
243 
244     int64_t Icolon [3] = { 1, 1, 0 } ;
245     CHECK (!GB_ij_is_in_list (NULL, 0, 0, GB_STRIDE, Icolon)) ;
246 
247     //--------------------------------------------------------------------------
248     // GB_aliased
249     //--------------------------------------------------------------------------
250 
251     OK (GrB_Matrix_new (&A, GrB_INT32, n, n)) ;
252     OK (GrB_Matrix_setElement_INT32 (A, 12345, 0, 0)) ;
253     OK (GrB_Matrix_dup (&C, A)) ;
254     CHECK (!GB_aliased (A, C)) ;
255     GB_FREE (&(C->p), C->p_size) ;
256     C->p = A->p ;
257     C->p_shallow = true ;
258     CHECK (GB_aliased (A, C)) ;
259     C->p = NULL ;
260     C->p_shallow = false ;
261     CHECK (!GB_aliased (A, C)) ;
262     GB_FREE (&(C->i), C->i_size) ;
263     C->i = A->i ;
264     C->i_shallow = true ;
265     CHECK (GB_aliased (A, C)) ;
266     C->i = NULL ;
267     C->i_shallow = false ;
268     GrB_Matrix_free_(&A) ;
269     GrB_Matrix_free_(&C) ;
270 
271     //--------------------------------------------------------------------------
272     // GrB_apply with empty scalar
273     //--------------------------------------------------------------------------
274 
275     OK (GxB_Scalar_new (&scalar, GrB_INT32)) ;
276     OK (GrB_Matrix_new (&A, GrB_INT32, n, n)) ;
277     OK (GrB_Matrix_new (&C, GrB_INT32, n, n)) ;
278     expected = GrB_INVALID_VALUE ;
279     ERR (GxB_Matrix_apply_BinaryOp2nd (C, NULL, NULL, GrB_PLUS_INT32, A,
280         scalar, NULL)) ;
281     OK (GrB_Matrix_error (&message, C)) ;
282     printf ("expected error: %s\n", message) ;
283     GrB_Matrix_free_(&A) ;
284     GrB_Matrix_free_(&C) ;
285     GxB_Scalar_free_(&scalar) ;
286 
287     //--------------------------------------------------------------------------
288     // invalid descriptor
289     //--------------------------------------------------------------------------
290 
291     int method ;
292     OK (GrB_Descriptor_new (&desc)) ;
293     OK (GxB_Descriptor_fprint (desc, "descriptor", GxB_COMPLETE, NULL)) ;
294 
295     OK (GxB_Desc_get (NULL, GxB_AxB_METHOD, &method)) ;
296     CHECK (method == GxB_DEFAULT) ;
297     OK (GxB_Desc_set (desc, GxB_AxB_METHOD, GxB_AxB_GUSTAVSON)) ;
298     OK (GxB_Descriptor_fprint (desc, "descriptor", GxB_COMPLETE, NULL)) ;
299     OK (GxB_Desc_get (desc, GxB_AxB_METHOD, &method)) ;
300     CHECK (method == GxB_AxB_GUSTAVSON) ;
301 
302     desc->mask = GrB_REPLACE ;
303     expected = GrB_INVALID_OBJECT ;
304     ERR (GxB_Descriptor_fprint (desc, "invalid", GxB_COMPLETE, NULL)) ;
305     OK (GrB_Descriptor_free (&desc)) ;
306 
307     //--------------------------------------------------------------------------
308     // GrB_build an empty matrix
309     //--------------------------------------------------------------------------
310 
311     OK (GrB_Matrix_new (&A, GrB_INT32, n, n)) ;
312     OK (GrB_Matrix_build_INT32 (A, I, I, I, 0, GrB_PLUS_INT32)) ;
313     OK (GxB_Matrix_fprint (A, "empty", GxB_COMPLETE, NULL)) ;
314     CHECK (!GB_is_shallow (A)) ;
315     GrB_Matrix_free_(&A) ;
316 
317     OK (GrB_Matrix_new (&A, GrB_INT32, n, n)) ;
318     expected = GrB_DOMAIN_MISMATCH ;
319     ERR (GrB_Matrix_build_INT32 (A, I, I, I, 0, GxB_FIRSTI_INT32)) ;
320     OK (GrB_Matrix_error (&message, A)) ;
321     printf ("expected error: %s\n", message) ;
322     GrB_Matrix_free_(&A) ;
323 
324     //--------------------------------------------------------------------------
325     // reduce with positional op
326     //--------------------------------------------------------------------------
327 
328     OK (GrB_Matrix_new (&A, GrB_INT32, n, n)) ;
329     OK (GrB_Vector_new (&victor, GrB_INT32, n)) ;
330     OK (GxB_Vector_Option_get_(victor, GxB_BITMAP_SWITCH, &bswitch)) ;
331     printf ("vector bitmap switch: %g\n\n", bswitch) ;
332 
333     expected = GrB_DOMAIN_MISMATCH ;
334     ERR (GrB_Matrix_reduce_BinaryOp (victor, NULL, NULL, GxB_FIRSTI_INT32,
335         A, NULL)) ;
336     OK (GrB_Matrix_error (&message, victor)) ;
337     printf ("error expected: %s\n", message) ;
338     GrB_Matrix_free_(&A) ;
339     GrB_Vector_free_(&victor) ;
340 
341     //--------------------------------------------------------------------------
342     // GrB_init
343     //--------------------------------------------------------------------------
344 
345     expected = GrB_INVALID_VALUE ;
346     ERR (GrB_init (GrB_BLOCKING)) ;
347 
348     //--------------------------------------------------------------------------
349     // jumbled user-defined matrix
350     //--------------------------------------------------------------------------
351 
352     wild ww, w2 ;
353     n = 3 ;
354     memset (ww.gunk, 13, 16 * sizeof (int)) ;
355     OK (GrB_Type_new (&Wild, sizeof (wild))) ;
356     OK (GrB_Matrix_new (&C, Wild, n, n)) ;
357     OK (GxB_Matrix_Option_set (C, GxB_SPARSITY_CONTROL, GxB_SPARSE)) ;
358     OK (GrB_Matrix_assign_UDT (C, NULL, NULL, &ww, GrB_ALL, n, GrB_ALL, n,
359         NULL)) ;
360     OK (GxB_Matrix_fprint (C, "wild matrix", GxB_SHORT, NULL)) ;
361 
362     // jumble the matrix
363     C->jumbled = true ;
364     C->i [0] = 1 ;
365     C->i [1] = 0 ;
366     OK (GxB_Matrix_fprint (C, "wild matrix jumbled", GxB_SHORT, NULL)) ;
367 
368     // unjumble the matrix
369     OK (GrB_Matrix_wait (&C)) ;
370     OK (GxB_Matrix_fprint (C, "wild matrix unjumbled", GxB_SHORT, NULL)) ;
371 
372     GrB_Matrix_free_(&C) ;
373 
374     //--------------------------------------------------------------------------
375     // malloc/realloc wrappers
376     //--------------------------------------------------------------------------
377 
378     size_t nbytes ;
379     bool ok = false ;
380     int *p = GB_malloc_memory (4, sizeof (int), &nbytes) ;
381     CHECK (p != NULL) ;
382     p = GB_realloc_memory (1024*1024, 4, sizeof (int), p, &nbytes, &ok, NULL) ;
383     CHECK (p != NULL) ;
384     CHECK (ok) ;
385     p = GB_realloc_memory (4, 4, GxB_INDEX_MAX + 1, p, &nbytes, &ok, NULL) ;
386     CHECK (!ok) ;
387     GB_free_memory (&p, nbytes) ;
388 
389     //--------------------------------------------------------------------------
390     // try to import a huge full matrix (this will fail):
391     //--------------------------------------------------------------------------
392 
393     GrB_Matrix X = NULL ;
394     info = GxB_Matrix_import_FullC (&X, GrB_FP32, GxB_INDEX_MAX, GxB_INDEX_MAX,
395         NULL, UINT64_MAX, false, NULL) ;
396     if (info != GrB_INVALID_VALUE || X != NULL) mexErrMsgTxt ("huge fail1") ;
397 
398     GrB_Index nhuge = (((GrB_Index) 2) << 50) ;
399     info = GxB_Matrix_import_BitmapC (&X, GrB_FP32, nhuge, nhuge,
400         NULL, NULL, 0, 0, false, 0, NULL) ;
401     if (info != GrB_INVALID_VALUE || X != NULL) mexErrMsgTxt ("huge fail5") ;
402 
403     // try to convert a huge sparse matrix to bitmap (this will fail too):
404     info = GrB_Matrix_new (&X, GrB_FP32, nhuge, nhuge) ;
405     if (info != GrB_SUCCESS) mexErrMsgTxt ("huge fail2") ;
406     info = GxB_Matrix_Option_set_(X, GxB_SPARSITY_CONTROL, GxB_BITMAP) ;
407     if (info != GrB_OUT_OF_MEMORY) mexErrMsgTxt ("huge fail3") ;
408     info = GB_convert_to_full (X) ;
409     if (info != GrB_OUT_OF_MEMORY) mexErrMsgTxt ("huge fail4") ;
410     GrB_Matrix_free (&X) ;
411 
412     //--------------------------------------------------------------------------
413     // hypermatrix prune
414     //--------------------------------------------------------------------------
415 
416     OK (GrB_Matrix_new (&C, GrB_FP32, GxB_INDEX_MAX, GxB_INDEX_MAX)) ;
417     OK (GrB_Matrix_setElement_FP32 (C, (double) 3, 0, 0)) ;
418     OK (GrB_Matrix_wait (&C)) ;
419     OK (GxB_Matrix_fprint (C, "huge matrix", GxB_SHORT, NULL)) ;
420     C->nvec_nonempty = -1 ;
421     OK (GB_hypermatrix_prune (C, NULL)) ;
422     CHECK (C->nvec_nonempty == 1) ;
423     GrB_Matrix_free (&C) ;
424 
425     //--------------------------------------------------------------------------
426     // vector option set/get
427     //--------------------------------------------------------------------------
428 
429     OK (GrB_Vector_new (&victor, GrB_FP32, 10)) ;
430     OK (GxB_Vector_Option_set (victor, GxB_BITMAP_SWITCH, (double) 4.5)) ;
431     double bitmap_switch = 8 ;
432     OK (GxB_Vector_Option_get (victor, GxB_BITMAP_SWITCH, &bitmap_switch)) ;
433     CHECK (bitmap_switch == 4.5) ;
434     GrB_Vector_free (&victor) ;
435 
436     //--------------------------------------------------------------------------
437     // vector transpose
438     //--------------------------------------------------------------------------
439 
440     #define FREE_ALL ;
441     #define GET_DEEP_COPY ;
442     #define FREE_DEEP_COPY ;
443     OK (GrB_Matrix_new (&C, GrB_FP32, 100, 1)) ;
444     OK (GrB_Matrix_setElement_FP32 (C, (double) 3, 0, 0)) ;
445     OK (GrB_Matrix_wait (&C)) ;
446     X = NULL ;
447     METHOD (GB_transpose (&X, NULL, true, C, NULL, NULL, NULL, false, NULL)) ;
448     OK (GxB_Matrix_fprint (X, "row", GxB_SHORT, NULL)) ;
449     GrB_Matrix Z = NULL ;
450     OK (GrB_Matrix_dup (&Z, X)) ;
451     GrB_Matrix_free (&C) ;
452     METHOD (GB_transpose (&C, NULL, true, Z, NULL, NULL, NULL, false, NULL)) ;
453     OK (GxB_Matrix_fprint (C, "col", GxB_SHORT, NULL)) ;
454     GrB_Matrix_free (&Z) ;
455     GrB_Matrix_free (&X) ;
456     GrB_Matrix_free (&C) ;
457 
458     //--------------------------------------------------------------------------
459     // split/concat for user-defined types
460     //--------------------------------------------------------------------------
461 
462     printf ("\n ======================== split/concat tests: ") ;
463     int sparsity [4] ;
464     sparsity [0] = GxB_HYPERSPARSE ;
465     sparsity [1] = GxB_SPARSE ;
466     sparsity [2] = GxB_BITMAP ;
467     sparsity [3] = GxB_FULL ;
468     GrB_Matrix Tiles [4] ;
469     memset (Tiles, 0, 4 * sizeof (GrB_Matrix)) ;
470     n = 20 ;
471     GrB_Index Tile_nrows [2] = { 5, 15 } ;
472     GrB_Index Tile_ncols [2] = { 12, 8 } ;
473 
474     for (int k = 0 ; k <= 3 ; k++)
475     {
476         for (int k2 = 0 ; k2 <= 1 ; k2++)
477         {
478             OK (GrB_Matrix_new (&C, Wild, n, n)) ;
479             OK (GxB_Matrix_Option_set (C, GxB_SPARSITY_CONTROL, sparsity [k])) ;
480             if (k2 == 0)
481             {
482                 // C(:,:) = ww
483                 OK (GrB_Matrix_assign_UDT (C, NULL, NULL, &ww, GrB_ALL,
484                     n, GrB_ALL, n, NULL)) ;
485             }
486             else
487             {
488                 // C = diagonal matrix
489                 for (int64_t kk = 0 ; kk < 20 ; kk++)
490                 {
491                     OK (GrB_Matrix_setElement_UDT (C, &ww, kk, kk)) ;
492                 }
493             }
494             // split C into 4 matrices
495             OK (GxB_Matrix_split (Tiles, 2, 2, Tile_nrows, Tile_ncols, C,
496                 NULL)) ;
497             // concatenate the 4 matrices back in X
498             OK (GrB_Matrix_new (&X, Wild, n, n)) ;
499             OK (GxB_Matrix_Option_set (X, GxB_SPARSITY_CONTROL, sparsity [k])) ;
500             OK (GxB_Matrix_concat (X, Tiles, 2, 2, NULL)) ;
501             // ensure C and X are the same (just use a brute force method)
502             for (int64_t i = 0 ; i < n ; i++)
503             {
504                 for (int64_t j = 0 ; j < n ; j++)
505                 {
506                     wild wc, wx ;
507                     int infoc = GrB_Matrix_extractElement_UDT (&wc, C, i, j) ;
508                     int infox = GrB_Matrix_extractElement_UDT (&wx, X, i, j) ;
509                     CHECK (infoc == GrB_SUCCESS || infoc == GrB_NO_VALUE) ;
510                     CHECK (infoc == infox) ;
511                     if (infoc == GrB_SUCCESS)
512                     {
513                         for (int kk = 0 ; kk < 16 ; kk++)
514                         {
515                             CHECK (wc.gunk [kk] == wx.gunk [kk]) ;
516                         }
517                     }
518                 }
519             }
520             GrB_Matrix_free (&X) ;
521             GrB_Matrix_free (&C) ;
522 
523             expected = GrB_DOMAIN_MISMATCH ;
524             OK (GrB_Matrix_new (&X, GrB_FP32, n, n)) ;
525             ERR (GxB_Matrix_concat (X, Tiles, 2, 2, NULL)) ;
526             OK (GrB_Matrix_error (&err, X)) ;
527             printf ("expected error: %s\n", err) ;
528             GrB_Matrix_free (&X) ;
529 
530             expected = GrB_DIMENSION_MISMATCH ;
531             OK (GrB_Matrix_new (&X, Wild, 100, 100)) ;
532             ERR (GxB_Matrix_concat (X, Tiles, 2, 2, NULL)) ;
533             OK (GrB_Matrix_error (&err, X)) ;
534             printf ("expected error: %s\n", err) ;
535             GrB_Matrix_free (&X) ;
536 
537             OK (GrB_Matrix_new (&X, Wild, n, n)) ;
538             GrB_Matrix_free (&(Tiles [3])) ;
539             OK (GrB_Matrix_new (&(Tiles [3]), Wild, 15, 100)) ;
540             ERR (GxB_Matrix_concat (X, Tiles, 2, 2, NULL)) ;
541             GxB_print (X, 3) ;
542             OK (GrB_Matrix_error (&err, X)) ;
543             printf ("expected error: %s\n", err) ;
544             GrB_Matrix_free (&(Tiles [3])) ;
545 
546             OK (GrB_Matrix_new (&(Tiles [3]), Wild, 100, 8)) ;
547             ERR (GxB_Matrix_concat (X, Tiles, 2, 2, NULL)) ;
548             OK (GrB_Matrix_error (&err, X)) ;
549             printf ("expected error: %s\n", err) ;
550 
551             for (int kk = 0 ; kk < 4 ; kk++)
552             {
553                 GrB_Matrix_free (&(Tiles [kk])) ;
554             }
555 
556             expected = GrB_NULL_POINTER ;
557             ERR (GxB_Matrix_concat (X, Tiles, 2, 2, NULL)) ;
558             GrB_Matrix_free (&X) ;
559         }
560     }
561 
562     //--------------------------------------------------------------------------
563     // split/concat error handling
564     //--------------------------------------------------------------------------
565 
566     expected = GrB_INVALID_VALUE ;
567     OK (GrB_Matrix_new (&C, GrB_FP32, n, n)) ;
568     ERR (GxB_Matrix_split (Tiles, 0, 0, Tile_nrows, Tile_ncols, C, NULL)) ;
569     ERR (GxB_Matrix_concat (C, Tiles, 0, 0, NULL)) ;
570     GrB_Matrix_free (&C) ;
571 
572     expected = GrB_DIMENSION_MISMATCH ;
573     OK (GrB_Matrix_new (&C, GrB_FP32, n, n)) ;
574     Tile_nrows [0] = -1 ;
575     ERR (GxB_Matrix_split (Tiles, 2, 2, Tile_nrows, Tile_ncols, C, NULL)) ;
576     Tile_nrows [0] = 1 ;
577     ERR (GxB_Matrix_split (Tiles, 2, 2, Tile_nrows, Tile_ncols, C, NULL)) ;
578     Tile_nrows [0] = 5 ;
579     Tile_ncols [0] = -1 ;
580     ERR (GxB_Matrix_split (Tiles, 2, 2, Tile_nrows, Tile_ncols, C, NULL)) ;
581     Tile_ncols [0] = 1 ;
582     ERR (GxB_Matrix_split (Tiles, 2, 2, Tile_nrows, Tile_ncols, C, NULL)) ;
583     GrB_Matrix_free (&C) ;
584 
585     //--------------------------------------------------------------------------
586     // C<C,struct> = scalar
587     //--------------------------------------------------------------------------
588 
589     printf ("\n\ntesting C<C,struct> = scalar for user-defined type:\n") ;
590     OK (GxB_Global_Option_set (GxB_BURBLE, true)) ;
591     OK (GrB_Matrix_new (&C, Wild, n, n)) ;
592     memset (ww.gunk,  0, 16 * sizeof (int)) ;
593     memset (w2.gunk,  1, 16 * sizeof (int)) ;
594     for (int64_t kk = 0 ; kk < 16 ; kk++)
595     {
596         w2.gunk [kk] = kk ;
597     }
598     for (int64_t kk = 0 ; kk < 20 ; kk++)
599     {
600         OK (GrB_Matrix_setElement_UDT (C, &ww, kk, kk)) ;
601     }
602     OK (GrB_Matrix_wait (&C)) ;
603     info = GrB_Matrix_assign_UDT (C, C, NULL, &w2, GrB_ALL, 20, GrB_ALL, 20,
604         GrB_DESC_S) ;
605     wild w3 ;
606 
607     for (int64_t kk = 0 ; kk < 20 ; kk++)
608     {
609         memset (w3.gunk,  9, 16 * sizeof (int)) ;
610         info = (GrB_Matrix_extractElement_UDT (&w3, C, kk, kk)) ;
611         CHECK (info == GrB_SUCCESS) ;
612         for (int64_t t = 0 ; t < 16 ; t++)
613         {
614             CHECK (w3.gunk [t] == t) ;
615         }
616     }
617     GrB_Matrix_free (&C) ;
618     OK (GxB_Global_Option_set (GxB_BURBLE, false)) ;
619 
620     //--------------------------------------------------------------------------
621     // GxB_Matrix_diag and GxB_Vector_diag error handling
622     //--------------------------------------------------------------------------
623 
624     expected = GrB_DIMENSION_MISMATCH ;
625 
626     OK (GrB_Matrix_new (&C, GrB_FP32, 10, 20)) ;
627     OK (GrB_Vector_new (&victor, GrB_FP32, 10)) ;
628     ERR (GxB_Matrix_diag (C, victor, 0, NULL)) ;
629     OK (GrB_Matrix_error (&err, C)) ;
630     printf ("expected error: %s\n", err) ;
631     GrB_Matrix_free (&C) ;
632 
633     OK (GrB_Matrix_new (&C, GrB_FP32, 5, 5)) ;
634     ERR (GxB_Matrix_diag (C, victor, 0, NULL)) ;
635     OK (GrB_Matrix_error (&err, C)) ;
636     printf ("expected error: %s\n", err) ;
637     ERR (GxB_Vector_diag (victor, C, 0, NULL)) ;
638     OK (GrB_Vector_error (&err, victor)) ;
639     printf ("expected error: %s\n", err) ;
640     GrB_Matrix_free (&C) ;
641 
642     expected = GrB_DOMAIN_MISMATCH ;
643 
644     OK (GrB_Matrix_new (&C, Wild, 10, 10)) ;
645     ERR (GxB_Matrix_diag (C, victor, 0, NULL)) ;
646     OK (GrB_Matrix_error (&err, C)) ;
647     printf ("expected error: %s\n", err) ;
648     ERR (GxB_Vector_diag (victor, C, 0, NULL)) ;
649     OK (GrB_Vector_error (&err, victor)) ;
650     printf ("expected error: %s\n", err) ;
651     GrB_Matrix_free (&C) ;
652     GrB_Vector_free (&victor) ;
653 
654     //--------------------------------------------------------------------------
655     // wrapup
656     //--------------------------------------------------------------------------
657 
658     GrB_Type_free_(&Wild) ;
659     GB_mx_put_global (true) ;
660     fclose (f) ;
661     printf ("\nAll errors printed above were expected.\n") ;
662     printf ("GB_mex_about2: all tests passed\n\n") ;
663 }
664 
665