GCC Code Coverage Report


Directory: include/polyfloat/
File: include/polyfloat/module/core/two_prod.hpp
Date: 2026-11-09 15:28:50
Exec Total Coverage
Lines: 7 7 100.0%
Functions: 3 3 100.0%
Branches: 1 1 100.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 #include <polyfloat/details/inner_fma.hpp>
17
18 namespace plf
19 {
20
21 template<typename Options>
22 struct two_prod_t : eve::strict_tuple_callable<two_prod_t, Options, raw_option, pedantic_option>
23 {
24 template<concepts::polyfloat_like T>
25 4 POLYFLOAT_ABI typename eve::zipped<T, T> constexpr operator()(T t0, T t1) const noexcept
26 {
27 4 return POLYFLOAT_CALL(t0, t1);
28 }
29
30 4 POLYFLOAT_CALLABLE_OBJECT(two_prod_t, two_prod_);
31 };
32 //================================================================================================
33 //! @addtogroup core_accuracy
34 //! @{
35 //! @var two_prod
36 //! @brief Computes the [elementwise](@ref glossary_elementwise) pair consisting of the
37 //! product and its resulting rounding error.
38 //!
39 //! @groupheader{Header file}
40 //!
41 //! @code
42 //! #include <eve/module/core.hpp>
43 //! @endcode
44 //!
45 //! @groupheader{Callable Signatures}
46 //!
47 //! @code
48 //! namespace eve
49 //! {
50 //! // Regular overload
51 //! constexpr auto two_prod( auto x, auto y) noexcept; // 1
52 //! // Semantic options
53 //! constexpr auto two_prod[pedantic](auto x, auto y) noexcept; // 2
54 //! }
55 //! @endcode
56 //!
57 //! **Parameters**
58 //!
59 //! * `x`, `y`: polyfloatt arguments](@ref eve::floating_value) of same dimension.
60 //!
61 //! **Return value**
62 //!
63 //! Computes [elementwise](@ref glossary_elementwise) a pair of values `[a,e]` such that:
64 //! * `a` is `x+y`
65 //! * `e` is a value such that `a`\f$\oplus\f$`e` is equal to `x`\f$\oplus\f$`y`,
66 //! where \f$\oplus\f$ adds its two parameters with infinite precision.
67 //!
68 //! The algorithm depends on the overload:
69 //!
70 //! 1. Classical algorithm, always valid.
71 //! 2. Handles overflow.
72 //!
73 //! @groupheader{External references}
74 //! * [On the Computation of Correctly-Rounded Sums](https://www.vinc17.net/research/papers/rr_ccrsums2.pdf)
75 //!
76 //! @groupheader{Example}
77 //! @godbolt_todo{doc/core/core/two_prod.cpp}
78 //================================================================================================
79 inline constexpr auto two_prod = eve::functor<two_prod_t>;
80 //================================================================================================
81 //! @}
82 //================================================================================================
83
84 namespace _
85 {
86 4 template<typename T, eve::callable_options O> constexpr auto two_prod_(POLYFLOAT_DELAY(), O const&, T a, T b)
87 {
88 4 auto r0 = a * b;
89 if constexpr (dimension_v<T> == 1)
90 {
91 auto e0 = if_else(plf::is_not_finite(r0), zero, eve::fma[pedantic](a, b, -r0));
92 return eve::zip(r0, e0);
93 }
94 else
95 {
96
1/1
✓ Branch 4 taken 4 times.
4 auto e0 = if_else(plf::is_not_finite(r0), zero(eve::as(a)), plf::_::inner_fma(a, b, -r0));
97 8 return eve::zip(r0, e0);
98 }
99 }
100 }
101 }
102