GCC Code Coverage Report


Directory: include/polyfloat/
File: include/polyfloat/module/core/two_add.hpp
Date: 2026-11-09 15:28:50
Exec Total Coverage
Lines: 9 9 100.0%
Functions: 27 27 100.0%
Branches: 0 0 -%

Line Branch Exec Source
1 //======================================================================================================================
2 /*
3 POLYFLOAT - Extended precision floating points
4 Copyright : POLYFLOAT Contributors & Maintainers
5 SPDX-License-Identifier: BSL-1.0
6 */
7 //======================================================================================================================
8 #pragma once
9
10 #include <polyfloat/details/callable.hpp>
11 #include <polyfloat/types/concepts.hpp>
12 #include <polyfloat/types/traits.hpp>
13 #include <type_traits>
14 #include <polyfloat/module/core/if_else.hpp>
15 #include <polyfloat/module/core/is_not_finite.hpp>
16
17 namespace plf
18 {
19
20 template<typename Options>
21 struct two_add_t : eve::strict_tuple_callable<two_add_t, Options, raw_option, pedantic_option>
22 {
23 template<concepts::polyfloat_like T>
24 28054 POLYFLOAT_ABI typename eve::zipped<T, T> constexpr operator()(T t0, T t1) const noexcept
25 {
26 28054 return POLYFLOAT_CALL(t0, t1);
27 }
28
29 28054 POLYFLOAT_CALLABLE_OBJECT(two_add_t, two_add_);
30 };
31 //================================================================================================
32 //! @addtogroup core_accuracy
33 //! @{
34 //! @var two_add
35 //! @brief Computes the [elementwise](@ref glossary_elementwise) pair consisting of the
36 //! sum and its resulting rounding error.
37 //!
38 //! @groupheader{Header file}
39 //!
40 //! @code
41 //! #include <eve/module/core.hpp>
42 //! @endcode
43 //!
44 //! @groupheader{Callable Signatures}
45 //!
46 //! @code
47 //! namespace eve
48 //! {
49 //! // Regular overload
50 //! constexpr auto two_add( auto x, auto y) noexcept; // 1
51 //! constexpr auto two_add[raw](auto x, auto y) noexcept; // 2
52 //!
53 //! // Semantic options
54 //! constexpr auto two_add[pedantic](floating_value auto x, floating_value auto y) noexcept; // 3
55 //! }
56 //! @endcode
57 //!
58 //! **Parameters**
59 //!
60 //! * `x`, `y`: polyfloatt arguments](@ref eve::floating_value) of same dimension.
61 //!
62 //! **Return value**
63 //!
64 //! Computes [elementwise](@ref glossary_elementwise) a pair of values `[a,e]` such that:
65 //! * `a` is `x+y`
66 //! * `e` is a value such that `a`\f$\oplus\f$`e` is equal to `x`\f$\oplus\f$`y`,
67 //! where \f$\oplus\f$ adds its two parameters with infinite precision.
68 //!
69 //! The algorithm depends on the overload:
70 //!
71 //! 1. Classical algorithm, always valid.
72 //! 2. 'Fast' algorithm, valid only if |x| < |y|.
73 //! 3. Handles overflow.
74 //!
75 //! @groupheader{External references}
76 //! * [On the Computation of Correctly-Rounded Sums](https://www.vinc17.net/research/papers/rr_ccrsums2.pdf)
77 //!
78 //! @groupheader{Example}
79 //! @godbolt_todo{doc/core/core/two_add.cpp}
80 //================================================================================================
81 inline constexpr auto two_add = eve::functor<two_add_t>;
82 //================================================================================================
83 //! @}
84 //================================================================================================
85
86 namespace _
87 {
88 28054 template<typename T, eve::callable_options O> constexpr auto two_add_(POLYFLOAT_DELAY(), O const&, T a, T b)
89 {
90 28054 auto r0 = a + b;
91 28022 T err;
92 if constexpr (O::contains(raw)) // 2fp, this does not work if |a| < |b| (or if radix is not 2, not our case)
93 {
94 err = b - (r0 - a);
95 }
96 else //6fp always ok
97 {
98 28054 auto z = r0 - a;
99 28054 err = a - (r0 - z) + (b - z);
100 }
101 if constexpr (eve::platform::supports_infinites && O::contains(pedantic))
102 err = if_else(is_not_finite(err) || is_not_finite(r0), eve::zero, err);
103 28054 return eve::zip(r0, err);
104 }
105 }
106 }
107