@@ -91,11 +91,99 @@ QDLDL_int QDLDL_etree(const QDLDL_int n, const QDLDL_int* Ap, const QDLDL_int* A
9191}
9292
9393
94- QDLDL_int QDLDL_factor (const QDLDL_int n , const QDLDL_int * Ap , const QDLDL_int * Ai ,
95- const QDLDL_float * Ax , QDLDL_int * Lp , QDLDL_int * Li , QDLDL_float * Lx ,
96- QDLDL_float * D , QDLDL_float * Dinv , const QDLDL_int * Lnz ,
97- const QDLDL_int * etree , QDLDL_bool * bwork , QDLDL_int * iwork ,
98- QDLDL_float * fwork ) {
94+ void QDLDL_symbolic (const QDLDL_int n , const QDLDL_int * Ap , const QDLDL_int * Ai , QDLDL_int * Lp ,
95+ QDLDL_int * Li , const QDLDL_int * Lnz , const QDLDL_int * etree ,
96+ QDLDL_bool * bwork , QDLDL_int * iwork ) {
97+ QDLDL_int i = 0 ;
98+ QDLDL_int k = 0 ;
99+ QDLDL_int bidx = 0 ;
100+ QDLDL_int nextIdx = 0 ;
101+ QDLDL_int nnzE = 0 ;
102+ QDLDL_int nnzY = 0 ;
103+ QDLDL_int tmpIdx = 0 ;
104+ QDLDL_int * yIdx ;
105+ QDLDL_int * elimBuffer ;
106+ QDLDL_int * LNextSpaceInCol ;
107+ QDLDL_bool * yMarkers ;
108+
109+ // Partition working memory into pieces
110+ yMarkers = bwork ;
111+ yIdx = iwork ;
112+ elimBuffer = iwork + n ;
113+ LNextSpaceInCol = iwork + n * 2 ;
114+
115+ Lp [0 ] = 0 ; // First column starts at index zero
116+
117+ for (i = 0 ; i < n ; i ++ ) {
118+ // Compute L column pointers (cumulative sum of Lnz)
119+ Lp [i + 1 ] = Lp [i ] + Lnz [i ];
120+
121+ // Initialize markers and next-space trackers
122+ yMarkers [i ] = QDLDL_UNUSED ;
123+ LNextSpaceInCol [i ] = Lp [i ];
124+ }
125+
126+ // Start from 1: column 0 of L has no subdiagonal entries
127+ for (k = 1 ; k < n ; k ++ ) {
128+ nnzY = 0 ;
129+
130+ tmpIdx = Ap [k + 1 ];
131+
132+ for (i = Ap [k ]; i < tmpIdx ; i ++ ) {
133+ bidx = Ai [i ];
134+
135+ // Skip the diagonal entry
136+ if (bidx == k ) {
137+ continue ;
138+ }
139+
140+ // Walk the elimination tree to find the nonzero pattern
141+ nextIdx = bidx ;
142+
143+ if (yMarkers [nextIdx ] == QDLDL_UNUSED ) {
144+
145+ yMarkers [nextIdx ] = QDLDL_USED ;
146+ elimBuffer [0 ] = nextIdx ;
147+ nnzE = 1 ;
148+
149+ nextIdx = etree [bidx ];
150+
151+ while (nextIdx != QDLDL_UNKNOWN && nextIdx < k ) {
152+ if (yMarkers [nextIdx ] == QDLDL_USED )
153+ break ;
154+
155+ yMarkers [nextIdx ] = QDLDL_USED ;
156+ elimBuffer [nnzE ] = nextIdx ;
157+ nnzE ++ ;
158+ nextIdx = etree [nextIdx ];
159+ }
160+
161+ while (nnzE ) {
162+ yIdx [nnzY ++ ] = elimBuffer [-- nnzE ];
163+ }
164+ }
165+ }
166+
167+ // Place the row indices into Li
168+ for (i = (nnzY - 1 ); i >= 0 ; i -- ) {
169+ QDLDL_int cidx = yIdx [i ];
170+ tmpIdx = LNextSpaceInCol [cidx ];
171+
172+ Li [tmpIdx ] = k ;
173+ LNextSpaceInCol [cidx ]++ ;
174+
175+ // Reset marker
176+ yMarkers [cidx ] = QDLDL_UNUSED ;
177+ }
178+ }
179+ }
180+
181+
182+ QDLDL_int QDLDL_numeric (const QDLDL_int n , const QDLDL_int * Ap , const QDLDL_int * Ai ,
183+ const QDLDL_float * Ax , const QDLDL_int * Lp , const QDLDL_int * Li ,
184+ QDLDL_float * Lx , QDLDL_float * D , QDLDL_float * Dinv , const QDLDL_int * Lnz ,
185+ const QDLDL_int * etree , QDLDL_bool * bwork , QDLDL_int * iwork ,
186+ QDLDL_float * fwork ) {
99187 QDLDL_int i = 0 ;
100188 QDLDL_int j = 0 ;
101189 QDLDL_int k = 0 ;
@@ -120,16 +208,7 @@ QDLDL_int QDLDL_factor(const QDLDL_int n, const QDLDL_int* Ap, const QDLDL_int*
120208 LNextSpaceInCol = iwork + n * 2 ;
121209 yVals = fwork ;
122210
123-
124- Lp [0 ] = 0 ; // First column starts at index zero
125-
126211 for (i = 0 ; i < n ; i ++ ) {
127- // Compute L column indices
128- Lp [i + 1 ] = Lp [i ] + Lnz [i ]; // cumsum, total at the end
129-
130- // Set all Yidx to be 'unused' initially
131- // in each column of L, the next available space
132- // to start is just the first space in the column
133212 yMarkers [i ] = QDLDL_UNUSED ;
134213 yVals [i ] = 0.0 ;
135214 D [i ] = 0.0 ;
@@ -228,7 +307,6 @@ QDLDL_int QDLDL_factor(const QDLDL_int n, const QDLDL_int* Ap, const QDLDL_int*
228307 // Now I have the cidx^th element of y = L\b.
229308 // so compute the corresponding element of
230309 // this row of L and put it into the right place
231- Li [tmpIdx ] = k ;
232310 Lx [tmpIdx ] = yVals_cidx * Dinv [cidx ];
233311
234312 // D[k] -= yVals[cidx]*yVals[cidx]*Dinv[cidx];
@@ -261,6 +339,18 @@ QDLDL_int QDLDL_factor(const QDLDL_int n, const QDLDL_int* Ap, const QDLDL_int*
261339 return positiveValuesInD ;
262340}
263341
342+
343+ QDLDL_int QDLDL_factor (const QDLDL_int n , const QDLDL_int * Ap , const QDLDL_int * Ai ,
344+ const QDLDL_float * Ax , QDLDL_int * Lp , QDLDL_int * Li , QDLDL_float * Lx ,
345+ QDLDL_float * D , QDLDL_float * Dinv , const QDLDL_int * Lnz ,
346+ const QDLDL_int * etree , QDLDL_bool * bwork , QDLDL_int * iwork ,
347+ QDLDL_float * fwork ) {
348+
349+ QDLDL_symbolic (n , Ap , Ai , Lp , Li , Lnz , etree , bwork , iwork );
350+
351+ return QDLDL_numeric (n , Ap , Ai , Ax , Lp , Li , Lx , D , Dinv , Lnz , etree , bwork , iwork , fwork );
352+ }
353+
264354// Solves (L+I)x = b
265355void QDLDL_Lsolve (const QDLDL_int n , const QDLDL_int * Lp , const QDLDL_int * Li ,
266356 const QDLDL_float * Lx , QDLDL_float * x ) {
0 commit comments