Dune Core Modules (unstable)

bigfloat.hh
Go to the documentation of this file.
1// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2// vi: set et ts=4 sw=2 sts=2:
3// SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root
4// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
5#ifndef DUNE_COMMON_BIGFLOAT_HH
6#define DUNE_COMMON_BIGFLOAT_HH
7
12#if HAVE_MPFR
13// The BigFloat type requires MPFR to be found and enabled. Use find_package(MPFR) and
14// add_dune_mpfr_flags(target) in CMake to activate this package on your target.
15
16#include <compare>
17#include <limits>
18#include <type_traits>
19
20#include <mpreal.h>
21
22#include <dune/common/math.hh>
24#include <dune/common/quadmath.hh>
27
28namespace Dune
29{
34 template< unsigned int precision >
35 class BigFloat
36 : public mpfr::mpreal
37 {
38 using Base = mpfr::mpreal;
39 using Prec = mp_prec_t;
40
41 static_assert(precision > 0 && precision < std::numeric_limits<Prec>::max());
42
43 public:
45 BigFloat () noexcept
46 : Base(0, Prec(precision))
47 {}
48
53 explicit BigFloat (const char* str)
54 : Base(str, Prec(precision))
55 {}
56
58 BigFloat (const Base& v) noexcept
59 : Base(v)
60 {}
61
63 BigFloat (Base&& v) noexcept
64 : Base(std::move(v))
65 {}
66
68 template <class T,
69 std::enable_if_t<std::is_arithmetic_v<T>,int> = 0>
70 BigFloat (const T& v) noexcept
71 : Base(v, Prec(precision))
72 {}
73
74#if HAVE_QUADMATH
76 BigFloat (const Dune::Float128& v)
77 : Base([](const Dune::Float128& v) {
78 std::ostringstream oss; oss << v;
79 return oss.str();
80 }(v), Prec(precision))
81 {}
82#endif
83
84 BigFloat (const BigFloat&) = default;
85 BigFloat (BigFloat&&) = default;
86
88 template <class T,
89 std::enable_if_t<std::is_arithmetic_v<T>,int> = 0>
90 BigFloat& operator= (const T& v) noexcept
91 {
92 static_cast<Base&>(*this) = v;
93 return *this;
94 }
95
96#if HAVE_QUADMATH
98 BigFloat& operator= (const Dune::Float128& v)
99 {
100 std::ostringstream oss; oss << v;
101 static_cast<Base&>(*this) = oss.str();
102 return *this;
103 }
104#endif
105
106 BigFloat& operator= (const BigFloat&) = default;
107 BigFloat& operator= (BigFloat&&) = default;
108
110 template <unsigned int p1, unsigned int p2>
111 friend bool operator== (const BigFloat<p1>& A, const BigFloat<p2>& B)
112 {
113 const Base& a = static_cast<const Base&>(A);
114 const Base& b = static_cast<const Base&>(B);
115 return a == b;
116 }
117
119 template <unsigned int p1, unsigned int p2>
120 friend std::partial_ordering operator<=> (const BigFloat<p1>& A, const BigFloat<p2>& B)
121 {
122 const Base& a = static_cast<const Base&>(A);
123 const Base& b = static_cast<const Base&>(B);
124 if (isnan(a) || isnan(b))
125 return std::partial_ordering::unordered;
126 if (a < b)
127 return std::partial_ordering::less;
128 if (a > b)
129 return std::partial_ordering::greater;
130 return std::partial_ordering::equivalent;
131 }
132
134 template <class T,
135 std::enable_if_t<std::is_arithmetic_v<T>,int> = 0>
136 explicit operator T () const
137 {
138#ifdef MPREAL_HAVE_EXPLICIT_CONVERTERS
139 return T(static_cast<const Base&>(*this));
140#else
141 if constexpr(std::is_same_v<T,bool>)
142 return this->toBool();
143 else if constexpr(std::is_same_v<T,long long>)
144 return this->toLLong();
145 else if constexpr(std::is_same_v<T,unsigned long long>)
146 return this->toULLong();
147 else if constexpr(std::is_signed_v<T>) // e.g. long
148 return T(this->toLong());
149 else if constexpr(std::is_unsigned_v<T>) // e.g. unsigned long
150 return T(this->toULong());
151 else if constexpr(std::is_same_v<T,float>)
152 return this->toFloat();
153 else if constexpr(std::is_same_v<T,double>)
154 return this->toDouble();
155 else if constexpr(std::is_floating_point_v<T>) // e.g. long double
156 return T(this->toLDouble());
157 else {
158 DUNE_ASSUME(false);
159 return T{};
160 }
161#endif
162 }
163
164#if HAVE_QUADMATH
166 explicit operator Dune::Float128 () const
167 {
168 const int n = std::numeric_limits<Dune::Impl::Float128>::max_digits10;
169 return Float128(this->toString(n,10).c_str());
170 }
171#endif
172 };
173
174} // end namespace Dune
175
176
177namespace Dune
178{
179 template <unsigned int precision>
180 struct IsNumber<BigFloat<precision>>
181 : public std::true_type {};
182
183 template <unsigned int precision1, unsigned int precision2>
184 struct PromotionTraits<BigFloat<precision1>, BigFloat<precision2>>
185 {
186 using PromotedType = BigFloat<(precision1 > precision2 ? precision1 : precision2)>;
187 };
188
189 template <unsigned int precision>
190 struct PromotionTraits<BigFloat<precision>,BigFloat<precision>>
191 {
192 using PromotedType = BigFloat<precision>;
193 };
194
195 template <unsigned int precision, class T>
196 struct PromotionTraits<BigFloat<precision>, T>
197 {
198 using PromotedType = BigFloat<std::max<unsigned int>(8*sizeof(T), precision)>;
199 };
200
201 template <class T, unsigned int precision>
202 struct PromotionTraits<T, BigFloat<precision>>
203 {
204 using PromotedType = BigFloat<std::max<unsigned int>(8*sizeof(T), precision)>;
205 };
206
207
208 template< unsigned int precision >
209 struct MathematicalConstants<BigFloat<precision>>
210 {
211 using T = BigFloat<precision>;
212 static const T e ()
213 {
214 return exp(T(1));
215 }
216
217 static const T pi ()
218 {
219 return mpfr::const_pi(mp_prec_t(precision));
220 }
221 };
222
223} // end namespace Dune
224
225namespace std
226{
227 template <unsigned int precision>
228 inline void swap (Dune::BigFloat<precision>& x, Dune::BigFloat<precision>& y)
229 {
230 return mpfr::swap(x, y);
231 }
232
234 template <unsigned int precision>
235 class numeric_limits<Dune::BigFloat<precision>>
236 : public numeric_limits<mpfr::mpreal>
237 {
238 using type = Dune::BigFloat<precision>;
239 using Base = numeric_limits<mpfr::mpreal>;
240
241 static constexpr int bits2digits (int prec)
242 {
243 constexpr double LOG10_2 = 0.301029995663981195213738894724493;
244 return int(prec * LOG10_2);
245 }
246
247 public:
248 inline static type min () { return mpfr::minval(precision); }
249 inline static type max () { return mpfr::maxval(precision); }
250 inline static type lowest () { return -mpfr::maxval(precision); }
251 inline static type epsilon () { return mpfr::machine_epsilon(precision); }
252 inline static type round_error () { return Base::round_error(precision); }
253
254 static constexpr int digits = int(precision);
255 static constexpr int digits10 = bits2digits(precision);
256 static constexpr int max_digits10 = bits2digits(precision);
257 };
258
259} // end namespace std
260
261#else // HAVE_MPFR
262
264
265namespace Dune
266{
267 template< unsigned int precision >
268 class BigFloat
269 {
270 static_assert(AlwaysFalse<BigFloat<precision>>::value,
271 "The BigFloat type requires MPFR to be found and enabled. Use find_package(MPFR) and add_dune_mpfr_flags(target) in CMake to activate this package on your target.");
272 };
273
274} // end namespace std
275
276#endif // HAVE_MPFR
277#endif // DUNE_COMMON_BIGFLOAT_HH
Provide the macro DUNE_ASSUME(...) that is a portable assume expression as a hint for the compiler/op...
std::string toString(Precision p)
map precision to VTK type name
Definition: common.hh:280
constexpr auto max
Function object that returns the greater of the given values.
Definition: hybridutilities.hh:489
constexpr auto min
Function object that returns the smaller of the given values.
Definition: hybridutilities.hh:511
constexpr EnableIfInterOperable< T1, T2, bool >::type operator==(const ForwardIteratorFacade< T1, V1, R1, D > &lhs, const ForwardIteratorFacade< T2, V2, R2, D > &rhs)
Checks for equality.
Definition: iteratorfacades.hh:238
Some useful basic math stuff.
Dune namespace
Definition: alignedallocator.hh:13
STL namespace.
Compute type of the result of an arithmetic operation involving two different number types.
static const Field e()
Euler's number.
Definition: math.hh:38
static const Field pi()
Archimedes' constant.
Definition: math.hh:48
Traits for type conversions and type information.
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden & Uni Heidelberg  |  generated with Hugo v0.111.3 (Jun 15, 23:13, 2026)