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