
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{GraphBLAS Options ({\sf GrB\_get} and {\sf GrB\_set})}
\label{options}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

The latest v2.1 C API adds a pair of methods, \verb'GrB_get' and \verb'GrB_set'
that allows the user to query GraphBLAS objects and change their state.  These
two methods are polymorphic wrappers for a suite of methods for each object.
They replace the \verb'GxB_get' and \verb'GxB_set' methods in
SuiteSparse:GraphBLAS v8.* and earlier.

The general polymorphic signatures of these methods are given below:

{\footnotesize
\begin{verbatim}
    GrB_Info GrB_get (object, value, GrB_Field field) ;
    GrB_Info GrB_set (object, value, GrB_Field field) ;
    GrB_Info GrB_set (object, void *value, GrB_Field field, size_t s) ; \end{verbatim}}

\noindent
where \verb'object' can be any GraphBLAS object.  The \verb'value' can be a
\verb'GrB_Scalar', an \verb'int32_t' (or a pointer to \verb'int32_t' for
\verb'GrB_get'), a string (\verb'char *'), or a \verb'void *' pointer.  In the
latter case, \verb'GrB_set' requires an additional parameter (\verb'size_t s')
that specifies the size of the object pointed to by \verb'void *value'.

The non-polymorphic names have the following format, where \verb'[OBJ]'
is any GraphBLAS object. 

{\footnotesize
\begin{verbatim}
    GrB_Info GrB_[OBJ]_get_[KIND] (object, value, GrB_Field field) ;
    GrB_Info GrB_[OBJ]_set_[KIND] (object, value, GrB_Field field) ;
    GrB_Info GrB_[OBJ]_set_VOID (object, void *value, GrB_Field field, size_t s) ; \end{verbatim}}

The \verb'[KIND]' suffix defines the type of second parameter, and can be:
    \verb'Scalar' (for \verb'GrB_Scalar'),
    \verb'String' (for \verb'char *'),
    \verb'INT32' (for \verb'int32_t'), and
    \verb'SIZE' (for \verb'size_t *' for \verb'GrB_get' only), and
    \verb'VOID' (for \verb'void *').

The tables below list all the valid fields that can be used for each object. 
Each table contains four columns:  (1) the \verb'GrB_Field',
(2) a column labelled R/W, (3) a column defining the C type, and a description.
For the R/W column:

\begin{itemize}
\item If the R/W column of a table is R, then the value can be read by \verb'GrB_get'
    but not written by \verb'GrB_set'.
\item R/W means that both \verb'GrB_get' and \verb'GrB_set' can be used any number of times,
    with different values.
\item R/W1 means that \verb'GrB_get' can be done multiple times,
    but \verb'GrB_set' can be used only once.
    Subsequent calls to \verb'GrB_set' return the error code \verb'GrB_ALREADY_SET'.
\item W means that only \verb'GrB_set' can be used (any number of times),
    but \verb'GrB_get' cannot be done.
\end{itemize}

The second parameter (\verb'value') of \verb'GrB_get' and \verb'GrB_set' can take on several
different C types, and it can also be a \verb'GrB_Scalar' that holds a value
with the given C type (or that can be typecasted to the given C type):

\begin{itemize}
\item \verb'int32_t': 
    For \verb'GrB_set' the \verb'value' parameter is \verb'int32_t'.
    For \verb'GrB_get' the \verb'value' parameter is \verb'int32_t *.'
    The following example sets the global number of threads, and then
    retrieves that \verb'value' into \verb'nthreads'.

    {\footnotesize
    \begin{verbatim}
        GrB_set (GrB_GLOBAL, 8, GxB_NTHREADS) ;
        int32_t nthreads ;
        GrB_get (GrB_GLOBAL, &nthreads, GxB_NTHREADS) ;
        printf ("nthreads: %d\n", nthreads) ; \end{verbatim} }

    A \verb'GrB_Scalar' can also be used for an \verb'int32_t' \verb'value'.
    For \verb'GrB_set', the scalar must not be empty.
    Here is the same example but using a \verb'GrB_Scalar' instead:

    {\footnotesize
    \begin{verbatim}
        GrB_Scalar s ;
        GrB_Scalar_new (s, GrB_INT32) ;
        GrB_Scalar_setElement (s, 8) ;
        GrB_set (GrB_GLOBAL, s, GxB_NTHREADS) ;
        GrB_get (GrB_GLOBAL, s, GxB_NTHREADS) ;
        int32_t nthreads ;
        GrB_Scalar_extractElement (&nthreads, s) ;
        printf ("nthreads: %d\n", nthreads) ; \end{verbatim} }

\item \verb'char *':
    The \verb'value' parameter is \verb'char *' for both \verb'GrB_get' and
    \verb'GrB_set'.  A \verb'GrB_Scalar' cannot be used.  The size of the
    string required for \verb'GrB_get' is given by using a \verb'size_t *'
    parameter with the same field.  For example:

    {\footnotesize
    \begin{verbatim}
        size_t len ;
        GrB_get (GrB_GLOBAL, &len, GrB_NAME) ;
        char *name = malloc (len) ;
        GrB_get (GrB_GLOBAL, name, GrB_NAME) ;
        printf ("The library is: %s\n", name) ;
        free (name) ; \end{verbatim} }

    To get the current JIT C compiler and then set it to something else:

    {\footnotesize
    \begin{verbatim}
        size_t len ;
        GrB_get (GrB_GLOBAL, &len, GxB_JIT_C_COMPILER_NAME) ;
        char *compiler = malloc (len) ;
        GrB_get (GrB_GLOBAL, compiler, GxB_JIT_C_COMPILER_NAME) ;
        printf ("The current JIT compiler is: %s\n", compiler) ;
        GrB_set (GrB_GLOBAL, "gcc", GxB_JIT_C_COMPILER_NAME) ;
        GrB_get (GrB_GLOBAL, &len, GxB_JIT_C_COMPILER_NAME) ;
        char *new_compiler = malloc (len) ;
        GrB_get (GrB_GLOBAL, new_compiler, GxB_JIT_C_COMPILER_NAME) ;
        printf ("The new JIT compiler is: %s\n", new_compiler) ;
        free (compiler) ;
        free (new_compiler) ; \end{verbatim} }

\item Other scalar data types (typically \verb'double'):
    Only a \verb'GrB_Scalar' can be used.  When using \verb'GrB_set' with a
    \verb'GrB_Scalar', the scalar cannot be empty.  For example, to get then
    set the global \verb'GxB_HYPER_SWITCH' parameter to 0.3: 

    {\footnotesize
    \begin{verbatim}
        GrB_Scalar s ;
        GrB_Scalar_new (s, GrB_FP64) ;
        GrB_get (GrB_GLOBAL, s, GxB_HYPER_SWITCH) ;
        double hs ;
        GrB_Scalar_extractElement (&hs, s) ;
        printf ("current hyper_switch: %g\n", hs) ;
        GrB_Scalar_setElement (s, 0.3) ;
        GrB_set (GrB_GLOBAL, s, GxB_HYPER_SWITCH) ; \end{verbatim} }

\item \verb'void *':
    This type is used for all other cases.
    For \verb'GrB_get', the array must have the right size, just like a
    \verb'char *' string.  Use the same field first, but with
    \verb'size_t *value' as the second parameter to obtain the size of the
    \verb'void *' array, then use \verb'GrB_get' with a \verb'void *' array of
    the right size.  In some cases, the size is always the same.  For example,
    to query the operator of a monoid:

    {\footnotesize
    \begin{verbatim}
        GrB_BinaryOp op ;
        GrB_get (GrB_PLUS_MONOID_FP64, (void *) &op, GxB_MONOID_OPERATOR) ;
        assert (op == GrB_PLUS_FP64) ; \end{verbatim} }

    For \verb'GrB_set', a fourth parameter is required to tell GraphBLAS the
    size of the input array.

\end{itemize}

%-------------------------------------------------------------------------------
\subsection{Enum types for get/set: {\sf GrB\_Field}, {\sf GrB\_Orientation},
and {\sf GrB\_Type\_Code}}
\label{get_set_enums}
%-------------------------------------------------------------------------------

The get/set methods share a \verb'GrB_Field' enum type to specify which
component of the object is to be set or retrieved.
fields.

{\footnotesize
\begin{verbatim}
typedef enum
{
    // GrB_Descriptor only:
    GrB_OUTP_FIELD = 0,     // descriptor for output of a method
    GrB_MASK_FIELD = 1,     // descriptor for the mask input of a method
    GrB_INP0_FIELD = 2,     // descriptor for the first input of a method
    GrB_INP1_FIELD = 3,     // descriptor for the second input of a method

    // all objects, including GrB_GLOBAL:
    GrB_NAME = 10,          // name of the object, as a string

    // GrB_GLOBAL only:
    GrB_LIBRARY_VER_MAJOR = 11,     // SuiteSparse:GraphBLAS version
    GrB_LIBRARY_VER_MINOR = 12,
    GrB_LIBRARY_VER_PATCH = 13,
    GrB_API_VER_MAJOR = 14,         // C API version
    GrB_API_VER_MINOR = 15,
    GrB_API_VER_PATCH = 16,
    GrB_BLOCKING_MODE = 17,         // GrB_Mode

    // GrB_GLOBAL, GrB_Matrix, GrB_Vector, GrB_Scalar (and void * serialize?):
    GrB_STORAGE_ORIENTATION_HINT = 100, // GrB_Orientation

    // GrB_Matrix, GrB_Vector, GrB_Scalar (and void * serialize):
    GrB_EL_TYPE_CODE = 102,         // a GrB_Type_code (see below)
    GrB_EL_TYPE_STRING = 106,       // name of the type

    // GrB_*Op, GrB_Monoid, and GrB_Semiring:
    GrB_INP1_TYPE_CODE = 103,       // GrB_Type_code
    GrB_INP2_TYPE_CODE = 104,
    GrB_OUTP_TYPE_CODE = 105,
    GrB_INP1_TYPE_STRING = 107,     // name of the type, as a string
    GrB_INP2_TYPE_STRING = 108,
    GrB_OUTP_TYPE_STRING = 109,

    // GrB_Type (readable only):
    GrB_SIZE = 110,                 // size of the type

    // GrB_Type, GrB_UnaryOp, GrB_BinaryOp, and GrB_IndexUnaryOp:
    GxB_JIT_C_NAME = 7041,          // C type or function name
    GxB_JIT_C_DEFINITION = 7042,    // C typedef or function definition

    // GrB_Monoid and GrB_Semiring:
    GxB_MONOID_IDENTITY = 7043,     // monoid identity value
    GxB_MONOID_TERMINAL = 7044,     // monoid terminal value
    GxB_MONOID_OPERATOR = 7045,     // monoid binary operator

    // GrB_Semiring only:
    GxB_SEMIRING_MONOID = 7046,     // semiring monoid
    GxB_SEMIRING_MULTIPLY = 7047,   // semiring multiplicative op
}
GrB_Field ;

#define GxB_NTHREADS 7086
#define GxB_CHUNK 7087

typedef enum            // more SuiteSparse extensions for GrB_Field:
{

    // GrB_get/GrB_set for GrB_Matrix and GrB_GLOBAL:
    GxB_HYPER_SWITCH = 7000,    // switch to hypersparse (double value)
    GxB_HYPER_HASH = 7048,      // hyper_hash control (int64 value)
    GxB_BITMAP_SWITCH = 7001,   // switch to bitmap (double value)

    // GrB_get for GrB_GLOBAL:
    GxB_LIBRARY_DATE = 7006,         // date of the library (char *)
    GxB_LIBRARY_ABOUT = 7007,        // about the library (char *)
    GxB_LIBRARY_URL = 7008,          // URL for the library (char *)
    GxB_LIBRARY_LICENSE = 7009,      // license of the library (char *)
    GxB_LIBRARY_COMPILE_DATE = 7010, // date library was compiled (char *)
    GxB_LIBRARY_COMPILE_TIME = 7011, // time library was compiled (char *)
    GxB_API_DATE = 7013,             // date of the API (char *)
    GxB_API_ABOUT = 7014,            // about the API (char *)
    GxB_API_URL = 7015,              // URL for the API (char *)
    GxB_COMPILER_VERSION = 7016,     // compiler version (3 int's)
    GxB_COMPILER_NAME = 7017,        // compiler name (char *)
    GxB_LIBRARY_OPENMP = 7018,       // library compiled with OpenMP
    GxB_MALLOC_FUNCTION = 7037,      // malloc function pointer
    GxB_CALLOC_FUNCTION = 7038,      // calloc function pointer
    GxB_REALLOC_FUNCTION = 7039,     // realloc function pointer
    GxB_FREE_FUNCTION = 7040,        // free function pointer

    // GrB_get/GrB_set for GrB_GLOBAL:
    GxB_GLOBAL_NTHREADS = GxB_NTHREADS,  // max number of threads to use
    GxB_GLOBAL_CHUNK = GxB_CHUNK,        // chunk size for small problems.
    GxB_BURBLE = 7019,               // diagnostic output (bool *)
    GxB_PRINTF = 7020,               // printf function diagnostic output
    GxB_FLUSH = 7021,                // flush function diagnostic output
    GxB_PRINT_1BASED = 7023,         // print matrices as 0-based or 1-based
    GxB_JIT_C_COMPILER_NAME = 7024,  // CPU JIT C compiler name
    GxB_JIT_C_COMPILER_FLAGS = 7025, // CPU JIT C compiler flags
    GxB_JIT_C_LINKER_FLAGS = 7026,   // CPU JIT C linker flags
    GxB_JIT_C_LIBRARIES = 7027,      // CPU JIT C libraries
    GxB_JIT_C_PREFACE = 7028,        // CPU JIT C preface
    GxB_JIT_C_CONTROL = 7029,        // CPU JIT C control
    GxB_JIT_CACHE_PATH = 7030,       // CPU/CUDA JIT path for compiled kernels
    GxB_JIT_C_CMAKE_LIBS = 7031,     // CPU JIT C libraries when using cmake
    GxB_JIT_USE_CMAKE = 7032,        // CPU JIT: use cmake or direct compile
    GxB_JIT_ERROR_LOG = 7033,        // CPU JIT: error log file

    // GrB_get for GrB_Matrix:
    GxB_SPARSITY_STATUS = 7034,     // hyper, sparse, bitmap or full (1,2,4,8)

    // GrB_get/GrB_set for GrB_Matrix:
    GxB_SPARSITY_CONTROL = 7036,    // sparsity control: 0 to 15; see below

} GxB_Option_Field ;

typedef enum
{
    GrB_ROWMAJOR = 0,
    GrB_COLMAJOR = 1,
    GrB_BOTH     = 2,
    GrB_UNKNOWN  = 3,
}
GrB_Orientation ;

typedef enum
{
    GrB_UDT_CODE    = 0,        // user-defined type
    GrB_BOOL_CODE   = 1,        // GraphBLAS: GrB_BOOL      C: bool
    GrB_INT8_CODE   = 2,        // GraphBLAS: GrB_INT8      C: int8_t
    GrB_UINT8_CODE  = 3,        // GraphBLAS: GrB_UINT8     C: uint8_t
    GrB_INT16_CODE  = 4,        // GraphBLAS: GrB_INT16     C: int16_t
    GrB_UINT16_CODE = 5,        // GraphBLAS: GrB_UINT16    C: uint16_t
    GrB_INT32_CODE  = 6,        // GraphBLAS: GrB_INT32     C: int32_t
    GrB_UINT32_CODE = 7,        // GraphBLAS: GrB_UINT32    C: uint32_t
    GrB_INT64_CODE  = 8,        // GraphBLAS: GrB_INT64     C: int64_t
    GrB_UINT64_CODE = 9,        // GraphBLAS: GrB_UINT64    C: uint64_t
    GrB_FP32_CODE   = 10,       // GraphBLAS: GrB_FP32      C: float
    GrB_FP64_CODE   = 11,       // GraphBLAS: GrB_FP64      C: double
    GxB_FC32_CODE   = 7070,     // GraphBLAS: GxB_FC32      C: float complex
    GxB_FC64_CODE   = 7071,     // GraphBLAS: GxB_FC64      C: double complex
}
GrB_Type_Code ; \end{verbatim}}


%-------------------------------------------------------------------------------
\subsection{Global Options ({\sf GrB\_Global})}
\label{get_set_global}
%-------------------------------------------------------------------------------

A single object \verb'GrB_GLOBAL' whose type is \verb'GrB_Global' is used to
denote global settings to read or modify.  To use it with \verb'GrB_get' and
\verb'GrB_set', pass in \verb'GrB_GLOBAL' as the first parameter.

\begin{mdframed}[userdefinedwidth=6in]
{\footnotesize
\begin{verbatim}
GrB_Info GrB_get (GrB_Global g, GrB_Scalar value, GrB_Field f) ;
GrB_Info GrB_get (GrB_Global g, char *     value, GrB_Field f) ;
GrB_Info GrB_get (GrB_Global g, int32_t *  value, GrB_Field f) ;
GrB_Info GrB_get (GrB_Global g, size_t *   value, GrB_Field f) ;
GrB_Info GrB_get (GrB_Global g, void *     value, GrB_Field f) ;

GrB_Info GrB_set (GrB_Global g, GrB_Scalar value, GrB_Field f) ;
GrB_Info GrB_set (GrB_Global g, char *     value, GrB_Field f) ;
GrB_Info GrB_set (GrB_Global g, int32_t    value, GrB_Field f) ;
GrB_Info GrB_set (GrB_Global g, void *     value, GrB_Field f, size_t s) ;
\end{verbatim}
}\end{mdframed}


\noindent
{\small
\begin{tabular}{|l|l|l|p{2.5in}|}
\hline
\verb'GrB_Field'                    & R/W  & C type        & description \\
\hline
\verb'GrB_LIBRARY_VER_MAJOR'        & R    & \verb'int32_t'& major version of the library \\
\verb'GrB_LIBRARY_VER_MINOR'        & R    & \verb'int32_t'& minor version of the library \\
\verb'GrB_LIBRARY_VER_PATCH'        & R    & \verb'int32_t'& patch version of the library \\
\verb'GrB_API_VER_MAJOR'            & R    & \verb'int32_t'& major version of the API \\
\verb'GrB_API_VER_MINOR'            & R    & \verb'int32_t'& major version of the API \\
\verb'GrB_API_VER_PATCH'            & R    & \verb'int32_t'& major version of the API \\
\verb'GrB_BLOCKING_MODE'            & R    & \verb'int32_t'& blocking mode (\verb'GrB_BLOCKING' \newline
                                                                or \verb'GrB_NONBLOCKING') \\
\verb'GxB_LIBRARY_OPENMP'           & R    & \verb'int32_t'& if OpenMP is in use (true/false) \\
\hline
\end{tabular}
}
\vspace{0.05in}

\vspace{0.1in}
\noindent
{\small
\begin{tabular}{|l|l|l|p{2.5in}|}
\hline
\verb'GrB_Field'                    & R/W  & C type        & description \\
\hline
\verb'GrB_STORAGE_ORIENTATION_HINT' & R/W  & \verb'int32_t'& see \verb'GrB_Orientation': default
                                                            format for matrices. \\
%                                                           Matrices are held by row, unless this
%                                                           value is set to \verb'GrB_COLMAJOR'. \\
\verb'GxB_NTHREADS'                 & R/W  & \verb'int32_t'& number of OpenMP threads used. \newline
                                                            See Section~\ref{omp_parallelism}. \\
% \verb'GxB_GPU_ID'                 & R/W  & \verb'int32_t'& which GPU to use \\
\verb'GxB_BURBLE'                   & R/W  & \verb'int32_t'& diagnostic output (true/false). \newline
                                                                See Section~\ref{diag}. \\
\verb'GxB_PRINT_1BASED'             & R/W  & \verb'int32_t'& matrices printed as 1-based or 0-based  \\
\verb'GxB_JIT_C_CONTROL'            & R/W  & \verb'int32_t'& see Section~\ref{jit} \\
\verb'GxB_JIT_USE_CMAKE'            & R/W  & \verb'int32_t'& see Section~\ref{jit} \\
\hline
\verb'GxB_HYPER_SWITCH'             & R/W  & \verb'double' & global hypersparsity control. \newline
                                                                See Section~\ref{hypersparse}. \\
\verb'GxB_HYPER_HASH'               & R/W  & \verb'int64_t' & global hypersparsity (hyper-hash)
                                                                control \\
\verb'GxB_CHUNK'                    & R/W  & \verb'double' & global chunk size for parallel task creation.
                                                                See Section~\ref{omp_parallelism}. \\
\hline
\verb'GrB_NAME'                     & R    & \verb'char *' & name of the library \newline
                                                                (\verb'"SuiteSparse:GraphBLAS"') \\
\verb'GxB_LIBRARY_DATE'             & R    & \verb'char *' & library release date \\
\verb'GxB_LIBRARY_ABOUT'            & R    & \verb'char *' & details about the library \\
\verb'GxB_LIBRARY_LICENSE'          & R    & \verb'char *' & license of the library \\
\verb'GxB_LIBRARY_COMPILE_DATE'     & R    & \verb'char *' & date the library was compiled \\
\verb'GxB_LIBRARY_COMPILE_TIME'     & R    & \verb'char *' & time the library was compiled \\
\verb'GxB_LIBRARY_URL'              & R    & \verb'char *' & URL for the library \\
\verb'GxB_API_DATE'                 & R    & \verb'char *' & C API release date \\
\verb'GxB_API_ABOUT'                & R    & \verb'char *' & about the C API \\
\verb'GxB_API_URL'                  & R    & \verb'char *' & URL for the C API \\
\verb'GxB_COMPILER_NAME'            & R    & \verb'char *' & name of the compiler used to compile the library \\
\hline
\verb'GxB_JIT_C_COMPILER_NAME'      & R/W  & \verb'char *' & See Section~\ref{jit} \\
\verb'GxB_JIT_C_COMPILER_FLAGS'     & R/W  & \verb'char *' & " \\
\verb'GxB_JIT_C_LINKER_FLAGS'       & R/W  & \verb'char *' & " \\
\verb'GxB_JIT_C_LIBRARIES'          & R/W  & \verb'char *' & " \\
\verb'GxB_JIT_C_CMAKE_LIBS'         & R/W  & \verb'char *' & " \\
\verb'GxB_JIT_C_PREFACE'            & R/W  & \verb'char *' & " \\
\verb'GxB_JIT_ERROR_LOG'            & R/W  & \verb'char *' & " \\
\verb'GxB_JIT_CACHE_PATH'           & R/W  & \verb'char *' & " \\
\hline
\end{tabular}
}

\vspace{0.1in}
\noindent
{\small
\begin{tabular}{|l|l|l|p{2.5in}|}
\hline
\verb'GrB_Field'                    & R/W  & C type        & description \\
\verb'GxB_BITMAP_SWITCH'            & R/W  & \verb'void *' & \verb'double' array of size \newline
                                                                \verb'GxB_NBITMAP_SWITCH'.  \newline
                                                                See Section~\ref{bitmap_switch}. \\
\verb'GxB_COMPILER_VERSION'         & R    & \verb'void *' & \verb'int32_t' array of size 3.
                                        The version of the compiler used to
                                        compile the library. \\
\verb'GxB_PRINTF'                   & W    & \verb'void *' & pointer to \verb'printf' function for diagnostic output.
                                                                See Section~\ref{diag}. \\
\verb'GxB_FLUSH'                    & W    & \verb'void *' & pointer to \verb'flush' function for diagnostic output.
                                                                See Section~\ref{diag}. \\
\verb'GxB_MALLOC_FUNCTION'  & R    & \verb'void *' & malloc function \\
\verb'GxB_CALLOC_FUNCTION'  & R    & \verb'void *' & calloc function \\
\verb'GxB_REALLOC_FUNCTION' & R    & \verb'void *' & realloc function \\
\verb'GxB_FREE_FUNCTION'    & R    & \verb'void *' & free function \\
\hline
\end{tabular}
}

% \newpage
%-------------------------------------------------------------------------------
\subsubsection{Global diagnostic settings}
\label{diag}
%-------------------------------------------------------------------------------

\verb'GrB_set (GrB_GLOBAL, ..., GxB_BURBLE)' controls the burble setting.  It can also be
controlled via \verb'GrB.burble(b)' in the MATLAB/Octave interface.

{\footnotesize
\begin{verbatim}
     GrB_set (GrB_GLOBAL, true,  GxB_BURBLE) ;  // enable burble
     GrB_set (GrB_GLOBAL, false, GxB_BURBLE) ;  // disable burble \end{verbatim}}

If enabled, SuiteSparse:GraphBLAS reports which internal kernels it uses, and
how much time is spent.  If you see the word \verb'generic', it means that
SuiteSparse:GraphBLAS was unable to use its JIT kernels, or its faster kernels
in \verb'Source/FactoryKernels', but used a generic kernel that relies on
function pointers.  This is done for user-defined types and operators when they
cannot be used in the JIT, and when typecasting is performed.  Generic kernels
are typically slower than the JIT kernels or kernels in
\verb'Source/FactoryKernels'.

If you see a lot of \verb'wait' statements, it may mean that a lot of time is
spent finishing a matrix or vector.  This may be the result of an inefficient
use of the \verb'setElement' and \verb'assign' methods.  If this occurs you
might try changing the sparsity format of a vector or matrix to
\verb'GxB_BITMAP', assuming there's enough space for it.

The following setting allows the user application to change the
function used to print diagnostic output:

{\small
\begin{verbatim}
    GrB_set (GrB_GLOBAL, (void *) printf, GxB_PRINTF, sizeof (void *)) ; \end{verbatim} }

This also controls the output of the
\verb'GxB_*print' functions.  By default this parameter is \verb'NULL', in
which case the C11 \verb'printf' function is used.  The parameter is a
function pointer with the same signature as the C11 \verb'printf'
function.  The MATLAB/Octave interface to GraphBLAS sets it to \verb'mexPrintf'
so that GraphBLAS can print to the MATLAB/Octave Command Window.

After each call to the \verb'printf' function, an optional
\verb'flush' function is called, which is \verb'NULL' by default.  If
\verb'NULL', the function is not used.  This can be changed with:

{\small
\begin{verbatim}
    GrB_set (GrB_GLOBAL, (void *) flush, GxB_FLUSH, sizeof (void *)) ; \end{verbatim} }

The \verb'flush' function takes no
arguments, and returns an \verb'int' which is 0 if successful, or any nonzero
value on failure (the same output as the C11 \verb'fflush' function,
except that \verb'flush' has no inputs).

%-------------------------------------------------------------------------------
\subsubsection{OpenMP parallelism}
%-------------------------------------------------------------------------------
\label{omp_parallelism}

SuiteSparse:GraphBLAS is a parallel library, based on OpenMP.  By
default, all GraphBLAS operations will use up to the maximum number of threads
specified by the \verb'omp_get_max_threads' OpenMP function.  For small
problems, GraphBLAS may choose to use fewer threads, using two parameters: the
maximum number of threads to use (which may differ from the
\verb'omp_get_max_threads' value), and a parameter called the \verb'chunk'.
Suppose \verb'work' is a measure of the work an operation needs to perform (say
the number of entries in the two input matrices for \verb'GrB_eWiseAdd').  No
more than \verb'floor(work/chunk)' threads will be used (or one thread if the
ratio is less than 1).

\verb'GxB_NTHREADS' controls how many threads a method uses.
    By default (if set to zero, or \verb'GrB_DEFAULT'), all available threads
    are used.  The maximum available threads is controlled by the global
    setting, which is \verb'omp_get_max_threads ( )' by default.  If set to
    some positive integer \verb'nthreads' less than this maximum, at most
    \verb'nthreads' threads will be used.

\verb'GxB_CHUNK' is a \verb'double' value that controls how many threads
    a method uses for small problems.
The default \verb'chunk' value is 65,536, but this may change in future
versions, or it may be modified when GraphBLAS is installed on a particular
machine.

Both parameters can be set in two ways:

\begin{itemize}

\item Globally:  If the following methods are used, then all subsequent
GraphBLAS operations will use these settings.  Note the typecast,
\verb'(double)' \verb'chunk'.  This is necessary if a literal constant such as
\verb'20000' is passed as this argument.  The type of the constant must be
\verb'double'.

    {\footnotesize
    \begin{verbatim}
    int32_t nthreads_max = 40 ;
    GrB_set (GrB_GLOBAL, nthreads_max, GxB_NTHREADS) ;
    GrB_Scalar_new (&s, GrB_FP64) ;
    GrB_Scalar_setElement (s, (double) 20000) ;
    GrB_set (GrB_GLOBAL, s, GxB_CHUNK) ; \end{verbatim} }

\item Context: this object can be used to choose a different number of
threads used in calls to GraphBLAS from different user threads, exploiting
nested parallelism.  Refer to Section~\ref{context}.  If a thread has engaged a
context object, it ignores the global settings for \verb'GxB_NTHREADS' and
\verb'GxB_CHUNK', and uses the settings in its own context instead.

\end{itemize}

The smaller of \verb'nthreads_max' and \verb'floor(work/chunk)' is used for any
given GraphBLAS operation, except that a single thread is used if this value is
zero or less.

If either parameter is set to \verb'GrB_DEFAULT', then default values are used.
The default for \verb'nthreads_max' is the return value from
\verb'omp_get_max_threads', and the default chunk size is currently 65,536.

If a descriptor value for either parameter is left at its default, or set to
\verb'GrB_DEFAULT', then the global setting is used.  This global setting may
have been modified from its default, and this modified value will be used.

For example, suppose \verb'omp_get_max_threads' reports 8 threads.  If \newline
\verb'GrB_set (GrB_GLOBAL, 4, GxB_NTHREADS)' is used, then the global setting is four
threads, not eight.

GraphBLAS may be compiled without OpenMP, by setting \verb'-DNOPENMP=1'.
The library will be thread-safe, with one exception.  \verb'GrB_wait' is
intended to provide thread-safety by flushing the cache of one user thread
so the object can be safely read by another thread.  This is accomplished
with \verb'pragma omp flush', but if OpenMP is not available, this does
nothing.  If OpenMP is not available or \verb'-DNOPEMP=1' is used, then
user applications need to ensure their own thread safety when one user thread
computes a result that is then read by another thread.

You can query GraphBLAS at run-time to ask if it was compiled with OpenMP:

{\small
\begin{verbatim}
    bool have_openmp ;
    GrB_get (GrB_GLOBAL, &have_openmp, GxB_LIBRARY_OPENMP) ;
    if (!have_openmp) printf ("GraphBLAS not compiled with OpenMP\n") : \end{verbatim}}

Compiling GraphBLAS without OpenMP is not recommended for installation in a
package manager (Linux, conda-forge, spack, brew, vcpkg, etc).

%-------------------------------------------------------------------------------
\subsubsection{Other global options}
%-------------------------------------------------------------------------------

\verb'GrB_BLOCKING_MODE' can only be queried by \verb'GrB_get'; it cannot be
modified by \verb'GrB_set'.  The mode is the value passed to \verb'GrB_init'
(blocking or non-blocking).

All threads in the same user application share the same global options,
including hypersparsity, bitmap options, and CSR/CSC format determined by
\verb'GrB_set', and the blocking mode determined by \verb'GrB_init'.
Specific format and hypersparsity parameters of each matrix are specific to
that matrix and can be independently changed.

The \verb'GrB_LIBRARY_*' and \verb'GxB_LIBRARY_*' options can be used to query
the current implementation of SuiteSparse:GraphBLAS.  The \verb'GrB_API_*' and
\verb'GxB_API_*' options can be used to query the current GraphBLAS C API
Specification.

%-------------------------------------------------------------------------------
\newpage
\subsection{{\sf GrB\_Type} Options}
\label{get_set_type}
%-------------------------------------------------------------------------------

\begin{mdframed}[userdefinedwidth=6in]
{\footnotesize
\begin{verbatim}
GrB_Info GrB_get (GrB_Type t, GrB_Scalar value, GrB_Field f) ;
GrB_Info GrB_get (GrB_Type t, char *     value, GrB_Field f) ;
GrB_Info GrB_get (GrB_Type t, int32_t *  value, GrB_Field f) ;
GrB_Info GrB_get (GrB_Type t, size_t *   value, GrB_Field f) ;

GrB_Info GrB_set (GrB_Type t, char *     value, GrB_Field f) ;
\end{verbatim}
}\end{mdframed}

\noindent
{\small
\begin{tabular}{|l|l|l|p{2.85in}|}
\hline
\verb'GrB_Field'                    & R/W  & C type        & description \\
\hline
\verb'GrB_EL_TYPE_CODE'             & R    & \verb'int32_t'& type code (see \verb'GrB_Type_Code') \\
\verb'GrB_SIZE'                     & R    & \verb'size_t' & \verb'sizeof' the type \\
\hline
\verb'GrB_NAME'                     & R/W1 & \verb'char *' &    % GrB_ALREADY_SET (type)
    name of the type.  For built-in types, this returns the GraphBLAS
    name (\verb'"GrB_FP32"' for \verb'GrB_FP32', for example).
    For user-defined types, the name can be any string of any length.  It is
    not used by the JIT.  It can be set at most once. \\
\verb'GxB_JIT_C_NAME'               & R/W1 & \verb'char *' & 
    This must be a valid name of a C type to enable its use in the JIT.  For
    built-in types, this returns the C name of the type (\verb'"float"' for
    \verb'GrB_FP32', for example). The length of the name can be at most
    \verb'GxB_MAX_NAME_LEN', including the \verb'nul' terminating byte.  It can
    be set at most once. \\
\verb'GxB_JIT_C_DEFINITION'               & R/W1 & \verb'char *' &
    type definition, as a C \verb'typedef';
    built-in types return an empty string. 
    It can be set at most once. \\
\hline
\end{tabular}
}

Built-in types cannot be modified by \verb'GrB_set'.  User-defined types can be
used without setting their name or definition, but they can be used in JIT
kernels only when both the JIT C name and the definition are set.

To use the JIT, all operators, monoids, and semirings that access this type
must be defined after the user-defined type has been given both a name and a
definition.  GraphBLAS can use an operator that uses a type without a name,
but it cannot use the JIT, even if the type is given a name later on after
the operator is created.

The size of the type can be returned as a \verb'size_t' C scalar, or as a
\verb'GrB_Scalar', normally of type \verb'GrB_UINT64', with the examples below.

{\footnotesize
\begin{verbatim}
    size_t size ;
    GrB_get (GrB_FP32, &size, GrB_SIZE) ;
    assert (size == sizeof (float)) ;

    GrB_Scalar s ;
    GrB_Scalar_new (&s, GrB_UINT64) ;
    GrB_get (GrB_FP32, s, GrB_SIZE) ;
    GrB_Scalar_extractElement (&size, s) ;
    assert (size == sizeof (float)) ; \end{verbatim}}

%-------------------------------------------------------------------------------
\newpage
\subsection{{\sf GrB\_UnaryOp} Options}
\label{get_set_unop}
%-------------------------------------------------------------------------------

\begin{mdframed}[userdefinedwidth=6in]
{\footnotesize
\begin{verbatim}
GrB_Info GrB_get (GrB_UnaryOp op, GrB_Scalar value, GrB_Field f) ;
GrB_Info GrB_get (GrB_UnaryOp op, char *     value, GrB_Field f) ;
GrB_Info GrB_get (GrB_UnaryOp op, int32_t *  value, GrB_Field f) ;
GrB_Info GrB_get (GrB_UnaryOp op, size_t *   value, GrB_Field f) ;

GrB_Info GrB_set (GrB_UnaryOp op, char *     value, GrB_Field f) ;
\end{verbatim}
}\end{mdframed}

\noindent
{\small
\begin{tabular}{|l|l|l|p{2.8in}|}
\hline
\verb'GrB_Field'                    & R/W  & C type        & description \\
\hline
\verb'GrB_INP0_TYPE_CODE'          & R    & \verb'int32_t'& input type code (see \verb'GrB_Type_code') \\
\verb'GrB_OUTP_TYPE_CODE'          & R    & \verb'int32_t'& output type code \\
\verb'GrB_INP0_TYPE_STRING'        & R    & \verb'char *' & name of the input type \\
\verb'GrB_OUTP_TYPE_STRING'        & R    & \verb'char *' & name of the output type \\
\hline
\verb'GrB_NAME'                     & R/W1 & \verb'char *' &    % GrB_ALREADY_SET (unop)
    name of the operator.  For built-in operators, this returns the GraphBLAS
    name (\verb'"GrB_LNOT"' for \verb'GrB_LNOT', for example).
    For user-defined operators, the name can be any string of any length.  It
    is not used by the JIT.  It can be set at most once. \\
\verb'GxB_JIT_C_NAME'               & R/W1 & \verb'char *' &
    This must be a valid name of a C function to enable its use in the JIT.
    The length of the name can be at most \verb'GxB_MAX_NAME_LEN', including
    the \verb'nul' terminating byte.  It can be set at most once. \\
\verb'GxB_JIT_C_DEFINITION'         & R/W1 & \verb'char *' &
    definition for a user-defined operator, as a C function; built-in operators
    return an empty string.  It can be set at most once. \\
\hline
\end{tabular}
}

Built-in operators cannot be modified by \verb'GrB_set'.  User-defined
operators can be used without setting their name or definition, but they can be
used in JIT kernels only when both the JIT C name and the definition are set.

%-------------------------------------------------------------------------------
\newpage
\subsection{{\sf GrB\_IndexUnaryOp} Options}
\label{get_set_idxunop}
%-------------------------------------------------------------------------------

\begin{mdframed}[userdefinedwidth=6in]
{\footnotesize
\begin{verbatim}
GrB_Info GrB_get (GrB_IndexUnaryOp op, GrB_Scalar value, GrB_Field f) ;
GrB_Info GrB_get (GrB_IndexUnaryOp op, char *     value, GrB_Field f) ;
GrB_Info GrB_get (GrB_IndexUnaryOp op, int32_t *  value, GrB_Field f) ;
GrB_Info GrB_get (GrB_IndexUnaryOp op, size_t *   value, GrB_Field f) ;

GrB_Info GrB_set (GrB_IndexUnaryOp op, char *     value, GrB_Field f) ;
\end{verbatim}
}\end{mdframed}

\noindent
{\small
\begin{tabular}{|l|l|l|p{2.8in}|}
\hline
\verb'GrB_Field'                    & R/W  & C type        & description \\
\hline
\verb'GrB_INP0_TYPE_CODE'          & R    & \verb'int32_t'& 1st input type code (see \verb'GrB_Type_code') \\
\verb'GrB_INP1_TYPE_CODE'          & R    & \verb'int32_t'& 2nd input type code \\
\verb'GrB_OUTP_TYPE_CODE'          & R    & \verb'int32_t'& output type code \\
\verb'GrB_INP0_TYPE_STRING'        & R    & \verb'char *' & name of the 1st input type \\
\verb'GrB_INP1_TYPE_STRING'        & R    & \verb'char *' & name of the 2nd input type \\
\verb'GrB_OUTP_TYPE_STRING'        & R    & \verb'char *' & name of the output type \\
\hline
\verb'GrB_NAME'                     & R/W1 & \verb'char *' &    % GrB_ALREADY_SET (idxunop)
    name of the operator.  For built-in operators, this returns the GraphBLAS
    name (\verb'"GrB_TRIL"' for \verb'GrB_TRIL', for example).
    For user-defined operators, the name can be any string of any length.  It
    is not used by the JIT.  It can be set at most once. \\
\verb'GxB_JIT_C_NAME'               & R/W1 & \verb'char *' &
    This must be a valid name of a C function to enable its use in the JIT.
    The length of the name can be at most \verb'GxB_MAX_NAME_LEN', including
    the \verb'nul' terminating byte.  It can be set at most once. \\
\verb'GxB_JIT_C_DEFINITION'         & R/W1 & \verb'char *' &
    definition for a user-defined operator, as a C function; built-in operators
    return an empty string.  It can be set at most once. \\
\hline
\end{tabular}
}

Built-in operators cannot be modified by \verb'GrB_set'.  User-defined
operators can be used without setting their name or definition, but they can be
used in JIT kernels only when both the JIT C name and the definition are set.

%-------------------------------------------------------------------------------
\newpage
\subsection{{\sf GrB\_BinaryOp} Options}
\label{get_set_binop}
%-------------------------------------------------------------------------------

\begin{mdframed}[userdefinedwidth=6in]
{\footnotesize
\begin{verbatim}
GrB_Info GrB_get (GrB_BinaryOp op, GrB_Scalar value, GrB_Field f) ;
GrB_Info GrB_get (GrB_BinaryOp op, char *     value, GrB_Field f) ;
GrB_Info GrB_get (GrB_BinaryOp op, int32_t *  value, GrB_Field f) ;
GrB_Info GrB_get (GrB_BinaryOp op, size_t *   value, GrB_Field f) ;

GrB_Info GrB_set (GrB_BinaryOp op, char *     value, GrB_Field f) ;
\end{verbatim}
}\end{mdframed}

\noindent
{\small
\begin{tabular}{|l|l|l|p{2.8in}|}
\hline
\verb'GrB_Field'                    & R/W  & C type        & description \\
\hline
\verb'GrB_INP0_TYPE_CODE'          & R    & \verb'int32_t'& 1st input type code (see \verb'GrB_Type_code') \\
\verb'GrB_INP1_TYPE_CODE'          & R    & \verb'int32_t'& 2nd input type code \\
\verb'GrB_OUTP_TYPE_CODE'          & R    & \verb'int32_t'& output type code \\
\verb'GrB_INP0_TYPE_STRING'        & R    & \verb'char *' & name of the 1st input type \\
\verb'GrB_INP1_TYPE_STRING'        & R    & \verb'char *' & name of the 2nd input type \\
\verb'GrB_OUTP_TYPE_STRING'        & R    & \verb'char *' & name of the output type \\
\hline
\verb'GrB_NAME'                     & R/W1 & \verb'char *' &    % GrB_ALREADY_SET (binop)
    name of the operator.  For built-in operators, this returns the GraphBLAS
    name (\verb'"GrB_LOR"' for \verb'GrB_LOR', for example).
    For user-defined operators, the name can be any string of any length.  It
    is not used by the JIT.  It can be set at most once. \\
\verb'GxB_JIT_C_NAME'               & R/W1 & \verb'char *' &
    This must be a valid name of a C function to enable its use in the JIT.
    The length of the name can be at most \verb'GxB_MAX_NAME_LEN', including
    the \verb'nul' terminating byte.  It can be set at most once. \\
\verb'GxB_JIT_C_DEFINITION'         & R/W1 & \verb'char *' &
    definition for a user-defined operator, as a C function; built-in operators
    return an empty string.  It can be set at most once. \\
\hline
\end{tabular}
}

Built-in operators cannot be modified by \verb'GrB_set'.  User-defined
operators can be used without setting their name or definition, but they can be
used in JIT kernels only when both the JIT C name and the definition are set.

To use the JIT, all monoids and semirings that access this binary operator must
be defined after the user-defined operator has been given both a name and a
definition.  GraphBLAS can use a monoid or semiring that uses a binary operator
without a name, but it cannot use the JIT, even if the operator is given a name
later on after the operator is created.

%-------------------------------------------------------------------------------
\newpage
\subsection{{\sf GrB\_Monoid} Options}
\label{get_set_monoid}
%-------------------------------------------------------------------------------

\begin{mdframed}[userdefinedwidth=6in]
{\footnotesize
\begin{verbatim}
GrB_Info GrB_get (GrB_Monoid monoid, GrB_Scalar value, GrB_Field f) ;
GrB_Info GrB_get (GrB_Monoid monoid, char *     value, GrB_Field f) ;
GrB_Info GrB_get (GrB_Monoid monoid, int32_t *  value, GrB_Field f) ;
GrB_Info GrB_get (GrB_Monoid monoid, size_t *   value, GrB_Field f) ;
GrB_Info GrB_get (GrB_Monoid monoid, void *     value, GrB_Field f) ;

GrB_Info GrB_set (GrB_Monoid monoid, char *     value, GrB_Field f) ;
\end{verbatim}
}\end{mdframed}


\noindent
{\small
\begin{tabular}{|l|l|l|p{2.5in}|}
\hline
\verb'GrB_Field'                    & R/W  & C type        & description \\
\hline
\verb'GrB_INP0_TYPE_CODE'          & R    & \verb'int32_t'& 1st input type code \newline
                                                             (see \verb'GrB_Type_code') \\
\verb'GrB_INP1_TYPE_CODE'          & R    & \verb'int32_t'& 2nd input type code \\
\verb'GrB_OUTP_TYPE_CODE'          & R    & \verb'int32_t'& output type code \\
\verb'GrB_INP0_TYPE_STRING'        & R    & \verb'char *' & name of the 1st input type \\
\verb'GrB_INP1_TYPE_STRING'        & R    & \verb'char *' & name of the 2nd input type \\
\verb'GrB_OUTP_TYPE_STRING'        & R    & \verb'char *' & name of the output type \\
\hline
\verb'GrB_NAME'                     & R/W1 & \verb'char *' &    % GrB_ALREADY_SET (monoid)
    name of the monoid.  For built-in monoids, this returns the GraphBLAS
    name (\verb'"GrB_LOR_MONOID_BOOL"' for \verb'GrB_LOR_MONOID_BOOL', for example).
    For user-defined monoids, the name can be any string of any length.  It is
    not used by the JIT.  It can be set at most once. \\
\hline
\verb'GxB_MONOID_IDENTITY'          & R  & \verb'GrB_Scalar' &
    identity value of the monoid.  The type of the \verb'GrB_Scalar'
    must match the monoid type exactly. \\
\verb'GxB_MONOID_TERMINAL'          & R  & \verb'GrB_Scalar' &
    terminal value of a terminal monoid.  The type of the \verb'GrB_Scalar'
    must match the monoid type exactly.  If the monoid is not terminal,
    the \verb'GrB_Scalar' is returned with no entry. \\
\hline
\verb'GxB_MONOID_OPERATOR'          & R  & \verb'void *' &
    binary operator of the monoid, as a \verb'GrB_BinaryOp' \\
\hline
\end{tabular}
}

Built-in monoids cannot be modified by \verb'GrB_set'.

For \verb'GxB_MONOID_OPERATOR',
the \verb'op' is returned as an alias, not as a new object.  For example,
if a monoid is created with a user-defined binary operator, the following usage
returns a shallow copy of the operator:

    {\footnotesize
    \begin{verbatim}
    GrB_BinaryOp binop ;
    GrB_BinaryOp_new (&binop, func, GrB_BOOL, GrB_BOOL, GrB_BOOL) ;
    GrB_Monoid monoid ;
    GrB_Monoid_new (&monoid, binop, (bool) false) ; \end{verbatim} }

With the above objects defined, the following two code snippets do the same thing:

    {\footnotesize
    \begin{verbatim}
    // getting an alias to the binary operator directly:
    GrB_BinaryOp op ;
    op = binop ; \end{verbatim} }

    {\footnotesize
    \begin{verbatim}
    // getting an alias to the binary operator using GrB_get:
    GrB_BinaryOp op ;
    GrB_get (monoid, (void *) &op, GxB_MONOID_OPERATOR) ;
    assert (op == binop) ; \end{verbatim} }

As a result, it is not valid to free both the \verb'op' and the \verb'binop',
since they are the same object.  This usage returns the built-in \verb'GrB_LOR'
operator of the corresponding built-in monoid:

    {\footnotesize
    \begin{verbatim}
    GrB_BinaryOp op ;
    GrB_get (GrB_LOR_MONOID, (void *) &op, GxB_MONOID_OPERATOR) ;
    assert (op == GrB_LOR) ; \end{verbatim} }

%-------------------------------------------------------------------------------
\newpage
\subsection{{\sf GrB\_Semiring} Options}
\label{get_set_semiring}
%-------------------------------------------------------------------------------

\begin{mdframed}[userdefinedwidth=6in]
{\footnotesize
\begin{verbatim}
GrB_Info GrB_get (GrB_Semiring semiring, GrB_Scalar value, GrB_Field f) ;
GrB_Info GrB_get (GrB_Semiring semiring, char *     value, GrB_Field f) ;
GrB_Info GrB_get (GrB_Semiring semiring, int32_t *  value, GrB_Field f) ;
GrB_Info GrB_get (GrB_Semiring semiring, size_t *   value, GrB_Field f) ;
GrB_Info GrB_get (GrB_Semiring semiring, void *     value, GrB_Field f) ;

GrB_Info GrB_set (GrB_Semiring semiring, GrB_Scalar value, GrB_Field f) ;
\end{verbatim}
}\end{mdframed}

\noindent
{\small
\begin{tabular}{|l|l|l|p{2.8in}|}
\hline
\verb'GrB_Field'                    & R/W  & C type        & description \\
\hline
\verb'GrB_INP0_TYPE_CODE'          & R    & \verb'int32_t'& 1st input type code (see \verb'GrB_Type_code')
    of the multiplicative operator \\
\verb'GrB_INP1_TYPE_CODE'          & R    & \verb'int32_t'& 2nd input type code
    of the multiplicative operator \\
\verb'GrB_OUTP_TYPE_CODE'          & R    & \verb'int32_t'& output type code 
    of the multiplicative operator,
    and the monoid type. \\
\verb'GrB_INP0_TYPE_STRING'        & R    & \verb'char *' & name of the 1st input type
    of the multiplicative operator \\
\verb'GrB_INP1_TYPE_STRING'        & R    & \verb'char *' & name of the 2nd input type
    of the multiplicative operator \\
\verb'GrB_OUTP_TYPE_STRING'        & R    & \verb'char *' & name of the output type
    of the multiplicative operator,
    and the monoid type. \\
\hline
\verb'GrB_NAME'                     & R/W1 & \verb'char *' &    % GrB_ALREADY_SET (semiring)
    name of the semiring.  For built-in semirings, this returns the GraphBLAS
    name (\verb'"GrB_LOR_LAND_SEMIRING_BOOL"' for \verb'GrB_LOR_LAND_SEMIRING_BOOL',
    for example).  For user-defined semirings, the name can be any string of any
    length.  It is not used by the JIT.  It can be set at most once. \\
\hline
\end{tabular}
}

\noindent
{\small
\begin{tabular}{|l|l|l|p{2.5in}|}
\hline
\verb'GrB_Field'                    & R/W  & C type        & description \\
\hline
\verb'GxB_MONOID_IDENTITY'          & R  & \verb'GrB_Scalar' &
    identity value of the monoid.  The type of the \verb'GrB_Scalar'
    must match the monoid type exactly. \\
\verb'GxB_MONOID_TERMINAL'          & R  & \verb'GrB_Scalar' &
    terminal value of a terminal monoid.  The type of the \verb'GrB_Scalar'
    must match the monoid type exactly.  If the monoid is not terminal,
    the \verb'GrB_Scalar' is returned with no entry. \\
\hline
\verb'GxB_MONOID_OPERATOR'          & R  & \verb'void *' &
    binary operator of the monoid, as a \verb'GrB_BinaryOp';
    See Section~\ref{get_set_monoid} \\
\verb'GxB_SEMIRING_MONOID'          & R  & \verb'void *' &
    monoid of the semiring, as a \verb'GrB_Monoid' \\
\verb'GxB_SEMIRING_MULTIPLY'        & R  & \verb'void *' &
    multiplicative operator of the semiring, as a \verb'GrB_BinaryOp' \\
\hline
\end{tabular}
}

Built-in semirings cannot be modified by \verb'GrB_set'.

The \verb'GxB_SEMIRING_MONOID' option returns the \verb'GrB_Monoid' of the
semiring.  The \verb'GxB_SEMIRING_MULTIPLY' option returns the
\verb'GrB_BinaryOp' for the multiplicative operator of the semiring.  For
example:

    {\footnotesize
    \begin{verbatim}
    // getting an alias to the monoid and multiply operator using GrB_get:
    GrB_BinaryOp op ;
    GrB_Monoid mon ;
    GrB_Semiring semiring = GrB_PLUS_TIMES_FP32 ;
    GrB_get (semiring, (void *) &mon, GxB_SEMIRING_MONOID) ;
    GrB_get (semiring, (void *) &op, GxB_SEMIRING_MULTIPLY) ;
    assert (op == GrB_TIMES_FP32) ;
    assert (mon == GrB_PLUS_MONOID_FP32) ; \end{verbatim} }

The binary op and monoid returned are aliases, not new objects.

%-------------------------------------------------------------------------------
\newpage
\subsection{{\sf GrB\_Matrix} Options}
\label{get_set_matrix}
%-------------------------------------------------------------------------------

\begin{mdframed}[userdefinedwidth=6in]
{\footnotesize
\begin{verbatim}
GrB_Info GrB_get (GrB_Matrix A, GrB_Scalar value, GrB_Field f) ;
GrB_Info GrB_get (GrB_Matrix A, char *     value, GrB_Field f) ;
GrB_Info GrB_get (GrB_Matrix A, int32_t *  value, GrB_Field f) ;
GrB_Info GrB_get (GrB_Matrix A, size_t *   value, GrB_Field f) ;

GrB_Info GrB_set (GrB_Matrix A, GrB_Scalar value, GrB_Field f) ;
GrB_Info GrB_set (GrB_Matrix A, char *     value, GrB_Field f) ;
GrB_Info GrB_set (GrB_Matrix A, int32_t    value, GrB_Field f) ;
\end{verbatim}
}\end{mdframed}

\noindent
{\small
\begin{tabular}{|l|l|l|p{2.2in}|}
\hline
\verb'GrB_Field'                    & R/W  & C type        & description \\
\hline
\verb'GrB_STORAGE_ORIENTATION_HINT' & R/W  & \verb'int32_t'& See \verb'GrB_Orientation', \newline
                                                             and Section~\ref{storage_orientation}. \\
\verb'GrB_EL_TYPE_CODE'             & R    & \verb'int32_t'& matrix type \\
\verb'GxB_SPARSITY_CONTROL'         & R/W  & \verb'int32_t'& See Section~\ref{sparsity_status} \\
\verb'GxB_SPARSITY_STATUS'          & R    & \verb'int32_t'& See Section~\ref{sparsity_status} \\
\hline
\verb'GrB_NAME'                     & R/W  & \verb'char *' & name of the matrix.
                                        This can be set any number of times. \\
\verb'GrB_EL_TYPE_STRING'           & R    & \verb'char *' & name of the type of the matrix. \\
\verb'GxB_JIT_C_NAME'               & R    & \verb'char *' & JIT C name of the type of the matrix. \\
\hline
\verb'GxB_HYPER_SWITCH'             & R/W  & \verb'double' & See Section~\ref{hypersparse} \\
\verb'GxB_BITMAP_SWITCH'            & R/W  & \verb'double' & See Section~\ref{bitmap_switch} \\
\hline
\end{tabular}
}

%-------------------------------------------------------------------------------
\subsubsection{Storing a matrix by row or by column}
\label{storage_orientation}
%-------------------------------------------------------------------------------

The GraphBLAS \verb'GrB_Matrix' is entirely opaque to the user application, and
the GraphBLAS API does not specify how the matrix should be stored.  However,
choices made in how the matrix is represented in a particular implementation,
such as SuiteSparse:GraphBLAS, can have a large impact on performance.

Many graph algorithms are just as fast in any format, but some algorithms are
much faster in one format or the other.  For example, suppose the user
application stores a directed graph as a matrix \verb'A', with the edge $(i,j)$
represented as the value \verb'A(i,j)', and the application makes many accesses
to the $i$th row of the matrix, with \verb'GrB_Col_extract'
\verb'(w,...,A,GrB_ALL,...,i,desc)' with the transposed descriptor
(\verb'GrB_INP0' set to \verb'GrB_TRAN').  If the matrix is stored by column
this can be extremely slow, just like the expression \verb'w=A(i,:)' in MATLAB,
where \verb'i' is a scalar.  Since this is a typical use-case in graph
algorithms, the default format in SuiteSparse:GraphBLAS is to store its
matrices by row, in Compressed Sparse Row format (CSR).

MATLAB stores its sparse matrices by column, in ``non-hypersparse'' format, in
what is called the Compressed Sparse Column format, or CSC for short.  An
\verb'm'-by-\verb'n' matrix in MATLAB is represented as a set of \verb'n'
column vectors, each with a sorted list of row indices and values of the
nonzero entries in that column.  As a result, \verb'w=A(:,j)' is very fast in
MATLAB, since the result is already held in the data structure a single list,
the $j$th column vector.  However, \verb'w=A(i,:)' is very slow in MATLAB,
since every column in the matrix has to be searched to see if it contains row
\verb'i'.  In MATLAB, if many such accesses are made, it is much better to
transpose the matrix (say \verb"AT=A'") and then use \verb"w=AT(:,i)" instead.
This can have a dramatic impact on the performance of MATLAB.

Likewise, if \verb'u' is a very sparse column vector and \verb'A' is stored by
column, then \verb"w=u'*A" (via \verb'GrB_vxm') is slower than \verb'w=A*u'
(via \verb'GrB_mxv').  The opposite is true if the matrix is stored by row.

SuiteSparse:GraphBLAS stores its matrices by row, by default (with one
exception described below).  However, it can also be instructed to store any
selected matrices, or all matrices, by column instead (just like MATLAB), so
that \verb'w=A(:,j)' (via \verb'GrB_Col_extract') is very fast.  The change in
data format has no effect on the result, just the time and memory usage.  To
use a column-oriented format by default, the following can be done in a user
application that tends to access its matrices by column.

    {\footnotesize
    \begin{verbatim}
    GrB_init (...) ;
    // just after GrB_init: do the following:
    GrB_set (GrB_GLOBAL, GrB_COLMAJOR, GrB_STORAGE_ORIENTATION_HINT) ; \end{verbatim} }

If this is done, and no other \verb'GrB_set' calls are made with \newline
\verb'GrB_STORAGE_ORIENATION_HINT', all matrices will be stored by column.
The default format is \verb'GrB_ROWMAJOR'.

All vectors (\verb'GrB_Vector') are held by column, and this cannot be changed.

By default, matrices of size \verb'm-by-1' are held by column, regardless of
the global setting described above.  Matrices of size \verb'1-by-n' with
\verb'n' not equal to 1 are held by row, regardless of the global setting.
The global setting only affects matrices with both \verb'm > 1' and \verb'n > 1'.
Empty matrices (\verb'0-by-0') are also controlled by the global setting.

After creating a matrix with \verb'GrB_Matrix_new (&A, ...)',
its format can be changed arbitrarily with:

    {\footnotesize
    \begin{verbatim}
    GrB_set (A, GrB_COLMAJOR, GrB_STORAGE_ORIENTATION_HINT) ;
    GrB_set (A, GrB_ROWMAJOR, GrB_STORAGE_ORIENTATION_HINT) ; \end{verbatim} }

If set to other values (\verb'GrB_BOTH' or \verb'GrB_UNKNOWN'), the
format is changed to \verb'GrB_ROWMAJOR'.

With this setting, even an \verb'm-by-1' matrix can then be changed to be held
by row, for example.  Likewise, once a \verb'1-by-n' matrix is created, it can
be converted to column-oriented format.

%-------------------------------------------------------------------------------
\subsubsection{Hypersparse matrices}
\label{hypersparse}
%-------------------------------------------------------------------------------

MATLAB can store an \verb'm'-by-\verb'n' matrix with a very large value of
\verb'm', since a CSC data structure takes $O(n+|{\bf A}|)$ memory, independent
of \verb'm', where $|{\bf A}|$ is the number of nonzeros in the matrix.  It
cannot store a matrix with a huge \verb'n', and this structure is also
inefficient when $|{\bf A}|$ is much smaller than \verb'n'.  In contrast,
SuiteSparse:GraphBLAS can store its matrices in {\em hypersparse} format,
taking only $O(|{\bf A}|)$ memory, independent of how it is stored (by row or
by column) and independent of both \verb'm' and \verb'n'
\cite{BulucGilbert08,BulucGilbert12}.

In both the CSR and CSC formats, the matrix is held as a set of sparse vectors.
In non-hypersparse format, the set of sparse vectors is itself dense; all
vectors are present, even if they are empty.  For example, an
\verb'm'-by-\verb'n' matrix in non-hypersparse CSC format contains \verb'n'
sparse vectors.  Each column vector takes at least one integer to represent,
even for a column with no entries.  This allows for quick lookup for a
particular vector, but the memory required is $O(n+|{\bf A}|)$.  With a
hypersparse CSC format, the set of vectors itself is sparse, and columns with
no entries take no memory at all.  The drawback of the hypersparse format is
that finding an arbitrary column vector \verb'j', such as for the computation
\verb'C=A(:,j)', takes $O(\log k)$ time if there $k \le n$ vectors in the data
structure.  One advantage of the hypersparse structure is the memory required
for an \verb'm'-by-\verb'n' hypersparse CSC matrix is only $O(|{\bf A}|)$,
independent of \verb'm' and \verb'n'.  Algorithms that must visit all non-empty
columns of a matrix are much faster when working with hypersparse matrices,
since empty columns can be skipped.

The \verb'hyper_switch' parameter controls the hypersparsity of the internal
data structure for a matrix.  The parameter is typically in the range 0 to 1.
The default is \verb'hyper_switch' = \verb'GxB_HYPER_DEFAULT', which is an
\verb'extern' \verb'const' \verb'double' value, currently set to 0.0625, or
1/16.  This default ratio may change in the future.

The \verb'hyper_switch' determines how the matrix is converted between the
hypersparse and non-hypersparse formats.  Let $n$ be the number of columns of a
CSC matrix, or the number of rows of a CSR matrix.  The matrix can have at most
$n$ non-empty vectors.

Let $k$ be the actual number of non-empty vectors.  That is, for the CSC
format, $k \le n$ is the number of columns that have at least one entry.  Let
$h$ be the value of \verb'hyper_switch'.

If a matrix is currently hypersparse, it can be converted to non-hypersparse if
the either condition $n \le 1$ or $k > 2nh$ holds, or both.  Otherwise, it
stays hypersparse.  Note that if $n \le 1$ the matrix is always stored as
non-hypersparse.

If currently non-hypersparse, it can be converted to hypersparse if
both conditions $n > 1$ and $k \le nh$ hold.  Otherwise, it stays
non-hypersparse.  Note that if $n \le 1$ the matrix always remains
non-hypersparse.

The default value of \verb'hyper_switch' is assigned at startup by
\verb'GrB_init', and can then be modified globally with \verb'GrB_set'.  All
new matrices are created with the same \verb'hyper_switch', determined by the
global value.  Once a particular matrix \verb'A' has been constructed, its
hypersparsity ratio can be modified from the default with:

    {\footnotesize
    \begin{verbatim}
    double hyper_switch = 0.2 ;
    GrB_set (A, hyper_switch, GxB_HYPER_SWITCH) ; \end{verbatim}}

To force a matrix to always be non-hypersparse, use \verb'hyper_switch' equal to
\verb'GxB_NEVER_HYPER'.  To force a matrix to always stay hypersparse, set
\verb'hyper_switch' to \verb'GxB_ALWAYS_HYPER'.

A \verb'GrB_Matrix' can thus be held in one of four formats: any combination of
hyper/non-hyper and CSR/CSC.  All \verb'GrB_Vector' objects are always stored
in non-hypersparse CSC format.

A new matrix created via \verb'GrB_Matrix_new' starts with $k=0$ and is created
in hypersparse form by default unless $n \le 1$ or if $h<0$, where $h$ is the
global \verb'hyper_switch' value.  The matrix is created in either
\verb'GrB_ROWMAJOR' or \verb'GrB_COLMAJOR' format, as determined by the last call
to
\verb'GrB_set(GrB_GLOBAL,' \verb'..., GrB_STORAGE_ORIENTATION_HINT,...)' or \verb'GrB_init'.

A new matrix \verb'C' created via \verb'GrB_dup (&C,A)' inherits the CSR/CSC
format, hypersparsity format, and \verb'hyper_switch' from \verb'A'.

%-------------------------------------------------------------------------------
\subsubsection{Bitmap matrices}
\label{bitmap_switch}
%-------------------------------------------------------------------------------

By default, SuiteSparse:GraphBLAS switches between all four formats
(hypersparse, sparse, bitmap, and full) automatically.  Let $d = |{\bf A}|/mn$
for an $m$-by-$n$ matrix $\bf A$ with $|{\bf A}|$ entries.  If the matrix is
currently in sparse or hypersparse format, and is modified so that $d$ exceeds
a given threshold, it is converted into bitmap format.  The default threshold
is controlled by the \verb'GxB_BITMAP_SWITCH' setting, which can be set
globally, or for a particular matrix or vector.

The default value of the switch to bitmap format depends on $\min(m,n)$, for a
matrix of size $m$-by-$n$.  For the global setting, the bitmap switch is a
\verb'double' array of size \verb'GxB_NBITMAP_SWITCH'.  The defaults are given
below:

\vspace{0.2in}
{\small
\begin{tabular}{lll}
parameter & default & matrix sizes \\
\hline
\verb'bitmap_switch [0]' & 0.04 & $\min(m,n) = 1$ (and all vectors) \\
\verb'bitmap_switch [1]' & 0.05 & $\min(m,n) = 2$ \\
\verb'bitmap_switch [2]' & 0.06 & $\min(m,n) = 3$ to 4 \\
\verb'bitmap_switch [3]' & 0.08 & $\min(m,n) = 5$ to 8 \\
\verb'bitmap_switch [4]' & 0.10 & $\min(m,n) = 9$ to 16\\
\verb'bitmap_switch [5]' & 0.20 & $\min(m,n) = 17$ to 32\\
\verb'bitmap_switch [6]' & 0.30 & $\min(m,n) = 33$ to 64 \\
\verb'bitmap_switch [7]' & 0.40 & $\min(m,n) > 64$ \\
\end{tabular}
}
\vspace{0.2in}

That is, by default a \verb'GrB_Vector' is held in bitmap format if its density
exceeds 4\%.  To change the global settings, do the following:

{\footnotesize
\begin{verbatim}
    double bswitch [GxB_NBITMAP_SWITCH] = { 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8 } ;
    GrB_set (GrB_GLOBAL, (void *) bswitch, GxB_BITMAP_SWITCH,
        GxB_NBITMAP_SWITCH * sizeof (double)) ;
\end{verbatim}
}

If the matrix is currently in bitmap format, it is converted to full if all
entries are present, or to sparse/hypersparse if $d$ drops below $b/2$, if its
bitmap switch is $b$.  A matrix or vector with $d$ between $b/2$ and $b$
remains in its current format.

%-------------------------------------------------------------------------------
\subsubsection{Sparsity status}
\label{sparsity_status}
%-------------------------------------------------------------------------------

The sparsity status of a matrix can be queried with the following, which
returns a value of \verb'GxB_HYPERSPARSE' (1), \verb'GxB_SPARSE' (2),
\verb'GxB_BITMAP' (4), or \verb'GxB_FULL' (8).

{\footnotesize
\begin{verbatim}
    int32_t sparsity ;
    GrB_get (A, &sparsity, GxB_SPARSITY_STATUS) ; \end{verbatim}}

The sparsity format of a matrix can be controlled with the field set to
\verb'GxB_SPARSITY_CONTROL', for which the \verb'value' can be any mix (a sum or bitwise
or) of \verb'GxB_HYPERSPARSE', \verb'GxB_SPARSE', \verb'GxB_BITMAP', and
\verb'GxB_FULL'.  By default, a matrix or vector can be held in any format,
with the default setting \verb'GxB_AUTO_SPARSITY', which is equal to
\verb'GxB_HYPERSPARSE' + \verb'GxB_SPARSE' + \verb'GxB_BITMAP' +
\verb'GxB_FULL' (15).  To enable a matrix to take on just \verb'GxB_SPARSE' or
\verb'GxB_FULL' formats, but not \verb'GxB_HYPERSPARSE' or \verb'GxB_BITMAP',
for example, use the following:

{\footnotesize
\begin{verbatim}
    GrB_set (A, GxB_SPARSE + GxB_FULL, GxB_SPARSITY_CONTROL) ; \end{verbatim}}

In this case, SuiteSparse:GraphBLAS will hold the matrix in sparse format
(\verb'CSR' or \verb'CSC', depending on its
\verb'GrB_STORAGE_ORIENTATION_HINT'), unless all entries are present, in which
case it will be converted to full format.

Only the least significant 4 bits of the sparsity control are considered, so
the formats can be bitwise negated.  For example, to allow for any format
except full:

{\footnotesize
\begin{verbatim}
    GrB_set (A, ~GxB_FULL, GxB_SPARSITY_CONTROL) ; \end{verbatim}}

%-------------------------------------------------------------------------------
\newpage
\subsection{{\sf GrB\_Vector} Options}
\label{get_set_vector}
%-------------------------------------------------------------------------------

\begin{mdframed}[userdefinedwidth=6in]
{\footnotesize
\begin{verbatim}
GrB_Info GrB_get (GrB_Vector v, GrB_Scalar value, GrB_Field f) ;
GrB_Info GrB_get (GrB_Vector v, char *     value, GrB_Field f) ;
GrB_Info GrB_get (GrB_Vector v, int32_t *  value, GrB_Field f) ;
GrB_Info GrB_get (GrB_Vector v, size_t *   value, GrB_Field f) ;

GrB_Info GrB_set (GrB_Vector v, GrB_Scalar value, GrB_Field f) ;
GrB_Info GrB_set (GrB_Vector v, char *     value, GrB_Field f) ;
GrB_Info GrB_set (GrB_Vector v, int32_t    value, GrB_Field f) ;
\end{verbatim}
}\end{mdframed}

\noindent
{\small
\begin{tabular}{|l|l|l|p{3in}|}
\hline
\verb'GrB_Field'                    & R/W  & C type        & description \\
\hline
\verb'GrB_EL_TYPE_CODE'             & R    & \verb'int32_t'& vector type \\
\verb'GxB_SPARSITY_CONTROL'         & R/W  & \verb'int32_t'& See Section~\ref{sparsity_status} \\
\verb'GxB_SPARSITY_STATUS'          & R    & \verb'int32_t'& See Section~\ref{sparsity_status} \\
\hline
\verb'GrB_NAME'                     & R/W  & \verb'char *' & name of the vector. \\
%                                       This can be set any number of times. \\
\verb'GrB_EL_TYPE_STRING'           & R    & \verb'char *' & name of the type of the vector. \\
\verb'GxB_JIT_C_NAME'               & R    & \verb'char *' & JIT C name of the type of the vector. \\
\hline
\verb'GxB_BITMAP_SWITCH'            & R/W  & \verb'double' & See Section~\ref{bitmap_switch} \\
\hline
\end{tabular}
}

See Section~\ref{get_set_matrix}; a \verb'GrB_Vector' is treated as if it were
an $n$-by-1 matrix, and is always in column major form.  It is never
hypersparse.

%-------------------------------------------------------------------------------
% \newpage
\subsection{{\sf GrB\_Scalar} Options}
\label{get_set_scalar}
%-------------------------------------------------------------------------------

\begin{mdframed}[userdefinedwidth=6in]
{\footnotesize
\begin{verbatim}
GrB_Info GrB_get (GrB_Scalar s, GrB_Scalar value, GrB_Field f) ;
GrB_Info GrB_get (GrB_Scalar s, char *     value, GrB_Field f) ;
GrB_Info GrB_get (GrB_Scalar s, int32_t *  value, GrB_Field f) ;
GrB_Info GrB_get (GrB_Scalar s, size_t *   value, GrB_Field f) ;

GrB_Info GrB_set (GrB_Scalar s, GrB_Scalar value, GrB_Field f) ;
GrB_Info GrB_set (GrB_Scalar s, char *     value, GrB_Field f) ;
GrB_Info GrB_set (GrB_Scalar s, int32_t    value, GrB_Field f) ;
\end{verbatim}
}\end{mdframed}

\noindent
{\small
\begin{tabular}{|l|l|l|p{3in}|}
\hline
\verb'GrB_Field'                    & R/W  & C type        & description \\
\hline

\verb'GrB_EL_TYPE_CODE'             & R    & \verb'int32_t'& scalar type \\
\verb'GxB_SPARSITY_STATUS'          & R    & \verb'int32_t'& See Section~\ref{sparsity_status} \\
\hline
\verb'GrB_NAME'                     & R/W  & \verb'char *' & name of the scalar. \\
%                                       This can be set any number of times. \\
\verb'GrB_EL_TYPE_STRING'           & R    & \verb'char *' & name of the type of the scalar. \\
\verb'GxB_JIT_C_NAME'               & R    & \verb'char *' & JIT C name of the type of the scalar. \\
\hline
\end{tabular}
}
\vspace{0.1in}

See Section~\ref{get_set_matrix}; a \verb'GrB_Scalar' is treated as if it were
a 1-by-1 matrix, and is always in column major form.  It is never hypersparse.

%-------------------------------------------------------------------------------
\newpage
\subsection{{\sf GrB\_Descriptor} Options}
\label{get_set_descriptor}
%-------------------------------------------------------------------------------

\begin{mdframed}[userdefinedwidth=6in]
{\footnotesize
\begin{verbatim}
GrB_Info GrB_get (GrB_Descriptor desc, GrB_Scalar value, GrB_Field f) ;
GrB_Info GrB_get (GrB_Descriptor desc, char *     value, GrB_Field f) ;
GrB_Info GrB_get (GrB_Descriptor desc, int32_t *  value, GrB_Field f) ;
GrB_Info GrB_get (GrB_Descriptor desc, size_t *   value, GrB_Field f) ;

GrB_Info GrB_set (GrB_Descriptor desc, GrB_Scalar value, GrB_Field f) ;
GrB_Info GrB_set (GrB_Descriptor desc, char *     value, GrB_Field f) ;
GrB_Info GrB_set (GrB_Descriptor desc, int32_t    value, GrB_Field f) ;
\end{verbatim}
}\end{mdframed}

\noindent
{\small
\begin{tabular}{|l|l|l|p{3.3in}|}
\hline
\verb'GrB_Field'                    & R/W  & C type        & description \\
\hline
\verb'GrB_OUTP'         & R/W  & \verb'int32_t'& \verb'GrB_DEFAULT' or \verb'GrB_REPLACE' \\
\verb'GrB_MASK'         & R/W  & \verb'int32_t'& \verb'GrB_DEFAULT', \verb'GrB_COMP', \verb'GrB_STRUCTURE', or
                                                    \newline \verb'GrB_COMP_STRUCTURE' \\
\verb'GrB_INP0'         & R/W  & \verb'int32_t'& \verb'GrB_DEFAULT' or \verb'GrB_TRAN' \\
\verb'GrB_INP1'         & R/W  & \verb'int32_t'& \verb'GrB_DEFAULT' or \verb'GrB_TRAN' \\
\verb'GxB_AxB_METHOD'   & R/W  & \verb'int32_t'& Method used by \verb'GrB_mxm' (\verb'GrB_DEFAULT', \newline
                                                 \verb'GxB_AxB_GUSTAVSON'.  \verb'GxB_AxB_HASH', \newline
                                                 \verb'GxB_AxB_SAXPY', or \verb'GxB_AxB_DOT'). \\
\verb'GxB_SORT'         & R/W  & \verb'int32_t'& if true, \verb'GrB_mxm' returns its output in sorted form. \\
\verb'GxB_COMPRESSION'  & R/W  & \verb'int32_t'& compression method for serialize methods. \\
\verb'GxB_IMPORT'       & R/W  & \verb'int32_t'& \verb'GxB_FAST_IMPORT' or \verb'GxB_SECURE_IMPORT' for \verb'GxB*_pack*' methods. \\
\hline
\verb'GrB_NAME'         & R/W  & \verb'char *' & name of the descriptor.
    This can be set any number of times for user-defined descriptors.  Built-in
    descriptors have the same name as the variable name (\verb'"GrB_DESC_T1"'
    for the \verb'GrB_DESC_T1' descriptor, for example) \\
\hline
\end{tabular}
}

The following table describes each option.
See Section~\ref{descriptor} for more details.

\vspace{0.2in}
\noindent
{\footnotesize
\begin{tabular}{|l|p{2.4in}|p{2.2in}|}
\hline
Descriptor & Default   & Non-default \\
field      & &  \\
\hline

\verb'GrB_OUTP'
    & \verb'GrB_DEFAULT':
    The output matrix is not cleared.  The operation computes
    ${\bf C \langle M \rangle = C \odot T}$.
    & \verb'GrB_REPLACE':
    After computing ${\bf Z=C\odot T}$,
    the output {\bf C} is cleared of all entries.
    Then ${\bf C \langle M \rangle = Z}$ is performed. \\

\hline

\verb'GrB_MASK'
    & \verb'GrB_DEFAULT':
    The Mask is not complemented.  \verb'Mask(i,j)=1' means the value $C_{ij}$
    can be modified by the operation, while \verb'Mask(i,j)=0' means the value
    $C_{ij}$ shall not be modified by the operation.
    & \verb'GrB_COMP':
    The Mask is complemented.  \verb'Mask(i,j)=0' means the value $C_{ij}$
    can be modified by the operation, while \verb'Mask(i,j)=1' means the value
    $C_{ij}$ shall not be modified by the operation. \\
    &
    & \verb'GrB_STRUCTURE':
    The values of the Mask are ignored.  If \verb'Mask(i,j)' is an entry
    in the \verb'Mask' matrix, it is treated as if \verb'Mask(i,j)=1'.
    The two options \verb'GrB_COMP' and \verb'GrB_STRUCTURE' can be
    combined, with two subsequent calls, or with a single call with the setting
    \verb'GrB_COMP+GrB_STRUCTURE'.  \\

\hline

\verb'GrB_INP0'
    & \verb'GrB_DEFAULT':
    The first input is not transposed prior to using it in the operation.
    & \verb'GrB_TRAN':
    The first input is transposed prior to using it in the operation.  Only
    matrices are transposed, never vectors. \\

\hline

\verb'GrB_INP1'
    & \verb'GrB_DEFAULT':
    The second input is not transposed prior to using it in the operation.
    & \verb'GrB_TRAN':
    The second input is transposed prior to using it in the operation.  Only
    matrices are transposed, never vectors. \\

\hline

\verb'GxB_AxB_METHOD'
    & \verb'GrB_DEFAULT':
    The method for \verb'C=A*B' is selected automatically.
    & \verb'GxB_AxB_'{\em method}: The selected method is used to compute
    \verb'C=A*B'.  \\

\hline

\verb'GxB_SORT'
    & \verb'GrB_DEFAULT':
    The computation of \verb'C=A*B' may leave \verb'C' in a jumbled state;
    \verb'GrB_wait' will finalize the matrix.
    & any nonzero value: \verb'C=A*B' always returns \verb'C' in final,
    sorted form. \\

\hline

\verb'GxB_COMPRESION'
    & \verb'GrB_DEFAULT':
    Serialize methods will use the default method, ZSTD (level 1)
    & See Section~\ref{serialize_deserialize} \\

\hline

\verb'GxB_IMPORT'
    & \verb'GrB_DEFAULT': fast import
    & \verb'GxB_SECURE_IMPORT': secure import \\

\hline
\end{tabular}
}


%-------------------------------------------------------------------------------
\newpage
\subsection{{\sf GxB\_Context} Options}
\label{get_set_context}
%-------------------------------------------------------------------------------

\begin{mdframed}[userdefinedwidth=6in]
{\footnotesize
\begin{verbatim}
GrB_Info GrB_get (GxB_Context Context, GrB_Scalar value, GrB_Field f) ;
GrB_Info GrB_get (GxB_Context Context, char *     value, GrB_Field f) ;
GrB_Info GrB_get (GxB_Context Context, int32_t *  value, GrB_Field f) ;
GrB_Info GrB_get (GxB_Context Context, size_t *   value, GrB_Field f) ;

GrB_Info GrB_set (GxB_Context Context, GrB_Scalar value, GrB_Field f) ;
GrB_Info GrB_set (GxB_Context Context, char *     value, GrB_Field f) ;
GrB_Info GrB_set (GxB_Context Context, int32_t    value, GrB_Field f) ;
\end{verbatim}
}\end{mdframed}

\noindent
{\small
\begin{tabular}{|l|l|l|p{3.5in}|}
\hline
\verb'GrB_Field'                    & R/W  & C type        & description \\
\hline
\verb'GxB_NTHREADS' & R/W & \verb'int32_t' & number of OpenMP threads to use;
    See Section~\ref{omp_parallelism} \\
\verb'GxB_CHUNK'    & R/W & \verb'double' & chunk factor for task creation;
    See Section~\ref{omp_parallelism} \\
\hline
\verb'GrB_NAME'         & R/W  & \verb'char *' & name of the context.
    This can be set any number of times for user-defined contexts.  Built-in
    contexts have the same name as the variable name (\verb'"GxB_CONTEXT_WORLD"'
    for the \verb'GxB_CONTEXT_WORLD' context, for example) \\
\hline
\end{tabular}
}

NOTE: the non-polymorphic names for this method are
\verb'GxB_Context_get_[KIND]' and \verb'GxB_Context_set_[KIND]', where
\verb'KIND' can be:
    \verb'Scalar' (for \verb'GrB_Scalar'),
    \verb'String' (for \verb'char *'),
    \verb'INT' (for \verb'int32_t'), and
    \verb'SIZE' (for \verb'size_t *' for \verb'GrB_get' only), and
    \verb'VOID' (for \verb'void *').
The non-polymorphic suffix of \verb'INT' is used here instead of
\verb'INT32' because \verb'GxB_Context_*_INT32' appear as historical methods
in version v8.0 and earlier, which are now deprecated.

For the \verb'int32_t' type, the use of the polymorphic \verb'GrB_set' and
\verb'GrB_get' accesses the correct version of this method.  When using
non-polymorphic methods, the use of \verb'GxB_Context_get_INT' and
\verb'GxB_Context_set_INT' is recommended.

%-------------------------------------------------------------------------------
\newpage
\subsection{Options for inspecting a serialized blob}
\label{get_set_blob}
%-------------------------------------------------------------------------------

\begin{mdframed}[userdefinedwidth=6.5in]
{\footnotesize
\begin{verbatim}
GrB_Info GrB_get (const void *blob, GrB_Scalar value, GrB_Field f, size_t blobsize) ;
GrB_Info GrB_get (const void *blob, char *     value, GrB_Field f, size_t blobsize) ;
GrB_Info GrB_get (const void *blob, int32_t *  value, GrB_Field f, size_t blobsize) ;
GrB_Info GrB_get (const void *blob, size_t *   value, GrB_Field f, size_t blobsize) ;
\end{verbatim}
}\end{mdframed}

\noindent
{\small
\begin{tabular}{|l|l|l|p{2.2in}|}
\hline
\verb'GrB_Field'                    & R/W  & C type        & description \\
\hline
\verb'GrB_STORAGE_ORIENTATION_HINT' & R    & \verb'int32_t'& See \verb'GrB_Orientation', \newline
                                                             and Section~\ref{storage_orientation}. \\
\verb'GrB_EL_TYPE_CODE'             & R    & \verb'int32_t'& type of matrix in the blob \\
\verb'GxB_SPARSITY_CONTROL'         & R    & \verb'int32_t'& See Section~\ref{sparsity_status} \\
\verb'GxB_SPARSITY_STATUS'          & R    & \verb'int32_t'& See Section~\ref{sparsity_status} \\
\hline
\verb'GrB_NAME'                     & R    & \verb'char *' & name of the matrix in the blob. \\
\verb'GrB_EL_TYPE_STRING'           & R    & \verb'char *' & name of the type of the matrix in the blob. \\
\verb'GxB_JIT_C_NAME'               & R    & \verb'char *' & JIT C name of the type of the matrix in the blob. \\
\hline
\verb'GxB_HYPER_SWITCH'             & R    & \verb'double' & See Section~\ref{hypersparse} \\
\verb'GxB_BITMAP_SWITCH'            & R    & \verb'double' & See Section~\ref{bitmap_switch} \\
\hline
\end{tabular}
}

The \verb'GrB_Matrix_serialize' and \verb'GxB_Matrix_serialize' methods create
a {\em blob} as a single array of bytes that contains all content of a
\verb'GrB_Matrix'.  These \verb'GrB_get' methods can query a blob for the same
values that can be queried for a \verb'GrB_Matrix'.  The blob cannot be
modified by \verb'GrB_set'.

Note that these \verb'GrB_get' methods add a fourth parameter, the size of
the blob.  All other \verb'GrB_get' methods have just three parameters:
the object, the value, and the field.

