7 #include "bivariate.hpp"
8 #include "univariate.hpp"
15 #include <eve/module/math.hpp>
16 #include <eve/module/special.hpp>
18 namespace VSTAT_NAMESPACE {
22 template<eve::simd_value T, std::input_iterator I,
typename F>
23 requires std::is_invocable_v<F, std::iter_value_t<I>>
24 auto inline load(I iter, F&& func) {
25 return [&]<std::size_t ...Idx>(std::index_sequence<Idx...>){
26 return T{ std::forward<F>(func)(*(iter + Idx))... };
27 }(std::make_index_sequence<T::size()>{});
31 template<
typename Distance,
typename... Iters>
32 auto inline advance(Distance d, Iters&... iters) ->
void {
33 (std::advance(iters, d), ...);
39 concept arithmetic = std::is_arithmetic_v<T>;
41 template<
typename F,
typename... Args>
42 concept arithmetic_projection = requires(F&&) {
43 { std::is_invocable_v<F, Args...> };
44 { arithmetic<std::remove_reference_t<std::invoke_result_t<F, Args...>>> };
54 namespace univariate {
66 template<std::
floating_po
int T, std::input_iterator I,
typename F = std::
identity>
67 requires concepts::arithmetic_projection<F, std::iter_value_t<I>>
70 using wide = eve::wide<T>;
71 auto constexpr s{ wide::size() };
72 auto const n{ std::distance(first, last) };
73 auto const m = n - n % s;
76 univariate_accumulator<T> scalar_acc;
77 for (; first < last; ++first) {
78 scalar_acc(std::invoke(std::forward<F>(f), *first));
80 return univariate_statistics(scalar_acc);
83 univariate_accumulator<wide> acc;
84 for (
size_t i = 0; i < m; i += s) {
85 acc(detail::load<wide>(first, std::forward<F>(f)));
86 detail::advance(s, first);
91 auto [sw, sx, sxx] = acc.stats();
92 auto scalar_acc = univariate_accumulator<T>::load_state(sw, sx, sxx);
93 for (; first < last; ++first) {
94 scalar_acc(std::invoke(std::forward<F>(f), *first));
96 return univariate_statistics(scalar_acc);
98 return univariate_statistics(acc);
113 template<std::
floating_po
int T, std::input_iterator I, std::input_iterator J,
typename F = std::
identity>
114 requires concepts::arithmetic_projection<F, std::iter_value_t<I>> and std::is_arithmetic_v<std::iter_value_t<J>>
117 using wide = eve::wide<T>;
118 auto constexpr s{ wide::size() };
119 auto const n { std::distance(first1, last1) };
120 const size_t m = n - n % s;
123 univariate_accumulator<T> scalar_acc;
124 for (; first1 < last1; ++first1, ++first2) {
125 scalar_acc(std::invoke(std::forward<F>(f), *first1), *first2);
127 return univariate_statistics(scalar_acc);
130 univariate_accumulator<wide> acc;
131 for (
size_t i = 0; i < m; i += s) {
132 acc(detail::load<wide>(first1, std::forward<F>(f)), wide(first2, first2 + s));
133 detail::advance(s, first1, first2);
138 auto [sw, sx, sxx] = acc.stats();
139 auto scalar_acc = univariate_accumulator<T>::load_state(sw, sx, sxx);
140 for (; first1 < last1; ++first1, ++first2) {
141 scalar_acc(std::invoke(std::forward<F>(f), *first1), *first2);
143 return univariate_statistics(scalar_acc);
145 return univariate_statistics(acc);
165 template<std::
floating_po
int T, std::input_iterator I, std::input_iterator J,
typename BinaryOp,
typename F1 = std::
identity,
typename F2 = std::
identity>
166 requires std::is_invocable_v<F1, std::iter_value_t<I>> and
167 std::is_invocable_v<F2, std::iter_value_t<J>> and
170 std::invoke_result_t<F1, std::iter_value_t<I>>,
171 std::invoke_result_t<F2, std::iter_value_t<J>>
173 concepts::arithmetic_projection<
175 std::invoke_result_t<F1, std::iter_value_t<I>>,
176 std::invoke_result_t<F2, std::iter_value_t<J>>
178 inline auto accumulate(I first1, std::sized_sentinel_for<I>
auto last1, J first2, BinaryOp&& op = BinaryOp{}, F1&& f1 = F1{}, F2&& f2 = F2{}) noexcept -> univariate_statistics
180 using wide = eve::wide<T>;
181 auto constexpr s{ wide::size() };
182 auto const n{ std::distance(first1, last1) };
183 auto const m = n - n % s;
185 auto f = [&](
auto a,
auto b){
186 return std::invoke(std::forward<BinaryOp>(op), std::invoke(std::forward<F1>(f1), a), std::invoke(std::forward<F2>(f2), b));
190 univariate_accumulator<T> scalar_acc;
191 for (; first1 < last1; ++first1, ++first2) {
192 scalar_acc(f(*first1, *first2));
194 return univariate_statistics(scalar_acc);
198 univariate_accumulator<wide> acc;
199 for (
size_t i = 0; i < m; i += s) {
200 std::transform(first1, first1 + s, first2, x.begin(), f);
202 detail::advance(s, first1, first2);
207 auto [sw, sx, sxx] = acc.stats();
208 auto scalar_acc = univariate_accumulator<T>::load_state(sw, sx, sxx);
209 for (; first1 < last1; ++first1, ++first2) {
210 scalar_acc(f(*first1, *first2));
212 return univariate_statistics(scalar_acc);
214 return univariate_statistics(acc);
235 template<std::
floating_po
int T, std::input_iterator I, std::input_iterator J, std::input_iterator K,
typename BinaryOp,
typename F1 = std::
identity,
typename F2 = std::
identity>
236 requires std::is_arithmetic_v<std::iter_value_t<K>> &&
237 std::is_invocable_v<F1, std::iter_value_t<I>> &&
238 std::is_invocable_v<F2, std::iter_value_t<J>> &&
241 std::invoke_result_t<F1, std::iter_value_t<I>>,
242 std::invoke_result_t<F2, std::iter_value_t<J>>
244 concepts::arithmetic_projection<
246 std::invoke_result_t<F1, std::iter_value_t<I>>,
247 std::invoke_result_t<F2, std::iter_value_t<J>>
249 inline auto accumulate(I first1, std::sized_sentinel_for<I>
auto last1, J first2, K first3, BinaryOp&& op = BinaryOp{}, F1&& f1 = F1{}, F2&& f2 = F2{}) noexcept -> univariate_statistics
251 using wide = eve::wide<T>;
252 auto constexpr s{ wide::size() };
253 auto const n{ std::distance(first1, last1) };
254 auto const m = n - n % s;
256 auto f = [&](
auto a,
auto b){
257 return std::invoke(std::forward<BinaryOp>(op), std::invoke(std::forward<F1>(f1), a), std::invoke(std::forward<F2>(f2), b));
261 univariate_accumulator<T> scalar_acc;
262 for (; first1 < last1; ++first1, ++first2, ++first3) {
263 scalar_acc(f(*first1, *first2), *first3);
265 return univariate_statistics(scalar_acc);
269 univariate_accumulator<wide> acc;
270 for (
size_t i = 0; i < m; i += s) {
271 std::transform(first1, first1 + s, first2, x.begin(), f);
272 acc(wide(x), wide(first3, first3 + s));
273 detail::advance(s, first1, first2, first3);
278 auto [sw, sx, sxx] = acc.stats();
279 auto scalar_acc = univariate_accumulator<T>::load_state(sw, sx, sxx);
280 for (; first1 < last1; ++first1, ++first2, ++first3) {
281 scalar_acc(f(*first1, *first2), *first3);
283 return univariate_statistics(scalar_acc);
285 return univariate_statistics(acc);
289 namespace bivariate {
333 template<std::
floating_po
int T, std::input_iterator I, std::input_iterator J,
typename F1 = std::
identity,
typename F2 = std::
identity>
334 requires concepts::arithmetic_projection<F1, std::iter_value_t<I>> and
335 concepts::arithmetic_projection<F2, std::iter_value_t<J>>
336 inline auto accumulate(I first1, std::sized_sentinel_for<I>
auto last1, J first2, F1&& f1 = F1{}, F2&& f2 = F2{})
338 using wide = eve::wide<T>;
339 auto constexpr s { wide::size() };
340 auto const n { std::distance(first1, last1) };
341 auto const m = n - n % s;
344 bivariate_accumulator<T> scalar_acc;
345 for (; first1 < last1; ++first1, ++first2) {
346 scalar_acc(std::invoke(std::forward<F1>(f1), *first1), std::invoke(std::forward<F2>(f2), *first2));
348 return bivariate_statistics(scalar_acc);
351 bivariate_accumulator<wide> acc;
352 for (
size_t i = 0; i < m; i += s) {
353 acc(detail::load<wide>(first1, std::forward<F1>(f1)), detail::load<wide>(first2, std::forward<F2>(f2)));
354 detail::advance(s, first1, first2);
358 auto [sw, sx, sy, sxx, syy, sxy] = acc.stats();
359 auto scalar_acc = bivariate_accumulator<T>::load_state(sx, sy, sw, sxx, syy, sxy);
360 for (; first1 < last1; ++first1, ++first2) {
361 scalar_acc(std::invoke(std::forward<F1>(f1), *first1), std::invoke(std::forward<F2>(f2), *first2));
363 return bivariate_statistics(scalar_acc);
366 return bivariate_statistics(acc);
369 template<std::
floating_po
int T, std::input_iterator I, std::input_iterator J, std::input_iterator K,
typename F1 = std::
identity,
typename F2 = std::
identity>
370 requires concepts::arithmetic_projection<F1, std::iter_value_t<I>> and
371 concepts::arithmetic_projection<F2, std::iter_value_t<J>> and
372 std::is_arithmetic_v<std::iter_value_t<K>>
373 inline auto accumulate(I first1, std::sized_sentinel_for<I>
auto last1, J first2, K first3, F1&& f1 = F1{}, F2&& f2 = F2{}) noexcept -> bivariate_statistics
375 using wide = eve::wide<T>;
376 auto constexpr s { wide::size() };
377 auto const n = std::distance(first1, last1);
378 auto const m = n - n % s;
381 bivariate_accumulator<T> scalar_acc;
382 for (; first1 < last1; ++first1, ++first2, ++first3) {
383 scalar_acc(std::invoke(std::forward<F1>(f1), *first1++), std::invoke(std::forward<F2>(f2), *first2++), *first3++);
385 return bivariate_statistics(scalar_acc);
388 bivariate_accumulator<wide> acc;
389 for (
size_t i = 0; i < m; i += s) {
391 detail::load<wide>(first1, std::forward<F1>(f1)),
392 detail::load<wide>(first2, std::forward<F2>(f2)),
393 wide(first3, first3 + s)
395 detail::advance(s, first1, first2, first3);
399 auto [sw, sx, sy, sxx, syy, sxy] = acc.stats();
400 auto scalar_acc = bivariate_accumulator<T>::load_state(sx, sy, sw, sxx, syy, sxy);
401 for (; first1 < last1; ++first1, ++first2, ++first3) {
402 scalar_acc(std::invoke(std::forward<F1>(f1), *first1), std::invoke(std::forward<F2>(f2), *first2), *first3);
404 return bivariate_statistics(scalar_acc);
406 return bivariate_statistics(acc);
430 template<std::
floating_po
int T, std::input_iterator I, std::input_iterator J>
431 inline auto r2_score(I first1, std::sentinel_for<I>
auto last1, J first2) noexcept ->
double {
432 using wide = eve::wide<T>;
433 auto constexpr s{ wide::size() };
434 auto const n{ std::distance(first1, last1) };
435 auto const m{ n - n % s };
439 for (
auto i = 0; i < m; i += s) {
440 wide y_true{first1, first1+s};
441 wide y_pred{first2, first2+s};
442 wx(eve::sqr(y_true-y_pred));
444 detail::advance(s, first1, first2);
451 for(; first1 < last1; ++first1, ++first2) {
452 sx(eve::sqr(*first1 - *first2));
459 return tss < std::numeric_limits<double>::epsilon()
460 ? std::numeric_limits<double>::lowest()
475 template<std::
floating_po
int T, std::input_iterator I, std::input_iterator J, std::input_iterator K>
476 inline auto r2_score(I first1, std::sentinel_for<I>
auto last1, J first2, K first3) noexcept ->
double {
477 using wide = eve::wide<T>;
478 auto constexpr s{ wide::size() };
479 auto const n{ std::distance(first1, last1) };
480 auto const m{ n - n % s };
484 for (
auto i = 0; i < m; i += s) {
485 wide y_true{first1, first1+s};
486 wide y_pred{first2, first2+s};
487 wide weight{first3, first3+s};
488 wx(eve::sqr(y_true-y_pred), weight);
490 detail::advance(s, first1, first2, first3);
497 for(; first1 < last1; ++first1, ++first2, ++first3) {
498 sx(eve::sqr(*first1 - *first2), *first3);
499 sy(*first1, *first3);
505 return tss < std::numeric_limits<double>::epsilon()
506 ? std::numeric_limits<double>::lowest()
519 template<std::
floating_po
int T, std::input_iterator I, std::input_iterator J>
520 inline auto mean_squared_error(I first1, std::sentinel_for<I>
auto last1, J first2) noexcept ->
double {
521 using wide = eve::wide<T>;
522 auto constexpr s{ wide::size() };
523 auto const n{ std::distance(first1, last1) };
524 auto const m{ n - n % s };
527 for (
auto i = 0; i < m; i += s) {
528 wide y_true{first1, first1+s};
529 wide y_pred{first2, first2+s};
530 we(eve::sqr(y_true-y_pred));
531 detail::advance(s, first1, first2);
536 for(; first1 < last1; ++first1, ++first2) {
537 se(eve::sqr(*first1 - *first2));
551 template<std::
floating_po
int T, std::input_iterator I, std::input_iterator J, std::input_iterator K>
552 inline auto mean_squared_error(I first1, std::sentinel_for<I>
auto last1, J first2, K first3) noexcept ->
double {
553 using wide = eve::wide<T>;
554 auto constexpr s{ wide::size() };
555 auto const n{ std::distance(first1, last1) };
556 auto const m{ n - n % s };
559 for (
auto i = 0; i < m; i += s) {
560 wide y_true{first1, first1+s};
561 wide y_pred{first2, first2+s};
562 wide weight{first3, first3+s};
563 we(eve::sqr(y_true-y_pred), weight);
564 detail::advance(s, first1, first2, first3);
569 for(; first1 < last1; ++first1, ++first2, ++first3) {
570 se(eve::sqr(*first1 - *first2), *first3);
584 template<std::
floating_po
int T, std::input_iterator I, std::input_iterator J>
586 using wide = eve::wide<T>;
587 auto constexpr s{ wide::size() };
588 auto const n{ std::distance(first1, last1) };
589 auto const m{ n - n % s };
592 for (
auto i = 0; i < m; i += s) {
593 wide y_true{first1, first1+s};
594 wide y_pred{first2, first2+s};
595 we(eve::sqr(eve::log1p(y_true)-eve::log1p(y_pred)));
596 detail::advance(s, first1, first2);
601 for(; first1 < last1; ++first1, ++first2) {
602 se(eve::sqr(eve::log1p(*first1) - eve::log1p(*first2)));
616 template<std::
floating_po
int T, std::input_iterator I, std::input_iterator J, std::input_iterator K>
618 using wide = eve::wide<T>;
619 auto constexpr s{ wide::size() };
620 auto const n{ std::distance(first1, last1) };
621 auto const m{ n - n % s };
624 for (
auto i = 0; i < m; i += s) {
625 wide y_true{first1, first1+s};
626 wide y_pred{first2, first2+s};
627 wide weight{first3, first3+s};
628 we(eve::sqr(eve::log1p(y_true)-eve::log1p(y_pred)), weight);
629 detail::advance(s, first1, first2, first3);
634 for(; first1 < last1; ++first1, ++first2, ++first3) {
635 se(eve::sqr(eve::log1p(*first1) - eve::log1p(*first2)), *first3);
649 template<std::
floating_po
int T, std::input_iterator I, std::input_iterator J>
651 using wide = eve::wide<T>;
652 auto constexpr s{ wide::size() };
653 auto const n{ std::distance(first1, last1) };
654 auto const m{ n - n % s };
657 for (
auto i = 0; i < m; i += s) {
658 wide y_true{first1, first1+s};
659 wide y_pred{first2, first2+s};
660 we(eve::abs(y_true-y_pred));
661 detail::advance(s, first1, first2);
666 for(; first1 < last1; ++first1, ++first2) {
667 se(eve::abs(*first1 - *first2));
681 template<std::
floating_po
int T, std::input_iterator I, std::input_iterator J, std::input_iterator K>
682 inline auto mean_absolute_error(I first1, std::sentinel_for<I>
auto last1, J first2, K first3) noexcept ->
double {
683 using wide = eve::wide<T>;
684 auto constexpr s{ wide::size() };
685 auto const n{ std::distance(first1, last1) };
686 auto const m{ n - n % s };
689 for (
auto i = 0; i < m; i += s) {
690 wide y_true{first1, first1+s};
691 wide y_pred{first2, first2+s};
692 wide weight{first3, first3+s};
693 we(eve::abs(y_true-y_pred), weight);
694 detail::advance(s, first1, first2, first3);
699 for(; first1 < last1; ++first1, ++first2, ++first3) {
700 se(eve::abs(*first1 - *first2), *first3);
717 template<std::
floating_po
int T, std::input_iterator I, std::input_iterator J>
719 using wide = eve::wide<T>;
720 auto constexpr s{ wide::size() };
721 auto const n{ std::distance(first1, last1) };
722 auto const m{ n - n % s };
724 auto constexpr eps{ std::numeric_limits<T>::epsilon() };
727 for (
auto i = 0; i < m; i += s) {
728 wide y_true{first1, first1+s};
729 wide y_pred{first2, first2+s};
730 we(eve::abs(y_true-y_pred) / eve::max(eps, eve::abs(y_true)));
731 detail::advance(s, first1, first2);
736 for(; first1 < last1; ++first1, ++first2) {
737 se(eve::abs(*first1 - *first2) / eve::max(eps, eve::abs(*first1)));
751 template<std::
floating_po
int T, std::input_iterator I, std::input_iterator J, std::input_iterator K>
753 using wide = eve::wide<T>;
754 auto constexpr s{ wide::size() };
755 auto const n{ std::distance(first1, last1) };
756 auto const m{ n - n % s };
759 for (
auto i = 0; i < m; i += s) {
760 wide y_true{first1, first1+s};
761 wide y_pred{first2, first2+s};
762 wide weight{first3, first3+s};
763 we(eve::abs(y_true-y_pred), weight);
764 detail::advance(s, first1, first2, first3);
769 for(; first1 < last1; ++first1, ++first2, ++first3) {
770 se(eve::abs(*first1 - *first2), *first3);
784 template<std::
floating_po
int T, std::input_iterator I, std::input_iterator J>
786 using wide = eve::wide<T>;
787 auto constexpr s{ wide::size() };
788 auto const n{ std::distance(first1, last1) };
789 auto const m{ n - n % s };
791 auto constexpr eps{ std::numeric_limits<T>::epsilon() };
794 for (
auto i = 0; i < m; i += s) {
795 wide y_true{first1, first1+s};
796 wide y_pred{first2, first2+s};
797 we(y_pred - y_true * eve::log(y_pred) + eve::log_abs_gamma(T{1} + y_true));
798 detail::advance(s, first1, first2);
803 for(; first1 < last1; ++first1, ++first2) {
804 se(*first2 - *first1 * eve::log(*first2) + eve::log_abs_gamma(T{1} + *first1));
818 template<std::
floating_po
int T, std::input_iterator I, std::input_iterator J, std::input_iterator K>
820 using wide = eve::wide<T>;
821 auto constexpr s{ wide::size() };
822 auto const n{ std::distance(first1, last1) };
823 auto const m{ n - n % s };
825 auto constexpr eps{ std::numeric_limits<T>::epsilon() };
828 for (
auto i = 0; i < m; i += s) {
829 wide y_true{first1, first1+s};
830 wide y_pred = eve::mul(wide{first2, first2+s}, wide{first3, first3+s});
831 we(y_pred - y_true * eve::log(y_pred) + eve::log_abs_gamma(T{1} + y_true));
832 detail::advance(s, first1, first2, first3);
837 for(; first1 < last1; ++first1, ++first2, ++first3) {
838 se(*first2 * *first3 - *first1 * eve::log(*first2 * *first3) + eve::log_abs_gamma(T{1} + *first1));
requires concepts::arithmetic_projection< F1, std::iter_value_t< I > > and concepts::arithmetic_projection< F2, std::iter_value_t< J > > auto accumulate(I first1, std::sized_sentinel_for< I > auto last1, J first2, F1 &&f1=F1{}, F2 &&f2=F2{})
Compute bivariate statistics from two sequences of values. The values can be provided directly or via...
Definition: vstat.hpp:336
auto poisson_neg_likelihood_loss(I first1, std::sentinel_for< I > auto last1, J first2, K first3) noexcept -> double
Negative log likelihood loss with Poisson distribution of target. The mean in each bin is multiplied ...
Definition: vstat.hpp:819
auto mean_absolute_percentage_error(I first1, std::sentinel_for< I > auto last1, J first2, K first3) noexcept -> double
Weighted mean absolute percentage error.
Definition: vstat.hpp:752
auto mean_squared_log_error(I first1, std::sentinel_for< I > auto last1, J first2, K first3) noexcept -> double
Computes the weighted mean squared logarithmic error.
Definition: vstat.hpp:617
auto mean_squared_error(I first1, std::sentinel_for< I > auto last1, J first2, K first3) noexcept -> double
Computes the weighted mean squared error.
Definition: vstat.hpp:552
auto r2_score(I first1, std::sentinel_for< I > auto last1, J first2, K first3) noexcept -> double
Computes the weighted coefficient of determination .
Definition: vstat.hpp:476
auto mean_absolute_error(I first1, std::sentinel_for< I > auto last1, J first2, K first3) noexcept -> double
Weighted mean absolute error.
Definition: vstat.hpp:682
Univariate accumulator object.
Definition: univariate.hpp:14
Univariate statistics.
Definition: univariate.hpp:84