1 // -*- C++ -*-
2 /** @file */
3 #pragma once
4 
5 /** \defgroup DSPPP C++ extension
6  *  C++ template extension to CMSIS-DSP. It is not yet part of
7  *  the pack but the headers can be found on the
8  *  [CMSIS-DSP github](https://github.com/ARM-software/CMSIS-DSP/tree/main/dsppp/Include)
9  *  The principles are described in this @ref dsppp_main "page"
10  */
11 
12 
13 /**
14 In this file we have kernels that are written in an
15 architecture independant way (using operators of the library)
16 
17 */
18 
19 namespace arm_cmsis_dsp {
20 
21 /** \addtogroup ALGO Architecture independent algorithms
22  *  \ingroup DSPPP
23  *  Algorithms written in an architecture independent way
24  */
25 
26 /*
27 
28 Matrix transpose
29 
30 */
31 
32 
33 
34  /** @ingroup ALGO
35   *  @brief Transpose a matrix.
36   *
37   * @tparam MA Any matrix type
38   * @tparam MB Any matrix type
39   * @param dst Destination matrix.
40   * @param src Source matrix.
41   *
42   */
43 template<typename MA,
44          typename MB,
45          typename std::enable_if<
46          HasMatrixIndexing<MA>::value &&
47          HasMatrixIndexing<MB>::value /*&&
48          SameElementType<MA,Q15>::value*/,bool>::type = true>
transposeTo(MA & dst,const MB & src)49 inline void transposeTo(MA &dst,
50                         const MB& src)
51 {
52   _arm_mat_trans(src,dst,CURRENT_ARCH);
53 }
54 
55 
56 
57 /*
58 
59 Init a diagonal matrix (0 outside of diagonal)
60 
61 */
62 template<typename P,int R,
63          template<int> typename A,
64          typename VB,
65 typename std::enable_if<IsVector<VB>::value &&
66          SameElementType<VB,P>::value,bool>::type = true>
_diagonal(Matrix<P,R,R,A> & v,const VB & other,const vector_length_t rows)67 inline void _diagonal(Matrix<P,R,R,A> &v,
68                       const VB& other,
69                       const vector_length_t rows)
70 {
71   UNROLL_LOOP
72   for(index_t r=0;r < rows ; r++)
73   {
74      v.row(r) = P{};
75      v(r,r) = other[r];
76   }
77 }
78 
79 
80 /*
81 
82 
83 Fill diagonal of an existing matrix
84 
85 */
86 template<typename P,int R,
87          template<int> typename A,
88          typename VB,
89 typename std::enable_if<IsVector<VB>::value &&
90          SameElementType<VB,P>::value,bool>::type = true>
_fill_diagonal(Matrix<P,R,R,A> & v,const VB & other,const vector_length_t rows)91 inline void _fill_diagonal(Matrix<P,R,R,A> &v,
92                            const VB& other,
93                            const vector_length_t rows)
94 {
95   for(index_t r=0;r < rows ; r++)
96   {
97      v(r,r) = other[r];
98   }
99 }
100 
101 template<typename P,int R,
102          template<int> typename A>
_identity(Matrix<P,R,R,A> & v,const vector_length_t rows)103 inline void _identity(Matrix<P,R,R,A> &v,
104                       const vector_length_t rows)
105 {
106   UNROLL_LOOP
107   for(index_t r=0;r < rows ; r++)
108   {
109      v.row(r) = P{};
110      v(r,r) = number_traits<P>::one();
111   }
112 }
113 
114 
115 /**
116  * @ingroup ALGO
117  * @brief Matrix x Vector product.
118  *
119  * @tparam M Any matrix type
120  * @tparam V Any vector type
121  * @param m matrix.
122  * @param v vector.
123  * @return The matrix x vector product
124  *
125  */
126 template<typename M,
127          typename V,
128          typename std::enable_if<CompatibleStaticMatVecProduct<M,V>::value,bool>::type = true>
dot(const M & m,const V & v)129 inline typename OutputVector<M,V>::type dot(const M&m,const V&v)
130 {
131    typename OutputVector<M,V>::type res;
132    _dot_m_v(res,m,v,CURRENT_ARCH);
133    return(res);
134 }
135 
136 template<typename M,
137          typename V,
138          typename std::enable_if<CompatibleDynamicMatVecProduct<M,V>::value,bool>::type = true>
dot(const M & m,const V & v)139 inline typename OutputVector<M,V>::type dot(const M&m,const V&v)
140 {
141    typename OutputVector<M,V>::type res(m.rows());
142    _dot_m_v(res,m,v,CURRENT_ARCH);
143    return(res);
144 }
145 
146 template<typename M,
147          typename V,
148          typename RES,
149          typename std::enable_if<CompatibleDynamicMatVecProduct<M,V>::value,bool>::type = true>
dot(RES && res,const M & m,const V & v)150 inline void dot(RES && res,const M&m,const V&v)
151 {
152    //typename OutputVector<M,V>::type res(m.rows());
153    _dot_m_v(res,m,v,CURRENT_ARCH);
154 }
155 
156 
157  /** @ingroup ALGO
158   *  @brief Matrix x Matrix product.
159   *
160   * @tparam MA Any matrix type
161   * @tparam MB Any matrix type
162   * @param ma Matrix.
163   * @param mb Matrix.
164   * @return ma x mb matrix product
165   *
166   */
167 template<typename MA,
168          typename MB,
169          typename std::enable_if<CompatibleStaticMatMatProduct<MA,MB>::value &&
170                                  number_traits<typename traits<MA>::Scalar>::is_fixed,bool>::type = true>
dot(const MA & ma,const MB & mb)171 inline typename OutputMatrix<MA,MB>::type dot(const MA&ma,const MB&mb)
172 {
173 
174    typename OutputMatrix<MA,MB>::type res;
175    auto BT = mb.transpose();
176 
177    //using M = MatMult<typename ElementType<MA>::type,MA,MB,typename OutputMatrix<MA,MB>::type,decltype(BT)>;
178    _dot_m_m(ma,mb,res,BT,CURRENT_ARCH);
179    return(res);
180 }
181 
182 template<typename MA,
183          typename MB,
184          typename std::enable_if<CompatibleStaticMatMatProduct<MA,MB>::value &&
185                                  number_traits<typename traits<MA>::Scalar>::is_float,bool>::type = true>
dot(const MA & ma,const MB & mb)186 inline typename OutputMatrix<MA,MB>::type dot(const MA&ma,const MB&mb)
187 {
188 
189    typename OutputMatrix<MA,MB>::type res;
190 
191    //using M = MatMult<typename ElementType<MA>::type,MA,MB,typename OutputMatrix<MA,MB>::type,decltype(BT)>;
192    _dot_m_m(ma,mb,res,CURRENT_ARCH);
193    return(res);
194 }
195 
196 template<typename MA,
197          typename MB,
198          typename std::enable_if<CompatibleDynamicMatMatProduct<MA,MB>::value &&
199                                  number_traits<typename traits<MA>::Scalar>::is_fixed,bool>::type = true>
dot(const MA & ma,const MB & mb)200 inline typename OutputMatrix<MA,MB>::type dot(const MA&ma,const MB&mb)
201 {
202    typename OutputMatrix<MA,MB>::type res(ma.rows(),mb.columns());
203    auto BT = mb.transpose();
204 
205    //using M = MatMult<typename ElementType<MA>::type,MA,MB,typename OutputMatrix<MA,MB>::type,decltype(BT)>;
206    _dot_m_m(ma,mb,res,BT,CURRENT_ARCH);
207    return(res);
208 }
209 
210 template<typename MA,
211          typename MB,
212          typename std::enable_if<CompatibleDynamicMatMatProduct<MA,MB>::value &&
213                                  number_traits<typename traits<MA>::Scalar>::is_float,bool>::type = true>
dot(const MA & ma,const MB & mb)214 inline typename OutputMatrix<MA,MB>::type dot(const MA&ma,const MB&mb)
215 {
216    typename OutputMatrix<MA,MB>::type res(ma.rows(),mb.columns());
217 
218    //using M = MatMult<typename ElementType<MA>::type,MA,MB,typename OutputMatrix<MA,MB>::type,decltype(BT)>;
219    _dot_m_m(ma,mb,res,CURRENT_ARCH);
220    return(res);
221 }
222 
223  /** @ingroup ALGO
224   *  @brief Matrix x Matrix product
225   *
226   * @tparam MA Any matrix type
227   * @tparam MB Any matrix type
228   * @tparam RES Any matrix type
229   * @param res Output matrix. Result of ma x mb is written to this argument
230   * @param ma Matrix.
231   * @param mb Matrix.
232   *
233   * Used in dynamic mode (dimension of matrix not know at build time)
234   * to avoid a memory allocation if the result matrix is already available
235   * (Enable to reuse the same matrix storage for the result in some algorithms)
236   *
237   */
238 template<typename MA,
239          typename MB,
240          typename RES,
241          typename std::enable_if<CompatibleDynamicMatMatProduct<MA,MB>::value &&
242                                  number_traits<typename traits<MA>::Scalar>::is_float,bool>::type = true>
dot(RES && res,const MA & ma,const MB & mb)243 inline void dot(RES &&res,const MA&ma,const MB&mb)
244 {
245    //typename OutputMatrix<MA,MB>::type res(ma.rows(),mb.columns());
246 
247    //using M = MatMult<typename ElementType<MA>::type,MA,MB,typename OutputMatrix<MA,MB>::type,decltype(BT)>;
248    _dot_m_m(ma,mb,std::forward<RES>(res),CURRENT_ARCH);
249 }
250 
251 template<typename MA,
252          typename MB,
253          typename TMP,
254          typename std::enable_if<CompatibleDynamicMatMatProductDynamicStride<MA,MB>::value &&
255                                  number_traits<typename traits<MA>::Scalar>::is_float,bool>::type = true>
dot(const MA & ma,const MB & mb)256 inline typename OutputMatrix<MA,MB>::type dot(const MA&ma,const MB&mb)
257 {
258    typename OutputMatrix<MA,MB>::type res(ma.rows(),mb.columns());
259 
260    //using M = MatMult<typename ElementType<MA>::type,MA,MB,typename OutputMatrix<MA,MB>::type,decltype(mbt)>;
261    _dot_m_m(ma,mb,res,CURRENT_ARCH);
262    return(res);
263 }
264 
265 template<typename MA,
266          typename MB,
267          typename TMP,
268          typename std::enable_if<CompatibleDynamicMatMatProductDynamicStride<MA,MB>::value &&
269                                  number_traits<typename traits<MA>::Scalar>::is_fixed,bool>::type = true>
dot(const MA & ma,const MB & mb,const TMP & mbt)270 inline typename OutputMatrix<MA,MB>::type dot(const MA&ma,const MB&mb,const TMP &mbt)
271 {
272    typename OutputMatrix<MA,MB>::type res(ma.rows(),mb.columns());
273 
274    //using M = MatMult<typename ElementType<MA>::type,MA,MB,typename OutputMatrix<MA,MB>::type,decltype(mbt)>;
275    _dot_m_m(ma,mb,res,mbt,CURRENT_ARCH);
276    return(res);
277 }
278 
279 
280  /** @ingroup ALGO
281   *  @brief Create identity matrix
282   *
283   * @tparam P Datatype of matrix elements
284   * @param l Dimension of matrix (l x l)
285   * @return Identity matrix. It is a dynamic matrix (size not know at build time)
286   *
287   */
288 template<typename P>
mk_identity(const vector_length_t l)289 Matrix<P,DYNAMIC,DYNAMIC,TMP_ALLOC> mk_identity(const vector_length_t l)
290 {
291        Matrix<P,DYNAMIC,DYNAMIC,TMP_ALLOC> res(l,l);
292        _identity(res,l);
293        return(res);
294 };
295 
296 
297  /** @ingroup ALGO
298   *  @brief Create identity matrix
299   *
300   * @tparam P Datatype of matrix elements
301   * @tparam L Matrix dimension (L x L)
302   * @return Identity matrix. It is a static matrix : size known at build time.
303   *
304   */
305 template<typename P,int L>
mk_identity()306 Matrix<P,L,L,TMP_ALLOC> mk_identity()
307 {
308        Matrix<P,L,L,TMP_ALLOC> res;
309        _identity(res,L);
310        return(res);
311 };
312 
313 }
314