xref: /petsc/include/petsccxxcomplexfix.h (revision a17a2c17395fd5f30b5a762bb0dbf7d722de50da)
1a4963045SJacob Faibussowitsch #pragma once
239829747SLisandro Dalcin 
31850900dSBarry Smith /* MANSEC = Sys */
41850900dSBarry Smith 
5f636a84aSBarry Smith /*
6d5b43468SJose E. Roman     The pragma below silence all compiler warnings coming from code in this header file.
74cdc28b3SLisandro Dalcin     In particular, it silences `-Wfloat-equal` warnings in `operator==()` and `operator!=` below.
84cdc28b3SLisandro Dalcin     Other compilers beyond GCC support this pragma.
94cdc28b3SLisandro Dalcin */
1077ba14dbSStefano Zampini #if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__NEC__)
114cdc28b3SLisandro Dalcin   #pragma GCC system_header
124cdc28b3SLisandro Dalcin #endif
134cdc28b3SLisandro Dalcin 
144cdc28b3SLisandro Dalcin /*
15f636a84aSBarry Smith      Defines additional operator overloading for the C++ complex class that are "missing" in the standard
16f636a84aSBarry Smith      include files. For example, the code fragment
17f636a84aSBarry Smith 
18f636a84aSBarry Smith      std::complex<double> c = 22.0;
19f636a84aSBarry Smith      c = 11 + c;
20f636a84aSBarry Smith 
21f636a84aSBarry Smith      will produce a compile time error such as
22f636a84aSBarry Smith 
23f636a84aSBarry Smith      error: no match for 'operator+' (operand types are 'int' and 'std::complex<double>')
24f636a84aSBarry Smith 
25f636a84aSBarry Smith      The code fragment
26f636a84aSBarry Smith 
27f636a84aSBarry Smith      std::complex<float> c = 22.0;
28f636a84aSBarry Smith      c = 11.0 + c;
29f636a84aSBarry Smith 
30f636a84aSBarry Smith      will produce a compile time error such as
31f636a84aSBarry Smith 
32f636a84aSBarry Smith      error: no match for 'operator+' (operand types are 'double' and 'std::complex<float>')
33f636a84aSBarry Smith 
34f636a84aSBarry Smith      This deficiency means one may need to write cumbersome code while working with the C++ complex classes.
35f636a84aSBarry Smith 
36f636a84aSBarry Smith      This include file defines a few additional operator overload methods for the C++ complex classes to handle
37f636a84aSBarry Smith      these cases naturally within PETSc code.
38f636a84aSBarry Smith 
39a966371cSJunchao Zhang      This file is included in petscsystypes.h when feasible. In the small number of cases where these additional methods
40a966371cSJunchao Zhang      may conflict with other code one may add '#define PETSC_SKIP_CXX_COMPLEX_FIX 1' before including any PETSc include
41a966371cSJunchao Zhang      files to prevent these methods from being provided.
42f636a84aSBarry Smith */
43f636a84aSBarry Smith 
44108513bbSJunchao Zhang // In PETSc, a quad precision PetscComplex is a C type even with clanguage=cxx, therefore no C++ operator overloading needed for it.
45108513bbSJunchao Zhang #if !defined(PETSC_USE_REAL___FLOAT128)
46*8ecb7dbcSJunchao Zhang   #include <type_traits>
47*8ecb7dbcSJunchao Zhang // For operations "Atype op Cmplex" or "Cmplex op Atype" with Cmplex being PetscComplex, the built-in support allows Atype to be PetscComplex or PetscReal.
48*8ecb7dbcSJunchao Zhang // We extend Atype to other C++ arithmetic types, and __fp16, __float128 if available.
49*8ecb7dbcSJunchao Zhang // 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.
50*8ecb7dbcSJunchao Zhang // This requires C++11 or later.
51*8ecb7dbcSJunchao Zhang template <typename Cmplex, typename Atype> // operation on a complex and an arithmetic type
52*8ecb7dbcSJunchao Zhang struct petsccomplex_extended_type :
53*8ecb7dbcSJunchao Zhang   std::integral_constant<bool, (std::is_same<Cmplex, PetscComplex>::value && std::is_arithmetic<Atype>::value && !std::is_same<Atype, PetscReal>::value)
54*8ecb7dbcSJunchao Zhang   #if defined(PETSC_HAVE_REAL___FP16) && !defined(PETSC_USE_REAL___FP16)
55*8ecb7dbcSJunchao Zhang                                  || std::is_same<Atype, __fp16>::value
56108513bbSJunchao Zhang   #endif
57*8ecb7dbcSJunchao Zhang   #if defined(PETSC_HAVE_REAL___FLOAT128) && !defined(PETSC_USE_REAL___FLOAT128)
58*8ecb7dbcSJunchao Zhang                                  || std::is_same<Atype, __float128>::value
59108513bbSJunchao Zhang   #endif
60*8ecb7dbcSJunchao Zhang                          > {
61*8ecb7dbcSJunchao Zhang };
62108513bbSJunchao Zhang 
63*8ecb7dbcSJunchao Zhang template <typename Cmplex, typename Atype>
64*8ecb7dbcSJunchao Zhang inline typename std::enable_if<petsccomplex_extended_type<Cmplex, Atype>::value, Cmplex>::type operator+(const Atype &lhs, const Cmplex &rhs)
65*8ecb7dbcSJunchao Zhang {
66*8ecb7dbcSJunchao Zhang   return PetscReal(lhs) + rhs;
67*8ecb7dbcSJunchao Zhang }
68108513bbSJunchao Zhang 
69*8ecb7dbcSJunchao Zhang template <typename Cmplex, typename Atype>
70*8ecb7dbcSJunchao Zhang inline typename std::enable_if<petsccomplex_extended_type<Cmplex, Atype>::value, Cmplex>::type operator+(const Cmplex &lhs, const Atype &rhs)
71*8ecb7dbcSJunchao Zhang {
72*8ecb7dbcSJunchao Zhang   return lhs + PetscReal(rhs);
73*8ecb7dbcSJunchao Zhang }
74108513bbSJunchao Zhang 
75*8ecb7dbcSJunchao Zhang template <typename Cmplex, typename Atype>
76*8ecb7dbcSJunchao Zhang inline typename std::enable_if<petsccomplex_extended_type<Cmplex, Atype>::value, Cmplex>::type operator-(const Atype &lhs, const Cmplex &rhs)
77*8ecb7dbcSJunchao Zhang {
78*8ecb7dbcSJunchao Zhang   return PetscReal(lhs) - rhs;
79*8ecb7dbcSJunchao Zhang }
80108513bbSJunchao Zhang 
81*8ecb7dbcSJunchao Zhang template <typename Cmplex, typename Atype>
82*8ecb7dbcSJunchao Zhang inline typename std::enable_if<petsccomplex_extended_type<Cmplex, Atype>::value, Cmplex>::type operator-(const Cmplex &lhs, const Atype &rhs)
83*8ecb7dbcSJunchao Zhang {
84*8ecb7dbcSJunchao Zhang   return lhs - PetscReal(rhs);
85*8ecb7dbcSJunchao Zhang }
86108513bbSJunchao Zhang 
87*8ecb7dbcSJunchao Zhang template <typename Cmplex, typename Atype>
88*8ecb7dbcSJunchao Zhang inline typename std::enable_if<petsccomplex_extended_type<Cmplex, Atype>::value, Cmplex>::type operator*(const Atype &lhs, const Cmplex &rhs)
89*8ecb7dbcSJunchao Zhang {
90*8ecb7dbcSJunchao Zhang   return PetscReal(lhs) * rhs;
91*8ecb7dbcSJunchao Zhang }
92*8ecb7dbcSJunchao Zhang 
93*8ecb7dbcSJunchao Zhang template <typename Cmplex, typename Atype>
94*8ecb7dbcSJunchao Zhang inline typename std::enable_if<petsccomplex_extended_type<Cmplex, Atype>::value, Cmplex>::type operator*(const Cmplex &lhs, const Atype &rhs)
95*8ecb7dbcSJunchao Zhang {
96*8ecb7dbcSJunchao Zhang   return lhs * PetscReal(rhs);
97*8ecb7dbcSJunchao Zhang }
98*8ecb7dbcSJunchao Zhang 
99*8ecb7dbcSJunchao Zhang template <typename Cmplex, typename Atype>
100*8ecb7dbcSJunchao Zhang inline typename std::enable_if<petsccomplex_extended_type<Cmplex, Atype>::value, Cmplex>::type operator/(const Atype &lhs, const Cmplex &rhs)
101*8ecb7dbcSJunchao Zhang {
102*8ecb7dbcSJunchao Zhang   return PetscReal(lhs) / rhs;
103*8ecb7dbcSJunchao Zhang }
104*8ecb7dbcSJunchao Zhang 
105*8ecb7dbcSJunchao Zhang template <typename Cmplex, typename Atype>
106*8ecb7dbcSJunchao Zhang inline typename std::enable_if<petsccomplex_extended_type<Cmplex, Atype>::value, Cmplex>::type operator/(const Cmplex &lhs, const Atype &rhs)
107*8ecb7dbcSJunchao Zhang {
108*8ecb7dbcSJunchao Zhang   return lhs / PetscReal(rhs);
109*8ecb7dbcSJunchao Zhang }
110*8ecb7dbcSJunchao Zhang 
111*8ecb7dbcSJunchao Zhang template <typename Cmplex, typename Atype>
112*8ecb7dbcSJunchao Zhang inline typename std::enable_if<petsccomplex_extended_type<Cmplex, Atype>::value, bool>::type operator==(const Atype &lhs, const Cmplex &rhs)
113*8ecb7dbcSJunchao Zhang {
114*8ecb7dbcSJunchao Zhang   return rhs.imag() == PetscReal(0) && rhs.real() == PetscReal(lhs);
115*8ecb7dbcSJunchao Zhang }
116*8ecb7dbcSJunchao Zhang 
117*8ecb7dbcSJunchao Zhang template <typename Cmplex, typename Atype>
118*8ecb7dbcSJunchao Zhang inline typename std::enable_if<petsccomplex_extended_type<Cmplex, Atype>::value, bool>::type operator==(const Cmplex &lhs, const Atype &rhs)
119*8ecb7dbcSJunchao Zhang {
120*8ecb7dbcSJunchao Zhang   return lhs.imag() == PetscReal(0) && lhs.real() == PetscReal(rhs);
121*8ecb7dbcSJunchao Zhang }
122*8ecb7dbcSJunchao Zhang 
123*8ecb7dbcSJunchao Zhang template <typename Cmplex, typename Atype>
124*8ecb7dbcSJunchao Zhang inline typename std::enable_if<petsccomplex_extended_type<Cmplex, Atype>::value, bool>::type operator!=(const Atype &lhs, const Cmplex &rhs)
125*8ecb7dbcSJunchao Zhang {
126*8ecb7dbcSJunchao Zhang   return rhs.imag() != PetscReal(0) || rhs.real() != PetscReal(lhs);
127*8ecb7dbcSJunchao Zhang }
128*8ecb7dbcSJunchao Zhang 
129*8ecb7dbcSJunchao Zhang template <typename Cmplex, typename Atype>
130*8ecb7dbcSJunchao Zhang inline typename std::enable_if<petsccomplex_extended_type<Cmplex, Atype>::value, bool>::type operator!=(const Cmplex &lhs, const Atype &rhs)
131*8ecb7dbcSJunchao Zhang {
132*8ecb7dbcSJunchao Zhang   return lhs.imag() != PetscReal(0) || lhs.real() != PetscReal(rhs);
133*8ecb7dbcSJunchao Zhang }
134108513bbSJunchao Zhang 
135108513bbSJunchao Zhang #endif
136