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 
19 namespace arm_cmsis_dsp {
20 
21 /** \addtogroup VECTOR
22  *  @{
23  */
24 
25 /** @brief Vector view
26  *  @tparam T Type of the scalar
27  *  @tparam S Stride known at build time (default 1)
28  */
29 template<typename T,int stride=1>
30 struct VectorView
31 {
32 
33     /*
34 
35     Start and stop are the position in the raw Vector_base pointer.
36     Stop is the first sample outside of the vector
37 
38     */
39     VectorView() = delete;
40 
41     /**
42     * @brief  Compute the number of elements in the vector view
43     * @param start Vector view start index
44     * @param stop Vector view stop index (first elemnt after the view)
45     * @return Vector dimension
46     *
47     */
compute_lengtharm_cmsis_dsp::VectorView48     constexpr static vector_length_t compute_length(const index_t start,const index_t stop)
49     {
50         return(1+(stop-1 -start)/stride);
51     }
52 
53     /**
54     * @brief  Create a vector view on a buffer
55     * @param v Buffer of samples (not owned by the view)
56     * @param start Start index of the view
57     * @param stop Stop index of the view (first elemnt after the view)
58     *
59     */
VectorViewarm_cmsis_dsp::VectorView60     explicit VectorView(T *v,const vector_length_t start,const vector_length_t stop):
61       v_(v+start),nb_samples_(compute_length(start,stop)){};
62 
63    /**
64     * @brief  Create a vector on a vector
65     * @param v Vector storage (not owned by the view)
66     *
67     */
VectorViewarm_cmsis_dsp::VectorView68     explicit VectorView(const Vector_Base<T> &v):
69       v_(v.ptr()),nb_samples_(compute_length(0,v.length())){};
70 
71     /**
72     * @brief  Create a vector view on vector
73     * @param v Vector storage (not owned by the view)
74     * @param start Start index of the view
75     * @param stop Stop index of the view (first elemnt after the view)
76     *
77     */
VectorViewarm_cmsis_dsp::VectorView78     explicit VectorView(const Vector_Base<T> &v,const index_t start,const index_t stop):
79       v_(v.ptr()+start),nb_samples_(compute_length(start,stop)){};
80 
81     /**
82     * @brief  Vector view dimension
83     * @return Number of elements
84     *
85     */
lengtharm_cmsis_dsp::VectorView86     vector_length_t length() const {return(nb_samples_);};
87 
88 
89     /**
90     * @brief  Pointer to view storage
91     * @return Pointer to start of storage
92     *
93     */
ptrarm_cmsis_dsp::VectorView94     T* ptr() const {return(v_);}
95 
96     /**
97     * @brief  Pointer to view storage at index i
98     * @param i Index
99     * @return Pointer to storage at index i
100     *
101     * The stride is used to compute this pointer.
102     * The index is scaled by the stride.
103     */
ptrarm_cmsis_dsp::VectorView104     T* ptr(const index_t i) const {return(&v_[i*stride]);}
105 
106     /**
107     * @brief  Pointer to view constant storage
108     * @return Pointer to start of constant storage
109     *
110     */
const_ptrarm_cmsis_dsp::VectorView111     const T* const_ptr() const {return(v_);}
112 
113     /**
114     * @brief  Pointer to view constant storage at index i
115     * @param i Index
116     * @return Pointer to constant storage at index i
117     *
118     * The stride is used to compute this pointer.
119     * The index is scaled by the stride.
120     */
const_ptrarm_cmsis_dsp::VectorView121     const T* const_ptr(const index_t i) const {return(&v_[i*stride]);}
122 
123     /**
124     * @brief  Element at index i
125     * @param i Index
126     * @return Reference to element
127     *
128     * The stride is used to compute this reference.
129     * The index is scaled by the stride.
130     */
operator []arm_cmsis_dsp::VectorView131     T& operator[](const index_t i)
132     {
133         return(v_[i*stride]);
134     }
135 
136     /**
137     * @brief  Element at index i
138     * @param i Index
139     * @return Reference to element
140     *
141     * The stride is used to compute this reference.
142     * The index is scaled by the stride.
143     */
operator []arm_cmsis_dsp::VectorView144     T& operator[](const index_t i) const
145     {
146         return(v_[i*stride]);
147     }
148 
149 #if defined(HAS_VECTOR)
150      //! Type of vectors for a vector architecture and for scalar datatype P
151     using Vector = typename vector_traits<T>::vector;
152 
153     /**
154     * @brief   %Vector store at index i
155     *
156     * @param i index
157     * @param val Vector value
158     *
159     * On an architecture supporting vectors, if the scalar datatype T
160     * has a corresponding vector datatype, this function stores a vector
161     * value at index i in this vector datatype
162     */
vector_storearm_cmsis_dsp::VectorView163     void vector_store(const index_t i,const Vector val)
164     {
165         inner::vstore1<stride>((typename std::remove_cv<T>::type*)(&v_[i*stride]),val);
166     }
167 
168 #if defined(HAS_PREDICATED_LOOP)
169     /**
170     * @brief   %Vector store at index i with predicated tail
171     *
172     * @param i index
173     * @param remaining Number of remaining samples in the loop
174     * @param val Vector value to write at index i with tail predication
175     *
176     * On an architecture supporting vectors and predicated loops, if the
177     * scalar datatype T has a corresponding vector datatype, this
178     * function stores a vector value at index i in this vector datatype
179     * with predication
180     */
vector_store_tailarm_cmsis_dsp::VectorView181     void vector_store_tail(const index_t i,const vector_length_t remaining,const Vector val)
182     {
183         inner::vstore1_z<stride>((typename std::remove_cv<T>::type*)(&v_[i*stride]),val,remaining,inner::vctpq<T>::mk(remaining));
184     }
185 
186     /**
187     * @brief   %Vector operation at index i with predicated tail
188     *
189     * @param i index
190     * @param remaining Number of remaining samples in the loop
191     * @return Result of operation
192     *
193     * On an architecture supporting vectors and predicated loops, if the
194     * scalar datatype T has a corresponding vector datatype, this
195     * function execute an operation at index i with predication.
196     * In the case of a vector, this operation is a load
197     */
vector_op_tailarm_cmsis_dsp::VectorView198     Vector const vector_op_tail(const index_t i,const vector_length_t remaining) const
199     {
200         return(inner::vload1_z<stride>((typename std::remove_cv<T>::type*)(&v_[i*stride]),remaining,inner::vctpq<T>::mk(remaining)));
201     }
202 #endif
203 
204     /**
205     * @brief   %Vector operation at index i
206     *
207     * @param i index
208     * @return Result of operation
209     *
210     * On an architecture supporting vectors, if the
211     * scalar datatype T has a corresponding vector datatype, this
212     * function execute an operation at index i.
213     * In the case of a vector, this operation is a load
214     */
vector_oparm_cmsis_dsp::VectorView215     Vector const vector_op(const index_t i) const
216     {
217         return(inner::vload1<stride>((typename std::remove_cv<T>::type*)(&v_[i*stride])));
218     }
219 #endif
220 
~VectorViewarm_cmsis_dsp::VectorView221     virtual ~VectorView() {};
222 
223     /**
224     * @brief  Create a vector view from another view
225     * @param other the other vector view
226     *
227     * The new vector view will point to the same storage as the
228     * other vector view. No copy of element is occuring.
229     * To copy vector view content, the expr and copy operators
230     * are needed.
231     */
VectorViewarm_cmsis_dsp::VectorView232     VectorView(const VectorView& other):
233     v_(other.v_),nb_samples_(other.nb_samples_){};
234 
235 
236     /**
237     * @brief  Move a vector view to another view
238     * @param other the other vector view
239     *
240     * The new vector view will point to the same storage as the
241     * other vector view. No copy of element is occuring.
242     *
243     * The other vector view is no more valid (points to null storage)
244     */
VectorViewarm_cmsis_dsp::VectorView245     VectorView(VectorView&& other) :
246      v_(std::move(other.v_)),nb_samples_(other.nb_samples_)
247      {
248         other.v_ = nullptr;
249      };
250 
251 VectorView& operator=(const VectorView& other) = delete;
252 VectorView& operator=(VectorView&& other)  = delete;
253 
254 
255    /**
256     * @brief  Assign an expression to a vector view
257     * @tparam Derived the datatype representing the abstract syntax tree of the view
258     * @param other the expression
259     * @return the vector view
260     *
261     * Evaluate an expression an assign its result to the vector view
262     */
263    template<typename Derived>
operator =arm_cmsis_dsp::VectorView264    VectorView& operator=(const _Expr<Derived>&other)
265    {
266       eval(*this,other.derived(),length(),CURRENT_ARCH);
267       return(*this);
268    }
269 
270 
271    /**
272     * @brief  Assign a scalar to a vector view
273     * @param val the scalar
274     * @return the vector view
275     *
276     */
operator =arm_cmsis_dsp::VectorView277    VectorView& operator=(const T val)
278    {
279         _Fill(*this,val,length(),CURRENT_ARCH);
280 
281         return(*this);
282    }
283 
284    /**
285     * @brief  Elementwise  add an expression to a vector view
286     * @tparam Derived the datatype representing the abstract syntax tree of the view
287     * @param other the expression
288     * @return the vector view
289     *
290     */
291    template<typename Derived>
operator +=arm_cmsis_dsp::VectorView292    VectorView& operator +=(const _Expr<Derived>& other)
293    {
294       eval(*this,*this + other.derived(),length(),CURRENT_ARCH);
295       return(*this);
296    };
297 
298    /**
299     * @brief  Elementwise add a vector view to a vector view
300     * @param other the vector view to add
301     * @return the vector view
302     *
303     */
operator +=arm_cmsis_dsp::VectorView304    VectorView& operator +=(const VectorView& other)
305    {
306       eval(*this,*this + other,length(),CURRENT_ARCH);
307       return(*this);
308    };
309 
310    /**
311     * @brief  Elementwise  add a scalar to a vector view
312     * @param other the scalar
313     * @return the vector view
314     *
315     */
operator +=arm_cmsis_dsp::VectorView316    VectorView& operator +=(const T other)
317    {
318       eval(*this,*this + other,length(),CURRENT_ARCH);
319       return(*this);
320    };
321 
322     /**
323     * @brief  Elementwise  subtract an expression to a vector view
324     * @tparam Derived the datatype representing the abstract syntax tree of the view
325     * @param other the expression
326     * @return the vector view
327     *
328     */
329    template<typename Derived>
operator -=arm_cmsis_dsp::VectorView330    VectorView& operator -=(const _Expr<Derived>& other)
331    {
332       eval(*this,*this - other.derived(),length(),CURRENT_ARCH);
333       return(*this);
334    };
335 
336     /**
337     * @brief  Elementwise subtract a vector view to a vector view
338     * @param other the vector view to add
339     * @return the vector view
340     *
341     */
operator -=arm_cmsis_dsp::VectorView342    VectorView& operator -=(const VectorView& other)
343    {
344       eval(*this,*this - other,length(),CURRENT_ARCH);
345       return(*this);
346    };
347 
348    /**
349     * @brief  Elementwise  subtract a scalar to a vector view
350     * @param other the scalar
351     * @return the vector view
352     *
353     */
operator -=arm_cmsis_dsp::VectorView354    VectorView& operator -=(const T other)
355    {
356       eval(*this,*this - other,length(),CURRENT_ARCH);
357       return(*this);
358    };
359 
360     /**
361     * @brief  Elementwise multiply an expression to a vector view
362     * @tparam Derived the datatype representing the abstract syntax tree of the view
363     * @param other the expression
364     * @return the vector view
365     *
366     */
367    template<typename Derived>
operator *=arm_cmsis_dsp::VectorView368    VectorView& operator *=(const _Expr<Derived>& other)
369    {
370       eval(*this,*this * other.derived(),length(),CURRENT_ARCH);
371       return(*this);
372    };
373 
374     /**
375     * @brief  Elementwise multiply a vector view to a vector view
376     * @param other the vector view to add
377     * @return the vector view
378     *
379     */
operator *=arm_cmsis_dsp::VectorView380    VectorView& operator *=(const VectorView& other)
381    {
382       eval(*this,*this * other,length(),CURRENT_ARCH);
383       return(*this);
384    };
385 
386    /**
387     * @brief  Elementwise  multiply a scalar to a vector view
388     * @param other the scalar
389     * @return the vector view
390     *
391     */
operator *=arm_cmsis_dsp::VectorView392    VectorView& operator *=(const T other)
393    {
394       eval(*this,*this * other,length(),CURRENT_ARCH);
395       return(*this);
396    };
397 
398   /**
399     * @brief  Display the vector view content for debug purpose
400     * @param stream Output stream
401     * @param other The vector view to display
402     * @return the stream
403     *
404     */
operator <<(std::ostream & stream,const VectorView<T,stride> & other)405   friend std::ostream& operator<< (std::ostream& stream, const VectorView<T,stride>& other) {
406         constexpr int nb = 10;
407         int i=0;
408         for(index_t k=0;k<other.length();k++)
409         {
410            stream << other[k] << " , ";
411            i++;
412            if(i==nb)
413            {
414              i=0;
415              stream << "\r\n";
416            };
417         }
418         stream << "\r\n";
419         return(stream);
420     }
421 
422    /**
423     * @brief  Create a sub vector (a view of a view)
424     * @tparam S stride known at build time
425     * @param start Start index
426     * @param stop Stop index (first element after the view)
427     *             By default it is the vector view length
428     * @return the vector view
429     *
430     */
431    template<int S=1>
subarm_cmsis_dsp::VectorView432    VectorView<T,S*stride> sub(const index_t start=0,const index_t stop=-1)
433    {
434      if (stop < 0)
435      {
436        return(VectorView<T,S*stride>(v_,stride*start,stride*length()));
437      }
438      else
439      {
440        return(VectorView<T,S*stride>(v_,stride*start,stride*stop));
441      }
442    }
443 
444    /**
445     * @brief  Create a constant sub vector (a view of a view)
446     * @tparam S stride known at build time
447     * @param start Start index
448     * @param stop Stop index (first element after the view)
449     *             By default it is the vector view length
450     * @return the vector view
451     *
452     */
453    template<int S=1>
subarm_cmsis_dsp::VectorView454    const VectorView<T,S*stride> sub(const index_t start=0,const index_t stop=-1) const
455    {
456      if (stop < 0)
457      {
458         return(VectorView<T,S*stride>(v_,stride*start,stride*length()));
459      }
460      else
461      {
462         return(VectorView<T,S*stride>(v_,stride*start,stride*stop));
463      }
464    }
465 
466 
467 protected:
468     T* const v_;
469     const vector_length_t nb_samples_;
470 };
471 
472 /** @brief Vector view with dynamic stride (not known at build time)
473  *  @tparam T Type of the scalar
474  */
475 template<typename T>
476 struct VectorView<T,DYNAMIC>
477 {
478 
479     /*
480 
481     Start and stop are the position in the raw Vector_base pointer.
482     Stop is the first sample outside of the vector
483 
484     */
485     VectorView() = delete;
486 
487     /**
488     * @brief  Compute the number of elements in the vector view
489     * @param start Vector view start index
490     * @param stop Vector view stop index (first elemnt after the view)
491     * @param stride Stride (only known at runtime)
492     * @return Vector dimension
493     *
494     */
compute_lengtharm_cmsis_dsp::VectorView495     vector_length_t compute_length(const index_t start,const index_t stop,const index_t stride) const
496     {
497         return(1+(stop-1 -start)/stride);
498     }
499 
500     /**
501     * @brief  Create a vector view on a buffer
502     * @param v Buffer of samples (not owned by the view)
503     * @param start Start index of the view
504     * @param stop Stop index of the view (first elemnt after the view)
505     * @param stride Stride (only known at runtime)
506     *
507     */
VectorViewarm_cmsis_dsp::VectorView508     explicit VectorView(T *v,const index_t start,const index_t stop,const index_t stride):
509       v_(v+start),nb_samples_(compute_length(start,stop,stride)),stride_(stride){};
510 
511 
512     /**
513     * @brief  Create a vector view on a vector
514     * @param v Vector owning the storage (not owned by the view)
515     * @param stride Stride (only known at runtime)
516     *
517     * start is 0
518     * stop is defined by the length of the vector
519     *
520     */
VectorViewarm_cmsis_dsp::VectorView521     explicit VectorView(const Vector_Base<T> &v,const index_t stride):
522       v_(v.ptr()),nb_samples_(compute_length(0,v.length(),stride)),stride_(stride){};
523 
524     /**
525     * @brief  Create a vector view on a vector
526     * @param v Vector owning the storage (not owned by the view)
527     * @param start Start index of the view
528     * @param stop Stop index
529     * @param stride Stride (only known at runtime)
530     *
531     *
532     */
VectorViewarm_cmsis_dsp::VectorView533     explicit VectorView(const Vector_Base<T> &v,const index_t start,const index_t stop,const index_t stride):
534       v_(v.ptr()+start),nb_samples_(compute_length(start,stop,stride)),stride_(stride){};
535 
536     /**
537     * @brief  Vector view dimension
538     * @return Number of elements
539     *
540     */
lengtharm_cmsis_dsp::VectorView541     vector_length_t length() const {return(nb_samples_);};
542 
543 
544     /**
545     * @brief  Pointer to view storage
546     * @return Pointer to start of storage
547     *
548     */
ptrarm_cmsis_dsp::VectorView549     T* ptr() const {return(v_);}
550 
551     /**
552     * @brief  Pointer to view storage at index i
553     * @param i Index
554     * @return Pointer to storage at index i
555     *
556     * The stride is used to compute this pointer.
557     * The index is scaled by the stride.
558     */
ptrarm_cmsis_dsp::VectorView559     T* ptr(const index_t i) const {return(&v_[i*stride_]);}
560 
561 
562     /**
563     * @brief  Pointer to view constant storage
564     * @return Pointer to start of constant storage
565     *
566     */
const_ptrarm_cmsis_dsp::VectorView567     const T* const_ptr() const {return(v_);}
568 
569     /**
570     * @brief  Pointer to view constant storage at index i
571     * @param i Index
572     * @return Pointer to constant storage at index i
573     *
574     * The stride is used to compute this pointer.
575     * The index is scaled by the stride.
576     */
const_ptrarm_cmsis_dsp::VectorView577     const T* const_ptr(const index_t i) const {return(&v_[i*stride_]);}
578 
579     /**
580     * @brief  Element at index i
581     * @param i Index
582     * @return Reference to element
583     *
584     * The stride is used to compute this reference.
585     * The index is scaled by the stride.
586     */
operator []arm_cmsis_dsp::VectorView587     T& operator[](index_t i)
588     {
589         return(v_[i*stride_]);
590     }
591 
592     /**
593     * @brief  Element at index i
594     * @param i Index
595     * @return Reference to element
596     *
597     * The stride is used to compute this reference.
598     * The index is scaled by the stride.
599     */
operator []arm_cmsis_dsp::VectorView600     T& operator[](index_t i) const
601     {
602         return(v_[i*stride_]);
603     }
604 
605 #if defined(HAS_VECTOR)
606     //! Type of vectors for a vector architecture and for scalar datatype P
607     using Vector = typename vector_traits<T>::vector;
608 
609     /**
610     * @brief   %Vector store at index i
611     *
612     * @param i index
613     * @param val Vector value
614     *
615     * On an architecture supporting vectors, if the scalar datatype T
616     * has a corresponding vector datatype, this function stores a vector
617     * value at index i in this vector datatype
618     */
vector_storearm_cmsis_dsp::VectorView619     void vector_store(index_t i,Vector val)
620     {
621         inner::vstore1((typename std::remove_cv<T>::type*)(&v_[i*stride_]),stride_,val);
622     }
623 
624 #if defined(HAS_PREDICATED_LOOP)
625     /**
626     * @brief   %Vector store at index i with predicated tail
627     *
628     * @param i index
629     * @param remaining Number of remaining samples in the loop
630     * @param val Vector value to write at index i with tail predication
631     *
632     * On an architecture supporting vectors and predicated loops, if the
633     * scalar datatype T has a corresponding vector datatype, this
634     * function stores a vector value at index i in this vector datatype
635     * with predication
636     */
vector_store_tailarm_cmsis_dsp::VectorView637     void vector_store_tail(index_t i,vector_length_t remaining,Vector val)
638     {
639         inner::vstore1_z((typename std::remove_cv<T>::type*)(&v_[i*stride_]),stride_,val,remaining,inner::vctpq<T>::mk(remaining));
640     }
641 
642      /**
643     * @brief   %Vector operation at index i with predicated tail
644     *
645     * @param i index
646     * @param remaining Number of remaining samples in the loop
647     * @return Result of operation
648     *
649     * On an architecture supporting vectors and predicated loops, if the
650     * scalar datatype T has a corresponding vector datatype, this
651     * function execute an operation at index i with predication.
652     * In the case of a vector, this operation is a load
653     */
vector_op_tailarm_cmsis_dsp::VectorView654     Vector const vector_op_tail(index_t i,vector_length_t remaining) const
655     {
656         return(inner::vload1_z((typename std::remove_cv<T>::type*)(&v_[i*stride_]),stride_,remaining,inner::vctpq<T>::mk(remaining)));
657     }
658 #endif
659 
660     /**
661     * @brief   %Vector operation at index i
662     *
663     * @param i index
664     * @return Result of operation
665     *
666     * On an architecture supporting vectors, if the
667     * scalar datatype T has a corresponding vector datatype, this
668     * function execute an operation at index i.
669     * In the case of a vector, this operation is a load
670     */
vector_oparm_cmsis_dsp::VectorView671     Vector const vector_op(index_t i) const
672     {
673         return(inner::vload1((typename std::remove_cv<T>::type*)(&v_[i*stride_]),stride_));
674     }
675 #endif
676 
~VectorViewarm_cmsis_dsp::VectorView677     virtual ~VectorView() {};
678 
679     /**
680     * @brief  Create a vector view from another view
681     * @param other the other vector view
682     *
683     * The new vector view will point to the same storage as the
684     * other vector view. No copy of element is occuring.
685     * To copy vector view content, the expr and copy operators
686     * are needed.
687     */
VectorViewarm_cmsis_dsp::VectorView688     VectorView(const VectorView& other):
689     v_(other.v_),nb_samples_(other.nb_samples_),stride_(other.stride_){};
690 
691 
692     /**
693     * @brief  Move a vector view to another view
694     * @param other the other vector view
695     *
696     * The new vector view will point to the same storage as the
697     * other vector view. No copy of element is occuring.
698     *
699     * The other vector view is no more valid (points to null storage)
700     */
VectorViewarm_cmsis_dsp::VectorView701     VectorView(VectorView&& other) :
702      v_(std::move(other.v_)),nb_samples_(other.nb_samples_),stride_(other.stride_)
703      {
704         other.v_ = nullptr;
705      };
706 
707 VectorView& operator=(const VectorView& other) = delete;
708 VectorView& operator=(VectorView&& other)  = delete;
709 
710 
711 
712    /**
713     * @brief  Assign an expression to a vector view
714     * @tparam Derived the datatype representing the abstract syntax tree of the view
715     * @param other the expression
716     * @return the vector view
717     *
718     * Evaluate an expression an assign its result to the vector view
719     */
720    template<typename Derived>
operator =arm_cmsis_dsp::VectorView721    VectorView& operator=(const _Expr<Derived>&other)
722    {
723       eval(*this,other.derived(),length(),CURRENT_ARCH);
724       return(*this);
725    }
726 
727 
728     /**
729     * @brief  Assign a scalar to a vector view
730     * @param val the scalar
731     * @return the vector view
732     *
733     */
operator =arm_cmsis_dsp::VectorView734    VectorView& operator=(const T val)
735    {
736         _Fill(*this,val,length(),CURRENT_ARCH);
737 
738         return(*this);
739    }
740 
741    /**
742     * @brief  Elementwise  add an expression to a vector view
743     * @tparam Derived the datatype representing the abstract syntax tree of the view
744     * @param other the expression
745     * @return the vector view
746     *
747     */
748    template<typename Derived>
operator +=arm_cmsis_dsp::VectorView749    VectorView& operator +=(const _Expr<Derived>& other)
750    {
751       eval(*this,*this + other.derived(),length(),CURRENT_ARCH);
752       return(*this);
753    };
754 
755    /**
756     * @brief  Elementwise add a vector view to a vector view
757     * @param other the vector view to add
758     * @return the vector view
759     *
760     */
operator +=arm_cmsis_dsp::VectorView761    VectorView& operator +=(const VectorView& other)
762    {
763       eval(*this,*this + other,length(),CURRENT_ARCH);
764       return(*this);
765    };
766 
767     /**
768     * @brief  Elementwise  add a scalar to a vector view
769     * @param other the scalar
770     * @return the vector view
771     *
772     */
operator +=arm_cmsis_dsp::VectorView773    VectorView& operator +=(const T other)
774    {
775       eval(*this,*this + other,length(),CURRENT_ARCH);
776       return(*this);
777    };
778 
779     /**
780     * @brief  Elementwise  subtract an expression to a vector view
781     * @tparam Derived the datatype representing the abstract syntax tree of the view
782     * @param other the expression
783     * @return the vector view
784     *
785     */
786    template<typename Derived>
operator -=arm_cmsis_dsp::VectorView787    VectorView& operator -=(const _Expr<Derived>& other)
788    {
789       eval(*this,*this - other.derived(),length(),CURRENT_ARCH);
790       return(*this);
791    };
792 
793     /**
794     * @brief  Elementwise subtract a vector view to a vector view
795     * @param other the vector view to add
796     * @return the vector view
797     *
798     */
operator -=arm_cmsis_dsp::VectorView799    VectorView& operator -=(const VectorView& other)
800    {
801       eval(*this,*this - other,length(),CURRENT_ARCH);
802       return(*this);
803    };
804 
805    /**
806     * @brief  Elementwise  subtract a scalar to a vector view
807     * @param other the scalar
808     * @return the vector view
809     *
810     */
operator -=arm_cmsis_dsp::VectorView811    VectorView& operator -=(const T other)
812    {
813       eval(*this,*this - other,length(),CURRENT_ARCH);
814       return(*this);
815    };
816 
817     /**
818     * @brief  Elementwise multiply an expression to a vector view
819     * @tparam Derived the datatype representing the abstract syntax tree of the view
820     * @param other the expression
821     * @return the vector view
822     *
823     */
824    template<typename Derived>
operator *=arm_cmsis_dsp::VectorView825    VectorView& operator *=(const _Expr<Derived>& other)
826    {
827       eval(*this,*this * other.derived(),length(),CURRENT_ARCH);
828       return(*this);
829    };
830 
831     /**
832     * @brief  Elementwise multiply a vector view to a vector view
833     * @param other the vector view to add
834     * @return the vector view
835     *
836     */
operator *=arm_cmsis_dsp::VectorView837    VectorView& operator *=(const VectorView& other)
838    {
839       eval(*this,*this * other,length(),CURRENT_ARCH);
840       return(*this);
841    };
842 
843    /**
844     * @brief  Elementwise  multiply a scalar to a vector view
845     * @param other the scalar
846     * @return the vector view
847     *
848     */
operator *=arm_cmsis_dsp::VectorView849    VectorView& operator *=(const T other)
850    {
851       eval(*this,*this * other,length(),CURRENT_ARCH);
852       return(*this);
853    };
854 
855    /**
856     * @brief  Display the vector view content for debug purpose
857     * @param stream Output stream
858     * @param other The vector view to display
859     * @return the stream
860     *
861     */
operator <<(std::ostream & stream,const VectorView<T,DYNAMIC> & other)862   friend std::ostream& operator<< (std::ostream& stream, const VectorView<T,DYNAMIC>& other) {
863         constexpr int nb = 10;
864         int i=0;
865         for(index_t k=0;k<other.length();k++)
866         {
867            stream << other[k] << " , ";
868            i++;
869            if(i==nb)
870            {
871              i=0;
872              stream << "\r\n";
873            };
874         }
875         stream << "\r\n";
876         return(stream);
877     }
878 
879     /**
880     * @brief  Stride of the vector view
881     * @return the stride
882     *
883     */
stridearm_cmsis_dsp::VectorView884     index_t stride() const {return stride_;}
885 
886 
887    /**
888     * @brief  Create a sub vector (a view of a view)
889     * @tparam S stride known at build time
890     * @param start Start index
891     * @param stop Stop index (first element after the view)
892     *             By default it is the vector view length
893     * @return the vector view
894     *
895     */
896    template<int S=1>
subarm_cmsis_dsp::VectorView897    VectorView<T,DYNAMIC> sub(const index_t start=0,const index_t stop=-1)
898    {
899      if  (stop<0)
900      {
901         return(VectorView<T,DYNAMIC>(v_,stride()*start,stride()*length(),stride()*S));
902      }
903      else
904      {
905        return(VectorView<T,DYNAMIC>(v_,stride()*start,stride()*stop,stride()*S));
906      }
907    }
908 
909    /**
910     * @brief  Create a constant sub vector (a view of a view)
911     * @tparam S stride known at build time
912     * @param start Start index
913     * @param stop Stop index (first element after the view)
914     *             By default it is the vector view length
915     * @return the vector view
916     *
917     */
918    template<int S=1>
subarm_cmsis_dsp::VectorView919    const VectorView<T,DYNAMIC> sub(const index_t start=0,const index_t stop=-1) const
920    {
921      if  (stop<0)
922      {
923         return(VectorView<T,DYNAMIC>(v_,stride()*start,stride()*length(),stride()*S));
924      }
925      else
926      {
927        return(VectorView<T,DYNAMIC>(v_,stride()*start,stride()*stop,stride()*S));
928      }
929    }
930 
931 protected:
932     T* const v_;
933     const vector_length_t nb_samples_;
934     const index_t stride_;
935 };
936 
937 /*! @} */
938 
939 }
940 
941