1function [opname optype ztype xtype ytype] = GB_spec_operator (op,optype_default) 2%GB_SPEC_OPERATOR get the contents of an operator 3% 4% On input, op can be a struct with a string op.opname that gives the operator 5% name, and a string op.optype with the operator type. Alternatively, op can 6% be a string with the operator name, in which case the operator type is given 7% by optype_default. 8% 9% ztype, xtype, and ytype are the types of z, x, and y for z = f(x,y), if 10% f is a binary operator, or z = f(x) if f is a unary operator. 11 12% SuiteSparse:GraphBLAS, Timothy A. Davis, (c) 2017-2021, All Rights Reserved. 13% SPDX-License-Identifier: Apache-2.0 14 15if (isempty (op)) 16 % No operator has been defined; return an empty operator. GB_spec_accum 17 % uses this condition just like the (accum == NULL) condition in the C 18 % version of GraphBLAS. It means C<Mask>=T is to be done instead of 19 % C<Mask>=accum(C,T). 20 opname = '' ; 21 optype = '' ; 22 xtype = '' ; 23 ytype = '' ; 24 ztype = '' ; 25 return 26elseif (isstruct (op)) 27 % op is a struct with opname and optype 28 opname = op.opname ; 29 optype = op.optype ; 30else 31 % op is a string 32 opname = op ; 33 if (nargin == 1 && GB_spec_is_positional (opname)) 34 % optype_default is ignored 35 optype = 'int64' ; 36 else 37 optype = optype_default ; 38 end 39end 40 41% xtype is always the optype 42xtype = optype ; 43 44% for binary ops: ytype is usually the optype, except for bitshift. 45% for unary ops: ytype is 'none'. 46ytype = optype ; 47 48% ztype is usually the optype, except for the cases below 49ztype = optype ; 50 51is_float = contains (optype, 'single') || contains (optype, 'double') ; 52is_complex = contains (optype, 'complex') ; 53is_int = contains (optype, 'int') ; % int or uint 54is_logical = isequal (optype, 'logical') ; 55is_real_float = is_float && ~is_complex ; 56 57%------------------------------------------------------------------------------- 58% boolean rename: 59%------------------------------------------------------------------------------- 60 61if (is_logical) 62 63 switch (opname) 64 65 case { 'div' } 66 opname = 'first' ; 67 68 case { 'rdiv' } 69 opname = 'second' ; 70 71 case { 'min', 'times' } 72 opname = 'and' ; 73 74 case { 'max', 'plus' } 75 opname = 'or' ; 76 77 case { 'minus', 'rminus', 'isne', 'ne' } 78 opname = 'xor' ; 79 80 case { 'iseq' } 81 opname = 'eq' ; 82 83 case { 'isgt' } 84 opname = 'gt' ; 85 86 case { 'islt' } 87 opname = 'lt' ; 88 89 case { 'isge', 'pow' } 90 opname = 'ge' ; 91 92 case { 'isle' } 93 opname = 'le' ; 94 95 otherwise 96 % op not renamed 97 end 98end 99 100%------------------------------------------------------------------------------- 101% get the x,y,z types of the operator and check if valid 102%------------------------------------------------------------------------------- 103 104switch opname 105 106 %-------------------------------------------------------------------------- 107 % binary ops for all 13 types 108 %-------------------------------------------------------------------------- 109 110 case { 'first', 'second', 'pow', 'plus', 'minus', 'times', 'div', ... 111 'rminus', 'rdiv', 'pair', 'any', 'iseq', 'isne' } 112 % x,y,z types are all the same. 113 114 case { 'eq', 'ne' } 115 % x,y types the the same, z is logical 116 ztype = 'logical' ; 117 118 %-------------------------------------------------------------------------- 119 % binary ops for 11 types (all but complex) 120 %-------------------------------------------------------------------------- 121 122 case { 'max', 'min', 'isgt', 'islt', 'isge', 'isle', 'or', 'and', 'xor' } 123 % x,y,z types are all the same. 124 % available for 11 real types, not complex 125 if (is_complex) 126 error ('invalid op') ; 127 end 128 129 case { 'gt', 'lt', 'ge', 'le' } 130 % x,y types the the same, z is logical 131 % available for 11 real types, not complex 132 ztype = 'logical' ; 133 if (is_complex) 134 error ('invalid op') ; 135 end 136 137 %-------------------------------------------------------------------------- 138 % binary ops for real floating point 139 %-------------------------------------------------------------------------- 140 141 case { 'atan2', 'hypot', 'fmod', 'remainder', 'ldexp', 'copysign' } 142 % x,y,z types are all the same. 143 % available for real float and double only 144 if (~is_real_float) 145 error ('invalid op') ; 146 end 147 148 case { 'cmplx', 'complex' } 149 % x and y are real (float or double). z is the corresponding complex 150 if (~is_real_float) 151 error ('invalid op') ; 152 elseif (isequal (optype, 'single')) 153 ztype = 'single complex' ; 154 else 155 ztype = 'double complex' ; 156 end 157 opname = 'cmplx' ; 158 159 %-------------------------------------------------------------------------- 160 % binary ops for integer only 161 %-------------------------------------------------------------------------- 162 163 case { 'bitor', 'bitand', 'bitxor', 'bitxnor', ... 164 'bitget', 'bitset', 'bitclr', ... 165 'bor', 'band', 'bxor', 'bxnor', ... 166 'bget', 'bset', 'bclr' } 167 168 % x,y,z types are all the same. 169 % available for int and uint only 170 if (~(is_int)) 171 error ('invalid op') ; 172 end 173 174 switch (opname) 175 case { 'bitor', 'bor' } 176 opname = 'bor' ; 177 case { 'bitand', 'band' } 178 opname = 'band' ; 179 case { 'bitxor', 'bxor' } 180 opname = 'bxor' ; 181 case { 'bitxnor', 'bxnor' } 182 opname = 'bxnor' ; 183 case { 'bitget', 'bget' } 184 opname = 'bget' ; 185 case { 'bitset', 'bset' } 186 opname = 'bset' ; 187 case { 'bitclr', 'bclr' } 188 opname = 'bclr' ; 189 end 190 191 case { 'bitshift' , 'bshift' } 192 % x,z types are the same. y is int8 193 % available for int and uint only 194 ytype = 'int8' ; 195 if (~(is_int)) 196 error ('invalid op') ; 197 end 198 199 %-------------------------------------------------------------------------- 200 % unary ops for all 13 types 201 %-------------------------------------------------------------------------- 202 203 case { 'identity', 'one', 'ainv', 'minv' } 204 % x,y,z types are all the same. 205 206 case { 'abs' } 207 % x,y the same. z is the same as x, except if x is complex 208 if (isequal (optype, 'single complex')) 209 ztype = 'single' ; 210 elseif (isequal (optype, 'double complex')) 211 ztype = 'double' ; 212 else 213 ztype = xtype ; 214 end 215 216 %-------------------------------------------------------------------------- 217 % unary ops for 11 real types 218 %-------------------------------------------------------------------------- 219 220 case { 'not' } 221 % x and z have the same type 222 if (is_complex) 223 error ('invalid op') ; 224 end 225 ytype = 'none' ; 226 227 %-------------------------------------------------------------------------- 228 % unary ops for integer only 229 %-------------------------------------------------------------------------- 230 231 case { 'bitnot', 'bnot', 'bitcmp', 'bcmp' } 232 % x and z have the same type 233 if (~is_int) 234 error ('invalid op') ; 235 end 236 ytype = 'none' ; 237 opname = 'bnot' ; 238 239 %-------------------------------------------------------------------------- 240 % unary ops for floating-point only (both real and complex) 241 %-------------------------------------------------------------------------- 242 243 case { 'sqrt', 'log', 'exp', 'log2', ... 244 'sin', 'cos', 'tan', ... 245 'acos', 'asin', 'atan', ... 246 'sinh', 'cosh', 'tanh', ... 247 'acosh', 'asinh', 'atanh', ... 248 'ceil', 'floor', 'round', 'trunc', ... 249 'exp2', 'expm1', 'log10', 'log1p', ... 250 'signum' } 251 % x and z have the same type 252 if (~is_float) 253 error ('invalid op') ; 254 end 255 ytype = 'none' ; 256 257 case { 'isinf', 'isnan', 'isfinite' } 258 % z is logical 259 ztype = 'logical' ; 260 if (~is_float) 261 error ('invalid op') ; 262 end 263 ytype = 'none' ; 264 265 %-------------------------------------------------------------------------- 266 % unary ops for real floating-point only 267 %-------------------------------------------------------------------------- 268 269 case { 'lgamma', 'tgamma', 'erf', 'erfc', 'frexpx', 'frexpe' } 270 % x and z have the same type 271 if (~is_real_float) 272 error ('invalid op') ; 273 end 274 ytype = 'none' ; 275 276 %-------------------------------------------------------------------------- 277 % unary ops for complex only 278 %-------------------------------------------------------------------------- 279 280 case { 'conj' } 281 if (~is_complex) 282 error ('invalid op') ; 283 end 284 ytype = 'none' ; 285 286 case { 'real', 'imag', 'carg' } 287 if (~is_complex) 288 error ('invalid op') ; 289 end 290 if (isequal (optype, 'single complex')) 291 ztype = 'single' ; 292 else 293 ztype = 'double' ; 294 end 295 ytype = 'none' ; 296 297 %-------------------------------------------------------------------------- 298 % binary positional ops 299 %-------------------------------------------------------------------------- 300 301 case { 'firsti' , 'firsti1' , 'firstj' , 'firstj1', ... 302 'secondi', 'secondi1', 'secondj', 'secondj1' } ; 303 if (~(isequal (ztype, 'int64') || isequal (ztype, 'int32'))) 304 error ('invalid op') ; 305 end 306 xtype = optype ; 307 ytype = optype ; 308 309 %-------------------------------------------------------------------------- 310 % unary positional ops 311 %-------------------------------------------------------------------------- 312 313 case { 'positioni', 'positioni1', 'positionj', 'positionj1' } 314 if (~(isequal (ztype, 'int64') || isequal (ztype, 'int32'))) 315 error ('invalid op') ; 316 end 317 ytype = optype ; 318 319 otherwise 320 error ('unknown op') ; 321 322end 323 324