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