1 //------------------------------------------------------------------------------
2 // gb_matlab.h: definitions for MATLAB interface for SuiteSparse:GraphBLAS
3 //------------------------------------------------------------------------------
4 
5 // SuiteSparse:GraphBLAS, Timothy A. Davis, (c) 2017-2021, All Rights Reserved.
6 // SPDX-License-Identifier: GPL-3.0-or-later
7 
8 //------------------------------------------------------------------------------
9 
10 // This MATLAB interface depends heavily on internal details of the
11 // SuiteSparse:GraphBLAS library.  Thus, GB.h is #include'd, not just
12 // GraphBLAS.h.
13 
14 #ifndef GB_MATLAB_H
15 #define GB_MATLAB_H
16 
17 #include "GB_matlab_helper.h"
18 #include "mex.h"
19 #include <ctype.h>
20 
21 //------------------------------------------------------------------------------
22 // error handling and test coverage
23 //------------------------------------------------------------------------------
24 
25 #ifdef GBCOV
26 #define GBCOV_MAX 1000
27 extern int64_t gbcov [GBCOV_MAX] ;
28 extern int gbcov_max ;
29 void gbcov_get (void) ;
30 void gbcov_put (void) ;
31 #define GB_COV_PUT gbcov_put ( )
32 #else
33 #define GB_COV_PUT
34 #endif
35 
36 #define GB_WRAPUP                                           \
37 {                                                           \
38     GB_COV_PUT ;                                            \
39     if (GB_Global_memtable_n ( ) != 0)                      \
40     {                                                       \
41         printf ("GrB memory leak!\n") ;                     \
42         GB_Global_memtable_dump ( ) ;                       \
43         mexErrMsgIdAndTxt ("GrB:error", "memory leak") ;    \
44     }                                                       \
45 }
46 
47 #define ERROR2(message, arg)                                \
48 {                                                           \
49     GB_COV_PUT ;                                            \
50     mexErrMsgIdAndTxt ("GrB:error", message, arg) ;         \
51 }
52 
53 #define ERROR(message)                                      \
54 {                                                           \
55     GB_COV_PUT ;                                            \
56     mexErrMsgIdAndTxt ("GrB:error", message) ;              \
57 }
58 
59 #define CHECK_ERROR(error,message) if (error) ERROR (message) ;
60 
61 #define OK(method) CHECK_ERROR ((method) != GrB_SUCCESS, "GrB:error") ;
62 
63 #define OK1(C,method)                                       \
64 {                                                           \
65     if ((method) != GrB_SUCCESS)                            \
66     {                                                       \
67         char *message ;                                     \
68         GrB_Matrix_error (&message, C) ;                    \
69         ERROR (message) ;                                   \
70     }                                                       \
71 }
72 
73 //------------------------------------------------------------------------------
74 // basic macros
75 //------------------------------------------------------------------------------
76 
77 // MATCH(s,t) compares two strings and returns true if equal
78 #define MATCH(s,t) (strcmp(s,t) == 0)
79 
80 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
81 
82 // largest integer representable as a double
83 #define FLINTMAX (((int64_t) 1) << 53)
84 
85 //------------------------------------------------------------------------------
86 // typedefs
87 //------------------------------------------------------------------------------
88 
89 typedef enum            // output of GrB.methods
90 {
91     KIND_GRB = 0,       // return a MATLAB struct containing a GrB_Matrix
92     KIND_SPARSE = 1,    // return a MATLAB sparse matrix
93     KIND_FULL = 2,      // return a MATLAB full matrix
94     KIND_MATLAB = 3     // return a MATLAB sparse or full matrix (full if all
95                         // entries present, sparse otherwise)
96 }
97 kind_enum_t ;
98 
99 // [I,J,X] = GrB.extracttuples (A, desc) can return I and J in three ways:
100 //
101 //      one-based double:   just like [I,J,X] = find (A)
102 //      one-based int64:    I and J are one-based, just as in MATLAB, but
103 //                          are int64.
104 //      zero-based int64:   I and J are zero-based, and int64.  This is meant
105 //                          for internal use in GrB methods, but it is also
106 //                          the
107 //
108 // The descriptor is also used for GrB.build, GrB.extract, GrB.assign, and
109 // GrB.subassign.  In that case, the type is determined by the input arrays I
110 // and J.
111 //
112 // desc.base can be one of several strings:
113 //
114 //      'default'           the default is used
115 //      'zero-based'        the type is always int64
116 //      'one-based'         the type is inferred from the inputs I and J
117 //      'one-based int'     the type is int64, and one-based
118 //      'one-based double'  the type is double, and one-based
119 //
120 // Note that there is no option for zero-based double.
121 
122 typedef enum            // type of indices
123 {
124     BASE_DEFAULT = 0,   // The type is determined automatically.  It is
125                         // BASE_1_DOUBLE, unless the dimensions are
126                         // too big for a flint (max(size(A)) > flintmax).  In
127                         // that case, BASE_1_INT64 is used.
128     BASE_0_INT64 = 1,   // indices are returned as zero-based int64 values
129     BASE_1_INT64 = 2,   // indices are returned as one-based int64
130     BASE_1_DOUBLE = 3   // this is the typical default: one-based double
131 }
132 base_enum_t ;
133 
134 //------------------------------------------------------------------------------
135 // gb_double_to_integer: convert a double to int64_t and check conversion
136 //------------------------------------------------------------------------------
137 
gb_double_to_integer(double x)138 static inline int64_t gb_double_to_integer (double x)
139 {
140     int64_t i = (int64_t) x ;
141     CHECK_ERROR (x != (double) i, "index must be integer") ;
142     return (i) ;
143 }
144 
145 //------------------------------------------------------------------------------
146 // function prototypes
147 //------------------------------------------------------------------------------
148 
149 GrB_Type gb_mxarray_type        // return the GrB_Type of a MATLAB matrix
150 (
151     const mxArray *X
152 ) ;
153 
154 GrB_Type gb_mxstring_to_type    // return the GrB_Type from a MATLAB string
155 (
156     const mxArray *S        // MATLAB mxArray containing a string
157 ) ;
158 
159 void gb_mxstring_to_string  // copy a MATLAB string into a C string
160 (
161     char *string,           // size at least maxlen+1
162     const size_t maxlen,    // length of string
163     const mxArray *S,       // MATLAB mxArray containing a string
164     const char *name        // name of the mxArray
165 ) ;
166 
167 GrB_Matrix gb_get_shallow   // return a shallow copy of MATLAB sparse matrix
168 (
169     const mxArray *X
170 ) ;
171 
172 GrB_Matrix gb_get_deep      // return a deep GrB_Matrix copy of a MATLAB X
173 (
174     const mxArray *X        // input MATLAB matrix (sparse or struct)
175 ) ;
176 
177 GrB_Type gb_type_to_mxstring    // return the MATLAB string from a GrB_Type
178 (
179     const GrB_Type type
180 ) ;
181 
182 GrB_Matrix gb_typecast          // C = (type) A, where C is deep
183 (
184     GrB_Matrix A,               // may be shallow
185     GrB_Type type,              // if NULL, copy but do not typecast
186     GxB_Format_Value fmt,       // format of C
187     int sparsity                // sparsity control for C, if 0 use A
188 ) ;
189 
190 GrB_Matrix gb_new               // create and empty matrix C
191 (
192     GrB_Type type,              // type of C
193     GrB_Index nrows,            // # of rows
194     GrB_Index ncols,            // # of rows
195     GxB_Format_Value fmt,       // requested format
196     int sparsity                // sparsity control for C, 0 for default
197 ) ;
198 
199 void gb_abort ( void ) ;    // failure
200 
201 int gb_flush ( void ) ;     // flush mexPrintf output to MATLAB Command Window
202 
203 void gb_usage       // check usage and make sure GxB_init has been called
204 (
205     bool ok,                // if false, then usage is not correct
206     const char *message     // error message if usage is not correct
207 ) ;
208 
209 void gb_find_dot            // find 1st and 2nd dot ('.') in a string
210 (
211     int32_t position [2],   // positions of one or two dots
212     const char *s           // null-terminated string to search
213 ) ;
214 
215 GrB_Type gb_string_to_type      // return the GrB_Type from a string
216 (
217     const char *classname
218 ) ;
219 
220 GrB_UnaryOp gb_mxstring_to_unop         // return unary operator from a string
221 (
222     const mxArray *mxstring,            // MATLAB string
223     const GrB_Type default_type         // default type if not in the string
224 ) ;
225 
226 GrB_UnaryOp gb_string_to_unop           // return unary operator from a string
227 (
228     char *opstring,                     // string defining the operator
229     const GrB_Type default_type         // default type if not in the string
230 ) ;
231 
232 GrB_UnaryOp gb_string_and_type_to_unop  // return op from string and type
233 (
234     const char *op_name,        // name of the operator, as a string
235     const GrB_Type type,        // type of the x,y inputs to the operator
236     const bool type_not_given   // true if no type present in the string
237 ) ;
238 
239 GrB_BinaryOp gb_mxstring_to_binop       // return binary operator from a string
240 (
241     const mxArray *mxstring,            // MATLAB string
242     const GrB_Type atype,               // type of A
243     const GrB_Type btype                // type of B
244 ) ;
245 
246 GrB_BinaryOp gb_string_to_binop         // return binary operator from a string
247 (
248     char *opstring,                     // string defining the operator
249     const GrB_Type atype,               // type of A
250     const GrB_Type btype                // type of B
251 ) ;
252 
253 GrB_BinaryOp gb_string_and_type_to_binop    // return op from string and type
254 (
255     const char *op_name,        // name of the operator, as a string
256     const GrB_Type type,        // type of the x,y inputs to the operator
257     const bool type_not_given   // true if no type present in the string
258 ) ;
259 
260 GrB_Semiring gb_mxstring_to_semiring    // return semiring from a string
261 (
262     const mxArray *mxstring,            // MATLAB string
263     const GrB_Type atype,               // type of A
264     const GrB_Type btype                // type of B
265 ) ;
266 
267 GrB_Semiring gb_string_to_semiring      // return a semiring from a string
268 (
269     char *semiring_string,              // string defining the semiring
270     const GrB_Type atype,               // type of A
271     const GrB_Type btype                // type of B
272 ) ;
273 
274 GrB_Semiring gb_semiring            // built-in semiring, or NULL if error
275 (
276     const GrB_BinaryOp add,         // add operator
277     const GrB_BinaryOp mult         // multiply operator
278 ) ;
279 
280 GrB_Descriptor gb_mxarray_to_descriptor // new descriptor, or NULL if none
281 (
282     const mxArray *desc_matlab, // MATLAB struct with possible descriptor
283     kind_enum_t *kind,          // GrB, sparse, or full
284     GxB_Format_Value *fmt,      // by row or by col
285     int *sparsity,              // hypersparse/sparse/bitmap/full
286     base_enum_t *base           // 0-based int, 1-based int, or 1-based double
287 ) ;
288 
289 GrB_Matrix gb_expand_to_full    // C = full (A), and typecast
290 (
291     const GrB_Matrix A,         // input matrix to expand to full
292     GrB_Type type,              // type of C, if NULL use the type of A
293     GxB_Format_Value fmt,       // format of C
294     GrB_Matrix id               // identity value, use zero if NULL
295 ) ;
296 
297 mxArray *gb_export_to_mxstruct  // return exported MATLAB struct G
298 (
299     GrB_Matrix *A_handle        // matrix to export; freed on output
300 ) ;
301 
302 mxArray *gb_export_to_mxsparse  // return exported MATLAB sparse matrix S
303 (
304     GrB_Matrix *A_handle        // matrix to export; freed on output
305 ) ;
306 
307 mxArray *gb_export_to_mxfull    // return exported MATLAB full matrix F
308 (
309     void **X_handle,            // pointer to array to export
310     const GrB_Index nrows,      // dimensions of F
311     const GrB_Index ncols,
312     GrB_Type type               // type of the array
313 ) ;
314 
315 mxArray *gb_export              // return the exported MATLAB matrix or struct
316 (
317     GrB_Matrix *C_handle,       // GrB_Matrix to export and free
318     kind_enum_t kind            // GrB, sparse, or full
319 ) ;
320 
321 GxB_SelectOp gb_string_to_selectop      // return select operator from a string
322 (
323     char *opstring                      // string defining the operator
324 ) ;
325 
326 GxB_SelectOp gb_mxstring_to_selectop    // return select operator from a string
327 (
328     const mxArray *mxstring             // MATLAB string
329 ) ;
330 
331 bool gb_mxarray_is_scalar   // true if MATLAB array is a scalar
332 (
333     const mxArray *S
334 ) ;
335 
336 bool gb_mxarray_is_empty    // true if MATLAB array is NULL, or 2D and 0-by-0
337 (
338     const mxArray *S
339 ) ;
340 
341 void gb_mxfree              // mxFree wrapper
342 (
343     void **p_handle         // handle to pointer to be freed
344 ) ;
345 
346 int64_t *gb_mxarray_to_list     // return List of integers
347 (
348     const mxArray *mxList,      // list to extract
349     base_enum_t base,           // input is zero-based or one-based
350     bool *allocated,            // true if output list was allocated
351     int64_t *len,               // length of list
352     int64_t *List_max           // max entry in the list, if computed
353 ) ;
354 
355 GrB_Index *gb_mxcell_to_index   // return index list I
356 (
357     const mxArray *I_cell,      // MATLAB cell array
358     base_enum_t base,           // I is one-based or zero-based
359     const GrB_Index n,          // dimension of matrix being indexed
360     bool *I_allocated,          // true if output array I is allocated
361     GrB_Index *ni               // length (I)
362 ) ;
363 
364 GrB_BinaryOp gb_first_binop         // return GrB_FIRST_[type] operator
365 (
366     const GrB_Type type
367 ) ;
368 
369 GrB_Monoid gb_binop_to_monoid           // return monoid from a binary op
370 (
371     GrB_BinaryOp op
372 ) ;
373 
374 GrB_Monoid gb_string_to_monoid          // return monoid from a string
375 (
376     char *opstring,                     // string defining the operator
377     const GrB_Type type                 // default type if not in the string
378 ) ;
379 
380 GrB_Monoid gb_mxstring_to_monoid        // return monoid from a string
381 (
382     const mxArray *mxstring,            // MATLAB string
383     const GrB_Type type                 // default type if not in the string
384 ) ;
385 
386 bool gb_mxstring_to_format      // true if a valid format is found
387 (
388     // input
389     const mxArray *mxformat,    // MATLAB string, 'by row' or 'by col'
390     // output
391     GxB_Format_Value *fmt,
392     int *sparsity
393 ) ;
394 
395 void gb_matrix_assign_scalar
396 (
397     GrB_Matrix C,               // C can be of any type
398     const GrB_Matrix M,
399     const GrB_BinaryOp accum,
400     const GrB_Matrix A,
401     const GrB_Index *I,
402     const GrB_Index ni,
403     const GrB_Index *J,
404     const GrB_Index nj,
405     const GrB_Descriptor desc,
406     bool do_subassign           // true: use GxB_subassign, false: GrB_assign
407 ) ;
408 
409 void gb_assign                  // gbassign or gbsubassign mexFunctions
410 (
411     int nargout,                // # output arguments for mexFunction
412     mxArray *pargout [ ],       // output arguments for mexFunction
413     int nargin,                 // # input arguments for mexFunction
414     const mxArray *pargin [ ],  // input arguments for mexFunction
415     bool do_subassign,          // true: do subassign, false: do assign
416     const char *usage           // usage string to print if error
417 ) ;
418 
419 GrB_Matrix gb_by_col            // return the matrix by column
420 (
421     GrB_Matrix *A_copy_handle,  // copy made of A, stored by column, or NULL
422     GrB_Matrix A_input          // input matrix, by row or column
423 ) ;
424 
425 GxB_Format_Value gb_default_format      // GxB_BY_ROW or GxB_BY_COL
426 (
427     GrB_Index nrows,        // row vectors are stored by row
428     GrB_Index ncols         // column vectors are stored by column
429 ) ;
430 
431 bool gb_is_vector               // true if A is a row or column vector
432 (
433     GrB_Matrix A                // GrB_Matrix to query
434 ) ;
435 
436 GxB_Format_Value gb_get_format          // GxB_BY_ROW or GxB_BY_COL
437 (
438     GrB_Index cnrows,                   // C is cnrows-by-cncols
439     GrB_Index cncols,
440     GrB_Matrix A,                       // may be NULL
441     GrB_Matrix B,                       // may be NULL
442     GxB_Format_Value fmt_descriptor     // may be GxB_NO_FORMAT
443 ) ;
444 
445 GxB_Format_Value gb_get_sparsity        // 1 to 15
446 (
447     GrB_Matrix A,                       // may be NULL
448     GrB_Matrix B,                       // may be NULL
449     int sparsity_default                // may be 0
450 ) ;
451 
452 bool gb_is_equal            // true if A == B, false if A ~= B
453 (
454     GrB_Matrix A,
455     GrB_Matrix B
456 ) ;
457 
458 bool gb_is_all              // true if op (A,B) is all true, false otherwise
459 (
460     GrB_Matrix A,
461     GrB_Matrix B,
462     GrB_BinaryOp op
463 ) ;
464 
465 bool gb_isnan32      (GrB_Index i, GrB_Index j, const void *x, const void *b) ;
466 bool gb_isnan64      (GrB_Index i, GrB_Index j, const void *x, const void *b) ;
467 bool gb_isnotnan32   (GrB_Index i, GrB_Index j, const void *x, const void *b) ;
468 bool gb_isnotnan64   (GrB_Index i, GrB_Index j, const void *x, const void *b) ;
469 bool gb_isnanfc32    (GrB_Index i, GrB_Index j, const void *x, const void *b) ;
470 bool gb_isnanfc64    (GrB_Index i, GrB_Index j, const void *x, const void *b) ;
471 bool gb_isnotnanfc32 (GrB_Index i, GrB_Index j, const void *x, const void *b) ;
472 bool gb_isnotnanfc64 (GrB_Index i, GrB_Index j, const void *x, const void *b) ;
473 
474 void gb_get_mxargs
475 (
476     // input:
477     int nargin,                 // # input arguments for mexFunction
478     const mxArray *pargin [ ],  // input arguments for mexFunction
479     const char *usage,          // usage to print, if too many args appear
480     // output:
481     const mxArray *Matrix [4],  // matrix arguments
482     int *nmatrices,             // # of matrix arguments
483     const mxArray *String [2],  // string arguments
484     int *nstrings,              // # of string arguments
485     const mxArray *Cell [2],    // cell array arguments
486     int *ncells,                // # of cell array arguments
487     GrB_Descriptor *desc,       // last argument is always the descriptor
488     base_enum_t *base,          // desc.base
489     kind_enum_t *kind,          // desc.kind
490     GxB_Format_Value *fmt,      // desc.format : by row or by col
491     int *sparsity               // desc.format : hypersparse/sparse/bitmap/full
492 ) ;
493 
494 int64_t gb_norm_kind (const mxArray *arg) ;
495 
496 double gb_norm              // compute norm (A,kind)
497 (
498     GrB_Matrix A,
499     int64_t norm_kind       // 0, 1, 2, INT64_MAX, or INT64_MIN
500 ) ;
501 
502 GrB_Type gb_default_type        // return the default type to use
503 (
504     const GrB_Type atype,       // type of the A matrix
505     const GrB_Type btype        // type of the B matrix
506 ) ;
507 
508 bool gb_is_integer (const GrB_Type type) ;
509 
510 bool gb_is_float (const GrB_Type type) ;
511 
512 GrB_BinaryOp gb_round_binop (const GrB_Type type) ;
513 
514 mxArray *gb_mxclass_to_mxstring (mxClassID class, bool is_complex) ;
515 
516 #endif
517 
518