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 }