GCC Code Coverage Report


Directory: include/polyfloat/
File: include/polyfloat/module/core/diff.hpp
Date: 2026-11-09 15:28:50
Exec Total Coverage
Lines: 20 20 100.0%
Functions: 154 154 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/cumfun.hpp>
15 #include <polyfloat/module/core/sub.hpp>
16
17 namespace plf
18 {
19
20 template<typename Options> struct diff_t : eve::callable<diff_t, Options, raw_option, pedantic_option>
21 {
22 template<std::size_t N, typename... Ts> struct result;
23
24 template<size_t N, size_t SZ> static constexpr size_t sz = SZ > N ? SZ - N : 0;
25
26 template<std::size_t N, concepts::polyfloat_like... Ts>
27 struct result<N, Ts...> : kumi::result::fill<sz<N, sizeof...(Ts)>, plf::as_polyfloat_like_t<Ts...>>
28 {
29 };
30
31 template<std::size_t N, eve::same_lanes_or_scalar_tuple Tup>
32 struct result<N, Tup> : kumi::result::fill<sz<N, kumi::size_v<Tup>>, kumi::apply_traits_t<as_polyfloat_like, Tup>>
33 {
34 };
35
36 template<eve::same_lanes_or_scalar_tuple Tup>
37 62 POLYFLOAT_ABI typename result<1, Tup>::type constexpr operator()(Tup const& t) const noexcept
38 {
39 62 return POLYFLOAT_CALL(t);
40 }
41
42 template<std::size_t N, eve::same_lanes_or_scalar_tuple Tup>
43 36 POLYFLOAT_ABI typename result<N, Tup>::type constexpr operator()(kumi::index_t<N>, Tup const& t) const noexcept
44 {
45 36 return POLYFLOAT_CALL(kumi::index_t<N>{}, t);
46 }
47
48 template<concepts::polyfloat_like... Ts>
49 requires(eve::same_lanes_or_scalar<Ts...>)
50 13 POLYFLOAT_ABI typename result<1, Ts...>::type constexpr operator()(Ts const&... ts) const noexcept
51 {
52 13 return POLYFLOAT_CALL(kumi::make_tuple(ts...));
53 }
54
55 template<size_t N, concepts::polyfloat_like... Ts>
56 requires(eve::same_lanes_or_scalar<Ts...>)
57 24 POLYFLOAT_ABI typename result<N, Ts...>::type constexpr operator()(kumi::index_t<N>, Ts const&... ts) const
58 {
59
1/1
✓ Branch 1 taken 12 times.
24 return POLYFLOAT_CALL(kumi::index_t<N>{}, kumi::make_tuple(ts...));
60 }
61
62 136 POLYFLOAT_CALLABLE_OBJECT(diff_t, diff_);
63 };
64 //======================================================================================================================
65 //! @addtogroup core
66 //! @{
67 //! @var diff
68 //! @brief convert a pack of values into
69 //! a tuple of the cumulative sum of its values
70 //!
71 //! @groupheader{Header file}
72 //!
73 //! @code
74 //! #include <polyfloat/module/core.hpp>
75 //! @endcode
76 //!
77 //! @groupheader{Callable Signatures}
78 //!
79 //! @code
80 //! namespace plf
81 //! {
82 //! constexpr auto diff(auto const& xs...) noexcept; // 1
83 //! constexpr auto diff(eve::non_empty_product_type auto const& x) noexcept; // 1
84 //! typename<auto N> constexpr auto diff(kumi::index_t<N>, auto const& xs...) noexcept; // 2
85 //! typename<auto N> constexpr auto diff(kumi::index_t<N>,eve::non_empty_product_type auto const& x) noexcept; // 2
86 //! }
87 //! @endcode
88 //!
89 //! **Parameters**
90 //!
91 //! * `xs ...` : polyfloat arguments
92 //! * `x` : kumi::tuple of arguments
93 //!
94 //! **Return value**
95 //!
96 //! * 1. Return a tuple containing the elementwise adjacent differences of the parameters or of the elements of the tuple.
97 //! * 2. Return a tuple containing the elementwise Nth adjacent differences of the parameters or of the elements of the tuple.
98 //!
99 //! @groupheader{External references}
100 //! * [Wikipedia divided differences](https://en.cppreference.com/w/cpp/types/integral_constant.html)
101 //!
102 //! @groupheader{Example}
103 //! @godbolt{doc/core/diff.cpp}
104 //================================================================================================
105 inline constexpr auto diff = eve::functor<diff_t>;
106 //================================================================================================
107 //! @}
108 //================================================================================================
109 }
110
111 namespace plf::_
112 {
113 template<eve::non_empty_product_type CHKS> auto internal_dif(CHKS chks)
114 {
115 constexpr auto SZ = CHKS::size();
116 if constexpr (SZ > 3)
117 {
118 auto t0 = get<0>(chks);
119 auto t1 = get<1>(chks);
120 auto v0 = plf::sub(t0, eve::slide_left(t0, t1, eve::index<1>));
121 return kumi::cat(eve::unfold(v0), internal_dif(kumi::pop_front(chks)));
122 }
123 else if constexpr (SZ == 3)
124 {
125 auto t0 = get<0>(chks);
126 auto t1 = get<1>(chks);
127 auto t2 = get<2>(chks);
128 auto v0 = plf::sub(t0, eve::slide_left(t0, t1, eve::index<1>));
129 auto v1 = plf::sub(t1, eve::slide_left(t1, t2, eve::index<1>));
130 auto v2 = plf::sub(t2, eve::slide_left(t2, eve::index<1>));
131 return eve::unfold(v0, v1, v2);
132 }
133 else if constexpr (SZ == 2)
134 {
135 auto t0 = get<0>(chks);
136 auto t1 = get<1>(chks);
137 auto v0 = plf::sub(t0, eve::slide_left(t0, t1, eve::index<1>));
138 auto v1 = plf::sub(t1, eve::slide_left(t1, eve::index<1>));
139 return eve::unfold(v0, v1);
140 }
141 else //if constexpr(SZ == 1)
142 {
143 auto t0 = get<0>(chks);
144 return eve::unfold(eve::sub(t0, eve::slide_left(t0, eve::index<1>)));
145 }
146 }
147
148 template<eve::non_empty_product_type PT, eve::callable_options O>
149 76 POLYFLOAT_NOINLINE constexpr auto diff_(POLYFLOAT_DELAY(), O const&, PT const& x) noexcept
150 {
151 using r_t = kumi::apply_traits_t<as_polyfloat_like, PT>;
152 using u_t = eve::element_type_t<r_t>;
153 165 auto cvt = [](auto a) { return plf::convert(a, as<u_t>()); };
154 241 auto xx = kumi::map([cvt](auto m) { return cvt(m); }, x);
155 92 return kumi::map(eve::sub, kumi::pop_back(xx), kumi::pop_front(xx));
156 }
157
158 template<std::size_t N, eve::non_empty_product_type PT, eve::callable_options O>
159 60 POLYFLOAT_NOINLINE constexpr auto diff_(POLYFLOAT_DELAY(), O const&, kumi::index_t<N>, PT const& x) noexcept
160 {
161 using r_t = kumi::apply_traits_t<plf::as_polyfloat_like, PT>;
162 using u_t = eve::element_type_t<r_t>;
163 140 auto cvt = [](auto a) { return plf::convert(a, as<u_t>()); };
164 200 auto xx = kumi::map([cvt](auto m) { return cvt(m); }, x);
165 2 if constexpr (N >= kumi::size_v<PT>) return kumi::tuple{};
166 2 else if constexpr (N == 0) return xx;
167 else
168 {
169 30 if constexpr (N == 1) return diff(xx);
170 26 else return diff(kumi::index_t<N - 1>{}, diff(xx));
171 }
172 }
173
174 template<plf::concepts::polyfloat_like... Ts, eve::callable_options O>
175 POLYFLOAT_NOINLINE constexpr auto diff_(POLYFLOAT_DELAY(), O const&, Ts const&... xs) noexcept
176 {
177 return diff(kumi::make_tuple(xs...));
178 }
179
180 template<std::size_t N, plf::concepts::polyfloat_like... Ts, eve::callable_options O>
181 POLYFLOAT_NOINLINE constexpr auto diff_(POLYFLOAT_DELAY(), O const&, kumi::index_t<N> in, Ts const&... xs) noexcept
182 {
183 return diff(in, kumi::make_tuple(xs...));
184 }
185 }
186