1 //------------------------------------------------------------------------------
2 // GB.h: definitions visible only inside GraphBLAS
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 #ifndef GB_H
11 #define GB_H
12 
13 //------------------------------------------------------------------------------
14 // definitions that modify GraphBLAS.h
15 //------------------------------------------------------------------------------
16 
17 #include "GB_warnings.h"
18 #ifndef MATLAB_MEX_FILE
19 #define GB_LIBRARY
20 #endif
21 
22 //------------------------------------------------------------------------------
23 // user-visible GraphBLAS.h
24 //------------------------------------------------------------------------------
25 
26 #include "GraphBLAS.h"
27 
28 //------------------------------------------------------------------------------
29 // internal #include files
30 //------------------------------------------------------------------------------
31 
32 #include "GB_prefix.h"
33 #include "GB_dev.h"
34 #include "GB_defaults.h"
35 #include "GB_compiler.h"
36 #include "GB_coverage.h"
37 #include "GB_index.h"
38 #include "GB_cplusplus.h"
39 #include "GB_Global.h"
40 #include "GB_printf.h"
41 #include "GB_assert.h"
42 #include "GB_opaque.h"
43 #include "GB_casting.h"
44 #include "GB_math.h"
45 #include "GB_bitwise.h"
46 #include "GB_binary_search.h"
47 #include "GB_check.h"
48 #include "GB_nnz.h"
49 #include "GB_zombie.h"
50 #include "GB_partition.h"
51 #include "GB_omp.h"
52 #include "GB_context.h"
53 #include "GB_memory.h"
54 #include "GB_werk.h"
55 #include "GB_log2.h"
56 
57 //------------------------------------------------------------------------------
58 // more internal definitions
59 //------------------------------------------------------------------------------
60 
61 int64_t GB_Pending_n        // return # of pending tuples in A
62 (
63     GrB_Matrix A
64 ) ;
65 
66 // A is nrows-by-ncols, in either CSR or CSC format
67 #define GB_NROWS(A) ((A)->is_csc ? (A)->vlen : (A)->vdim)
68 #define GB_NCOLS(A) ((A)->is_csc ? (A)->vdim : (A)->vlen)
69 
70 // The internal content of a GrB_Matrix and GrB_Vector are identical, and
71 // inside SuiteSparse:GraphBLAS, they can be typecasted between each other.
72 // This typecasting feature should not be done in user code, however, since it
73 // is not supported in the API.  All GrB_Vector objects can be safely
74 // typecasted into a GrB_Matrix, but not the other way around.  The GrB_Vector
75 // object is more restrictive.  The GB_VECTOR_OK(v) macro defines the content
76 // that all GrB_Vector objects must have.
77 
78 // GB_VECTOR_OK(v) is used mainly for assertions, but also to determine when it
79 // is safe to typecast an n-by-1 GrB_Matrix (in standard CSC format) into a
80 // GrB_Vector.  This is not done in the main SuiteSparse:GraphBLAS library, but
81 // in the GraphBLAS/Test directory only.  The macro is also used in
82 // GB_Vector_check, to ensure the content of a GrB_Vector is valid.
83 
84 #define GB_VECTOR_OK(v)                     \
85 (                                           \
86     ((v) != NULL) &&                        \
87     ((v)->is_csc == true) &&                \
88     ((v)->plen == 1 || (v)->plen == -1) &&  \
89     ((v)->vdim == 1) &&                     \
90     ((v)->nvec == 1) &&                     \
91     ((v)->h == NULL)                        \
92 )
93 
94 // A GxB_Vector is a GrB_Vector of length 1
95 #define GB_SCALAR_OK(v) (GB_VECTOR_OK(v) && ((v)->vlen == 1))
96 
97 //------------------------------------------------------------------------------
98 // aliased and shallow objects
99 //------------------------------------------------------------------------------
100 
101 // GraphBLAS allows all inputs to all user-accessible objects to be aliased, as
102 // in GrB_mxm (C, C, accum, C, C, ...), which is valid.  Internal routines are
103 // more restrictive.
104 
105 // GB_aliased also checks the content of A and B
106 GB_PUBLIC   // accessed by the MATLAB tests in GraphBLAS/Test only
107 bool GB_aliased             // determine if A and B are aliased
108 (
109     GrB_Matrix A,           // input A matrix
110     GrB_Matrix B            // input B matrix
111 ) ;
112 
113 // matrices returned to the user are never shallow; internal matrices may be
114 GB_PUBLIC                       // used by the MATLAB interface
115 bool GB_is_shallow              // true if any component of A is shallow
116 (
117     GrB_Matrix A                // matrix to query
118 ) ;
119 
120 //------------------------------------------------------------------------------
121 // internal GraphBLAS functions
122 //------------------------------------------------------------------------------
123 
124 GrB_Info GB_init            // start up GraphBLAS
125 (
126     const GrB_Mode mode,    // blocking or non-blocking mode
127 
128     // pointers to memory management functions
129     void * (* malloc_function  ) (size_t),
130     void * (* calloc_function  ) (size_t, size_t),
131     void * (* realloc_function ) (void *, size_t),
132     void   (* free_function    ) (void *),
133     bool malloc_is_thread_safe,
134 
135     bool caller_is_GxB_cuda_init,       // true for GxB_cuda_init only
136 
137     GB_Context Context      // from GrB_init or GxB_init
138 ) ;
139 
140 typedef enum                    // input parameter to GB_new and GB_new_bix
141 {
142     GB_Ap_calloc,               // 0: calloc A->p, malloc A->h if hypersparse
143     GB_Ap_malloc,               // 1: malloc A->p, malloc A->h if hypersparse
144     GB_Ap_null                  // 2: do not allocate A->p or A->h
145 }
146 GB_Ap_code ;
147 
148 GB_PUBLIC   // accessed by the MATLAB tests in GraphBLAS/Test only
149 GrB_Info GB_new                 // create matrix, except for indices & values
150 (
151     GrB_Matrix *Ahandle,        // handle of matrix to create
152     const bool A_static_header, // true if Ahandle is statically allocated
153     const GrB_Type type,        // matrix type
154     const int64_t vlen,         // length of each vector
155     const int64_t vdim,         // number of vectors
156     const GB_Ap_code Ap_option, // allocate A->p and A->h, or leave NULL
157     const bool is_csc,          // true if CSC, false if CSR
158     const int sparsity,         // hyper, sparse, bitmap, full, or
159                                 // auto (hyper + sparse)
160     const float hyper_switch,   // A->hyper_switch, ignored if auto
161     const int64_t plen,         // size of A->p and A->h, if A hypersparse.
162                                 // Ignored if A is not hypersparse.
163     GB_Context Context
164 ) ;
165 
166 GrB_Info GB_new_bix             // create a new matrix, incl. A->b, A->i, A->x
167 (
168     GrB_Matrix *Ahandle,        // output matrix to create
169     const bool A_static_header, // true if Ahandle is statically allocated
170     const GrB_Type type,        // type of output matrix
171     const int64_t vlen,         // length of each vector
172     const int64_t vdim,         // number of vectors
173     const GB_Ap_code Ap_option, // allocate A->p and A->h, or leave NULL
174     const bool is_csc,          // true if CSC, false if CSR
175     const int sparsity,         // hyper, sparse, bitmap, full, or auto
176     const bool bitmap_calloc,   // if true, calloc A->b, otherwise use malloc
177     const float hyper_switch,   // A->hyper_switch, unless auto
178     const int64_t plen,         // size of A->p and A->h, if hypersparse
179     const int64_t anz,          // number of nonzeros the matrix must hold
180     const bool numeric,         // if true, allocate A->x, else A->x is NULL
181     GB_Context Context
182 ) ;
183 
184 GrB_Info GB_hyper_realloc
185 (
186     GrB_Matrix A,               // matrix with hyperlist to reallocate
187     int64_t plen_new,           // new size of A->p and A->h
188     GB_Context Context
189 ) ;
190 
191 GrB_Info GB_clear           // clear a matrix, type and dimensions unchanged
192 (
193     GrB_Matrix A,           // matrix to clear
194     GB_Context Context
195 ) ;
196 
197 GrB_Info GB_dup             // make an exact copy of a matrix
198 (
199     GrB_Matrix *Chandle,    // handle of output matrix to create
200     const GrB_Matrix A,     // input matrix to copy
201     GB_Context Context
202 ) ;
203 
204 GrB_Info GB_dup2            // make an exact copy of a matrix
205 (
206     GrB_Matrix *Chandle,    // handle of output matrix to create
207     const GrB_Matrix A,     // input matrix to copy
208     const bool numeric,     // if true, duplicate the numeric values
209     const GrB_Type ctype,   // type of C, if numeric is false
210     GB_Context Context
211 ) ;
212 
213 void GB_memcpy                  // parallel memcpy
214 (
215     void *dest,                 // destination
216     const void *src,            // source
217     size_t n,                   // # of bytes to copy
218     int nthreads                // # of threads to use
219 ) ;
220 
221 void GB_memset                  // parallel memset
222 (
223     void *dest,                 // destination
224     const int c,                // value to to set
225     size_t n,                   // # of bytes to set
226     int nthreads                // # of threads to use
227 ) ;
228 
229 GrB_Info GB_nvals           // get the number of entries in a matrix
230 (
231     GrB_Index *nvals,       // matrix has nvals entries
232     const GrB_Matrix A,     // matrix to query
233     GB_Context Context
234 ) ;
235 
236 GrB_Info GB_matvec_type            // get the type of a matrix
237 (
238     GrB_Type *type,         // returns the type of the matrix
239     const GrB_Matrix A,     // matrix to query
240     GB_Context Context
241 ) ;
242 
243 GB_PUBLIC   // accessed by the MATLAB tests in GraphBLAS/Test only
244 GrB_Info GB_bix_alloc       // allocate A->b, A->i, and A->x space in a matrix
245 (
246     GrB_Matrix A,           // matrix to allocate space for
247     const GrB_Index nzmax,  // number of entries the matrix can hold
248     const bool is_bitmap,   // if true, allocate A->b, otherwise A->b is NULL
249     const bool bitmap_calloc,   // if true, calloc A->b, otherwise use malloc
250     const bool is_sparse,   // if true, allocate A->i, otherwise A->i is NULL
251     const bool numeric,     // if true, allocate A->x, otherwise A->x is NULL
252     GB_Context Context
253 ) ;
254 
255 GB_PUBLIC   // accessed by the MATLAB tests in GraphBLAS/Test only
256 GrB_Info GB_ix_realloc      // reallocate space in a matrix
257 (
258     GrB_Matrix A,               // matrix to allocate space for
259     const int64_t nzmax_new,    // new number of entries the matrix can hold
260     const bool numeric,         // if true, reallocate A->x, else A->x is NULL
261     GB_Context Context
262 ) ;
263 
264 GrB_Info GB_ix_resize       // resize a matrix
265 (
266     GrB_Matrix A,           // matrix to resize (sparse/hyper, not full/bitmap)
267     const int64_t anz_new,  // required new nnz(A)
268     GB_Context Context
269 ) ;
270 
271 GB_PUBLIC   // accessed by the MATLAB tests in GraphBLAS/Test only
272 void GB_bix_free                // free A->b, A->i, and A->x of a matrix
273 (
274     GrB_Matrix A                // matrix with content to free
275 ) ;
276 
277 GB_PUBLIC   // accessed by the MATLAB tests in GraphBLAS/Test only
278 void GB_ph_free                 // free A->p and A->h of a matrix
279 (
280     GrB_Matrix A                // matrix with content to free
281 ) ;
282 
283 void GB_phbix_free              // free all content of a matrix
284 (
285     GrB_Matrix A                // matrix with content to free
286 ) ;
287 
288 GB_PUBLIC   // accessed by the MATLAB tests in GraphBLAS/Test only
289 bool GB_Type_compatible             // check if two types can be typecast
290 (
291     const GrB_Type atype,
292     const GrB_Type btype
293 ) ;
294 
295 //------------------------------------------------------------------------------
296 // GB_code_compatible: return true if domains are compatible
297 //------------------------------------------------------------------------------
298 
299 // Two domains are compatible for typecasting between them if both are built-in
300 // types (of any kind) or if both are the same user-defined type.  This
301 // function does not have the type itself, but just the code.  If the types are
302 // available, GB_Type_compatible should be called instead.
303 
GB_code_compatible(const GB_Type_code acode,const GB_Type_code bcode)304 static inline bool GB_code_compatible       // true if two types can be typecast
305 (
306     const GB_Type_code acode,   // type code of a
307     const GB_Type_code bcode    // type code of b
308 )
309 {
310 
311     bool a_user = (acode == GB_UDT_code) ;
312     bool b_user = (bcode == GB_UDT_code) ;
313 
314     if (a_user || b_user)
315     {
316         // both a and b must be user-defined.  They should be the same
317         // user-defined type, but the caller does not have the actual type,
318         // just the code.
319         return (a_user && b_user) ;
320     }
321     else
322     {
323         // any built-in domain is compatible with any other built-in domain
324         return (true) ;
325     }
326 }
327 
328 
329 //------------------------------------------------------------------------------
330 // GB_task_struct: parallel task descriptor
331 //------------------------------------------------------------------------------
332 
333 // The element-wise computations (GB_add, GB_emult, and GB_mask) compute
334 // C(:,j)<M(:,j)> = op (A (:,j), B(:,j)).  They are parallelized by slicing the
335 // work into tasks, described by the GB_task_struct.
336 
337 // There are two kinds of tasks.  For a coarse task, kfirst <= klast, and the
338 // task computes all vectors in C(:,kfirst:klast), inclusive.  None of the
339 // vectors are sliced and computed by other tasks.  For a fine task, klast is
340 // -1.  The task computes part of the single vector C(:,kfirst).  It starts at
341 // pA in Ai,Ax, at pB in Bi,Bx, and (if M is present) at pM in Mi,Mx.  It
342 // computes C(:,kfirst), starting at pC in Ci,Cx.
343 
344 // GB_subref also uses the TaskList.  It has 12 kinds of fine tasks,
345 // corresponding to each of the 12 methods used in GB_subref_template.  For
346 // those fine tasks, method = -TaskList [taskid].klast defines the method to
347 // use.
348 
349 // The GB_subassign functions use the TaskList, in many different ways.
350 
351 typedef struct          // task descriptor
352 {
353     int64_t kfirst ;    // C(:,kfirst) is the first vector in this task.
354     int64_t klast  ;    // C(:,klast) is the last vector in this task.
355     int64_t pC ;        // fine task starts at Ci, Cx [pC]
356     int64_t pC_end ;    // fine task ends at Ci, Cx [pC_end-1]
357     int64_t pM ;        // fine task starts at Mi, Mx [pM]
358     int64_t pM_end ;    // fine task ends at Mi, Mx [pM_end-1]
359     int64_t pA ;        // fine task starts at Ai, Ax [pA]
360     int64_t pA_end ;    // fine task ends at Ai, Ax [pA_end-1]
361     int64_t pB ;        // fine task starts at Bi, Bx [pB]
362     int64_t pB_end ;    // fine task ends at Bi, Bx [pB_end-1]
363     int64_t len ;       // fine task handles a subvector of this length
364 }
365 GB_task_struct ;
366 
367 // GB_REALLOC_TASK_WERK: Allocate or reallocate the TaskList so that it can
368 // hold at least ntasks.  Double the size if it's too small.
369 
370 #define GB_REALLOC_TASK_WERK(TaskList,ntasks,max_ntasks)                    \
371 {                                                                           \
372     if ((ntasks) >= max_ntasks)                                             \
373     {                                                                       \
374         bool ok ;                                                           \
375         int nold = (max_ntasks == 0) ? 0 : (max_ntasks + 1) ;               \
376         int nnew = 2 * (ntasks) + 1 ;                                       \
377         GB_REALLOC_WERK (TaskList, nnew, nold, GB_task_struct,              \
378             &TaskList_size, &ok, NULL) ;                                    \
379         if (!ok)                                                            \
380         {                                                                   \
381             /* out of memory */                                             \
382             GB_FREE_ALL ;                                                   \
383             return (GrB_OUT_OF_MEMORY) ;                                    \
384         }                                                                   \
385         for (int t = nold ; t < nnew ; t++)                                 \
386         {                                                                   \
387             TaskList [t].kfirst = -1 ;                                      \
388             TaskList [t].klast  = INT64_MIN ;                               \
389             TaskList [t].pA     = INT64_MIN ;                               \
390             TaskList [t].pA_end = INT64_MIN ;                               \
391             TaskList [t].pB     = INT64_MIN ;                               \
392             TaskList [t].pB_end = INT64_MIN ;                               \
393             TaskList [t].pC     = INT64_MIN ;                               \
394             TaskList [t].pC_end = INT64_MIN ;                               \
395             TaskList [t].pM     = INT64_MIN ;                               \
396             TaskList [t].pM_end = INT64_MIN ;                               \
397             TaskList [t].len    = INT64_MIN ;                               \
398         }                                                                   \
399         max_ntasks = 2 * (ntasks) ;                                         \
400     }                                                                       \
401     ASSERT ((ntasks) < max_ntasks) ;                                        \
402 }
403 
404 GrB_Info GB_ewise_slice
405 (
406     // output:
407     GB_task_struct **p_TaskList,    // array of structs
408     size_t *p_TaskList_size,        // size of TaskList
409     int *p_ntasks,                  // # of tasks constructed
410     int *p_nthreads,                // # of threads for eWise operation
411     // input:
412     const int64_t Cnvec,            // # of vectors of C
413     const int64_t *restrict Ch,     // vectors of C, if hypersparse
414     const int64_t *restrict C_to_M, // mapping of C to M
415     const int64_t *restrict C_to_A, // mapping of C to A
416     const int64_t *restrict C_to_B, // mapping of C to B
417     bool Ch_is_Mh,                  // if true, then Ch == Mh; GB_add only
418     const GrB_Matrix M,             // mask matrix to slice (optional)
419     const GrB_Matrix A,             // matrix to slice
420     const GrB_Matrix B,             // matrix to slice
421     GB_Context Context
422 ) ;
423 
424 GB_PUBLIC   // accessed by the MATLAB tests in GraphBLAS/Test only
425 void GB_slice_vector
426 (
427     // output: return i, pA, and pB
428     int64_t *p_i,                   // work starts at A(i,kA) and B(i,kB)
429     int64_t *p_pM,                  // M(i:end,kM) starts at pM
430     int64_t *p_pA,                  // A(i:end,kA) starts at pA
431     int64_t *p_pB,                  // B(i:end,kB) starts at pB
432     // input:
433     const int64_t pM_start,         // M(:,kM) starts at pM_start in Mi,Mx
434     const int64_t pM_end,           // M(:,kM) ends at pM_end-1 in Mi,Mx
435     const int64_t *restrict Mi,     // indices of M (or NULL)
436     const int64_t pA_start,         // A(:,kA) starts at pA_start in Ai,Ax
437     const int64_t pA_end,           // A(:,kA) ends at pA_end-1 in Ai,Ax
438     const int64_t *restrict Ai,     // indices of A
439     const int64_t pB_start,         // B(:,kB) starts at pB_start in Bi,Bx
440     const int64_t pB_end,           // B(:,kB) ends at pB_end-1 in Bi,Bx
441     const int64_t *restrict Bi,     // indices of B
442     const int64_t vlen,             // A->vlen and B->vlen
443     const double target_work        // target work
444 ) ;
445 
446 void GB_task_cumsum
447 (
448     int64_t *Cp,                        // size Cnvec+1
449     const int64_t Cnvec,
450     int64_t *Cnvec_nonempty,            // # of non-empty vectors in C
451     GB_task_struct *restrict TaskList,  // array of structs
452     const int ntasks,                   // # of tasks
453     const int nthreads,                 // # of threads
454     GB_Context Context
455 ) ;
456 
457 //------------------------------------------------------------------------------
458 // GB_GET_VECTOR: get the content of a vector for a coarse/fine task
459 //------------------------------------------------------------------------------
460 
461 #define GB_GET_VECTOR(pX_start, pX_fini, pX, pX_end, Xp, kX, Xvlen)         \
462     int64_t pX_start, pX_fini ;                                             \
463     if (fine_task)                                                          \
464     {                                                                       \
465         /* A fine task operates on a slice of X(:,k) */                     \
466         pX_start = TaskList [taskid].pX ;                                   \
467         pX_fini  = TaskList [taskid].pX_end ;                               \
468     }                                                                       \
469     else                                                                    \
470     {                                                                       \
471         /* vectors are never sliced for a coarse task */                    \
472         pX_start = GBP (Xp, kX, Xvlen) ;                                    \
473         pX_fini  = GBP (Xp, kX+1, Xvlen) ;                                  \
474     }
475 
476 //------------------------------------------------------------------------------
477 
478 GrB_Info GB_transplant          // transplant one matrix into another
479 (
480     GrB_Matrix C,               // output matrix to overwrite with A
481     const GrB_Type ctype,       // new type of C
482     GrB_Matrix *Ahandle,        // input matrix to copy from and free
483     GB_Context Context
484 ) ;
485 
486 GrB_Info GB_transplant_conform      // transplant and conform hypersparsity
487 (
488     GrB_Matrix C,                   // destination matrix to transplant into
489     GrB_Type ctype,                 // type to cast into
490     GrB_Matrix *Thandle,            // source matrix
491     GB_Context Context
492 ) ;
493 
494 GB_PUBLIC   // accessed by the MATLAB tests in GraphBLAS/Test only
495 size_t GB_code_size             // return the size of a type, given its code
496 (
497     const GB_Type_code code,    // input code of the type to find the size of
498     const size_t usize          // known size of user-defined type
499 ) ;
500 
501 void GB_Matrix_free             // free a matrix
502 (
503     GrB_Matrix *Ahandle         // handle of matrix to free
504 ) ;
505 
506 //------------------------------------------------------------------------------
507 
508 GB_PUBLIC   // accessed by the MATLAB tests in GraphBLAS/Test only
509 GrB_Type GB_code_type           // return the GrB_Type corresponding to the code
510 (
511     const GB_Type_code code,    // type code to convert
512     const GrB_Type type         // user type if code is GB_UDT_code
513 ) ;
514 
515 GB_PUBLIC   // accessed by the MATLAB tests in GraphBLAS/Test only
516 void GB_pslice                      // slice Ap
517 (
518     int64_t *restrict Slice,     // size ntasks+1
519     const int64_t *restrict Ap,  // array size n+1 (NULL if full or bitmap)
520     const int64_t n,
521     const int ntasks,               // # of tasks
522     const bool perfectly_balanced
523 ) ;
524 
525 void GB_eslice
526 (
527     // output:
528     int64_t *Slice,         // array of size ntasks+1
529     // input:
530     int64_t e,              // number items to partition amongst the tasks
531     const int ntasks        // # of tasks
532 ) ;
533 
534 GB_PUBLIC   // accessed by the MATLAB tests in GraphBLAS/Test only
535 void GB_cumsum                      // cumulative sum of an array
536 (
537     int64_t *restrict count,     // size n+1, input/output
538     const int64_t n,
539     int64_t *restrict kresult,   // return k, if needed by the caller
540     int nthreads,
541     GB_Context Context
542 ) ;
543 
544 GB_PUBLIC   // accessed by the MATLAB tests in GraphBLAS/Test only
545 GrB_Info GB_Descriptor_get      // get the contents of a descriptor
546 (
547     const GrB_Descriptor desc,  // descriptor to query, may be NULL
548     bool *C_replace,            // if true replace C before C<M>=Z
549     bool *Mask_comp,            // if true use logical negation of M
550     bool *Mask_struct,          // if true use the structure of M
551     bool *In0_transpose,        // if true transpose first input
552     bool *In1_transpose,        // if true transpose second input
553     GrB_Desc_Value *AxB_method, // method for C=A*B
554     int *do_sort,               // if nonzero, sort in GrB_mxm
555     GB_Context Context
556 ) ;
557 
558 GrB_Info GB_compatible          // SUCCESS if all is OK, *_MISMATCH otherwise
559 (
560     const GrB_Type ctype,       // the type of C (matrix or scalar)
561     const GrB_Matrix C,         // the output matrix C; NULL if C is a scalar
562     const GrB_Matrix M,         // optional mask, NULL if no mask
563     const bool Mask_struct,     // true if M is structural
564     const GrB_BinaryOp accum,   // C<M> = accum(C,T) is computed
565     const GrB_Type ttype,       // type of T
566     GB_Context Context
567 ) ;
568 
569 GrB_Info GB_Mask_compatible     // check type and dimensions of mask
570 (
571     const GrB_Matrix M,         // mask to check
572     const bool Mask_struct,     // true if M is structural
573     const GrB_Matrix C,         // C<M>= ...
574     const GrB_Index nrows,      // size of output if C is NULL (see GB*assign)
575     const GrB_Index ncols,
576     GB_Context Context
577 ) ;
578 
579 GrB_Info GB_BinaryOp_compatible     // check for domain mismatch
580 (
581     const GrB_BinaryOp op,          // binary operator to check
582     const GrB_Type ctype,           // C must be compatible with op->ztype
583     const GrB_Type atype,           // A must be compatible with op->xtype
584     const GrB_Type btype,           // B must be compatible with op->ytype
585     const GB_Type_code bcode,       // B may not have a type, just a code
586     GB_Context Context
587 ) ;
588 
589 GB_PUBLIC   // accessed by the MATLAB interface only
590 bool GB_Index_multiply      // true if ok, false if overflow
591 (
592     GrB_Index *restrict c,  // c = a*b, or zero if overflow occurs
593     const int64_t a,
594     const int64_t b
595 ) ;
596 
597 GB_PUBLIC   // accessed by the MATLAB tests in GraphBLAS/Test only
598 bool GB_size_t_multiply     // true if ok, false if overflow
599 (
600     size_t *c,              // c = a*b, or zero if overflow occurs
601     const size_t a,
602     const size_t b
603 ) ;
604 
605 GrB_Info GB_extract_vector_list     // extract vector list from a matrix
606 (
607     // output:
608     int64_t *restrict J,         // size nnz(A) or more
609     // input:
610     const GrB_Matrix A,
611     GB_Context Context
612 ) ;
613 
614 GrB_Info GB_extractTuples       // extract all tuples from a matrix
615 (
616     GrB_Index *I_out,           // array for returning row indices of tuples
617     GrB_Index *J_out,           // array for returning col indices of tuples
618     void *X,                    // array for returning values of tuples
619     GrB_Index *p_nvals,         // I,J,X size on input; # tuples on output
620     const GB_Type_code xcode,   // type of array X
621     const GrB_Matrix A,         // matrix to extract tuples from
622     GB_Context Context
623 ) ;
624 
625 GrB_Info GB_Monoid_new          // create a monoid
626 (
627     GrB_Monoid *monoid,         // handle of monoid to create
628     GrB_BinaryOp op,            // binary operator of the monoid
629     const void *identity,       // identity value
630     const void *terminal,       // terminal value, if any (may be NULL)
631     const GB_Type_code idcode,  // identity and terminal type code
632     GB_Context Context
633 ) ;
634 
635 GrB_Info GB_Semiring_new            // create a semiring
636 (
637     GrB_Semiring semiring,          // semiring to create
638     GrB_Monoid add,                 // additive monoid of the semiring
639     GrB_BinaryOp multiply           // multiply operator of the semiring
640 ) ;
641 
642 //------------------------------------------------------------------------------
643 
644 GrB_Info GB_setElement              // set a single entry, C(row,col) = scalar
645 (
646     GrB_Matrix C,                   // matrix to modify
647     void *scalar,                   // scalar to set
648     const GrB_Index row,            // row index
649     const GrB_Index col,            // column index
650     const GB_Type_code scalar_code, // type of the scalar
651     GB_Context Context
652 ) ;
653 
654 GB_PUBLIC   // accessed by the MATLAB tests in GraphBLAS/Test only
655 GrB_Info GB_block   // apply all pending computations if blocking mode enabled
656 (
657     GrB_Matrix A,
658     GB_Context Context
659 ) ;
660 
661 GB_PUBLIC   // accessed by the MATLAB tests in GraphBLAS/Test only
662 bool GB_op_is_second    // return true if op is SECOND, of the right type
663 (
664     GrB_BinaryOp op,
665     GrB_Type type
666 ) ;
667 
668 
669 //------------------------------------------------------------------------------
670 
671 GB_PUBLIC   // accessed by the MATLAB tests in GraphBLAS/Test only
672 char *GB_code_string            // return a static string for a type name
673 (
674     const GB_Type_code code     // code to convert to string
675 ) ;
676 
677 GrB_Info GB_resize              // change the size of a matrix
678 (
679     GrB_Matrix A,               // matrix to modify
680     const GrB_Index nrows_new,  // new number of rows in matrix
681     const GrB_Index ncols_new,  // new number of columns in matrix
682     GB_Context Context
683 ) ;
684 
685 GB_PUBLIC   // accessed by the MATLAB tests in GraphBLAS/Test only
686 int64_t GB_nvec_nonempty        // return # of non-empty vectors
687 (
688     const GrB_Matrix A,         // input matrix to examine
689     GB_Context Context
690 ) ;
691 
692 GrB_Info GB_conform_hyper       // conform a matrix to sparse/hypersparse
693 (
694     GrB_Matrix A,               // matrix to conform
695     GB_Context Context
696 ) ;
697 
698 GrB_Info GB_hyper_prune
699 (
700     // output, not allocated on input:
701     int64_t *restrict *p_Ap, size_t *p_Ap_size,      // size nvec+1
702     int64_t *restrict *p_Ah, size_t *p_Ah_size,      // size nvec
703     int64_t *p_nvec,                // # of vectors, all nonempty
704     // input, not modified
705     const int64_t *Ap_old,          // size nvec_old+1
706     const int64_t *Ah_old,          // size nvec_old
707     const int64_t nvec_old,         // original number of vectors
708     GB_Context Context
709 ) ;
710 
711 GrB_Info GB_hypermatrix_prune
712 (
713     GrB_Matrix A,               // matrix to prune
714     GB_Context Context
715 ) ;
716 
717 GB_PUBLIC   // accessed by the MATLAB tests in GraphBLAS/Test only
718 void GB_cast_array              // typecast an array
719 (
720     GB_void *Cx,                // output array
721     const GB_Type_code code1,   // type code for Cx
722     GB_void *Ax,                // input array
723     const GB_Type_code code2,   // type code for Ax
724     const int8_t *restrict Ab,   // bitmap for Ax
725     const size_t user_size,     // size of Ax and Cx if user-defined
726     const int64_t anz,          // number of entries in Cx and Ax
727     const int nthreads          // number of threads to use
728 ) ;
729 
730 //------------------------------------------------------------------------------
731 // boiler plate macros for checking inputs and returning if an error occurs
732 //------------------------------------------------------------------------------
733 
734 // Functions use these macros to check/get their inputs and return an error
735 // if something has gone wrong.
736 
737 #define GB_OK(method)                       \
738 {                                           \
739     info = method ;                         \
740     if (info != GrB_SUCCESS)                \
741     {                                       \
742         GB_FREE_ALL ;                       \
743         return (info) ;                     \
744     }                                       \
745 }
746 
747 // check if a required arg is NULL
748 #define GB_RETURN_IF_NULL(arg)                                          \
749     if ((arg) == NULL)                                                  \
750     {                                                                   \
751         /* the required arg is NULL */                                  \
752         return (GrB_NULL_POINTER) ;                                     \
753     }
754 
755 // arg may be NULL, but if non-NULL then it must be initialized
756 #define GB_RETURN_IF_FAULTY(arg)                                        \
757     if ((arg) != NULL && (arg)->magic != GB_MAGIC)                      \
758     {                                                                   \
759         if ((arg)->magic == GB_MAGIC2)                                  \
760         {                                                               \
761             /* optional arg is not NULL, but invalid */                 \
762             return (GrB_INVALID_OBJECT) ;                               \
763         }                                                               \
764         else                                                            \
765         {                                                               \
766             /* optional arg is not NULL, but not initialized */         \
767             return (GrB_UNINITIALIZED_OBJECT) ;                         \
768         }                                                               \
769     }
770 
771 // arg must not be NULL, and it must be initialized
772 #define GB_RETURN_IF_NULL_OR_FAULTY(arg)                                \
773     GB_RETURN_IF_NULL (arg) ;                                           \
774     GB_RETURN_IF_FAULTY (arg) ;
775 
776 // positional ops not supported for use as accum operators
777 #define GB_RETURN_IF_FAULTY_OR_POSITIONAL(accum)                        \
778 {                                                                       \
779     GB_RETURN_IF_FAULTY (accum) ;                                       \
780     if (GB_OP_IS_POSITIONAL (accum))                                    \
781     {                                                                   \
782         GB_ERROR (GrB_DOMAIN_MISMATCH,                                  \
783             "Positional op z=%s(x,y) not supported as accum\n",         \
784                 accum->name) ;                                          \
785     }                                                                   \
786 }
787 
788 // check the descriptor and extract its contents; also copies
789 // nthreads_max and chunk from the descriptor to the Context
790 #define GB_GET_DESCRIPTOR(info,desc,dout,dmc,dms,d0,d1,dalgo,dsort)          \
791     GrB_Info info ;                                                          \
792     bool dout, dmc, dms, d0, d1 ;                                            \
793     int dsort ;                                                              \
794     GrB_Desc_Value dalgo ;                                                   \
795     /* if desc is NULL then defaults are used.  This is OK */                \
796     info = GB_Descriptor_get (desc, &dout, &dmc, &dms, &d0, &d1, &dalgo,     \
797         &dsort, Context) ;                                                   \
798     if (info != GrB_SUCCESS)                                                 \
799     {                                                                        \
800         /* desc not NULL, but uninitialized or an invalid object */          \
801         return (info) ;                                                      \
802     }
803 
804 // C<M>=Z ignores Z if an empty mask is complemented, or if M is full,
805 // structural and complemented, so return from the method without computing
806 // anything.  Clear C if replace option is true.
807 #define GB_RETURN_IF_QUICK_MASK(C, C_replace, M, Mask_comp, Mask_struct)    \
808     if (Mask_comp && (M == NULL || (GB_IS_FULL (M) && Mask_struct)))        \
809     {                                                                       \
810         /* C<!NULL>=NULL since result does not depend on computing Z */     \
811         return (C_replace ? GB_clear (C, Context) : GrB_SUCCESS) ;          \
812     }
813 
814 // GB_MASK_VERY_SPARSE is true if C<M>=A+B, C<M>=A.*B or C<M>=accum(C,T) is
815 // being computed, and the mask M is very sparse compared with A and B.
816 #define GB_MASK_VERY_SPARSE(alpha,M,A,B) \
817     ((alpha) * GB_NNZ (M) < GB_NNZ (A) + GB_NNZ (B))
818 
819 //------------------------------------------------------------------------------
820 // Pending upddate and zombies
821 //------------------------------------------------------------------------------
822 
823 GB_PUBLIC   // accessed by the MATLAB tests in GraphBLAS/Test only
824 GrB_Info GB_Matrix_wait         // finish all pending computations
825 (
826     GrB_Matrix A,               // matrix with pending computations
827     const char *name,           // name of the matrix
828     GB_Context Context
829 ) ;
830 
831 GrB_Info GB_unjumble        // unjumble a matrix
832 (
833     GrB_Matrix A,           // matrix to unjumble
834     GB_Context Context
835 ) ;
836 
837 // true if a matrix has pending tuples
838 #define GB_PENDING(A) ((A) != NULL && (A)->Pending != NULL)
839 
840 // true if a matrix is allowed to have pending tuples
841 #define GB_PENDING_OK(A) (GB_PENDING (A) || !GB_PENDING (A))
842 
843 // true if a matrix has zombies
844 #define GB_ZOMBIES(A) ((A) != NULL && (A)->nzombies > 0)
845 
846 // true if a matrix is allowed to have zombies
847 #define GB_ZOMBIES_OK(A) (((A) == NULL) || ((A) != NULL && (A)->nzombies >= 0))
848 
849 // true if a matrix has pending tuples or zombies
850 #define GB_PENDING_OR_ZOMBIES(A) (GB_PENDING (A) || GB_ZOMBIES (A))
851 
852 // true if a matrix is jumbled
853 #define GB_JUMBLED(A) ((A) != NULL && (A)->jumbled)
854 
855 // true if a matrix is allowed to be jumbled
856 #define GB_JUMBLED_OK(A) (GB_JUMBLED (A) || !GB_JUMBLED (A))
857 
858 // true if a matrix has pending tuples, zombies, or is jumbled
859 #define GB_ANY_PENDING_WORK(A) \
860     (GB_PENDING (A) || GB_ZOMBIES (A) || GB_JUMBLED (A))
861 
862 // wait if condition holds
863 #define GB_WAIT_IF(condition,A,name)                                    \
864 {                                                                       \
865     if (condition)                                                      \
866     {                                                                   \
867         GrB_Info info ;                                                 \
868         GB_OK (GB_Matrix_wait ((GrB_Matrix) A, name, Context)) ;        \
869     }                                                                   \
870 }
871 
872 // do all pending work:  zombies, pending tuples, and unjumble
873 #define GB_MATRIX_WAIT(A) GB_WAIT_IF (GB_ANY_PENDING_WORK (A), A, GB_STR (A))
874 
875 // do all pending work if pending tuples; zombies and jumbled are OK
876 #define GB_MATRIX_WAIT_IF_PENDING(A) GB_WAIT_IF (GB_PENDING (A), A, GB_STR (A))
877 
878 // delete zombies and assemble any pending tuples; jumbled is O
879 #define GB_MATRIX_WAIT_IF_PENDING_OR_ZOMBIES(A)                         \
880     GB_WAIT_IF (GB_PENDING_OR_ZOMBIES (A), A, GB_STR (A))
881 
882 // ensure A is not jumbled
883 #define GB_MATRIX_WAIT_IF_JUMBLED(A) GB_WAIT_IF (GB_JUMBLED (A), A, GB_STR (A))
884 
885 // true if a matrix has no entries; zombies OK
886 #define GB_IS_EMPTY(A) ((GB_NNZ (A) == 0) && !GB_PENDING (A))
887 
888 //------------------------------------------------------------------------------
889 
890 #include "GB_convert.h"
891 #include "GB_ops.h"
892 
893 //------------------------------------------------------------------------------
894 // CUDA (DRAFT: in progress)
895 //------------------------------------------------------------------------------
896 
897 #include "GB_cuda_gateway.h"
898 
899 #endif
900 
901