1 //------------------------------------------------------------------------------
2 // GB_stringify_binop: convert a binary op into a string or enum
3 //------------------------------------------------------------------------------
4 
5 // SuiteSparse:GraphBLAS, Timothy A. Davis, (c) 2021, All Rights Reserved.
6 // SPDX-License-Identifier: Apache-2.0
7 
8 //------------------------------------------------------------------------------
9 
10 // The binop macro generates an expression, not a full statement.  There
11 // is no semicolon or assignment.  For example:
12 
13 // #define GB_MULT(x,y) ((x) * (y))
14 
15 #include "GB.h"
16 #include "GB_stringify.h"
17 
18 //------------------------------------------------------------------------------
19 // GB_stringify_binop: construct the binop macro
20 //------------------------------------------------------------------------------
21 
GB_stringify_binop(char * binop_macro,const char * macro_name,GB_Opcode opcode,GB_Type_code xcode,bool for_semiring,bool flipxy)22 void GB_stringify_binop
23 (
24     // output:
25     char *binop_macro,  // string with the #define macro
26     // input:
27     const char *macro_name,   // name of macro to construct
28     GB_Opcode opcode,   // opcode of GraphBLAS operator to convert into a macro
29     GB_Type_code xcode, // op->xtype->code of the operator
30     bool for_semiring,  // if true: op is a multiplier in a semiring
31     bool flipxy         // if true, use mult(y,x) else mult(x,y)
32 )
33 {
34 
35     const char *op_string ;
36     int ecode ;
37 
38     // get ecode from opcode, xcode, and for_semiring
39     GB_enumify_binop (&ecode, opcode, xcode, for_semiring) ;
40 
41     // convert ecode to string
42     GB_charify_binop (&op_string, ecode) ;
43 
44     // convert string to macro
45     GB_macrofy_binop (binop_macro, macro_name, op_string, flipxy) ;
46 }
47 
48 //------------------------------------------------------------------------------
49 // GB_enumify_binop: convert binary opcode and xcode into a single enum
50 //------------------------------------------------------------------------------
51 
52 // ecodes 0 to 31 can be used as a monoid, but only 0:22 are currently in use.
53 // ecodes 32 and up are not valid for use in a monoid; only 32:139 are in use.
54 
GB_enumify_binop(int * ecode,GB_Opcode opcode,GB_Type_code xcode,bool for_semiring)55 void GB_enumify_binop
56 (
57     // output:
58     int *ecode,         // enumerated operator, range 0 to 139; -1 on failure
59     // input:
60     GB_Opcode opcode,   // opcode of GraphBLAS operator to convert into a macro
61     GB_Type_code xcode, // op->xtype->code of the operator
62     bool for_semiring   // true for A*B, false for A+B or A.*B
63 )
64 {
65 
66     int e = -1 ;
67 
68     switch (opcode)
69     {
70 
71         //----------------------------------------------------------------------
72         // user-defined operator
73         //----------------------------------------------------------------------
74 
75         case GB_USER_opcode
76 
77             e = 0 ; break ;
78 
79         //----------------------------------------------------------------------
80         // built-in ops that can be used in a monoid:
81         //----------------------------------------------------------------------
82 
83         case GB_FIRST_opcode :    // z = x, can be used as the ANY monoid
84 
85             e = 1 ; break ;
86 
87         case GB_ANY_opcode :      // z = y (same as SECOND)
88 
89             e = 2 ; break ;
90 
91         case GB_MIN_opcode :      //  z = min(x,y)
92 
93             switch (xcode)
94             {
95                 case GB_BOOL_code   : e = 18 ; break ; // x && y
96                 case GB_FP32_code   : e =  3 ; break ; // fminf (x,y)
97                 case GB_FP64_code   : e =  4 ; break ; // fmin (x,y)
98                 case GB_FC32_code   : e = -1 ; break ; // invalid
99                 case GB_FC64_code   : e = -1 ; break ; // invalid
100                 default             : e =  5 ; break ; // GB_IMIN (x,y)
101             }
102             break ;
103 
104         case GB_MAX_opcode :      // z = max(x,y)
105 
106             switch (xcode)
107             {
108                 case GB_BOOL_code   : e = 17 ; break ; // x || y
109                 case GB_FP32_code   : e =  6 ; break ; // fmaxf (x,y)
110                 case GB_FP64_code   : e =  7 ; break ; // fmax (x,y)
111                 case GB_FC32_code   : e = -1 ; break ; // invalid
112                 case GB_FC64_code   : e = -1 ; break ; // invalid
113                 default             : e =  8 ; break ; // GB_IMAX (x,y)
114             }
115             break ;
116 
117         case GB_PLUS_opcode :     // z = x + y
118 
119             switch (xcode)
120             {
121                 case GB_BOOL_code   : e = 17 ; break ; // x || y
122                 case GB_FC32_code   : e =  9 ; break ; // GB_FC32_add(x,y)
123                 case GB_FC64_code   : e = 10 ; break ; // GB_FC64_add(x,y)
124                 default             : e = 11 ; break ; // x + y
125             }
126             break ;
127 
128         case GB_TIMES_opcode :    // z = x * y
129 
130             switch (xcode)
131             {
132                 case GB_BOOL_code   : e = 18 ; break ; // x && y
133                 case GB_FC32_code   : e = 12 ; break ; // GB_FC32_mul(x,y)
134                 case GB_FC64_code   : e = 13 ; break ; // GB_FC64_mul(x,y)
135                 default             : e = 14 ; break ; // x * y
136             }
137             break ;
138 
139         case GB_EQ_opcode :       // z = (x == y), the LXNOR monoid for bool
140 
141             // only a monoid for bool (lxnor)
142             switch (xcode)
143             {
144                 case GB_BOOL_code   : e = 15 ; break ; // x == y
145                 case GB_FC32_code   : e = 32 ; break ; // GB_FC32_eq(x,y)
146                 case GB_FC64_code   : e = 33 ; break ; // GB_FC64_eq(x,y)
147                 default             : e = 15 ; break ; // x == y, not a monoid
148             }
149             break ;
150 
151         case GB_NE_opcode :       // z = (x != y), the LXOR monoid for bool
152 
153             // only a monoid for bool (lxor)
154             switch (xcode)
155             {
156                 case GB_BOOL_code   : e = 16 ; break ; // x != y
157                 case GB_FC32_code   : e = 36 ; break ; // GB_FC32_ne(x,y)
158                 case GB_FC64_code   : e = 37 ; break ; // GB_FC64_ne(x,y)
159                 default             : e = 16 ; break ; // x != y
160             }
161             break ;
162 
163         case GB_LOR_opcode :      // z = (x || y)
164 
165             switch (xcode)
166             {
167                 case GB_BOOL_code  : e = 17 ; break ; // x || y
168                 default            : e = 40 ; break ; // not a monoid
169             }
170             break ;
171 
172         case GB_LAND_opcode :     // z = (x && y)
173 
174             switch (xcode)
175             {
176                 case GB_BOOL_code   : e = 18 ; break ; // x && y
177                 default             : e = 41 ; break ; // not a monoid
178             }
179             break ;
180 
181         case GB_LXOR_opcode :     // z = (x != y)
182 
183             switch (xcode)
184             {
185                 case GB_BOOL_code   : e = 16 ; break ; // x != y
186                 default             : e = 42 ; break ; // not a monoid
187             }
188             break ;
189 
190         case GB_BOR_opcode       :   // z = (x | y), bitwise or
191 
192             if (xcode >= GB_INT8_code && xcode <= GB_UINT64_code) e = 19 ;
193             break ;
194 
195         case GB_BAND_opcode      :   // z = (x & y), bitwise and
196 
197             if (xcode >= GB_INT8_code && xcode <= GB_UINT64_code) e = 20 ;
198             break ;
199 
200         case GB_BXOR_opcode      :   // z = (x ^ y), bitwise xor
201 
202             if (xcode >= GB_INT8_code && xcode <= GB_UINT64_code) e = 21 ;
203             break ;
204 
205         case GB_BXNOR_opcode     :   // z = ~(x ^ y), bitwise xnor
206 
207             if (xcode >= GB_INT8_code && xcode <= GB_UINT64_code) e = 22 ;
208             break ;
209 
210         //----------------------------------------------------------------------
211         // built-in ops that cannot be used in a monoid:
212         //----------------------------------------------------------------------
213 
214         case GB_SECOND_opcode :   // z = y (same as ANY, but not a monoid)
215 
216             e = 2 ; break ;
217 
218         case GB_ISEQ_opcode :     // z = (x == y), but not a monoid
219 
220             switch (xcode)
221             {
222                 case GB_BOOL_code   : e = 15 ; break ; // x == y
223                 case GB_FC32_code   : e = 34 ; break ; // GB_FC32_iseq(x,y)
224                 case GB_FC64_code   : e = 35 ; break ; // GB_FC64_iseq(x,y)
225                 default             : e = 15 ; break ; // x == y, not a monoid
226             }
227             break ;
228 
229         case GB_ISNE_opcode :     // z = (x != y), but not a monoid
230 
231             switch (xcode)
232             {
233                 case GB_BOOL_code   : e = 16 ; break ; // x != y
234                 case GB_FC32_code   : e = 38 ; break ; // GB_FC32_isne(x,y)
235                 case GB_FC64_code   : e = 39 ; break ; // GB_FC64_isne(x,y)
236                 default             : e = 16 ; break ; // x != y
237             }
238             break ;
239 
240         case GB_MINUS_opcode :    // z = x - y
241 
242             switch (xcode)
243             {
244                 case GB_BOOL_code   : e = 16 ; break ; // x != y
245                 case GB_FC32_code   : e = 43 ; break ; // GB_FC32_minus(x,y)
246                 case GB_FC64_code   : e = 44 ; break ; // GB_FC64_minus(x,y)
247                 default             : e = 45 ; break ; // x - y
248             }
249             break ;
250 
251         case GB_RMINUS_opcode :   // z = y - x
252 
253             switch (xcode)
254             {
255                 case GB_BOOL_code   : e = 16 ; break ; // x != y
256                 case GB_FC32_code   : e = 46 ; break ; // GB_FC32_minus(y,x)
257                 case GB_FC64_code   : e = 47 ; break ; // GB_FC64_minus(y,x)
258                 default             : e = 48 ; break ; // y - x
259             }
260             break ;
261 
262         case GB_DIV_opcode :      // z = x / y ;
263 
264             switch (xcode)
265             {
266                 case GB_BOOL_code   : e =  1 ; break ; // x
267                 case GB_INT8_code   : e = 49 ; break ; // GB_IDIV_SIGNED(x,y,8)
268                 case GB_INT16_code  : e = 50 ; break ; // GB_IDIV_SIGNED(x,y,16)
269                 case GB_INT32_code  : e = 51 ; break ; // GB_IDIV_SIGNED(x,y,32)
270                 case GB_INT64_code  : e = 52 ; break ; // GB_IDIV_SIGNED(x,y,64)
271                 case GB_UINT8_code  : e = 53 ; break ; // GB_IDIV_UN...(x,y,8)
272                 case GB_UINT16_code : e = 54 ; break ; // GB_IDIV_UN...(x,y,16)
273                 case GB_UINT32_code : e = 55 ; break ; // GB_IDIV_UN...(x,y,32)
274                 case GB_UINT64_code : e = 56 ; break ; // GB_IDIV_UN...(x,y,64)
275                 case GB_FC32_code   : e = 57 ; break ; // GB_FC32_div(x,y)
276                 case GB_FC64_code   : e = 58 ; break ; // GB_FC64_div(x,y)
277                 default             : e = 59 ; break ; // (x) / (y)
278             }
279             break ;
280 
281         case GB_RDIV_opcode :      // z = y / x ;
282 
283             switch (xcode)
284             {
285                 case GB_BOOL_code   : e =  2 ; break ; // y
286                 case GB_INT8_code   : e = 60 ; break ; // GB_IDIV_SIGNED(y,x,8)
287                 case GB_INT16_code  : e = 61 ; break ; // GB_IDIV_SIGNED(y,x,16)
288                 case GB_INT32_code  : e = 62 ; break ; // GB_IDIV_SIGNED(y,x,32)
289                 case GB_INT64_code  : e = 63 ; break ; // GB_IDIV_SIGNED(y,x,64)
290                 case GB_UINT8_code  : e = 64 ; break ; // GB_IDIV_UN...(y,x,8)
291                 case GB_UINT16_code : e = 65 ; break ; // GB_IDIV_UN...(y,x,16)
292                 case GB_UINT32_code : e = 66 ; break ; // GB_IDIV_UN...(y,x,32)
293                 case GB_UINT64_code : e = 67 ; break ; // GB_IDIV_UN...(y,x,64)
294                 case GB_FC32_code   : e = 68 ; break ; // GB_FC32_div(y,x)
295                 case GB_FC64_code   : e = 69 ; break ; // GB_FC64_div(y,x)
296                 default             : e = 70 ; break ; // (y) / (x)
297             }
298             break ;
299 
300         case GB_GT_opcode :
301         case GB_ISGT_opcode :     // z = (x > y)
302 
303             e = 71 ; break ;
304 
305         case GB_LT_opcode :
306         case GB_ISLT_opcode :     // z = (x < y)
307 
308             e = 72 ; break ;
309 
310         case GB_GE_opcode :
311         case GB_ISGE_opcode :     // z = (x >= y)
312 
313             e = 73 ; break ;
314 
315         case GB_LE_opcode :
316         case GB_ISLE_opcode :     // z = (x <= y)
317 
318             e = 74 ; break ;
319 
320         case GB_BGET_opcode      :   // z = bitget (x,y)
321 
322             switch (xcode)
323             {
324                 case GB_INT8_code   : e = 75 ; break ;
325                 case GB_INT16_code  : e = 76 ; break ;
326                 case GB_INT32_code  : e = 77 ; break ;
327                 case GB_INT64_code  : e = 78 ; break ;
328                 case GB_UINT8_code  : e = 79 ; break ;
329                 case GB_UINT16_code : e = 80 ; break ;
330                 case GB_UINT32_code : e = 81 ; break ;
331                 case GB_UINT64_code : e = 82 ; break ;
332                 default             : e = -1 ; break ;
333             }
334             break ;
335 
336         case GB_BSET_opcode      :   // z = bitset (x,y)
337 
338             switch (xcode)
339             {
340                 case GB_INT8_code   : e = 83 ; break ;
341                 case GB_INT16_code  : e = 84 ; break ;
342                 case GB_INT32_code  : e = 85 ; break ;
343                 case GB_INT64_code  : e = 86 ; break ;
344                 case GB_UINT8_code  : e = 87 ; break ;
345                 case GB_UINT16_code : e = 88 ; break ;
346                 case GB_UINT32_code : e = 89 ; break ;
347                 case GB_UINT64_code : e = 90 ; break
348                 default             : e = -1 ; break ;
349             }
350             break ;
351 
352         case GB_BCLR_opcode      :   // z = bitclr (x,y)
353 
354             switch (xcode)
355             {
356                 case GB_INT8_code   : e = 91 ; break ;
357                 case GB_INT16_code  : e = 92 ; break ;
358                 case GB_INT32_code  : e = 93 ; break ;
359                 case GB_INT64_code  : e = 94 ; break ;
360                 case GB_UINT8_code  : e = 95 ; break ;
361                 case GB_UINT16_code : e = 96 ; break ;
362                 case GB_UINT32_code : e = 97 ; break ;
363                 case GB_UINT64_code : e = 98 ; break ;
364                 default             : e = -1 ; break ;
365             }
366             break ;
367 
368         case GB_BSHIFT_opcode    :   // z = bitshift (x,y)
369 
370             switch (xcode)
371             {
372                 case GB_INT8_code   : e =  99 ; break ;
373                 case GB_INT16_code  : e = 100 ; break ;
374                 case GB_INT32_code  : e = 101 ; break ;
375                 case GB_INT64_code  : e = 102 ; break ;
376                 case GB_UINT8_code  : e = 103 ; break ;
377                 case GB_UINT16_code : e = 104 ; break ;
378                 case GB_UINT32_code : e = 105 ; break ;
379                 case GB_UINT64_code : e = 106 ; break ;
380                 default             : e = -1 ; break ;
381             }
382             break ;
383 
384         case GB_POW_opcode    :   // z = pow (x,y)
385 
386             switch (xcode)
387             {
388                 case GB_BOOL_code   : e =  71 ; break ; // x >= y
389                 case GB_INT8_code   : e = 107 ; break ;
390                 case GB_INT16_code  : e = 108 ; break ;
391                 case GB_INT32_code  : e = 109 ; break ;
392                 case GB_INT64_code  : e = 110 ; break ;
393                 case GB_UINT8_code  : e = 111 ; break ;
394                 case GB_UINT16_code : e = 112 ; break ;
395                 case GB_UINT32_code : e = 113 ; break ;
396                 case GB_UINT64_code : e = 114 ; break ;
397                 case GB_FP32_code   : e = 115 ; break ;
398                 case GB_FP64_code   : e = 116 ; break ;
399                 case GB_FC32_code   : e = 117 ; break ;
400                 case GB_FC64_code   : e = 118 ; break ;
401                 default             : e =  -1 ; break ;
402             }
403             break ;
404 
405         case GB_ATAN2_opcode     :   // z = atan2 (x,y)
406 
407             switch (xcode)
408             {
409                 case GB_FP32_code   : e = 119 ; break ;
410                 case GB_FP64_code   : e = 120 ; break ;
411                 default             : e =  -1 ; break ;
412             }
413             break ;
414 
415         case GB_HYPOT_opcode     :   // z = hypot (x,y)
416 
417             switch (xcode)
418             {
419                 case GB_FP32_code   : e = 121 ; break ;
420                 case GB_FP64_code   : e = 122 ; break ;
421                 default             : e =  -1 ; break ;
422             }
423             break ;
424 
425         case GB_FMOD_opcode      :   // z = fmod (x,y)
426 
427             switch (xcode)
428             {
429                 case GB_FP32_code   : e = 123 ; break ;
430                 case GB_FP64_code   : e = 124 ; break ;
431                 default             : e =  -1 ; break ;
432             }
433             break ;
434 
435         case GB_REMAINDER_opcode :   // z = remainder (x,y)
436 
437             switch (xcode)
438             {
439                 case GB_FP32_code   : e = 125 ; break ;
440                 case GB_FP64_code   : e = 126 ; break ;
441                 default             : e =  -1 ; break ;
442             }
443             break ;
444 
445         case GB_COPYSIGN_opcode  :   // z = copysign (x,y)
446 
447             switch (xcode)
448             {
449                 case GB_FP32_code   : e = 127 ; break ;
450                 case GB_FP64_code   : e = 128 ; break ;
451                 default             : e =  -1 ; break ;
452             }
453             break ;
454 
455         case GB_LDEXP_opcode     :   // z = ldexp (x,y)
456 
457             switch (xcode)
458             {
459                 case GB_FP32_code   : e = 129 ; break ;
460                 case GB_FP64_code   : e = 130 ; break ;
461                 default             : e =  -1 ; break ;
462             }
463             break ;
464 
465         case GB_CMPLX_opcode     :   // z = cmplx (x,y)
466 
467             switch (xcode)
468             {
469                 case GB_FP32_code   : e = 131 ; break ;
470                 case GB_FP64_code   : e = 132 ; break ;
471                 default             : e =  -1 ; break ;
472             }
473             break ;
474 
475         case GB_PAIR_opcode :       // z = 1
476 
477             e = 133 ; break ;
478 
479         //----------------------------------------------------------------------
480         // positional ops
481         //----------------------------------------------------------------------
482 
483         case GB_FIRSTI_opcode    :  // z = i
484 
485             e = 134 ; break ;
486 
487         case GB_FIRSTI1_opcode   :  // z = i+1
488 
489             e = 137 ; break ;
490 
491         case GB_FIRSTJ_opcode    :  // z = for_semiring ? (k) : (j)
492 
493             e = for_semiring ? 135 : 136 ; break ;
494 
495         case GB_FIRSTJ1_opcode   :  // z = for_semiring ? (k+1) : (j+1)
496 
497             e = for_semiring ? 138 : 139 ; break ;
498 
499         case GB_SECONDI_opcode   :  // z = for_semiring ? (k) : (i)
500 
501             e = for_semiring ? 135 : 134 ; break ;
502 
503         case GB_SECONDI1_opcode  :  // z = for_semiring ? (k+1) : (i+1)
504 
505             e = for_semiring ? 138 : 139 ; break ;
506 
507         case GB_SECONDJ_opcode   :  // z = j
508 
509             e = 136 ; break ;
510 
511         case GB_SECONDJ1_opcode  :  // z = j+1
512 
513             e = 139 ; break ;
514 
515         default : break ;
516     }
517 
518     (*ecode) = e ;
519 }
520 
521 //------------------------------------------------------------------------------
522 // GB_charify_binop: convert an ecode into a string
523 //------------------------------------------------------------------------------
524 
GB_charify_binop(char ** op_string,int ecode)525 void GB_charify_binop
526 (
527     // output:
528     char **op_string,   // string defining the operator (NULL if failure)
529     // input:
530     int ecode           // from GB_enumify_binop
531 )
532 {
533 
534     const char *f ;
535 
536     switch (ecode)
537     {
538 
539         //----------------------------------------------------------------------
540         // user-defined ops
541         //----------------------------------------------------------------------
542 
543         // f must be defined by a string provided by the user.  This is
544         // only a place-holder
545 
546         case   0 : f = "user-defined"               ; break ;
547 
548         //----------------------------------------------------------------------
549         // built-in ops, can be used in a monoid
550         //----------------------------------------------------------------------
551 
552         // first
553         case   1 : f = "x"                          ; break ;
554 
555         // any, second
556         case   2 : f = "y"                          ; break ;
557 
558         // min
559         case   3 : f = "fminf (x,y)"                ; break ;
560         case   4 : f = "fmin (x,y)"                 ; break ;
561         case   5 : f = "GB_IMIN (x,y)"              ; break ;
562 
563         // max
564         case   6 : f = "fmaxf (x,y)"                ; break ;
565         case   7 : f = "fmax (x,y)"                 ; break ;
566         case   8 : f = "GB_IMAX (x,y)"              ; break ;
567 
568         // plus
569         case   9 : f = "GB_FC32_add(x,y)"           ; break ;
570         case  10 : f = "GB_FC64_add(x,y)"           ; break ;
571         case  11 : f = "(x) + (y)"                  ; break ;
572 
573         // times
574         case  12 : f = "GB_FC32_mul(x,y)"           ; break ;
575         case  13 : f = "GB_FC64_mul(x,y)"           ; break ;
576         case  14 : f = "(x) * (y)"                  ; break ;
577 
578         // eq, iseq, lxnor
579         case  15 : f = "(x) == (y)"                 ; break ;
580 
581         // ne, isne, lxor
582         case  16 : f = "(x) != (y)"                 ; break ;
583 
584         // lor
585         case  17 : f = "(x) || (y)"                 ; break ;
586 
587         // land
588         case  18 : f = "(x) && (y)"                 ; break ;
589 
590         // bor
591         case  19 : f = "(x) | (y)"                  ; break ;
592 
593         // band
594         case  20 : f = "(x) & (y)"                  ; break ;
595 
596         // bxor
597         case  21 : f = "(x) ^ (y)"                  ; break ;
598 
599         // bxnor
600         case  22 : f = "~((x) ^ (y))"               ; break ;
601 
602         // 23 to 31 are unused, but reserved for future monoids
603 
604         //----------------------------------------------------------------------
605         // built-in ops, cannot be used in a monoid
606         //----------------------------------------------------------------------
607 
608         // eq for complex
609         case  32 : f = "GB_FC32_eq(x,y)"            ; break ;
610         case  33 : f = "GB_FC64_eq(x,y)"            ; break ;
611 
612         // iseq for complex
613         case  34 : f = "GB_FC32_iseq(x,y)"          ; break ;
614         case  35 : f = "GB_FC64_iseq(x,y)"          ; break ;
615 
616         // ne for complex
617         case  36 : f = "GB_FC32_ne(x,y)"            ; break ;
618         case  37 : f = "GB_FC64_ne(x,y)"            ; break ;
619 
620         // isne for complex
621         case  38 : f = "GB_FC32_isne(x,y)"          ; break ;
622         case  39 : f = "GB_FC64_isne(x,y)"          ; break ;
623 
624         // lor for non-boolean
625         case  40 : f = "((x)!=0) || ((y)!=0)"       ; break ;
626 
627         // land for non-boolean
628         case  41 : f = "((x)!=0) && ((y)!=0)"       ; break ;
629 
630         // lxor for non-boolean
631         case  42 : f = "((x)!=0) != ((y)!=0)"       ; break ;
632 
633         // minus
634         case  43 : f = "GB_FC32_minus(x,y)"         ; break ;
635         case  44 : f = "GB_FC64_minus(x,y)"         ; break ;
636         case  45 : f = "(x) - (y)"                  ; break ;
637 
638         // rminus
639         case  46 : f = "GB_FC32_minus(y,x)"         ; break ;
640         case  47 : f = "GB_FC64_minus(y,x)"         ; break ;
641         case  48 : f = "(y) - (x)"                  ; break ;
642 
643         // div
644         case  49 : f = "GB_IDIV_SIGNED(x,y,8)"      ; break ;
645         case  50 : f = "GB_IDIV_SIGNED(x,y,16)"     ; break ;
646         case  51 : f = "GB_IDIV_SIGNED(x,y,32)"     ; break ;
647         case  52 : f = "GB_IDIV_SIGNED(x,y,64)"     ; break ;
648         case  53 : f = "GB_IDIV_UNSIGNED(x,y,8)"    ; break ;
649         case  54 : f = "GB_IDIV_UNSIGNED(x,y,16)"   ; break ;
650         case  55 : f = "GB_IDIV_UNSIGNED(x,y,32)"   ; break ;
651         case  56 : f = "GB_IDIV_UNSIGNED(x,y,64)"   ; break ;
652         case  57 : f = "GB_FC32_div(x,y)"           ; break ;
653         case  58 : f = "GB_FC64_div(x,y)"           ; break ;
654         case  59 : f = "(x) / (y)"                  ; break ;
655 
656         // rdiv
657         case  60 : f = "GB_IDIV_SIGNED(y,x,8)"      ; break ;
658         case  61 : f = "GB_IDIV_SIGNED(y,x,16)"     ; break ;
659         case  62 : f = "GB_IDIV_SIGNED(y,x,32)"     ; break ;
660         case  63 : f = "GB_IDIV_SIGNED(y,x,64)"     ; break ;
661         case  64 : f = "GB_IDIV_UNSIGNED(y,x,8)"    ; break ;
662         case  65 : f = "GB_IDIV_UNSIGNED(y,x,16)"   ; break ;
663         case  66 : f = "GB_IDIV_UNSIGNED(y,x,32)"   ; break ;
664         case  67 : f = "GB_IDIV_UNSIGNED(y,x,64)"   ; break ;
665         case  68 : f = "GB_FC32_div(x,y)"           ; break ;
666         case  69 : f = "GB_FC64_div(x,y)"           ; break ;
667         case  70 : f = "(y) / (x)"                  ; break ;
668 
669         // gt, isgt
670         case  71 : f = "(x) > (y)"                  ; break ;
671 
672         // lt, islt
673         case  72 : f = "(x) < (y)"                  ; break ;
674 
675         // ge, isget
676         case  73 : f = "(x) >= (y)"                 ; break ;
677 
678         // le, isle
679         case  74 : f = "(x) <= (y)"                 ; break ;
680 
681         // bget
682         case  75 : f = "GB_BITGET(x,y,int8_t, 8)"   ; break ;
683         case  76 : f = "GB_BITGET(x,y,int16_t,16)"  ; break ;
684         case  77 : f = "GB_BITGET(x,y,int32_t,32)"  ; break ;
685         case  78 : f = "GB_BITGET(x,y,int64_t,64)"  ; break ;
686         case  79 : f = "GB_BITGET(x,y,uint8_t,8)"   ; break ;
687         case  80 : f = "GB_BITGET(x,y,uint16_t,16)" ; break ;
688         case  81 : f = "GB_BITGET(x,y,uint32_t,32)" ; break ;
689         case  82 : f = "GB_BITGET(x,y,uint64_t,64)" ; break ;
690 
691         // bset
692         case  83 : f = "GB_BITSET(x,y,int8_t, 8)"   ; break ;
693         case  84 : f = "GB_BITSET(x,y,int16_t,16)"  ; break ;
694         case  85 : f = "GB_BITSET(x,y,int32_t,32)"  ; break ;
695         case  86 : f = "GB_BITSET(x,y,int64_t,64)"  ; break ;
696         case  87 : f = "GB_BITSET(x,y,uint8_t,8)"   ; break ;
697         case  88 : f = "GB_BITSET(x,y,uint16_t,16)" ; break ;
698         case  89 : f = "GB_BITSET(x,y,uint32_t,32)" ; break ;
699         case  90 : f = "GB_BITSET(x,y,uint64_t,64)" ; break ;
700 
701         // bclr
702         case  91 : f = "GB_BITCLR(x,y,int8_t, 8)"   ; break ;
703         case  92 : f = "GB_BITCLR(x,y,int16_t,16)"  ; break ;
704         case  93 : f = "GB_BITCLR(x,y,int32_t,32)"  ; break ;
705         case  94 : f = "GB_BITCLR(x,y,int64_t,64)"  ; break ;
706         case  95 : f = "GB_BITCLR(x,y,uint8_t,8)"   ; break ;
707         case  96 : f = "GB_BITCLR(x,y,uint16_t,16)" ; break ;
708         case  97 : f = "GB_BITCLR(x,y,uint32_t,32)" ; break ;
709         case  98 : f = "GB_BITCLR(x,y,uint64_t,64)" ; break ;
710 
711         // bshift
712         case  99 : f = "GB_bitshift_int8(x,y)"      ; break ;
713         case 100 : f = "GB_bitshift_int16(x,y)"     ; break ;
714         case 101 : f = "GB_bitshift_int32(x,y)"     ; break ;
715         case 102 : f = "GB_bitshift_int64(x,y)"     ; break ;
716         case 103 : f = "GB_bitshift_uint8(x,y)"     ; break ;
717         case 104 : f = "GB_bitshift_uint16(x,y)"    ; break ;
718         case 105 : f = "GB_bitshift_uint32(x,y)"    ; break ;
719         case 106 : f = "GB_bitshift_uint64(x,y)"    ; break ;
720 
721         // pow
722         case 107 : f = "GB_pow_int8 (x, y)"         ; break ;
723         case 108 : f = "GB_pow_int16 (x, y)"        ; break ;
724         case 109 : f = "GB_pow_int32 (x, y)"        ; break ;
725         case 110 : f = "GB_pow_int64 (x, y)"        ; break ;
726         case 111 : f = "GB_pow_uint8 (x, y)"        ; break ;
727         case 112 : f = "GB_pow_uint16 (x, y)"       ; break ;
728         case 113 : f = "GB_pow_uint32 (x, y)"       ; break ;
729         case 114 : f = "GB_pow_uint64 (x, y)"       ; break ;
730         case 115 : f = "GB_powf (x, y)"             ; break ;
731         case 116 : f = "GB_pow (x, y)"              ; break ;
732         case 117 : f = "GB_cpowf (x, y)"            ; break ;
733         case 118 : f = "GB_cpow (x, y)"             ; break ;
734 
735         // atan2
736         case 119 : f = "atan2f (x, y)"              ; break ;
737         case 120 : f = "atan2 (x, y)"               ; break ;
738 
739         // hypot
740         case 121 : f = "hypotf (x, y)"              ; break ;
741         case 122 : f = "hypot (x, y)"               ; break ;
742 
743         // fmod
744         case 123 : f = "fmodf (x, y)"               ; break ;
745         case 124 : f = "fmod (x, y)"                ; break ;
746 
747         // remainder
748         case 125 : f = "remainderf (x, y)"          ; break ;
749         case 126 : f = "remainder (x, y)"           ; break ;
750 
751         // copysign
752         case 127 : f = "copysignf (x, y)"           ; break ;
753         case 128 : f = "copysign (x, y)"            ; break ;
754 
755         // ldexp
756         case 129 : f = "ldexpf (x, y)"              ; break ;
757         case 130 ; f = "ldexp (x, y)"               ; break ;
758 
759         // cmplex
760         case 131 : f = "GxB_CMPLXF (x, y)"          ; break ;
761         case 132 : f = "GxB_CMPLX (x, y)"           ; break ;
762 
763         // pair
764         case 133 : f = "1"                          ; break ;
765 
766         //----------------------------------------------------------------------
767         // positional ops
768         //----------------------------------------------------------------------
769 
770         // in a semiring:  cij += aik * bkj
771         //      firsti is i, firstj is k, secondi k, secondj is j
772 
773         // in an ewise operation:  cij = aij + bij
774         //      firsti is i, firstj is j, secondi i, secondj is j
775 
776         case 134 : f = "i"                          ; break ;
777         case 135 : f = "k"                          ; break ;
778         case 136 : f = "j"                          ; break ;
779         case 137 : f = "i+1"                        ; break ;
780         case 138 : f = "k+1"                        ; break ;
781         case 139 : f = "j+1"                        ; break ;
782 
783         default  : f = NULL ;                       ; break ;
784     }
785 
786     (*op_string) = f ;
787 }
788 
789 //------------------------------------------------------------------------------
790 // GB_macrofy_binop: convert an opstring into a macro
791 //------------------------------------------------------------------------------
792 
GB_macrofy_binop(char * binop_macro,const char * macro_name,char * op_string,bool flipxy)793 void GB_macrofy_binop
794 (
795     // output:
796     char *binop_macro,          // string with the #define macro
797     // input:
798     const char *macro_name,     // name of macro to construct
799     char *op_string,            // string defining the operator
800     bool flipxy                 // if true, use mult(y,x) else mult(x,y)
801 )
802 {
803     if (flipxy)
804     {
805         // reverse the x and y arguments to flip the operator
806         snprintf (binop_macro, GB_CUDA_STRLEN,
807             "#define %s(y,x) (%s)", macro_name, op_string) ;
808     }
809     else
810     {
811         // operator is not flipped
812         snprintf (binop_macro, GB_CUDA_STRLEN,
813             "#define %s(x,y) (%s)", macro_name, op_string) ;
814     }
815 }
816 
817