Amesos Package Browser (Single Doxygen Collection)  Development
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
amesos_klu_impl.c
Go to the documentation of this file.
1 /* ========================================================================== */
2 /* === klu ================================================================== */
3 /* ========================================================================== */
4 
5 /* KLU: factorizes P*A into L*U, using the Gilbert-Peierls algorithm [1], with
6  * optional symmetric pruning by Eisenstat and Liu [2]. The code is by Tim
7  * Davis. This algorithm is what appears as the default sparse LU routine in
8  * MATLAB version 6.0, and still appears in MATLAB 6.5 as [L,U,P] = lu (A).
9  * Note that no column ordering is provided (see COLAMD or AMD for suitable
10  * orderings). SuperLU is based on this algorithm, except that it adds the
11  * use of dense matrix operations on "supernodes" (adjacent columns with
12  * identical). This code doesn't use supernodes, thus its name ("Kent" LU,
13  * as in "Clark Kent", in contrast with Super-LU...). This algorithm is slower
14  * than SuperLU and UMFPACK for large matrices with lots of nonzeros in their
15  * factors (such as for most finite-element problems). However, for matrices
16  * with very sparse LU factors, this algorithm is typically faster than both
17  * SuperLU and UMFPACK, since in this case there is little chance to exploit
18  * dense matrix kernels (the BLAS).
19  *
20  * Only one block of A is factorized, in the BTF form. The input n is the
21  * size of the block; k1 is the first row and column in the block.
22  *
23  * NOTE: no error checking is done on the inputs. This version is not meant to
24  * be called directly by the user. Use klu_factor instead.
25  *
26  * No fill-reducing ordering is provided. The ordering quality of
27  * klu_kernel_factor is the responsibility of the caller. The input A must
28  * pre-permuted to reduce fill-in, or fill-reducing input permutation Q must
29  * be provided.
30  *
31  * The input matrix A must be in compressed-column form, with either sorted
32  * or unsorted row indices. Row indices for column j of A is in
33  * Ai [Ap [j] ... Ap [j+1]-1] and the same range of indices in Ax holds the
34  * numerical values. No duplicate entries are allowed.
35  *
36  * Copyright 2004-2007, Tim Davis. All rights reserved. See the README
37  * file for details on permitted use. Note that no code from The MathWorks,
38  * Inc, or from SuperLU, or from any other source appears here. The code is
39  * written from scratch, from the algorithmic description in Gilbert & Peierls'
40  * and Eisenstat & Liu's journal papers [1,2].
41  *
42  * If an input permutation Q is provided, the factorization L*U = A (P,Q)
43  * is computed, where P is determined by partial pivoting, and Q is the input
44  * ordering. If the pivot tolerance is less than 1, the "diagonal" entry that
45  * KLU attempts to choose is the diagonal of A (Q,Q). In other words, the
46  * input permutation is applied symmetrically to the input matrix. The output
47  * permutation P includes both the partial pivoting ordering and the input
48  * permutation. If Q is NULL, then it is assumed to be the identity
49  * permutation. Q is not modified.
50  *
51  * [1] Gilbert, J. R. and Peierls, T., "Sparse Partial Pivoting in Time
52  * Proportional to Arithmetic Operations," SIAM J. Sci. Stat. Comp.,
53  * vol 9, pp. 862-874, 1988.
54  * [2] Eisenstat, S. C. and Liu, J. W. H., "Exploiting Structural Symmetry in
55  * Unsymmetric Sparse Symbolic Factorization," SIAM J. Matrix Analysis &
56  * Applic., vol 13, pp. 202-211, 1992.
57  */
58 
59 /* ========================================================================== */
60 
61 #include "amesos_klu_internal.h"
62 
63 size_t KLU_kernel_factor /* 0 if failure, size of LU if OK */
64 (
65  /* inputs, not modified */
66  Int n, /* A is n-by-n. n must be > 0. */
67  Int Ap [ ], /* size n+1, column pointers for A */
68  Int Ai [ ], /* size nz = Ap [n], row indices for A */
69  Entry Ax [ ], /* size nz, values of A */
70  Int Q [ ], /* size n, optional column permutation */
71  double Lsize, /* estimate of number of nonzeros in L */
72 
73  /* outputs, not defined on input */
74  Unit **p_LU, /* row indices and values of L and U */
75  Entry Udiag [ ], /* size n, diagonal of U */
76  Int Llen [ ], /* size n, column length of L */
77  Int Ulen [ ], /* size n, column length of U */
78  Int Lip [ ], /* size n, column pointers for L */
79  Int Uip [ ], /* size n, column pointers for U */
80  Int P [ ], /* row permutation, size n */
81  Int *lnz, /* size of L */
82  Int *unz, /* size of U */
83 
84  /* workspace, undefined on input */
85  Entry *X, /* size n double's, zero on output */
86  Int *Work, /* size 5n Int's */
87 
88  /* inputs, not modified on output */
89  Int k1, /* the block of A is from k1 to k2-1 */
90  Int PSinv [ ], /* inverse of P from symbolic factorization */
91  double Rs [ ], /* scale factors for A */
92 
93  /* inputs, modified on output */
94  Int Offp [ ], /* off-diagonal matrix (modified by this routine) */
95  Int Offi [ ],
96  Entry Offx [ ],
97  /* --------------- */
98  KLU_common *Common
99 )
100 {
101  double maxlnz, dunits ;
102  Unit *LU ;
103  Int *Pinv, *Lpend, *Stack, *Flag, *Ap_pos, *W ;
104  Int lsize, usize, anz, ok ;
105  size_t lusize ;
106  ASSERT (Common != NULL) ;
107 
108  /* ---------------------------------------------------------------------- */
109  /* get control parameters, or use defaults */
110  /* ---------------------------------------------------------------------- */
111 
112  n = MAX (1, n) ;
113  anz = Ap [n+k1] - Ap [k1] ;
114 
115  if (Lsize <= 0)
116  {
117  Lsize = -Lsize ;
118  Lsize = MAX (Lsize, 1.0) ;
119  lsize = (int) ( Lsize * anz + n ) ;
120  }
121  else
122  {
123  lsize = (int) Lsize ;
124  }
125 
126  usize = lsize ;
127 
128  lsize = MAX (n+1, lsize) ;
129  usize = MAX (n+1, usize) ;
130 
131  maxlnz = (((double) n) * ((double) n) + ((double) n)) / 2. ;
132  maxlnz = MIN (maxlnz, ((double) INT_MAX)) ;
133  lsize = (int) ( MIN (maxlnz, lsize) ) ;
134  usize = (int) ( MIN (maxlnz, usize) ) ;
135 
136  PRINTF (("Welcome to klu: n %d anz %d k1 %d lsize %d usize %d maxlnz %g\n",
137  n, anz, k1, lsize, usize, maxlnz)) ;
138 
139  /* ---------------------------------------------------------------------- */
140  /* allocate workspace and outputs */
141  /* ---------------------------------------------------------------------- */
142 
143  /* return arguments are not yet assigned */
144  *p_LU = (Unit *) NULL ;
145 
146  /* these computations are safe from size_t overflow */
147  W = Work ;
148  Pinv = (Int *) W ; W += n ;
149  Stack = (Int *) W ; W += n ;
150  Flag = (Int *) W ; W += n ;
151  Lpend = (Int *) W ; W += n ;
152  Ap_pos = (Int *) W ; W += n ;
153 
154  dunits = DUNITS (Int, lsize) + DUNITS (Entry, lsize) +
155  DUNITS (Int, usize) + DUNITS (Entry, usize) ;
156  lusize = (size_t) dunits ;
157  ok = !INT_OVERFLOW (dunits) ;
158  LU = ok ? KLU_malloc (lusize, sizeof (Unit), Common) : NULL ;
159  if (LU == NULL)
160  {
161  /* out of memory, or problem too large */
162  Common->status = KLU_OUT_OF_MEMORY ;
163  lusize = 0 ;
164  return (lusize) ;
165  }
166 
167  /* ---------------------------------------------------------------------- */
168  /* factorize */
169  /* ---------------------------------------------------------------------- */
170 
171  /* with pruning, and non-recursive depth-first-search */
172  lusize = KLU_kernel (n, Ap, Ai, Ax, Q, lusize,
173  Pinv, P, &LU, Udiag, Llen, Ulen, Lip, Uip, lnz, unz,
174  X, Stack, Flag, Ap_pos, Lpend,
175  k1, PSinv, Rs, Offp, Offi, Offx, Common) ;
176 
177  /* ---------------------------------------------------------------------- */
178  /* return LU factors, or return nothing if an error occurred */
179  /* ---------------------------------------------------------------------- */
180 
181  if (Common->status < KLU_OK)
182  {
183  LU = KLU_free (LU, lusize, sizeof (Unit), Common) ;
184  lusize = 0 ;
185  }
186  *p_LU = LU ;
187  PRINTF ((" in klu noffdiag %d\n", Common->noffdiag)) ;
188  return (lusize) ;
189 }
190 
191 
192 /* ========================================================================== */
193 /* === KLU_lsolve =========================================================== */
194 /* ========================================================================== */
195 
196 /* Solve Lx=b. Assumes L is unit lower triangular and where the unit diagonal
197  * entry is NOT stored. Overwrites B with the solution X. B is n-by-nrhs
198  * and is stored in ROW form with row dimension nrhs. nrhs must be in the
199  * range 1 to 4. */
200 
201 void KLU_lsolve
202 (
203  /* inputs, not modified: */
204  Int n,
205  Int Lip [ ],
206  Int Llen [ ],
207  Unit LU [ ],
208  Int nrhs,
209  /* right-hand-side on input, solution to Lx=b on output */
210  Entry X [ ]
211 )
212 {
213  Entry x [4], lik ;
214  Int *Li ;
215  Entry *Lx ;
216  Int k, p, len, i ;
217 
218  switch (nrhs)
219  {
220 
221  case 1:
222  for (k = 0 ; k < n ; k++)
223  {
224  x [0] = X [k] ;
225  if (x[0] == 0.0) continue;
226  GET_POINTER (LU, Lip, Llen, Li, Lx, k, len) ;
227  /* unit diagonal of L is not stored*/
228  for (p = 0 ; p < len ; p++)
229  {
230  /* X [Li [p]] -= Lx [p] * x [0] ; */
231  MULT_SUB (X [Li [p]], Lx [p], x [0]) ;
232  }
233  }
234  break ;
235 
236  case 2:
237 
238  for (k = 0 ; k < n ; k++)
239  {
240  x [0] = X [2*k ] ;
241  x [1] = X [2*k + 1] ;
242  if (x[0] == 0.0 && x[1] == 0.0) continue;
243  GET_POINTER (LU, Lip, Llen, Li, Lx, k, len) ;
244  for (p = 0 ; p < len ; p++)
245  {
246  i = Li [p] ;
247  lik = Lx [p] ;
248  MULT_SUB (X [2*i], lik, x [0]) ;
249  MULT_SUB (X [2*i + 1], lik, x [1]) ;
250  }
251  }
252  break ;
253 
254  case 3:
255 
256  for (k = 0 ; k < n ; k++)
257  {
258  x [0] = X [3*k ] ;
259  x [1] = X [3*k + 1] ;
260  x [2] = X [3*k + 2] ;
261  if (x[0] == 0.0 && x[1] == 0.0 && x[2] == 0.0) continue;
262  GET_POINTER (LU, Lip, Llen, Li, Lx, k, len) ;
263  for (p = 0 ; p < len ; p++)
264  {
265  i = Li [p] ;
266  lik = Lx [p] ;
267  MULT_SUB (X [3*i], lik, x [0]) ;
268  MULT_SUB (X [3*i + 1], lik, x [1]) ;
269  MULT_SUB (X [3*i + 2], lik, x [2]) ;
270  }
271  }
272  break ;
273 
274  case 4:
275 
276  for (k = 0 ; k < n ; k++)
277  {
278  x [0] = X [4*k ] ;
279  x [1] = X [4*k + 1] ;
280  x [2] = X [4*k + 2] ;
281  x [3] = X [4*k + 3] ;
282  if (x[0] == 0.0 && x[1] == 0.0 && x[2] == 0.0 && x[3] == 0.0) continue;
283  GET_POINTER (LU, Lip, Llen, Li, Lx, k, len) ;
284  for (p = 0 ; p < len ; p++)
285  {
286  i = Li [p] ;
287  lik = Lx [p] ;
288  MULT_SUB (X [4*i], lik, x [0]) ;
289  MULT_SUB (X [4*i + 1], lik, x [1]) ;
290  MULT_SUB (X [4*i + 2], lik, x [2]) ;
291  MULT_SUB (X [4*i + 3], lik, x [3]) ;
292  }
293  }
294  break ;
295 
296  }
297 }
298 
299 /* ========================================================================== */
300 /* === KLU_usolve =========================================================== */
301 /* ========================================================================== */
302 
303 /* Solve Ux=b. Assumes U is non-unit upper triangular and where the diagonal
304  * entry is NOT stored. Overwrites B with the solution X. B is n-by-nrhs
305  * and is stored in ROW form with row dimension nrhs. nrhs must be in the
306  * range 1 to 4. */
307 
308 void KLU_usolve
309 (
310  /* inputs, not modified: */
311  Int n,
312  Int Uip [ ],
313  Int Ulen [ ],
314  Unit LU [ ],
315  Entry Udiag [ ],
316  Int nrhs,
317  /* right-hand-side on input, solution to Ux=b on output */
318  Entry X [ ]
319 )
320 {
321  Entry x [4], uik, ukk ;
322  Int *Ui ;
323  Entry *Ux ;
324  Int k, p, len, i ;
325 
326  switch (nrhs)
327  {
328 
329  case 1:
330 
331  for (k = n-1 ; k >= 0 ; k--)
332  {
333  GET_POINTER (LU, Uip, Ulen, Ui, Ux, k, len) ;
334  /* x [0] = X [k] / Udiag [k] ; */
335  if (X [k] == 0.0) continue;
336  DIV (x [0], X [k], Udiag [k]) ;
337  X [k] = x [0] ;
338  for (p = 0 ; p < len ; p++)
339  {
340  /* X [Ui [p]] -= Ux [p] * x [0] ; */
341  MULT_SUB (X [Ui [p]], Ux [p], x [0]) ;
342 
343  }
344  }
345 
346  break ;
347 
348  case 2:
349 
350  for (k = n-1 ; k >= 0 ; k--)
351  {
352  GET_POINTER (LU, Uip, Ulen, Ui, Ux, k, len) ;
353  ukk = Udiag [k] ;
354  /* x [0] = X [2*k ] / ukk ;
355  x [1] = X [2*k + 1] / ukk ; */
356  if (X [2*k] == 0.0 && X [2*k + 1] == 0.0) continue;
357  DIV (x [0], X [2*k], ukk) ;
358  DIV (x [1], X [2*k + 1], ukk) ;
359 
360  X [2*k ] = x [0] ;
361  X [2*k + 1] = x [1] ;
362  for (p = 0 ; p < len ; p++)
363  {
364  i = Ui [p] ;
365  uik = Ux [p] ;
366  /* X [2*i ] -= uik * x [0] ;
367  X [2*i + 1] -= uik * x [1] ; */
368  MULT_SUB (X [2*i], uik, x [0]) ;
369  MULT_SUB (X [2*i + 1], uik, x [1]) ;
370  }
371  }
372 
373  break ;
374 
375  case 3:
376 
377  for (k = n-1 ; k >= 0 ; k--)
378  {
379  GET_POINTER (LU, Uip, Ulen, Ui, Ux, k, len) ;
380  ukk = Udiag [k] ;
381 
382  if (X [3*k] == 0.0 && X [3*k + 1] == 0.0 && X [3*k + 2] == 0.0) continue;
383  DIV (x [0], X [3*k], ukk) ;
384  DIV (x [1], X [3*k + 1], ukk) ;
385  DIV (x [2], X [3*k + 2], ukk) ;
386 
387  X [3*k ] = x [0] ;
388  X [3*k + 1] = x [1] ;
389  X [3*k + 2] = x [2] ;
390  for (p = 0 ; p < len ; p++)
391  {
392  i = Ui [p] ;
393  uik = Ux [p] ;
394  MULT_SUB (X [3*i], uik, x [0]) ;
395  MULT_SUB (X [3*i + 1], uik, x [1]) ;
396  MULT_SUB (X [3*i + 2], uik, x [2]) ;
397  }
398  }
399 
400  break ;
401 
402  case 4:
403 
404  for (k = n-1 ; k >= 0 ; k--)
405  {
406  GET_POINTER (LU, Uip, Ulen, Ui, Ux, k, len) ;
407  ukk = Udiag [k] ;
408 
409  if (X [4*k] == 0.0 && X [4*k + 1] == 0.0 && X [4*k + 2] == 0.0 && X [4*k + 3] == 0.0) continue;
410  DIV (x [0], X [4*k], ukk) ;
411  DIV (x [1], X [4*k + 1], ukk) ;
412  DIV (x [2], X [4*k + 2], ukk) ;
413  DIV (x [3], X [4*k + 3], ukk) ;
414 
415  X [4*k ] = x [0] ;
416  X [4*k + 1] = x [1] ;
417  X [4*k + 2] = x [2] ;
418  X [4*k + 3] = x [3] ;
419  for (p = 0 ; p < len ; p++)
420  {
421  i = Ui [p] ;
422  uik = Ux [p] ;
423 
424  MULT_SUB (X [4*i], uik, x [0]) ;
425  MULT_SUB (X [4*i + 1], uik, x [1]) ;
426  MULT_SUB (X [4*i + 2], uik, x [2]) ;
427  MULT_SUB (X [4*i + 3], uik, x [3]) ;
428  }
429  }
430 
431  break ;
432 
433  }
434 }
435 
436 
437 /* ========================================================================== */
438 /* === KLU_ltsolve ========================================================== */
439 /* ========================================================================== */
440 
441 /* Solve L'x=b. Assumes L is unit lower triangular and where the unit diagonal
442  * entry is NOT stored. Overwrites B with the solution X. B is n-by-nrhs
443  * and is stored in ROW form with row dimension nrhs. nrhs must in the
444  * range 1 to 4. */
445 
446 void KLU_ltsolve
447 (
448  /* inputs, not modified: */
449  Int n,
450  Int Lip [ ],
451  Int Llen [ ],
452  Unit LU [ ],
453  Int nrhs,
454 #ifdef COMPLEX
455  Int conj_solve,
456 #endif
457  /* right-hand-side on input, solution to L'x=b on output */
458  Entry X [ ]
459 )
460 {
461  Entry x [4], lik ;
462  Int *Li ;
463  Entry *Lx ;
464  Int k, p, len, i ;
465 
466  switch (nrhs)
467  {
468 
469  case 1:
470 
471  for (k = n-1 ; k >= 0 ; k--)
472  {
473  GET_POINTER (LU, Lip, Llen, Li, Lx, k, len) ;
474  x [0] = X [k] ;
475  for (p = 0 ; p < len ; p++)
476  {
477  if (X[Li[p]] == 0.0 ) continue;
478 #ifdef COMPLEX
479  if (conj_solve)
480  {
481  /* x [0] -= CONJ (Lx [p]) * X [Li [p]] ; */
482  MULT_SUB_CONJ (x [0], X [Li [p]], Lx [p]) ;
483  }
484  else
485 #endif
486  {
487  /*x [0] -= Lx [p] * X [Li [p]] ;*/
488  MULT_SUB (x [0], Lx [p], X [Li [p]]) ;
489  }
490  }
491  X [k] = x [0] ;
492  }
493  break ;
494 
495  case 2:
496 
497  for (k = n-1 ; k >= 0 ; k--)
498  {
499  x [0] = X [2*k ] ;
500  x [1] = X [2*k + 1] ;
501  GET_POINTER (LU, Lip, Llen, Li, Lx, k, len) ;
502  for (p = 0 ; p < len ; p++)
503  {
504  i = Li [p] ;
505  if (X[2*i] == 0.0 && X[2*i + 1] == 0.0) continue;
506 #ifdef COMPLEX
507  if (conj_solve)
508  {
509  CONJ (lik, Lx [p]) ;
510  }
511  else
512 #endif
513  {
514  lik = Lx [p] ;
515  }
516  MULT_SUB (x [0], lik, X [2*i]) ;
517  MULT_SUB (x [1], lik, X [2*i + 1]) ;
518  }
519  X [2*k ] = x [0] ;
520  X [2*k + 1] = x [1] ;
521  }
522  break ;
523 
524  case 3:
525 
526  for (k = n-1 ; k >= 0 ; k--)
527  {
528  x [0] = X [3*k ] ;
529  x [1] = X [3*k + 1] ;
530  x [2] = X [3*k + 2] ;
531  GET_POINTER (LU, Lip, Llen, Li, Lx, k, len) ;
532  for (p = 0 ; p < len ; p++)
533  {
534  i = Li [p] ;
535  if (X[3*i] == 0.0 && X[3*i + 1] == 0.0 && X[3*i + 2] == 0.0) continue;
536 #ifdef COMPLEX
537  if (conj_solve)
538  {
539  CONJ (lik, Lx [p]) ;
540  }
541  else
542 #endif
543  {
544  lik = Lx [p] ;
545  }
546  MULT_SUB (x [0], lik, X [3*i]) ;
547  MULT_SUB (x [1], lik, X [3*i + 1]) ;
548  MULT_SUB (x [2], lik, X [3*i + 2]) ;
549  }
550  X [3*k ] = x [0] ;
551  X [3*k + 1] = x [1] ;
552  X [3*k + 2] = x [2] ;
553  }
554  break ;
555 
556  case 4:
557 
558  for (k = n-1 ; k >= 0 ; k--)
559  {
560  x [0] = X [4*k ] ;
561  x [1] = X [4*k + 1] ;
562  x [2] = X [4*k + 2] ;
563  x [3] = X [4*k + 3] ;
564  GET_POINTER (LU, Lip, Llen, Li, Lx, k, len) ;
565  for (p = 0 ; p < len ; p++)
566  {
567  i = Li [p] ;
568  if (X[4*i] == 0.0 && X[4*i + 1] == 0.0 && X[4*i + 2] == 0.0 && X[4*i + 3] == 0.0) continue;
569 #ifdef COMPLEX
570  if (conj_solve)
571  {
572  CONJ (lik, Lx [p]) ;
573  }
574  else
575 #endif
576  {
577  lik = Lx [p] ;
578  }
579  MULT_SUB (x [0], lik, X [4*i]) ;
580  MULT_SUB (x [1], lik, X [4*i + 1]) ;
581  MULT_SUB (x [2], lik, X [4*i + 2]) ;
582  MULT_SUB (x [3], lik, X [4*i + 3]) ;
583  }
584  X [4*k ] = x [0] ;
585  X [4*k + 1] = x [1] ;
586  X [4*k + 2] = x [2] ;
587  X [4*k + 3] = x [3] ;
588  }
589  break ;
590  }
591 }
592 
593 
594 /* ========================================================================== */
595 /* === KLU_utsolve ========================================================== */
596 /* ========================================================================== */
597 
598 /* Solve U'x=b. Assumes U is non-unit upper triangular and where the diagonal
599  * entry is stored (and appears last in each column of U). Overwrites B
600  * with the solution X. B is n-by-nrhs and is stored in ROW form with row
601  * dimension nrhs. nrhs must be in the range 1 to 4. */
602 
603 void KLU_utsolve
604 (
605  /* inputs, not modified: */
606  Int n,
607  Int Uip [ ],
608  Int Ulen [ ],
609  Unit LU [ ],
610  Entry Udiag [ ],
611  Int nrhs,
612 #ifdef COMPLEX
613  Int conj_solve,
614 #endif
615  /* right-hand-side on input, solution to Ux=b on output */
616  Entry X [ ]
617 )
618 {
619  Entry x [4], uik, ukk ;
620  Int k, p, len, i ;
621  Int *Ui ;
622  Entry *Ux ;
623 
624  switch (nrhs)
625  {
626 
627  case 1:
628 
629  for (k = 0 ; k < n ; k++)
630  {
631  GET_POINTER (LU, Uip, Ulen, Ui, Ux, k, len) ;
632  x [0] = X [k] ;
633  for (p = 0 ; p < len ; p++)
634  {
635  if (X[Ui[p]] == 0.0) continue;
636 #ifdef COMPLEX
637  if (conj_solve)
638  {
639  /* x [0] -= CONJ (Ux [p]) * X [Ui [p]] ; */
640  MULT_SUB_CONJ (x [0], X [Ui [p]], Ux [p]) ;
641  }
642  else
643 #endif
644  {
645  /* x [0] -= Ux [p] * X [Ui [p]] ; */
646  MULT_SUB (x [0], Ux [p], X [Ui [p]]) ;
647  }
648  }
649 #ifdef COMPLEX
650  if (conj_solve)
651  {
652  CONJ (ukk, Udiag [k]) ;
653  }
654  else
655 #endif
656  {
657  ukk = Udiag [k] ;
658  }
659  DIV (X [k], x [0], ukk) ;
660  }
661  break ;
662 
663  case 2:
664 
665  for (k = 0 ; k < n ; k++)
666  {
667  GET_POINTER (LU, Uip, Ulen, Ui, Ux, k, len) ;
668  x [0] = X [2*k ] ;
669  x [1] = X [2*k + 1] ;
670  for (p = 0 ; p < len ; p++)
671  {
672  i = Ui [p] ;
673  if (X[2*i] == 0.0 && X[2*i + 1] == 0.0 ) continue;
674 #ifdef COMPLEX
675  if (conj_solve)
676  {
677  CONJ (uik, Ux [p]) ;
678  }
679  else
680 #endif
681  {
682  uik = Ux [p] ;
683  }
684  MULT_SUB (x [0], uik, X [2*i]) ;
685  MULT_SUB (x [1], uik, X [2*i + 1]) ;
686  }
687 #ifdef COMPLEX
688  if (conj_solve)
689  {
690  CONJ (ukk, Udiag [k]) ;
691  }
692  else
693 #endif
694  {
695  ukk = Udiag [k] ;
696  }
697  DIV (X [2*k], x [0], ukk) ;
698  DIV (X [2*k + 1], x [1], ukk) ;
699  }
700  break ;
701 
702  case 3:
703 
704  for (k = 0 ; k < n ; k++)
705  {
706  GET_POINTER (LU, Uip, Ulen, Ui, Ux, k, len) ;
707  x [0] = X [3*k ] ;
708  x [1] = X [3*k + 1] ;
709  x [2] = X [3*k + 2] ;
710  for (p = 0 ; p < len ; p++)
711  {
712  i = Ui [p] ;
713  if (X[3*i] == 0.0 && X[3*i + 1] == 0.0 && X[3*i + 2] == 0.0 ) continue;
714 #ifdef COMPLEX
715  if (conj_solve)
716  {
717  CONJ (uik, Ux [p]) ;
718  }
719  else
720 #endif
721  {
722  uik = Ux [p] ;
723  }
724  MULT_SUB (x [0], uik, X [3*i]) ;
725  MULT_SUB (x [1], uik, X [3*i + 1]) ;
726  MULT_SUB (x [2], uik, X [3*i + 2]) ;
727  }
728 #ifdef COMPLEX
729  if (conj_solve)
730  {
731  CONJ (ukk, Udiag [k]) ;
732  }
733  else
734 #endif
735  {
736  ukk = Udiag [k] ;
737  }
738  DIV (X [3*k], x [0], ukk) ;
739  DIV (X [3*k + 1], x [1], ukk) ;
740  DIV (X [3*k + 2], x [2], ukk) ;
741  }
742  break ;
743 
744  case 4:
745 
746  for (k = 0 ; k < n ; k++)
747  {
748  GET_POINTER (LU, Uip, Ulen, Ui, Ux, k, len) ;
749  x [0] = X [4*k ] ;
750  x [1] = X [4*k + 1] ;
751  x [2] = X [4*k + 2] ;
752  x [3] = X [4*k + 3] ;
753  for (p = 0 ; p < len ; p++)
754  {
755  i = Ui [p] ;
756  if (X[4*i] == 0.0 && X[4*i + 1] == 0.0 && X[4*i + 2] == 0.0 && X[4*i + 3] == 0.0) continue;
757 #ifdef COMPLEX
758  if (conj_solve)
759  {
760  CONJ (uik, Ux [p]) ;
761  }
762  else
763 #endif
764  {
765  uik = Ux [p] ;
766  }
767  MULT_SUB (x [0], uik, X [4*i]) ;
768  MULT_SUB (x [1], uik, X [4*i + 1]) ;
769  MULT_SUB (x [2], uik, X [4*i + 2]) ;
770  MULT_SUB (x [3], uik, X [4*i + 3]) ;
771  }
772 #ifdef COMPLEX
773  if (conj_solve)
774  {
775  CONJ (ukk, Udiag [k]) ;
776  }
777  else
778 #endif
779  {
780  ukk = Udiag [k] ;
781  }
782  DIV (X [4*k], x [0], ukk) ;
783  DIV (X [4*k + 1], x [1], ukk) ;
784  DIV (X [4*k + 2], x [2], ukk) ;
785  DIV (X [4*k + 3], x [3], ukk) ;
786  }
787  break ;
788  }
789 }
#define GET_POINTER(LU, Xip, Xlen, Xi, Xx, k, xlen)
#define CONJ(a, x)
#define COMPLEX
#define Int
#define KLU_kernel
#define P(k)
void KLU_ltsolve(Int n, Int Lip[], Int Llen[], Unit LU[], Int nrhs, Entry X[])
double Unit
#define MAX(a, b)
#define KLU_OUT_OF_MEMORY
#define NULL
#define ASSERT(expression)
#define MULT_SUB(c, a, b)
void KLU_usolve(Int n, Int Uip[], Int Ulen[], Unit LU[], Entry Udiag[], Int nrhs, Entry X[])
void KLU_utsolve(Int n, Int Uip[], Int Ulen[], Unit LU[], Entry Udiag[], Int nrhs, Entry X[])
#define KLU_malloc
#define MULT_SUB_CONJ(c, a, b)
#define INT_OVERFLOW(x)
size_t KLU_kernel_factor(Int n, Int Ap[], Int Ai[], Entry Ax[], Int Q[], double Lsize, Unit **p_LU, Entry Udiag[], Int Llen[], Int Ulen[], Int Lip[], Int Uip[], Int P[], Int *lnz, Int *unz, Entry *X, Int *Work, Int k1, Int PSinv[], double Rs[], Int Offp[], Int Offi[], Entry Offx[], KLU_common *Common)
#define DIV(c, a, b)
#define KLU_common
void KLU_lsolve(Int n, Int Lip[], Int Llen[], Unit LU[], Int nrhs, Entry X[])
#define DUNITS(type, n)
#define MIN(a, b)
#define Entry
#define PRINTF(params)
int n
#define KLU_free
#define KLU_OK