1 // -*- C++ -*-
2 /** @file */
3 #pragma once
4
5 #include <utility>
6 #include <tuple>
7
8 #include "common.hpp"
9 #include "arch.hpp"
10 #include <type_traits>
11 #include "number.hpp"
12 #include "forward.hpp"
13 #include "fusion.hpp"
14 #include "matrix.hpp"
15
16 namespace arm_cmsis_dsp {
17
18 /** \addtogroup UNROLLING Unrolling
19 * \ingroup DSPPP
20 * @{
21 */
22
23 template<typename ... E>
24 struct Merged
25 {
26
27 using ScalarResult = std::tuple<typename traits<std::remove_reference_t<E>>::Scalar...>;
28 using TypeOfElement = typename std::tuple_element<0,ScalarResult>::type;
29
Mergedarm_cmsis_dsp::Merged30 constexpr explicit Merged(const E& ... values) : vals { values ...} { }
31
32 constexpr Merged(Merged&& other) = default;
33 constexpr Merged(const Merged& other) = default;
34 constexpr Merged& operator=(const Merged& other) = delete;
35 constexpr Merged& operator=(Merged&& other) = delete;
36 ~Merged() = default;
37
lengtharm_cmsis_dsp::Merged38 constexpr vector_length_t length() const noexcept {return std::get<0>(vals).length();};
39
40 template<std::size_t... Ns>
val_implarm_cmsis_dsp::Merged41 constexpr ScalarResult val_impl(const int i, const std::index_sequence<Ns...>) const noexcept
42 {
43 return std::tuple(std::get<Ns>(vals)[i]...);
44 }
45
operator []arm_cmsis_dsp::Merged46 constexpr ScalarResult operator[](const int i) noexcept{
47 return val_impl(i,std::make_index_sequence<sizeof...(E)>());
48 }
49
operator []arm_cmsis_dsp::Merged50 constexpr ScalarResult const operator[](const int i) const noexcept{
51 return val_impl(i,std::make_index_sequence<sizeof...(E)>());
52 }
53
54 #if defined(HAS_VECTOR)
55
56 using Vector = std::tuple<typename vector_traits<typename traits<std::remove_reference_t<E>>::Scalar>::vector...>;
57
58 template<std::size_t... Ns>
vector_store_implarm_cmsis_dsp::Merged59 void vector_store_impl(const index_t i,const Vector &val, const std::index_sequence<Ns...>) const noexcept
60 {
61 (inner::vstore1<1>((std::get<Ns>(vals).ptr(i)),std::get<Ns>(val)),...);
62 }
63
vector_storearm_cmsis_dsp::Merged64 void vector_store(const index_t i,const Vector &val) const noexcept
65 {
66 vector_store_impl(i,val,std::make_index_sequence<sizeof...(E)>());
67 }
68
69 #if defined(HAS_PREDICATED_LOOP)
70 template<std::size_t... Ns>
vector_store_tail_implarm_cmsis_dsp::Merged71 void vector_store_tail_impl(const index_t i,const vector_length_t remaining,const Vector &val, const std::index_sequence<Ns...>) const noexcept
72 {
73 (inner::vstore1_z<1>((std::get<Ns>(vals).ptr(i)),std::get<Ns>(val),remaining,inner::vctpq<TypeOfElement>::mk(remaining)),...);
74 }
75
76
vector_store_tailarm_cmsis_dsp::Merged77 void vector_store_tail(const index_t i,const vector_length_t remaining,const Vector &val) const noexcept
78 {
79 vector_store_tail_impl(i,remaining,val,std::make_index_sequence<sizeof...(E)>());
80 }
81 #endif
82
83
84 template<std::size_t... Ns>
vector_op_implarm_cmsis_dsp::Merged85 Vector vector_op_impl(const int i, const std::index_sequence<Ns...>) const noexcept
86 {
87 return std::make_tuple(std::get<Ns>(vals).vector_op(i)...);
88 }
89
vector_oparm_cmsis_dsp::Merged90 Vector vector_op(const index_t i) const noexcept
91 {
92 return(vector_op_impl(i,std::make_index_sequence<sizeof...(E)>()));
93 }
94
95 #if defined(HAS_PREDICATED_LOOP)
96 template<std::size_t... Ns>
vector_op_tail_implarm_cmsis_dsp::Merged97 Vector vector_op_tail_impl(const index_t i,const vector_length_t remaining, const std::index_sequence<Ns...>) const noexcept
98 {
99 return std::make_tuple(std::get<Ns>(vals).vector_op_tail(i,remaining)...);
100 }
101
vector_op_tailarm_cmsis_dsp::Merged102 Vector vector_op_tail(const index_t i,const vector_length_t remaining) const noexcept
103 {
104 return(vector_op_tail_impl(i,remaining,std::make_index_sequence<sizeof...(E)>()));
105 }
106 #endif
107 #endif
108
109 template<typename ... EA>
operator =arm_cmsis_dsp::Merged110 Merged& operator=(const Merged<EA...>& other) noexcept
111 {
112 eval(*this,other,std::get<0>(vals).length(),CURRENT_ARCH);
113 return(*this);
114 }
115
116 const std::tuple<E...> vals;
117 };
118
119 template <typename ..._Tp>
120 static inline Merged<_Tp&...>
results(_Tp &...__t)121 results(_Tp&... __t) noexcept {return Merged<_Tp&...>(__t...);}
122
123
124 template<typename ... E>
125 struct traits<Merged<E...>>
126 {
127 typedef std::tuple<typename traits<std::remove_reference_t<E>>::Scalar...> Scalar;
128
129 #if defined(HAS_VECTOR)
130 typedef std::tuple<typename vector_traits<typename traits<std::remove_reference_t<E>>::Scalar>::vector...> Vector;
131 #endif
132 };
133
134 template<typename ... E>
135 struct IsVector<Merged<E...>>
136 {
137 constexpr static bool value = true;
138 };
139
140 template<typename ... E>
141 struct IsDynamic<Merged<E...>>
142 {
143 constexpr static bool value = (... && IsDynamic<std::remove_reference_t<E>>::value);
144 };
145
146 template<typename ... E>
147 struct ElementType<Merged<E...>>
148 {
149 typedef std::tuple<typename ElementType<std::remove_reference_t<E>>::type...> type;
150 };
151
max_length(const vector_length_t a,const vector_length_t b)152 constexpr vector_length_t max_length(const vector_length_t a,const vector_length_t b) noexcept
153 {
154 return((a>b) ? a : b);
155 };
156
157
158 template<typename F,typename ... N>
max_vec_length(F a,N...b)159 constexpr vector_length_t max_vec_length(F a,N ...b) noexcept
160 {
161 if constexpr (sizeof...(b) == 0)
162 {
163 return(a);
164 }
165 else
166 {
167 return max_length(a,max_vec_length(b...));
168 }
169 };
170
171
172 template<typename ... E>
173 struct StaticLength<Merged<E...>>
174 {
175 constexpr static vector_length_t value = max_vec_length(StaticLength<std::remove_reference_t<E>>::value...);
176 };
177
178
179 template<typename F,std::size_t... Ns>
unroll_impl(const F & func,std::index_sequence<Ns...>)180 auto unroll_impl(const F& func,std::index_sequence<Ns...>) noexcept
181 {
182 return Merged{func(Ns)...};
183 };
184
185 template<int N,typename F>
unroll(const F & func)186 auto unroll(const F& func) noexcept
187 {
188 return unroll_impl(func,std::make_index_sequence<N>());
189 };
190
191 template<typename E>
constres(const E & r,const std::size_t)192 constexpr static const E& constres(const E& r,const std::size_t) noexcept
193 {
194 return(r);
195 }
196
197 template<typename E,std::size_t... Ns>
replicate_impl(const E & expr,std::index_sequence<Ns...>)198 auto replicate_impl(const E& expr,std::index_sequence<Ns...>) noexcept
199 {
200 return Merged{constres(expr,Ns)...};
201 };
202
203 template<int N,typename E>
replicate(const E & expr)204 auto replicate(const E& expr) noexcept
205 {
206 return replicate_impl(expr,std::make_index_sequence<N>());
207 };
208
209 /*
210
211 We don't want to replicate the Vector but only a reference
212 to the vector. So it is packed into an expr
213
214 */
215 template<int N,typename P,int L,template<int> typename A>
replicate(const Vector<P,L,A> & e)216 auto replicate(const Vector<P,L,A>& e) noexcept
217 {
218 //return replicate_impl(expr(e),std::make_index_sequence<N>());
219 return replicate_impl(VectorView<P,1>(e),std::make_index_sequence<N>());
220 };
221
222 template<typename T,unsigned int N,std::size_t... Ns>
results_impl(std::array<T,N> & a,std::index_sequence<Ns...>)223 auto results_impl(std::array<T,N> &a,std::index_sequence<Ns...>) noexcept
224 {
225 return std::tie(a[Ns]...);
226 };
227
228 template<unsigned int N,typename T>
results(std::array<T,N> & a)229 auto results(std::array<T,N> &a) noexcept
230 {
231 return results_impl(a,std::make_index_sequence<N>());
232 };
233
234 template<typename F,std::size_t... Ns>
result_impl_func(const F & func,std::index_sequence<Ns...>)235 auto result_impl_func(const F& func,std::index_sequence<Ns...>) noexcept
236 {
237 return std::tie(*func(Ns)...);
238 };
239
240 template<int N,typename F>
results(const F & func)241 auto results(const F& func) noexcept
242 {
243 return result_impl_func(func,std::make_index_sequence<N>());
244 };
245
246 /*! @} */
247 }
248