1 /* ----------------------------------------------------------------------
2  * Project:      CMSIS DSP Library
3  * Title:        arm_mat_ldl_f64.c
4  * Description:  Floating-point LDL decomposition
5  *
6  * $Date:        23 April 2021
7  * $Revision:    V1.9.0
8  *
9  * Target Processor: Cortex-M and Cortex-A cores
10  * -------------------------------------------------------------------- */
11 /*
12  * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved.
13  *
14  * SPDX-License-Identifier: Apache-2.0
15  *
16  * Licensed under the Apache License, Version 2.0 (the License); you may
17  * not use this file except in compliance with the License.
18  * You may obtain a copy of the License at
19  *
20  * www.apache.org/licenses/LICENSE-2.0
21  *
22  * Unless required by applicable law or agreed to in writing, software
23  * distributed under the License is distributed on an AS IS BASIS, WITHOUT
24  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
25  * See the License for the specific language governing permissions and
26  * limitations under the License.
27  */
28 
29 #include "dsp/matrix_functions.h"
30 #include <math.h>
31 
32 
33 
34 /// @private
35 #define SWAP_ROWS_F64(A,i,j)     \
36   for(int w=0;w < n; w++)    \
37   {                          \
38      float64_t tmp;          \
39      tmp = A[i*n + w];       \
40      A[i*n + w] = A[j*n + w];\
41      A[j*n + w] = tmp;       \
42   }
43 /// @private
44 #define SWAP_COLS_F64(A,i,j)     \
45   for(int w=0;w < n; w++)    \
46   {                          \
47      float64_t tmp;          \
48      tmp = A[w*n + i];       \
49      A[w*n + i] = A[w*n + j];\
50      A[w*n + j] = tmp;       \
51   }
52 
53 /**
54   @ingroup groupMatrix
55  */
56 
57 /**
58   @addtogroup MatrixChol
59   @{
60  */
61 
62 /**
63    * @brief Floating-point LDL^t decomposition of positive semi-definite matrix.
64    * @param[in]  pSrc   points to the instance of the input floating-point matrix structure.
65    * @param[out] pl   points to the instance of the output floating-point triangular matrix structure.
66    * @param[out] pd   points to the instance of the output floating-point diagonal matrix structure.
67    * @param[out] pp   points to the instance of the output floating-point permutation vector.
68    * @return The function returns ARM_MATH_SIZE_MISMATCH, if the dimensions do not match.
69    * @return        execution status
70                    - \ref ARM_MATH_SUCCESS       : Operation successful
71                    - \ref ARM_MATH_SIZE_MISMATCH : Matrix size check failed
72                    - \ref ARM_MATH_DECOMPOSITION_FAILURE      : Input matrix cannot be decomposed
73    * @par
74    *  Computes the LDL^t decomposition of a matrix A such that P A P^t = L D L^t.
75    */
76 
arm_mat_ldlt_f64(const arm_matrix_instance_f64 * pSrc,arm_matrix_instance_f64 * pl,arm_matrix_instance_f64 * pd,uint16_t * pp)77 arm_status arm_mat_ldlt_f64(
78   const arm_matrix_instance_f64 * pSrc,
79   arm_matrix_instance_f64 * pl,
80   arm_matrix_instance_f64 * pd,
81   uint16_t * pp)
82 {
83 
84   arm_status status;                             /* status of matrix inverse */
85 
86 
87 #ifdef ARM_MATH_MATRIX_CHECK
88 
89   /* Check for matrix mismatch condition */
90   if ((pSrc->numRows != pSrc->numCols) ||
91       (pl->numRows != pl->numCols) ||
92       (pd->numRows != pd->numCols) ||
93       (pl->numRows != pd->numRows)   )
94   {
95     /* Set status as ARM_MATH_SIZE_MISMATCH */
96     status = ARM_MATH_SIZE_MISMATCH;
97   }
98   else
99 
100 #endif /* #ifdef ARM_MATH_MATRIX_CHECK */
101 
102   {
103 
104     const int n=pSrc->numRows;
105     int fullRank = 1, diag,k;
106     float64_t *pA;
107 
108     memcpy(pl->pData,pSrc->pData,n*n*sizeof(float64_t));
109     pA = pl->pData;
110 
111     for(int k=0;k < n; k++)
112     {
113       pp[k] = k;
114     }
115 
116 
117     for(k=0;k < n; k++)
118     {
119         /* Find pivot */
120         float64_t m=F64_MIN,a;
121         int j=k;
122 
123 
124         for(int r=k;r<n;r++)
125         {
126            if (pA[r*n+r] > m)
127            {
128              m = pA[r*n+r];
129              j = r;
130            }
131         }
132 
133         if(j != k)
134         {
135           SWAP_ROWS_F64(pA,k,j);
136           SWAP_COLS_F64(pA,k,j);
137         }
138 
139 
140         pp[k] = j;
141 
142         a = pA[k*n+k];
143 
144         if (fabs(a) < 1.0e-18)
145         {
146 
147             fullRank = 0;
148             break;
149         }
150 
151         for(int w=k+1;w<n;w++)
152         {
153           for(int x=k+1;x<n;x++)
154           {
155              pA[w*n+x] = pA[w*n+x] - pA[w*n+k] * pA[x*n+k] / a;
156           }
157         }
158 
159         for(int w=k+1;w<n;w++)
160         {
161                pA[w*n+k] = pA[w*n+k] / a;
162         }
163 
164 
165 
166     }
167 
168 
169 
170     diag=k;
171     if (!fullRank)
172     {
173       diag--;
174       for(int row=0; row < n;row++)
175       {
176         for(int col=k; col < n;col++)
177         {
178            pl->pData[row*n+col]=0.0;
179         }
180       }
181     }
182 
183     for(int row=0; row < n;row++)
184     {
185        for(int col=row+1; col < n;col++)
186        {
187          pl->pData[row*n+col] = 0.0;
188        }
189     }
190 
191     for(int d=0; d < diag;d++)
192     {
193       pd->pData[d*n+d] = pl->pData[d*n+d];
194       pl->pData[d*n+d] = 1.0;
195     }
196 
197     status = ARM_MATH_SUCCESS;
198 
199   }
200 
201 
202   /* Return to application */
203   return (status);
204 }
205 
206 /**
207   @} end of MatrixChol group
208  */
209