Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
HPReal.h
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* HPReal.h (C) 2000-2019 */
9/* */
10/* High-precision real number. */
11/*---------------------------------------------------------------------------*/
12#ifndef ARCANE_UTILS_HPREAL_H
13#define ARCANE_UTILS_HPREAL_H
14/*---------------------------------------------------------------------------*/
15/*---------------------------------------------------------------------------*/
16
17#include "arcane/utils/Numeric.h"
18
19#include <iosfwd>
20
21/*---------------------------------------------------------------------------*/
22/*---------------------------------------------------------------------------*/
23
24namespace Arcane
25{
26
27/*---------------------------------------------------------------------------*/
28/*---------------------------------------------------------------------------*/
29
158class ARCANE_UTILS_EXPORT HPReal
159{
160 public:
161
166
168 explicit HPReal(double avalue)
169 : m_value(avalue)
170 , m_correction(0.0)
171 {}
172
174 HPReal(double avalue, double acorrection)
175 : m_value(avalue)
176 , m_correction(acorrection)
177 {}
178
180 Real value() const { return m_value; }
181
183 Real correction() const { return m_correction; }
184
187 {
188 *this = accumulate(v, *this);
189 }
190
192 inline void operator+=(HPReal v)
193 {
194 *this = reduce(*this, v);
195 }
196
198 inline Real toReal() const
199 {
200 return value() + correction();
201 }
202
205 {
206 return reduce(*this, b);
207 }
208
211 {
212 *this = product(v, *this);
213 }
214
216 inline void operator*=(HPReal v)
217 {
218 *this = product(*this, v);
219 }
220
223 {
224 *this = div2(v, *this);
225 }
226
228 inline void operator/=(HPReal v)
229 {
230 *this = div2(*this, v);
231 }
232
237 std::istream& assign(std::istream& i);
239 std::ostream& print(std::ostream& o) const;
241 std::ostream& printPretty(std::ostream& o) const;
242
243 public:
244
246 static HPReal zero() { return HPReal(0.0); }
247
248 public:
249
250 static HPReal accumulate(Real a, HPReal b)
251 {
252 HPReal x(_doTwoSum(a, b.value()));
253 Real c = x.correction() + b.correction();
254 return _doQuickTwoSum(x.value(), c);
255 }
256
257 // Mpi passes through
258 static HPReal reduce(HPReal a, HPReal b)
259 {
260 HPReal x(_doTwoSum(a.value(), b.value()));
261 Real c = x.correction() + a.correction() + b.correction();
262 return _doQuickTwoSum(x.value(), c);
263 }
264
265 // algo 11 of AC_TWOPRODUCTS Ref 2
266 static HPReal product(HPReal a, HPReal b)
267 {
268 HPReal x(_doTwoProducts(a.value(), b.value()));
269 Real w = x.correction() + (a.value() * b.correction() + b.value() * a.correction());
270 return HPReal(x.value(), w);
271 }
272 // algo 11 of AC_TWOPRODUCTS Ref 2
273 static HPReal product(Real a, HPReal b)
274 {
275 HPReal x(_doTwoProducts(a, b.value()));
276 Real w = x.correction() + (a * b.correction());
277 return HPReal(x.value(), w);
278 }
279
280 // algo div2 Ref 6 div2 = a/b
281 // I put parentheses in the evaluation of w to force an order sometimes the compiler options
282 // ATTENTION the last 2 lines of the div2 algorithm are not included (we do not renormalize)
283 // The "mul2" algorithm also contains them and did not include them for "product" because algorithm 11 of Ref 2 does not have them (in my humble opinion)
284 static HPReal div2(HPReal a, HPReal b)
285 {
286 Real c = a.value() / b.value();
287 HPReal u(_doTwoProducts(c, b.value()));
288 Real w = ((((a.value() - u.value()) + -u.correction()) + a.correction()) - c * b.correction()) / b.value();
289 return HPReal(c, w);
290 }
291 // algo div2 Ref 6 div2 = a/b
292 static HPReal div2(Real b, HPReal a)
293 {
294 Real c = a.value() / b;
295 HPReal u(_doTwoProducts(c, b));
296 Real w = (((a.value() - u.value()) + -u.correction()) + a.correction()) / b;
297 return HPReal(c, w);
298 }
299
300 private:
301
302 Real m_value;
303 Real m_correction;
304
305 private:
306
307 // Correction of ()
308 static HPReal _doTwoSum(Real a, Real b)
309 {
310 Real value = a + b;
311 Real approx_b = value - a;
312 Real sum_error = (a - (value - approx_b)) + (b - approx_b);
313 return HPReal(value, sum_error);
314 }
315 // correction tests of the values of a and b and we put absolute values
316 static HPReal _doQuickTwoSum(Real a1, Real b1)
317 {
318 Real a = a1;
319 Real b = b1;
320 if (std::abs(b1) > std::abs(a1)) {
321 a = b1;
322 b = a1;
323 }
324 Real value = a + b;
325 Real error_value = (b - (value - a));
326 return HPReal(value, error_value);
327 }
328 // algorithm 4 ref 2 or algorithm 2.4 ref 3 or algorithm 6 p.4
329 static HPReal _doTwoProducts(Real a, Real b)
330 {
331 Real x = a * b;
332 HPReal aw = SPLIT(a);
333 HPReal bw = SPLIT(b);
334 Real y = aw.correction() * bw.correction() - (((x - aw.value() * bw.value()) - aw.correction() * bw.value()) - aw.value() * bw.correction());
335 return HPReal(x, y);
336 }
337 static HPReal SPLIT(Real a)
338 {
339 const Real f = 134217729; // 1+ 2^ceil(52/2);
340 Real c = f * a;
341 Real x = c - (c - a);
342 Real y = a - x;
343 return HPReal(x, y);
344 }
345};
346
347/*---------------------------------------------------------------------------*/
348/*---------------------------------------------------------------------------*/
349
350inline bool
351operator<(const HPReal& a, const HPReal& b)
352{
353 return a.toReal() < b.toReal();
354}
355
356inline bool
357operator>(const HPReal& a, const HPReal& b)
358{
359 return a.toReal() > b.toReal();
360}
361
362inline bool
363operator==(const HPReal& a, const HPReal& b)
364{
365 return a.value() == b.value() && a.correction() == b.correction();
366}
367
368inline bool
369operator!=(const HPReal& a, const HPReal& b)
370{
371 return !operator==(a, b);
372}
373
374inline HPReal
375operator+(const HPReal& a, const HPReal& b)
376{
377 return HPReal::reduce(a, b);
378}
379
380/*---------------------------------------------------------------------------*/
381/*---------------------------------------------------------------------------*/
382
383inline std::ostream&
384operator<<(std::ostream& o, HPReal t)
385{
386 return t.printPretty(o);
387}
388
389inline std::istream&
390operator>>(std::istream& i, HPReal& t)
391{
392 return t.assign(i);
393}
394
395/*---------------------------------------------------------------------------*/
396/*---------------------------------------------------------------------------*/
397
398} // End namespace Arcane
399
400/*---------------------------------------------------------------------------*/
401/*---------------------------------------------------------------------------*/
402
403#endif
Class implementing a High-Precision real number.
Definition HPReal.h:159
void operator*=(HPReal v)
Multiplies an HPReal v while preserving the error (reduction).
Definition HPReal.h:216
HPReal()
Default constructor without initialization.
Definition HPReal.h:165
static HPReal zero()
Zero value.
Definition HPReal.h:246
HPReal reduce(HPReal b) const
Adds an HPReal v while preserving the error (reduction).
Definition HPReal.h:204
Real toReal() const
Converts the instance to a Real.
Definition HPReal.h:198
void operator+=(Real v)
Adds a Real while preserving the error.
Definition HPReal.h:186
HPReal(double avalue)
Creates an HP real with the value value and the correction correction.
Definition HPReal.h:168
void operator/=(Real v)
Multiplies a Real while preserving the error.
Definition HPReal.h:222
void operator+=(HPReal v)
Adds an HPReal v while preserving the error (reduction).
Definition HPReal.h:192
HPReal(double avalue, double acorrection)
Creates an HP real with the value value and the correction correction.
Definition HPReal.h:174
Real correction() const
Internal correction.
Definition HPReal.h:183
void operator*=(Real v)
Multiplies a Real while preserving the error.
Definition HPReal.h:210
void operator/=(HPReal v)
Multiplies an HPReal v while preserving the error (reduction).
Definition HPReal.h:228
Real value() const
Internal value. Generally, you must use toReal().
Definition HPReal.h:180
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
bool operator<(const Item &item1, const Item &item2)
Compare two entities.
Definition Item.h:566
std::istream & operator>>(std::istream &istr, eItemKind &item_kind)
Input operator from a stream.
double Real
Type representing a real number.