1 // -*- C++ -*- 2 /** @file */ 3 #pragma once 4 5 6 #include <memory> 7 #include <cstring> 8 #include <algorithm> 9 #include <iostream> 10 #include "common.hpp" 11 #include "arch.hpp" 12 #include <type_traits> 13 #include "number.hpp" 14 #include "forward.hpp" 15 #include "fusion.hpp" 16 #include "unroll.hpp" 17 #include "algorithms.hpp" 18 #include "vec.hpp" 19 20 namespace arm_cmsis_dsp { 21 22 /** \addtogroup Matrix 23 * @{ 24 */ 25 26 /******************** 27 * 28 * MATRIX 29 * 30 ********************/ 31 32 /** 33 * @brief Slice 34 */ 35 struct Slice 36 { 37 /** 38 * @brief Create new slice object 39 * @param s start index 40 * @param e stop index 41 * 42 */ Slicearm_cmsis_dsp::Slice43 Slice(const index_t s,const index_t e):start(s),stop(e){}; 44 45 //! Start index 46 const index_t start; 47 48 //! Stop index 49 const index_t stop; 50 }; 51 52 /** @brief Matrix 53 * @tparam P Type of the scalar 54 * @tparam R Number of rows 55 * @tparam C Number of columns 56 * @tparam Allocator Memory allocator 57 */ 58 template<typename P,int R=DYNAMIC,int C=DYNAMIC, 59 template<int> typename Allocator = TMP_ALLOC> 60 struct Matrix:Vector<P,R*C,Allocator> 61 { 62 /** @brief Number of rows 63 * @return Number of rows 64 */ rowsarm_cmsis_dsp::Matrix65 constexpr vector_length_t rows() const {return(R);} 66 67 /** @brief Number of columns 68 * @return Number of columns 69 */ columnsarm_cmsis_dsp::Matrix70 constexpr vector_length_t columns() const {return(C);} 71 72 /** @brief Number of stride 73 * @return Number of stride 74 */ stridearm_cmsis_dsp::Matrix75 constexpr uint32_t stride() const {return(C);} 76 77 78 /** @brief Create matrix 79 */ Matrixarm_cmsis_dsp::Matrix80 Matrix():Vector<P,R*C,Allocator>(){}; 81 82 /** @brief Create matrix 83 * @param init_val Initialization value 84 */ Matrixarm_cmsis_dsp::Matrix85 explicit Matrix(P init_val):Vector<P,R*C,Allocator>(init_val){}; 86 87 Matrix(const Matrix& other) = default; 88 Matrix(Matrix&& other) = default; 89 90 /** @brief Create matrix from another matrix using different memory allocator 91 * @tparam OtherAllocator other memory allocator 92 * @param other Other matrix 93 */ 94 template<template<int> typename OtherAllocator> Matrixarm_cmsis_dsp::Matrix95 explicit Matrix(const Matrix<P,R,C,OtherAllocator>& other):Vector<P,R*C,Allocator>() 96 { 97 eval(*this,+other,(vector_length_t)(R*C),CURRENT_ARCH); 98 }; 99 100 /* Applies only when the AST does not contain any dynamic MatrixView */ 101 102 /** @brief Create matrix from expression 103 * @tparam Derived Datatype representing the abstract syntax tree of the expression 104 * @param other Other matrix 105 * 106 * Only applies when the expression does not contain any MatrixView since 107 * matrix view may have a stride and cannot be used as vectors. 108 */ 109 template<typename Derived, 110 typename std::enable_if<IsVector<Derived>::value,bool>::type = true> Matrixarm_cmsis_dsp::Matrix111 Matrix(const _Expr<Derived>& other):Vector<P,R*C,Allocator>(other) 112 { 113 }; 114 115 /* Applies only when AST is containing any dynamic MatrixView */ 116 117 /** @brief Create matrix from expression 118 * @tparam Derived Datatype representing the abstract syntax tree of the expression 119 * @param other Other matrix 120 * 121 * Applies when contain a matrix view that has a stride and thus force a 2D 122 * evaluation loop. 123 */ 124 template<typename Derived, 125 typename std::enable_if<must_use_matrix_idx<Derived>(),bool>::type = true> 126 Matrix(const _Expr<Derived>& other):Vector<P,R*C,Allocator>() 127 { 128 eval2D(*this,other.derived(),rows(),columns(),CURRENT_ARCH); 129 }; 130 131 /** @brief Assign matrix from expression 132 * @tparam Derived Datatype representing the abstract syntax tree of the expression 133 * @param other Other matrix 134 * @return the matrix 135 * 136 * Applies when expression does not contain matrix view 137 */ 138 template<typename Derived, 139 typename std::enable_if<IsVector<Derived>::value,bool>::type = true> operator =arm_cmsis_dsp::Matrix140 Matrix& operator=(const _Expr<Derived>& other) 141 { 142 eval(*this,other.derived(),(vector_length_t)R*C,CURRENT_ARCH); 143 return(*this); 144 } 145 146 /* Applies only when AST is containing any dynamic MatrixView */ 147 /** @brief Assign matrix from expression 148 * @tparam Derived Datatype representing the abstract syntax tree of the expression 149 * @param other Other matrix 150 * @return the matrix 151 * 152 * Applies when contain a matrix view that has a stride and thus force a 2D 153 * evaluation loop. 154 */ 155 template<typename Derived, 156 typename std::enable_if<must_use_matrix_idx<Derived>(),bool>::type = true> 157 Matrix& operator=(const _Expr<Derived>& other) 158 { 159 eval2D(*this,other.derived(),rows(),columns(),CURRENT_ARCH); 160 return(*this); 161 } 162 163 /** @brief Create a matrix view 164 * @param rs start row 165 * @param cs start column 166 * @return matrix view 167 * 168 */ subarm_cmsis_dsp::Matrix169 MatrixView<P,C> sub(const index_t rs,const index_t cs) 170 { 171 const vector_length_t nb_rows = rows() - rs; 172 const vector_length_t nb_cols = columns() - cs; 173 174 return(MatrixView<P,C>(Vector_Base<P>::ptr(rs*stride()+cs),nb_rows,nb_cols)); 175 } 176 177 /** @brief Create a constant matrix view 178 * @param rs start row 179 * @param cs start column 180 * @return matrix view 181 * 182 */ subarm_cmsis_dsp::Matrix183 const MatrixView<P,C> sub(const index_t rs,const index_t cs) const 184 { 185 const vector_length_t nb_rows = rows() - rs; 186 const vector_length_t nb_cols = columns() - cs; 187 188 return(MatrixView<P,C>(Vector_Base<P>::ptr(rs*stride()+cs),nb_rows,nb_cols)); 189 } 190 191 /** @brief Create a matrix view 192 * @param rs Row slice (start and end row) 193 * @param cs start column 194 * @return matrix view 195 * 196 */ subarm_cmsis_dsp::Matrix197 MatrixView<P,C> sub(const Slice &rs,const index_t cs) 198 { 199 const vector_length_t nb_rows = rs.stop - rs.start; 200 const vector_length_t nb_cols = columns() - cs; 201 202 return(MatrixView<P,C>(Vector_Base<P>::ptr(rs.start*stride()+cs),nb_rows,nb_cols)); 203 } 204 205 /** @brief Create a constant matrix view 206 * @param rs Row slice (start and end row) 207 * @param cs start column 208 * @return matrix view 209 * 210 */ subarm_cmsis_dsp::Matrix211 const MatrixView<P,C> sub(const Slice &rs,const index_t cs) const 212 { 213 const vector_length_t nb_rows = rs.stop - rs.start; 214 const vector_length_t nb_cols = columns() - cs; 215 216 return(MatrixView<P,C>(Vector_Base<P>::ptr(rs.start*stride()+cs),nb_rows,nb_cols)); 217 } 218 219 220 /** @brief Create a matrix view 221 * @param rs Row start index 222 * @param cs Column slice 223 * @return matrix view 224 * 225 */ subarm_cmsis_dsp::Matrix226 MatrixView<P,C> sub(const index_t rs,const Slice &cs) 227 { 228 const vector_length_t nb_rows = rows() - rs; 229 const vector_length_t nb_cols = cs.stop - cs.start; 230 231 return(MatrixView<P,C>(Vector_Base<P>::ptr(rs*stride()+cs.start),nb_rows,nb_cols)); 232 } 233 234 /** @brief Create a constant matrix view 235 * @param rs Row start index 236 * @param cs Column slice 237 * @return matrix view 238 * 239 */ subarm_cmsis_dsp::Matrix240 const MatrixView<P,C> sub(const index_t rs,const Slice &cs) const 241 { 242 const vector_length_t nb_rows = rows() - rs; 243 const vector_length_t nb_cols = cs.stop - cs.start; 244 245 return(MatrixView<P,C>(Vector_Base<P>::ptr(rs*stride()+cs.start),nb_rows,nb_cols)); 246 } 247 248 /** @brief Create a matrix view 249 * @param rs Row slice 250 * @param cs Column slice 251 * @return matrix view 252 * 253 */ subarm_cmsis_dsp::Matrix254 MatrixView<P,C> sub(const Slice& rs,const Slice& cs) 255 { 256 const vector_length_t nb_rows = rs.stop - rs.start; 257 const vector_length_t nb_cols = cs.stop - cs.start; 258 259 return(MatrixView<P,C>(Vector_Base<P>::ptr(rs.start*stride()+cs.start),nb_rows,nb_cols)); 260 } 261 262 /** @brief Create a constant matrix view 263 * @param rs Row slice 264 * @param cs Column slice 265 * @return matrix view 266 * 267 */ subarm_cmsis_dsp::Matrix268 const MatrixView<P,C> sub(const Slice& rs,const Slice& cs) const 269 { 270 const vector_length_t nb_rows = rs.stop - rs.start; 271 const vector_length_t nb_cols = cs.stop - cs.start; 272 273 return(MatrixView<P,C>(Vector_Base<P>::ptr(rs.start*stride()+cs.start),nb_rows,nb_cols)); 274 } 275 276 /** @brief Create a matrix view 277 * @param rs Row start 278 * @param re Row end 279 * @param cs Column start 280 * @param ce Column end 281 * @return matrix view 282 * 283 */ subarm_cmsis_dsp::Matrix284 MatrixView<P,C> sub(const index_t rs, 285 const index_t re, 286 const index_t cs, 287 const index_t ce) 288 { 289 const vector_length_t nb_rows = re - rs; 290 const vector_length_t nb_cols = ce - cs; 291 292 return(MatrixView<P,C>(Vector_Base<P>::ptr(rs*stride()+cs),nb_rows,nb_cols)); 293 } 294 295 /** @brief Create a constant matrix view 296 * @param rs Row start 297 * @param re Row end 298 * @param cs Column start 299 * @param ce Column end 300 * @return matrix view 301 * 302 */ subarm_cmsis_dsp::Matrix303 const MatrixView<P,C> sub(const index_t rs, 304 const index_t re, 305 const index_t cs, 306 const index_t ce) const 307 { 308 const vector_length_t nb_rows = re - rs; 309 const vector_length_t nb_cols = ce - cs; 310 311 return(MatrixView<P,C>(Vector_Base<P>::ptr(rs*stride()+cs),nb_rows,nb_cols)); 312 } 313 314 315 Matrix& operator=(const Matrix& other) = default; 316 317 Matrix& operator=(Matrix&& other) = default; 318 319 /** @brief Access matrix element at given position 320 * @param r Row index 321 * @param c Column index 322 * @return reference to element 323 * 324 */ operator ()arm_cmsis_dsp::Matrix325 P& operator()(const index_t r,const index_t c) 326 { 327 return(Vector_Base<P>::ptr()[r*C+c]); 328 } 329 330 /** @brief Access matrix element at given position 331 * @param r Row index 332 * @param c Column index 333 * @return reference to element 334 * 335 */ operator ()arm_cmsis_dsp::Matrix336 P& operator()(const index_t r,const index_t c) const 337 { 338 return(Vector_Base<P>::ptr()[r*C+c]); 339 } 340 341 342 /** 343 * @brief Display the matrix content for debug purpose 344 * @param stream Output stream 345 * @param other The matrix to display 346 * @return the stream 347 * 348 */ operator <<(std::ostream & stream,const Matrix & other)349 friend std::ostream& operator<< (std::ostream& stream, const Matrix& other) { 350 int c=0; 351 for(index_t k=0;k<other.length();k++) 352 { 353 stream << other[k] << " , "; 354 c++; 355 if (c == other.columns()) 356 { 357 c=0; 358 stream << "\r\n"; 359 } 360 } 361 stream << "\r\n"; 362 return(stream); 363 } 364 365 /** @brief Create a row view vector with stride 366 * @tparam S stride 367 * @param i row index 368 * @param start Start index in row 369 * @param stop Stop index in row 370 * Default is number of columns 371 * @return row view vector 372 * 373 */ 374 template<int S=1> rowarm_cmsis_dsp::Matrix375 VectorView<P,S> row(const index_t i,const index_t start=0,const index_t stop=C) 376 { 377 return(VectorView<P,S>(*this,i*stride()+start,i*stride()+stop)); 378 } 379 380 /** @brief Create a constant row view vector with stride 381 * @tparam S stride 382 * @param i row index 383 * @param start Start index in row 384 * @param stop Stop index in row 385 * Default is number of columns 386 * @return row view vector 387 * 388 */ 389 template<int S=1> rowarm_cmsis_dsp::Matrix390 const VectorView<P,S> row(const index_t i,const index_t start=0,const index_t stop=C) const 391 { 392 return(VectorView<P,S>(*this,i*stride()+start,i*stride()+stop)); 393 } 394 395 /** @brief Create a column view vector with stride 396 * @tparam S stride 397 * @param i column index 398 * @param start Start index in row 399 * @param stop Stop index in row 400 * Default is number of rows 401 * @return column view vector 402 * 403 */ 404 template<int CS=1,int S=C> colarm_cmsis_dsp::Matrix405 VectorView<P,CS*S> col(const index_t i,const index_t start=0,const index_t stop=R) 406 { 407 return(VectorView<P,CS*S>(*this,i+stride()*start,i+stride()*stop)); 408 } 409 410 /** @brief Create a constant column view vector with stride 411 * @tparam S stride 412 * @param i column index 413 * @param start Start index in row 414 * @param stop Stop index in row 415 * Default is number of rows 416 * @return column view vector 417 * 418 */ 419 template<int CS=1,int S=C> colarm_cmsis_dsp::Matrix420 const VectorView<P,CS*S> col(const index_t i,const index_t start=0,const index_t stop=R) const 421 { 422 return(VectorView<P,CS*S>(*this,i+stride()*start,i+stride()*stop)); 423 } 424 425 /** @brief Create a diagonal matrix 426 * @tparam RA Number of rows 427 * @tparam CA Number of columns 428 * @tparam VA Vector datatype 429 * @param a Vector for initializing the diagonal 430 * @return a matrix 431 * 432 * Only exists when RA == CA and the size is known at built time 433 * 434 */ 435 template<int RA=R,int CA=C,typename VA, 436 typename std::enable_if<IsVector<VA>::value && 437 (RA == CA) && (RA>0) && 438 SameElementType<VA,P>::value,bool>::type = true> diagonalarm_cmsis_dsp::Matrix439 static Matrix<P,RA,CA,Allocator> diagonal(const VA& a) 440 { 441 Matrix<P,RA,CA,Allocator> res; 442 _diagonal(res,a,RA); 443 return(res); 444 } 445 446 /** @brief Fill diagonal of a matrix with a vector 447 * @tparam RA Number of rows 448 * @tparam CA Number of columns 449 * @tparam VA Vector datatype 450 * @param a Vector for initializing the diagonal 451 * 452 * Only exists when RA == CA and the size is known at built time 453 * 454 */ 455 template<int RA=R,int CA=C,typename VA, 456 typename std::enable_if<IsVector<VA>::value && 457 (RA == CA) && (RA>0) && 458 SameElementType<VA,P>::value,bool>::type = true> fill_diagonalarm_cmsis_dsp::Matrix459 void fill_diagonal(const VA& a) 460 { 461 _fill_diagonal(*this,a,RA); 462 } 463 464 /** @brief Create an identity matrix 465 * @tparam RA Number of rows 466 * @tparam CA Number of columns 467 * @return a matrix 468 * 469 * Only exists when RA == CA and the size is known at built time 470 * 471 */ 472 template<int RA=R, int CA=C, 473 typename std::enable_if< 474 (RA == CA) && (RA>0),bool>::type = true> identityarm_cmsis_dsp::Matrix475 static Matrix<P,RA,CA,Allocator> identity() 476 { 477 Matrix<P,RA,CA,Allocator> res; 478 _identity(res,RA); 479 return(res); 480 } 481 482 /** @brief Create a matrix of same type 483 * @return a matrix 484 * 485 */ createarm_cmsis_dsp::Matrix486 Matrix<P,R,C,Allocator> create() const 487 { 488 Matrix<P,R,C,Allocator> res; 489 return(res); 490 } 491 492 /** @brief Create the transposed matrix 493 * @return a matrix 494 * 495 */ transposearm_cmsis_dsp::Matrix496 Matrix<P,C,R,Allocator> transpose() const 497 { 498 Matrix<P,C,R,Allocator> res; 499 transposeTo(res,*this); 500 return(res); 501 } 502 503 #if defined(HAS_VECTOR) 504 //! Type of vectors for a vector architecture and for scalar datatype P 505 using VectorType = typename vector_traits<P>::vector; 506 507 /** 508 * @brief %Vector store at a given row,column position 509 * 510 * @param row row index 511 * @param col column index 512 * @param val %Vector value 513 * 514 * On an architecture supporting vectors, if the scalar datatype T 515 * has a corresponding vector datatype, this function stores a vector 516 * value at row,column in this matrix. 517 */ matrix_storearm_cmsis_dsp::Matrix518 void matrix_store(const index_t row, 519 const index_t col, 520 const VectorType val) const 521 { 522 Vector_Base<P>::vector_store(row*C + col,val); 523 } 524 525 #if defined(HAS_PREDICATED_LOOP) 526 /** 527 * @brief %Vector store at a given row,column position with predicated tail 528 * 529 * @param row row index 530 * @param col column index 531 * @param remaining Number of remaining samples in the loop 532 * @param val Vector value to write at index i with tail predication 533 * 534 * On an architecture supporting vectors and predicated loops, if the 535 * scalar datatype T has a corresponding vector datatype, this 536 * function stores a vector value at row,column index in this matrix datatype 537 * with predication 538 */ matrix_store_tailarm_cmsis_dsp::Matrix539 void matrix_store_tail(const index_t row, 540 const index_t col, 541 const vector_length_t remaining, 542 const VectorType val) const 543 { 544 Vector_Base<P>::vector_store_tail(row*C + col,remaining,val); 545 } 546 547 /** 548 * @brief %Vector operation at a given row,column position with predicated tail 549 * 550 * @param row row index 551 * @param col column index 552 * @param remaining Number of remaining samples in the loop 553 * @return the vector result of the operation 554 * 555 * On an architecture supporting vectors and predicated loops, if the 556 * scalar datatype T has a corresponding vector datatype, this 557 * function compute an operation at row,column index in this matrix datatype 558 * with predication 559 */ matrix_op_tailarm_cmsis_dsp::Matrix560 VectorType const matrix_op_tail(const index_t row, 561 const index_t col, 562 const vector_length_t remaining) const 563 { 564 return(Vector_Base<P>::vector_op_tail(row*C + col,remaining)); 565 } 566 #endif 567 568 /** 569 * @brief %Vector operation at a given row,column position 570 * 571 * @param row row index 572 * @param col column index 573 * @return the vector result of the operation 574 * 575 * On an architecture supporting vectors and predicated loops, if the 576 * scalar datatype T has a corresponding vector datatype, this 577 * function compute an operation at row,column index in this matrix datatype 578 */ matrix_oparm_cmsis_dsp::Matrix579 VectorType const matrix_op(const index_t row, 580 const index_t col) const 581 { 582 return(Vector_Base<P>::vector_op(row*C + col)); 583 } 584 #endif 585 586 }; 587 588 /** @brief Matrix 589 * @tparam P Type of the scalar 590 * @tparam Allocator Memory allocator 591 */ 592 template<typename P, 593 template<int> typename Allocator> 594 struct Matrix<P,DYNAMIC,DYNAMIC,Allocator>:Vector<P,DYNAMIC,Allocator> 595 { 596 /** @brief Number of rows 597 * @return Number of rows 598 */ rowsarm_cmsis_dsp::Matrix599 vector_length_t rows() const {return(rows_);} 600 601 /** @brief Number of columns 602 * @return Number of columns 603 */ columnsarm_cmsis_dsp::Matrix604 vector_length_t columns() const {return(columns_);} 605 606 /** @brief Number of stride 607 * @return Number of stride 608 */ stridearm_cmsis_dsp::Matrix609 uint32_t stride() const {return(columns_);} 610 611 /** @brief Create matrix 612 * @param r number of rows 613 * @param c number of columns 614 */ Matrixarm_cmsis_dsp::Matrix615 explicit Matrix(vector_length_t r,vector_length_t c): 616 Vector<P,DYNAMIC,Allocator>(r*c),rows_(r),columns_(c){}; 617 618 /** @brief Create matrix 619 * @param r number of rows 620 * @param c number of columns 621 * @param init_val Initialization value 622 */ Matrixarm_cmsis_dsp::Matrix623 explicit Matrix(vector_length_t r,vector_length_t c,P init_val): 624 Vector<P,DYNAMIC,Allocator>(r*c,init_val),rows_(r),columns_(c){}; 625 626 Matrix(const Matrix& other) = default; 627 Matrix(Matrix&& other) = default; 628 629 /** @brief Access matrix element at given position 630 * @param r Row index 631 * @param c Column index 632 * @return reference to element 633 * 634 */ operator ()arm_cmsis_dsp::Matrix635 P& operator()(const index_t r,const index_t c) 636 { 637 return(Vector_Base<P>::ptr()[r*columns()+c]); 638 } 639 640 /** @brief Access matrix element at given position 641 * @param r Row index 642 * @param c Column index 643 * @return reference to element 644 * 645 */ operator ()arm_cmsis_dsp::Matrix646 P& operator()(const index_t r,const index_t c) const 647 { 648 return(Vector_Base<P>::ptr()[r*columns()+c]); 649 } 650 651 /** @brief Create matrix from another matrix using different memory allocator 652 * @tparam RK Number of rows 653 * @tparam CK Number of columns 654 * @tparam OtherAllocator other memory allocator 655 * @param other Other matrix 656 */ 657 template<int RK,int CK,template<int> typename OtherAllocator> Matrixarm_cmsis_dsp::Matrix658 explicit Matrix(const Matrix<P,RK,CK,OtherAllocator>& other): 659 Vector<P,DYNAMIC,Allocator>(other.rows()*other.columns()), 660 rows_(other.rows()),columns_(other.columns()) 661 { 662 if ((other.rows() == rows()) && (other.columns() == columns())) 663 { 664 eval(*this,+other,(vector_length_t)(other.rows()*other.columns()),CURRENT_ARCH); 665 } 666 }; 667 668 /** @brief Create matrix from expression 669 * @tparam Derived Datatype representing the abstract syntax tree of the expression 670 * @param other Other matrix 671 * 672 * Only applies when the expression does not contain any MatrixView since 673 * matrix view may have a stride and cannot be used as vectors. 674 */ 675 template<typename Derived, 676 typename std::enable_if<IsVector<Derived>::value,bool>::type = true> Matrixarm_cmsis_dsp::Matrix677 Matrix(const _Expr<Derived>& other):Vector<P,DYNAMIC,Allocator>(other), 678 rows_(other.rows()),columns_(other.columns()) 679 { 680 }; 681 682 /** @brief Create matrix from expression 683 * @tparam Derived Datatype representing the abstract syntax tree of the expression 684 * @param other Other matrix 685 * 686 * Applies when contain a matrix view that has a stride and thus force a 2D 687 * evaluation loop. 688 */ 689 template<typename Derived, 690 typename std::enable_if<must_use_matrix_idx<Derived>(),bool>::type = true> 691 Matrix(const _Expr<Derived>& other): 692 Vector<P,DYNAMIC,Allocator>(other.rows()*other.columns()), 693 rows_(other.rows()),columns_(other.columns()) 694 { 695 eval2D(*this,other.derived(),rows(),columns(),CURRENT_ARCH); 696 }; 697 698 /** @brief Assign matrix from expression 699 * @tparam Derived Datatype representing the abstract syntax tree of the expression 700 * @param other Other matrix 701 * @return the matrix 702 * 703 * Applies when expression does not contain matrix view 704 */ 705 template<typename Derived, 706 typename std::enable_if<IsVector<Derived>::value,bool>::type = true> operator =arm_cmsis_dsp::Matrix707 Matrix& operator=(const _Expr<Derived>& other) 708 { 709 eval(*this,other.derived(),rows()*columns(),CURRENT_ARCH); 710 return(*this); 711 }; 712 713 714 /** @brief Assign matrix from expression 715 * @tparam Derived Datatype representing the abstract syntax tree of the expression 716 * @param other Other matrix 717 * @return the matrix 718 * 719 * Applies when contain a matrix view that has a stride and thus force a 2D 720 * evaluation loop. 721 */ 722 template<typename Derived, 723 typename std::enable_if<must_use_matrix_idx<Derived>(),bool>::type = true> 724 Matrix& operator=(const _Expr<Derived>& other) 725 { 726 eval2D(*this,other.derived(),rows(),columns(),CURRENT_ARCH); 727 return(*this); 728 }; 729 730 Matrix& operator=(const Matrix& other) = default; 731 732 Matrix& operator=(Matrix&& other) = default; 733 734 /** 735 * @brief Display the matrix content for debug purpose 736 * @param stream Output stream 737 * @param other The matrix to display 738 * @return the stream 739 * 740 */ operator <<(std::ostream & stream,const Matrix & other)741 friend std::ostream& operator<< (std::ostream& stream, const Matrix& other) { 742 int c=0; 743 for(index_t k=0;k<other.length();k++) 744 { 745 stream << other[k] << " , "; 746 c++; 747 if (c == other.columns()) 748 { 749 c=0; 750 stream << "\r\n"; 751 } 752 } 753 stream << "\r\n"; 754 return(stream); 755 } 756 757 /** @brief Create a diagonal matrix 758 * @tparam VA Vector datatype 759 * @param a Vector for initializing the diagonal 760 * @return a matrix 761 * 762 * 763 */ 764 template<typename VA, 765 typename std::enable_if<IsVector<VA>::value && 766 SameElementType<VA,P>::value,bool>::type = true> diagonalarm_cmsis_dsp::Matrix767 static Matrix<P,DYNAMIC,DYNAMIC,Allocator> diagonal(const VA& a) 768 { 769 Matrix<P,DYNAMIC,DYNAMIC,Allocator> res(a.length(),a.length()); 770 _diagonal(res,a,a.length()); 771 return(res); 772 } 773 774 /** @brief Fill diagonal of a matrix with a vector 775 * @tparam VA Vector datatype 776 * @param a Vector for initializing the diagonal 777 * 778 */ 779 template<typename VA, 780 typename std::enable_if<IsVector<VA>::value && 781 SameElementType<VA,P>::value,bool>::type = true> fill_diagonalarm_cmsis_dsp::Matrix782 void fill_diagonal(const VA& a) 783 { 784 _fill_diagonal(*this,a,this->length()); 785 } 786 787 /** @brief Create an identity matrix 788 * @param l Matrix dimension (l x l) 789 * @return a matrix 790 * 791 */ identityarm_cmsis_dsp::Matrix792 static Matrix<P,DYNAMIC,DYNAMIC,Allocator> identity(const vector_length_t l) 793 { 794 Matrix<P,DYNAMIC,DYNAMIC,Allocator> res(l,l); 795 _identity(res,l); 796 return(res); 797 } 798 799 /** @brief Create a matrix of same type 800 * @return a matrix 801 * 802 */ createarm_cmsis_dsp::Matrix803 Matrix<P,DYNAMIC,DYNAMIC,Allocator> create() const 804 { 805 Matrix<P,DYNAMIC,DYNAMIC,Allocator> res(rows(),columns()); 806 return(res); 807 } 808 809 /** @brief Create the transposed matrix 810 * @return a matrix 811 * 812 */ transposearm_cmsis_dsp::Matrix813 Matrix<P,DYNAMIC,DYNAMIC,Allocator> transpose() const 814 { 815 Matrix<P,DYNAMIC,DYNAMIC,Allocator> res(columns(),rows()); 816 transposeTo(res,*this); 817 return(res); 818 } 819 820 /** @brief Create a row view with stride 1 821 * @param i row index 822 * @param start Start index in row 823 * @return row view vector 824 * 825 */ rowarm_cmsis_dsp::Matrix826 VectorView<P,1> row(const index_t i,const index_t start=0) 827 { 828 return(VectorView<P,1>(*this,i*this->stride()+start,i*this->stride()+this->columns())); 829 } 830 831 /** @brief Create a row view with stride 1 832 * @param i row index 833 * @param start Start index in row 834 * @param stop Stop index in row 835 * @return row view vector 836 * 837 */ rowarm_cmsis_dsp::Matrix838 VectorView<P,1> row(const index_t i,const index_t start,const index_t stop) 839 { 840 return(VectorView<P,1>(*this,i*this->stride()+start,i*this->stride()+stop)); 841 } 842 843 /** @brief Create a constant row view with stride 1 844 * @param i row index 845 * @param start Start index in row 846 * @return row view vector 847 * 848 */ rowarm_cmsis_dsp::Matrix849 const VectorView<P,1> row(const index_t i,const index_t start=0) const 850 { 851 return(VectorView<P,1>(*this,i*this->stride()+start,i*this->stride()+this->columns())); 852 } 853 854 /** @brief Create a constant row view with stride 1 855 * @param i row index 856 * @param start Start index in row 857 * @param stop Stop index in row 858 * @return row view vector 859 * 860 */ rowarm_cmsis_dsp::Matrix861 const VectorView<P,1> row(const index_t i,const index_t start,const index_t stop) const 862 { 863 return(VectorView<P,1>(*this,i*this->stride()+start,i*this->stride()+stop)); 864 } 865 866 /** @brief Create a column view vector 867 * @tparam CS column stride 868 * @param i column index 869 * @param start Start index in column 870 * @return column view vector 871 * 872 */ 873 template<int CS=1> colarm_cmsis_dsp::Matrix874 VectorView<P,DYNAMIC> col(const index_t i,const index_t start=0) 875 { 876 return(VectorView<P,DYNAMIC>(*this,i+this->stride()*start,i+this->stride()*this->rows(),this->stride()*CS)); 877 } 878 879 /** @brief Create a column view vector 880 * @tparam CS column stride 881 * @param i column index 882 * @param start Start index in column 883 * @param stop Stop index in column 884 * @return column view vector 885 * 886 */ 887 template<int CS=1> colarm_cmsis_dsp::Matrix888 VectorView<P,DYNAMIC> col(const index_t i,const index_t start,const index_t stop) 889 { 890 return(VectorView<P,DYNAMIC>(*this,i+this->stride()*start,i+this->stride()*stop,this->stride()*CS)); 891 } 892 893 /** @brief Create a constant column view vector 894 * @tparam CS column stride 895 * @param i column index 896 * @param start Start index in column 897 * @return column view vector 898 * 899 */ 900 template<int CS=1> colarm_cmsis_dsp::Matrix901 const VectorView<P,DYNAMIC> col(const index_t i,const index_t start=0) const 902 { 903 return(VectorView<P,DYNAMIC>(*this,i+this->stride()*start,i+this->stride()*this->rows(),this->stride()*CS)); 904 } 905 906 /** @brief Create a constant column view vector 907 * @tparam CS column stride 908 * @param i column index 909 * @param start Start index in column 910 * @param stop Stop index in column 911 * @return column view vector 912 * 913 */ 914 template<int CS=1> colarm_cmsis_dsp::Matrix915 const VectorView<P,DYNAMIC> col(const index_t i,const index_t start,const index_t stop) const 916 { 917 return(VectorView<P,DYNAMIC>(*this,i+this->stride()*start,i+this->stride()*stop,this->stride()*CS)); 918 } 919 920 #if defined(HAS_VECTOR) 921 //! Type of vectors for a vector architecture and for scalar datatype P 922 using VectorType = typename vector_traits<P>::vector; 923 924 /** 925 * @brief %Vector store at a given row,column position 926 * 927 * @param row row index 928 * @param col column index 929 * @param val %Vector value 930 * 931 * On an architecture supporting vectors, if the scalar datatype T 932 * has a corresponding vector datatype, this function stores a vector 933 * value at row,column in this matrix. 934 */ matrix_storearm_cmsis_dsp::Matrix935 void matrix_store(const index_t row, 936 const index_t col, 937 const VectorType val) const 938 { 939 Vector_Base<P>::vector_store(row*stride() + col,val); 940 } 941 942 #if defined(HAS_PREDICATED_LOOP) 943 944 /** 945 * @brief %Vector store at a given row,column position with predicated tail 946 * 947 * @param row row index 948 * @param col column index 949 * @param remaining Number of remaining samples in the loop 950 * @param val Vector value to write at index i with tail predication 951 * 952 * On an architecture supporting vectors and predicated loops, if the 953 * scalar datatype T has a corresponding vector datatype, this 954 * function stores a vector value at row,column index in this matrix datatype 955 * with predication 956 */ matrix_store_tailarm_cmsis_dsp::Matrix957 void matrix_store_tail(const index_t row, 958 const index_t col, 959 const vector_length_t remaining, 960 const VectorType val) const 961 { 962 Vector_Base<P>::vector_store_tail(row*stride() + col,remaining,val); 963 } 964 965 /** 966 * @brief %Vector operation at a given row,column position with predicated tail 967 * 968 * @param row row index 969 * @param col column index 970 * @param remaining Number of remaining samples in the loop 971 * @return the vector result of the operation 972 * 973 * On an architecture supporting vectors and predicated loops, if the 974 * scalar datatype T has a corresponding vector datatype, this 975 * function compute an operation at row,column index in this matrix datatype 976 * with predication 977 */ matrix_op_tailarm_cmsis_dsp::Matrix978 VectorType const matrix_op_tail(const index_t row, 979 const index_t col, 980 const vector_length_t remaining) const 981 { 982 return(Vector_Base<P>::vector_op_tail(row*stride() + col,remaining)); 983 } 984 #endif 985 986 /** 987 * @brief %Vector operation at a given row,column position 988 * 989 * @param row row index 990 * @param col column index 991 * @return the vector result of the operation 992 * 993 * On an architecture supporting vectors and predicated loops, if the 994 * scalar datatype T has a corresponding vector datatype, this 995 * function compute an operation at row,column index in this matrix datatype 996 */ matrix_oparm_cmsis_dsp::Matrix997 VectorType const matrix_op(const index_t row, 998 const index_t col) const 999 { 1000 return(Vector_Base<P>::vector_op(row*stride() + col)); 1001 } 1002 #endif 1003 1004 /** @brief Create a matrix view 1005 * @param rs start row 1006 * @param cs start column 1007 * @return matrix view 1008 * 1009 */ subarm_cmsis_dsp::Matrix1010 MatrixView<P,DYNAMIC> sub(const index_t rs,const index_t cs) 1011 { 1012 const vector_length_t nb_rows = rows() - rs; 1013 const vector_length_t nb_cols = columns() - cs; 1014 1015 return(MatrixView<P,DYNAMIC>(Vector_Base<P>::ptr(rs*stride()+cs),nb_rows,nb_cols,stride())); 1016 } 1017 1018 /** @brief Create a constant matrix view 1019 * @param rs start row 1020 * @param cs start column 1021 * @return matrix view 1022 * 1023 */ subarm_cmsis_dsp::Matrix1024 const MatrixView<P,DYNAMIC> sub(const index_t rs,const index_t cs) const 1025 { 1026 const vector_length_t nb_rows = rows() - rs; 1027 const vector_length_t nb_cols = columns() - cs; 1028 1029 return(MatrixView<P,DYNAMIC>(Vector_Base<P>::ptr(rs*stride()+cs),nb_rows,nb_cols,stride())); 1030 } 1031 1032 /** @brief Create a matrix view 1033 * @param rs Row slice (start and end row) 1034 * @param cs start column 1035 * @return matrix view 1036 * 1037 */ subarm_cmsis_dsp::Matrix1038 MatrixView<P,DYNAMIC> sub(const Slice &rs,const index_t cs) 1039 { 1040 const vector_length_t nb_rows = rs.stop - rs.start; 1041 const vector_length_t nb_cols = columns() - cs; 1042 1043 return(MatrixView<P,DYNAMIC>(Vector_Base<P>::ptr(rs.start*stride()+cs),nb_rows,nb_cols,stride())); 1044 } 1045 1046 /** @brief Create a constant matrix view 1047 * @param rs Row slice (start and end row) 1048 * @param cs start column 1049 * @return matrix view 1050 * 1051 */ subarm_cmsis_dsp::Matrix1052 const MatrixView<P,DYNAMIC> sub(const Slice &rs,const index_t cs) const 1053 { 1054 const vector_length_t nb_rows = rs.stop - rs.start; 1055 const vector_length_t nb_cols = columns() - cs; 1056 1057 return(MatrixView<P,DYNAMIC>(Vector_Base<P>::ptr(rs.start*stride()+cs),nb_rows,nb_cols,stride())); 1058 } 1059 1060 /** @brief Create a matrix view 1061 * @param rs Row start index 1062 * @param cs Column slice 1063 * @return matrix view 1064 * 1065 */ subarm_cmsis_dsp::Matrix1066 MatrixView<P,DYNAMIC> sub(const index_t rs,const Slice &cs) 1067 { 1068 const vector_length_t nb_rows = rows() - rs; 1069 const vector_length_t nb_cols = cs.stop - cs.start; 1070 1071 return(MatrixView<P,DYNAMIC>(Vector_Base<P>::ptr(rs*stride()+cs.start),nb_rows,nb_cols,stride())); 1072 } 1073 1074 1075 /** @brief Create a constant matrix view 1076 * @param rs Row start index 1077 * @param cs Column slice 1078 * @return matrix view 1079 * 1080 */ subarm_cmsis_dsp::Matrix1081 const MatrixView<P,DYNAMIC> sub(const index_t rs,const Slice &cs) const 1082 { 1083 const vector_length_t nb_rows = rows() - rs; 1084 const vector_length_t nb_cols = cs.stop - cs.start; 1085 1086 return(MatrixView<P,DYNAMIC>(Vector_Base<P>::ptr(rs*stride()+cs.start),nb_rows,nb_cols,stride())); 1087 } 1088 1089 /** @brief Create a matrix view 1090 * @param rs Row slice 1091 * @param cs Column slice 1092 * @return matrix view 1093 * 1094 */ subarm_cmsis_dsp::Matrix1095 MatrixView<P,DYNAMIC> sub(const Slice& rs,const Slice& cs) 1096 { 1097 const vector_length_t nb_rows = rs.stop - rs.start; 1098 const vector_length_t nb_cols = cs.stop - cs.start; 1099 1100 return(MatrixView<P,DYNAMIC>(Vector_Base<P>::ptr(rs.start*stride()+cs.start),nb_rows,nb_cols,stride())); 1101 } 1102 1103 /** @brief Create a constant matrix view 1104 * @param rs Row slice 1105 * @param cs Column slice 1106 * @return matrix view 1107 * 1108 */ subarm_cmsis_dsp::Matrix1109 const MatrixView<P,DYNAMIC> sub(const Slice& rs,const Slice& cs) const 1110 { 1111 const vector_length_t nb_rows = rs.stop - rs.start; 1112 const vector_length_t nb_cols = cs.stop - cs.start; 1113 1114 return(MatrixView<P,DYNAMIC>(Vector_Base<P>::ptr(rs.start*stride()+cs.start),nb_rows,nb_cols,stride())); 1115 } 1116 1117 /** @brief Create a matrix view 1118 * @param rs Row start 1119 * @param re Row end 1120 * @param cs Column start 1121 * @param ce Column end 1122 * @return matrix view 1123 * 1124 */ subarm_cmsis_dsp::Matrix1125 MatrixView<P,DYNAMIC> sub(const index_t rs, 1126 const index_t re, 1127 const index_t cs, 1128 const index_t ce) 1129 { 1130 const vector_length_t nb_rows = re - rs; 1131 const vector_length_t nb_cols = ce - cs; 1132 1133 return(MatrixView<P,DYNAMIC>(Vector_Base<P>::ptr(rs*stride()+cs),nb_rows,nb_cols,stride())); 1134 } 1135 1136 /** @brief Create a constant matrix view 1137 * @param rs Row start 1138 * @param re Row end 1139 * @param cs Column start 1140 * @param ce Column end 1141 * @return matrix view 1142 * 1143 */ subarm_cmsis_dsp::Matrix1144 const MatrixView<P,DYNAMIC> sub(const index_t rs, 1145 const index_t re, 1146 const index_t cs, 1147 const index_t ce) const 1148 { 1149 const vector_length_t nb_rows = re - rs; 1150 const vector_length_t nb_cols = ce - cs; 1151 1152 return(MatrixView<P,DYNAMIC>(Vector_Base<P>::ptr(rs*stride()+cs),nb_rows,nb_cols,stride())); 1153 } 1154 1155 protected: 1156 vector_length_t rows_,columns_; 1157 }; 1158 1159 1160 /*! @} */ 1161 }