1 //------------------------------------------------------------------------------ 2 // GB_AxB_factory: switch factory for C=A*B 3 //------------------------------------------------------------------------------ 4 5 // SuiteSparse:GraphBLAS, Timothy A. Davis, (c) 2017-2021, All Rights Reserved. 6 // SPDX-License-Identifier: Apache-2.0 7 8 //------------------------------------------------------------------------------ 9 10 // This is used by GB_AxB_saxpy3.c and GB_AxB_dot[234].c to create the 11 // built-in versions of sparse matrix-matrix multiplication. The #include'ing 12 // file defines the GB_AxB_WORKER macro, and mult_opcode, add_opcode, xcode, 13 // ycode, and zcode. 14 15 // Three 2nd level switch factories are used: 16 17 // GB_AxB_type_factory: handles all semirings where the multiply operator 18 // is TxT->T (as is the monoid). 19 20 // GB_AxB_compare_factory: handles all semirings where the multiply 21 // operator is TxT -> bool (for the comparison operators, LT, GT, 22 // etc), and where the monoid is bool x bool -> bool. 23 24 // GB_AxB_bitwise_factory: handles all semirings for bitwise operators. 25 26 // GxB_AxB_positional_factory: handles all semirings for positional 27 // multiply operators. Those operators are of the for XxX -> int64, 28 // where "X" denotes any type. No typecasting is needed from the 29 // types of A and B. 30 31 // If the multiplicative operator is ANY, then it has already been renamed to 32 // SECOND, prior to using this factory, since that is faster for the 33 // saxpy-based methods (y is the value of B(k,j), which is loaded less 34 // frequently from memory than A(i,k)). 35 36 ASSERT (mult_opcode != GB_ANY_opcode) ; 37 38 { 39 //-------------------------------------------------------------------------- 40 // launch the switch factory 41 //-------------------------------------------------------------------------- 42 43 switch (mult_opcode) 44 { 45 46 //---------------------------------------------------------------------- 47 case GB_FIRST_opcode : // z = x 48 //---------------------------------------------------------------------- 49 50 // 61 semirings with FIRST: 51 // 50: (min,max,plus,times,any) for 10 non-boolean real 52 // 5: (or,and,xor,eq,any) for boolean 53 // 6: (plus,times,any) for 2 complex 54 #define GB_MNAME _first 55 #define GB_COMPLEX 56 #include "GB_AxB_type_factory.c" 57 break ; 58 59 //---------------------------------------------------------------------- 60 case GB_SECOND_opcode : // z = y 61 //---------------------------------------------------------------------- 62 63 // 61 semirings with SECOND: 64 // 50: (min,max,plus,times,any) for 10 real non-boolean 65 // 5: (or,and,xor,eq,any) for boolean 66 // 6: (plus,times,any) for 2 complex 67 #define GB_MNAME _second 68 #define GB_COMPLEX 69 #include "GB_AxB_type_factory.c" 70 break ; 71 72 //---------------------------------------------------------------------- 73 case GB_PAIR_opcode : // z = 1 74 //---------------------------------------------------------------------- 75 76 // 26 semirings with PAIR: 77 // 20: (plus,any) for 10 real non-boolean 78 // 2: (xor,any) for boolean 79 // 4: (plus,any) for 2 complex 80 // land_pair, lor_pair, max_pair, min_pair, times_pair, eq_pair 81 // all become any_pair. 82 #define GB_MULT_IS_PAIR_OPERATOR 83 #define GB_MNAME _pair 84 #define GB_COMPLEX 85 #include "GB_AxB_type_factory.c" 86 #undef GB_MULT_IS_PAIR_OPERATOR 87 break ; 88 89 //---------------------------------------------------------------------- 90 case GB_MIN_opcode : // z = min(x,y) 91 //---------------------------------------------------------------------- 92 93 // 50 semirings: (min,max,plus,times,any) for 10 real non-boolean 94 // MIN == TIMES == AND for boolean 95 #define GB_NO_BOOLEAN 96 #define GB_MNAME _min 97 #include "GB_AxB_type_factory.c" 98 break ; 99 100 //---------------------------------------------------------------------- 101 case GB_MAX_opcode : // z = max(x,y) 102 //---------------------------------------------------------------------- 103 104 // 50 semirings: (min,max,plus,times,any) for 10 real non-boolean 105 // MAX == PLUS == OR for boolean 106 #define GB_NO_BOOLEAN 107 #define GB_MNAME _max 108 #include "GB_AxB_type_factory.c" 109 break ; 110 111 //---------------------------------------------------------------------- 112 case GB_PLUS_opcode : // z = x + y 113 //---------------------------------------------------------------------- 114 115 // 56 semirings: 116 // 50: (min,max,plus,times,any) for 10 real non-boolean 117 // 6: (plus,times,any) for 2 complex types 118 // MAX == PLUS == OR for boolean 119 #define GB_NO_BOOLEAN 120 #define GB_MNAME _plus 121 #define GB_COMPLEX 122 #include "GB_AxB_type_factory.c" 123 break ; 124 125 //---------------------------------------------------------------------- 126 case GB_MINUS_opcode : // z = x - y 127 //---------------------------------------------------------------------- 128 129 // 56 semirings: 130 // 50 semirings: (min,max,plus,times,any) for 10 real non-boolean 131 // 6: (plus,times,any) for 2 complex types 132 // MINUS == RMINUS == NE == ISNE == XOR for boolean 133 #define GB_NO_BOOLEAN 134 #define GB_MNAME _minus 135 #define GB_COMPLEX 136 #include "GB_AxB_type_factory.c" 137 break ; 138 139 //---------------------------------------------------------------------- 140 case GB_RMINUS_opcode : // z = y - x (reverse minus) 141 //---------------------------------------------------------------------- 142 143 // 56 semirings: 144 // 50 semirings: (min,max,plus,times,any) for 10 real non-boolean 145 // 6: (plus,times,any) for 2 complex types 146 #define GB_NO_BOOLEAN 147 #define GB_MNAME _rminus 148 #define GB_COMPLEX 149 #include "GB_AxB_type_factory.c" 150 break ; 151 152 //---------------------------------------------------------------------- 153 case GB_TIMES_opcode : // z = x * y 154 //---------------------------------------------------------------------- 155 156 // 56 semirings: 157 // 50 semirings: (min,max,plus,times,any) for 10 real non-boolean 158 // 6: (plus,times,any) for 2 complex types 159 #define GB_NO_BOOLEAN 160 #define GB_MNAME _times 161 #define GB_COMPLEX 162 #include "GB_AxB_type_factory.c" 163 break ; 164 165 //---------------------------------------------------------------------- 166 case GB_DIV_opcode : // z = x / y 167 //---------------------------------------------------------------------- 168 169 // 56 semirings: 170 // 50 semirings: (min,max,plus,times,any) for 10 real non-boolean 171 // 6: (plus,times,any) for 2 complex types 172 // FIRST == DIV for boolean 173 #define GB_NO_BOOLEAN 174 #define GB_MNAME _div 175 #define GB_COMPLEX 176 #include "GB_AxB_type_factory.c" 177 break ; 178 179 //---------------------------------------------------------------------- 180 case GB_RDIV_opcode : // z = y / x (reverse division) 181 //---------------------------------------------------------------------- 182 183 // 56 semirings: 184 // 50 semirings: (min,max,plus,times,any) for 10 real non-boolean 185 // 6: (plus,times,any) for 2 complex types 186 // SECOND == RDIV for boolean 187 #define GB_NO_BOOLEAN 188 #define GB_MNAME _rdiv 189 #define GB_COMPLEX 190 #include "GB_AxB_type_factory.c" 191 break ; 192 193 #if 0 194 // in v5.0.1, the *_IS* semirings are completely disabled. 195 196 //---------------------------------------------------------------------- 197 case GB_ISEQ_opcode : // z = (x == y) 198 //---------------------------------------------------------------------- 199 200 // 50 semirings: (min,max,plus,times,any) for 10 real non-boolean 201 // ISEQ == EQ for boolean 202 #define GB_NO_BOOLEAN 203 #define GB_MNAME _iseq 204 #include "GB_AxB_type_factory.c" 205 break ; 206 207 //---------------------------------------------------------------------- 208 case GB_ISNE_opcode : // z = (x != y) 209 //---------------------------------------------------------------------- 210 211 // 50 semirings: (min,max,plus,times,any) for 10 real non-boolean 212 // MINUS == RMINUS == NE == ISNE == XOR for boolean 213 #define GB_NO_BOOLEAN 214 #define GB_MNAME _isne 215 #include "GB_AxB_type_factory.c" 216 break ; 217 218 //---------------------------------------------------------------------- 219 case GB_ISGT_opcode : // z = (x > y) 220 //---------------------------------------------------------------------- 221 222 // 50 semirings: (min,max,plus,times,any) for 10 real non-boolean 223 // ISGT == GT for boolean 224 #define GB_NO_BOOLEAN 225 #define GB_MNAME _isgt 226 #include "GB_AxB_type_factory.c" 227 break ; 228 229 //---------------------------------------------------------------------- 230 case GB_ISLT_opcode : // z = (x < y) 231 //---------------------------------------------------------------------- 232 233 // 50 semirings: (min,max,plus,times,any) for 10 real non-boolean 234 // ISLT == LT for boolean 235 #define GB_NO_BOOLEAN 236 #define GB_MNAME _islt 237 #include "GB_AxB_type_factory.c" 238 break ; 239 240 //---------------------------------------------------------------------- 241 case GB_ISGE_opcode : // z = (x >= y) 242 //---------------------------------------------------------------------- 243 244 // 50 semirings: (min,max,plus,times,any) for 10 real non-boolean 245 // ISGE == GE for boolean 246 #define GB_NO_BOOLEAN 247 #define GB_MNAME _isge 248 #include "GB_AxB_type_factory.c" 249 break ; 250 251 //---------------------------------------------------------------------- 252 case GB_ISLE_opcode : // z = (x <= y) 253 //---------------------------------------------------------------------- 254 255 // 50 semirings: (min,max,plus,times,any) for 10 real non-boolean 256 // ISLE == LE for boolean 257 #define GB_NO_BOOLEAN 258 #define GB_MNAME _isle 259 #include "GB_AxB_type_factory.c" 260 break ; 261 #endif 262 263 //---------------------------------------------------------------------- 264 case GB_EQ_opcode : // z = (x == y) 265 //---------------------------------------------------------------------- 266 267 // 55 semirings: (and,or,xor,eq,any) * 11 types (all but complex) 268 #define GB_MNAME _eq 269 #include "GB_AxB_compare_factory.c" 270 break ; 271 272 //---------------------------------------------------------------------- 273 case GB_NE_opcode : // z = (x != y) 274 //---------------------------------------------------------------------- 275 276 // 50 semirings: (and,or,xor,eq,any) * (10 real non-boolean types) 277 // MINUS == RMINUS == NE == ISNE == XOR for boolean 278 #define GB_NO_BOOLEAN 279 #define GB_MNAME _ne 280 #include "GB_AxB_compare_factory.c" 281 break ; 282 283 //---------------------------------------------------------------------- 284 case GB_GT_opcode : // z = (x > y) 285 //---------------------------------------------------------------------- 286 287 // 55 semirings: (and,or,xor,eq,any) * 11 types (all but complex) 288 #define GB_MNAME _gt 289 #include "GB_AxB_compare_factory.c" 290 break ; 291 292 //---------------------------------------------------------------------- 293 case GB_LT_opcode : // z = (x < y) 294 //---------------------------------------------------------------------- 295 296 // 55 semirings: (and,or,xor,eq,any) * 11 types (all but complex) 297 #define GB_MNAME _lt 298 #include "GB_AxB_compare_factory.c" 299 break ; 300 301 //---------------------------------------------------------------------- 302 case GB_GE_opcode : // z = (x >= y) 303 //---------------------------------------------------------------------- 304 305 // 55 semirings: (and,or,xor,eq,any) * 11 types (all but complex) 306 #define GB_MNAME _ge 307 #include "GB_AxB_compare_factory.c" 308 break ; 309 310 //---------------------------------------------------------------------- 311 case GB_LE_opcode : // z = (x <= y) 312 //---------------------------------------------------------------------- 313 314 // 55 semirings: (and,or,xor,eq,any) * 11 types (all but complex) 315 #define GB_MNAME _le 316 #include "GB_AxB_compare_factory.c" 317 break ; 318 319 //---------------------------------------------------------------------- 320 case GB_LOR_opcode : // z = x || y 321 //---------------------------------------------------------------------- 322 323 // 14 semirings: 324 // 10 semirings: plus_lor for 10 real non-boolean types 325 // 4 semirings: (lor,land,eq,lxor) for boolean 326 #define GB_NO_MIN_MAX_ANY_TIMES_MONOIDS 327 #define GB_MNAME _lor 328 #include "GB_AxB_type_factory.c" 329 break ; 330 331 //---------------------------------------------------------------------- 332 case GB_LAND_opcode : // z = x && y 333 //---------------------------------------------------------------------- 334 335 // 14 semirings: same as LOR 336 #define GB_MNAME _land 337 #include "GB_AxB_type_factory.c" 338 break ; 339 340 //---------------------------------------------------------------------- 341 case GB_LXOR_opcode : // z = x != y 342 //---------------------------------------------------------------------- 343 344 // 14 semirings: same as LOR 345 #define GB_MNAME _lxor 346 #include "GB_AxB_type_factory.c" 347 #define GB_NO_MIN_MAX_TIMES_MONOIDS 348 break ; 349 350 //---------------------------------------------------------------------- 351 case GB_BOR_opcode : // z = (x | y), bitwise or 352 //---------------------------------------------------------------------- 353 354 // 16 semirings: (bor,band,bxor,bxnor) * (uint8,16,32,64) 355 #define GB_MNAME _bor 356 #include "GB_AxB_bitwise_factory.c" 357 break ; 358 359 //---------------------------------------------------------------------- 360 case GB_BAND_opcode : // z = (x & y), bitwise and 361 //---------------------------------------------------------------------- 362 363 // 16 semirings: (bor,band,bxor,bxnor) * (uint8,16,32,64) 364 #define GB_MNAME _band 365 #include "GB_AxB_bitwise_factory.c" 366 break ; 367 368 //---------------------------------------------------------------------- 369 case GB_BXOR_opcode : // z = (x ^ y), bitwise xor 370 //---------------------------------------------------------------------- 371 372 // 16 semirings: (bor,band,bxor,bxnor) * (uint8,16,32,64) 373 #define GB_MNAME _bxor 374 #include "GB_AxB_bitwise_factory.c" 375 break ; 376 377 //---------------------------------------------------------------------- 378 case GB_BXNOR_opcode : // z = ~(x ^ y), bitwise xnor 379 //---------------------------------------------------------------------- 380 381 // 16 semirings: (bor,band,bxor,bxnor) * (uint8,16,32,64) 382 #define GB_MNAME _bxnor 383 #include "GB_AxB_bitwise_factory.c" 384 break ; 385 386 //---------------------------------------------------------------------- 387 case GB_FIRSTI_opcode : // z = first_i(A(i,k),y) == i 388 //---------------------------------------------------------------------- 389 390 // 10 semirings: (min,max,times,plus,any) * (int32,int64) 391 #define GB_MNAME _firsti 392 #include "GB_AxB_positional_factory.c" 393 break ; 394 395 //---------------------------------------------------------------------- 396 case GB_FIRSTI1_opcode : // z = first_i1(A(i,k),y) == i+1 397 //---------------------------------------------------------------------- 398 399 // 10 semirings: (min,max,times,plus,any) * (int32,int64) 400 #define GB_MNAME _firsti1 401 #include "GB_AxB_positional_factory.c" 402 break ; 403 404 //---------------------------------------------------------------------- 405 case GB_FIRSTJ_opcode : // z = first_j(A(i,k),y) == k 406 case GB_SECONDI_opcode : // z = second_i(x,B(k,j)) == k 407 //---------------------------------------------------------------------- 408 409 // 10 semirings: (min,max,times,plus,any) * (int32,int64) 410 // FIRSTJ and SECONDI are identical when used in a semiring 411 #define GB_MNAME _firstj 412 #include "GB_AxB_positional_factory.c" 413 break ; 414 415 //---------------------------------------------------------------------- 416 case GB_FIRSTJ1_opcode : // z = first_j1(A(i,k),y) == k+1 417 case GB_SECONDI1_opcode : // z = second_i1(x,B(k,j)) == k+1 418 //---------------------------------------------------------------------- 419 420 // 10 semirings: (min,max,times,plus,any) * (int32,int64) 421 // FIRSTJ1 and SECONDI1 are identical when used in a semiring 422 #define GB_MNAME _firstj1 423 #include "GB_AxB_positional_factory.c" 424 break ; 425 426 //---------------------------------------------------------------------- 427 case GB_SECONDJ_opcode : // z = second_j(x,B(i,j)) == j 428 //---------------------------------------------------------------------- 429 430 // 10 semirings: (min,max,times,plus,any) * (int32,int64) 431 #define GB_MNAME _secondj 432 #include "GB_AxB_positional_factory.c" 433 break ; 434 435 //---------------------------------------------------------------------- 436 case GB_SECONDJ1_opcode : // z = second_j1(x,B(i,j)) == j+1 437 //---------------------------------------------------------------------- 438 439 // 10 semirings: (min,max,times,plus,any) * (int32,int64) 440 #define GB_MNAME _secondj1 441 #include "GB_AxB_positional_factory.c" 442 break ; 443 444 default: ; 445 } 446 } 447 448