1 /* ----------------------------------------------------------------------
2 * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
3 *
4 * $Date:         17. January 2013
5 * $Revision:     V1.4.0
6 *
7 * Project:       CMSIS DSP Library
8 * Title:         arm_matrix_example_f32.c
9 *
10 * Description:   Example code demonstrating least square fit to data
11 *                using matrix functions
12 *
13 * Target Processor: Cortex-M4/Cortex-M3
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 *   - Redistributions of source code must retain the above copyright
19 *     notice, this list of conditions and the following disclaimer.
20 *   - Redistributions in binary form must reproduce the above copyright
21 *     notice, this list of conditions and the following disclaimer in
22 *     the documentation and/or other materials provided with the
23 *     distribution.
24 *   - Neither the name of ARM LIMITED nor the names of its contributors
25 *     may be used to endorse or promote products derived from this
26 *     software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
31 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
32 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
33 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
34 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
35 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
36 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
38 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39 * POSSIBILITY OF SUCH DAMAGE.
40  * -------------------------------------------------------------------- */
41 
42 /**
43  * @addtogroup groupExamples
44  * @{
45  *
46  * @defgroup MatrixExample Matrix Example
47  *
48  * \par Description:
49  * \par
50  * Demonstrates the use of Matrix Transpose, Matrix Muliplication, and Matrix Inverse
51  * functions to apply least squares fitting to input data. Least squares fitting is
52  * the procedure for finding the best-fitting curve that minimizes the sum of the
53  * squares of the offsets (least square error) from a given set of data.
54  *
55  * \par Algorithm:
56  * \par
57  * The linear combination of parameters considered is as follows:
58  * \par
59  * <code>A * X = B</code>, where \c X is the unknown value and can be estimated
60  * from \c A & \c B.
61  * \par
62  * The least squares estimate \c X is given by the following equation:
63  * \par
64  * <code>X = Inverse(A<sup>T</sup> * A) *  A<sup>T</sup> * B</code>
65  *
66  * \par Block Diagram:
67  * \par
68  *
69  * \par Variables Description:
70  * \par
71  * \li \c A_f32 input matrix in the linear combination equation
72  * \li \c B_f32 output matrix in the linear combination equation
73  * \li \c X_f32 unknown matrix estimated using \c A_f32 & \c B_f32 matrices
74  *
75  * \par CMSIS DSP Software Library Functions Used:
76  * \par
77  * - arm_mat_init_f32()
78  * - arm_mat_trans_f32()
79  * - arm_mat_mult_f32()
80  * - arm_mat_inverse_f32()
81  *
82  * <b> Refer  </b>
83  * \link arm_matrix_example_f32.c \endlink
84  *
85  * \example arm_matrix_example_f32.c
86  *
87  * @} */
88 
89 #include "arm_math.h"
90 #include "math_helper.h"
91 
92 #if defined(SEMIHOSTING)
93 #include <stdio.h>
94 #endif
95 
96 #define SNR_THRESHOLD   77
97 
98 /* --------------------------------------------------------------------------------
99 * Test input data(Cycles) taken from FIR Q15 module for differant cases of blockSize
100 * and tapSize
101 * --------------------------------------------------------------------------------- */
102 
103 const float32_t B_f32[4] =
104 {
105   782.0, 7577.0, 470.0, 4505.0
106 };
107 
108 /* --------------------------------------------------------------------------------
109 * Formula to fit is  C1 + C2 * numTaps + C3 * blockSize + C4 * numTaps * blockSize
110 * -------------------------------------------------------------------------------- */
111 
112 const float32_t A_f32[16] =
113 {
114   /* Const,   numTaps,   blockSize,   numTaps*blockSize */
115   1.0,     32.0,      4.0,     128.0,
116   1.0,     32.0,     64.0,    2048.0,
117   1.0,     16.0,      4.0,      64.0,
118   1.0,     16.0,     64.0,    1024.0,
119 };
120 
121 
122 /* ----------------------------------------------------------------------
123 * Temporary buffers  for storing intermediate values
124 * ------------------------------------------------------------------- */
125 /* Transpose of A Buffer */
126 float32_t AT_f32[16];
127 /* (Transpose of A * A) Buffer */
128 float32_t ATMA_f32[16];
129 /* Inverse(Transpose of A * A)  Buffer */
130 float32_t ATMAI_f32[16];
131 /* Test Output Buffer */
132 float32_t X_f32[4];
133 
134 /* ----------------------------------------------------------------------
135 * Reference ouput buffer C1, C2, C3 and C4 taken from MATLAB
136 * ------------------------------------------------------------------- */
137 const float32_t xRef_f32[4] = {73.0, 8.0, 21.25, 2.875};
138 
139 float32_t snr;
140 
141 
142 /* ----------------------------------------------------------------------
143 * Max magnitude FFT Bin test
144 * ------------------------------------------------------------------- */
145 
main(void)146 int32_t main(void)
147 {
148 
149   arm_matrix_instance_f32 A;      /* Matrix A Instance */
150   arm_matrix_instance_f32 AT;     /* Matrix AT(A transpose) instance */
151   arm_matrix_instance_f32 ATMA;   /* Matrix ATMA( AT multiply with A) instance */
152   arm_matrix_instance_f32 ATMAI;  /* Matrix ATMAI(Inverse of ATMA) instance */
153   arm_matrix_instance_f32 B;      /* Matrix B instance */
154   arm_matrix_instance_f32 X;      /* Matrix X(Unknown Matrix) instance */
155 
156   uint32_t srcRows, srcColumns;  /* Temporary variables */
157   arm_status status;
158 
159   /* Initialise A Matrix Instance with numRows, numCols and data array(A_f32) */
160   srcRows = 4;
161   srcColumns = 4;
162   arm_mat_init_f32(&A, srcRows, srcColumns, (float32_t *)A_f32);
163 
164   /* Initialise Matrix Instance AT with numRows, numCols and data array(AT_f32) */
165   srcRows = 4;
166   srcColumns = 4;
167   arm_mat_init_f32(&AT, srcRows, srcColumns, AT_f32);
168 
169   /* calculation of A transpose */
170   status = arm_mat_trans_f32(&A, &AT);
171 
172 
173   /* Initialise ATMA Matrix Instance with numRows, numCols and data array(ATMA_f32) */
174   srcRows = 4;
175   srcColumns = 4;
176   arm_mat_init_f32(&ATMA, srcRows, srcColumns, ATMA_f32);
177 
178   /* calculation of AT Multiply with A */
179   status = arm_mat_mult_f32(&AT, &A, &ATMA);
180 
181   /* Initialise ATMAI Matrix Instance with numRows, numCols and data array(ATMAI_f32) */
182   srcRows = 4;
183   srcColumns = 4;
184   arm_mat_init_f32(&ATMAI, srcRows, srcColumns, ATMAI_f32);
185 
186   /* calculation of Inverse((Transpose(A) * A) */
187   status = arm_mat_inverse_f32(&ATMA, &ATMAI);
188 
189   /* calculation of (Inverse((Transpose(A) * A)) *  Transpose(A)) */
190   status = arm_mat_mult_f32(&ATMAI, &AT, &ATMA);
191 
192   /* Initialise B Matrix Instance with numRows, numCols and data array(B_f32) */
193   srcRows = 4;
194   srcColumns = 1;
195   arm_mat_init_f32(&B, srcRows, srcColumns, (float32_t *)B_f32);
196 
197   /* Initialise X Matrix Instance with numRows, numCols and data array(X_f32) */
198   srcRows = 4;
199   srcColumns = 1;
200   arm_mat_init_f32(&X, srcRows, srcColumns, X_f32);
201 
202   /* calculation ((Inverse((Transpose(A) * A)) *  Transpose(A)) * B) */
203   status = arm_mat_mult_f32(&ATMA, &B, &X);
204 
205   /* Comparison of reference with test output */
206   snr = arm_snr_f32((float32_t *)xRef_f32, X_f32, 4);
207 
208   /*------------------------------------------------------------------------------
209   *            Initialise status depending on SNR calculations
210   *------------------------------------------------------------------------------*/
211   status = (snr < SNR_THRESHOLD) ? ARM_MATH_TEST_FAILURE : ARM_MATH_SUCCESS;
212 
213   if (status != ARM_MATH_SUCCESS)
214   {
215 #if defined (SEMIHOSTING)
216     printf("FAILURE\n");
217 #else
218     while (1);                             /* main function does not return */
219 #endif
220   }
221   else
222   {
223 #if defined (SEMIHOSTING)
224     printf("SUCCESS\n");
225 #else
226     while (1);                             /* main function does not return */
227 #endif
228   }
229 
230 }
231 
232  /** \endlink */
233