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