1
/* ========================================================================== */
2
/* === klu_factor =========================================================== */
3
/* ========================================================================== */
5
/* Factor the matrix, after ordering and analyzing it with klu_analyze
6
* or klu_analyze_given.
9
#include "klu_internal.h"
11
/* ========================================================================== */
12
/* === klu_factor2 ========================================================== */
13
/* ========================================================================== */
15
static void klu_factor2
17
/* inputs, not modified */
18
int Ap [ ], /* size n+1, column pointers */
19
int Ai [ ], /* size nz, row indices */
21
klu_symbolic *Symbolic,
23
/* inputs, modified on output: */
30
int *P, *Q, *R, *Pnum, *Offp, *Offi, *Pblock, *Pinv, *Iwork ;
31
int **Lbip, **Ubip, **Lblen, **Ublen ;
32
Entry *Offx, *Singleton, *X, s ;
33
Unit **LUbx, **Udiag ;
34
int k1, k2, nk, k, block, oldcol, pend, oldrow, n, lnz, unz, p, newrow,
35
nblocks, poff, nzoff, lnz_block, unz_block, scale, max_lnz_block,
38
/* ---------------------------------------------------------------------- */
40
/* ---------------------------------------------------------------------- */
42
/* get the contents of the Symbolic object */
48
nblocks = Symbolic->nblocks ;
49
nzoff = Symbolic->nzoff ;
51
Pnum = Numeric->Pnum ;
52
Offp = Numeric->Offp ;
53
Offi = Numeric->Offi ;
54
Offx = (Entry *) Numeric->Offx ;
55
Singleton = (Entry *) Numeric->Singleton ;
57
Lbip = Numeric->Lbip ;
58
Ubip = Numeric->Ubip ;
59
Lblen = Numeric->Lblen ;
60
Ublen = Numeric->Ublen ;
61
LUbx = (Unit **) Numeric->LUbx ;
62
Udiag = (Unit **) Numeric->Udiag ;
65
Pinv = Numeric->Pinv ;
66
X = (Entry *) Numeric->Xwork ; /* X is of size n */
67
Iwork = Numeric->Iwork ; /* 5*maxblock for klu_factor */
68
/* 1*maxblock for Pblock */
69
Pblock = Iwork + 5*((size_t) Symbolic->maxblock) ;
70
Common->nrealloc = 0 ;
71
scale = Common->scale ;
75
/* compute the inverse of P from symbolic analysis. Will be updated to
76
* become the inverse of the numerical factorization when the factorization
77
* is done, for use in klu_refactor */
79
for (k = 0 ; k < n ; k++)
84
for (k = 0 ; k < n ; k++)
86
ASSERT (P [k] >= 0 && P [k] < n) ;
90
for (k = 0 ; k < n ; k++) ASSERT (Pinv [k] != EMPTY) ;
93
for (block = 0 ; block < nblocks ; block++)
95
/* Singleton [block] = 0 ; */
96
CLEAR (Singleton [block]) ;
101
Common->noffdiag = 0 ;
104
/* ---------------------------------------------------------------------- */
105
/* optionally check input matrix and compute scale factors */
106
/* ---------------------------------------------------------------------- */
110
/* use Pnum as workspace */
111
KLU_scale (scale, n, Ap, Ai, (double *) Ax, Rs, Pnum, Common) ;
112
if (Common->status < KLU_OK)
114
/* matrix is invalid */
122
for (k = 0 ; k < n ; k++) PRINTF (("Rs [%d] %g\n", k, Rs [k])) ;
126
/* ---------------------------------------------------------------------- */
127
/* factor each block using klu */
128
/* ---------------------------------------------------------------------- */
130
for (block = 0 ; block < nblocks ; block++)
133
/* ------------------------------------------------------------------ */
134
/* the block is from rows/columns k1 to k2-1 */
135
/* ------------------------------------------------------------------ */
140
PRINTF (("FACTOR BLOCK %d, k1 %d k2-1 %d nk %d\n", block, k1,k2-1,nk)) ;
145
/* -------------------------------------------------------------- */
147
/* -------------------------------------------------------------- */
151
pend = Ap [oldcol+1] ;
157
for (p = Ap [oldcol] ; p < pend ; p++)
160
newrow = Pinv [oldrow] ;
163
Offi [poff] = oldrow ;
164
Offx [poff] = Ax [p] ;
169
ASSERT (newrow == k1) ;
170
PRINTF (("Singleton block %d", block)) ;
171
PRINT_ENTRY (Ax [p]) ;
179
for (p = Ap [oldcol] ; p < pend ; p++)
182
newrow = Pinv [oldrow] ;
185
Offi [poff] = oldrow ;
186
/*Offx [poff] = Ax [p] / Rs [oldrow] ; */
187
SCALE_DIV_ASSIGN (Offx [poff], Ax [p], Rs [oldrow]) ;
192
ASSERT (newrow == k1) ;
193
PRINTF (("Singleton block %d ", block)) ;
194
PRINT_ENTRY (Ax[p]) ;
195
SCALE_DIV_ASSIGN (s, Ax [p], Rs [oldrow]) ;
200
Singleton [block] = s ;
204
/* singular singleton */
205
Common->status = KLU_SINGULAR ;
206
Common->numerical_rank = k1 ;
207
Common->singular_col = oldcol ;
208
if (Common->halt_if_singular)
223
/* -------------------------------------------------------------- */
224
/* construct and factorize the kth block */
225
/* -------------------------------------------------------------- */
229
/* COLAMD was used - no estimate of fill-in */
230
/* use 10 times the nnz in A, plus n */
231
lsize = -(Common->initmem) ;
235
lsize = Common->initmem_amd * Lnz [block] + nk ;
238
/* allocates 5 arrays:
239
* Lbip [block], Ubip [block], Lblen [block], Ublen [block],
241
KLU_kernel_factor (nk, Ap, Ai, Ax, Q, lsize,
242
&LUbx [block], Udiag [block], Lblen [block], Ublen [block],
243
Lbip [block], Ubip [block], Pblock, &lnz_block, &unz_block,
245
/* BTF and scale-related arguments: */
246
k1, Pinv, Rs, Offp, Offi, Offx, Common) ;
248
if (Common->status < KLU_OK ||
249
(Common->status == KLU_SINGULAR && Common->halt_if_singular))
251
/* out of memory, invalid inputs, or singular */
255
PRINTF (("\n----------------------- L %d:\n", block)) ;
256
ASSERT (KLU_valid_LU (nk, TRUE, Lbip [block],
257
Lblen [block], LUbx [block])) ;
258
PRINTF (("\n----------------------- U %d:\n", block)) ;
259
ASSERT (KLU_valid_LU (nk, FALSE, Ubip [block],
260
Ublen [block], LUbx [block])) ;
262
/* -------------------------------------------------------------- */
264
/* -------------------------------------------------------------- */
268
max_lnz_block = MAX (max_lnz_block, lnz_block) ;
269
max_unz_block = MAX (max_unz_block, unz_block) ;
271
if (Lnz [block] == EMPTY)
273
/* revise estimate for subsequent factorization */
274
Lnz [block] = MAX (lnz_block, unz_block) ;
277
/* -------------------------------------------------------------- */
278
/* combine the klu row ordering with the symbolic pre-ordering */
279
/* -------------------------------------------------------------- */
281
PRINTF (("Pnum, 1-based:\n")) ;
282
for (k = 0 ; k < nk ; k++)
284
ASSERT (k + k1 < n) ;
285
ASSERT (Pblock [k] + k1 < n) ;
286
Pnum [k + k1] = P [Pblock [k] + k1] ;
287
PRINTF (("Pnum (%d + %d + 1 = %d) = %d + 1 = %d\n",
288
k, k1, k+k1+1, Pnum [k+k1], Pnum [k+k1]+1)) ;
291
/* the local pivot row permutation Pblock is no longer needed */
294
ASSERT (nzoff == Offp [n]) ;
295
PRINTF (("\n------------------- Off diagonal entries:\n")) ;
296
ASSERT (KLU_valid (n, Offp, Offi, Offx)) ;
300
Numeric->max_lnz_block = max_lnz_block ;
301
Numeric->max_unz_block = max_unz_block ;
303
/* Numeric->flops = EMPTY ; TODO not yet computed */
305
/* compute the inverse of Pnum */
307
for (k = 0 ; k < n ; k++)
312
for (k = 0 ; k < n ; k++)
314
ASSERT (Pnum [k] >= 0 && Pnum [k] < n) ;
315
Pinv [Pnum [k]] = k ;
318
for (k = 0 ; k < n ; k++) ASSERT (Pinv [k] != EMPTY) ;
321
/* permute scale factors Rs according to pivotal row order */
324
for (k = 0 ; k < n ; k++)
326
REAL (X [k]) = Rs [Pnum [k]] ;
328
for (k = 0 ; k < n ; k++)
330
Rs [k] = REAL (X [k]) ;
334
PRINTF (("\n------------------- Off diagonal entries, old:\n")) ;
335
ASSERT (KLU_valid (n, Offp, Offi, Offx)) ;
337
/* apply the pivot row permutations to the off-diagonal entries */
338
for (p = 0 ; p < nzoff ; p++)
340
ASSERT (Offi [p] >= 0 && Offi [p] < n) ;
341
Offi [p] = Pinv [Offi [p]] ;
344
PRINTF (("\n------------------- Off diagonal entries, new:\n")) ;
345
ASSERT (KLU_valid (n, Offp, Offi, Offx)) ;
349
PRINTF (("\n ############# KLU_BTF_FACTOR done, nblocks %d\n",nblocks));
350
Entry *singleton = Numeric->Singleton ;
351
for (block = 0 ; block < nblocks && Common->status == KLU_OK ; block++)
356
PRINTF (("\n======================klu_factor output: k1 %d k2 %d nk %d\n",k1,k2,nk)) ;
359
PRINTF (("singleton ")) ;
360
/* ENTRY_PRINT (singleton [block]) ; */
361
PRINT_ENTRY (singleton [block]) ;
365
int *Lip, *Uip, *Llen, *Ulen ;
368
Llen = Lblen [block] ;
369
LU = (Unit *) Numeric->LUbx [block] ;
370
PRINTF (("\n---- L block %d\n", block));
371
ASSERT (KLU_valid_LU (nk, TRUE, Lip, Llen, LU)) ;
373
Ulen = Ublen [block] ;
374
PRINTF (("\n---- U block %d\n", block)) ;
375
ASSERT (KLU_valid_LU (nk, FALSE, Uip, Ulen, LU)) ;
383
/* ========================================================================== */
384
/* === CLEAR_PTR ============================================================ */
385
/* ========================================================================== */
387
/* Set an array of pointers to NULL */
389
#define CLEAR_PTR(Ptr,size) \
394
for (ii = 0 ; ii < size ; ii++) \
402
/* ========================================================================== */
403
/* === klu_factor =========================================================== */
404
/* ========================================================================== */
406
klu_numeric *KLU_factor /* returns NULL if error, or a valid
407
klu_numeric object if successful */
410
int Ap [ ], /* size n+1, column pointers */
411
int Ai [ ], /* size nz, row indices */
413
klu_symbolic *Symbolic,
418
int n, nzoff, nblocks, maxblock, block, k1, k2, nk, ok = TRUE ;
420
int **Lbip, **Ubip, **Lblen, **Ublen ;
421
klu_numeric *Numeric ;
423
size_t n1, nzoff1, nunits, s, b6, n3, nk1 ;
429
Common->status = KLU_OK ;
430
Common->numerical_rank = EMPTY ;
431
Common->singular_col = EMPTY ;
433
/* ---------------------------------------------------------------------- */
434
/* get the contents of the Symbolic object */
435
/* ---------------------------------------------------------------------- */
437
/* check for a valid Symbolic object */
438
if (Symbolic == NULL)
440
Common->status = KLU_INVALID ;
445
nzoff = Symbolic->nzoff ;
446
nblocks = Symbolic->nblocks ;
447
maxblock = Symbolic->maxblock ;
449
PRINTF (("klu_factor: n %d nzoff %d nblocks %d maxblock %d\n",
450
n, nzoff, nblocks, maxblock)) ;
452
/* ---------------------------------------------------------------------- */
453
/* get control parameters and make sure they are in the proper range */
454
/* ---------------------------------------------------------------------- */
456
Common->initmem_amd = MAX (1.0, Common->initmem_amd) ;
457
Common->initmem = MAX (1.0, Common->initmem) ;
458
Common->tol = MIN (Common->tol, 1.0) ;
459
Common->tol = MAX (0.0, Common->tol) ;
460
Common->growth = MAX (1.0, Common->growth) ;
462
/* ---------------------------------------------------------------------- */
463
/* allocate the Numeric object */
464
/* ---------------------------------------------------------------------- */
466
/* this will not cause size_t overflow (already checked by klu_symbolic) */
467
n1 = ((size_t) n) + 1 ;
468
nzoff1 = ((size_t) nzoff) + 1 ;
470
Numeric = klu_malloc (sizeof (klu_numeric), 1, Common) ;
471
if (Common->status < KLU_OK)
474
Common->status = KLU_OUT_OF_MEMORY ;
477
Numeric->nblocks = nblocks ;
478
Numeric->Pnum = klu_malloc (n, sizeof (int), Common) ;
479
Numeric->Offp = klu_malloc (n1, sizeof (int), Common) ;
480
Numeric->Offi = klu_malloc (nzoff1, sizeof (int), Common) ;
481
Numeric->Offx = klu_malloc (nzoff1, sizeof (Entry), Common) ;
482
Numeric->Singleton = klu_malloc (nblocks, sizeof (Entry), Common) ;
484
Numeric->Lbip = klu_malloc (nblocks, sizeof (int *), Common) ;
485
Numeric->Ubip = klu_malloc (nblocks, sizeof (int *), Common) ;
486
Numeric->Lblen = klu_malloc (nblocks, sizeof (int *), Common) ;
487
Numeric->Ublen = klu_malloc (nblocks, sizeof (int *), Common) ;
488
Numeric->LUbx = klu_malloc (nblocks, sizeof (Unit *), Common) ;
489
Numeric->Udiag = klu_malloc (nblocks, sizeof (Unit *), Common) ;
491
if (Common->scale > 0)
493
Numeric->Rs = klu_malloc (n, sizeof (double), Common) ;
501
Numeric->Pinv = klu_malloc (n, sizeof (int), Common) ;
503
/* allocate permanent workspace for factorization and solve.
504
* Note that the solver will use an Xwork of size 4n, whereas
505
* the factorization codes use an Xwork of size n and integer space
506
* (Iwork) of size 6n. klu_condest uses an Xwork of size 2n. */
508
s = klu_mult_size_t (n, sizeof (Entry), &ok) ;
509
n3 = klu_mult_size_t (n, 3 * sizeof (Entry), &ok) ;
510
b6 = klu_mult_size_t (maxblock, 6 * sizeof (int), &ok) ;
511
Numeric->worksize = klu_add_size_t (s, MAX (n3, b6), &ok) ;
514
/* problem too large (almost impossible to happen here) */
515
Common->status = KLU_TOO_LARGE ;
516
KLU_free_numeric (&Numeric, Common) ;
521
Numeric->worksize = n * sizeof (Entry) +
522
MAX (n * 3 *sizeof (Entry), 6*maxblock * sizeof (int)) ;
525
Numeric->Work = klu_malloc (Numeric->worksize, 1, Common) ;
526
Numeric->Xwork = Numeric->Work ;
527
Numeric->Iwork = (int *) ((Entry *) Numeric->Xwork + n) ;
529
if (Common->status < KLU_OK)
532
KLU_free_numeric (&Numeric, Common) ;
536
/* clear the pointer arrays, so that klu_free_numeric works OK */
537
CLEAR_PTR (Numeric->Lbip, nblocks) ;
538
CLEAR_PTR (Numeric->Ubip, nblocks) ;
539
CLEAR_PTR (Numeric->Lblen, nblocks) ;
540
CLEAR_PTR (Numeric->Ublen, nblocks) ;
541
CLEAR_PTR (Numeric->LUbx, nblocks) ;
542
CLEAR_PTR (Numeric->Udiag, nblocks) ;
544
/* allocate the column pointer arrays for each block */
545
Lbip = Numeric->Lbip ;
546
Ubip = Numeric->Ubip ;
547
Lblen = Numeric->Lblen ;
548
Ublen = Numeric->Ublen ;
549
Udiag = (Unit **) Numeric->Udiag ;
551
for (block = 0 ; block < nblocks ; block++)
556
nk1 = ((size_t) nk) + 1 ; /* cannot overflow */
559
nunits = UNITS (Entry, nk) ;
560
Lbip [block] = klu_malloc (nk1, sizeof (int), Common) ;
561
Ubip [block] = klu_malloc (nk1, sizeof (int), Common) ;
562
Lblen [block] = klu_malloc (nk1, sizeof (int), Common) ;
563
Ublen [block] = klu_malloc (nk1, sizeof (int), Common) ;
564
Udiag [block] = klu_malloc (nunits, sizeof (Unit), Common) ;
565
if (Common->status < KLU_OK)
568
KLU_free_numeric (&Numeric, Common) ;
574
/* ---------------------------------------------------------------------- */
575
/* factorize the blocks */
576
/* ---------------------------------------------------------------------- */
578
klu_factor2 (Ap, Ai, (Entry *) Ax, Symbolic, Numeric, Common) ;
580
/* ---------------------------------------------------------------------- */
581
/* return or free the Numeric object */
582
/* ---------------------------------------------------------------------- */
584
if (Common->status < KLU_OK)
586
/* out of memory or inputs invalid */
587
KLU_free_numeric (&Numeric, Common) ;
589
else if (Common->status == KLU_SINGULAR)
591
if (Common->halt_if_singular)
593
/* Matrix is singular, and the Numeric object is only partially
594
* defined because we halted early. This is the default case for
595
* a singular matrix. */
596
KLU_free_numeric (&Numeric, Common) ;
599
else if (Common->status == KLU_OK)
601
/* successful non-singular factorization */
602
Common->numerical_rank = n ;
603
Common->singular_col = n ;