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