xref: /petsc/include/petsccxxcomplexfix.h (revision 053abcdfeaa3c4bf7b7c01a7334c7edc5567db03)
1 #pragma once
2 
3 /* MANSEC = Sys */
4 
5 /*
6     The pragma below silence all compiler warnings coming from code in this header file.
7     In particular, it silences `-Wfloat-equal` warnings in `operator==()` and `operator!=` below.
8     Other compilers beyond GCC support this pragma.
9 */
10 #if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__NEC__)
11   #pragma GCC system_header
12 #endif
13 
14 /*
15      Defines additional operator overloading for the C++ complex class that are "missing" in the standard
16      include files. For example, the code fragment
17 
18      std::complex<double> c = 22.0;
19      c = 11 + c;
20 
21      will produce a compile time error such as
22 
23      error: no match for 'operator+' (operand types are 'int' and 'std::complex<double>')
24 
25      The code fragment
26 
27      std::complex<float> c = 22.0;
28      c = 11.0 + c;
29 
30      will produce a compile time error such as
31 
32      error: no match for 'operator+' (operand types are 'double' and 'std::complex<float>')
33 
34      This deficiency means one may need to write cumbersome code while working with the C++ complex classes.
35 
36      This include file defines a few additional operator overload methods for the C++ complex classes to handle
37      these cases naturally within PETSc code.
38 
39      This file is included in petscsystypes.h when feasible. In the small number of cases where these additional methods
40      may conflict with other code one may add '#define PETSC_SKIP_CXX_COMPLEX_FIX 1' before including any PETSc include
41      files to prevent these methods from being provided.
42 */
43 
44 #define PETSC_CXX_COMPLEX_FIX(Type) \
45   static inline PetscComplex operator+(const PetscComplex &lhs, const Type &rhs) \
46   { \
47     return const_cast<PetscComplex &>(lhs) + PetscReal(rhs); \
48   } \
49   static inline PetscComplex operator+(const Type &lhs, const PetscComplex &rhs) \
50   { \
51     return PetscReal(lhs) + const_cast<PetscComplex &>(rhs); \
52   } \
53   static inline PetscComplex operator-(const PetscComplex &lhs, const Type &rhs) \
54   { \
55     return const_cast<PetscComplex &>(lhs) - PetscReal(rhs); \
56   } \
57   static inline PetscComplex operator-(const Type &lhs, const PetscComplex &rhs) \
58   { \
59     return PetscReal(lhs) - const_cast<PetscComplex &>(rhs); \
60   } \
61   static inline PetscComplex operator*(const PetscComplex &lhs, const Type &rhs) \
62   { \
63     return const_cast<PetscComplex &>(lhs) * PetscReal(rhs); \
64   } \
65   static inline PetscComplex operator*(const Type &lhs, const PetscComplex &rhs) \
66   { \
67     return PetscReal(lhs) * const_cast<PetscComplex &>(rhs); \
68   } \
69   static inline PetscComplex operator/(const PetscComplex &lhs, const Type &rhs) \
70   { \
71     return const_cast<PetscComplex &>(lhs) / PetscReal(rhs); \
72   } \
73   static inline PetscComplex operator/(const Type &lhs, const PetscComplex &rhs) \
74   { \
75     return PetscReal(lhs) / const_cast<PetscComplex &>(rhs); \
76   } \
77   static inline bool operator==(const PetscComplex &lhs, const Type &rhs) \
78   { \
79     return const_cast<PetscComplex &>(lhs).imag() == PetscReal(0) && const_cast<PetscComplex &>(lhs).real() == PetscReal(rhs); \
80   } \
81   static inline bool operator==(const Type &lhs, const PetscComplex &rhs) \
82   { \
83     return const_cast<PetscComplex &>(rhs).imag() == PetscReal(0) && const_cast<PetscComplex &>(rhs).real() == PetscReal(lhs); \
84   } \
85   static inline bool operator!=(const PetscComplex &lhs, const Type &rhs) \
86   { \
87     return const_cast<PetscComplex &>(lhs).imag() != PetscReal(0) || const_cast<PetscComplex &>(lhs).real() != PetscReal(rhs); \
88   } \
89   static inline bool operator!=(const Type &lhs, const PetscComplex &rhs) \
90   { \
91     return const_cast<PetscComplex &>(rhs).imag() != PetscReal(0) || const_cast<PetscComplex &>(rhs).real() != PetscReal(lhs); \
92   } \
93 /* PETSC_CXX_COMPLEX_FIX */
94 
95 // In PETSc, a quad precision PetscComplex is a C type even with clanguage=cxx, therefore no C++ operator overloading needed for it.
96 #if !defined(PETSC_USE_REAL___FLOAT128)
97 
98 // Provide operator overloading for 'PetscComplex .op. (an integer type or a real type but not PetscReal)'.
99 //
100 // We enumerate all C/C++ POD (Plain Old Data) types to provide exact overload resolution, to keep the precision change
101 // in the Type to PetscReal conversion intact, as intended by users performing these mixed precision operations.
102   #if !defined(PETSC_USE_REAL___FP16) && defined(PETSC_HAVE_REAL___FP16)
103 PETSC_CXX_COMPLEX_FIX(__fp16)
104   #endif
105 
106   #if !defined(PETSC_USE_REAL_SINGLE)
107 PETSC_CXX_COMPLEX_FIX(float)
108   #endif
109 
110   #if !defined(PETSC_USE_REAL_DOUBLE)
111 PETSC_CXX_COMPLEX_FIX(double)
112   #endif
113 
114 PETSC_CXX_COMPLEX_FIX(long double)
115 
116   #if defined(PETSC_HAVE_REAL___FLOAT128)
117 PETSC_CXX_COMPLEX_FIX(__float128)
118   #endif
119 
120 PETSC_CXX_COMPLEX_FIX(signed char)
121 PETSC_CXX_COMPLEX_FIX(short)
122 PETSC_CXX_COMPLEX_FIX(int)
123 PETSC_CXX_COMPLEX_FIX(long)
124 PETSC_CXX_COMPLEX_FIX(long long)
125 
126 PETSC_CXX_COMPLEX_FIX(unsigned char)
127 PETSC_CXX_COMPLEX_FIX(unsigned short)
128 PETSC_CXX_COMPLEX_FIX(unsigned int)
129 PETSC_CXX_COMPLEX_FIX(unsigned long)
130 PETSC_CXX_COMPLEX_FIX(unsigned long long)
131 
132 #endif
133