GCC Code Coverage Report


Directory: include/polyfloat/
File: include/polyfloat/module/core/covariance.hpp
Date: 2026-11-09 15:28:50
Exec Total Coverage
Lines: 18 18 100.0%
Functions: 28 28 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/dot.hpp>
15 #include <polyfloat/module/core/average.hpp>
16
17 namespace plf
18 {
19 template<typename Options>
20 struct covariance_t : eve::strict_tuple_callable<covariance_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 8 POLYFLOAT_ABI typename result<Ts...>::type constexpr operator()(Ts... ts) const noexcept
29 {
30 8 return POLYFLOAT_CALL(ts...);
31 }
32
33 template<eve::non_empty_product_type Tup1, eve::non_empty_product_type Tup2>
34 requires(eve::same_lanes_or_scalar_tuple<Tup1> && eve::same_lanes_or_scalar_tuple<Tup2>)
35 12 POLYFLOAT_ABI constexpr kumi::apply_traits_t<result, kumi::result::cat_t<Tup1, Tup2>> operator()(
36 Tup1 const& t1, Tup2 const& t2) const noexcept
37 {
38 12 return POLYFLOAT_CALL(t1, t2);
39 }
40
41 20 POLYFLOAT_CALLABLE_OBJECT(covariance_t, covariance_);
42 };
43 //======================================================================================================================
44 //! @addtogroup core
45 //! @{
46 //! @var covariance
47 //! @brief `elementwise_callable` object computing the elementwise covariance product
48 //! of the vector of the first half parameters by the vector of the last half.
49 //!
50 //! @groupheader{Header file}
51 //!
52 //! @code
53 //! #include <eve/module/core.hpp>
54 //! @endcode
55 //!
56 //! @groupheader{Callable Signatures}
57 //!
58 //! @code
59 //! namespace eve
60 //! {
61 //! // Regular overloads
62 //! constexpr auto covariance(auto xsys...) noexcept; // 1
63 //! constexpr auto covariance(eve::non_empty_product_type xs, eve::non_empty_product_type ys) noexcept; // 2
64 //!
65 //! // Semantic options
66 //! constexpr auto covariance[unbiased](/*any of the above overloads*/) noexcept; // 3
67 //! }
68 //! @endcode
69 //!
70 //! **Parameters**
71 //!
72 //! * `xsys` : `xs` followed by same number of `ys`
73 //! * `xs`, `ys` : tuples of floating value arguments.
74 //!
75 //! **Return value**
76 //!
77 //! 1. covariance product. \f$\frac1N\sum_s (x_s-\bar{x_s})*(y_s-\bar{y_s})\f$.
78 //! where N is the number of `x_s` (minus 1 if `unbiased` option is used).
79 //! 2. Uses the tuples elements
80 //! 3. see 1.
81 //!
82 //! @see `welford_covariance` for incremental or parallel covariance and averages computations.
83 //!
84 //! @groupheader{Example}
85 //! @godbolt_todo{doc/core/covariance.cpp}
86 //======================================================================================================================
87
88 inline constexpr auto covariance = eve::functor<covariance_t>;
89 //======================================================================================================================
90 //! @}
91 //======================================================================================================================
92 }
93
94 namespace plf::_
95 {
96
97 template<eve::callable_options O, concepts::polyfloat_like... Ts>
98 8 constexpr auto covariance_(POLYFLOAT_DELAY(), O const& o, Ts const&... args) noexcept
99 requires(sizeof...(Ts) > 1 && sizeof...(Ts) % 2 == 0)
100 {
101 using r_t = as_polyfloat_like_t<Ts...>;
102 using u_t = eve::element_type_t<r_t>;
103 16 auto cvt = [](auto a) { return plf::convert(a, as<u_t>()); };
104 8 auto coeffs = eve::zip(cvt(args)...);
105 24 auto [f, s] = kumi::split(coeffs, kumi::index<sizeof...(Ts) / 2>);
106 8 return covariance[o](f, s);
107 }
108
109 template<eve::non_empty_product_type PT1, eve::non_empty_product_type PT2, eve::callable_options O>
110 12 constexpr auto covariance_(POLYFLOAT_DELAY(), O const& o, PT1 f, PT2 s) noexcept
111 requires(kumi::as_tuple_t<PT1>::size() == kumi::as_tuple_t<PT2>::size())
112 {
113 using Tup1 = kumi::as_tuple_t<PT1>;
114 using Tup2 = kumi::as_tuple_t<PT2>;
115 12 constexpr auto siz = Tup1::size();
116 12 constexpr auto fac = O::contains(unbiased) ? siz - 1 : siz;
117 using r1_t = kumi::apply_traits_t<as_polyfloat_like, Tup1>;
118 using r2_t = kumi::apply_traits_t<as_polyfloat_like, Tup2>;
119 using r_t = eve::common_value_t<r1_t, r2_t>;
120
121 if constexpr (siz == 1) return eve::zero(eve::as<r_t>());
122 else
123 {
124 12 auto avgf = plf::average[o](f);
125 12 auto avgs = plf::average[o](s);
126 if constexpr (O::contains(raw))
127 auto cov = kumi::sum(kumi::map([avgf, avgs](auto a, auto b) { return (a - avgf) * (b - avgs); }, f, s)) / fac;
128 else
129 {
130 24 auto fc = kumi::map([avgf](auto a) { return (a - avgf); }, f);
131 24 auto sc = kumi::map([avgs](auto a) { return (a - avgs); }, s);
132 12 return eve::dot[o](fc, sc) / fac;
133 }
134 }
135 }
136 }
137