1 //------------------------------------------------------------------------------
2 // GB_math.h: definitions for complex types, and mathematical operators
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 #ifndef GB_MATH_H
11 #define GB_MATH_H
12 
13 //------------------------------------------------------------------------------
14 // complex macros
15 //------------------------------------------------------------------------------
16 
17 #if ( _MSC_VER && !__INTEL_COMPILER )
18 
19     //--------------------------------------------------------------------------
20     // Microsoft Visual Studio compiler with its own complex type
21     //--------------------------------------------------------------------------
22 
23     // complex-complex multiply: z = x*y where both x and y are complex
24     #define GB_FC32_mul(x,y) (_FCmulcc (x, y))
25     #define GB_FC64_mul(x,y) ( _Cmulcc (x, y))
26 
27     // complex-real multiply: z = x*y where x is complex and y is real
28     #define GB_FC32_rmul(x,y) (_FCmulcr (x, y))
29     #define GB_FC64_rmul(x,y) ( _Cmulcr (x, y))
30 
31     // complex-complex addition: z = x+y where both x and y are complex
32     #define GB_FC32_add(x,y) \
33         GxB_CMPLXF (crealf (x) + crealf (y), cimagf (x) + cimagf (y))
34     #define GB_FC64_add(x,y) \
35         GxB_CMPLX  (creal  (x) + creal  (y), cimag  (x) + cimag  (y))
36 
37     // complex-complex subtraction: z = x-y where both x and y are complex
38     #define GB_FC32_minus(x,y) \
39         GxB_CMPLXF (crealf (x) - crealf (y), cimagf (x) - cimagf (y))
40     #define GB_FC64_minus(x,y) \
41         GxB_CMPLX  (creal  (x) - creal  (y), cimag  (x) - cimag  (y))
42 
43     // complex negation: z = -x
44     #define GB_FC32_ainv(x) GxB_CMPLXF (-crealf (x), -cimagf (x))
45     #define GB_FC64_ainv(x) GxB_CMPLX (-creal  (x), -cimag  (x))
46 
47 #else
48 
49     //--------------------------------------------------------------------------
50     // native complex type support
51     //--------------------------------------------------------------------------
52 
53     // complex-complex multiply: z = x*y where both x and y are complex
54     #define GB_FC32_mul(x,y) ((x) * (y))
55     #define GB_FC64_mul(x,y) ((x) * (y))
56 
57     // complex-real multiply: z = x*y where x is complex and y is real
58     #define GB_FC32_rmul(x,y) ((x) * (y))
59     #define GB_FC64_rmul(x,y) ((x) * (y))
60 
61     // complex-complex addition: z = x+y where both x and y are complex
62     #define GB_FC32_add(x,y) ((x) + (y))
63     #define GB_FC64_add(x,y) ((x) + (y))
64 
65     // complex-complex subtraction: z = x-y where both x and y are complex
66     #define GB_FC32_minus(x,y) ((x) - (y))
67     #define GB_FC64_minus(x,y) ((x) - (y))
68 
69     // complex negation
70     #define GB_FC32_ainv(x) (-(x))
71     #define GB_FC64_ainv(x) (-(x))
72 
73 #endif
74 
75 // complex inverse: z = 1/x
76 #define GB_FC32_minv(x) GB_FC32_div (GxB_CMPLXF (1,0), x)
77 #define GB_FC64_minv(x) GB_FC64_div (GxB_CMPLX (1,0), x)
78 
79 // complex comparisons
80 #define GB_FC32_eq(x,y) ((crealf(x) == crealf(y)) && (cimagf(x) == cimagf(y)))
81 #define GB_FC64_eq(x,y) ((creal (x) == creal (y)) && (cimag (x) == cimag (y)))
82 
83 #define GB_FC32_ne(x,y) ((crealf(x) != crealf(y)) || (cimagf(x) != cimagf(y)))
84 #define GB_FC64_ne(x,y) ((creal (x) != creal (y)) || (cimag (x) != cimag (y)))
85 
86 #define GB_FC32_iseq(x,y) GxB_CMPLXF ((float)  GB_FC32_eq (x,y), 0)
87 #define GB_FC64_iseq(x,y) GxB_CMPLX  ((double) GB_FC64_eq (x,y), 0)
88 
89 #define GB_FC32_isne(x,y) GxB_CMPLXF ((float)  GB_FC32_ne (x,y), 0)
90 #define GB_FC64_isne(x,y) GxB_CMPLX  ((double) GB_FC64_ne (x,y), 0)
91 
92 #define GB_FC32_eq0(x) ((crealf(x) == 0) && (cimagf(x) == 0))
93 #define GB_FC64_eq0(x) ((creal (x) == 0) && (cimag (x) == 0))
94 
95 #define GB_FC32_ne0(x) ((crealf(x) != 0) || (cimagf(x) != 0))
96 #define GB_FC64_ne0(x) ((creal (x) != 0) || (cimag (x) != 0))
97 
98 //------------------------------------------------------------------------------
99 // min, max, and NaN handling
100 //------------------------------------------------------------------------------
101 
102 // For floating-point computations, SuiteSparse:GraphBLAS relies on the IEEE
103 // 754 standard for the basic operations (+ - / *).  Comparison operators also
104 // work as they should; any comparison with NaN is always false, even
105 // eq(NaN,NaN) is false.  This follows the IEEE 754 standard.
106 
107 // For integer MIN and MAX, SuiteSparse:GraphBLAS relies on one comparison:
108 
109 // z = min(x,y) = (x < y) ? x : y
110 // z = max(x,y) = (x > y) ? x : y
111 
112 // However, this is not suitable for floating-point x and y.  Comparisons with
113 // NaN always return false, so if either x or y are NaN, then z = y, for both
114 // min(x,y) and max(x,y).  In MATLAB, min(3,NaN), min(NaN,3), max(3,NaN), and
115 // max(NaN,3) are all 3, which is another interpretation.  The MATLAB min and
116 // max functions have a 3rd argument that specifies how NaNs are handled:
117 // 'omitnan' (default) and 'includenan'.  In SuiteSparse:GraphBLAS 2.2.* and
118 // earlier, the min and max functions were the same as 'includenan' in MATLAB.
119 // As of version 2.3 and later, they are 'omitnan', to facilitate the terminal
120 // exit of the MIN and MAX monoids for floating-point values.
121 
122 // The ANSI C11 fmin, fminf, fmax, and fmaxf functions have the 'omitnan'
123 // behavior.  These are used in SuiteSparse:GraphBLAS v2.3.0 and later.
124 
125 // Below is a complete comparison of MATLAB and GraphBLAS.  Both tables are the
126 // results for both min and max (they return the same results in these cases):
127 
128 //   x    y  MATLAB    MATLAB   (x<y)?x:y   SuiteSparse:    SuiteSparse:    ANSI
129 //           omitnan includenan             GraphBLAS       GraphBLAS       fmin
130 //                                          v 2.2.x         this version
131 //
132 //   3    3     3        3          3        3              3               3
133 //   3   NaN    3       NaN        NaN      NaN             3               3
134 //  NaN   3     3       NaN         3       NaN             3               3
135 //  NaN  NaN   NaN      NaN        NaN      NaN             NaN             NaN
136 
137 // for integers only:
138 #define GB_IABS(x) (((x) >= 0) ? (x) : (-(x)))
139 
140 // suitable for integers, and non-NaN floating point:
141 #include "GB_imin.h"
142 
143 // ceiling of a/b for two integers a and b
144 #define GB_ICEIL(a,b) (((a) + (b) - 1) / (b))
145 
146 //------------------------------------------------------------------------------
147 // division by zero
148 //------------------------------------------------------------------------------
149 
150 // Integer division by zero is done the same way it's done in MATLAB.  This
151 // approach allows GraphBLAS to not terminate the user's application on
152 // divide-by-zero, and allows GraphBLAS results to be tested against MATLAB.
153 // To compute X/0: if X is zero, the result is zero (like NaN).  if X is
154 // negative, the result is the negative integer with biggest magnitude (like
155 // -infinity).  if X is positive, the result is the biggest positive integer
156 // (like +infinity).
157 
158 // For places affected by this decision in the code do:
159 // grep "integer division"
160 
161 // Signed and unsigned integer division, z = x/y.  The bits parameter can be 8,
162 // 16, 32, or 64.
163 #define GB_INT_MIN(bits)  INT ## bits ## _MIN
164 #define GB_INT_MAX(bits)  INT ## bits ## _MAX
165 #define GB_UINT_MAX(bits) UINT ## bits ## _MAX
166 
167 // x/y when x and y are signed integers
168 #define GB_IDIV_SIGNED(x,y,bits)                                            \
169 (                                                                           \
170     ((y) == -1) ?                                                           \
171     (                                                                       \
172         /* INT32_MIN/(-1) causes floating point exception; avoid it  */     \
173         -(x)                                                                \
174     )                                                                       \
175     :                                                                       \
176     (                                                                       \
177         ((y) == 0) ?                                                        \
178         (                                                                   \
179             /* x/0 */                                                       \
180             ((x) == 0) ?                                                    \
181             (                                                               \
182                 /* zero divided by zero gives 'Nan' */                      \
183                 0                                                           \
184             )                                                               \
185             :                                                               \
186             (                                                               \
187                 /* x/0 and x is nonzero */                                  \
188                 ((x) < 0) ?                                                 \
189                 (                                                           \
190                     /* x is negative: x/0 gives '-Inf' */                   \
191                     GB_INT_MIN (bits)                                       \
192                 )                                                           \
193                 :                                                           \
194                 (                                                           \
195                     /* x is positive: x/0 gives '+Inf' */                   \
196                     GB_INT_MAX (bits)                                       \
197                 )                                                           \
198             )                                                               \
199         )                                                                   \
200         :                                                                   \
201         (                                                                   \
202             /* normal case for signed integer division */                   \
203             (x) / (y)                                                       \
204         )                                                                   \
205     )                                                                       \
206 )
207 
208 // x/y when x and y are unsigned integers
209 #define GB_IDIV_UNSIGNED(x,y,bits)                                          \
210 (                                                                           \
211     ((y) == 0) ?                                                            \
212     (                                                                       \
213         /* x/0 */                                                           \
214         ((x) == 0) ?                                                        \
215         (                                                                   \
216             /* zero divided by zero gives 'Nan' */                          \
217             0                                                               \
218         )                                                                   \
219         :                                                                   \
220         (                                                                   \
221             /* x is positive: x/0 gives '+Inf' */                           \
222             GB_UINT_MAX (bits)                                              \
223         )                                                                   \
224     )                                                                       \
225     :                                                                       \
226     (                                                                       \
227         /* normal case for unsigned integer division */                     \
228         (x) / (y)                                                           \
229     )                                                                       \
230 )
231 
232 // 1/y when y is a signed integer
233 #define GB_IMINV_SIGNED(y,bits)                                             \
234 (                                                                           \
235     ((y) == -1) ?                                                           \
236     (                                                                       \
237         -1                                                                  \
238     )                                                                       \
239     :                                                                       \
240     (                                                                       \
241         ((y) == 0) ?                                                        \
242         (                                                                   \
243             GB_INT_MAX (bits)                                               \
244         )                                                                   \
245         :                                                                   \
246         (                                                                   \
247             ((y) == 1) ?                                                    \
248             (                                                               \
249                 1                                                           \
250             )                                                               \
251             :                                                               \
252             (                                                               \
253                 0                                                           \
254             )                                                               \
255         )                                                                   \
256     )                                                                       \
257 )
258 
259 // 1/y when y is an unsigned integer
260 #define GB_IMINV_UNSIGNED(y,bits)                                           \
261 (                                                                           \
262     ((y) == 0) ?                                                            \
263     (                                                                       \
264         GB_UINT_MAX (bits)                                                  \
265     )                                                                       \
266     :                                                                       \
267     (                                                                       \
268         ((y) == 1) ?                                                        \
269         (                                                                   \
270             1                                                               \
271         )                                                                   \
272         :                                                                   \
273         (                                                                   \
274             0                                                               \
275         )                                                                   \
276     )                                                                       \
277 )                                                                           \
278 
279 // GraphBLAS includes a built-in GrB_DIV_BOOL operator, so boolean division
280 // must be defined.  There is no MATLAB equivalent since x/y for logical x and
281 // y is not permitted in MATLAB.  ANSI C11 does not provide a definition
282 // either, and dividing by zero (boolean false) will typically terminate an
283 // application.  In this GraphBLAS implementation, boolean division is treated
284 // as if it were int1, where 1/1 = 1, 0/1 = 0, 0/0 = integer NaN = 0, 1/0 =
285 // +infinity = 1.  Thus Z=X/Y is Z=X.  This is arbitrary, but it allows all
286 // operators to work on all types without causing run time exceptions.  It also
287 // means that GrB_DIV(x,y) is the same as GrB_FIRST(x,y) for boolean x and y.
288 // See for example GB_boolean_rename and Template/GB_ops_template.c.
289 // Similarly, GrB_MINV_BOOL, which is 1/x, is simply 'true' for all x.
290 
291 //------------------------------------------------------------------------------
292 // complex division
293 //------------------------------------------------------------------------------
294 
295 // z = x/y where z, x, and y are double complex.  The real and imaginary parts
296 // are passed as separate arguments to this routine.  The NaN case is ignored
297 // for the double relop yr >= yi.  Returns 1 if the denominator is zero, 0
298 // otherwise.
299 //
300 // This uses ACM Algo 116, by R. L. Smith, 1962, which tries to avoid underflow
301 // and overflow.
302 //
303 // z can be the same variable as x or y.
304 //
305 // Note that this function has the same signature as SuiteSparse_divcomplex.
306 
GB_divcomplex(double xr,double xi,double yr,double yi,double * zr,double * zi)307 inline int GB_divcomplex
308 (
309     double xr, double xi,       // real and imaginary parts of x
310     double yr, double yi,       // real and imaginary parts of y
311     double *zr, double *zi      // real and imaginary parts of z
312 )
313 {
314     double tr, ti, r, den ;
315 
316     int yr_class = fpclassify (yr) ;
317     int yi_class = fpclassify (yi) ;
318 
319     if (yi_class == FP_ZERO)
320     {
321         den = yr ;
322         if (xi == 0)
323         {
324             tr = xr / den ;
325             ti = 0 ;
326         }
327         else if (xr == 0)
328         {
329             tr = 0 ;
330             ti = xi / den ;
331         }
332         else
333         {
334             tr = xr / den ;
335             ti = xi / den ;
336         }
337     }
338     else if (yr_class == FP_ZERO)
339     {
340         den = yi ;
341         if (xr == 0)
342         {
343             tr = xi / den ;
344             ti = 0 ;
345         }
346         else if (xi == 0)
347         {
348             tr = 0 ;
349             ti = -xr / den ;
350         }
351         else
352         {
353             tr = xi / den ;
354             ti = -xr / den ;
355         }
356     }
357     else if (yi_class == FP_INFINITE && yr_class == FP_INFINITE)
358     {
359         r = (signbit (yr) == signbit (yi)) ? (1) : (-1) ;
360         den = yr + r * yi ;
361         tr = (xr + xi * r) / den ;
362         ti = (xi - xr * r) / den ;
363     }
364     else if (fabs (yr) >= fabs (yi))
365     {
366         r = yi / yr ;
367         den = yr + r * yi ;
368         tr = (xr + xi * r) / den ;
369         ti = (xi - xr * r) / den ;
370     }
371     else
372     {
373         r = yr / yi ;
374         den = r * yr + yi ;
375         tr = (xr * r + xi) / den ;
376         ti = (xi * r - xr) / den ;
377     }
378     (*zr) = tr ;
379     (*zi) = ti ;
380     return (den == 0) ;
381 }
382 
GB_FC64_div(GxB_FC64_t x,GxB_FC64_t y)383 inline GxB_FC64_t GB_FC64_div (GxB_FC64_t x, GxB_FC64_t y)
384 {
385     double zr, zi ;
386     GB_divcomplex (creal (x), cimag (x), creal (y), cimag (y), &zr, &zi) ;
387     return (GxB_CMPLX (zr, zi)) ;
388 }
389 
GB_FC32_div(GxB_FC32_t x,GxB_FC32_t y)390 inline GxB_FC32_t GB_FC32_div (GxB_FC32_t x, GxB_FC32_t y)
391 {
392     // single complex division: typecast to double complex, do the division,
393     // and then typecast back to single complex
394     double zr, zi ;
395     GB_divcomplex ((double) crealf (x), (double) cimagf (x),
396                    (double) crealf (y), (double) cimagf (y), &zr, &zi) ;
397     return (GxB_CMPLXF ((float) zr, (float) zi)) ;
398 }
399 
400 //------------------------------------------------------------------------------
401 // z = x^y: wrappers for pow, powf, cpow, and cpowf
402 //------------------------------------------------------------------------------
403 
404 // The following rules are used to try to align the results with what MATLAB
405 // computes for x^y:
406 
407 //      if x or y are NaN, then z is NaN
408 //      if y is zero, then z is 1
409 //      if (x and y are complex but with zero imaginary parts, and
410 //          (x >= 0 or if y is an integer, NaN, or Inf)), then z is real
411 //      else use the built-in C library function, z = pow (x,y)
412 
GB_powf(float x,float y)413 inline float GB_powf (float x, float y)
414 {
415     int xr_class = fpclassify (x) ;
416     int yr_class = fpclassify (y) ;
417     if (xr_class == FP_NAN || yr_class == FP_NAN)
418     {
419         // z is nan if either x or y are nan
420         return (NAN) ;
421     }
422     if (yr_class == FP_ZERO)
423     {
424         // z is 1 if y is zero
425         return (1) ;
426     }
427     // otherwise, z = powf (x,y)
428     return (powf (x, y)) ;
429 }
430 
GB_pow(double x,double y)431 inline double GB_pow (double x, double y)
432 {
433     int xr_class = fpclassify (x) ;
434     int yr_class = fpclassify (y) ;
435     if (xr_class == FP_NAN || yr_class == FP_NAN)
436     {
437         // z is nan if either x or y are nan
438         return (NAN) ;
439     }
440     if (yr_class == FP_ZERO)
441     {
442         // z is 1 if y is zero
443         return (1) ;
444     }
445     // otherwise, z = pow (x,y)
446     return (pow (x, y)) ;
447 }
448 
GB_cpowf(GxB_FC32_t x,GxB_FC32_t y)449 inline GxB_FC32_t GB_cpowf (GxB_FC32_t x, GxB_FC32_t y)
450 {
451     float xr = crealf (x) ;
452     float yr = crealf (y) ;
453     int xr_class = fpclassify (xr) ;
454     int yr_class = fpclassify (yr) ;
455     int xi_class = fpclassify (cimagf (x)) ;
456     int yi_class = fpclassify (cimagf (y)) ;
457     if (xi_class == FP_ZERO && yi_class == FP_ZERO)
458     {
459         // both x and y are real; see if z should be real
460         if (xr >= 0 || yr_class == FP_NAN || yr_class == FP_INFINITE ||
461             yr == truncf (yr))
462         {
463             // z is real if x >= 0, or if y is an integer, NaN, or Inf
464             return (GxB_CMPLXF (GB_powf (xr, yr), 0)) ;
465         }
466     }
467     if (xr_class == FP_NAN || xi_class == FP_NAN ||
468         yr_class == FP_NAN || yi_class == FP_NAN)
469     {
470         // z is (nan,nan) if any part of x or y are nan
471         return (GxB_CMPLXF (NAN, NAN)) ;
472     }
473     if (yr_class == FP_ZERO && yi_class == FP_ZERO)
474     {
475         // z is (1,0) if y is (0,0)
476         return (GxB_CMPLXF (1, 0)) ;
477     }
478     return (cpowf (x, y)) ;
479 }
480 
GB_cpow(GxB_FC64_t x,GxB_FC64_t y)481 inline GxB_FC64_t GB_cpow (GxB_FC64_t x, GxB_FC64_t y)
482 {
483     double xr = creal (x) ;
484     double yr = creal (y) ;
485     int xr_class = fpclassify (xr) ;
486     int yr_class = fpclassify (yr) ;
487     int xi_class = fpclassify (cimag (x)) ;
488     int yi_class = fpclassify (cimag (y)) ;
489     if (xi_class == FP_ZERO && yi_class == FP_ZERO)
490     {
491         // both x and y are real; see if z should be real
492         if (xr >= 0 || yr_class == FP_NAN || yr_class == FP_INFINITE ||
493             yr == trunc (yr))
494         {
495             // z is real if x >= 0, or if y is an integer, NaN, or Inf
496             return (GxB_CMPLX (GB_pow (xr, yr), 0)) ;
497         }
498     }
499     if (xr_class == FP_NAN || xi_class == FP_NAN ||
500         yr_class == FP_NAN || yi_class == FP_NAN)
501     {
502         // z is (nan,nan) if any part of x or y are nan
503         return (GxB_CMPLX (NAN, NAN)) ;
504     }
505     if (yr_class == FP_ZERO && yi_class == FP_ZERO)
506     {
507         // z is (1,0) if y is (0,0)
508         return (GxB_CMPLX (1, 0)) ;
509     }
510     return (cpow (x, y)) ;
511 }
512 
GB_pow_int8(int8_t x,int8_t y)513 inline int8_t GB_pow_int8 (int8_t x, int8_t y)
514 {
515     return (GB_cast_to_int8_t (GB_pow ((double) x, (double) y))) ;
516 }
517 
GB_pow_int16(int16_t x,int16_t y)518 inline int16_t GB_pow_int16 (int16_t x, int16_t y)
519 {
520     return (GB_cast_to_int16_t (GB_pow ((double) x, (double) y))) ;
521 }
522 
GB_pow_int32(int32_t x,int32_t y)523 inline int32_t GB_pow_int32 (int32_t x, int32_t y)
524 {
525     return (GB_cast_to_int32_t (GB_pow ((double) x, (double) y))) ;
526 }
527 
GB_pow_int64(int64_t x,int64_t y)528 inline int64_t GB_pow_int64 (int64_t x, int64_t y)
529 {
530     return (GB_cast_to_int64_t (GB_pow ((double) x, (double) y))) ;
531 }
532 
GB_pow_uint8(uint8_t x,uint8_t y)533 inline uint8_t GB_pow_uint8 (uint8_t x, uint8_t y)
534 {
535     return (GB_cast_to_uint8_t (GB_pow ((double) x, (double) y))) ;
536 }
537 
GB_pow_uint16(uint16_t x,uint16_t y)538 inline uint16_t GB_pow_uint16 (uint16_t x, uint16_t y)
539 {
540     return (GB_cast_to_uint16_t (GB_pow ((double) x, (double) y))) ;
541 }
542 
GB_pow_uint32(uint32_t x,uint32_t y)543 inline uint32_t GB_pow_uint32 (uint32_t x, uint32_t y)
544 {
545     return (GB_cast_to_uint32_t (GB_pow ((double) x, (double) y))) ;
546 }
547 
GB_pow_uint64(uint64_t x,uint64_t y)548 inline uint64_t GB_pow_uint64 (uint64_t x, uint64_t y)
549 {
550     return (GB_cast_to_uint64_t (GB_pow ((double) x, (double) y))) ;
551 }
552 
553 //------------------------------------------------------------------------------
554 // frexp for float and double
555 //------------------------------------------------------------------------------
556 
GB_frexpxf(float x)557 inline float GB_frexpxf (float x)
558 {
559     int exp_ignored ;
560     return (frexpf (x, &exp_ignored)) ;
561 }
562 
GB_frexpef(float x)563 inline float GB_frexpef (float x)
564 {
565     int exp ;
566     float mantissa_ignored = frexpf (x, &exp) ;
567     return ((float) exp) ;
568 }
569 
GB_frexpx(double x)570 inline double GB_frexpx (double x)
571 {
572     int exp_ignored ;
573     return (frexp (x, &exp_ignored)) ;
574 }
575 
GB_frexpe(double x)576 inline double GB_frexpe (double x)
577 {
578     int exp ;
579     double mantissa_ignored = frexp (x, &exp) ;
580     return ((double) exp) ;
581 }
582 
583 //------------------------------------------------------------------------------
584 // signum functions
585 //------------------------------------------------------------------------------
586 
GB_signumf(float x)587 inline float GB_signumf (float x)
588 {
589     if (isnan (x)) return (x) ;
590     return ((float) ((x < 0) ? (-1) : ((x > 0) ? 1 : 0))) ;
591 }
592 
GB_signum(double x)593 inline double GB_signum (double x)
594 {
595     if (isnan (x)) return (x) ;
596     return ((double) ((x < 0) ? (-1) : ((x > 0) ? 1 : 0))) ;
597 }
598 
GB_csignumf(GxB_FC32_t x)599 inline GxB_FC32_t GB_csignumf (GxB_FC32_t x)
600 {
601     if (crealf (x) == 0 && cimagf (x) == 0) return (GxB_CMPLXF (0,0)) ;
602     float y = cabsf (x) ;
603     return (GxB_CMPLXF (crealf (x) / y, cimagf (x) / y)) ;
604 }
605 
GB_csignum(GxB_FC64_t x)606 inline GxB_FC64_t GB_csignum (GxB_FC64_t x)
607 {
608     if (creal (x) == 0 && cimag (x) == 0) return (GxB_CMPLX (0,0)) ;
609     double y = cabs (x) ;
610     return (GxB_CMPLX (creal (x) / y, cimag (x) / y)) ;
611 }
612 
613 //------------------------------------------------------------------------------
614 // complex functions
615 //------------------------------------------------------------------------------
616 
617 // The ANSI C11 math.h header defines the ceil, floor, round, trunc,
618 // exp2, expm1, log10, log1pm, or log2 functions for float and double,
619 // but the corresponding functions do not appear in the ANSI C11 complex.h.
620 // These functions are used instead, for float complex and double complex.
621 
622 //------------------------------------------------------------------------------
623 // z = ceil (x) for float complex
624 //------------------------------------------------------------------------------
625 
GB_cceilf(GxB_FC32_t x)626 inline GxB_FC32_t GB_cceilf (GxB_FC32_t x)
627 {
628     return (GxB_CMPLXF (ceilf (crealf (x)), ceilf (cimagf (x)))) ;
629 }
630 
631 //------------------------------------------------------------------------------
632 // z = ceil (x) for double complex
633 //------------------------------------------------------------------------------
634 
GB_cceil(GxB_FC64_t x)635 inline GxB_FC64_t GB_cceil (GxB_FC64_t x)
636 {
637     return (GxB_CMPLX (ceil (creal (x)), ceil (cimag (x)))) ;
638 }
639 
640 //------------------------------------------------------------------------------
641 // z = floor (x) for float complex
642 //------------------------------------------------------------------------------
643 
GB_cfloorf(GxB_FC32_t x)644 inline GxB_FC32_t GB_cfloorf (GxB_FC32_t x)
645 {
646     return (GxB_CMPLXF (floorf (crealf (x)), floorf (cimagf (x)))) ;
647 }
648 
649 //------------------------------------------------------------------------------
650 // z = floor (x) for double complex
651 //------------------------------------------------------------------------------
652 
GB_cfloor(GxB_FC64_t x)653 inline GxB_FC64_t GB_cfloor (GxB_FC64_t x)
654 {
655     return (GxB_CMPLX (floor (creal (x)), floor (cimag (x)))) ;
656 }
657 
658 //------------------------------------------------------------------------------
659 // z = round (x) for float complex
660 //------------------------------------------------------------------------------
661 
GB_croundf(GxB_FC32_t x)662 inline GxB_FC32_t GB_croundf (GxB_FC32_t x)
663 {
664     return (GxB_CMPLXF (roundf (crealf (x)), roundf (cimagf (x)))) ;
665 }
666 
667 //------------------------------------------------------------------------------
668 // z = round (x) for double complex
669 //------------------------------------------------------------------------------
670 
GB_cround(GxB_FC64_t x)671 inline GxB_FC64_t GB_cround (GxB_FC64_t x)
672 {
673     return (GxB_CMPLX (round (creal (x)), round (cimag (x)))) ;
674 }
675 
676 //------------------------------------------------------------------------------
677 // z = trunc (x) for float complex
678 //------------------------------------------------------------------------------
679 
GB_ctruncf(GxB_FC32_t x)680 inline GxB_FC32_t GB_ctruncf (GxB_FC32_t x)
681 {
682     return (GxB_CMPLXF (truncf (crealf (x)), truncf (cimagf (x)))) ;
683 }
684 
685 //------------------------------------------------------------------------------
686 // z = trunc (x) for double complex
687 //------------------------------------------------------------------------------
688 
GB_ctrunc(GxB_FC64_t x)689 inline GxB_FC64_t GB_ctrunc (GxB_FC64_t x)
690 {
691     return (GxB_CMPLX (trunc (creal (x)), trunc (cimag (x)))) ;
692 }
693 
694 //------------------------------------------------------------------------------
695 // z = exp2 (x) for float complex
696 //------------------------------------------------------------------------------
697 
GB_cexp2f(GxB_FC32_t x)698 inline GxB_FC32_t GB_cexp2f (GxB_FC32_t x)
699 {
700     if (fpclassify (cimagf (x)) == FP_ZERO)
701     {
702         // x is real, use exp2f
703         return (GxB_CMPLXF (exp2f (crealf (x)), 0)) ;
704     }
705     return (GB_cpowf (GxB_CMPLXF (2,0), x)) ;     // z = 2^x
706 }
707 
708 //------------------------------------------------------------------------------
709 // z = exp2 (x) for double complex
710 //------------------------------------------------------------------------------
711 
GB_cexp2(GxB_FC64_t x)712 inline GxB_FC64_t GB_cexp2 (GxB_FC64_t x)
713 {
714     if (fpclassify (cimag (x)) == FP_ZERO)
715     {
716         // x is real, use exp2
717         return (GxB_CMPLX (exp2 (creal (x)), 0)) ;
718     }
719     return (GB_cpow (GxB_CMPLX (2,0), x)) ;      // z = 2^x
720 }
721 
722 //------------------------------------------------------------------------------
723 // z = expm1 (x) for double complex
724 //------------------------------------------------------------------------------
725 
GB_cexpm1(GxB_FC64_t x)726 inline GxB_FC64_t GB_cexpm1 (GxB_FC64_t x)
727 {
728     // FUTURE: GB_cexpm1 is not accurate
729     // z = cexp (x) - 1
730     GxB_FC64_t z = cexp (x) ;
731     return (GxB_CMPLX (creal (z) - 1, cimag (z))) ;
732 }
733 
734 //------------------------------------------------------------------------------
735 // z = expm1 (x) for float complex
736 //------------------------------------------------------------------------------
737 
GB_cexpm1f(GxB_FC32_t x)738 inline GxB_FC32_t GB_cexpm1f (GxB_FC32_t x)
739 {
740     // typecast to double and use GB_cexpm1
741     GxB_FC64_t z = GxB_CMPLX ((double) crealf (x), (double) cimagf (x)) ;
742     z = GB_cexpm1 (z) ;
743     return (GxB_CMPLXF ((float) creal (z), (float) cimag (z))) ;
744 }
745 
746 //------------------------------------------------------------------------------
747 // z = log1p (x) for double complex
748 //------------------------------------------------------------------------------
749 
GB_clog1p(GxB_FC64_t x)750 inline GxB_FC64_t GB_clog1p (GxB_FC64_t x)
751 {
752     // FUTURE: GB_clog1p is not accurate
753     // z = clog (1+x)
754     return (clog (GxB_CMPLX (creal (x) + 1, cimag (x)))) ;
755 }
756 
757 //------------------------------------------------------------------------------
758 // z = log1p (x) for float complex
759 //------------------------------------------------------------------------------
760 
GB_clog1pf(GxB_FC32_t x)761 inline GxB_FC32_t GB_clog1pf (GxB_FC32_t x)
762 {
763     // typecast to double and use GB_clog1p
764     GxB_FC64_t z = GxB_CMPLX ((double) crealf (x), (double) cimagf (x)) ;
765     z = GB_clog1p (z) ;
766     return (GxB_CMPLXF ((float) creal (z), (float) cimag (z))) ;
767 }
768 
769 //------------------------------------------------------------------------------
770 // z = log10 (x) for float complex
771 //------------------------------------------------------------------------------
772 
773 // log_e (10) in single precision
774 #define GB_LOG10EF 2.3025851f
775 
GB_clog10f(GxB_FC32_t x)776 inline GxB_FC32_t GB_clog10f (GxB_FC32_t x)
777 {
778     // z = log (x) / log (10)
779     return (GB_FC32_div (clogf (x), GxB_CMPLXF (GB_LOG10EF, 0))) ;
780 }
781 
782 //------------------------------------------------------------------------------
783 // z = log10 (x) for double complex
784 //------------------------------------------------------------------------------
785 
786 // log_e (10) in double precision
787 #define GB_LOG10E 2.302585092994045901
788 
GB_clog10(GxB_FC64_t x)789 inline GxB_FC64_t GB_clog10 (GxB_FC64_t x)
790 {
791     // z = log (x) / log (10)
792     return (GB_FC64_div (clog (x), GxB_CMPLX (GB_LOG10E, 0))) ;
793 }
794 
795 //------------------------------------------------------------------------------
796 // z = log2 (x) for float complex
797 //------------------------------------------------------------------------------
798 
799 // log_e (2) in single precision
800 #define GB_LOG2EF 0.69314718f
801 
GB_clog2f(GxB_FC32_t x)802 inline GxB_FC32_t GB_clog2f (GxB_FC32_t x)
803 {
804     // z = log (x) / log (2)
805     return (GB_FC32_div (clogf (x), GxB_CMPLXF (GB_LOG2EF, 0))) ;
806 }
807 
808 //------------------------------------------------------------------------------
809 // z = log2 (x) for double complex
810 //------------------------------------------------------------------------------
811 
812 // log_e (2) in double precision
813 #define GB_LOG2E 0.693147180559945286
814 
GB_clog2(GxB_FC64_t x)815 inline GxB_FC64_t GB_clog2 (GxB_FC64_t x)
816 {
817     // z = log (x) / log (2)
818     return (GB_FC64_div (clog (x), GxB_CMPLX (GB_LOG2E, 0))) ;
819 }
820 
821 //------------------------------------------------------------------------------
822 // z = isinf (x) for float complex
823 //------------------------------------------------------------------------------
824 
GB_cisinff(GxB_FC32_t x)825 inline bool GB_cisinff (GxB_FC32_t x)
826 {
827     return (isinf (crealf (x)) || isinf (cimagf (x))) ;
828 }
829 
830 //------------------------------------------------------------------------------
831 // z = isinf (x) for double complex
832 //------------------------------------------------------------------------------
833 
GB_cisinf(GxB_FC64_t x)834 inline bool GB_cisinf (GxB_FC64_t x)
835 {
836     return (isinf (creal (x)) || isinf (cimag (x))) ;
837 }
838 
839 //------------------------------------------------------------------------------
840 // z = isnan (x) for float complex
841 //------------------------------------------------------------------------------
842 
GB_cisnanf(GxB_FC32_t x)843 inline bool GB_cisnanf (GxB_FC32_t x)
844 {
845     return (isnan (crealf (x)) || isnan (cimagf (x))) ;
846 }
847 
848 //------------------------------------------------------------------------------
849 // z = isnan (x) for double complex
850 //------------------------------------------------------------------------------
851 
GB_cisnan(GxB_FC64_t x)852 inline bool GB_cisnan (GxB_FC64_t x)
853 {
854     return (isnan (creal (x)) || isnan (cimag (x))) ;
855 }
856 
857 //------------------------------------------------------------------------------
858 // z = isfinite (x) for float complex
859 //------------------------------------------------------------------------------
860 
GB_cisfinitef(GxB_FC32_t x)861 inline bool GB_cisfinitef (GxB_FC32_t x)
862 {
863     return (isfinite (crealf (x)) && isfinite (cimagf (x))) ;
864 }
865 
866 //------------------------------------------------------------------------------
867 // z = isfinite (x) for double complex
868 //------------------------------------------------------------------------------
869 
GB_cisfinite(GxB_FC64_t x)870 inline bool GB_cisfinite (GxB_FC64_t x)
871 {
872     return (isfinite (creal (x)) && isfinite (cimag (x))) ;
873 }
874 
875 #endif
876 
877