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