libMesh
Loading...
Searching...
No Matches
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
32namespace libMesh
33{
34
35// Copy of boost's enable_if_c - needed before we had std::enable_if
36#ifdef LIBMESH_ENABLE_DEPRECATED
37namespace boostcopy {
38template <bool B, class T = void>
40 typedef T type;
41};
42
43template <class T>
44struct 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.
52template <typename T1, typename T2>
53struct TypesEqual {
54 static const bool value = false;
55};
56
57template <typename T>
58struct TypesEqual<T,T> {
59 static const bool value = true;
60};
61
62
63// Complete list of scalar classes, needed for disambiguation
64template <typename T>
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
80ScalarTraits_true(unsigned char);
81ScalarTraits_true(unsigned short);
82ScalarTraits_true(unsigned int);
83ScalarTraits_true(unsigned long);
86ScalarTraits_true(long double);
87#ifdef LIBMESH_DEFAULT_QUADRUPLE_PRECISION
89#endif
90
91template<typename T>
92struct 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
96template <typename T>
97struct 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
107RealTraits_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
116template<typename S, typename T>
118 typedef void supertype;
119};
120
121template<typename T>
122struct CompareTypes<T, T> {
123 typedef T supertype;
124};
125
126template<typename T>
127struct CompareTypes<T, std::complex<T>> {
128 typedef std::complex<T> supertype;
129};
130
131template<typename T>
132struct 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
156SUPERTYPE(unsigned char, short);
157SUPERTYPE(unsigned char, int);
158SUPERTYPE(unsigned char, float);
159SUPERTYPE(unsigned char, double);
160SUPERTYPE(unsigned char, long double);
161SUPERTYPE(unsigned short, int);
162SUPERTYPE(unsigned short, float);
163SUPERTYPE(unsigned short, double);
164SUPERTYPE(unsigned short, long double);
165SUPERTYPE(unsigned int, float);
166SUPERTYPE(unsigned int, double);
167SUPERTYPE(unsigned int, long double);
168SUPERTYPE(char, short);
169SUPERTYPE(char, int);
170SUPERTYPE(char, float);
171SUPERTYPE(char, double);
172SUPERTYPE(char, long double);
173SUPERTYPE(short, int);
174SUPERTYPE(short, float);
175SUPERTYPE(short, double);
176SUPERTYPE(short, long double);
177SUPERTYPE(int, float);
178SUPERTYPE(int, double);
179SUPERTYPE(int, long double);
180SUPERTYPE(float, double);
181SUPERTYPE(float, long double);
182SUPERTYPE(double, long double);
183
184#ifdef LIBMESH_DEFAULT_QUADRUPLE_PRECISION
185SUPERTYPE(unsigned char, Real);
186SUPERTYPE(unsigned short, Real);
187SUPERTYPE(unsigned int, Real);
193SUPERTYPE(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
224namespace libMesh
225{
226template <typename T, typename T2, typename D, bool asd>
227struct 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};
234template <typename T, typename D, typename T2, bool asd>
235struct 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};
242template <typename T, typename D, typename T2, typename D2, bool asd>
243struct 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};
250template <typename T, typename D, bool asd>
251struct CompareTypes<MetaPhysicL::DualNumber<T, D, asd>, MetaPhysicL::DualNumber<T, D, asd>>
252{
253 typedef MetaPhysicL::DualNumber<T, D, asd> supertype;
254};
255template <typename T, typename T2, bool asd>
256struct CompareTypes<T, MetaPhysicL::DualNumber<T2, T2, asd>>
257{
258 typedef MetaPhysicL::DualNumber<typename CompareTypes<T, T2>::supertype,
260 asd>
262};
263template <typename T, typename T2, bool asd>
264struct CompareTypes<MetaPhysicL::DualNumber<T, T, asd>, T2>
265{
266 typedef MetaPhysicL::DualNumber<typename CompareTypes<T, T2>::supertype,
268 asd>
270};
271template <typename T, typename T2, bool asd>
272struct CompareTypes<MetaPhysicL::DualNumber<T, T, asd>, MetaPhysicL::DualNumber<T2, T2, asd>>
273{
274 typedef MetaPhysicL::DualNumber<typename CompareTypes<T, T2>::supertype,
276 asd>
278};
279template <typename T, typename D, bool asd>
280struct ScalarTraits<MetaPhysicL::DualNumber<T, D, asd>>
281{
282 static const bool value = ScalarTraits<T>::value;
283};
284template <typename T, typename D, bool asd>
285struct 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
The libMesh namespace provides an interface to certain functionality in the library.
RealTraits_true(float)
SUPERTYPE(unsigned char, short)
ScalarTraits_true(char)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
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
MetaPhysicL::DualNumber< typename CompareTypes< T, T2 >::supertype, typename CompareTypes< T, T2 >::supertype, 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
static const bool value
static const bool value
static const bool value