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