1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368
|
\newpage
%===============================================================================
\subsection{GraphBLAS unary operators: {\sf GrB\_UnaryOp}, $z=f(x)$} %==========
%===============================================================================
\label{unaryop}
A unary operator is a scalar function of the form $z=f(x)$. The domain (type)
of $z$ and $x$ need not be the same.
In the notation in the tables
below, $T$ is any of the 13 built-in types and is a place-holder for
\verb'BOOL', \verb'INT8', \verb'UINT8', ...
\verb'FP32', \verb'FP64', \verb'FC32', or \verb'FC64'.
For example, \verb'GrB_AINV_INT32' is a unary operator that computes
\verb'z=-x' for two values \verb'x' and \verb'z' of type \verb'GrB_INT32'.
The notation $R$ refers to any real type (all but \verb'FC32' and \verb'FC64'),
$I$ refers to any integer type (\verb'INT*' and \verb'UINT*'),
$F$ refers to any real or complex floating point type
(\verb'FP32', \verb'FP64', \verb'FC32', or \verb'FC64'),
$Z$ refers to any complex floating point type
(\verb'FC32' or \verb'FC64'),
and $N$ refers to \verb'INT32' or \verb'INT64'.
The logical negation operator \verb'GrB_LNOT' only works on Boolean types. The
\verb'GxB_LNOT_'$R$ functions operate on inputs of type $R$, implicitly
typecasting their input to Boolean and returning result of type $R$, with a
value 1 for true and 0 for false. The operators \verb'GxB_LNOT_BOOL' and
\verb'GrB_LNOT' are identical.
\vspace{0.2in}
{\footnotesize
\begin{tabular}{|llll|}
\hline
\multicolumn{4}{|c|}{Unary operators for all types} \\
\hline
GraphBLAS name & types (domains) & $z=f(x)$ & description \\
\hline
\verb'GxB_ONE_'$T$ & $T \rightarrow T$ & $z = 1$ & one \\
\verb'GrB_IDENTITY_'$T$ & $T \rightarrow T$ & $z = x$ & identity \\
\verb'GrB_AINV_'$T$ & $T \rightarrow T$ & $z = -x$ & additive inverse \\
\verb'GrB_MINV_'$T$ & $T \rightarrow T$ & $z = 1/x$ & multiplicative inverse \\
\hline
\end{tabular}
\vspace{0.2in}
\begin{tabular}{|llll|}
\hline
\multicolumn{4}{|c|}{Unary operators for real and integer types} \\
\hline
GraphBLAS name & types (domains) & $z=f(x)$ & description \\
\hline
\verb'GrB_ABS_'$T$ & $R \rightarrow R$ & $z = |x|$ & absolute value \\
\verb'GrB_LNOT' & \verb'bool'
$\rightarrow$
\verb'bool' & $z = \lnot x$ & logical negation \\
\verb'GxB_LNOT_'$R$ & $R \rightarrow R$ & $z = \lnot (x \ne 0)$ & logical negation \\
\verb'GrB_BNOT_'$I$ & $I \rightarrow I$ & $z = \lnot x$ & bitwise negation \\
\hline
\end{tabular}
\vspace{0.2in}
\begin{tabular}{|llll|}
\hline
\multicolumn{4}{|c|}{Index-based unary operators for any type (including user-defined)} \\
\hline
GraphBLAS name & types (domains) & $z=f(a_{ij})$ & description \\
\hline
\verb'GxB_POSITIONI_'$N$ & $ \rightarrow N$ & $z = i$ & row index (0-based) \\
\verb'GxB_POSITIONI1_'$N$ & $ \rightarrow N$ & $z = i+1$ & row index (1-based) \\
\verb'GxB_POSITIONJ_'$N$ & $ \rightarrow N$ & $z = j$ & column index (0-based) \\
\verb'GxB_POSITIONJ1_'$N$ & $ \rightarrow N$ & $z = j+1$ & column index (1-based) \\
\hline
\end{tabular}
\vspace{0.2in}
\begin{tabular}{|llll|}
\hline
\multicolumn{4}{|c|}{Unary operators for floating-point types (real and complex)} \\
\hline
GraphBLAS name & types (domains) & $z=f(x)$ & description \\
\hline
\verb'GxB_SQRT_'$F$ & $F \rightarrow F$ & $z = \sqrt(x)$ & square root \\
\verb'GxB_LOG_'$F$ & $F \rightarrow F$ & $z = \log_e(x)$ & natural logarithm \\
\verb'GxB_EXP_'$F$ & $F \rightarrow F$ & $z = e^x$ & natural exponent \\
\hline
\verb'GxB_LOG10_'$F$ & $F \rightarrow F$ & $z = \log_{10}(x)$ & base-10 logarithm \\
\verb'GxB_LOG2_'$F$ & $F \rightarrow F$ & $z = \log_2(x)$ & base-2 logarithm \\
\verb'GxB_EXP2_'$F$ & $F \rightarrow F$ & $z = 2^x$ & base-2 exponent \\
\hline
\verb'GxB_EXPM1_'$F$ & $F \rightarrow F$ & $z = e^x - 1$ & natural exponent - 1 \\
\verb'GxB_LOG1P_'$F$ & $F \rightarrow F$ & $z = \log(x+1)$ & natural log of $x+1$ \\
\hline
\verb'GxB_SIN_'$F$ & $F \rightarrow F$ & $z = \sin(x)$ & sine \\
\verb'GxB_COS_'$F$ & $F \rightarrow F$ & $z = \cos(x)$ & cosine \\
\verb'GxB_TAN_'$F$ & $F \rightarrow F$ & $z = \tan(x)$ & tangent \\
\hline
\verb'GxB_ASIN_'$F$ & $F \rightarrow F$ & $z = \sin^{-1}(x)$ & inverse sine \\
\verb'GxB_ACOS_'$F$ & $F \rightarrow F$ & $z = \cos^{-1}(x)$ & inverse cosine \\
\verb'GxB_ATAN_'$F$ & $F \rightarrow F$ & $z = \tan^{-1}(x)$ & inverse tangent \\
\hline
\verb'GxB_SINH_'$F$ & $F \rightarrow F$ & $z = \sinh(x)$ & hyperbolic sine \\
\verb'GxB_COSH_'$F$ & $F \rightarrow F$ & $z = \cosh(x)$ & hyperbolic cosine \\
\verb'GxB_TANH_'$F$ & $F \rightarrow F$ & $z = \tanh(x)$ & hyperbolic tangent \\
\hline
\verb'GxB_ASINH_'$F$ & $F \rightarrow F$ & $z = \sinh^{-1}(x)$ & inverse hyperbolic sine \\
\verb'GxB_ACOSH_'$F$ & $F \rightarrow F$ & $z = \cosh^{-1}(x)$ & inverse hyperbolic cosine \\
\verb'GxB_ATANH_'$F$ & $F \rightarrow F$ & $z = \tanh^{-1}(x)$ & inverse hyperbolic tangent \\
\hline
\verb'GxB_SIGNUM_'$F$ & $F \rightarrow F$ & $z = \sgn(x)$ & sign, or signum function \\
\verb'GxB_CEIL_'$F$ & $F \rightarrow F$ & $z = \lceil x \rceil $ & ceiling function \\
\verb'GxB_FLOOR_'$F$ & $F \rightarrow F$ & $z = \lfloor x \rfloor $ & floor function \\
\verb'GxB_ROUND_'$F$ & $F \rightarrow F$ & $z = \mbox{round}(x)$ & round to nearest \\
\verb'GxB_TRUNC_'$F$ & $F \rightarrow F$ & $z = \mbox{trunc}(x)$ & round towards zero \\
\hline
\verb'GxB_ISINF_'$F$ & $F \rightarrow $ \verb'bool' & $z = \mbox{isinf}(x)$ & true if $\pm \infty$ \\
\verb'GxB_ISNAN_'$F$ & $F \rightarrow $ \verb'bool' & $z = \mbox{isnan}(x)$ & true if \verb'NaN' \\
\verb'GxB_ISFINITE_'$F$ & $F \rightarrow $ \verb'bool' & $z = \mbox{isfinite}(x)$ & true if finite \\
\hline
\end{tabular}
\vspace{0.2in}
\begin{tabular}{|llll|}
\hline
\multicolumn{4}{|c|}{Unary operators for floating-point types (real only)} \\
\hline
GraphBLAS name & types (domains) & $z=f(x)$ & description \\
\hline
\verb'GxB_LGAMMA_'$R$ & $R \rightarrow R$ & $z = \log(|\Gamma (x)|)$ & log of gamma function \\
\verb'GxB_TGAMMA_'$R$ & $R \rightarrow R$ & $z = \Gamma(x)$ & gamma function \\
\verb'GxB_ERF_'$R$ & $R \rightarrow R$ & $z = \erf(x)$ & error function \\
\verb'GxB_ERFC_'$R$ & $R \rightarrow R$ & $z = \erfc(x)$ & complimentary error function \\
\verb'GxB_CBRT_'$R$ & $R \rightarrow R$ & $z = x^{1/3}$ & cube root \\
\hline
\verb'GxB_FREXPX_'$R$ & $R \rightarrow R$ & $z = \mbox{frexpx}(x)$ & normalized fraction \\
\verb'GxB_FREXPE_'$R$ & $R \rightarrow R$ & $z = \mbox{frexpe}(x)$ & normalized exponent \\
\hline
\end{tabular}
\vspace{0.2in}
\begin{tabular}{|llll|}
\hline
\multicolumn{4}{|c|}{Unary operators for complex types} \\
\hline
GraphBLAS name & types (domains) & $z=f(x)$ & description \\
\hline
\verb'GxB_CONJ_'$Z$ & $Z \rightarrow Z$ & $z = \overline{x}$ & complex conjugate \\
\verb'GxB_ABS_'$Z$ & $Z \rightarrow F$ & $z = |x|$ & absolute value \\
\verb'GxB_CREAL_'$Z$ & $Z \rightarrow F$ & $z = \mbox{real}(x)$ & real part \\
\verb'GxB_CIMAG_'$Z$ & $Z \rightarrow F$ & $z = \mbox{imag}(x)$ & imaginary part \\
\verb'GxB_CARG_'$Z$ & $Z \rightarrow F$ & $z = \mbox{carg}(x)$ & angle \\
\hline
\end{tabular}
}
\vspace{0.2in}
Built-in index-based unary operators return the row or column index of an entry. For a
matrix $z=f(a_{ij})$ returns $z = i$ or $z = j$, or +1 for 1-based indices.
The latter is useful in the MATLAB/Octave interface, where row and column indices are
1-based. When applied to a vector, $j$ is always zero, and $i$ is the index in
the vector. These built-in unary operators come in two types: \verb'INT32' and
\verb'INT64', which is the type of the output, $z$. The functions are agnostic
to the type of their inputs; they only depend on the position of the entries,
not their values.
User-defined index-based operators cannot be defined by \verb'GrB_UnaryOp_new';
use \verb'GrB_IndexUnaryOp_new' instead; see Section~\ref{idxunop}.
\verb'GxB_FREXPX' and \verb'GxB_FREXPE' return the mantissa and exponent,
respectively, from the C11 \verb'frexp' function. The exponent is
returned as a floating-point value, not an integer.
The operators \verb'GxB_EXPM1_FC*' and \verb'GxB_LOG1P_FC*' for complex
types are currently not accurate. They will be revised in a future version.
The functions \verb'casin', \verb'casinf', \verb'casinh', and \verb'casinhf'
provided by Microsoft Visual Studio for computing $\sin^{-1}(x)$ and
$\sinh^{-1}(x)$ when $x$ is complex do not compute the correct result. Thus,
the unary operators \verb'GxB_ASIN_FC32', \verb'GxB_ASIN_FC64'
\verb'GxB_ASINH_FC32', and \verb'GxB_ASINH_FC64' do not work properly if the MS
Visual Studio compiler is used. These functions work properly if the gcc, icc,
or clang compilers are used on Linux or MacOS.
Integer division by zero normally terminates an application, but this is
avoided in SuiteSparse:GraphBLAS. For details, see the binary
\verb'GrB_DIV_'$T$ operators.
\begin{alert}
{\bf SPEC:} The definition of integer division by zero is an extension to the
specification.
\end{alert}
The next sections define the following methods for the \verb'GrB_UnaryOp'
object:
\vspace{0.1in}
{\footnotesize
\noindent
\begin{tabular}{lll}
\hline
GraphBLAS function & purpose & Section \\
\hline
\verb'GrB_UnaryOp_new' & create a user-defined unary operator & \ref{unaryop_new} \\
\verb'GxB_UnaryOp_new' & create a named user-defined unary operator & \ref{unaryop_new_named} \\
\verb'GrB_UnaryOp_wait' & wait for a user-defined unary operator & \ref{unaryop_wait} \\
\verb'GrB_UnaryOp_free' & free a user-defined unary operator & \ref{unaryop_free} \\
\verb'GrB_get' & get properties of an operator & \ref{get_set_unop} \\
\verb'GrB_set' & set the operator name/definition & \ref{get_set_unop} \\
\hline
\end{tabular}
}
\vspace{0.1in}
% \newpage
%-------------------------------------------------------------------------------
\subsubsection{{\sf GrB\_UnaryOp\_new:} create a user-defined unary operator}
%-------------------------------------------------------------------------------
\label{unaryop_new}
\begin{mdframed}[userdefinedwidth=6in]
{\footnotesize
\begin{verbatim}
GrB_Info GrB_UnaryOp_new // create a new user-defined unary operator
(
GrB_UnaryOp *unaryop, // handle for the new unary operator
void *function, // pointer to the unary function
GrB_Type ztype, // type of output z
GrB_Type xtype // type of input x
) ;
\end{verbatim} }\end{mdframed}
\verb'GrB_UnaryOp_new' creates a new unary operator. The new operator is
returned in the \verb'unaryop' handle, which must not be \verb'NULL' on input.
On output, its contents contains a pointer to the new unary operator.
The two types \verb'xtype' and \verb'ztype' are the GraphBLAS types of the
input $x$ and output $z$ of the user-defined function $z=f(x)$. These types
may be built-in types or user-defined types, in any combination. The two types
need not be the same, but they must be previously defined before passing them
to \verb'GrB_UnaryOp_new'.
The \verb'function' argument to \verb'GrB_UnaryOp_new' is a pointer to a
user-defined function with the following signature:
{\footnotesize
\begin{verbatim}
void (*f) (void *z, const void *x) ; \end{verbatim} }
When the function \verb'f' is called, the arguments \verb'z' and \verb'x' are
passed as \verb'(void *)' pointers, but they will be pointers to values of the
correct type, defined by \verb'ztype' and \verb'xtype', respectively, when the
operator was created.
{\bf NOTE:}
The pointers passed to a user-defined operator may not be unique. That is, the
user function may be called with multiple pointers that point to the same
space, such as when \verb'z=f(z,y)' is to be computed by a binary operator, or
\verb'z=f(z)' for a unary operator. Any parameters passed to the user-callable
function may be aliased to each other.
\newpage
%-------------------------------------------------------------------------------
\subsubsection{{\sf GxB\_UnaryOp\_new:} create a named user-defined unary operator}
%-------------------------------------------------------------------------------
\label{unaryop_new_named}
\begin{mdframed}[userdefinedwidth=6in]
{\footnotesize
\begin{verbatim}
GrB_Info GxB_UnaryOp_new // create a new user-defined unary operator
(
GrB_UnaryOp *unaryop, // handle for the new unary operator
GxB_unary_function function, // pointer to the unary function
GrB_Type ztype, // type of output z
GrB_Type xtype, // type of input x
const char *unop_name, // name of the user function
const char *unop_defn // definition of the user function
) ;
\end{verbatim} }\end{mdframed}
Creates a named \verb'GrB_UnaryOp'. Only the first 127 characters of
\verb'unop_name' are used. The \verb'unop_defn' is a string containing the
entire function itself. For example:
{\footnotesize
\begin{verbatim}
void square (double *z, double *x) { (*z) = (*x) * (*x) ; } ;
...
GrB_Type Square ;
GxB_UnaryOp_new (&Square, square, GrB_FP64, GrB_FP64, "square",
"void square (double *z, double *x) { (*z) = (*x) * (*x) ; } ;") ;
\end{verbatim}}
The two strings \verb'unop_name' and \verb'unop_defn' are optional, but are
required to enable the JIT compilation of kernels that use this operator.
If JIT compilation is enabled, or if the corresponding JIT kernel has been
copied into the \verb'PreJIT' folder, the \verb'function' may be \verb'NULL'.
In this case, a JIT kernel is compiled that contains just the user-defined
function. If the JIT is disabled and the \verb'function' is \verb'NULL', this
method returns \verb'GrB_NULL_POINTER'.
The above example is identical to the following usage, except that
\verb'GrB_UnaryOp_new' requires a non-NULL function pointer.
{\footnotesize
\begin{verbatim}
void square (double *z, double *x) { (*z) = (*x) * (*x) ; } ;
...
GrB_Type Square ;
GrB_UnaryOp_new (&Square, square, GrB_FP64, GrB_FP64) ;
GrB_set (Square, "square", GxB_JIT_C_NAME) ;
GrB_set (Square, "void square (double *z, double *x) { (*z) = (*x) * (*x) ; } ;",
GxB_JIT_C_DEFINITION) ; \end{verbatim}}
% \newpage
%-------------------------------------------------------------------------------
\subsubsection{{\sf GrB\_UnaryOp\_wait:} wait for a unary operator}
%-------------------------------------------------------------------------------
\label{unaryop_wait}
\begin{mdframed}[userdefinedwidth=6in]
{\footnotesize
\begin{verbatim}
GrB_Info GrB_wait // wait for a user-defined unary operator
(
GrB_UnaryOp unaryop, // unary operator to wait for
int mode // GrB_COMPLETE or GrB_MATERIALIZE
) ;
\end{verbatim}
}\end{mdframed}
After creating a user-defined unary operator, a GraphBLAS library may choose to
exploit non-blocking mode to delay its creation. Currently,
SuiteSparse:GraphBLAS currently does nothing except to ensure that the
\verb'unaryop' is valid.
% \newpage
%-------------------------------------------------------------------------------
\subsubsection{{\sf GrB\_UnaryOp\_free:} free a user-defined unary operator}
%-------------------------------------------------------------------------------
\label{unaryop_free}
\begin{mdframed}[userdefinedwidth=6in]
{\footnotesize
\begin{verbatim}
GrB_Info GrB_free // free a user-created unary operator
(
GrB_UnaryOp *unaryop // handle of unary operator to free
) ;
\end{verbatim}
}\end{mdframed}
\verb'GrB_UnaryOp_free' frees a user-defined unary operator.
Either usage:
{\small
\begin{verbatim}
GrB_UnaryOp_free (&unaryop) ;
GrB_free (&unaryop) ; \end{verbatim}}
\noindent
frees the \verb'unaryop' and sets \verb'unaryop' to \verb'NULL'.
It safely does nothing if passed a \verb'NULL'
handle, or if \verb'unaryop == NULL' on input.
It does nothing at all if passed a built-in unary operator.
|