1 /** @addtogroup horizontal
2  *  @{
3  */
4 /*
5   Copyright (C) 2016 D Levin (https://www.kfrlib.com)
6   This file is part of KFR
7 
8   KFR is free software: you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation, either version 2 of the License, or
11   (at your option) any later version.
12 
13   KFR is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17 
18   You should have received a copy of the GNU General Public License
19   along with KFR.
20 
21   If GPL is not suitable for your project, you must purchase a commercial license to use KFR.
22   Buying a commercial license is mandatory as soon as you develop commercial activities without
23   disclosing the source code of your own applications.
24   See https://www.kfrlib.com for details.
25  */
26 #pragma once
27 
28 #include "operators.hpp"
29 
30 namespace kfr
31 {
32 inline namespace CMT_ARCH_NAME
33 {
34 
35 namespace intrinsics
36 {
37 
38 template <typename T, typename ReduceFn>
horizontal_impl(const vec<T,1> & value,ReduceFn &&)39 KFR_INTRINSIC T horizontal_impl(const vec<T, 1>& value, ReduceFn&&)
40 {
41     return T(value.front());
42 }
43 
44 template <typename T, size_t N, typename ReduceFn, KFR_ENABLE_IF(N > 1 && is_poweroftwo(N))>
horizontal_impl(const vec<T,N> & value,ReduceFn && reduce)45 KFR_INTRINSIC T horizontal_impl(const vec<T, N>& value, ReduceFn&& reduce)
46 {
47     return horizontal_impl(reduce(low(value), high(value)), std::forward<ReduceFn>(reduce));
48 }
49 template <typename T, size_t N, typename ReduceFn, KFR_ENABLE_IF(N > 1 && !is_poweroftwo(N))>
horizontal_impl(const vec<T,N> & value,ReduceFn && reduce)50 KFR_INTRINSIC T horizontal_impl(const vec<T, N>& value, ReduceFn&& reduce)
51 {
52     const T initial = reduce(initialvalue<T>());
53     return horizontal_impl(widen<next_poweroftwo(N)>(value, initial), std::forward<ReduceFn>(reduce));
54 }
55 } // namespace intrinsics
56 
57 template <typename T, size_t N, typename ReduceFn>
horizontal(const vec<T,N> & value,ReduceFn && reduce)58 KFR_INTRINSIC T horizontal(const vec<T, N>& value, ReduceFn&& reduce)
59 {
60     return intrinsics::horizontal_impl(value, std::forward<ReduceFn>(reduce));
61 }
62 
63 /// @brief Sum all elements of the vector
64 template <typename T, size_t N>
hadd(const vec<T,N> & value)65 KFR_INTRINSIC T hadd(const vec<T, N>& value)
66 {
67     return horizontal(value, fn::add());
68 }
KFR_FN(hadd)69 KFR_FN(hadd)
70 
71 /// @brief Sum all elements of the vector
72 template <typename T, size_t N>
73 KFR_INTRINSIC T hsum(const vec<T, N>& value)
74 {
75     return horizontal(value, fn::add());
76 }
KFR_FN(hsum)77 KFR_FN(hsum)
78 
79 /// @brief Multiply all elements of the vector
80 template <typename T, size_t N>
81 KFR_INTRINSIC T hmul(const vec<T, N>& value)
82 {
83     return horizontal(value, fn::mul());
84 }
KFR_FN(hmul)85 KFR_FN(hmul)
86 
87 /// @brief Multiply all elements of the vector
88 template <typename T, size_t N>
89 KFR_INTRINSIC T hproduct(const vec<T, N>& value)
90 {
91     return horizontal(value, fn::mul());
92 }
KFR_FN(hproduct)93 KFR_FN(hproduct)
94 
95 template <typename T, size_t N>
96 KFR_INTRINSIC T hbitwiseand(const vec<T, N>& value)
97 {
98     return horizontal(value, fn::bitwiseand());
99 }
KFR_FN(hbitwiseand)100 KFR_FN(hbitwiseand)
101 template <typename T, size_t N>
102 KFR_INTRINSIC T hbitwiseor(const vec<T, N>& value)
103 {
104     return horizontal(value, fn::bitwiseor());
105 }
KFR_FN(hbitwiseor)106 KFR_FN(hbitwiseor)
107 template <typename T, size_t N>
108 KFR_INTRINSIC T hbitwisexor(const vec<T, N>& value)
109 {
110     return horizontal(value, fn::bitwisexor());
111 }
KFR_FN(hbitwisexor)112 KFR_FN(hbitwisexor)
113 
114 /// @brief Calculate the Dot-Product of two vectors
115 template <typename T, size_t N>
116 KFR_INTRINSIC T hdot(const vec<T, N>& x, const vec<T, N>& y)
117 {
118     return hadd(x * y);
119 }
KFR_FN(hdot)120 KFR_FN(hdot)
121 
122 /// @brief Calculate the Arithmetic mean of all elements in the vector
123 template <typename T, size_t N>
124 KFR_INTRINSIC T havg(const vec<T, N>& value)
125 {
126     return hadd(value) / N;
127 }
KFR_FN(havg)128 KFR_FN(havg)
129 
130 /// @brief Calculate the RMS of all elements in the vector
131 template <typename T, size_t N>
132 KFR_INTRINSIC T hrms(const vec<T, N>& value)
133 {
134     return builtin_sqrt(hadd(value * value) / N);
135 }
136 KFR_FN(hrms)
137 } // namespace CMT_ARCH_NAME
138 } // namespace kfr
139