1 //------------------------------------------------------------------------------
2 // GraphBLAS/Demo/Source/usercomplex.c:  complex numbers as a user-defined type
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 #include "GraphBLAS.h"
11 #undef GB_PUBLIC
12 #define GB_LIBRARY
13 #include "graphblas_demos.h"
14 
15 #if defined __INTEL_COMPILER
16 #pragma warning (disable: 58 167 144 161 177 181 186 188 589 593 869 981 1418 1419 1572 1599 2259 2282 2557 2547 3280 )
17 #elif defined __GNUC__
18 #pragma GCC diagnostic ignored "-Wunused-parameter"
19 #if !defined ( __cplusplus )
20 #pragma GCC diagnostic ignored "-Wincompatible-pointer-types"
21 #endif
22 #endif
23 
24 GrB_BinaryOp Complex_first = NULL, Complex_second = NULL, Complex_min = NULL,
25              Complex_max   = NULL, Complex_plus   = NULL, Complex_minus = NULL,
26              Complex_times = NULL, Complex_div    = NULL, Complex_rminus = NULL,
27              Complex_rdiv  = NULL, Complex_pair   = NULL ;
28 
29 GrB_BinaryOp Complex_iseq = NULL, Complex_isne = NULL,
30              Complex_isgt = NULL, Complex_islt = NULL,
31              Complex_isge = NULL, Complex_isle = NULL ;
32 
33 GrB_BinaryOp Complex_or = NULL, Complex_and = NULL, Complex_xor = NULL ;
34 
35 GrB_BinaryOp Complex_eq = NULL, Complex_ne = NULL,
36              Complex_gt = NULL, Complex_lt = NULL,
37              Complex_ge = NULL, Complex_le = NULL ;
38 
39 GrB_BinaryOp Complex_complex = NULL ;
40 
41 GrB_UnaryOp  Complex_identity = NULL, Complex_ainv = NULL, Complex_minv = NULL,
42              Complex_not = NULL,      Complex_conj = NULL,
43              Complex_one = NULL,      Complex_abs  = NULL ;
44 
45 GrB_UnaryOp Complex_real = NULL, Complex_imag = NULL,
46             Complex_cabs = NULL, Complex_angle = NULL ;
47 
48 GrB_UnaryOp Complex_complex_real = NULL, Complex_complex_imag = NULL ;
49 
50 GrB_Type Complex = NULL ;
51 GrB_Monoid   Complex_plus_monoid = NULL, Complex_times_monoid = NULL ;
52 GrB_Semiring Complex_plus_times = NULL ;
53 
54 #define ONE  GxB_CMPLX(1,0)
55 #define ZERO GxB_CMPLX(0,0)
56 #define C    GxB_FC64_t
57 
58 #define X *x
59 #define Y *y
60 #define Z *z
61 
62 #define T ONE
63 #define F ZERO
64 #define BOOL(X) (creal (X) != 0 || cimag (X) != 0)
65 
66 //------------------------------------------------------------------------------
67 // binary functions, z=f(x,y), where CxC -> C
68 //------------------------------------------------------------------------------
69 
70 #if GxB_STDC_VERSION >= 201112L
complex_first(C Z,const C X,const C Y)71 GB_PUBLIC void complex_first  (C Z, const C X, const C Y) { Z = X ; }
complex_second(C Z,const C X,const C Y)72 GB_PUBLIC void complex_second (C Z, const C X, const C Y) { Z = Y ; }
complex_pair(C Z,const C X,const C Y)73 GB_PUBLIC void complex_pair   (C Z, const C X, const C Y) { Z = ONE ; }
complex_plus(C Z,const C X,const C Y)74 GB_PUBLIC void complex_plus   (C Z, const C X, const C Y) { Z = X + Y ; }
complex_minus(C Z,const C X,const C Y)75 GB_PUBLIC void complex_minus  (C Z, const C X, const C Y) { Z = X - Y ; }
complex_rminus(C Z,const C X,const C Y)76 GB_PUBLIC void complex_rminus (C Z, const C X, const C Y) { Z = Y - X ; }
complex_times(C Z,const C X,const C Y)77 GB_PUBLIC void complex_times  (C Z, const C X, const C Y) { Z = X * Y ; }
complex_div(C Z,const C X,const C Y)78 GB_PUBLIC void complex_div    (C Z, const C X, const C Y) { Z = X / Y ; }
complex_rdiv(C Z,const C X,const C Y)79 GB_PUBLIC void complex_rdiv   (C Z, const C X, const C Y) { Z = Y / X ; }
80 #endif
81 
82 GB_PUBLIC
complex_min(C Z,const C X,const C Y)83 void complex_min (C Z, const C X, const C Y)
84 {
85     // min (x,y): complex number with smallest magnitude.  If tied, select the
86     // one with the smallest phase angle (same as MATLAB definition).
87     // No special cases for NaNs.
88     double absx = cabs (X) ;
89     double absy = cabs (Y) ;
90     if (absx < absy)
91     {
92         Z = X ;
93     }
94     else if (absx > absy)
95     {
96         Z = Y ;
97     }
98     else
99     {
100         if (carg (X) < carg (Y))
101         {
102             Z = X ;
103         }
104         else
105         {
106             Z = Y ;
107         }
108     }
109 }
110 
111 GB_PUBLIC
complex_max(C Z,const C X,const C Y)112 void complex_max (C Z, const C X, const C Y)
113 {
114     // max (x,y): complex number with largest magnitude.  If tied, select the
115     // one with the largest phase angle (same as MATLAB definition).
116     // No special cases for NaNs.
117     double absx = cabs (X) ;
118     double absy = cabs (Y) ;
119     if (absx > absy)
120     {
121         Z = X ;
122     }
123     else if (absx < absy)
124     {
125         Z = Y ;
126     }
127     else
128     {
129         if (carg (X) > carg (Y))
130         {
131             Z = X ;
132         }
133         else
134         {
135             Z = Y ;
136         }
137     }
138 }
139 
140 //------------------------------------------------------------------------------
141 // 6 binary functions, z=f(x,y), where CxC -> C ; (1,0) = true, (0,0) = false
142 //------------------------------------------------------------------------------
143 
144 // inequality operators follow the MATLAB convention
145 
146 #if GxB_STDC_VERSION >= 201112L
147 GB_PUBLIC
complex_iseq(C Z,const C X,const C Y)148 void complex_iseq (C Z, const C X, const C Y)
149 {
150     Z = (creal (X) == creal (Y) && cimag (X) == cimag (Y)) ? T : F ;
151 }
152 
153 GB_PUBLIC
complex_isne(C Z,const C X,const C Y)154 void complex_isne (C Z, const C X, const C Y)
155 {
156     Z = (creal (X) != creal (Y) || cimag (X) != cimag (Y)) ? T : F ;
157 }
158 #endif
159 
160 GB_PUBLIC
complex_isgt(C Z,const C X,const C Y)161 void complex_isgt (C Z, const C X, const C Y)
162 {
163     Z = (creal (X) > creal (Y)) ? T : F ;
164 }
165 
166 GB_PUBLIC
complex_islt(C Z,const C X,const C Y)167 void complex_islt (C Z, const C X, const C Y)
168 {
169     Z = (creal (X) < creal (Y)) ? T : F ;
170 }
171 GB_PUBLIC
complex_isge(C Z,const C X,const C Y)172 void complex_isge (C Z, const C X, const C Y)
173 {
174     Z = (creal (X) >= creal (Y)) ? T : F ;
175 }
176 GB_PUBLIC
complex_isle(C Z,const C X,const C Y)177 void complex_isle (C Z, const C X, const C Y)
178 {
179     Z = (creal (X) <= creal (Y)) ? T : F ;
180 }
181 
182 //------------------------------------------------------------------------------
183 // binary boolean functions, z=f(x,y), where CxC -> C
184 //------------------------------------------------------------------------------
185 
186 GB_PUBLIC
complex_or(C Z,const C X,const C Y)187 void complex_or (C Z, const C X, const C Y)
188 {
189     Z = (BOOL (X) || BOOL (Y)) ? T : F ;
190 }
191 
192 GB_PUBLIC
complex_and(C Z,const C X,const C Y)193 void complex_and (C Z, const C X, const C Y)
194 {
195     Z = (BOOL (X) && BOOL (Y)) ? T : F ;
196 }
197 
198 GB_PUBLIC
complex_xor(C Z,const C X,const C Y)199 void complex_xor (C Z, const C X, const C Y)
200 {
201     Z = (BOOL (X) != BOOL (Y)) ? T : F ;
202 }
203 
204 //------------------------------------------------------------------------------
205 // 6 binary functions, z=f(x,y), where CxC -> bool
206 //------------------------------------------------------------------------------
207 
208 // inequality operators follow the MATLAB convention
209 
210 #if GxB_STDC_VERSION >= 201112L
211 GB_PUBLIC
complex_eq(bool Z,const C X,const C Y)212 void complex_eq (bool Z, const C X, const C Y)
213 {
214     Z = (creal (X) == creal (Y) && cimag (X) == cimag (Y)) ;
215 }
216 
217 GB_PUBLIC
complex_ne(bool Z,const C X,const C Y)218 void complex_ne (bool Z, const C X, const C Y)
219 {
220     Z = (creal (X) != creal (Y) || cimag (X) != cimag (Y)) ;
221 }
222 #endif
223 
224 GB_PUBLIC
complex_gt(bool Z,const C X,const C Y)225 void complex_gt (bool Z, const C X, const C Y)
226 {
227     Z = (creal (X) > creal (Y)) ;
228 }
229 
230 GB_PUBLIC
complex_lt(bool Z,const C X,const C Y)231 void complex_lt (bool Z, const C X, const C Y)
232 {
233     Z = (creal (X) < creal (Y)) ;
234 }
235 
236 GB_PUBLIC
complex_ge(bool Z,const C X,const C Y)237 void complex_ge (bool Z, const C X, const C Y)
238 {
239     Z = (creal (X) >= creal (Y)) ;
240 }
241 
242 GB_PUBLIC
complex_le(bool Z,const C X,const C Y)243 void complex_le (bool Z, const C X, const C Y)
244 {
245     Z = (creal (X) <= creal (Y)) ;
246 }
247 
248 //------------------------------------------------------------------------------
249 // binary functions, z=f(x,y), where double x double -> complex
250 //------------------------------------------------------------------------------
251 
252 #if GxB_STDC_VERSION >= 201112L
253 GB_PUBLIC
complex_complex(C Z,const double X,const double Y)254 void complex_complex (C Z, const double X, const double Y)
255 {
256     Z = GxB_CMPLX (X,Y) ;
257 }
258 #endif
259 
260 //------------------------------------------------------------------------------
261 // unary functions, z=f(x) where C -> C
262 //------------------------------------------------------------------------------
263 
264 #if GxB_STDC_VERSION >= 201112L
265 GB_PUBLIC
complex_one(C Z,const C X)266 void complex_one      (C Z, const C X) { Z =      ONE ; }
267 GB_PUBLIC
complex_identity(C Z,const C X)268 void complex_identity (C Z, const C X) { Z =       X  ; }
269 GB_PUBLIC
complex_ainv(C Z,const C X)270 void complex_ainv     (C Z, const C X) { Z =      -X  ; }
271 GB_PUBLIC
complex_minv(C Z,const C X)272 void complex_minv     (C Z, const C X) { Z =  1. / X  ; }
273 GB_PUBLIC
complex_conj(C Z,const C X)274 void complex_conj     (C Z, const C X) { Z = conj (X) ; }
275 #endif
276 
277 GB_PUBLIC
complex_abs(C Z,const C X)278 void complex_abs      (C Z, const C X) { Z = GxB_CMPLX (cabs (X), 0) ; }
279 GB_PUBLIC
complex_not(C Z,const C X)280 void complex_not      (C Z, const C X) { Z = BOOL (X) ? F : T ; }
281 
282 //------------------------------------------------------------------------------
283 // unary functions, z=f(x) where C -> double
284 //------------------------------------------------------------------------------
285 
286 #if GxB_STDC_VERSION >= 201112L
287 GB_PUBLIC
complex_real(double Z,const C X)288 void complex_real  (double Z, const C X) { Z = creal (X) ; }
289 GB_PUBLIC
complex_imag(double Z,const C X)290 void complex_imag  (double Z, const C X) { Z = cimag (X) ; }
291 GB_PUBLIC
complex_cabs(double Z,const C X)292 void complex_cabs  (double Z, const C X) { Z = cabs  (X) ; }
293 GB_PUBLIC
complex_angle(double Z,const C X)294 void complex_angle (double Z, const C X) { Z = carg  (X) ; }
295 #endif
296 
297 //------------------------------------------------------------------------------
298 // unary functions, z=f(x) where double -> C
299 //------------------------------------------------------------------------------
300 
301 GB_PUBLIC
complex_complex_real(C Z,const double X)302 void complex_complex_real (C Z, const double X) { Z = GxB_CMPLX (X, 0) ; }
303 GB_PUBLIC
complex_complex_imag(C Z,const double X)304 void complex_complex_imag (C Z, const double X) { Z = GxB_CMPLX (0, X) ; }
305 
306 //------------------------------------------------------------------------------
307 // macro to check if a method fails
308 //------------------------------------------------------------------------------
309 
310 #undef OK
311 #define OK(method)              \
312     info = method ;             \
313     if (info != GrB_SUCCESS)    \
314     {                           \
315         Complex_finalize ( ) ;  \
316         return (info) ;         \
317     }
318 
319 //------------------------------------------------------------------------------
320 // Complex_init: create the complex type, operators, monoids, and semiring
321 //------------------------------------------------------------------------------
322 
323 #undef C
324 #undef D
325 #define C Complex
326 #define D GrB_FP64
327 
328 #define U (GxB_unary_function)
329 #define B (GxB_binary_function)
330 
331 GB_PUBLIC
Complex_init(bool builtin_complex)332 GrB_Info Complex_init (bool builtin_complex)
333 {
334 
335     GrB_Info info ;
336 
337 #if GxB_STDC_VERSION < 201112L
338     // the Complex type requires the ANSI C11 "double complex" type
339     builtin_complex = true ;
340 #endif
341 
342     //--------------------------------------------------------------------------
343     // create the Complex type, or set to GxB_FC64
344     //--------------------------------------------------------------------------
345 
346     if (builtin_complex)
347     {
348         // use the built-in type
349         Complex = GxB_FC64 ;
350     }
351     else
352     {
353         // create the user-defined type
354         #if GxB_STDC_VERSION >= 201112L
355         OK (GrB_Type_new (&Complex, sizeof (GxB_FC64_t))) ;
356         #endif
357     }
358 
359     //--------------------------------------------------------------------------
360     // create the Complex binary operators, CxC->C
361     //--------------------------------------------------------------------------
362 
363     if (builtin_complex)
364     {
365         // use the built-in versions
366         Complex_first  = GxB_FIRST_FC64 ;
367         Complex_second = GxB_SECOND_FC64 ;
368         Complex_pair   = GxB_PAIR_FC64 ;
369         Complex_plus   = GxB_PLUS_FC64 ;
370         Complex_minus  = GxB_MINUS_FC64 ;
371         Complex_rminus = GxB_RMINUS_FC64 ;
372         Complex_times  = GxB_TIMES_FC64 ;
373         Complex_div    = GxB_DIV_FC64 ;
374         Complex_rdiv   = GxB_RDIV_FC64 ;
375     }
376     else
377     {
378         // create user-defined versions
379         #if GxB_STDC_VERSION >= 201112L
380         OK (GrB_BinaryOp_new (&Complex_first  , B complex_first  , C, C, C)) ;
381         OK (GrB_BinaryOp_new (&Complex_second , B complex_second , C, C, C)) ;
382         OK (GrB_BinaryOp_new (&Complex_pair   , B complex_pair   , C, C, C)) ;
383         OK (GrB_BinaryOp_new (&Complex_plus   , B complex_plus   , C, C, C)) ;
384         OK (GrB_BinaryOp_new (&Complex_minus  , B complex_minus  , C, C, C)) ;
385         OK (GrB_BinaryOp_new (&Complex_rminus , B complex_rminus , C, C, C)) ;
386         OK (GrB_BinaryOp_new (&Complex_times  , B complex_times  , C, C, C)) ;
387         OK (GrB_BinaryOp_new (&Complex_div    , B complex_div    , C, C, C)) ;
388         OK (GrB_BinaryOp_new (&Complex_rdiv   , B complex_rdiv   , C, C, C)) ;
389         #endif
390     }
391 
392     // these are not built-in
393     OK (GrB_BinaryOp_new (&Complex_min    , B complex_min    , C, C, C)) ;
394     OK (GrB_BinaryOp_new (&Complex_max    , B complex_max    , C, C, C)) ;
395 
396     //--------------------------------------------------------------------------
397     // create the Complex binary comparison operators, CxC -> C
398     //--------------------------------------------------------------------------
399 
400     if (builtin_complex)
401     {
402         // use the built-in versions
403         Complex_iseq = GxB_ISEQ_FC64 ;
404         Complex_isne = GxB_ISNE_FC64 ;
405     }
406     else
407     {
408         // create user-defined versions
409         #if GxB_STDC_VERSION >= 201112L
410         OK (GrB_BinaryOp_new (&Complex_iseq , B complex_iseq ,  C, C, C)) ;
411         OK (GrB_BinaryOp_new (&Complex_isne , B complex_isne ,  C, C, C)) ;
412         #endif
413     }
414 
415     // these are not built-in
416     OK (GrB_BinaryOp_new (&Complex_isgt , B complex_isgt ,  C, C, C)) ;
417     OK (GrB_BinaryOp_new (&Complex_islt , B complex_islt ,  C, C, C)) ;
418     OK (GrB_BinaryOp_new (&Complex_isge , B complex_isge ,  C, C, C)) ;
419     OK (GrB_BinaryOp_new (&Complex_isle , B complex_isle ,  C, C, C)) ;
420 
421     //--------------------------------------------------------------------------
422     // create the Complex boolean operators, CxC -> C
423     //--------------------------------------------------------------------------
424 
425     // these are not built-in
426     OK (GrB_BinaryOp_new (&Complex_or  , B complex_or  ,  C, C, C)) ;
427     OK (GrB_BinaryOp_new (&Complex_and , B complex_and ,  C, C, C)) ;
428     OK (GrB_BinaryOp_new (&Complex_xor , B complex_xor ,  C, C, C)) ;
429 
430     //--------------------------------------------------------------------------
431     // create the Complex binary operators, CxC -> bool
432     //--------------------------------------------------------------------------
433 
434     if (builtin_complex)
435     {
436         // use the built-in versions
437         Complex_eq = GxB_EQ_FC64 ;
438         Complex_ne = GxB_NE_FC64 ;
439     }
440     else
441     {
442         // create user-defined versions
443         #if GxB_STDC_VERSION >= 201112L
444         OK (GrB_BinaryOp_new (&Complex_eq , B complex_eq ,  GrB_BOOL, C, C)) ;
445         OK (GrB_BinaryOp_new (&Complex_ne , B complex_ne ,  GrB_BOOL, C, C)) ;
446         #endif
447     }
448 
449     // these are not built-in
450     OK (GrB_BinaryOp_new (&Complex_gt , B complex_gt ,  GrB_BOOL, C, C)) ;
451     OK (GrB_BinaryOp_new (&Complex_lt , B complex_lt ,  GrB_BOOL, C, C)) ;
452     OK (GrB_BinaryOp_new (&Complex_ge , B complex_ge ,  GrB_BOOL, C, C)) ;
453     OK (GrB_BinaryOp_new (&Complex_le , B complex_le ,  GrB_BOOL, C, C)) ;
454 
455     //--------------------------------------------------------------------------
456     // create the Complex binary operator, double x double -> C
457     //--------------------------------------------------------------------------
458 
459     if (builtin_complex)
460     {
461         // use the built-in versions
462         Complex_complex = GxB_CMPLX_FP64 ;
463     }
464     else
465     {
466         // create user-defined versions
467         #if GxB_STDC_VERSION >= 201112L
468         OK (GrB_BinaryOp_new (&Complex_complex, B complex_complex, C, D, D)) ;
469         #endif
470     }
471 
472     //--------------------------------------------------------------------------
473     // create the Complex unary operators, C->C
474     //--------------------------------------------------------------------------
475 
476     if (builtin_complex)
477     {
478         // use the built-in versions
479         Complex_one      = GxB_ONE_FC64 ;
480         Complex_identity = GxB_IDENTITY_FC64 ;
481         Complex_ainv     = GxB_AINV_FC64 ;
482         Complex_minv     = GxB_MINV_FC64 ;
483         Complex_conj     = GxB_CONJ_FC64 ;
484     }
485     else
486     {
487         // create user-defined versions
488         #if GxB_STDC_VERSION >= 201112L
489         OK (GrB_UnaryOp_new (&Complex_one     , U complex_one     , C, C)) ;
490         OK (GrB_UnaryOp_new (&Complex_identity, U complex_identity, C, C)) ;
491         OK (GrB_UnaryOp_new (&Complex_ainv    , U complex_ainv    , C, C)) ;
492         OK (GrB_UnaryOp_new (&Complex_minv    , U complex_minv    , C, C)) ;
493         OK (GrB_UnaryOp_new (&Complex_conj    , U complex_conj    , C, C)) ;
494         #endif
495     }
496 
497     // these are not built-in
498     OK (GrB_UnaryOp_new (&Complex_abs     , U complex_abs     , C, C)) ;
499     OK (GrB_UnaryOp_new (&Complex_not     , U complex_not     , C, C)) ;
500 
501     //--------------------------------------------------------------------------
502     // create the unary functions, C -> double
503     //--------------------------------------------------------------------------
504 
505     if (builtin_complex)
506     {
507         // use the built-in versions
508         Complex_real  = GxB_CREAL_FC64 ;
509         Complex_imag  = GxB_CIMAG_FC64 ;
510         Complex_cabs  = GxB_ABS_FC64 ;
511         Complex_angle = GxB_CARG_FC64 ;
512     }
513     else
514     {
515         // create user-defined versions
516         #if GxB_STDC_VERSION >= 201112L
517         OK (GrB_UnaryOp_new (&Complex_real  , U complex_real  , D, C)) ;
518         OK (GrB_UnaryOp_new (&Complex_imag  , U complex_imag  , D, C)) ;
519         OK (GrB_UnaryOp_new (&Complex_cabs  , U complex_cabs  , D, C)) ;
520         OK (GrB_UnaryOp_new (&Complex_angle , U complex_angle , D, C)) ;
521         #endif
522     }
523 
524     //--------------------------------------------------------------------------
525     // create the unary functions, double -> C
526     //--------------------------------------------------------------------------
527 
528     // these are not built-in
529     OK (GrB_UnaryOp_new (&Complex_complex_real, U complex_complex_real, C, D)) ;
530     OK (GrB_UnaryOp_new (&Complex_complex_imag, U complex_complex_imag, C, D)) ;
531 
532     //--------------------------------------------------------------------------
533     // create the Complex monoids
534     //--------------------------------------------------------------------------
535 
536     if (builtin_complex)
537     {
538         // use the built-in versions
539         Complex_plus_monoid  = GxB_PLUS_FC64_MONOID ;
540         Complex_times_monoid = GxB_TIMES_FC64_MONOID ;
541     }
542     else
543     {
544         // create user-defined versions
545         #if GxB_STDC_VERSION >= 201112L
546         double complex C_1 = ONE ;
547         double complex C_0 = ZERO ;
548         OK (GrB_Monoid_new_UDT (&Complex_plus_monoid,  Complex_plus,  &C_0)) ;
549         OK (GrB_Monoid_new_UDT (&Complex_times_monoid, Complex_times, &C_1)) ;
550         #endif
551     }
552 
553     //----------------------------------------------------------------------
554     // create the Complex plus-times semiring
555     //----------------------------------------------------------------------
556 
557     if (builtin_complex)
558     {
559         // use the built-in versions
560         Complex_plus_times = GxB_PLUS_TIMES_FC64 ;
561     }
562     else
563     {
564         // more could be created, but this suffices for testing GraphBLAS
565         OK (GrB_Semiring_new (&Complex_plus_times, Complex_plus_monoid,
566             Complex_times)) ;
567     }
568 
569     return (GrB_SUCCESS) ;
570 }
571 
572 
573 //------------------------------------------------------------------------------
574 // Complex_finalize: free all complex types, operators, monoids, and semiring
575 //------------------------------------------------------------------------------
576 
577 // These may be built-in types and operators.  They are safe to free; the
578 // GrB_*_free functions silently do nothing if asked to free bulit-in objects.
579 
580 GB_PUBLIC
Complex_finalize()581 GrB_Info Complex_finalize ( )
582 {
583 
584     //--------------------------------------------------------------------------
585     // free the Complex plus-times semiring
586     //--------------------------------------------------------------------------
587 
588     GrB_Semiring_free (&Complex_plus_times) ;
589 
590     //--------------------------------------------------------------------------
591     // free the Complex monoids
592     //--------------------------------------------------------------------------
593 
594     GrB_Monoid_free (&Complex_plus_monoid ) ;
595     GrB_Monoid_free (&Complex_times_monoid) ;
596 
597     //--------------------------------------------------------------------------
598     // free the Complex binary operators, CxC->C
599     //--------------------------------------------------------------------------
600 
601     GrB_BinaryOp_free (&Complex_first ) ;
602     GrB_BinaryOp_free (&Complex_second) ;
603     GrB_BinaryOp_free (&Complex_pair  ) ;
604     GrB_BinaryOp_free (&Complex_min   ) ;
605     GrB_BinaryOp_free (&Complex_max   ) ;
606     GrB_BinaryOp_free (&Complex_plus  ) ;
607     GrB_BinaryOp_free (&Complex_minus ) ;
608     GrB_BinaryOp_free (&Complex_rminus) ;
609     GrB_BinaryOp_free (&Complex_times ) ;
610     GrB_BinaryOp_free (&Complex_div   ) ;
611     GrB_BinaryOp_free (&Complex_rdiv  ) ;
612 
613     GrB_BinaryOp_free (&Complex_iseq) ;
614     GrB_BinaryOp_free (&Complex_isne) ;
615     GrB_BinaryOp_free (&Complex_isgt) ;
616     GrB_BinaryOp_free (&Complex_islt) ;
617     GrB_BinaryOp_free (&Complex_isge) ;
618     GrB_BinaryOp_free (&Complex_isle) ;
619 
620     GrB_BinaryOp_free (&Complex_or) ;
621     GrB_BinaryOp_free (&Complex_and) ;
622     GrB_BinaryOp_free (&Complex_xor) ;
623 
624     //--------------------------------------------------------------------------
625     // free the Complex binary operators, CxC -> bool
626     //--------------------------------------------------------------------------
627 
628     GrB_BinaryOp_free (&Complex_eq) ;
629     GrB_BinaryOp_free (&Complex_ne) ;
630     GrB_BinaryOp_free (&Complex_gt) ;
631     GrB_BinaryOp_free (&Complex_lt) ;
632     GrB_BinaryOp_free (&Complex_ge) ;
633     GrB_BinaryOp_free (&Complex_le) ;
634 
635     //--------------------------------------------------------------------------
636     // free the Complex binary operator, double x double -> complex
637     //--------------------------------------------------------------------------
638 
639     GrB_BinaryOp_free (&Complex_complex) ;
640 
641     //--------------------------------------------------------------------------
642     // free the Complex unary operators, C->C
643     //--------------------------------------------------------------------------
644 
645     GrB_UnaryOp_free (&Complex_one     ) ;
646     GrB_UnaryOp_free (&Complex_identity) ;
647     GrB_UnaryOp_free (&Complex_ainv    ) ;
648     GrB_UnaryOp_free (&Complex_abs     ) ;
649     GrB_UnaryOp_free (&Complex_minv    ) ;
650     GrB_UnaryOp_free (&Complex_not     ) ;
651     GrB_UnaryOp_free (&Complex_conj    ) ;
652 
653     //--------------------------------------------------------------------------
654     // free the unary functions, C -> double
655     //--------------------------------------------------------------------------
656 
657     GrB_UnaryOp_free (&Complex_real ) ;
658     GrB_UnaryOp_free (&Complex_imag ) ;
659     GrB_UnaryOp_free (&Complex_cabs ) ;
660     GrB_UnaryOp_free (&Complex_angle) ;
661 
662     //--------------------------------------------------------------------------
663     // free the unary functions, double -> C
664     //--------------------------------------------------------------------------
665 
666     GrB_UnaryOp_free (&Complex_complex_real) ;
667     GrB_UnaryOp_free (&Complex_complex_imag) ;
668 
669     //--------------------------------------------------------------------------
670     // free the Complex type
671     //--------------------------------------------------------------------------
672 
673     GrB_Type_free (&Complex) ;
674 
675     return (GrB_SUCCESS) ;
676 }
677 
678