Amesos Package Browser (Single Doxygen Collection)  Development
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
amesos_klu_kernel.c
Go to the documentation of this file.
1 /* ========================================================================== */
2 /* === KLU_kernel =========================================================== */
3 /* ========================================================================== */
4 
5 /* Sparse left-looking LU factorization, with partial pivoting. Based on
6  * Gilbert & Peierl's method, with a non-recursive DFS and with Eisenstat &
7  * Liu's symmetric pruning. No user-callable routines are in this file.
8  */
9 
10 #include "amesos_klu_internal.h"
11 
12 /* ========================================================================== */
13 /* === dfs ================================================================== */
14 /* ========================================================================== */
15 
16 /* Does a depth-first-search, starting at node j. */
17 
18 static Int dfs
19 (
20  /* input, not modified on output: */
21  Int j, /* node at which to start the DFS */
22  Int k, /* mark value, for the Flag array */
23  Int Pinv [ ], /* Pinv [i] = k if row i is kth pivot row, or EMPTY if
24  * row i is not yet pivotal. */
25  Int Llen [ ], /* size n, Llen [k] = # nonzeros in column k of L */
26  Int Lip [ ], /* size n, Lip [k] is position in LU of column k of L */
27 
28  /* workspace, not defined on input or output */
29  Int Stack [ ], /* size n */
30 
31  /* input/output: */
32  Int Flag [ ], /* Flag [i] == k means i is marked */
33  Int Lpend [ ], /* for symmetric pruning */
34  Int top, /* top of stack on input*/
35  Unit LU [],
36  Int *Lik, /* Li row index array of the kth column */
37  Int *plength,
38 
39  /* other, not defined on input or output */
40  Int Ap_pos [ ] /* keeps track of position in adj list during DFS */
41 )
42 {
43  Int i, pos, jnew, head, l_length ;
44  Int *Li ;
45 
46  l_length = *plength ;
47 
48  head = 0 ;
49  Stack [0] = j ;
50  ASSERT (Flag [j] != k) ;
51 
52  while (head >= 0)
53  {
54  j = Stack [head] ;
55  jnew = Pinv [j] ;
56  ASSERT (jnew >= 0 && jnew < k) ; /* j is pivotal */
57 
58  if (Flag [j] != k) /* a node is not yet visited */
59  {
60  /* first time that j has been visited */
61  Flag [j] = k ;
62  PRINTF (("[ start dfs at %d : new %d\n", j, jnew)) ;
63  /* set Ap_pos [head] to one past the last entry in col j to scan */
64  Ap_pos [head] =
65  (Lpend [jnew] == EMPTY) ? Llen [jnew] : Lpend [jnew] ;
66  }
67 
68  /* add the adjacent nodes to the recursive stack by iterating through
69  * until finding another non-visited pivotal node */
70  Li = (Int *) (LU + Lip [jnew]) ;
71  for (pos = --Ap_pos [head] ; pos >= 0 ; --pos)
72  {
73  i = Li [pos] ;
74  if (Flag [i] != k)
75  {
76  /* node i is not yet visited */
77  if (Pinv [i] >= 0)
78  {
79  /* keep track of where we left off in the scan of the
80  * adjacency list of node j so we can restart j where we
81  * left off. */
82  Ap_pos [head] = pos ;
83 
84  /* node i is pivotal; push it onto the recursive stack
85  * and immediately break so we can recurse on node i. */
86  Stack [++head] = i ;
87  break ;
88  }
89  else
90  {
91  /* node i is not pivotal (no outgoing edges). */
92  /* Flag as visited and store directly into L,
93  * and continue with current node j. */
94  Flag [i] = k ;
95  Lik [l_length] = i ;
96  l_length++ ;
97  }
98  }
99  }
100 
101  if (pos == -1)
102  {
103  /* if all adjacent nodes of j are already visited, pop j from
104  * recursive stack and push j onto output stack */
105  head-- ;
106  Stack[--top] = j ;
107  PRINTF ((" end dfs at %d ] head : %d\n", j, head)) ;
108  }
109  }
110 
111  *plength = l_length ;
112  return (top) ;
113 }
114 
115 
116 /* ========================================================================== */
117 /* === lsolve_symbolic ====================================================== */
118 /* ========================================================================== */
119 
120 /* Finds the pattern of x, for the solution of Lx=b */
121 
122 static Int lsolve_symbolic
123 (
124  /* input, not modified on output: */
125  Int n, /* L is n-by-n, where n >= 0 */
126  Int k, /* also used as the mark value, for the Flag array */
127  Int Ap [ ],
128  Int Ai [ ],
129  Int Q [ ],
130  Int Pinv [ ], /* Pinv [i] = k if i is kth pivot row, or EMPTY if row i
131  * is not yet pivotal. */
132 
133  /* workspace, not defined on input or output */
134  Int Stack [ ], /* size n */
135 
136  /* workspace, defined on input and output */
137  Int Flag [ ], /* size n. Initially, all of Flag [0..n-1] < k. After
138  * lsolve_symbolic is done, Flag [i] == k if i is in
139  * the pattern of the output, and Flag [0..n-1] <= k. */
140 
141  /* other */
142  Int Lpend [ ], /* for symmetric pruning */
143  Int Ap_pos [ ], /* workspace used in dfs */
144 
145  Unit LU [ ], /* LU factors (pattern and values) */
146  Int lup, /* pointer to free space in LU */
147  Int Llen [ ], /* size n, Llen [k] = # nonzeros in column k of L */
148  Int Lip [ ], /* size n, Lip [k] is position in LU of column k of L */
149 
150  /* ---- the following are only used in the BTF case --- */
151 
152  Int k1, /* the block of A is from k1 to k2-1 */
153  Int PSinv [ ] /* inverse of P from symbolic factorization */
154 )
155 {
156  Int *Lik ;
157  Int i, p, pend, oldcol, kglobal, top, l_length ;
158 
159  top = n ;
160  l_length = 0 ;
161  Lik = (Int *) (LU + lup);
162 
163  /* ---------------------------------------------------------------------- */
164  /* BTF factorization of A (k1:k2-1, k1:k2-1) */
165  /* ---------------------------------------------------------------------- */
166 
167  kglobal = k + k1 ; /* column k of the block is col kglobal of A */
168  oldcol = Q [kglobal] ; /* Q must be present for BTF case */
169  pend = Ap [oldcol+1] ;
170  for (p = Ap [oldcol] ; p < pend ; p++)
171  {
172  i = PSinv [Ai [p]] - k1 ;
173  if (i < 0) continue ; /* skip entry outside the block */
174 
175  /* (i,k) is an entry in the block. start a DFS at node i */
176  PRINTF (("\n ===== DFS at node %d in b, inew: %d\n", i, Pinv [i])) ;
177  if (Flag [i] != k)
178  {
179  if (Pinv [i] >= 0)
180  {
181  top = dfs (i, k, Pinv, Llen, Lip, Stack, Flag,
182  Lpend, top, LU, Lik, &l_length, Ap_pos) ;
183  }
184  else
185  {
186  /* i is not pivotal, and not flagged. Flag and put in L */
187  Flag [i] = k ;
188  Lik [l_length] = i ;
189  l_length++;
190  }
191  }
192  }
193 
194  /* If Llen [k] is zero, the matrix is structurally singular */
195  Llen [k] = l_length ;
196  return (top) ;
197 }
198 
199 
200 /* ========================================================================== */
201 /* === construct_column ===================================================== */
202 /* ========================================================================== */
203 
204 /* Construct the kth column of A, and the off-diagonal part, if requested.
205  * Scatter the numerical values into the workspace X, and construct the
206  * corresponding column of the off-diagonal matrix. */
207 
208 static void construct_column
209 (
210  /* inputs, not modified on output */
211  Int k, /* the column of A (or the column of the block) to get */
212  Int Ap [ ],
213  Int Ai [ ],
214  Entry Ax [ ],
215  Int Q [ ], /* column pre-ordering */
216 
217  /* zero on input, modified on output */
218  Entry X [ ],
219 
220  /* ---- the following are only used in the BTF case --- */
221 
222  /* inputs, not modified on output */
223  Int k1, /* the block of A is from k1 to k2-1 */
224  Int PSinv [ ], /* inverse of P from symbolic factorization */
225  double Rs [ ], /* scale factors for A */
226  Int scale, /* 0: no scaling, nonzero: scale the rows with Rs */
227 
228  /* inputs, modified on output */
229  Int Offp [ ], /* off-diagonal matrix (modified by this routine) */
230  Int Offi [ ],
231  Entry Offx [ ]
232 )
233 {
234  Entry aik ;
235  Int i, p, pend, oldcol, kglobal, poff, oldrow ;
236 
237  /* ---------------------------------------------------------------------- */
238  /* Scale and scatter the column into X. */
239  /* ---------------------------------------------------------------------- */
240 
241  kglobal = k + k1 ; /* column k of the block is col kglobal of A */
242  poff = Offp [kglobal] ; /* start of off-diagonal column */
243  oldcol = Q [kglobal] ;
244  pend = Ap [oldcol+1] ;
245 
246  if (scale <= 0)
247  {
248  /* no scaling */
249  for (p = Ap [oldcol] ; p < pend ; p++)
250  {
251  oldrow = Ai [p] ;
252  i = PSinv [oldrow] - k1 ;
253  aik = Ax [p] ;
254  if (i < 0)
255  {
256  /* this is an entry in the off-diagonal part */
257  Offi [poff] = oldrow ;
258  Offx [poff] = aik ;
259  poff++ ;
260  }
261  else
262  {
263  /* (i,k) is an entry in the block. scatter into X */
264  X [i] = aik ;
265  }
266  }
267  }
268  else
269  {
270  /* row scaling */
271  for (p = Ap [oldcol] ; p < pend ; p++)
272  {
273  oldrow = Ai [p] ;
274  i = PSinv [oldrow] - k1 ;
275  aik = Ax [p] ;
276  SCALE_DIV (aik, Rs [oldrow]) ;
277  if (i < 0)
278  {
279  /* this is an entry in the off-diagonal part */
280  Offi [poff] = oldrow ;
281  Offx [poff] = aik ;
282  poff++ ;
283  }
284  else
285  {
286  /* (i,k) is an entry in the block. scatter into X */
287  X [i] = aik ;
288  }
289  }
290  }
291 
292  Offp [kglobal+1] = poff ; /* start of the next col of off-diag part */
293 }
294 
295 
296 /* ========================================================================== */
297 /* === lsolve_numeric ======================================================= */
298 /* ========================================================================== */
299 
300 /* Computes the numerical values of x, for the solution of Lx=b. Note that x
301  * may include explicit zeros if numerical cancelation occurs. L is assumed
302  * to be unit-diagonal, with possibly unsorted columns (but the first entry in
303  * the column must always be the diagonal entry). */
304 
305 static void lsolve_numeric
306 (
307  /* input, not modified on output: */
308  Int Pinv [ ], /* Pinv [i] = k if i is kth pivot row, or EMPTY if row i
309  * is not yet pivotal. */
310  Unit *LU, /* LU factors (pattern and values) */
311  Int Stack [ ], /* stack for dfs */
312  Int Lip [ ], /* size n, Lip [k] is position in LU of column k of L */
313  Int top, /* top of stack on input */
314  Int n, /* A is n-by-n */
315  Int Llen [ ], /* size n, Llen [k] = # nonzeros in column k of L */
316 
317  /* output, must be zero on input: */
318  Entry X [ ] /* size n, initially zero. On output,
319  * X [Ui [up1..up-1]] and X [Li [lp1..lp-1]]
320  * contains the solution. */
321 
322 )
323 {
324  Entry xj ;
325  Entry *Lx ;
326  Int *Li ;
327  Int p, s, j, jnew, len ;
328 
329  /* solve Lx=b */
330  for (s = top ; s < n ; s++)
331  {
332  /* forward solve with column j of L */
333  j = Stack [s] ;
334  jnew = Pinv [j] ;
335  ASSERT (jnew >= 0) ;
336  xj = X [j] ;
337  GET_POINTER (LU, Lip, Llen, Li, Lx, jnew, len) ;
338  ASSERT (Lip [jnew] <= Lip [jnew+1]) ;
339  for (p = 0 ; p < len ; p++)
340  {
341  /*X [Li [p]] -= Lx [p] * xj ; */
342  MULT_SUB (X [Li [p]], Lx [p], xj) ;
343  }
344  }
345 }
346 
347 
348 /* ========================================================================== */
349 /* === lpivot =============================================================== */
350 /* ========================================================================== */
351 
352 /* Find a pivot via partial pivoting, and scale the column of L. */
353 
354 static Int lpivot
355 (
356  Int diagrow,
357  Int *p_pivrow,
358  Entry *p_pivot,
359  double *p_abs_pivot,
360  double tol,
361  Entry X [ ],
362  Unit *LU, /* LU factors (pattern and values) */
363  Int Lip [ ],
364  Int Llen [ ],
365  Int k,
366  Int n,
367 
368  Int Pinv [ ], /* Pinv [i] = k if row i is kth pivot row, or EMPTY if
369  * row i is not yet pivotal. */
370 
371  Int *p_firstrow,
372  KLU_common *Common
373 )
374 {
375  Entry x, pivot, *Lx ;
376  double abs_pivot, xabs ;
377  Int p, i, ppivrow, pdiag, pivrow, *Li, last_row_index, firstrow, len ;
378 
379  pivrow = EMPTY ;
380  if (Llen [k] == 0)
381  {
382  /* matrix is structurally singular */
383  if (Common->halt_if_singular)
384  {
385  return (FALSE) ;
386  }
387  for (firstrow = *p_firstrow ; firstrow < n ; firstrow++)
388  {
389  PRINTF (("check %d\n", firstrow)) ;
390  if (Pinv [firstrow] < 0)
391  {
392  /* found the lowest-numbered non-pivotal row. Pick it. */
393  pivrow = firstrow ;
394  PRINTF (("Got pivotal row: %d\n", pivrow)) ;
395  break ;
396  }
397  }
398  ASSERT (pivrow >= 0 && pivrow < n) ;
399  CLEAR (pivot) ;
400  *p_pivrow = pivrow ;
401  *p_pivot = pivot ;
402  *p_abs_pivot = 0 ;
403  *p_firstrow = firstrow ;
404  return (FALSE) ;
405  }
406 
407  pdiag = EMPTY ;
408  ppivrow = EMPTY ;
409  abs_pivot = EMPTY ;
410  i = Llen [k] - 1 ;
411  GET_POINTER (LU, Lip, Llen, Li, Lx, k, len) ;
412  last_row_index = Li [i] ;
413 
414  /* decrement the length by 1 */
415  Llen [k] = i ;
416  GET_POINTER (LU, Lip, Llen, Li, Lx, k, len) ;
417 
418  /* look in Li [0 ..Llen [k] - 1 ] for a pivot row */
419  for (p = 0 ; p < len ; p++)
420  {
421  /* gather the entry from X and store in L */
422  i = Li [p] ;
423  x = X [i] ;
424  CLEAR (X [i]) ;
425 
426  Lx [p] = x ;
427  /* xabs = ABS (x) ; */
428  ABS (xabs, x) ;
429 
430  /* find the diagonal */
431  if (i == diagrow)
432  {
433  pdiag = p ;
434  }
435 
436  /* find the partial-pivoting choice */
437  if (xabs > abs_pivot)
438  {
439  abs_pivot = xabs ;
440  ppivrow = p ;
441  }
442  }
443 
444  /* xabs = ABS (X [last_row_index]) ;*/
445  ABS (xabs, X [last_row_index]) ;
446  if (xabs > abs_pivot)
447  {
448  abs_pivot = xabs ;
449  ppivrow = EMPTY ;
450  }
451 
452  /* compare the diagonal with the largest entry */
453  if (last_row_index == diagrow)
454  {
455  if (xabs >= tol * abs_pivot)
456  {
457  abs_pivot = xabs ;
458  ppivrow = EMPTY ;
459  }
460  }
461  else if (pdiag != EMPTY)
462  {
463  /* xabs = ABS (Lx [pdiag]) ;*/
464  ABS (xabs, Lx [pdiag]) ;
465  if (xabs >= tol * abs_pivot)
466  {
467  /* the diagonal is large enough */
468  abs_pivot = xabs ;
469  ppivrow = pdiag ;
470  }
471  }
472 
473  if (ppivrow != EMPTY)
474  {
475  pivrow = Li [ppivrow] ;
476  pivot = Lx [ppivrow] ;
477  /* overwrite the ppivrow values with last index values */
478  Li [ppivrow] = last_row_index ;
479  Lx [ppivrow] = X [last_row_index] ;
480  }
481  else
482  {
483  pivrow = last_row_index ;
484  pivot = X [last_row_index] ;
485  }
486  CLEAR (X [last_row_index]) ;
487 
488  *p_pivrow = pivrow ;
489  *p_pivot = pivot ;
490  *p_abs_pivot = abs_pivot ;
491  ASSERT (pivrow >= 0 && pivrow < n) ;
492 
493  if (IS_ZERO (pivot) && Common->halt_if_singular)
494  {
495  /* numerically singular case */
496  return (FALSE) ;
497  }
498 
499  /* divide L by the pivot value */
500  for (p = 0 ; p < Llen [k] ; p++)
501  {
502  /* Lx [p] /= pivot ; */
503  DIV (Lx [p], Lx [p], pivot) ;
504  }
505 
506  return (TRUE) ;
507 }
508 
509 
510 /* ========================================================================== */
511 /* === prune ================================================================ */
512 /* ========================================================================== */
513 
514 /* Prune the columns of L to reduce work in subsequent depth-first searches */
515 static void prune
516 (
517  /* input/output: */
518  Int Lpend [ ], /* Lpend [j] marks symmetric pruning point for L(:,j) */
519 
520  /* input: */
521  Int Pinv [ ], /* Pinv [i] = k if row i is kth pivot row, or EMPTY if
522  * row i is not yet pivotal. */
523  Int k, /* prune using column k of U */
524  Int pivrow, /* current pivot row */
525 
526  /* input/output: */
527  Unit *LU, /* LU factors (pattern and values) */
528 
529  /* input */
530  Int Uip [ ], /* size n, column pointers for U */
531  Int Lip [ ], /* size n, column pointers for L */
532  Int Ulen [ ], /* size n, column length of U */
533  Int Llen [ ] /* size n, column length of L */
534 )
535 {
536  Entry x ;
537  Entry *Lx, *Ux ;
538  Int *Li, *Ui ;
539  Int p, i, j, p2, phead, ptail, llen, ulen ;
540 
541  /* check to see if any column of L can be pruned */
542  GET_POINTER (LU, Uip, Ulen, Ui, Ux, k, ulen) ;
543  for (p = 0 ; p < ulen ; p++)
544  {
545  j = Ui [p] ;
546  ASSERT (j < k) ;
547  PRINTF (("%d is pruned: %d. Lpend[j] %d Lip[j+1] %d\n",
548  j, Lpend [j] != EMPTY, Lpend [j], Lip [j+1])) ;
549  if (Lpend [j] == EMPTY)
550  {
551  /* scan column j of L for the pivot row */
552  GET_POINTER (LU, Lip, Llen, Li, Lx, j, llen) ;
553  for (p2 = 0 ; p2 < llen ; p2++)
554  {
555  if (pivrow == Li [p2])
556  {
557  /* found it! This column can be pruned */
558 #ifndef NDEBUG
559  PRINTF (("==== PRUNE: col j %d of L\n", j)) ;
560  {
561  Int p3 ;
562  for (p3 = 0 ; p3 < Llen [j] ; p3++)
563  {
564  PRINTF (("before: %i pivotal: %d\n", Li [p3],
565  Pinv [Li [p3]] >= 0)) ;
566  }
567  }
568 #endif
569 
570  /* partition column j of L. The unit diagonal of L
571  * is not stored in the column of L. */
572  phead = 0 ;
573  ptail = Llen [j] ;
574  while (phead < ptail)
575  {
576  i = Li [phead] ;
577  if (Pinv [i] >= 0)
578  {
579  /* leave at the head */
580  phead++ ;
581  }
582  else
583  {
584  /* swap with the tail */
585  ptail-- ;
586  Li [phead] = Li [ptail] ;
587  Li [ptail] = i ;
588  x = Lx [phead] ;
589  Lx [phead] = Lx [ptail] ;
590  Lx [ptail] = x ;
591  }
592  }
593 
594  /* set Lpend to one past the last entry in the
595  * first part of the column of L. Entries in
596  * Li [0 ... Lpend [j]-1] are the only part of
597  * column j of L that needs to be scanned in the DFS.
598  * Lpend [j] was EMPTY; setting it >= 0 also flags
599  * column j as pruned. */
600  Lpend [j] = ptail ;
601 
602 #ifndef NDEBUG
603  {
604  Int p3 ;
605  for (p3 = 0 ; p3 < Llen [j] ; p3++)
606  {
607  if (p3 == Lpend [j]) PRINTF (("----\n")) ;
608  PRINTF (("after: %i pivotal: %d\n", Li [p3],
609  Pinv [Li [p3]] >= 0)) ;
610  }
611  }
612 #endif
613 
614  break ;
615  }
616  }
617  }
618  }
619 }
620 
621 
622 /* ========================================================================== */
623 /* === KLU_kernel =========================================================== */
624 /* ========================================================================== */
625 
626 size_t KLU_kernel /* final size of LU on output */
627 (
628  /* input, not modified */
629  Int n, /* A is n-by-n */
630  Int Ap [ ], /* size n+1, column pointers for A */
631  Int Ai [ ], /* size nz = Ap [n], row indices for A */
632  Entry Ax [ ], /* size nz, values of A */
633  Int Q [ ], /* size n, optional input permutation */
634  size_t lusize, /* initial size of LU on input */
635 
636  /* output, not defined on input */
637  Int Pinv [ ], /* size n, inverse row permutation, where Pinv [i] = k if
638  * row i is the kth pivot row */
639  Int P [ ], /* size n, row permutation, where P [k] = i if row i is the
640  * kth pivot row. */
641  Unit **p_LU, /* LU array, size lusize on input */
642  Entry Udiag [ ], /* size n, diagonal of U */
643  Int Llen [ ], /* size n, column length of L */
644  Int Ulen [ ], /* size n, column length of U */
645  Int Lip [ ], /* size n, column pointers for L */
646  Int Uip [ ], /* size n, column pointers for U */
647  Int *lnz, /* size of L*/
648  Int *unz, /* size of U*/
649  /* workspace, not defined on input */
650  Entry X [ ], /* size n, undefined on input, zero on output */
651 
652  /* workspace, not defined on input or output */
653  Int Stack [ ], /* size n */
654  Int Flag [ ], /* size n */
655  Int Ap_pos [ ], /* size n */
656 
657  /* other workspace: */
658  Int Lpend [ ], /* size n workspace, for pruning only */
659 
660  /* inputs, not modified on output */
661  Int k1, /* the block of A is from k1 to k2-1 */
662  Int PSinv [ ], /* inverse of P from symbolic factorization */
663  double Rs [ ], /* scale factors for A */
664 
665  /* inputs, modified on output */
666  Int Offp [ ], /* off-diagonal matrix (modified by this routine) */
667  Int Offi [ ],
668  Entry Offx [ ],
669  /* --------------- */
670  KLU_common *Common
671 )
672 {
673  Entry pivot ;
674  double abs_pivot, xsize, nunits, tol, memgrow ;
675  Entry *Ux ;
676  Int *Li, *Ui ;
677  Unit *LU ; /* LU factors (pattern and values) */
678  Int k, p, i, j, pivrow, kbar, diagrow, firstrow, lup, top, scale, len ;
679  size_t newlusize ;
680 
681 #ifndef NDEBUG
682  Entry *Lx ;
683 #endif
684 
685  ASSERT (Common != NULL) ;
686  scale = Common->scale ;
687  tol = Common->tol ;
688  memgrow = Common->memgrow ;
689  *lnz = 0 ;
690  *unz = 0 ;
691 
692  /* ---------------------------------------------------------------------- */
693  /* get initial Li, Lx, Ui, and Ux */
694  /* ---------------------------------------------------------------------- */
695 
696  PRINTF (("input: lusize %d \n", lusize)) ;
697  ASSERT (lusize > 0) ;
698  LU = *p_LU ;
699 
700  /* ---------------------------------------------------------------------- */
701  /* initializations */
702  /* ---------------------------------------------------------------------- */
703 
704  firstrow = 0 ;
705  lup = 0 ;
706 
707  for (k = 0 ; k < n ; k++)
708  {
709  /* X [k] = 0 ; */
710  CLEAR (X [k]) ;
711  Flag [k] = EMPTY ;
712  Lpend [k] = EMPTY ; /* flag k as not pruned */
713  }
714 
715  /* ---------------------------------------------------------------------- */
716  /* mark all rows as non-pivotal and determine initial diagonal mapping */
717  /* ---------------------------------------------------------------------- */
718 
719  /* PSinv does the symmetric permutation, so don't do it here */
720  for (k = 0 ; k < n ; k++)
721  {
722  P [k] = k ;
723  Pinv [k] = FLIP (k) ; /* mark all rows as non-pivotal */
724  }
725  /* initialize the construction of the off-diagonal matrix */
726  Offp [0] = 0 ;
727 
728  /* P [k] = row means that UNFLIP (Pinv [row]) = k, and visa versa.
729  * If row is pivotal, then Pinv [row] >= 0. A row is initially "flipped"
730  * (Pinv [k] < EMPTY), and then marked "unflipped" when it becomes
731  * pivotal. */
732 
733 #ifndef NDEBUG
734  for (k = 0 ; k < n ; k++)
735  {
736  PRINTF (("Initial P [%d] = %d\n", k, P [k])) ;
737  }
738 #endif
739 
740  /* ---------------------------------------------------------------------- */
741  /* factorize */
742  /* ---------------------------------------------------------------------- */
743 
744  for (k = 0 ; k < n ; k++)
745  {
746 
747  PRINTF (("\n\n==================================== k: %d\n", k)) ;
748 
749  /* ------------------------------------------------------------------ */
750  /* determine if LU factors have grown too big */
751  /* ------------------------------------------------------------------ */
752 
753  /* (n - k) entries for L and k entries for U */
754  nunits = DUNITS (Int, n - k) + DUNITS (Int, k) +
755  DUNITS (Entry, n - k) + DUNITS (Entry, k) ;
756 
757  /* LU can grow by at most 'nunits' entries if the column is dense */
758  PRINTF (("lup %d lusize %g lup+nunits: %g\n", lup, (double) lusize,
759  lup+nunits));
760  xsize = ((double) lup) + nunits ;
761  if (xsize > (double) lusize)
762  {
763  /* check here how much to grow */
764  xsize = (memgrow * ((double) lusize) + 4*n + 1) ;
765  if (INT_OVERFLOW (xsize))
766  {
767  PRINTF (("Matrix is too large (Int overflow)\n")) ;
768  Common->status = KLU_TOO_LARGE ;
769  return (lusize) ;
770  }
771  newlusize = (size_t) ( memgrow * lusize + 2*n + 1 ) ;
772  /* Future work: retry mechanism in case of malloc failure */
773  LU = KLU_realloc (newlusize, lusize, sizeof (Unit), LU, Common) ;
774  Common->nrealloc++ ;
775  *p_LU = LU ;
776  if (Common->status == KLU_OUT_OF_MEMORY)
777  {
778  PRINTF (("Matrix is too large (LU)\n")) ;
779  return (lusize) ;
780  }
781  lusize = newlusize ;
782  PRINTF (("inc LU to %d done\n", lusize)) ;
783  }
784 
785  /* ------------------------------------------------------------------ */
786  /* start the kth column of L and U */
787  /* ------------------------------------------------------------------ */
788 
789  Lip [k] = lup ;
790 
791  /* ------------------------------------------------------------------ */
792  /* compute the nonzero pattern of the kth column of L and U */
793  /* ------------------------------------------------------------------ */
794 
795 #ifndef NDEBUG
796  for (i = 0 ; i < n ; i++)
797  {
798  ASSERT (Flag [i] < k) ;
799  /* ASSERT (X [i] == 0) ; */
800  ASSERT (IS_ZERO (X [i])) ;
801  }
802 #endif
803 
804  top = lsolve_symbolic (n, k, Ap, Ai, Q, Pinv, Stack, Flag,
805  Lpend, Ap_pos, LU, lup, Llen, Lip, k1, PSinv) ;
806 
807 #ifndef NDEBUG
808  PRINTF (("--- in U:\n")) ;
809  for (p = top ; p < n ; p++)
810  {
811  PRINTF (("pattern of X for U: %d : %d pivot row: %d\n",
812  p, Stack [p], Pinv [Stack [p]])) ;
813  ASSERT (Flag [Stack [p]] == k) ;
814  }
815  PRINTF (("--- in L:\n")) ;
816  Li = (Int *) (LU + Lip [k]);
817  for (p = 0 ; p < Llen [k] ; p++)
818  {
819  PRINTF (("pattern of X in L: %d : %d pivot row: %d\n",
820  p, Li [p], Pinv [Li [p]])) ;
821  ASSERT (Flag [Li [p]] == k) ;
822  }
823  p = 0 ;
824  for (i = 0 ; i < n ; i++)
825  {
826  ASSERT (Flag [i] <= k) ;
827  if (Flag [i] == k) p++ ;
828  }
829 #endif
830 
831  /* ------------------------------------------------------------------ */
832  /* get the column of the matrix to factorize and scatter into X */
833  /* ------------------------------------------------------------------ */
834 
835  construct_column (k, Ap, Ai, Ax, Q, X,
836  k1, PSinv, Rs, scale, Offp, Offi, Offx) ;
837 
838  /* ------------------------------------------------------------------ */
839  /* compute the numerical values of the kth column (s = L \ A (:,k)) */
840  /* ------------------------------------------------------------------ */
841 
842  lsolve_numeric (Pinv, LU, Stack, Lip, top, n, Llen, X) ;
843 
844 #ifndef NDEBUG
845  for (p = top ; p < n ; p++)
846  {
847  PRINTF (("X for U %d : ", Stack [p])) ;
848  PRINT_ENTRY (X [Stack [p]]) ;
849  }
850  Li = (Int *) (LU + Lip [k]) ;
851  for (p = 0 ; p < Llen [k] ; p++)
852  {
853  PRINTF (("X for L %d : ", Li [p])) ;
854  PRINT_ENTRY (X [Li [p]]) ;
855  }
856 #endif
857 
858  /* ------------------------------------------------------------------ */
859  /* partial pivoting with diagonal preference */
860  /* ------------------------------------------------------------------ */
861 
862  /* determine what the "diagonal" is */
863  diagrow = P [k] ; /* might already be pivotal */
864  PRINTF (("k %d, diagrow = %d, UNFLIP (diagrow) = %d\n",
865  k, diagrow, UNFLIP (diagrow))) ;
866 
867  /* find a pivot and scale the pivot column */
868  if (!lpivot (diagrow, &pivrow, &pivot, &abs_pivot, tol, X, LU, Lip,
869  Llen, k, n, Pinv, &firstrow, Common))
870  {
871  /* matrix is structurally or numerically singular */
872  Common->status = KLU_SINGULAR ;
873  if (Common->numerical_rank == EMPTY)
874  {
875  Common->numerical_rank = k+k1 ;
876  Common->singular_col = Q [k+k1] ;
877  }
878  if (Common->halt_if_singular)
879  {
880  /* do not continue the factorization */
881  return (lusize) ;
882  }
883  }
884 
885  /* we now have a valid pivot row, even if the column has NaN's or
886  * has no entries on or below the diagonal at all. */
887  PRINTF (("\nk %d : Pivot row %d : ", k, pivrow)) ;
888  PRINT_ENTRY (pivot) ;
889  ASSERT (pivrow >= 0 && pivrow < n) ;
890  ASSERT (Pinv [pivrow] < 0) ;
891 
892  /* set the Uip pointer */
893  Uip [k] = Lip [k] + UNITS (Int, Llen [k]) + UNITS (Entry, Llen [k]) ;
894 
895  /* move the lup pointer to the position where indices of U
896  * should be stored */
897  lup += UNITS (Int, Llen [k]) + UNITS (Entry, Llen [k]) ;
898 
899  Ulen [k] = n - top ;
900 
901  /* extract Stack [top..n-1] to Ui and the values to Ux and clear X */
902  GET_POINTER (LU, Uip, Ulen, Ui, Ux, k, len) ;
903  for (p = top, i = 0 ; p < n ; p++, i++)
904  {
905  j = Stack [p] ;
906  Ui [i] = Pinv [j] ;
907  Ux [i] = X [j] ;
908  CLEAR (X [j]) ;
909  }
910 
911  /* position the lu index at the starting point for next column */
912  lup += UNITS (Int, Ulen [k]) + UNITS (Entry, Ulen [k]) ;
913 
914  /* U(k,k) = pivot */
915  Udiag [k] = pivot ;
916 
917  /* ------------------------------------------------------------------ */
918  /* log the pivot permutation */
919  /* ------------------------------------------------------------------ */
920 
921  ASSERT (UNFLIP (Pinv [diagrow]) < n) ;
922  ASSERT (P [UNFLIP (Pinv [diagrow])] == diagrow) ;
923 
924  if (pivrow != diagrow)
925  {
926  /* an off-diagonal pivot has been chosen */
927  Common->noffdiag++ ;
928  PRINTF ((">>>>>>>>>>>>>>>>> pivrow %d k %d off-diagonal\n",
929  pivrow, k)) ;
930  if (Pinv [diagrow] < 0)
931  {
932  /* the former diagonal row index, diagrow, has not yet been
933  * chosen as a pivot row. Log this diagrow as the "diagonal"
934  * entry in the column kbar for which the chosen pivot row,
935  * pivrow, was originally logged as the "diagonal" */
936  kbar = FLIP (Pinv [pivrow]) ;
937  P [kbar] = diagrow ;
938  Pinv [diagrow] = FLIP (kbar) ;
939  }
940  }
941  P [k] = pivrow ;
942  Pinv [pivrow] = k ;
943 
944 #ifndef NDEBUG
945  for (i = 0 ; i < n ; i++) { ASSERT (IS_ZERO (X [i])) ;}
946  GET_POINTER (LU, Uip, Ulen, Ui, Ux, k, len) ;
947  for (p = 0 ; p < len ; p++)
948  {
949  PRINTF (("Column %d of U: %d : ", k, Ui [p])) ;
950  PRINT_ENTRY (Ux [p]) ;
951  }
952  GET_POINTER (LU, Lip, Llen, Li, Lx, k, len) ;
953  for (p = 0 ; p < len ; p++)
954  {
955  PRINTF (("Column %d of L: %d : ", k, Li [p])) ;
956  PRINT_ENTRY (Lx [p]) ;
957  }
958 #endif
959 
960  /* ------------------------------------------------------------------ */
961  /* symmetric pruning */
962  /* ------------------------------------------------------------------ */
963 
964  prune (Lpend, Pinv, k, pivrow, LU, Uip, Lip, Ulen, Llen) ;
965 
966  *lnz += Llen [k] + 1 ; /* 1 added to lnz for diagonal */
967  *unz += Ulen [k] + 1 ; /* 1 added to unz for diagonal */
968  }
969 
970  /* ---------------------------------------------------------------------- */
971  /* finalize column pointers for L and U, and put L in the pivotal order */
972  /* ---------------------------------------------------------------------- */
973 
974  for (p = 0 ; p < n ; p++)
975  {
976  Li = (Int *) (LU + Lip [p]) ;
977  for (i = 0 ; i < Llen [p] ; i++)
978  {
979  Li [i] = Pinv [Li [i]] ;
980  }
981  }
982 
983 #ifndef NDEBUG
984  for (i = 0 ; i < n ; i++)
985  {
986  PRINTF (("P [%d] = %d Pinv [%d] = %d\n", i, P [i], i, Pinv [i])) ;
987  }
988  for (i = 0 ; i < n ; i++)
989  {
990  ASSERT (Pinv [i] >= 0 && Pinv [i] < n) ;
991  ASSERT (P [i] >= 0 && P [i] < n) ;
992  ASSERT (P [Pinv [i]] == i) ;
993  ASSERT (IS_ZERO (X [i])) ;
994  }
995 #endif
996 
997  /* ---------------------------------------------------------------------- */
998  /* shrink the LU factors to just the required size */
999  /* ---------------------------------------------------------------------- */
1000 
1001  newlusize = lup ;
1002  ASSERT ((size_t) newlusize <= lusize) ;
1003 
1004  /* this cannot fail, since the block is descreasing in size */
1005  LU = KLU_realloc (newlusize, lusize, sizeof (Unit), LU, Common) ;
1006  *p_LU = LU ;
1007  return (newlusize) ;
1008 }
#define GET_POINTER(LU, Xip, Xlen, Xi, Xx, k, xlen)
#define PRINT_ENTRY(a)
#define EMPTY
#define Int
#define FALSE
#define P(k)
double Unit
#define KLU_OUT_OF_MEMORY
#define NULL
static void prune(Int Lpend[], Int Pinv[], Int k, Int pivrow, Unit *LU, Int Uip[], Int Lip[], Int Ulen[], Int Llen[])
#define CLEAR(c)
#define KLU_TOO_LARGE
#define ASSERT(expression)
static Int lpivot(Int diagrow, Int *p_pivrow, Entry *p_pivot, double *p_abs_pivot, double tol, Entry X[], Unit *LU, Int Lip[], Int Llen[], Int k, Int n, Int Pinv[], Int *p_firstrow, KLU_common *Common)
#define FLIP(i)
size_t KLU_kernel(Int n, Int Ap[], Int Ai[], Entry Ax[], Int Q[], size_t lusize, Int Pinv[], Int P[], Unit **p_LU, Entry Udiag[], Int Llen[], Int Ulen[], Int Lip[], Int Uip[], Int *lnz, Int *unz, Entry X[], Int Stack[], Int Flag[], Int Ap_pos[], Int Lpend[], Int k1, Int PSinv[], double Rs[], Int Offp[], Int Offi[], Entry Offx[], KLU_common *Common)
#define MULT_SUB(c, a, b)
#define KLU_realloc
#define UNFLIP(i)
#define IS_ZERO(x)
#define INT_OVERFLOW(x)
#define SCALE_DIV(c, s)
#define DIV(c, a, b)
static void construct_column(Int k, Int Ap[], Int Ai[], Entry Ax[], Int Q[], Entry X[], Int k1, Int PSinv[], double Rs[], Int scale, Int Offp[], Int Offi[], Entry Offx[])
#define KLU_common
#define DUNITS(type, n)
#define KLU_SINGULAR
#define UNITS(type, n)
#define Entry
#define PRINTF(params)
static void lsolve_numeric(Int Pinv[], Unit *LU, Int Stack[], Int Lip[], Int top, Int n, Int Llen[], Entry X[])
#define TRUE
static Int lsolve_symbolic(Int n, Int k, Int Ap[], Int Ai[], Int Q[], Int Pinv[], Int Stack[], Int Flag[], Int Lpend[], Int Ap_pos[], Unit LU[], Int lup, Int Llen[], Int Lip[], Int k1, Int PSinv[])
#define ABS(s, a)
static Int dfs(Int j, Int k, Int Pinv[], Int Llen[], Int Lip[], Int Stack[], Int Flag[], Int Lpend[], Int top, Unit LU[], Int *Lik, Int *plength, Int Ap_pos[])