1 // -*- C++ -*-
2 /** @file */
3 #pragma once
4 
5 #include <memory>
6 #include <cstring>
7 #include <algorithm>
8 #include <iostream>
9 #include "common.hpp"
10 #include "arch.hpp"
11 #include <type_traits>
12 #include "number.hpp"
13 #include "forward.hpp"
14 #include "fusion.hpp"
15 #include "unroll.hpp"
16 #include "algorithms.hpp"
17 #include "vector_impl.hpp"
18 #include "vector_view.hpp"
19 
20 namespace arm_cmsis_dsp {
21 
22 /** \addtogroup VECTOR Vectors
23  *  \ingroup DSPPP
24  *  @{
25  */
26 
27 template<typename T,bool = true>
28 struct VecRef;
29 
30 template<typename T>
31 struct VecRef<Vector_Base<T>>
32 {
33    typedef VectorView<T,1> type;
refarm_cmsis_dsp::VecRef34    static type ref(const Vector_Base<T>&a){
35       return(type(a));
36    };
37 };
38 
39 template<typename T,int S>
40 struct VecRef<VectorView<T,S>>
41 {
42    typedef VectorView<T,S> type;
refarm_cmsis_dsp::VecRef43    static type ref(const VectorView<T,S>&a){
44       return(a);
45    };
46 };
47 
48 
49 template<typename P,int L,
50          template<int> typename A>
51 struct VecRef<Vector<P,L,A>,(L<0)>
52 {
53 
54    typedef VectorView<P,1> type;
refarm_cmsis_dsp::VecRef55    static VectorView<P,1> ref(const Vector<P,L,A>&a,typename std::enable_if<(L<0)>::type* = nullptr){
56       return(VectorView<P,1>(a));
57    };
58 
59 };
60 
61 template<typename P,int L,
62          template<int> typename A>
63 struct VecRef<Vector<P,L,A>,(L>0)>
64 {
65    typedef const Vector<P,L,A>& type;
refarm_cmsis_dsp::VecRef66    static const Vector<P,L,A>& ref(const Vector<P,L,A>&a,typename std::enable_if<(L>0)>::type* = nullptr){
67       return(a);
68    };
69 };
70 
71 
72 
73 template<typename LHS,typename RHS,typename OP>
74 struct VecRef<_Binary<LHS,RHS,OP>>
75 {
76    typedef _Binary<LHS,RHS,OP> type;
refarm_cmsis_dsp::VecRef77    static type ref(const _Binary<LHS,RHS,OP>&a){
78       return(a);
79    };
80 };
81 
82 template<typename LHS,typename OP>
83 struct VecRef<_Unary<LHS,OP>>
84 {
85    typedef _Unary<LHS,OP> type;
refarm_cmsis_dsp::VecRef86    static type ref(const _Unary<LHS,OP>&a){
87       return(a);
88    };
89 };
90 
91 template<typename Derived>
92 struct VecRef<_Expr<Derived>>
93 {
94    typedef Derived type;
refarm_cmsis_dsp::VecRef95    static type ref(const _Expr<Derived>&a){
96       return(a.derived());
97    };
98 };
99 
100 template<>
101 struct VecRef<double>
102 {
103    typedef double type;
refarm_cmsis_dsp::VecRef104    static type ref(const double a){
105       return(a);
106    };
107 };
108 
109 template<>
110 struct VecRef<float>
111 {
112    typedef float type;
refarm_cmsis_dsp::VecRef113    static type ref(const float a){
114       return(a);
115    };
116 };
117 
118 #if defined(ARM_FLOAT16_SUPPORTED)
119 template<>
120 struct VecRef<float16_t>
121 {
122    typedef float16_t type;
refarm_cmsis_dsp::VecRef123    static type ref(const float16_t a){
124       return(a);
125    };
126 };
127 #endif
128 
129 template<>
130 struct VecRef<Q7>
131 {
132    typedef Q7 type;
refarm_cmsis_dsp::VecRef133    static type ref(const Q7 a){
134       return(a);
135    };
136 };
137 
138 template<>
139 struct VecRef<Q15>
140 {
141    typedef Q15 type;
refarm_cmsis_dsp::VecRef142    static type ref(const Q15 a){
143       return(a);
144    };
145 };
146 
147 template<>
148 struct VecRef<Q31>
149 {
150    typedef Q31 type;
refarm_cmsis_dsp::VecRef151    static type ref(const Q31 a){
152       return(a);
153    };
154 };
155 
156 
157 template<typename T,int S>
158 struct traits<VectorView<T,S>>
159 {
160     typedef T Scalar;
161 #if defined(HAS_VECTOR)
162     typedef typename vector_traits<T>::vector Vector;
163 #endif
164 };
165 
166 
167 template<typename P,int L,
168          template<int> typename Allocator>
169 struct traits<Vector<P,L,Allocator>>
170 {
171     typedef P Scalar;
172 #if defined(HAS_VECTOR)
173     typedef typename vector_traits<P>::vector Vector;
174 #endif
175 };
176 
177 
178 template<typename P,int L,
179          template<int> typename Allocator>
180 struct traits<const Vector<P,L,Allocator>&>
181 {
182     typedef P Scalar;
183 #if defined(HAS_VECTOR)
184     typedef typename vector_traits<P>::vector Vector;
185 #endif
186 };
187 
188 
189 
190 template<typename T>
191 struct StaticStride
192 {
193     constexpr static std::size_t value = 1;
194 };
195 
196 template<typename T,int S>
197 struct StaticStride<VectorView<T,S>>
198 {
199     constexpr static std::size_t value = S;
200 };
201 
202 
203 template<typename P,int L,
204          template<int> typename Allocator>
205 struct IsVector<Vector<P,L,Allocator>>
206 {
207     constexpr static bool value = true;
208 };
209 
210 template<typename P,int L,
211          template<int> typename Allocator>
212 struct IsVector<const Vector<P,L,Allocator>&>
213 {
214     constexpr static bool value = true;
215 };
216 
217 template<typename P>
218 struct IsVector<const Vector_Base<P>&>
219 {
220     constexpr static bool value = true;
221 };
222 
223 template<typename P>
224 struct IsVector<Vector_Base<P>>
225 {
226     constexpr static bool value = true;
227 };
228 
229 template<typename P,int L,
230          template<int> typename Allocator>
231 struct ElementType<Vector<P,L,Allocator>>
232 {
233     typedef P type;
234 };
235 
236 template<typename P,int L,
237          template<int> typename Allocator>
238 struct ElementType<const Vector<P,L,Allocator>&>
239 {
240     typedef P type;
241 };
242 
243 
244 template<typename P>
245 struct ElementType<Vector_Base<P>>
246 {
247     typedef P type;
248 };
249 
250 template<typename P>
251 struct ElementType<const Vector_Base<P>&>
252 {
253     typedef P type;
254 };
255 
256 template<typename T,int stride>
257 struct IsVector<VectorView<T,stride>>
258 {
259     constexpr static bool value = true;
260 };
261 
262 
263 template<typename P,int L,
264          template<int> typename Allocator>
265 struct StaticLength<Vector<P,L,Allocator>>
266 {
267     constexpr static vector_length_t value = (L<0) ? 0 : L;
268 };
269 
270 template<typename P,int L,
271          template<int> typename Allocator>
272 struct StaticLength<const Vector<P,L,Allocator>&>
273 {
274     constexpr static vector_length_t value = (L<0) ? 0 : L;
275 };
276 
277 
278 template<typename T,int stride>
279 struct ElementType<VectorView<T,stride>>
280 {
281     typedef T type;
282 };
283 
284 template<typename T,int stride>
285 struct ElementType<const VectorView<T,stride>&>
286 {
287     typedef T type;
288 };
289 
290 
291 template<typename P,int L,
292          template<int> typename Allocator>
293 struct IsDynamic<Vector<P,L,Allocator>>
294 {
295     constexpr static bool value = (L<0);
296 };
297 
298 template<typename P,int L,
299          template<int> typename Allocator>
300 struct IsDynamic<const Vector<P,L,Allocator>&>
301 {
302     constexpr static bool value = (L<0);
303 };
304 
305 template<typename T,int stride>
306 struct IsDynamic<VectorView<T,stride>>
307 {
308     constexpr static bool value = true;
309 };
310 
311 
312 
313 
314 // Assume one at least is static
315 template<typename VA,typename VB>
316 using StaticType=typename std::conditional<IsDynamic<VA>::value,VB,VA>::type;
317 
318 
319 
320 /**
321  * @brief  Addition operator for expressions
322  *
323  * @tparam LHS Left hand side datatype
324  * @tparam RHS Right hand side datatype
325  * @param a Left hand side expression tree
326  * @param b Right hand side expression tree
327  * @return Expression representing the add
328  *
329  * vector + vector (including matrix)
330  */
331 template<typename LHS,typename RHS,
332 typename std::enable_if<(!is_scalar<LHS>() ||
333                         !is_scalar<RHS>()) &&
334                         SameElementType<LHS,RHS>::value &&
335                         same_static_length<LHS,RHS>(),bool>::type = true>
operator +(const LHS & a,const RHS & b)336 inline auto operator+(const LHS &a,const RHS &b)
337 {
338     using Scalar = typename traits<LHS>::Scalar;
339     using VecLHS = VecRef<LHS>;
340     using VecRHS = VecRef<RHS>;
341 
342     return(_Binary<typename VecLHS::type,typename VecRHS::type,_AddOp<Scalar>>(VecLHS::ref(a),VecRHS::ref(b),_AddOp<Scalar>()));
343 };
344 
345 
346 /**
347  * @brief  + operator for expressions
348  *
349  * @tparam LHS Left hand side datatype
350  * @param a Left hand side expression tree
351  * @return Expression representing + vector
352  *
353  * +vector  (including matrix)
354  */
355 template<typename LHS,
356 typename std::enable_if<!is_scalar<LHS>(),bool>::type = true>
operator +(const LHS & a)357 inline auto operator+(const LHS &a)
358 {
359     using Scalar = typename traits<LHS>::Scalar;
360     using VecLHS = VecRef<LHS>;
361 
362     return(_Unary<typename VecLHS::type,_NoOp<Scalar>>(VecLHS::ref(a),_NoOp<Scalar>()));
363 };
364 
365 
366 /*
367 
368 VectorView = VectorView must be a cheap copy of reference only.
369 So when we want to copy a VectorView onto another we need to
370 write
371 VectorView = expr(VectorView) or copy
372 
373 we cannot rely on the copy or move constructors.
374 
375 */
376 
377 /**
378  * @brief  Identity operator for expression
379  *
380  * @tparam LHS Left hand side datatype
381  * @param a Left hand side expression tree
382  * @return Expression representing the identity
383  *
384  * Used to consider a vector view as an expression and force the copy
385  * of this vector view when assigned to another vector entity.
386  *
387  */
388 template<typename LHS,
389 typename std::enable_if<!is_scalar<LHS>(),bool>::type = true>
expr(const LHS & a)390 inline auto expr(const LHS &a)
391 {
392     using Scalar = typename traits<LHS>::Scalar;
393     using VecLHS = VecRef<LHS>;
394     return(_Unary<typename VecLHS::type,_NoOp<Scalar>>(VecLHS::ref(a),_NoOp<Scalar>()));
395 };
396 
397 /**
398  * @brief  Identity operator for expression
399  *
400  * @tparam LHS Left hand side datatype
401  * @param a Left hand side expression tree
402  * @return Expression representing the identity
403  *
404  * Used to consider a vector view as an expression and force the copy
405  * of this vector view when assigned to another vector entity.
406  *
407  */
408 template<typename LHS,
409 typename std::enable_if<!is_scalar<LHS>(),bool>::type = true>
copy(const LHS & a)410 inline auto copy(const LHS &a)
411 {
412     using Scalar = typename traits<LHS>::Scalar;
413     using VecLHS = VecRef<LHS>;
414     return(_Unary<typename VecLHS::type,_NoOp<Scalar>>(VecLHS::ref(a),_NoOp<Scalar>()));
415 };
416 
417 
418 /**
419  * @brief  Subtraction operator for expressions
420  *
421  * @tparam LHS Left hand side datatype
422  * @tparam RHS Right hand side datatype
423  * @param a Left hand side expression tree
424  * @param b Right hand side expression tree
425  * @return Expression representing the add
426  *
427  * vector - vector (including matrix)
428  */
429 template<typename LHS,typename RHS,
430 typename std::enable_if<(!is_scalar<LHS>() ||
431                         !is_scalar<RHS>()) &&
432                         SameElementType<LHS,RHS>::value &&
433                         same_static_length<LHS,RHS>(),bool>::type = true>
operator -(const LHS & a,const RHS & b)434 inline auto operator-(const LHS &a,const RHS &b)
435 {
436     using Scalar = typename traits<LHS>::Scalar;
437     using VecLHS = VecRef<LHS>;
438     using VecRHS = VecRef<RHS>;
439 
440     return(_Binary<typename VecLHS::type,typename VecRHS::type,_SubOp<Scalar>>(
441         VecLHS::ref(a),VecRHS::ref(b),_SubOp<Scalar>()));
442 };
443 
444 
445 /**
446  * @brief  - operator for expressions
447  *
448  * @tparam LHS Left hand side datatype
449  * @param a Left hand side expression tree
450  * @return Expression representing the - vector
451  *
452  * -vector (including matrix)
453  */
454 template<typename LHS,
455 typename std::enable_if<!is_scalar<LHS>(),bool>::type = true>
operator -(const LHS & a)456 inline auto operator-(const LHS &a)
457 {
458     using Scalar = typename traits<LHS>::Scalar;
459     using VecLHS = VecRef<LHS>;
460 
461     return(_Unary<typename VecLHS::type,_NegOp<Scalar>>(VecLHS::ref(a),_NegOp<Scalar>()));
462 };
463 
464 
465 /**
466  * @brief  Element wise multiplication operator for expressions
467  *
468  * @tparam LHS Left hand side datatype
469  * @tparam RHS Right hand side datatype
470  * @param a Left hand side expression tree
471  * @param b Right hand side expression tree
472  * @return Expression representing the *
473  *
474  * elementwise vector * vector (including matrix)
475  */
476 template<typename LHS,typename RHS,
477 typename std::enable_if<(!is_scalar<LHS>() ||
478                         !is_scalar<RHS>())  &&
479                         SameElementType<LHS,RHS>::value &&
480                         same_static_length<LHS,RHS>(),bool>::type = true>
operator *(const LHS & a,const RHS & b)481 inline auto operator*(const LHS &a,const RHS &b)
482 {
483     using Scalar = typename traits<LHS>::Scalar;
484     using VecLHS = VecRef<LHS>;
485     using VecRHS = VecRef<RHS>;
486 
487     return(_Binary<typename VecLHS::type,typename VecRHS::type,_MulOp<Scalar>>(
488         VecLHS::ref(a),VecRHS::ref(b),_MulOp<Scalar>()));
489 };
490 
491 
492 
493 #if 0
494 template<typename VA,typename VB,typename OP,
495 std::enable_if<IsVector<VA>::value &&
496                IsVector<VB>::value &&
497                SameElementType<VA,VB>::value &&
498                (same_static_length(StaticLength<VA>::value , StaticLength<VB>::value)),bool>::type = true>
499 inline _Expr<OP> operator+(const VA &a,
500                            const VB &b)
501 {
502 
503     return(_Add<decltype(pA),decltype(pB)>(a,b));
504 };
505 #endif
506 
507 /*
508 
509 Core algorithms that cannot be expressed only with high level
510 abstractions and need intrinsincs.
511 
512 */
513 #include "Helium/matrix_multiply.hpp"
514 #include "DSP/matrix_multiply.hpp"
515 #include "Scalar/matrix_multiply.hpp"
516 
517 /*! @} */
518 
519 }
520