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