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