arm_mat_inverse_f32.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695
  1. /* ----------------------------------------------------------------------
  2. * Copyright (C) 2010-2014 ARM Limited. All rights reserved.
  3. *
  4. * $Date: 12. March 2014
  5. * $Revision: V1.4.4
  6. *
  7. * Project: CMSIS DSP Library
  8. * Title: arm_mat_inverse_f32.c
  9. *
  10. * Description: Floating-point matrix inverse.
  11. *
  12. * Target Processor: Cortex-M4/Cortex-M3/Cortex-M0
  13. *
  14. * Redistribution and use in source and binary forms, with or without
  15. * modification, are permitted provided that the following conditions
  16. * are met:
  17. * - Redistributions of source code must retain the above copyright
  18. * notice, this list of conditions and the following disclaimer.
  19. * - Redistributions in binary form must reproduce the above copyright
  20. * notice, this list of conditions and the following disclaimer in
  21. * the documentation and/or other materials provided with the
  22. * distribution.
  23. * - Neither the name of ARM LIMITED nor the names of its contributors
  24. * may be used to endorse or promote products derived from this
  25. * software without specific prior written permission.
  26. *
  27. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  28. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  29. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  30. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  31. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  32. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  33. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  34. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  35. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  36. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  37. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  38. * POSSIBILITY OF SUCH DAMAGE.
  39. * -------------------------------------------------------------------- */
  40. #include "arm_math.h"
  41. /**
  42. * @ingroup groupMatrix
  43. */
  44. /**
  45. * @defgroup MatrixInv Matrix Inverse
  46. *
  47. * Computes the inverse of a matrix.
  48. *
  49. * The inverse is defined only if the input matrix is square and non-singular (the determinant
  50. * is non-zero). The function checks that the input and output matrices are square and of the
  51. * same size.
  52. *
  53. * Matrix inversion is numerically sensitive and the CMSIS DSP library only supports matrix
  54. * inversion of floating-point matrices.
  55. *
  56. * \par Algorithm
  57. * The Gauss-Jordan method is used to find the inverse.
  58. * The algorithm performs a sequence of elementary row-operations until it
  59. * reduces the input matrix to an identity matrix. Applying the same sequence
  60. * of elementary row-operations to an identity matrix yields the inverse matrix.
  61. * If the input matrix is singular, then the algorithm terminates and returns error status
  62. * <code>ARM_MATH_SINGULAR</code>.
  63. * \image html MatrixInverse.gif "Matrix Inverse of a 3 x 3 matrix using Gauss-Jordan Method"
  64. */
  65. /**
  66. * @addtogroup MatrixInv
  67. * @{
  68. */
  69. /**
  70. * @brief Floating-point matrix inverse.
  71. * @param[in] *pSrc points to input matrix structure
  72. * @param[out] *pDst points to output matrix structure
  73. * @return The function returns
  74. * <code>ARM_MATH_SIZE_MISMATCH</code> if the input matrix is not square or if the size
  75. * of the output matrix does not match the size of the input matrix.
  76. * If the input matrix is found to be singular (non-invertible), then the function returns
  77. * <code>ARM_MATH_SINGULAR</code>. Otherwise, the function returns <code>ARM_MATH_SUCCESS</code>.
  78. */
  79. arm_status arm_mat_inverse_f32(
  80. const arm_matrix_instance_f32 * pSrc,
  81. arm_matrix_instance_f32 * pDst)
  82. {
  83. float32_t *pIn = pSrc->pData; /* input data matrix pointer */
  84. float32_t *pOut = pDst->pData; /* output data matrix pointer */
  85. float32_t *pInT1, *pInT2; /* Temporary input data matrix pointer */
  86. float32_t *pOutT1, *pOutT2; /* Temporary output data matrix pointer */
  87. float32_t *pPivotRowIn, *pPRT_in, *pPivotRowDst, *pPRT_pDst; /* Temporary input and output data matrix pointer */
  88. uint32_t numRows = pSrc->numRows; /* Number of rows in the matrix */
  89. uint32_t numCols = pSrc->numCols; /* Number of Cols in the matrix */
  90. #ifndef ARM_MATH_CM0_FAMILY
  91. float32_t maxC; /* maximum value in the column */
  92. /* Run the below code for Cortex-M4 and Cortex-M3 */
  93. float32_t Xchg, in = 0.0f, in1; /* Temporary input values */
  94. uint32_t i, rowCnt, flag = 0u, j, loopCnt, k, l; /* loop counters */
  95. arm_status status; /* status of matrix inverse */
  96. #ifdef ARM_MATH_MATRIX_CHECK
  97. /* Check for matrix mismatch condition */
  98. if((pSrc->numRows != pSrc->numCols) || (pDst->numRows != pDst->numCols)
  99. || (pSrc->numRows != pDst->numRows))
  100. {
  101. /* Set status as ARM_MATH_SIZE_MISMATCH */
  102. status = ARM_MATH_SIZE_MISMATCH;
  103. }
  104. else
  105. #endif /* #ifdef ARM_MATH_MATRIX_CHECK */
  106. {
  107. /*--------------------------------------------------------------------------------------------------------------
  108. * Matrix Inverse can be solved using elementary row operations.
  109. *
  110. * Gauss-Jordan Method:
  111. *
  112. * 1. First combine the identity matrix and the input matrix separated by a bar to form an
  113. * augmented matrix as follows:
  114. * _ _ _ _
  115. * | a11 a12 | 1 0 | | X11 X12 |
  116. * | | | = | |
  117. * |_ a21 a22 | 0 1 _| |_ X21 X21 _|
  118. *
  119. * 2. In our implementation, pDst Matrix is used as identity matrix.
  120. *
  121. * 3. Begin with the first row. Let i = 1.
  122. *
  123. * 4. Check to see if the pivot for column i is the greatest of the column.
  124. * The pivot is the element of the main diagonal that is on the current row.
  125. * For instance, if working with row i, then the pivot element is aii.
  126. * If the pivot is not the most significant of the columns, exchange that row with a row
  127. * below it that does contain the most significant value in column i. If the most
  128. * significant value of the column is zero, then an inverse to that matrix does not exist.
  129. * The most significant value of the column is the absolute maximum.
  130. *
  131. * 5. Divide every element of row i by the pivot.
  132. *
  133. * 6. For every row below and row i, replace that row with the sum of that row and
  134. * a multiple of row i so that each new element in column i below row i is zero.
  135. *
  136. * 7. Move to the next row and column and repeat steps 2 through 5 until you have zeros
  137. * for every element below and above the main diagonal.
  138. *
  139. * 8. Now an identical matrix is formed to the left of the bar(input matrix, pSrc).
  140. * Therefore, the matrix to the right of the bar is our solution(pDst matrix, pDst).
  141. *----------------------------------------------------------------------------------------------------------------*/
  142. /* Working pointer for destination matrix */
  143. pOutT1 = pOut;
  144. /* Loop over the number of rows */
  145. rowCnt = numRows;
  146. /* Making the destination matrix as identity matrix */
  147. while(rowCnt > 0u)
  148. {
  149. /* Writing all zeroes in lower triangle of the destination matrix */
  150. j = numRows - rowCnt;
  151. while(j > 0u)
  152. {
  153. *pOutT1++ = 0.0f;
  154. j--;
  155. }
  156. /* Writing all ones in the diagonal of the destination matrix */
  157. *pOutT1++ = 1.0f;
  158. /* Writing all zeroes in upper triangle of the destination matrix */
  159. j = rowCnt - 1u;
  160. while(j > 0u)
  161. {
  162. *pOutT1++ = 0.0f;
  163. j--;
  164. }
  165. /* Decrement the loop counter */
  166. rowCnt--;
  167. }
  168. /* Loop over the number of columns of the input matrix.
  169. All the elements in each column are processed by the row operations */
  170. loopCnt = numCols;
  171. /* Index modifier to navigate through the columns */
  172. l = 0u;
  173. while(loopCnt > 0u)
  174. {
  175. /* Check if the pivot element is zero..
  176. * If it is zero then interchange the row with non zero row below.
  177. * If there is no non zero element to replace in the rows below,
  178. * then the matrix is Singular. */
  179. /* Working pointer for the input matrix that points
  180. * to the pivot element of the particular row */
  181. pInT1 = pIn + (l * numCols);
  182. /* Working pointer for the destination matrix that points
  183. * to the pivot element of the particular row */
  184. pOutT1 = pOut + (l * numCols);
  185. /* Temporary variable to hold the pivot value */
  186. in = *pInT1;
  187. /* Grab the most significant value from column l */
  188. maxC = 0;
  189. for (i = l; i < numRows; i++)
  190. {
  191. maxC = *pInT1 > 0 ? (*pInT1 > maxC ? *pInT1 : maxC) : (-*pInT1 > maxC ? -*pInT1 : maxC);
  192. pInT1 += numCols;
  193. }
  194. /* Update the status if the matrix is singular */
  195. if(maxC == 0.0f)
  196. {
  197. return ARM_MATH_SINGULAR;
  198. }
  199. /* Restore pInT1 */
  200. pInT1 = pIn;
  201. /* Destination pointer modifier */
  202. k = 1u;
  203. /* Check if the pivot element is the most significant of the column */
  204. if( (in > 0.0f ? in : -in) != maxC)
  205. {
  206. /* Loop over the number rows present below */
  207. i = numRows - (l + 1u);
  208. while(i > 0u)
  209. {
  210. /* Update the input and destination pointers */
  211. pInT2 = pInT1 + (numCols * l);
  212. pOutT2 = pOutT1 + (numCols * k);
  213. /* Look for the most significant element to
  214. * replace in the rows below */
  215. if((*pInT2 > 0.0f ? *pInT2: -*pInT2) == maxC)
  216. {
  217. /* Loop over number of columns
  218. * to the right of the pilot element */
  219. j = numCols - l;
  220. while(j > 0u)
  221. {
  222. /* Exchange the row elements of the input matrix */
  223. Xchg = *pInT2;
  224. *pInT2++ = *pInT1;
  225. *pInT1++ = Xchg;
  226. /* Decrement the loop counter */
  227. j--;
  228. }
  229. /* Loop over number of columns of the destination matrix */
  230. j = numCols;
  231. while(j > 0u)
  232. {
  233. /* Exchange the row elements of the destination matrix */
  234. Xchg = *pOutT2;
  235. *pOutT2++ = *pOutT1;
  236. *pOutT1++ = Xchg;
  237. /* Decrement the loop counter */
  238. j--;
  239. }
  240. /* Flag to indicate whether exchange is done or not */
  241. flag = 1u;
  242. /* Break after exchange is done */
  243. break;
  244. }
  245. /* Update the destination pointer modifier */
  246. k++;
  247. /* Decrement the loop counter */
  248. i--;
  249. }
  250. }
  251. /* Update the status if the matrix is singular */
  252. if((flag != 1u) && (in == 0.0f))
  253. {
  254. return ARM_MATH_SINGULAR;
  255. }
  256. /* Points to the pivot row of input and destination matrices */
  257. pPivotRowIn = pIn + (l * numCols);
  258. pPivotRowDst = pOut + (l * numCols);
  259. /* Temporary pointers to the pivot row pointers */
  260. pInT1 = pPivotRowIn;
  261. pInT2 = pPivotRowDst;
  262. /* Pivot element of the row */
  263. in = *pPivotRowIn;
  264. /* Loop over number of columns
  265. * to the right of the pilot element */
  266. j = (numCols - l);
  267. while(j > 0u)
  268. {
  269. /* Divide each element of the row of the input matrix
  270. * by the pivot element */
  271. in1 = *pInT1;
  272. *pInT1++ = in1 / in;
  273. /* Decrement the loop counter */
  274. j--;
  275. }
  276. /* Loop over number of columns of the destination matrix */
  277. j = numCols;
  278. while(j > 0u)
  279. {
  280. /* Divide each element of the row of the destination matrix
  281. * by the pivot element */
  282. in1 = *pInT2;
  283. *pInT2++ = in1 / in;
  284. /* Decrement the loop counter */
  285. j--;
  286. }
  287. /* Replace the rows with the sum of that row and a multiple of row i
  288. * so that each new element in column i above row i is zero.*/
  289. /* Temporary pointers for input and destination matrices */
  290. pInT1 = pIn;
  291. pInT2 = pOut;
  292. /* index used to check for pivot element */
  293. i = 0u;
  294. /* Loop over number of rows */
  295. /* to be replaced by the sum of that row and a multiple of row i */
  296. k = numRows;
  297. while(k > 0u)
  298. {
  299. /* Check for the pivot element */
  300. if(i == l)
  301. {
  302. /* If the processing element is the pivot element,
  303. only the columns to the right are to be processed */
  304. pInT1 += numCols - l;
  305. pInT2 += numCols;
  306. }
  307. else
  308. {
  309. /* Element of the reference row */
  310. in = *pInT1;
  311. /* Working pointers for input and destination pivot rows */
  312. pPRT_in = pPivotRowIn;
  313. pPRT_pDst = pPivotRowDst;
  314. /* Loop over the number of columns to the right of the pivot element,
  315. to replace the elements in the input matrix */
  316. j = (numCols - l);
  317. while(j > 0u)
  318. {
  319. /* Replace the element by the sum of that row
  320. and a multiple of the reference row */
  321. in1 = *pInT1;
  322. *pInT1++ = in1 - (in * *pPRT_in++);
  323. /* Decrement the loop counter */
  324. j--;
  325. }
  326. /* Loop over the number of columns to
  327. replace the elements in the destination matrix */
  328. j = numCols;
  329. while(j > 0u)
  330. {
  331. /* Replace the element by the sum of that row
  332. and a multiple of the reference row */
  333. in1 = *pInT2;
  334. *pInT2++ = in1 - (in * *pPRT_pDst++);
  335. /* Decrement the loop counter */
  336. j--;
  337. }
  338. }
  339. /* Increment the temporary input pointer */
  340. pInT1 = pInT1 + l;
  341. /* Decrement the loop counter */
  342. k--;
  343. /* Increment the pivot index */
  344. i++;
  345. }
  346. /* Increment the input pointer */
  347. pIn++;
  348. /* Decrement the loop counter */
  349. loopCnt--;
  350. /* Increment the index modifier */
  351. l++;
  352. }
  353. #else
  354. /* Run the below code for Cortex-M0 */
  355. float32_t Xchg, in = 0.0f; /* Temporary input values */
  356. uint32_t i, rowCnt, flag = 0u, j, loopCnt, k, l; /* loop counters */
  357. arm_status status; /* status of matrix inverse */
  358. #ifdef ARM_MATH_MATRIX_CHECK
  359. /* Check for matrix mismatch condition */
  360. if((pSrc->numRows != pSrc->numCols) || (pDst->numRows != pDst->numCols)
  361. || (pSrc->numRows != pDst->numRows))
  362. {
  363. /* Set status as ARM_MATH_SIZE_MISMATCH */
  364. status = ARM_MATH_SIZE_MISMATCH;
  365. }
  366. else
  367. #endif /* #ifdef ARM_MATH_MATRIX_CHECK */
  368. {
  369. /*--------------------------------------------------------------------------------------------------------------
  370. * Matrix Inverse can be solved using elementary row operations.
  371. *
  372. * Gauss-Jordan Method:
  373. *
  374. * 1. First combine the identity matrix and the input matrix separated by a bar to form an
  375. * augmented matrix as follows:
  376. * _ _ _ _ _ _ _ _
  377. * | | a11 a12 | | | 1 0 | | | X11 X12 |
  378. * | | | | | | | = | |
  379. * |_ |_ a21 a22 _| | |_0 1 _| _| |_ X21 X21 _|
  380. *
  381. * 2. In our implementation, pDst Matrix is used as identity matrix.
  382. *
  383. * 3. Begin with the first row. Let i = 1.
  384. *
  385. * 4. Check to see if the pivot for row i is zero.
  386. * The pivot is the element of the main diagonal that is on the current row.
  387. * For instance, if working with row i, then the pivot element is aii.
  388. * If the pivot is zero, exchange that row with a row below it that does not
  389. * contain a zero in column i. If this is not possible, then an inverse
  390. * to that matrix does not exist.
  391. *
  392. * 5. Divide every element of row i by the pivot.
  393. *
  394. * 6. For every row below and row i, replace that row with the sum of that row and
  395. * a multiple of row i so that each new element in column i below row i is zero.
  396. *
  397. * 7. Move to the next row and column and repeat steps 2 through 5 until you have zeros
  398. * for every element below and above the main diagonal.
  399. *
  400. * 8. Now an identical matrix is formed to the left of the bar(input matrix, src).
  401. * Therefore, the matrix to the right of the bar is our solution(dst matrix, dst).
  402. *----------------------------------------------------------------------------------------------------------------*/
  403. /* Working pointer for destination matrix */
  404. pOutT1 = pOut;
  405. /* Loop over the number of rows */
  406. rowCnt = numRows;
  407. /* Making the destination matrix as identity matrix */
  408. while(rowCnt > 0u)
  409. {
  410. /* Writing all zeroes in lower triangle of the destination matrix */
  411. j = numRows - rowCnt;
  412. while(j > 0u)
  413. {
  414. *pOutT1++ = 0.0f;
  415. j--;
  416. }
  417. /* Writing all ones in the diagonal of the destination matrix */
  418. *pOutT1++ = 1.0f;
  419. /* Writing all zeroes in upper triangle of the destination matrix */
  420. j = rowCnt - 1u;
  421. while(j > 0u)
  422. {
  423. *pOutT1++ = 0.0f;
  424. j--;
  425. }
  426. /* Decrement the loop counter */
  427. rowCnt--;
  428. }
  429. /* Loop over the number of columns of the input matrix.
  430. All the elements in each column are processed by the row operations */
  431. loopCnt = numCols;
  432. /* Index modifier to navigate through the columns */
  433. l = 0u;
  434. //for(loopCnt = 0u; loopCnt < numCols; loopCnt++)
  435. while(loopCnt > 0u)
  436. {
  437. /* Check if the pivot element is zero..
  438. * If it is zero then interchange the row with non zero row below.
  439. * If there is no non zero element to replace in the rows below,
  440. * then the matrix is Singular. */
  441. /* Working pointer for the input matrix that points
  442. * to the pivot element of the particular row */
  443. pInT1 = pIn + (l * numCols);
  444. /* Working pointer for the destination matrix that points
  445. * to the pivot element of the particular row */
  446. pOutT1 = pOut + (l * numCols);
  447. /* Temporary variable to hold the pivot value */
  448. in = *pInT1;
  449. /* Destination pointer modifier */
  450. k = 1u;
  451. /* Check if the pivot element is zero */
  452. if(*pInT1 == 0.0f)
  453. {
  454. /* Loop over the number rows present below */
  455. for (i = (l + 1u); i < numRows; i++)
  456. {
  457. /* Update the input and destination pointers */
  458. pInT2 = pInT1 + (numCols * l);
  459. pOutT2 = pOutT1 + (numCols * k);
  460. /* Check if there is a non zero pivot element to
  461. * replace in the rows below */
  462. if(*pInT2 != 0.0f)
  463. {
  464. /* Loop over number of columns
  465. * to the right of the pilot element */
  466. for (j = 0u; j < (numCols - l); j++)
  467. {
  468. /* Exchange the row elements of the input matrix */
  469. Xchg = *pInT2;
  470. *pInT2++ = *pInT1;
  471. *pInT1++ = Xchg;
  472. }
  473. for (j = 0u; j < numCols; j++)
  474. {
  475. Xchg = *pOutT2;
  476. *pOutT2++ = *pOutT1;
  477. *pOutT1++ = Xchg;
  478. }
  479. /* Flag to indicate whether exchange is done or not */
  480. flag = 1u;
  481. /* Break after exchange is done */
  482. break;
  483. }
  484. /* Update the destination pointer modifier */
  485. k++;
  486. }
  487. }
  488. /* Update the status if the matrix is singular */
  489. if((flag != 1u) && (in == 0.0f))
  490. {
  491. return ARM_MATH_SINGULAR;
  492. }
  493. /* Points to the pivot row of input and destination matrices */
  494. pPivotRowIn = pIn + (l * numCols);
  495. pPivotRowDst = pOut + (l * numCols);
  496. /* Temporary pointers to the pivot row pointers */
  497. pInT1 = pPivotRowIn;
  498. pOutT1 = pPivotRowDst;
  499. /* Pivot element of the row */
  500. in = *(pIn + (l * numCols));
  501. /* Loop over number of columns
  502. * to the right of the pilot element */
  503. for (j = 0u; j < (numCols - l); j++)
  504. {
  505. /* Divide each element of the row of the input matrix
  506. * by the pivot element */
  507. *pInT1 = *pInT1 / in;
  508. pInT1++;
  509. }
  510. for (j = 0u; j < numCols; j++)
  511. {
  512. /* Divide each element of the row of the destination matrix
  513. * by the pivot element */
  514. *pOutT1 = *pOutT1 / in;
  515. pOutT1++;
  516. }
  517. /* Replace the rows with the sum of that row and a multiple of row i
  518. * so that each new element in column i above row i is zero.*/
  519. /* Temporary pointers for input and destination matrices */
  520. pInT1 = pIn;
  521. pOutT1 = pOut;
  522. for (i = 0u; i < numRows; i++)
  523. {
  524. /* Check for the pivot element */
  525. if(i == l)
  526. {
  527. /* If the processing element is the pivot element,
  528. only the columns to the right are to be processed */
  529. pInT1 += numCols - l;
  530. pOutT1 += numCols;
  531. }
  532. else
  533. {
  534. /* Element of the reference row */
  535. in = *pInT1;
  536. /* Working pointers for input and destination pivot rows */
  537. pPRT_in = pPivotRowIn;
  538. pPRT_pDst = pPivotRowDst;
  539. /* Loop over the number of columns to the right of the pivot element,
  540. to replace the elements in the input matrix */
  541. for (j = 0u; j < (numCols - l); j++)
  542. {
  543. /* Replace the element by the sum of that row
  544. and a multiple of the reference row */
  545. *pInT1 = *pInT1 - (in * *pPRT_in++);
  546. pInT1++;
  547. }
  548. /* Loop over the number of columns to
  549. replace the elements in the destination matrix */
  550. for (j = 0u; j < numCols; j++)
  551. {
  552. /* Replace the element by the sum of that row
  553. and a multiple of the reference row */
  554. *pOutT1 = *pOutT1 - (in * *pPRT_pDst++);
  555. pOutT1++;
  556. }
  557. }
  558. /* Increment the temporary input pointer */
  559. pInT1 = pInT1 + l;
  560. }
  561. /* Increment the input pointer */
  562. pIn++;
  563. /* Decrement the loop counter */
  564. loopCnt--;
  565. /* Increment the index modifier */
  566. l++;
  567. }
  568. #endif /* #ifndef ARM_MATH_CM0_FAMILY */
  569. /* Set status as ARM_MATH_SUCCESS */
  570. status = ARM_MATH_SUCCESS;
  571. if((flag != 1u) && (in == 0.0f))
  572. {
  573. status = ARM_MATH_SINGULAR;
  574. }
  575. }
  576. /* Return to application */
  577. return (status);
  578. }
  579. /**
  580. * @} end of MatrixInv group
  581. */