libMesh
compare_types.h
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2024 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 // System includes
23 #include <complex>
24 
25 #include "libmesh_config.h"
26 
27 #ifdef LIBMESH_DEFAULT_QUADRUPLE_PRECISION
28 #include "libmesh_common.h" // for Real
29 #endif
30 
31 namespace libMesh
32 {
33 
34 // Copy of boost's enable_if_c
35 
36 namespace boostcopy {
37 template <bool B, class T = void>
38 struct enable_if_c {
39  typedef T type;
40 };
41 
42 template <class T>
43 struct enable_if_c<false, T> {};
44 }
45 
46 
47 // TypesEqual takes two types as parameters.
48 // If they are the exact same type, then TypesEqual::value is the boolean true,
49 // otherwise TypesEqual::value is the boolean false.
50 template <typename T1, typename T2>
51 struct TypesEqual {
52  static const bool value = false;
53 };
54 
55 template <typename T>
56 struct TypesEqual<T,T> {
57  static const bool value = true;
58 };
59 
60 
61 // Complete list of scalar classes, needed for disambiguation
62 template <typename T>
63 struct ScalarTraits {
64  static const bool value = false;
65 };
66 
67 #define ScalarTraits_true(type) \
68  template<> \
69  struct ScalarTraits<type> { static const bool value = true; }
70 #define RealTraits_true(type) \
71  template<> \
72  struct RealTraits<type> { static const bool value = true; }
73 
74 ScalarTraits_true(char);
75 ScalarTraits_true(short);
77 ScalarTraits_true(long);
78 ScalarTraits_true(unsigned char);
79 ScalarTraits_true(unsigned short);
80 ScalarTraits_true(unsigned int);
81 ScalarTraits_true(unsigned long);
82 ScalarTraits_true(float);
83 ScalarTraits_true(double);
84 ScalarTraits_true(long double);
85 #ifdef LIBMESH_DEFAULT_QUADRUPLE_PRECISION
87 #endif
88 
89 template<typename T>
90 struct ScalarTraits<std::complex<T>> { static const bool value = ScalarTraits<T>::value; };
91 
92 // List of classes for which instantiations of std::complex are defined, e.g. where
93 // TensorTools::MakeNumber will always make sense
94 template <typename T>
95 struct RealTraits {
96  static const bool value = false;
97 };
98 
99 #define RealTraits_true(type) \
100  template<> \
101  struct RealTraits<type> { static const bool value = true; }
102 
103 RealTraits_true(float);
104 RealTraits_true(double);
105 RealTraits_true(long double);
106 
107 // Operators using different but compatible types need a return value
108 // based on whichever type the other can be upconverted into. For
109 // instance, the proper return type for
110 // TypeVector<float>::operator*(double) is TypeVector<double>. In
111 // general, an operation using types S and T should return a value
112 // based on CompareTypes<S,T>::supertype
113 
114 template<typename S, typename T>
115 struct CompareTypes {
116  typedef void supertype;
117 };
118 
119 template<typename T>
120 struct CompareTypes<T, T> {
121  typedef T supertype;
122 };
123 
124 template<typename T>
125 struct CompareTypes<T, std::complex<T>> {
126  typedef std::complex<T> supertype;
127 };
128 
129 template<typename T>
130 struct CompareTypes<std::complex<T>, T> {
131  typedef std::complex<T> supertype;
132 };
133 
134 // There's got to be some magic template way to do these better - but the best
135 // thing on the net requires a bunch of Alexandrescu's code and doesn't work
136 // with older compilers
137 
138 #define CompareTypes_super(a,b,super) \
139  template<> \
140  struct CompareTypes<a, b> { \
141  typedef super supertype; \
142  }
143 
144 #define SUPERTYPE(mysub,mysuper) \
145  CompareTypes_super(mysub, mysuper, mysuper); \
146  CompareTypes_super(mysuper, mysub, mysuper); \
147  CompareTypes_super(std::complex<mysub>, mysuper, std::complex<mysuper>); \
148  CompareTypes_super(mysuper, std::complex<mysub>, std::complex<mysuper>); \
149  CompareTypes_super(mysub, std::complex<mysuper>, std::complex<mysuper>); \
150  CompareTypes_super(std::complex<mysuper>, mysub, std::complex<mysuper>); \
151  CompareTypes_super(std::complex<mysub>, std::complex<mysuper>, std::complex<mysuper>); \
152  CompareTypes_super(std::complex<mysuper>, std::complex<mysub>, std::complex<mysuper>)
153 
154 SUPERTYPE(unsigned char, short);
155 SUPERTYPE(unsigned char, int);
156 SUPERTYPE(unsigned char, float);
157 SUPERTYPE(unsigned char, double);
158 SUPERTYPE(unsigned char, long double);
159 SUPERTYPE(unsigned short, int);
160 SUPERTYPE(unsigned short, float);
161 SUPERTYPE(unsigned short, double);
162 SUPERTYPE(unsigned short, long double);
163 SUPERTYPE(unsigned int, float);
164 SUPERTYPE(unsigned int, double);
165 SUPERTYPE(unsigned int, long double);
166 SUPERTYPE(char, short);
167 SUPERTYPE(char, int);
168 SUPERTYPE(char, float);
169 SUPERTYPE(char, double);
170 SUPERTYPE(char, long double);
171 SUPERTYPE(short, int);
172 SUPERTYPE(short, float);
173 SUPERTYPE(short, double);
174 SUPERTYPE(short, long double);
175 SUPERTYPE(int, float);
176 SUPERTYPE(int, double);
177 SUPERTYPE(int, long double);
178 SUPERTYPE(float, double);
179 SUPERTYPE(float, long double);
180 SUPERTYPE(double, long double);
181 
182 #ifdef LIBMESH_DEFAULT_QUADRUPLE_PRECISION
183 SUPERTYPE(unsigned char, Real);
184 SUPERTYPE(unsigned short, Real);
185 SUPERTYPE(unsigned int, Real);
186 SUPERTYPE(char, Real);
187 SUPERTYPE(short, Real);
188 SUPERTYPE(int, Real);
189 SUPERTYPE(float, Real);
190 SUPERTYPE(double, Real);
191 SUPERTYPE(long double, Real);
192 #endif
193 
194 #undef CompareTypes_super
195 #undef SUPERTYPE
196 
197 // gcc can't tell which of the following is the most specialized? Weak.
198 /*
199  template<typename S, typename T>
200  struct CompareTypes<std::complex<S>, std::complex<T>> {
201  typedef std::complex<typename CompareTypes<S, T>::supertype> supertype;
202  };
203 
204  template<typename S, typename T>
205  struct CompareTypes<std::complex<S>, T> {
206  typedef std::complex<typename CompareTypes<S, T>::supertype> supertype;
207  };
208 
209  template<typename S, typename T>
210  struct CompareTypes<S, std::complex<T>> {
211  typedef std::complex<typename CompareTypes<S, T>::supertype> supertype;
212  };
213 */
214 
215 } // namespace libMesh
216 
217 #ifdef LIBMESH_HAVE_METAPHYSICL
218 #define LIBMESH_DUAL_NUMBER_COMPARE_TYPES
219 
220 #include "metaphysicl/dualnumber_forward.h"
221 
222 namespace libMesh
223 {
224 template <typename T, typename T2, typename D, bool asd>
225 struct CompareTypes<T, MetaPhysicL::DualNumber<T2, D, asd>>
226 {
227  typedef MetaPhysicL::DualNumber<typename CompareTypes<T, T2>::supertype,
228  typename D::template rebind<typename CompareTypes<T, T2>::supertype>::other,
229  asd>
231 };
232 template <typename T, typename D, typename T2, bool asd>
233 struct CompareTypes<MetaPhysicL::DualNumber<T, D, asd>, T2>
234 {
235  typedef MetaPhysicL::DualNumber<typename CompareTypes<T, T2>::supertype,
236  typename D::template rebind<typename CompareTypes<T, T2>::supertype>::other,
237  asd>
239 };
240 template <typename T, typename D, typename T2, typename D2, bool asd>
241 struct CompareTypes<MetaPhysicL::DualNumber<T, D, asd>, MetaPhysicL::DualNumber<T2, D2, asd>>
242 {
243  typedef MetaPhysicL::DualNumber<typename CompareTypes<T, T2>::supertype,
244  typename D::template rebind<typename CompareTypes<T, T2>::supertype>::other,
245  asd>
247 };
248 template <typename T, typename D, bool asd>
249 struct CompareTypes<MetaPhysicL::DualNumber<T, D, asd>, MetaPhysicL::DualNumber<T, D, asd>>
250 {
251  typedef MetaPhysicL::DualNumber<T, D, asd> supertype;
252 };
253 template <typename T, typename T2, bool asd>
254 struct CompareTypes<T, MetaPhysicL::DualNumber<T2, T2, asd>>
255 {
256  typedef MetaPhysicL::DualNumber<typename CompareTypes<T, T2>::supertype,
258  asd>
260 };
261 template <typename T, typename T2, bool asd>
262 struct CompareTypes<MetaPhysicL::DualNumber<T, T, asd>, T2>
263 {
264  typedef MetaPhysicL::DualNumber<typename CompareTypes<T, T2>::supertype,
266  asd>
268 };
269 template <typename T, typename T2, bool asd>
270 struct CompareTypes<MetaPhysicL::DualNumber<T, T, asd>, MetaPhysicL::DualNumber<T2, T2, asd>>
271 {
272  typedef MetaPhysicL::DualNumber<typename CompareTypes<T, T2>::supertype,
274  asd>
276 };
277 template <typename T, typename D, bool asd>
278 struct ScalarTraits<MetaPhysicL::DualNumber<T, D, asd>>
279 {
280  static const bool value = ScalarTraits<T>::value;
281 };
282 } // namespace libMesh
283 
284 #endif // LIBMESH_HAVE_METAPHYSICL
285 
286 #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:52
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:64
static const bool value
Definition: compare_types.h:96
MetaPhysicL::DualNumber< typename CompareTypes< T, T2 >::supertype, typename D::template rebind< typename CompareTypes< T, T2 >::supertype >::other, asd > supertype