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