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 
18 namespace arm_cmsis_dsp {
19 
20 /** \addtogroup VECTOR
21  *  @{
22  */
23 
24 /*
25 
26 Generic evaluators.
27 
28 */
29 #include "Scalar/basic.hpp"
30 #include "DSP/basic.hpp"
31 #include "Helium/basic.hpp"
32 #include "Neon/basic.hpp"
33 
34 /** @brief Storage for a vector
35  *  @tparam P Type of the scalar
36  */
37 template<typename P>
38 struct Vector_Base {
39 
40     //! Type of vector elements
41     typedef P element_type;
42 
43 
44     /**
45     * @brief   Vector dimension
46     * @return Vector dimension
47     *
48     */
lengtharm_cmsis_dsp::Vector_Base49     vector_length_t length() const   {return(length_);};
50 
51     /**
52     * @brief      Pointer to storage buffer
53     * @return Pointer to storage
54     */
ptrarm_cmsis_dsp::Vector_Base55     P* ptr() const {return(values_);}
56 
57     /**
58     * @brief      Pointer to storage buffer at index i
59     *
60     * @param i Index in buffer
61     * @return Pointer to storage
62     *
63     */
ptrarm_cmsis_dsp::Vector_Base64     P* ptr(const index_t i) const {return(&values_[i]);}
65 
66     /**
67     * @brief      Pointer to storage buffer
68     * @return Pointer to constant storage
69     *
70     */
const_ptrarm_cmsis_dsp::Vector_Base71     const P* const_ptr() const {return(values_);}
72 
73     /**
74     * @brief      Pointer to storage buffer at index i
75     *
76     * @param i Index in buffer
77     * @return Pointer to constant storage
78     *
79     */
const_ptrarm_cmsis_dsp::Vector_Base80     const P* const_ptr(const index_t i) const {return(&values_[i]);}
81 
82 
83 
84     /**
85     * @brief   Iterator begin
86     *
87     * @return Pointer to start of buffer
88     *
89     */
beginarm_cmsis_dsp::Vector_Base90     P* begin() const {return(values_);}
91 
92     /**
93     * @brief   Iterator end
94     *
95     * @return Pointer to first element after end of buffer
96     *
97     */
endarm_cmsis_dsp::Vector_Base98     P* end() const {return(values_+length_);}
99 
100     /**
101     * @brief  Display the vector content for debug purpose
102     * @param stream Output stream
103     * @param other The vector to display
104     * @return the stream
105     *
106     */
operator <<(std::ostream & stream,const Vector_Base<P> & other)107     friend std::ostream& operator<< (std::ostream& stream, const Vector_Base<P>& other) {
108         constexpr int nb = 10;
109         int i=0;
110         for(index_t k=0;k<other.length();k++)
111         {
112            stream << other[k] << " , ";
113            i++;
114            if(i==nb)
115            {
116              i=0;
117              stream << "\r\n";
118            };
119         }
120         stream << "\r\n";
121         return(stream);
122     }
123 
~Vector_Basearm_cmsis_dsp::Vector_Base124     virtual ~Vector_Base(){};
125 
Vector_Basearm_cmsis_dsp::Vector_Base126     Vector_Base(Vector_Base&& other) :
127      length_(other.length_),values_(other.values_){
128         other.values_=nullptr;
129         other.length_ = 0;
130      };
131 
132     // Done in derivated classes since they have
133    // knowledge of the allocator to use
134    // But used in VectorView
135    Vector_Base(const Vector_Base& other) = delete;
136    //   length_(other.length_),values_(other.values_){};
137 
138 
139    /**
140     * @brief      Element at index i
141     *
142     * @param i index
143     * @return     Reference to element
144     */
operator []arm_cmsis_dsp::Vector_Base145    P& operator[](const index_t i)
146    {
147        return(values_[i]);
148    }
149 
150    /**
151     * @brief      Element at index i
152     *
153     * @param i index
154     * @return     Reference to element
155     */
operator []arm_cmsis_dsp::Vector_Base156    P& operator[](const index_t i) const
157    {
158        return(values_[i]);
159    }
160 
161 #if defined(HAS_VECTOR)
162     //! Type of vectors for a vector architecture and for scalar datatype P
163     using Vector = typename vector_traits<P>::vector;
164 
165     /**
166     * @brief   %Vector store at index i
167     *
168     * @tparam T scalar datatype
169     * @param i index
170     * @param val Vector value
171     *
172     * On an architecture supporting vectors, if the scalar datatype T
173     * has a corresponding vector datatype, this function stores a vector
174     * value at index i in this vector datatype
175     */
176     template<typename T=P,
177              typename std::enable_if<vector_traits<T>::has_vector,bool>::type = true>
vector_storearm_cmsis_dsp::Vector_Base178     void vector_store(const index_t i,const Vector val) const
179     {
180         inner::vstore1<1>((typename std::remove_cv<P>::type*)(&values_[i]),val);
181     }
182 
183 #if defined(HAS_PREDICATED_LOOP)
184     /**
185     * @brief   %Vector store at index i with predicated tail
186     *
187     * @param i index
188     * @param remaining Number of remaining samples in the loop
189     * @param val Vector value to write at index i with tail predication
190     *
191     * On an architecture supporting vectors and predicated loops, if the
192     * scalar datatype T has a corresponding vector datatype, this
193     * function stores a vector value at index i in this vector datatype
194     * with predication
195     */
vector_store_tailarm_cmsis_dsp::Vector_Base196     void vector_store_tail(const index_t i,const vector_length_t remaining,const Vector val) const
197     {
198         inner::vstore1_z<1>((typename std::remove_cv<P>::type*)(&values_[i]),val,remaining,inner::vctpq<P>::mk(remaining));
199     }
200 
201     /**
202     * @brief   %Vector operation at index i with predicated tail
203     *
204     * @param i index
205     * @param remaining Number of remaining samples in the loop
206     * @return Result of operation
207     *
208     * On an architecture supporting vectors and predicated loops, if the
209     * scalar datatype T has a corresponding vector datatype, this
210     * function execute an operation at index i with predication.
211     * In the case of a vector, this operation is a load
212     */
vector_op_tailarm_cmsis_dsp::Vector_Base213     Vector const vector_op_tail(const index_t i,const vector_length_t remaining) const
214     {
215         return(inner::vload1_z<1>((typename std::remove_cv<P>::type*)(&values_[i]),remaining,inner::vctpq<P>::mk(remaining)));
216     }
217 #endif
218 
219     /**
220     * @brief   %Vector operation at index i
221     *
222     * @param i index
223     * @return Result of operation
224     *
225     * On an architecture supporting vectors, if the
226     * scalar datatype T has a corresponding vector datatype, this
227     * function execute an operation at index i.
228     * In the case of a vector, this operation is a load
229     */
vector_oparm_cmsis_dsp::Vector_Base230     Vector const vector_op(const index_t i) const
231     {
232         return(inner::vload1<1>((typename std::remove_cv<P>::type*)(&values_[i])));
233     }
234 
235 #endif
236 
237 
238 
239 protected:
240 
241    //Vector_Base():length_(0),values_(nullptr){};
242     Vector_Base() = delete;
243 
Vector_Basearm_cmsis_dsp::Vector_Base244    explicit Vector_Base(vector_length_t length, char *val):
245    length_(length),
246    values_(reinterpret_cast<P*>(val)){};
247 
Vector_Basearm_cmsis_dsp::Vector_Base248    explicit Vector_Base(vector_length_t length, char *val,P init_val):
249    length_(length),
250    values_(reinterpret_cast<P*>(val)){
251     _Fill(*this,init_val,length,CURRENT_ARCH);
252    };
253 
254 
operator =arm_cmsis_dsp::Vector_Base255    Vector_Base& operator=(const Vector_Base& other)
256    {
257         if ((length_ == other.length_) && (this != &other))
258         {
259             _Fill(*this,other,other.length_,CURRENT_ARCH);
260              //std::memcpy(values_,other.values_,sizeof(P)*length_);
261         }
262       return(*this);
263    }
264 
265    // Done in derivated classes since we need
266    // the allocator destroy
267    Vector_Base& operator=(Vector_Base&& other) = delete;
268 
269 
270 
271 
272    vector_length_t length_;
273    P* values_;
274 };
275 
276 
277 template<typename T>
278 struct traits<Vector_Base<T>>
279 {
280     typedef T Scalar;
281 #if defined(HAS_VECTOR)
282     typedef typename vector_traits<T>::vector Vector;
283 #endif
284 };
285 
286 /** @brief Vector template for size knonw at build time
287  *  @tparam P Type of the scalar
288  *  @tparam L Vector length in number of elements.
289  *            Negative if length not known at build time. It is the default value
290  *  @tparam Allocator Memory allocator to use. By default it is the macro `TMP_ALLOC`
291  */
292 template<typename P,
293          int L=DYNAMIC,
294          template<int> typename Allocator = TMP_ALLOC>
295 struct Vector:Vector_Base<P> {
296 
297 
298    //! Type of vector elements
299    using element_type = P;
300 
301    //! Length of the vector when known at build time.
302    constexpr static vector_length_t vector_size = sizeof(P)*L;
303 
304    /**
305     * @brief      Allocate a buffer for this vector using the memory allocator
306     *
307     * @return     A new memory buffer
308     */
allocatearm_cmsis_dsp::Vector309    static char* allocate(){return(Allocator<vector_size>::allocate());};
310 
311    /**
312     * @brief      Construct a new vector
313     *
314     *             The length is known at build time.
315     *
316     */
Vectorarm_cmsis_dsp::Vector317    Vector():Vector_Base<P>(L,Vector::allocate()){};
318 
319     /**
320     * @brief      Construct a new vector and initialize it
321     *
322     *             The length is known at build time.
323     *
324     * @param init_val Initialization value
325     */
Vectorarm_cmsis_dsp::Vector326    explicit Vector(P init_val):Vector_Base<P>(L,Vector::allocate(),init_val){
327    };
328 
329    /**
330     * @brief      Construct a new vector and initialize it with a list
331     *
332     *             A vector can be initialized like an array using {} syntax
333     *             The length is known at build time.
334     *
335     * @param l Initialization list
336     */
Vectorarm_cmsis_dsp::Vector337    Vector(const std::initializer_list<P> &l)
338    :Vector_Base<P>(L,Vector::allocate()){
339      std::memcpy(Vector_Base<P>::values_,l.data(),vector_size);
340    };
341 
342   Vector(Vector&& other) = default;
343 
Vectorarm_cmsis_dsp::Vector344   Vector(const Vector& other):Vector_Base<P>(L,Vector::allocate())
345   {
346         eval(*this,+other,(vector_length_t)L,CURRENT_ARCH);
347 
348         //std::memcpy(Vector_Base<P>::values_,other.values_,vector_size);
349   };
350 
351   /**
352     * @brief      Create a vector from a vector using a different memory allocator
353     *
354     * @param other Other vector using a different memory allocator
355     */
356    template<template<int> typename OtherAllocator>
Vectorarm_cmsis_dsp::Vector357    explicit Vector(const Vector<P,L,OtherAllocator>& other):Vector_Base<P>(L,Vector::allocate())
358    {
359         eval(*this,+other,(vector_length_t)L,CURRENT_ARCH);
360    };
361 
362    template<template<int> typename OtherAllocator>
Vectorarm_cmsis_dsp::Vector363    explicit Vector(const Vector<P,DYNAMIC,OtherAllocator>& other):Vector_Base<P>(L,Vector::allocate())
364    {
365         if (other.length() == Vector_Base<P>::length())
366         {
367            eval(*this,+other,(vector_length_t)L,CURRENT_ARCH);
368         }
369    };
370 
371     /**
372     * @brief      Create a vector from a VectorView
373     *
374     * @tparam S The stride of the vector view known at build time
375     * @param other The vector view
376     */
377    template<int S>
Vectorarm_cmsis_dsp::Vector378    explicit Vector(const VectorView<P,S>& other):Vector_Base<P>(L,Vector::allocate())
379    {
380         eval(*this,+other,(vector_length_t)L,CURRENT_ARCH);
381    };
382 
383 
384 
385     /**
386     * @brief      Create a vector from an expression
387     *
388     * @tparam Derived The type representing the abstract syntax tree
389     * @param other The expression
390     *
391     * It is the mechanism allowing to evaluate an expression
392     * and merge all of the operators the of the expression in the
393     * same loop
394     */
395    template<typename Derived>
Vectorarm_cmsis_dsp::Vector396    Vector(const _Expr<Derived>& other):Vector_Base<P>(L,Vector::allocate())
397    {
398         eval(*this,other.derived(),(vector_length_t)L,CURRENT_ARCH);
399    };
400 
401 
402   Vector& operator=(const Vector& other) = default;
403 
operator =arm_cmsis_dsp::Vector404   Vector& operator=(Vector&& other)
405    {
406       if (this != &other)
407       {
408         if (Vector_Base<P>::values_!=nullptr)
409         {
410            Allocator<vector_size>::destroy(reinterpret_cast<char*>(Vector_Base<P>::values_));
411         }
412 
413         Vector_Base<P>::length_= other.length_;
414         Vector_Base<P>::values_ = other.values_;
415         other.values_=nullptr;
416         other.length_ = 0;
417       }
418 
419       return(*this);
420    }
421 
422   /**
423   * @brief      Copy result of an expression to a vector content
424   *
425   * @tparam Derived The type representing the abstract syntax tree
426   * @param other The expression
427   * @return A reference to the vector
428   *
429   * It is the mechanism allowing to evaluate an expression
430   * and merge all of the operators the of the expression in the
431   * same loop
432   */
433   template<typename Derived>
operator =arm_cmsis_dsp::Vector434   Vector& operator=(const _Expr<Derived>&other)
435   {
436       eval(*this,other.derived(),(vector_length_t)L,CURRENT_ARCH);
437       return(*this);
438   }
439 
440 
441   /**
442   * @brief      Fill a vector with a constant
443   *
444   * @tparam T The constant datatype
445   * @param other The const
446   * @return A reference to the vector
447   *
448   */
449   template<typename T,
450            typename std::enable_if<is_scalar<T>(),bool>::type = true>
451   Vector& operator=(const T other)
452   {
453       _Fill(*this,other,L,CURRENT_ARCH);
454       return(*this);
455   }
456 
457 
458 
459 
460    /**
461    * @brief    Elementwise add the result of an expression to a vector
462    *
463    * @tparam Derived The type representing the abstract syntax tree of the expression
464    * @param other The expression
465    * @return A reference to the vector
466    *
467    */
468    template<typename Derived>
operator +=arm_cmsis_dsp::Vector469    Vector& operator +=(const _Expr<Derived>& other)
470    {
471       eval(*this,*this + other.derived(),(vector_length_t)L,CURRENT_ARCH);
472       return(*this);
473    };
474 
475    /**
476    * @brief    Elementwise add vector to another vector
477    *
478    * @param other The vector
479    * @return A reference to the vector
480    *
481    */
operator +=arm_cmsis_dsp::Vector482    Vector& operator +=(const Vector& other)
483    {
484       eval(*this,*this + other,(vector_length_t)L,CURRENT_ARCH);
485       return(*this);
486    };
487 
488 
489    /**
490    * @brief    Elementwise add a constant to a vector
491    *
492    * @tparam P The constant datatype
493    * @param other The expression
494    * @return A reference to the vector
495    *
496    */
operator +=arm_cmsis_dsp::Vector497    Vector& operator +=(const P other)
498    {
499       eval(*this,*this + other,(vector_length_t)L,CURRENT_ARCH);
500       return(*this);
501    };
502 
503    /**
504    * @brief    Elementwise subtract the result of an expression from a vector
505    *
506    * @tparam Derived The type representing the abstract syntax tree of the expression
507    * @param other The expression
508    * @return A reference to the vector
509    *
510    */
511    template<typename Derived>
operator -=arm_cmsis_dsp::Vector512    Vector& operator -=(const _Expr<Derived>& other)
513    {
514       eval(*this,*this - other.derived(),(vector_length_t)L,CURRENT_ARCH);
515       return(*this);
516    };
517 
518 
519    /**
520    * @brief    Elementwise subtract a vector from a vector
521    *
522    * @param other The other vector
523    * @return A reference to the vector
524    *
525    */
operator -=arm_cmsis_dsp::Vector526    Vector& operator -=(const Vector& other)
527    {
528       eval(*this,*this - other,(vector_length_t)L,CURRENT_ARCH);
529       return(*this);
530    };
531 
532    /**
533    * @brief    Elementwise subtract a constant from a vector
534    *
535    * @tparam P Datatype of the constant
536    * @param other The constant
537    * @return A reference to the vector
538    *
539    */
operator -=arm_cmsis_dsp::Vector540    Vector& operator -=(const P other)
541    {
542       eval(*this,*this - other,(vector_length_t)L,CURRENT_ARCH);
543       return(*this);
544    };
545 
546 
547    /**
548    * @brief    Elementwise multiply the result of an expression with a vector
549    *
550    * @tparam Derived The type representing the abstract syntax tree of the expression
551    * @param other The expression
552    * @return A reference to the vector
553    *
554    */
555    template<typename Derived>
operator *=arm_cmsis_dsp::Vector556    Vector& operator *=(const _Expr<Derived>& other)
557    {
558       eval(*this,*this * other.derived(),(vector_length_t)L,CURRENT_ARCH);
559       return(*this);
560    };
561 
562    /**
563    * @brief    Elementwise multiply a vector with a vector
564    *
565    * @param other The othr vector
566    * @return A reference to the vector
567    *
568    */
operator *=arm_cmsis_dsp::Vector569    Vector& operator *=(const Vector& other)
570    {
571       eval(*this,*this * other,(vector_length_t)L,CURRENT_ARCH);
572       return(*this);
573    };
574 
575    /**
576    * @brief    Elementwise multiply a constant with a vector
577    *
578    * @tparam Derived Constant datatype
579    * @param other The constant
580    * @return A reference to the vector
581    *
582    */
operator *=arm_cmsis_dsp::Vector583    Vector& operator *=(const P other)
584    {
585       eval(*this,*this * other,(vector_length_t)L,CURRENT_ARCH);
586       return(*this);
587    };
588 
589 
590 
591    /**
592    * @brief    Create a vector view
593    *
594    * @tparam S Stride known at build time
595    * @param start Start index for the vector view
596    * @param stop Stop index for the vector view (first element after the vector view)
597    *             Default is length of the vector if known at build time.
598    * @return A reference to the vector view
599    *
600    */
601    template<int S=1>
subarm_cmsis_dsp::Vector602    VectorView<P,S> sub(const index_t start=0,const index_t stop=L)
603    {
604      return(VectorView<P,S>(*this,start,stop));
605    }
606 
607    template<int S=1>
subarm_cmsis_dsp::Vector608    const VectorView<P,S> sub(const index_t start=0,const index_t stop=L) const
609    {
610      return(VectorView<P,S>(*this,start,stop));
611    }
612 
613 
~Vectorarm_cmsis_dsp::Vector614    virtual ~Vector() {
615       if (Vector_Base<P>::values_!=nullptr)
616       {
617          Allocator<vector_size>::destroy(reinterpret_cast<char*>(Vector_Base<P>::values_));
618       }
619     }
620 
621 
622 
623 
624 };
625 
626 
627 /** @brief Vector template for dynamic vector (size known at runtime)
628  *  @tparam P Type of the scalar
629  *  @tparam Allocator Memory allocator to use. By default it is the macro `TMP_ALLOC`
630  */
631 template<typename P,
632          template<int> typename Allocator>
633 struct Vector<P,DYNAMIC,Allocator>:Vector_Base<P> {
634 
635     /**
636     * @brief      Allocate a buffer for this vector using the memory allocator
637     *
638     * @param length Vector dimension
639     * @return     A new memory buffer
640     */
allocatearm_cmsis_dsp::Vector641     static char* allocate(vector_length_t length){return(Allocator<DYNAMIC>::allocate(sizeof(P)*length));};
642 
643     Vector() = delete;
644 
645     /**
646     * @brief  Create a new vector
647     *
648     * @param length Vector dimension
649     * @param init_val Initialization value
650     */
Vectorarm_cmsis_dsp::Vector651     explicit Vector(vector_length_t length,P init_val):
652     Vector_Base<P>(length,Vector::allocate(length),init_val){};
653 
654     /**
655     * @brief  Create a new vector
656     *
657     * @param length Vector dimension
658     */
Vectorarm_cmsis_dsp::Vector659     explicit Vector(vector_length_t length):
660     Vector_Base<P>(length,Vector::allocate(length)){};
661 
662 
663     /**
664     * @brief  Create a new vector
665     *
666     * @param l Initializer list
667     *          A vector can be initialized like an array using {} syntax
668     */
Vectorarm_cmsis_dsp::Vector669     explicit Vector(const std::initializer_list<P> &l)
670     :Vector_Base<P>(l.size(),Vector::allocate(l.size())){
671        std::memcpy(Vector_Base<P>::values_,l.data(),sizeof(P)*l.size());
672     };
673 
674    /**
675     * @brief  Create a new vector from a vector using a different memory allocator
676     *
677     * @tparam K Dimension of other vector (statically known or dynamic)
678     * @param other The vector to copy
679     */
680    template<int K,template<int> typename OtherAllocator>
Vectorarm_cmsis_dsp::Vector681    explicit Vector(const Vector<P,K,OtherAllocator>& other):Vector_Base<P>(other.length(),Vector::allocate(other.length()))
682    {
683         eval(*this,+other,Vector_Base<P>::length(),CURRENT_ARCH);
684    };
685 
686 
687    /**
688     * @brief  Create a new vector from a vector of same type
689     *
690     * @param other The vector to copy
691     */
Vectorarm_cmsis_dsp::Vector692    Vector(const Vector& other):Vector_Base<P>(other.length(),Vector::allocate(other.length()))
693    {
694         eval(*this,+other,Vector_Base<P>::length(),CURRENT_ARCH);
695 
696         //std::memcpy(Vector_Base<P>::values_,other.values_,vector_size);
697    };
698 
699    /**
700     * @brief  Create a new vector from a vector view
701     *
702     * @tparam S Stride of vector view known at build time
703     * @param other The vector to copy
704     */
705    template<int S>
Vectorarm_cmsis_dsp::Vector706    explicit Vector(const VectorView<P,S>& other):Vector_Base<P>(other.length(),Vector::allocate(other.length()))
707    {
708         eval(*this,+other,Vector_Base<P>::length(),CURRENT_ARCH);
709    };
710 
711    /**
712     * @brief  Create a new vector from an expressipn
713     *
714     * @tparam Derived Type representing the abstract syntax tree of the expression
715     * @param other The expression to evaluate
716     */
717    template<typename Derived>
Vectorarm_cmsis_dsp::Vector718    Vector(const _Expr<Derived>& other):Vector_Base<P>(other.length(),Vector::allocate(other.length()))
719    {
720         eval(*this,other.derived(),Vector_Base<P>::length(),CURRENT_ARCH);
721    };
722 
723    Vector(Vector&& other) = default;
724 
725 
726 
727    Vector& operator=(const Vector& other) = default;
728 
operator =arm_cmsis_dsp::Vector729    Vector& operator=(Vector&& other)
730    {
731       if (this != &other)
732       {
733         if (Vector_Base<P>::values_!=nullptr)
734         {
735            Allocator<DYNAMIC>::destroy(reinterpret_cast<char*>(Vector_Base<P>::values_));
736         }
737 
738         Vector_Base<P>::length_= other.length_;
739         Vector_Base<P>::values_ = other.values_;
740         other.values_=nullptr;
741         other.length_ = 0;
742       }
743 
744       return(*this);
745    }
746 
747   /**
748     * @brief  Fill a vector with an expression
749     *
750     * @tparam Derived Type representing the abstract syntax tree of the expression
751     * @param other The expression to evaluate
752     * @return A reference to the vector
753     */
754   template<typename Derived>
operator =arm_cmsis_dsp::Vector755   Vector& operator=(const _Expr<Derived>&other)
756   {
757       eval(*this,other.derived(),Vector_Base<P>::length(),CURRENT_ARCH);
758       return(*this);
759   }
760 
761   /**
762     * @brief  Fill a vector with a scalar
763     *
764     * @tparam T Scalar datatype
765     * @param other The scalar
766     * @return A reference to the vector
767     */
768   template<typename T,
769            typename std::enable_if<is_scalar<T>(),bool>::type = true>
770   Vector& operator=(const T other)
771   {
772       _Fill(*this,other,Vector_Base<P>::length(),CURRENT_ARCH);
773       return(*this);
774   }
775 
776     /**
777     * @brief  Elementwise add an expression to a vector
778     *
779     * @tparam Derived Type representing the abstract syntax tree of the expression
780     * @param other The expression to evaluate
781     * @return A reference to the vector
782     */
783    template<typename Derived>
operator +=arm_cmsis_dsp::Vector784    Vector& operator +=(const _Expr<Derived>& other)
785    {
786       eval(*this,*this + other.derived(),Vector_Base<P>::length(),CURRENT_ARCH);
787       return(*this);
788    };
789 
790    /**
791     * @brief  Elementwise add a vector to a vector
792     *
793     * @param other The vector to add
794     * @return A reference to the vector
795     */
operator +=arm_cmsis_dsp::Vector796    Vector& operator +=(const Vector& other)
797    {
798       eval(*this,*this + other,Vector_Base<P>::length(),CURRENT_ARCH);
799       return(*this);
800    };
801 
802    /**
803     * @brief  Elementwise add a scalar to a vector
804     *
805     * @tparam P Scalar datatype
806     * @param other The scalar
807     * @return A reference to the vector
808     */
operator +=arm_cmsis_dsp::Vector809    Vector& operator +=(const P other)
810    {
811       eval(*this,*this + other,Vector_Base<P>::length(),CURRENT_ARCH);
812       return(*this);
813    };
814 
815    /**
816     * @brief  Elementwise subtract an expression to a vector
817     *
818     * @tparam Derived Type representing the abstract syntax tree of the expression
819     * @param other The expression to evaluate
820     * @return A reference to the vector
821     */
822    template<typename Derived>
operator -=arm_cmsis_dsp::Vector823    Vector& operator -=(const _Expr<Derived>& other)
824    {
825       eval(*this,*this - other.derived(),Vector_Base<P>::length(),CURRENT_ARCH);
826       return(*this);
827    };
828 
829    /**
830     * @brief  Elementwise subtract a vector to a vector
831     *
832     * @param other The vector to add
833     * @return A reference to the vector
834     */
operator -=arm_cmsis_dsp::Vector835    Vector& operator -=(const Vector& other)
836    {
837       eval(*this,*this - other,Vector_Base<P>::length(),CURRENT_ARCH);
838       return(*this);
839    };
840 
841    /**
842     * @brief  Elementwise subtract a scalar to a vector
843     *
844     * @tparam P Scalar datatype
845     * @param other The scalar
846     * @return A reference to the vector
847     */
operator -=arm_cmsis_dsp::Vector848    Vector& operator -=(const P other)
849    {
850       eval(*this,*this - other,Vector_Base<P>::length(),CURRENT_ARCH);
851       return(*this);
852    };
853 
854    /**
855     * @brief  Elementwise multiply an expression with a vector
856     *
857     * @tparam Derived Type representing the abstract syntax tree of the expression
858     * @param other The expression to evaluate
859     * @return A reference to the vector
860     */
861    template<typename Derived>
operator *=arm_cmsis_dsp::Vector862    Vector& operator *=(const _Expr<Derived>& other)
863    {
864       eval(*this,*this * other.derived(),Vector_Base<P>::length(),CURRENT_ARCH);
865       return(*this);
866    };
867 
868    /**
869     * @brief  Elementwise multiply a vector with a vector
870     *
871     * @param other The vector to add
872     * @return A reference to the vector
873     */
operator *=arm_cmsis_dsp::Vector874    Vector& operator *=(const Vector& other)
875    {
876       eval(*this,*this * other,Vector_Base<P>::length(),CURRENT_ARCH);
877       return(*this);
878    };
879 
880 
881   /**
882     * @brief  Elementwise multiply a scalar with a vector
883     *
884     * @tparam P Scalar datatype
885     * @param other The scalar
886     * @return A reference to the vector
887     */
operator *=arm_cmsis_dsp::Vector888    Vector& operator *=(const P other)
889    {
890       eval(*this,*this * other,Vector_Base<P>::length(),CURRENT_ARCH);
891       return(*this);
892    };
893 
894    /**
895     * @brief  Create a vector view
896     *
897     * @tparam S stride
898     * @param start Start index of view
899     * @param stop Stop index of view (first index after end of view)
900     *              By default it is the length of the vector.
901     * @return The vector view
902     */
903    template<int S=1>
subarm_cmsis_dsp::Vector904    VectorView<P,S> sub(const index_t start=0,const index_t stop=-1)
905    {
906      if  (stop<0)
907      {
908         return(VectorView<P,S>(*this,start,Vector_Base<P>::length()));
909      }
910      else
911      {
912        return(VectorView<P,S>(*this,start,stop));
913      }
914    }
915 
916    template<int S=1>
subarm_cmsis_dsp::Vector917    const VectorView<P,S> sub(const index_t start=0,const index_t stop=-1) const
918    {
919      if  (stop<0)
920      {
921         return(VectorView<P,S>(*this,start,Vector_Base<P>::length()));
922      }
923      else
924      {
925        return(VectorView<P,S>(*this,start,stop));
926      }
927    }
928 
929 
930 
~Vectorarm_cmsis_dsp::Vector931    virtual ~Vector() {
932       if (Vector_Base<P>::values_!=nullptr)
933       {
934          Allocator<DYNAMIC>::destroy(reinterpret_cast<char*>(Vector_Base<P>::values_));
935       }
936     }
937 
938 };
939 
940 /*! @} */
941 
942 }
943 
944