1 //------------------------------------------------------------------------------
2 // GB_mx_Monoid: construct a monoid from a built-in operator
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 // Also defines the identity of the monoid
11
12 #define GET_DEEP_COPY ;
13 #define FREE_DEEP_COPY ;
14 #define FREE_ALL ;
15
16 #include "GB_mex.h"
17
GB_mx_Monoid(GrB_Monoid * handle,const GrB_BinaryOp add,const bool malloc_debug)18 bool GB_mx_Monoid // true if successful, false otherwise
19 (
20 GrB_Monoid *handle, // monoid to construct
21 const GrB_BinaryOp add, // monoid operator
22 const bool malloc_debug // true if malloc debug should be done
23 )
24 {
25
26 GrB_Monoid M = NULL ;
27 (*handle) = NULL ;
28 if (add == NULL)
29 {
30 mexWarnMsgIdAndTxt ("GB:warn", "monoid operator missing") ;
31 return (false) ;
32 }
33
34 switch (add->opcode)
35 {
36 case GB_MIN_opcode :
37
38 // 11 MIN monoids
39 switch (add->xtype->code)
40 {
41 // bool case redundant with AND
42 case GB_BOOL_code : METHOD (GrB_Monoid_new_BOOL_ (&M, add, (bool ) true)) ; break ;
43 case GB_INT8_code : METHOD (GrB_Monoid_new_INT8_ (&M, add, (int8_t ) INT8_MAX)) ; break ;
44 case GB_INT16_code : METHOD (GrB_Monoid_new_INT16_ (&M, add, (int16_t ) INT16_MAX)) ; break ;
45 case GB_INT32_code : METHOD (GrB_Monoid_new_INT32_ (&M, add, (int32_t ) INT32_MAX)) ; break ;
46 case GB_INT64_code : METHOD (GrB_Monoid_new_INT64_ (&M, add, (int64_t ) INT64_MAX)) ; break ;
47 case GB_UINT8_code : METHOD (GrB_Monoid_new_UINT8_ (&M, add, (uint8_t ) UINT8_MAX)) ; break ;
48 case GB_UINT16_code : METHOD (GrB_Monoid_new_UINT16_(&M, add, (uint16_t) UINT16_MAX)) ; break ;
49 case GB_UINT32_code : METHOD (GrB_Monoid_new_UINT32_(&M, add, (uint32_t) UINT32_MAX)) ; break ;
50 case GB_UINT64_code : METHOD (GrB_Monoid_new_UINT64_(&M, add, (uint64_t) UINT64_MAX)) ; break ;
51 case GB_FP32_code : METHOD (GrB_Monoid_new_FP32_ (&M, add, (float ) INFINITY)) ; break ;
52 case GB_FP64_code : METHOD (GrB_Monoid_new_FP64_ (&M, add, (double ) INFINITY)) ; break ;
53 default:
54 mexWarnMsgIdAndTxt ("GB:warn", "unknown type for MIN") ;
55 return (false) ;
56 }
57 break ;
58
59 case GB_MAX_opcode :
60
61 // 11 MAX monoids
62 switch (add->xtype->code)
63 {
64 // bool case redundant with OR
65 case GB_BOOL_code : METHOD (GrB_Monoid_new_BOOL_ (&M, add, (bool ) false)) ; break ;
66 case GB_INT8_code : METHOD (GrB_Monoid_new_INT8_ (&M, add, (int8_t ) INT8_MIN)) ; break ;
67 case GB_INT16_code : METHOD (GrB_Monoid_new_INT16_ (&M, add, (int16_t ) INT16_MIN)) ; break ;
68 case GB_INT32_code : METHOD (GrB_Monoid_new_INT32_ (&M, add, (int32_t ) INT32_MIN)) ; break ;
69 case GB_INT64_code : METHOD (GrB_Monoid_new_INT64_ (&M, add, (int64_t ) INT64_MIN)) ; break ;
70 case GB_UINT8_code : METHOD (GrB_Monoid_new_UINT8_ (&M, add, (uint8_t ) 0)) ; break ;
71 case GB_UINT16_code : METHOD (GrB_Monoid_new_UINT16_(&M, add, (uint16_t) 0)) ; break ;
72 case GB_UINT32_code : METHOD (GrB_Monoid_new_UINT32_(&M, add, (uint32_t) 0)) ; break ;
73 case GB_UINT64_code : METHOD (GrB_Monoid_new_UINT64_(&M, add, (uint64_t) 0)) ; break ;
74 case GB_FP32_code : METHOD (GrB_Monoid_new_FP32_ (&M, add, (float ) -INFINITY)) ; break ;
75 case GB_FP64_code : METHOD (GrB_Monoid_new_FP64_ (&M, add, (double ) -INFINITY)) ; break ;
76 default:
77 mexWarnMsgIdAndTxt ("GB:warn", "unknown type for MAX") ;
78 return (false) ;
79 }
80 break ;
81
82 case GB_PLUS_opcode :
83
84 // 13 PLUS monoids
85 switch (add->xtype->code)
86 {
87 // bool case redundant with OR
88 case GB_BOOL_code : METHOD (GrB_Monoid_new_BOOL_ (&M, add, (bool ) 0)) ; break ;
89 case GB_INT8_code : METHOD (GrB_Monoid_new_INT8_ (&M, add, (int8_t ) 0)) ; break ;
90 case GB_INT16_code : METHOD (GrB_Monoid_new_INT16_ (&M, add, (int16_t ) 0)) ; break ;
91 case GB_INT32_code : METHOD (GrB_Monoid_new_INT32_ (&M, add, (int32_t ) 0)) ; break ;
92 case GB_INT64_code : METHOD (GrB_Monoid_new_INT64_ (&M, add, (int64_t ) 0)) ; break ;
93 case GB_UINT8_code : METHOD (GrB_Monoid_new_UINT8_ (&M, add, (uint8_t ) 0)) ; break ;
94 case GB_UINT16_code : METHOD (GrB_Monoid_new_UINT16_(&M, add, (uint16_t) 0)) ; break ;
95 case GB_UINT32_code : METHOD (GrB_Monoid_new_UINT32_(&M, add, (uint32_t) 0)) ; break ;
96 case GB_UINT64_code : METHOD (GrB_Monoid_new_UINT64_(&M, add, (uint64_t) 0)) ; break ;
97 case GB_FP32_code : METHOD (GrB_Monoid_new_FP32_ (&M, add, (float ) 0)) ; break ;
98 case GB_FP64_code : METHOD (GrB_Monoid_new_FP64_ (&M, add, (double ) 0)) ; break ;
99 case GB_FC32_code : METHOD (GxB_Monoid_new_FC32_ (&M, add, (GxB_CMPLXF(0,0)))) ; break ;
100 case GB_FC64_code : METHOD (GxB_Monoid_new_FC64_ (&M, add, (GxB_CMPLX (0,0)))) ; break ;
101 default:
102 mexWarnMsgIdAndTxt ("GB:warn", "unknown type for (PLUS)") ;
103 return (false) ;
104 }
105 break ;
106
107 case GB_TIMES_opcode :
108
109 // 13 TIMES monoids
110 switch (add->xtype->code)
111 {
112 // bool case redundant with AND
113 case GB_BOOL_code : METHOD (GrB_Monoid_new_BOOL_ (&M, add, (bool ) true)) ; break ;
114 case GB_INT8_code : METHOD (GrB_Monoid_new_INT8_ (&M, add, (int8_t ) 1)) ; break ;
115 case GB_INT16_code : METHOD (GrB_Monoid_new_INT16_ (&M, add, (int16_t ) 1)) ; break ;
116 case GB_INT32_code : METHOD (GrB_Monoid_new_INT32_ (&M, add, (int32_t ) 1)) ; break ;
117 case GB_INT64_code : METHOD (GrB_Monoid_new_INT64_ (&M, add, (int64_t ) 1)) ; break ;
118 case GB_UINT8_code : METHOD (GrB_Monoid_new_UINT8_ (&M, add, (uint8_t ) 1)) ; break ;
119 case GB_UINT16_code : METHOD (GrB_Monoid_new_UINT16_(&M, add, (uint16_t) 1)) ; break ;
120 case GB_UINT32_code : METHOD (GrB_Monoid_new_UINT32_(&M, add, (uint32_t) 1)) ; break ;
121 case GB_UINT64_code : METHOD (GrB_Monoid_new_UINT64_(&M, add, (uint64_t) 1)) ; break ;
122 case GB_FP32_code : METHOD (GrB_Monoid_new_FP32_ (&M, add, (float ) 1)) ; break ;
123 case GB_FP64_code : METHOD (GrB_Monoid_new_FP64_ (&M, add, (double ) 1)) ; break ;
124 case GB_FC32_code : METHOD (GxB_Monoid_new_FC32_ (&M, add, (GxB_CMPLXF(1,0)))) ; break ;
125 case GB_FC64_code : METHOD (GxB_Monoid_new_FC64_ (&M, add, (GxB_CMPLX (1,0)))) ; break ;
126 default:
127 mexWarnMsgIdAndTxt ("GB:warn", "unknown type for (TIMES)") ;
128 return (false) ;
129 }
130 break ;
131
132 case GB_ANY_opcode :
133
134 // 13 ANY monoids
135 switch (add->xtype->code)
136 {
137 case GB_BOOL_code : METHOD (GrB_Monoid_new_BOOL (&M, add, (bool ) false)) ; break ;
138 case GB_INT8_code : METHOD (GrB_Monoid_new_INT8_ (&M, add, (int8_t ) 0)) ; break ;
139 case GB_INT16_code : METHOD (GrB_Monoid_new_INT16_ (&M, add, (int16_t ) 0)) ; break ;
140 case GB_INT32_code : METHOD (GrB_Monoid_new_INT32_ (&M, add, (int32_t ) 0)) ; break ;
141 case GB_INT64_code : METHOD (GrB_Monoid_new_INT64_ (&M, add, (int64_t ) 0)) ; break ;
142 case GB_UINT8_code : METHOD (GrB_Monoid_new_UINT8_ (&M, add, (uint8_t ) 0)) ; break ;
143 case GB_UINT16_code : METHOD (GrB_Monoid_new_UINT16_(&M, add, (uint16_t) 0)) ; break ;
144 case GB_UINT32_code : METHOD (GrB_Monoid_new_UINT32_(&M, add, (uint32_t) 0)) ; break ;
145 case GB_UINT64_code : METHOD (GrB_Monoid_new_UINT64_(&M, add, (uint64_t) 0)) ; break ;
146 case GB_FP32_code : METHOD (GrB_Monoid_new_FP32_ (&M, add, (float ) 0)) ; break ;
147 case GB_FP64_code : METHOD (GrB_Monoid_new_FP64_ (&M, add, (double ) 0)) ; break ;
148 case GB_FC32_code : METHOD (GxB_Monoid_new_FC32_ (&M, add, (GxB_CMPLXF(0,0)))) ; break ;
149 case GB_FC64_code : METHOD (GxB_Monoid_new_FC64_ (&M, add, (GxB_CMPLX (0,0)))) ; break ;
150 default:
151 mexWarnMsgIdAndTxt ("GB:warn", "unknown type for (ANY)") ;
152 return (false) ;
153 }
154 break ;
155
156 case GB_LOR_opcode :
157
158 // both GrB_LOR and GxB_LOR_BOOL (same opcode)
159 switch (add->xtype->code)
160 {
161 case GB_BOOL_code : METHOD (GrB_Monoid_new_BOOL_(&M, add, (bool ) false)) ; break ;
162 default:
163 mexWarnMsgIdAndTxt ("GB:warn", "invalid monoid for (OR)") ;
164 return (false) ;
165 }
166 break ;
167
168 case GB_LAND_opcode :
169
170 // both GrB_LAND and GxB_LAND_BOOL (same opcode)
171 switch (add->xtype->code)
172 {
173 case GB_BOOL_code : METHOD (GrB_Monoid_new_BOOL_(&M, add, (bool ) true)) ; break ;
174 default:
175 mexWarnMsgIdAndTxt ("GB:warn", "invalid monoid for (AND)") ;
176 return (false) ;
177 }
178 break ;
179
180 case GB_LXOR_opcode :
181
182 // both GrB_LXOR and GxB_LXOR_BOOL (same opcode)
183 switch (add->xtype->code)
184 {
185 case GB_BOOL_code : METHOD (GrB_Monoid_new_BOOL_(&M, add, (bool ) false)) ; break ;
186 default:
187 mexWarnMsgIdAndTxt ("GB:warn", "invalid monoid for (XOR)") ;
188 return (false) ;
189 }
190 break ;
191
192 case GB_ISEQ_opcode :
193 case GB_EQ_opcode :
194
195 // both GrB_EQ_BOOL and GxB_ISEQ_BOOL (same opcode), also GrB_LXNOR
196 switch (add->xtype->code)
197 {
198 case GB_BOOL_code : METHOD (GrB_Monoid_new_BOOL_(&M, add, (bool ) true)) ; break ;
199 default:
200 mexWarnMsgIdAndTxt ("GB:warn", "invalid monoid for (EQ)") ;
201 return (false) ;
202 }
203 break ;
204
205 case GB_BOR_opcode :
206
207 // BOR monoids (bitwise or):
208 // GxB_BOR_UINT8_MONOID, // identity: 0 terminal: 0xFF
209 // GxB_BOR_UINT16_MONOID, // identity: 0 terminal: 0xFFFF
210 // GxB_BOR_UINT32_MONOID, // identity: 0 terminal: 0xFFFFFFFF
211 // GxB_BOR_UINT64_MONOID, // identity: 0 terminal: 0xFFFFFFFFFFFFFFFF
212
213 switch (add->xtype->code)
214 {
215 case GB_UINT8_code : METHOD (GrB_Monoid_new_UINT8_ (&M, add, (uint8_t ) 0)) ; break ;
216 case GB_UINT16_code : METHOD (GrB_Monoid_new_UINT16_(&M, add, (uint16_t) 0)) ; break ;
217 case GB_UINT32_code : METHOD (GrB_Monoid_new_UINT32_(&M, add, (uint32_t) 0)) ; break ;
218 case GB_UINT64_code : METHOD (GrB_Monoid_new_UINT64_(&M, add, (uint64_t) 0)) ; break ;
219 default:
220 mexWarnMsgIdAndTxt ("GB:warn", "invalid monoid for (BOR)") ;
221 return (false) ;
222 }
223 break ;
224
225 case GB_BAND_opcode :
226
227 // BAND monoids (bitwise and):
228 // GxB_BAND_UINT8_MONOID, // identity: 0xFF terminal: 0
229 // GxB_BAND_UINT16_MONOID, // identity: 0xFFFF terminal: 0
230 // GxB_BAND_UINT32_MONOID, // identity: 0xFFFFFFFF terminal: 0
231 // GxB_BAND_UINT64_MONOID, // identity: 0xFFFFFFFFFFFFFFFF terminal: 0
232
233 switch (add->xtype->code)
234 {
235 case GB_UINT8_code : METHOD (GrB_Monoid_new_UINT8_ (&M, add, (uint8_t ) 0xFF)) ; break ;
236 case GB_UINT16_code : METHOD (GrB_Monoid_new_UINT16_(&M, add, (uint16_t) 0xFFFF)) ; break ;
237 case GB_UINT32_code : METHOD (GrB_Monoid_new_UINT32_(&M, add, (uint32_t) 0xFFFFFFFF)) ; break ;
238 case GB_UINT64_code : METHOD (GrB_Monoid_new_UINT64_(&M, add, (uint64_t) 0xFFFFFFFFFFFFFFFF)) ; break ;
239 default:
240 mexWarnMsgIdAndTxt ("GB:warn", "invalid monoid for (BAND)") ;
241 return (false) ;
242 }
243 break ;
244
245 case GB_BXOR_opcode :
246
247 // BXOR monoids (bitwise xor):
248 // GxB_BXOR_UINT8_MONOID, // identity: 0
249 // GxB_BXOR_UINT16_MONOID, // identity: 0
250 // GxB_BXOR_UINT32_MONOID, // identity: 0
251 // GxB_BXOR_UINT64_MONOID, // identity: 0
252
253 switch (add->xtype->code)
254 {
255 case GB_UINT8_code : METHOD (GrB_Monoid_new_UINT8_ (&M, add, (uint8_t ) 0)) ; break ;
256 case GB_UINT16_code : METHOD (GrB_Monoid_new_UINT16_(&M, add, (uint16_t) 0)) ; break ;
257 case GB_UINT32_code : METHOD (GrB_Monoid_new_UINT32_(&M, add, (uint32_t) 0)) ; break ;
258 case GB_UINT64_code : METHOD (GrB_Monoid_new_UINT64_(&M, add, (uint64_t) 0)) ; break ;
259 default:
260 mexWarnMsgIdAndTxt ("GB:warn", "invalid monoid for (BXOR)") ;
261 return (false) ;
262 }
263 break ;
264
265 case GB_BXNOR_opcode :
266
267 // BXNOR monoids (bitwise xnor):
268 // GxB_BXNOR_UINT8_MONOID, // identity: 0xFF
269 // GxB_BXNOR_UINT16_MONOID, // identity: 0xFFFF
270 // GxB_BXNOR_UINT32_MONOID, // identity: 0xFFFFFFFF
271 // GxB_BXNOR_UINT64_MONOID ; // identity: 0xFFFFFFFFFFFFFFFF
272
273 switch (add->xtype->code)
274 {
275 case GB_UINT8_code : METHOD (GrB_Monoid_new_UINT8_ (&M, add, (uint8_t ) 0xFF)) ; break ;
276 case GB_UINT16_code : METHOD (GrB_Monoid_new_UINT16_(&M, add, (uint16_t) 0xFFFF)) ; break ;
277 case GB_UINT32_code : METHOD (GrB_Monoid_new_UINT32_(&M, add, (uint32_t) 0xFFFFFFFF)) ; break ;
278 case GB_UINT64_code : METHOD (GrB_Monoid_new_UINT64_(&M, add, (uint64_t) 0xFFFFFFFFFFFFFFFF)) ; break ;
279 default:
280 mexWarnMsgIdAndTxt ("GB:warn", "invalid monoid for (BXNOR)") ;
281 return (false) ;
282 }
283 break ;
284
285 default:
286 mexWarnMsgIdAndTxt ("GB:warn", "unsupported add operator") ;
287 return (false) ;
288 }
289
290 ASSERT_MONOID_OK (M, "monoid", GB0) ;
291 (*handle) = M ;
292 return (true) ;
293 }
294
295