Actual source code: petsccxxcomplexfix.h
1: #pragma once
3: /* MANSEC = Sys */
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
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
18: std::complex<double> c = 22.0;
19: c = 11 + c;
21: will produce a compile time error such as
23: error: no match for 'operator+' (operand types are 'int' and 'std::complex<double>')
25: The code fragment
27: std::complex<float> c = 22.0;
28: c = 11.0 + c;
30: will produce a compile time error such as
32: error: no match for 'operator+' (operand types are 'double' and 'std::complex<float>')
34: This deficiency means one may need to write cumbersome code while working with the C++ complex classes.
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.
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: */
44: // In PETSc, a quad precision PetscComplex is a C type even with clanguage=cxx, therefore no C++ operator overloading needed for it.
45: #if !defined(PETSC_USE_REAL___FLOAT128)
46: #include <type_traits>
47: // 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: // We extend Atype to other C++ arithmetic types, and __fp16, __float128 if available.
49: // 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: // This requires C++11 or later.
51: template <typename Cmplex, typename Atype> // operation on a complex and an arithmetic type
52: struct petsccomplex_extended_type :
53: std::integral_constant<bool, (std::is_same<Cmplex, PetscComplex>::value && std::is_arithmetic<Atype>::value && !std::is_same<Atype, PetscReal>::value)
54: #if defined(PETSC_HAVE_REAL___FP16) && !defined(PETSC_USE_REAL___FP16)
55: || std::is_same<Atype, __fp16>::value
56: #endif
57: #if defined(PETSC_HAVE_REAL___FLOAT128) && !defined(PETSC_USE_REAL___FLOAT128)
58: || std::is_same<Atype, __float128>::value
59: #endif
60: > {
61: };
63: template <typename Cmplex, typename Atype>
64: inline typename std::enable_if<petsccomplex_extended_type<Cmplex, Atype>::value, Cmplex>::type operator+(const Atype &lhs, const Cmplex &rhs)
65: {
66: return PetscReal(lhs) + rhs;
67: }
69: template <typename Cmplex, typename Atype>
70: inline typename std::enable_if<petsccomplex_extended_type<Cmplex, Atype>::value, Cmplex>::type operator+(const Cmplex &lhs, const Atype &rhs)
71: {
72: return lhs + PetscReal(rhs);
73: }
75: template <typename Cmplex, typename Atype>
76: inline typename std::enable_if<petsccomplex_extended_type<Cmplex, Atype>::value, Cmplex>::type operator-(const Atype &lhs, const Cmplex &rhs)
77: {
78: return PetscReal(lhs) - rhs;
79: }
81: template <typename Cmplex, typename Atype>
82: inline typename std::enable_if<petsccomplex_extended_type<Cmplex, Atype>::value, Cmplex>::type operator-(const Cmplex &lhs, const Atype &rhs)
83: {
84: return lhs - PetscReal(rhs);
85: }
87: template <typename Cmplex, typename Atype>
88: inline typename std::enable_if<petsccomplex_extended_type<Cmplex, Atype>::value, Cmplex>::type operator*(const Atype &lhs, const Cmplex &rhs)
89: {
90: return PetscReal(lhs) * rhs;
91: }
93: template <typename Cmplex, typename Atype>
94: inline typename std::enable_if<petsccomplex_extended_type<Cmplex, Atype>::value, Cmplex>::type operator*(const Cmplex &lhs, const Atype &rhs)
95: {
96: return lhs * PetscReal(rhs);
97: }
99: template <typename Cmplex, typename Atype>
100: inline typename std::enable_if<petsccomplex_extended_type<Cmplex, Atype>::value, Cmplex>::type operator/(const Atype &lhs, const Cmplex &rhs)
101: {
102: return PetscReal(lhs) / rhs;
103: }
105: template <typename Cmplex, typename Atype>
106: inline typename std::enable_if<petsccomplex_extended_type<Cmplex, Atype>::value, Cmplex>::type operator/(const Cmplex &lhs, const Atype &rhs)
107: {
108: return lhs / PetscReal(rhs);
109: }
111: template <typename Cmplex, typename Atype>
112: inline typename std::enable_if<petsccomplex_extended_type<Cmplex, Atype>::value, bool>::type operator==(const Atype &lhs, const Cmplex &rhs)
113: {
114: return rhs.imag() == PetscReal(0) && rhs.real() == PetscReal(lhs);
115: }
117: template <typename Cmplex, typename Atype>
118: inline typename std::enable_if<petsccomplex_extended_type<Cmplex, Atype>::value, bool>::type operator==(const Cmplex &lhs, const Atype &rhs)
119: {
120: return lhs.imag() == PetscReal(0) && lhs.real() == PetscReal(rhs);
121: }
123: template <typename Cmplex, typename Atype>
124: inline typename std::enable_if<petsccomplex_extended_type<Cmplex, Atype>::value, bool>::type operator!=(const Atype &lhs, const Cmplex &rhs)
125: {
126: return rhs.imag() != PetscReal(0) || rhs.real() != PetscReal(lhs);
127: }
129: template <typename Cmplex, typename Atype>
130: inline typename std::enable_if<petsccomplex_extended_type<Cmplex, Atype>::value, bool>::type operator!=(const Cmplex &lhs, const Atype &rhs)
131: {
132: return lhs.imag() != PetscReal(0) || lhs.real() != PetscReal(rhs);
133: }
135: #endif