00001 /* ---------------------------------------------------------------------- 00002 * Copyright (C) 2011 ARM Limited. All rights reserved. 00003 * 00004 * $Date: 15. December 2011 00005 * $Revision: V2.0.0 00006 * 00007 * Project: Cortex-R DSP Library 00008 * Title: arm_mat_inverse_f32.c 00009 * 00010 * Description: Floating-point matrix inverse. 00011 * 00012 * Target Processor: Cortex-R4/R5 00013 * 00014 * Version 1.0.0 2011/03/08 00015 * Alpha release. 00016 * 00017 * Version 1.0.1 2011/09/30 00018 * Beta release. 00019 * 00020 * Version 2.0.0 2011/12/15 00021 * Final release. 00022 * 00023 * -------------------------------------------------------------------- */ 00024 #include "arm_math.h" 00025 00068 arm_status arm_mat_inverse_f32( 00069 const arm_matrix_instance_f32 * pSrc, 00070 arm_matrix_instance_f32 * pDst) 00071 { 00072 float32_t *pIn = pSrc->pData; /* input data matrix pointer */ 00073 float32_t *pOut = pDst->pData; /* output data matrix pointer */ 00074 float32_t *pInT1, *pInT2; /* Temporary input data matrix pointer */ 00075 float32_t *pInT3, *pInT4; /* Temporary output data matrix pointer */ 00076 float32_t *pPivotRowIn, *pPRT_in, *pPivotRowDst, *pPRT_pDst; /* Temporary input and output data matrix pointer */ 00077 uint32_t numRows = pSrc->numRows; /* Number of rows in the matrix */ 00078 uint32_t numCols = pSrc->numCols; /* Number of Cols in the matrix */ 00079 float32_t Xchg, in = 0.0f, in1; /* Temporary input values */ 00080 uint32_t i, rowCnt, flag = 0u, j, loopCnt, k, l; /* loop counters */ 00081 arm_status status; /* status of matrix inverse */ 00082 00083 #ifdef ARM_MATH_MATRIX_CHECK 00084 /* Check for matrix mismatch condition */ 00085 if((pSrc->numRows != pSrc->numCols) || (pDst->numRows != pDst->numCols) 00086 || (pSrc->numRows != pDst->numRows)) 00087 { 00088 /* Set status as ARM_MATH_SIZE_MISMATCH */ 00089 status = ARM_MATH_SIZE_MISMATCH; 00090 } 00091 else 00092 #endif 00093 { 00094 00095 /*-------------------------------------------------------------------------------------------------------------- 00096 * Matrix Inverse can be solved using elementary row operations. 00097 * 00098 * Gauss-Jordan Method: 00099 * 00100 * 1. First combine the identity matrix and the input matrix separated by a bar to form an 00101 * augmented matrix as follows: 00102 * _ _ _ _ 00103 * | a11 a12 | 1 0 | | X11 X12 | 00104 * | | | = | | 00105 * |_ a21 a22 | 0 1 _| |_ X21 X21 _| 00106 * 00107 * 2. In our implementation, pDst Matrix is used as identity matrix. 00108 * 00109 * 3. Begin with the first row. Let i = 1. 00110 * 00111 * 4. Check to see if the pivot for row i is zero. 00112 * The pivot is the element of the main diagonal that is on the current row. 00113 * For instance, if working with row i, then the pivot element is aii. 00114 * If the pivot is zero, exchange that row with a row below it that does not 00115 * contain a zero in column i. If this is not possible, then an inverse 00116 * to that matrix does not exist. 00117 * 00118 * 5. Divide every element of row i by the pivot. 00119 * 00120 * 6. For every row below and row i, replace that row with the sum of that row and 00121 * a multiple of row i so that each new element in column i below row i is zero. 00122 * 00123 * 7. Move to the next row and column and repeat steps 2 through 5 until you have zeros 00124 * for every element below and above the main diagonal. 00125 * 00126 * 8. Now an identical matrix is formed to the left of the bar(input matrix, pSrc). 00127 * Therefore, the matrix to the right of the bar is our solution(pDst matrix, pDst). 00128 *----------------------------------------------------------------------------------------------------------------*/ 00129 00130 /* Working pointer for destination matrix */ 00131 pInT2 = pOut; 00132 00133 /* Loop over the number of rows */ 00134 rowCnt = numRows; 00135 00136 /* Making the destination matrix as identity matrix */ 00137 while(rowCnt > 0u) 00138 { 00139 /* Writing all zeroes in lower triangle of the destination matrix */ 00140 j = numRows - rowCnt; 00141 while(j > 0u) 00142 { 00143 *pInT2++ = 0.0f; 00144 j--; 00145 } 00146 00147 /* Writing all ones in the diagonal of the destination matrix */ 00148 *pInT2++ = 1.0f; 00149 00150 /* Writing all zeroes in upper triangle of the destination matrix */ 00151 j = rowCnt - 1u; 00152 while(j > 0u) 00153 { 00154 *pInT2++ = 0.0f; 00155 j--; 00156 } 00157 00158 /* Decrement the loop counter */ 00159 rowCnt--; 00160 } 00161 00162 /* Loop over the number of columns of the input matrix. 00163 All the elements in each column are processed by the row operations */ 00164 loopCnt = numCols; 00165 00166 /* Index modifier to navigate through the columns */ 00167 l = 0u; 00168 00169 while(loopCnt > 0u) 00170 { 00171 /* Check if the pivot element is zero.. 00172 * If it is zero then interchange the row with non zero row below. 00173 * If there is no non zero element to replace in the rows below, 00174 * then the matrix is Singular. */ 00175 00176 /* Working pointer for the input matrix that points 00177 * to the pivot element of the particular row */ 00178 pInT1 = pIn + (l * numCols); 00179 00180 /* Working pointer for the destination matrix that points 00181 * to the pivot element of the particular row */ 00182 pInT3 = pOut + (l * numCols); 00183 00184 /* Temporary variable to hold the pivot value */ 00185 in = *pInT1; 00186 00187 /* Destination pointer modifier */ 00188 k = 1u; 00189 00190 /* Check if the pivot element is zero */ 00191 if(*pInT1 == 0.0f) 00192 { 00193 /* Loop over the number rows present below */ 00194 i = numRows - (l + 1u); 00195 00196 while(i > 0u) 00197 { 00198 /* Update the input and destination pointers */ 00199 pInT2 = pInT1 + (numCols * l); 00200 pInT4 = pInT3 + (numCols * k); 00201 00202 /* Check if there is a non zero pivot element to 00203 * replace in the rows below */ 00204 if(*pInT2 != 0.0f) 00205 { 00206 /* Loop over number of columns 00207 * to the right of the pilot element */ 00208 j = numCols - l; 00209 00210 while(j > 0u) 00211 { 00212 /* Exchange the row elements of the input matrix */ 00213 Xchg = *pInT2; 00214 *pInT2++ = *pInT1; 00215 *pInT1++ = Xchg; 00216 00217 /* Decrement the loop counter */ 00218 j--; 00219 } 00220 00221 /* Loop over number of columns of the destination matrix */ 00222 j = numCols; 00223 00224 while(j > 0u) 00225 { 00226 /* Exchange the row elements of the destination matrix */ 00227 Xchg = *pInT4; 00228 *pInT4++ = *pInT3; 00229 *pInT3++ = Xchg; 00230 00231 /* Decrement the loop counter */ 00232 j--; 00233 } 00234 00235 /* Flag to indicate whether exchange is done or not */ 00236 flag = 1u; 00237 00238 /* Break after exchange is done */ 00239 break; 00240 } 00241 00242 /* Update the destination pointer modifier */ 00243 k++; 00244 00245 /* Decrement the loop counter */ 00246 i--; 00247 } 00248 } 00249 00250 /* Update the status if the matrix is singular */ 00251 if((flag != 1u) && (in == 0.0f)) 00252 { 00253 status = ARM_MATH_SINGULAR; 00254 00255 break; 00256 } 00257 00258 /* Points to the pivot row of input and destination matrices */ 00259 pPivotRowIn = pIn + (l * numCols); 00260 pPivotRowDst = pOut + (l * numCols); 00261 00262 /* Temporary pointers to the pivot row pointers */ 00263 pInT1 = pPivotRowIn; 00264 pInT2 = pPivotRowDst; 00265 00266 /* Pivot element of the row */ 00267 in = *(pIn + (l * numCols)); 00268 00269 /* Loop over number of columns 00270 * to the right of the pilot element */ 00271 j = (numCols - l); 00272 00273 while(j > 0u) 00274 { 00275 /* Divide each element of the row of the input matrix 00276 * by the pivot element */ 00277 in1 = *pInT1; 00278 *pInT1++ = in1 / in; 00279 00280 /* Decrement the loop counter */ 00281 j--; 00282 } 00283 00284 /* Loop over number of columns of the destination matrix */ 00285 j = numCols; 00286 00287 while(j > 0u) 00288 { 00289 /* Divide each element of the row of the destination matrix 00290 * by the pivot element */ 00291 in1 = *pInT2; 00292 *pInT2++ = in1 / in; 00293 00294 /* Decrement the loop counter */ 00295 j--; 00296 } 00297 00298 /* Replace the rows with the sum of that row and a multiple of row i 00299 * so that each new element in column i above row i is zero.*/ 00300 00301 /* Temporary pointers for input and destination matrices */ 00302 pInT1 = pIn; 00303 pInT2 = pOut; 00304 00305 /* index used to check for pivot element */ 00306 i = 0u; 00307 00308 /* Loop over number of rows */ 00309 /* to be replaced by the sum of that row and a multiple of row i */ 00310 k = numRows; 00311 00312 while(k > 0u) 00313 { 00314 /* Check for the pivot element */ 00315 if(i == l) 00316 { 00317 /* If the processing element is the pivot element, 00318 only the columns to the right are to be processed */ 00319 pInT1 += numCols - l; 00320 00321 pInT2 += numCols; 00322 } 00323 else 00324 { 00325 /* Element of the reference row */ 00326 in = *pInT1; 00327 00328 /* Working pointers for input and destination pivot rows */ 00329 pPRT_in = pPivotRowIn; 00330 pPRT_pDst = pPivotRowDst; 00331 00332 /* Loop over the number of columns to the right of the pivot element, 00333 to replace the elements in the input matrix */ 00334 j = (numCols - l); 00335 00336 while(j > 0u) 00337 { 00338 /* Replace the element by the sum of that row 00339 and a multiple of the reference row */ 00340 in1 = *pInT1; 00341 *pInT1++ = in1 - (in * *pPRT_in++); 00342 00343 /* Decrement the loop counter */ 00344 j--; 00345 } 00346 00347 /* Loop over the number of columns to 00348 replace the elements in the destination matrix */ 00349 j = numCols; 00350 00351 while(j > 0u) 00352 { 00353 /* Replace the element by the sum of that row 00354 and a multiple of the reference row */ 00355 in1 = *pInT2; 00356 *pInT2++ = in1 - (in * *pPRT_pDst++); 00357 00358 /* Decrement the loop counter */ 00359 j--; 00360 } 00361 00362 } 00363 00364 /* Increment the temporary input pointer */ 00365 pInT1 = pInT1 + l; 00366 00367 /* Decrement the loop counter */ 00368 k--; 00369 00370 /* Increment the pivot index */ 00371 i++; 00372 } 00373 00374 /* Increment the input pointer */ 00375 pIn++; 00376 00377 /* Decrement the loop counter */ 00378 loopCnt--; 00379 00380 /* Increment the index modifier */ 00381 l++; 00382 } 00383 00384 /* Set status as ARM_MATH_SUCCESS */ 00385 status = ARM_MATH_SUCCESS; 00386 00387 if((flag != 1u) && (in == 0.0f)) 00388 { 00389 status = ARM_MATH_SINGULAR; 00390 } 00391 00392 } 00393 00394 /* Return to application */ 00395 return (status); 00396 } 00397