GCC Code Coverage Report


Directory: include/polyfloat/
File: include/polyfloat/module/math/logspace_sub.hpp
Date: 2026-11-09 15:28:50
Exec Total Coverage
Lines: 18 18 100.0%
Functions: 56 56 100.0%
Branches: 10 12 83.3%

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/math/pow_abs.hpp>
15
16 namespace plf
17 {
18
19 template<typename Options>
20 struct logspace_sub_t : eve::strict_tuple_callable<logspace_sub_t, Options, raw_option, pedantic_option>
21 {
22 template<typename... Ts> struct result : as_polyfloat_like<Ts...>
23 {
24 };
25
26 template<concepts::polyfloat_like... Ts>
27 requires(eve::same_lanes_or_scalar<Ts...>)
28 86 POLYFLOAT_ABI typename result<Ts...>::type constexpr operator()(Ts... ts) const noexcept
29 {
30 86 return POLYFLOAT_CALL(ts...);
31 }
32
33 template<eve::non_empty_product_type Tup>
34 requires(eve::same_lanes_or_scalar_tuple<Tup> && !concepts::polyfloat_like<Tup>)
35 POLYFLOAT_ABI constexpr kumi::apply_traits_t<result, Tup> operator()(Tup const& t) const noexcept
36 requires(kumi::size_v<Tup> >= 1)
37 {
38 return POLYFLOAT_CALL(t);
39 }
40
41 86 POLYFLOAT_CALLABLE_OBJECT(logspace_sub_t, logspace_sub_);
42 };
43 //======================================================================================================================
44 //! @addtogroup math
45 //! @{
46 //! @var logspace_sub
47 //! @brief object computing the logspace_sub operation: \f$\log\left(e^{\log x_0}-\sum_{i = 1}^n e^{\log x_i}\right)\f$.
48 //!
49 //! @groupheader{Header file}
50 //!
51 //! @code
52 //! #include <polyfloat/core.hpp>
53 //! @endcode
54 //!
55 //! @groupheader{Callable Signatures}
56 //!
57 //! @code
58 //! namespace polyfloat
59 //! {
60 //! template<polyfloat::concepts::polyfloat_like Z, polyfloat_like ... Zs> constexpr auto logspace_sub(Z z, Zs... zs) noexcept;
61 //! }
62 //! @endcode
63 //!
64 //! **Parameters**
65 //!
66 //! * `z, zs...`: Values to process.
67 //!
68 //! **Return value**
69 //!
70 //! Returns the sum of the arguments.
71 //!
72 //! @groupheader{Example}
73 //!
74 //! @godbolt{doc/math/logspace_sub.cpp}
75 //======================================================================================================================
76
77 inline constexpr auto logspace_sub = eve::functor<logspace_sub_t>;
78 //======================================================================================================================
79 //! @}
80 //======================================================================================================================
81 }
82
83 namespace plf::_
84 {
85 template<typename T0, eve::callable_options O>
86 constexpr auto logspace_sub_(POLYFLOAT_DELAY(), O const&, T0 t0) noexcept
87 {
88 return plf::abs(t0);
89 }
90
91 template<typename T0, typename T1, typename... Ts, eve::callable_options O>
92 86 constexpr auto logspace_sub_(POLYFLOAT_DELAY(), O const& o, T0 const& t0, T1 const& t1, Ts... ts) noexcept
93 {
94 using r_t = as_polyfloat_like_t<T0, T1, Ts...>;
95 using e_t = eve::element_type_t<r_t>;
96 60 auto cvt = [](auto a) { return plf::convert(a, eve::as<e_t>()); };
97 if constexpr (sizeof...(Ts) == 0)
98 {
99 60 auto r0 = cvt(t0);
100 60 auto r1 = cvt(t1);
101 60 auto x = r1 - r0;
102 60 auto test = x > -log_2(as(x));
103
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
60 if (eve::all(test)) return r0 + plf::log(-plf::expm1(x));
104
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
60 else if (eve::any(test)) return r0 + if_else(test, log[o](-expm1(x)), plf::log[o](plf::oneminus(exp(x))));
105 60 else return r0 + plf::log(plf::oneminus(plf::exp(x)));
106 }
107 else
108 {
109 26 r_t that(logspace_sub[o](t0, t1));
110 13 auto lsub = [o](auto that_, auto next) -> r_t {
111
8/8
✓ Branch 1 taken 2 times.
✓ Branch 5 taken 2 times.
✓ Branch 9 taken 1 times.
✓ Branch 13 taken 2 times.
✓ Branch 17 taken 1 times.
✓ Branch 21 taken 2 times.
✓ Branch 25 taken 1 times.
✓ Branch 29 taken 2 times.
13 that_ = logspace_sub[o](that_, next);
112 13 return that_;
113 };
114 26 ((that = lsub(that, ts)), ...);
115 26 return that;
116 }
117 }
118 }
119