libMesh
compare_types.h
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2026 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
13 
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 
18 
19 #ifndef LIBMESH_COMPARE_TYPES_H
20 #define LIBMESH_COMPARE_TYPES_H
21 
22 #include "libmesh_config.h"
23 
24 #ifdef LIBMESH_DEFAULT_QUADRUPLE_PRECISION
25 #include "libmesh_common.h" // for Real
26 #endif
27 
28 // System includes
29 #include <complex>
30 #include <type_traits>
31 
32 namespace libMesh
33 {
34 
35 // Copy of boost's enable_if_c - needed before we had std::enable_if
36 #ifdef LIBMESH_ENABLE_DEPRECATED
37 namespace boostcopy {
38 template <bool B, class T = void>
39 struct enable_if_c {
40  typedef T type;
41 };
42 
43 template <class T>
44 struct enable_if_c<false, T> {};
45 }
46 #endif // LIBMESH_ENABLE_DEPRECATED
47 
48 
49 // TypesEqual takes two types as parameters.
50 // If they are the exact same type, then TypesEqual::value is the boolean true,
51 // otherwise TypesEqual::value is the boolean false.
52 template <typename T1, typename T2>
53 struct TypesEqual {
54  static const bool value = false;
55 };
56 
57 template <typename T>
58 struct TypesEqual<T,T> {
59  static const bool value = true;
60 };
61 
62 
63 // Complete list of scalar classes, needed for disambiguation
64 template <typename T>
65 struct ScalarTraits {
66  static const bool value = false;
67 };
68 
69 #define ScalarTraits_true(type) \
70  template<> \
71  struct ScalarTraits<type> { static const bool value = true; }
72 #define RealTraits_true(type) \
73  template<> \
74  struct RealTraits<type> { static const bool value = true; }
75 
76 ScalarTraits_true(char);
77 ScalarTraits_true(short);
79 ScalarTraits_true(long);
80 ScalarTraits_true(unsigned char);
81 ScalarTraits_true(unsigned short);
82 ScalarTraits_true(unsigned int);
83 ScalarTraits_true(unsigned long);
84 ScalarTraits_true(float);
85 ScalarTraits_true(double);
86 ScalarTraits_true(long double);
87 #ifdef LIBMESH_DEFAULT_QUADRUPLE_PRECISION
89 #endif
90 
91 template<typename T>
92 struct ScalarTraits<std::complex<T>> { static const bool value = ScalarTraits<T>::value; };
93 
94 // List of classes for which instantiations of std::complex are defined, e.g. where
95 // TensorTools::MakeNumber will always make sense
96 template <typename T>
97 struct RealTraits {
98  static const bool value = false;
99 };
100 
101 #define RealTraits_true(type) \
102  template<> \
103  struct RealTraits<type> { static const bool value = true; }
104 
105 RealTraits_true(float);
106 RealTraits_true(double);
107 RealTraits_true(long double);
108 
109 // Operators using different but compatible types need a return value
110 // based on whichever type the other can be upconverted into. For
111 // instance, the proper return type for
112 // TypeVector<float>::operator*(double) is TypeVector<double>. In
113 // general, an operation using types S and T should return a value
114 // based on CompareTypes<S,T>::supertype
115 
116 template<typename S, typename T>
117 struct CompareTypes {
118  typedef void supertype;
119 };
120 
121 template<typename T>
122 struct CompareTypes<T, T> {
123  typedef T supertype;
124 };
125 
126 template<typename T>
127 struct CompareTypes<T, std::complex<T>> {
128  typedef std::complex<T> supertype;
129 };
130 
131 template<typename T>
132 struct CompareTypes<std::complex<T>, T> {
133  typedef std::complex<T> supertype;
134 };
135 
136 // There's got to be some magic template way to do these better - but the best
137 // thing on the net requires a bunch of Alexandrescu's code and doesn't work
138 // with older compilers
139 
140 #define CompareTypes_super(a,b,super) \
141  template<> \
142  struct CompareTypes<a, b> { \
143  typedef super supertype; \
144  }
145 
146 #define SUPERTYPE(mysub,mysuper) \
147  CompareTypes_super(mysub, mysuper, mysuper); \
148  CompareTypes_super(mysuper, mysub, mysuper); \
149  CompareTypes_super(std::complex<mysub>, mysuper, std::complex<mysuper>); \
150  CompareTypes_super(mysuper, std::complex<mysub>, std::complex<mysuper>); \
151  CompareTypes_super(mysub, std::complex<mysuper>, std::complex<mysuper>); \
152  CompareTypes_super(std::complex<mysuper>, mysub, std::complex<mysuper>); \
153  CompareTypes_super(std::complex<mysub>, std::complex<mysuper>, std::complex<mysuper>); \
154  CompareTypes_super(std::complex<mysuper>, std::complex<mysub>, std::complex<mysuper>)
155 
156 SUPERTYPE(unsigned char, short);
157 SUPERTYPE(unsigned char, int);
158 SUPERTYPE(unsigned char, float);
159 SUPERTYPE(unsigned char, double);
160 SUPERTYPE(unsigned char, long double);
161 SUPERTYPE(unsigned short, int);
162 SUPERTYPE(unsigned short, float);
163 SUPERTYPE(unsigned short, double);
164 SUPERTYPE(unsigned short, long double);
165 SUPERTYPE(unsigned int, float);
166 SUPERTYPE(unsigned int, double);
167 SUPERTYPE(unsigned int, long double);
168 SUPERTYPE(char, short);
169 SUPERTYPE(char, int);
170 SUPERTYPE(char, float);
171 SUPERTYPE(char, double);
172 SUPERTYPE(char, long double);
173 SUPERTYPE(short, int);
174 SUPERTYPE(short, float);
175 SUPERTYPE(short, double);
176 SUPERTYPE(short, long double);
177 SUPERTYPE(int, float);
178 SUPERTYPE(int, double);
179 SUPERTYPE(int, long double);
180 SUPERTYPE(float, double);
181 SUPERTYPE(float, long double);
182 SUPERTYPE(double, long double);
183 
184 #ifdef LIBMESH_DEFAULT_QUADRUPLE_PRECISION
185 SUPERTYPE(unsigned char, Real);
186 SUPERTYPE(unsigned short, Real);
187 SUPERTYPE(unsigned int, Real);
188 SUPERTYPE(char, Real);
189 SUPERTYPE(short, Real);
190 SUPERTYPE(int, Real);
191 SUPERTYPE(float, Real);
192 SUPERTYPE(double, Real);
193 SUPERTYPE(long double, Real);
194 #endif
195 
196 #undef CompareTypes_super
197 #undef SUPERTYPE
198 
199 // gcc can't tell which of the following is the most specialized? Weak.
200 /*
201  template<typename S, typename T>
202  struct CompareTypes<std::complex<S>, std::complex<T>> {
203  typedef std::complex<typename CompareTypes<S, T>::supertype> supertype;
204  };
205 
206  template<typename S, typename T>
207  struct CompareTypes<std::complex<S>, T> {
208  typedef std::complex<typename CompareTypes<S, T>::supertype> supertype;
209  };
210 
211  template<typename S, typename T>
212  struct CompareTypes<S, std::complex<T>> {
213  typedef std::complex<typename CompareTypes<S, T>::supertype> supertype;
214  };
215 */
216 
217 } // namespace libMesh
218 
219 #ifdef LIBMESH_HAVE_METAPHYSICL
220 #define LIBMESH_DUAL_NUMBER_COMPARE_TYPES
221 
222 #include "metaphysicl/dualnumber_forward.h"
223 
224 namespace libMesh
225 {
226 template <typename T, typename T2, typename D, bool asd>
227 struct CompareTypes<T, MetaPhysicL::DualNumber<T2, D, asd>>
228 {
229  typedef MetaPhysicL::DualNumber<typename CompareTypes<T, T2>::supertype,
230  typename D::template rebind<typename CompareTypes<T, T2>::supertype>::other,
231  asd>
233 };
234 template <typename T, typename D, typename T2, bool asd>
235 struct CompareTypes<MetaPhysicL::DualNumber<T, D, asd>, T2>
236 {
237  typedef MetaPhysicL::DualNumber<typename CompareTypes<T, T2>::supertype,
238  typename D::template rebind<typename CompareTypes<T, T2>::supertype>::other,
239  asd>
241 };
242 template <typename T, typename D, typename T2, typename D2, bool asd>
243 struct CompareTypes<MetaPhysicL::DualNumber<T, D, asd>, MetaPhysicL::DualNumber<T2, D2, asd>>
244 {
245  typedef MetaPhysicL::DualNumber<typename CompareTypes<T, T2>::supertype,
246  typename D::template rebind<typename CompareTypes<T, T2>::supertype>::other,
247  asd>
249 };
250 template <typename T, typename D, bool asd>
251 struct CompareTypes<MetaPhysicL::DualNumber<T, D, asd>, MetaPhysicL::DualNumber<T, D, asd>>
252 {
253  typedef MetaPhysicL::DualNumber<T, D, asd> supertype;
254 };
255 template <typename T, typename T2, bool asd>
256 struct CompareTypes<T, MetaPhysicL::DualNumber<T2, T2, asd>>
257 {
258  typedef MetaPhysicL::DualNumber<typename CompareTypes<T, T2>::supertype,
260  asd>
262 };
263 template <typename T, typename T2, bool asd>
264 struct CompareTypes<MetaPhysicL::DualNumber<T, T, asd>, T2>
265 {
266  typedef MetaPhysicL::DualNumber<typename CompareTypes<T, T2>::supertype,
268  asd>
270 };
271 template <typename T, typename T2, bool asd>
272 struct CompareTypes<MetaPhysicL::DualNumber<T, T, asd>, MetaPhysicL::DualNumber<T2, T2, asd>>
273 {
274  typedef MetaPhysicL::DualNumber<typename CompareTypes<T, T2>::supertype,
276  asd>
278 };
279 template <typename T, typename D, bool asd>
280 struct ScalarTraits<MetaPhysicL::DualNumber<T, D, asd>>
281 {
282  static const bool value = ScalarTraits<T>::value;
283 };
284 template <typename T, typename D, bool asd>
285 struct RealTraits<MetaPhysicL::DualNumber<T, D, asd>>
286 {
287  static const bool value = RealTraits<T>::value;
288 };
289 
290 } // namespace libMesh
291 
292 #endif // LIBMESH_HAVE_METAPHYSICL
293 
294 #endif // LIBMESH_COMPARE_TYPES_H
MetaPhysicL::DualNumber< typename CompareTypes< T, T2 >::supertype, typename D::template rebind< typename CompareTypes< T, T2 >::supertype >::other, asd > supertype
MetaPhysicL::DualNumber< typename CompareTypes< T, T2 >::supertype, typename D::template rebind< typename CompareTypes< T, T2 >::supertype >::other, asd > supertype
MetaPhysicL::DualNumber< typename CompareTypes< T, T2 >::supertype, typename CompareTypes< T, T2 >::supertype, asd > supertype
The libMesh namespace provides an interface to certain functionality in the library.
static const bool value
Definition: compare_types.h:54
SUPERTYPE(unsigned char, short)
MetaPhysicL::DualNumber< typename CompareTypes< T, T2 >::supertype, typename CompareTypes< T, T2 >::supertype, asd > supertype
RealTraits_true(float)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
ScalarTraits_true(char)
MetaPhysicL::DualNumber< typename CompareTypes< T, T2 >::supertype, typename CompareTypes< T, T2 >::supertype, asd > supertype
static const bool value
Definition: compare_types.h:66
static const bool value
Definition: compare_types.h:98
MetaPhysicL::DualNumber< typename CompareTypes< T, T2 >::supertype, typename D::template rebind< typename CompareTypes< T, T2 >::supertype >::other, asd > supertype