libMesh
Loading...
Searching...
No Matches
float128_shims.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#ifndef LIBMESH_FLOAT128_SHIMS_H
19#define LIBMESH_FLOAT128_SHIMS_H
20
21// The library configuration options
22#include "libmesh/libmesh_config.h"
23
24#ifdef LIBMESH_DEFAULT_QUADRUPLE_PRECISION
25
26# include <boost/multiprecision/float128.hpp>
27
28// Boost doesn't add float128 overloads to namespace std. But, we
29// expect to be able to explicitly specify std::foo(Real) in trailing
30// return types, where a using-declaration + ADL isn't an option. So
31// we add overloads ourselves.
32namespace std
33{
34#define LIBMESH_FLOAT128_UNARY(funcname) \
35inline boost::multiprecision::float128 funcname \
36 (const boost::multiprecision::float128 in) \
37{ \
38 return boost::multiprecision::funcname(in); \
39}
40
41#define LIBMESH_FLOAT128_MATH_BOOL(funcname) \
42inline bool funcname \
43 (const boost::multiprecision::float128 in) \
44{ \
45 return boost::math::funcname(in); \
46}
47
48#define LIBMESH_FLOAT128_BINARY(funcname) \
49inline boost::multiprecision::float128 funcname \
50 (const boost::multiprecision::float128 in1, \
51 const boost::multiprecision::float128 in2) \
52{ \
53 return boost::multiprecision::funcname(in1, in2); \
54}
55
73// LIBMESH_FLOAT128_UNARY(norm)
74
75inline boost::multiprecision::float128 norm
76 (const boost::multiprecision::float128 in)
77{
78 return in * in;
79}
80
81inline boost::multiprecision::float128 real
82 (const boost::multiprecision::float128 in)
83{
84 return in;
85}
86
87inline boost::multiprecision::float128 imag
88 (const boost::multiprecision::float128 /*in*/)
89{
90 return 0;
91}
92
93template <>
94struct plus<boost::multiprecision::float128>
95{
96 boost::multiprecision::float128 operator ()
97 (const boost::multiprecision::float128 a,
98 const boost::multiprecision::float128 b)
99 {
100 return a + b;
101 }
102};
103
104template <>
105struct multiplies<boost::multiprecision::float128>
106{
107 boost::multiprecision::float128 operator ()
108 (const boost::multiprecision::float128 a,
109 const boost::multiprecision::float128 b)
110 {
111 return a * b;
112 }
113};
114
115
118
119// Shimming modf by hand since Boost didn't add a shim until 1.62 and
120// I'd like to still support systems with older Boost in /usr/include/
121inline boost::multiprecision::float128 modf
122 (const boost::multiprecision::float128 in,
123 boost::multiprecision::float128 * intpart)
124{
125#ifdef BOOST_MP_USE_QUAD
126 return __modfq(in.backend().value(), &intpart->backend().value());
127#elif defined(BOOST_MP_USE_FLOAT128)
128 return modfq(in.backend().value(), &intpart->backend().value());
129#endif
130}
131
134// LIBMESH_FLOAT128_BINARY(max)
135// LIBMESH_FLOAT128_BINARY(min)
137
138inline boost::multiprecision::float128 pow
139 (const boost::multiprecision::float128 in1,
140 const int in2)
141{
142 return boost::multiprecision::pow(in1, in2);
143}
144
145// Boost float128 leaves a lot of C++11 math undefined? So we'll just
146// add shims as we need them, for maximum compatibility with older
147// Boost versions.
148
149// Stuff that was defined as far back as I've tested:
152
153// log1p was added in Boost 1.63
154#if BOOST_VERSION > 106300
156#endif
157
158// This doesn't take Real->Real:
159inline long long llround
160 (const boost::multiprecision::float128 in)
161{
162 return boost::multiprecision::llround(in);
163}
164
165// Stuff that wasn't, that we don't need yet:
166// LIBMESH_FLOAT128_UNARY(exp2)
167// LIBMESH_FLOAT128_UNARY(expm1)
168// LIBMESH_FLOAT128_UNARY(log2)
169// LIBMESH_FLOAT128_UNARY(cbrt)
170// LIBMESH_FLOAT128_UNARY(asinh)
171// LIBMESH_FLOAT128_UNARY(acosh)
172// LIBMESH_FLOAT128_UNARY(atanh)
173// LIBMESH_FLOAT128_UNARY(erf)
174// LIBMESH_FLOAT128_UNARY(erfc)
175// LIBMESH_FLOAT128_UNARY(nearbyint)
176// LIBMESH_FLOAT128_UNARY(rint)
177
178// LIBMESH_FLOAT128_BINARY(remainder)
179// LIBMESH_FLOAT128_BINARY(fmax)
180// LIBMESH_FLOAT128_BINARY(fmin)
181// LIBMESH_FLOAT128_BINARY(fdim)
182// LIBMESH_FLOAT128_BINARY(hypot)
183
184}
185
186#endif // LIBMESH_DEFAULT_QUADRUPLE_PRECISION
187
188#endif // LIBMESH_FLOAT128_SHIMS_H
static const Real b
boost::multiprecision::float128 real(const boost::multiprecision::float128 in)
boost::multiprecision::float128 imag(const boost::multiprecision::float128)
auto norm(const libMesh::TypeVector< T > &vector) -> decltype(std::norm(T()))
LIBMESH_FLOAT128_MATH_BOOL(isinf) LIBMESH_FLOAT128_MATH_BOOL(isnan) inline boost
LIBMESH_FLOAT128_UNARY(sqrt) LIBMESH_FLOAT128_UNARY(exp) LIBMESH_FLOAT128_UNARY(log) LIBMESH_FLOAT128_UNARY(log10) LIBMESH_FLOAT128_UNARY(sin) LIBMESH_FLOAT128_UNARY(cos) LIBMESH_FLOAT128_UNARY(tan) LIBMESH_FLOAT128_UNARY(asin) LIBMESH_FLOAT128_UNARY(acos) LIBMESH_FLOAT128_UNARY(atan) LIBMESH_FLOAT128_UNARY(sinh) LIBMESH_FLOAT128_UNARY(cosh) LIBMESH_FLOAT128_UNARY(tanh) LIBMESH_FLOAT128_UNARY(abs) LIBMESH_FLOAT128_UNARY(fabs) LIBMESH_FLOAT128_UNARY(ceil) LIBMESH_FLOAT128_UNARY(floor) inline boost
LIBMESH_FLOAT128_BINARY(pow) LIBMESH_FLOAT128_BINARY(atan2) LIBMESH_FLOAT128_BINARY(fmod) inline boost