File: fix_complex_overloading_MR8820.diff

package info (click to toggle)
petsc 3.24.1%2Bdfsg1-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 524,016 kB
  • sloc: ansic: 762,842; cpp: 52,564; python: 39,546; f90: 17,688; javascript: 3,493; makefile: 3,212; sh: 1,512; xml: 619; objc: 445; java: 13; csh: 1
file content (183 lines) | stat: -rw-r--r-- 7,821 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
diff --git a/include/petsccxxcomplexfix.h b/include/petsccxxcomplexfix.h
index 34cd3db5bfad013c935ddd2a2049899870d2fc75..3ff406c7b2380772a600818da937d8e12fed1cda 100644
--- a/include/petsccxxcomplexfix.h
+++ b/include/petsccxxcomplexfix.h
@@ -41,92 +41,95 @@
      files to prevent these methods from being provided.
 */
 
-#define PETSC_CXX_COMPLEX_FIX(Type) \
-  static inline PetscComplex operator+(const PetscComplex &lhs, const Type &rhs) \
-  { \
-    return const_cast<PetscComplex &>(lhs) + PetscReal(rhs); \
-  } \
-  static inline PetscComplex operator+(const Type &lhs, const PetscComplex &rhs) \
-  { \
-    return PetscReal(lhs) + const_cast<PetscComplex &>(rhs); \
-  } \
-  static inline PetscComplex operator-(const PetscComplex &lhs, const Type &rhs) \
-  { \
-    return const_cast<PetscComplex &>(lhs) - PetscReal(rhs); \
-  } \
-  static inline PetscComplex operator-(const Type &lhs, const PetscComplex &rhs) \
-  { \
-    return PetscReal(lhs) - const_cast<PetscComplex &>(rhs); \
-  } \
-  static inline PetscComplex operator*(const PetscComplex &lhs, const Type &rhs) \
-  { \
-    return const_cast<PetscComplex &>(lhs) * PetscReal(rhs); \
-  } \
-  static inline PetscComplex operator*(const Type &lhs, const PetscComplex &rhs) \
-  { \
-    return PetscReal(lhs) * const_cast<PetscComplex &>(rhs); \
-  } \
-  static inline PetscComplex operator/(const PetscComplex &lhs, const Type &rhs) \
-  { \
-    return const_cast<PetscComplex &>(lhs) / PetscReal(rhs); \
-  } \
-  static inline PetscComplex operator/(const Type &lhs, const PetscComplex &rhs) \
-  { \
-    return PetscReal(lhs) / const_cast<PetscComplex &>(rhs); \
-  } \
-  static inline bool operator==(const PetscComplex &lhs, const Type &rhs) \
-  { \
-    return const_cast<PetscComplex &>(lhs).imag() == PetscReal(0) && const_cast<PetscComplex &>(lhs).real() == PetscReal(rhs); \
-  } \
-  static inline bool operator==(const Type &lhs, const PetscComplex &rhs) \
-  { \
-    return const_cast<PetscComplex &>(rhs).imag() == PetscReal(0) && const_cast<PetscComplex &>(rhs).real() == PetscReal(lhs); \
-  } \
-  static inline bool operator!=(const PetscComplex &lhs, const Type &rhs) \
-  { \
-    return const_cast<PetscComplex &>(lhs).imag() != PetscReal(0) || const_cast<PetscComplex &>(lhs).real() != PetscReal(rhs); \
-  } \
-  static inline bool operator!=(const Type &lhs, const PetscComplex &rhs) \
-  { \
-    return const_cast<PetscComplex &>(rhs).imag() != PetscReal(0) || const_cast<PetscComplex &>(rhs).real() != PetscReal(lhs); \
-  } \
-/* PETSC_CXX_COMPLEX_FIX */
-
 // In PETSc, a quad precision PetscComplex is a C type even with clanguage=cxx, therefore no C++ operator overloading needed for it.
 #if !defined(PETSC_USE_REAL___FLOAT128)
-
-// Provide operator overloading for 'PetscComplex .op. (an integer type or a real type but not PetscReal)'.
-//
-// We enumerate all C/C++ POD (Plain Old Data) types to provide exact overload resolution, to keep the precision change
-// in the Type to PetscReal conversion intact, as intended by users performing these mixed precision operations.
-  #if !defined(PETSC_USE_REAL___FP16) && defined(PETSC_HAVE_REAL___FP16)
-PETSC_CXX_COMPLEX_FIX(__fp16)
+  #include <type_traits>
+// For operations "Atype op Cmplex" or "Cmplex op Atype" with Cmplex being PetscComplex, the built-in support allows Atype to be PetscComplex or PetscReal.
+// We extend Atype to other C++ arithmetic types, and __fp16, __float128 if available.
+// We put Cmplex as a template parameter so that we can enforce Cmplex to be PetscComplex and forbid compilers to convert other types to PetscComplex.
+// This requires C++11 or later.
+template <typename Cmplex, typename Atype> // operation on a complex and an arithmetic type
+struct petsccomplex_extended_type :
+  std::integral_constant<bool, (std::is_same<Cmplex, PetscComplex>::value && std::is_arithmetic<Atype>::value && !std::is_same<Atype, PetscReal>::value)
+  #if defined(PETSC_HAVE_REAL___FP16) && !defined(PETSC_USE_REAL___FP16)
+                                 || std::is_same<Atype, __fp16>::value
   #endif
-
-  #if !defined(PETSC_USE_REAL_SINGLE)
-PETSC_CXX_COMPLEX_FIX(float)
-  #endif
-
-  #if !defined(PETSC_USE_REAL_DOUBLE)
-PETSC_CXX_COMPLEX_FIX(double)
+  #if defined(PETSC_HAVE_REAL___FLOAT128) && !defined(PETSC_USE_REAL___FLOAT128)
+                                 || std::is_same<Atype, __float128>::value
   #endif
-
-PETSC_CXX_COMPLEX_FIX(long double)
-
-  #if defined(PETSC_HAVE_REAL___FLOAT128)
-PETSC_CXX_COMPLEX_FIX(__float128)
-  #endif
-
-PETSC_CXX_COMPLEX_FIX(signed char)
-PETSC_CXX_COMPLEX_FIX(short)
-PETSC_CXX_COMPLEX_FIX(int)
-PETSC_CXX_COMPLEX_FIX(long)
-PETSC_CXX_COMPLEX_FIX(long long)
-
-PETSC_CXX_COMPLEX_FIX(unsigned char)
-PETSC_CXX_COMPLEX_FIX(unsigned short)
-PETSC_CXX_COMPLEX_FIX(unsigned int)
-PETSC_CXX_COMPLEX_FIX(unsigned long)
-PETSC_CXX_COMPLEX_FIX(unsigned long long)
+                         > {
+};
+
+template <typename Cmplex, typename Atype>
+inline typename std::enable_if<petsccomplex_extended_type<Cmplex, Atype>::value, Cmplex>::type operator+(const Atype &lhs, const Cmplex &rhs)
+{
+  return PetscReal(lhs) + rhs;
+}
+
+template <typename Cmplex, typename Atype>
+inline typename std::enable_if<petsccomplex_extended_type<Cmplex, Atype>::value, Cmplex>::type operator+(const Cmplex &lhs, const Atype &rhs)
+{
+  return lhs + PetscReal(rhs);
+}
+
+template <typename Cmplex, typename Atype>
+inline typename std::enable_if<petsccomplex_extended_type<Cmplex, Atype>::value, Cmplex>::type operator-(const Atype &lhs, const Cmplex &rhs)
+{
+  return PetscReal(lhs) - rhs;
+}
+
+template <typename Cmplex, typename Atype>
+inline typename std::enable_if<petsccomplex_extended_type<Cmplex, Atype>::value, Cmplex>::type operator-(const Cmplex &lhs, const Atype &rhs)
+{
+  return lhs - PetscReal(rhs);
+}
+
+template <typename Cmplex, typename Atype>
+inline typename std::enable_if<petsccomplex_extended_type<Cmplex, Atype>::value, Cmplex>::type operator*(const Atype &lhs, const Cmplex &rhs)
+{
+  return PetscReal(lhs) * rhs;
+}
+
+template <typename Cmplex, typename Atype>
+inline typename std::enable_if<petsccomplex_extended_type<Cmplex, Atype>::value, Cmplex>::type operator*(const Cmplex &lhs, const Atype &rhs)
+{
+  return lhs * PetscReal(rhs);
+}
+
+template <typename Cmplex, typename Atype>
+inline typename std::enable_if<petsccomplex_extended_type<Cmplex, Atype>::value, Cmplex>::type operator/(const Atype &lhs, const Cmplex &rhs)
+{
+  return PetscReal(lhs) / rhs;
+}
+
+template <typename Cmplex, typename Atype>
+inline typename std::enable_if<petsccomplex_extended_type<Cmplex, Atype>::value, Cmplex>::type operator/(const Cmplex &lhs, const Atype &rhs)
+{
+  return lhs / PetscReal(rhs);
+}
+
+template <typename Cmplex, typename Atype>
+inline typename std::enable_if<petsccomplex_extended_type<Cmplex, Atype>::value, bool>::type operator==(const Atype &lhs, const Cmplex &rhs)
+{
+  return rhs.imag() == PetscReal(0) && rhs.real() == PetscReal(lhs);
+}
+
+template <typename Cmplex, typename Atype>
+inline typename std::enable_if<petsccomplex_extended_type<Cmplex, Atype>::value, bool>::type operator==(const Cmplex &lhs, const Atype &rhs)
+{
+  return lhs.imag() == PetscReal(0) && lhs.real() == PetscReal(rhs);
+}
+
+template <typename Cmplex, typename Atype>
+inline typename std::enable_if<petsccomplex_extended_type<Cmplex, Atype>::value, bool>::type operator!=(const Atype &lhs, const Cmplex &rhs)
+{
+  return rhs.imag() != PetscReal(0) || rhs.real() != PetscReal(lhs);
+}
+
+template <typename Cmplex, typename Atype>
+inline typename std::enable_if<petsccomplex_extended_type<Cmplex, Atype>::value, bool>::type operator!=(const Cmplex &lhs, const Atype &rhs)
+{
+  return lhs.imag() != PetscReal(0) || lhs.real() != PetscReal(rhs);
+}
 
 #endif