Int KLU_free_symbolic ( KLU_symbolic **SymbolicHandle, KLU_common *Common ) { KLU_symbolic *Symbolic ; Int n ; if (Common == NULL) { return (FALSE) ; } if (SymbolicHandle == NULL || *SymbolicHandle == NULL) { return (TRUE) ; } Symbolic = *SymbolicHandle ; n = Symbolic->n ; KLU_free (Symbolic->P, n, sizeof (Int), Common) ; KLU_free (Symbolic->Q, n, sizeof (Int), Common) ; KLU_free (Symbolic->R, n+1, sizeof (Int), Common) ; KLU_free (Symbolic->Lnz, n, sizeof (double), Common) ; KLU_free (Symbolic, 1, sizeof (KLU_symbolic), Common) ; *SymbolicHandle = NULL ; return (TRUE) ; }
static KLU_symbolic *order_and_analyze /* returns NULL if error, or a valid KLU_symbolic object if successful */ ( /* inputs, not modified */ Int n, /* A is n-by-n */ Int Ap [ ], /* size n+1, column pointers */ Int Ai [ ], /* size nz, row indices */ /* --------------------- */ KLU_common *Common ) { double work ; KLU_symbolic *Symbolic ; double *Lnz ; Int *Qbtf, *Cp, *Ci, *Pinv, *Pblk, *Pbtf, *P, *Q, *R ; Int nblocks, nz, block, maxblock, k1, k2, nk, do_btf, ordering, k, Cilen, *Work ; /* ---------------------------------------------------------------------- */ /* allocate the Symbolic object, and check input matrix */ /* ---------------------------------------------------------------------- */ Symbolic = KLU_alloc_symbolic (n, Ap, Ai, Common) ; if (Symbolic == NULL) { return (NULL) ; } P = Symbolic->P ; Q = Symbolic->Q ; R = Symbolic->R ; Lnz = Symbolic->Lnz ; nz = Symbolic->nz ; ordering = Common->ordering ; if (ordering == 1) { /* COLAMD */ Cilen = COLAMD_recommended (nz, n, n) ; } else if (ordering == 0 || (ordering == 3 && Common->user_order != NULL)) { /* AMD or user ordering function */ Cilen = nz+1 ; } else { /* invalid ordering */ Common->status = KLU_INVALID ; KLU_free_symbolic (&Symbolic, Common) ; return (NULL) ; } /* AMD memory management routines */ amd_malloc = Common->malloc_memory ; amd_free = Common->free_memory ; amd_calloc = Common->calloc_memory ; amd_realloc = Common->realloc_memory ; /* ---------------------------------------------------------------------- */ /* allocate workspace for BTF permutation */ /* ---------------------------------------------------------------------- */ Pbtf = KLU_malloc (n, sizeof (Int), Common) ; Qbtf = KLU_malloc (n, sizeof (Int), Common) ; if (Common->status < KLU_OK) { KLU_free (Pbtf, n, sizeof (Int), Common) ; KLU_free (Qbtf, n, sizeof (Int), Common) ; KLU_free_symbolic (&Symbolic, Common) ; return (NULL) ; } /* ---------------------------------------------------------------------- */ /* get the common parameters for BTF and ordering method */ /* ---------------------------------------------------------------------- */ do_btf = Common->btf ; do_btf = (do_btf) ? TRUE : FALSE ; Symbolic->ordering = ordering ; Symbolic->do_btf = do_btf ; Symbolic->structural_rank = EMPTY ; /* ---------------------------------------------------------------------- */ /* find the block triangular form (if requested) */ /* ---------------------------------------------------------------------- */ Common->work = 0 ; if (do_btf) { Work = KLU_malloc (5*n, sizeof (Int), Common) ; if (Common->status < KLU_OK) { /* out of memory */ KLU_free (Pbtf, n, sizeof (Int), Common) ; KLU_free (Qbtf, n, sizeof (Int), Common) ; KLU_free_symbolic (&Symbolic, Common) ; return (NULL) ; } nblocks = BTF_order (n, Ap, Ai, Common->maxwork, &work, Pbtf, Qbtf, R, &(Symbolic->structural_rank), Work) ; Common->structural_rank = Symbolic->structural_rank ; Common->work += work ; KLU_free (Work, 5*n, sizeof (Int), Common) ; /* unflip Qbtf if the matrix does not have full structural rank */ if (Symbolic->structural_rank < n) { for (k = 0 ; k < n ; k++) { Qbtf [k] = BTF_UNFLIP (Qbtf [k]) ; } } /* find the size of the largest block */ maxblock = 1 ; for (block = 0 ; block < nblocks ; block++) { k1 = R [block] ; k2 = R [block+1] ; nk = k2 - k1 ; PRINTF (("block %d size %d\n", block, nk)) ; maxblock = MAX (maxblock, nk) ; } } else { /* BTF not requested */ nblocks = 1 ; maxblock = n ; R [0] = 0 ; R [1] = n ; for (k = 0 ; k < n ; k++) { Pbtf [k] = k ; Qbtf [k] = k ; } } Symbolic->nblocks = nblocks ; PRINTF (("maxblock size %d\n", maxblock)) ; Symbolic->maxblock = maxblock ; /* ---------------------------------------------------------------------- */ /* allocate more workspace, for analyze_worker */ /* ---------------------------------------------------------------------- */ Pblk = KLU_malloc (maxblock, sizeof (Int), Common) ; Cp = KLU_malloc (maxblock + 1, sizeof (Int), Common) ; Ci = KLU_malloc (MAX (Cilen, nz+1), sizeof (Int), Common) ; Pinv = KLU_malloc (n, sizeof (Int), Common) ; /* ---------------------------------------------------------------------- */ /* order each block of the BTF ordering, and a fill-reducing ordering */ /* ---------------------------------------------------------------------- */ if (Common->status == KLU_OK) { PRINTF (("calling analyze_worker\n")) ; Common->status = analyze_worker (n, Ap, Ai, nblocks, Pbtf, Qbtf, R, ordering, P, Q, Lnz, Pblk, Cp, Ci, Cilen, Pinv, Symbolic, Common) ; PRINTF (("analyze_worker done\n")) ; } /* ---------------------------------------------------------------------- */ /* free all workspace */ /* ---------------------------------------------------------------------- */ KLU_free (Pblk, maxblock, sizeof (Int), Common) ; KLU_free (Cp, maxblock+1, sizeof (Int), Common) ; KLU_free (Ci, MAX (Cilen, nz+1), sizeof (Int), Common) ; KLU_free (Pinv, n, sizeof (Int), Common) ; KLU_free (Pbtf, n, sizeof (Int), Common) ; KLU_free (Qbtf, n, sizeof (Int), Common) ; /* ---------------------------------------------------------------------- */ /* return the symbolic object */ /* ---------------------------------------------------------------------- */ if (Common->status < KLU_OK) { KLU_free_symbolic (&Symbolic, Common) ; } return (Symbolic) ; }
size_t KLU_kernel_factor /* 0 if failure, size of LU if OK */ ( /* inputs, not modified */ Int n, /* A is n-by-n. n must be > 0. */ Int Ap [ ], /* size n+1, column pointers for A */ Int Ai [ ], /* size nz = Ap [n], row indices for A */ Entry Ax [ ], /* size nz, values of A */ Int Q [ ], /* size n, optional column permutation */ double Lsize, /* estimate of number of nonzeros in L */ /* outputs, not defined on input */ Unit **p_LU, /* row indices and values of L and U */ Entry Udiag [ ], /* size n, diagonal of U */ Int Llen [ ], /* size n, column length of L */ Int Ulen [ ], /* size n, column length of U */ Int Lip [ ], /* size n, column pointers for L */ Int Uip [ ], /* size n, column pointers for U */ Int P [ ], /* row permutation, size n */ Int *lnz, /* size of L */ Int *unz, /* size of U */ /* workspace, undefined on input */ Entry *X, /* size n double's, zero on output */ Int *Work, /* size 5n Int's */ /* inputs, not modified on output */ Int k1, /* the block of A is from k1 to k2-1 */ Int PSinv [ ], /* inverse of P from symbolic factorization */ double Rs [ ], /* scale factors for A */ /* inputs, modified on output */ Int Offp [ ], /* off-diagonal matrix (modified by this routine) */ Int Offi [ ], Entry Offx [ ], /* --------------- */ KLU_common *Common ) { double maxlnz, dunits ; Unit *LU ; Int *Pinv, *Lpend, *Stack, *Flag, *Ap_pos, *W ; Int lsize, usize, anz, ok ; size_t lusize ; ASSERT (Common != NULL) ; /* ---------------------------------------------------------------------- */ /* get control parameters, or use defaults */ /* ---------------------------------------------------------------------- */ n = MAX (1, n) ; anz = Ap [n+k1] - Ap [k1] ; if (Lsize <= 0) { Lsize = -Lsize ; Lsize = MAX (Lsize, 1.0) ; lsize = Lsize * anz + n ; } else { lsize = Lsize ; } usize = lsize ; lsize = MAX (n+1, lsize) ; usize = MAX (n+1, usize) ; maxlnz = (((double) n) * ((double) n) + ((double) n)) / 2. ; maxlnz = MIN (maxlnz, ((double) INT_MAX)) ; lsize = MIN (maxlnz, lsize) ; usize = MIN (maxlnz, usize) ; PRINTF (("Welcome to klu: n %d anz %d k1 %d lsize %d usize %d maxlnz %g\n", n, anz, k1, lsize, usize, maxlnz)) ; /* ---------------------------------------------------------------------- */ /* allocate workspace and outputs */ /* ---------------------------------------------------------------------- */ /* return arguments are not yet assigned */ *p_LU = (Unit *) NULL ; /* these computations are safe from size_t overflow */ W = Work ; Pinv = (Int *) W ; W += n ; Stack = (Int *) W ; W += n ; Flag = (Int *) W ; W += n ; Lpend = (Int *) W ; W += n ; Ap_pos = (Int *) W ; W += n ; dunits = DUNITS (Int, lsize) + DUNITS (Entry, lsize) + DUNITS (Int, usize) + DUNITS (Entry, usize) ; lusize = (size_t) dunits ; ok = !INT_OVERFLOW (dunits) ; LU = ok ? KLU_malloc (lusize, sizeof (Unit), Common) : NULL ; if (LU == NULL) { /* out of memory, or problem too large */ Common->status = KLU_OUT_OF_MEMORY ; lusize = 0 ; return (lusize) ; } /* ---------------------------------------------------------------------- */ /* factorize */ /* ---------------------------------------------------------------------- */ /* with pruning, and non-recursive depth-first-search */ lusize = KLU_kernel (n, Ap, Ai, Ax, Q, lusize, Pinv, P, &LU, Udiag, Llen, Ulen, Lip, Uip, lnz, unz, X, Stack, Flag, Ap_pos, Lpend, k1, PSinv, Rs, Offp, Offi, Offx, Common) ; /* ---------------------------------------------------------------------- */ /* return LU factors, or return nothing if an error occurred */ /* ---------------------------------------------------------------------- */ if (Common->status < KLU_OK) { LU = KLU_free (LU, lusize, sizeof (Unit), Common) ; lusize = 0 ; } *p_LU = LU ; PRINTF ((" in klu noffdiag %d\n", Common->noffdiag)) ; return (lusize) ; }
KLU_symbolic<Entry, Int> *KLU_alloc_symbolic ( Int n, Int *Ap, Int *Ai, KLU_common<Entry, Int> *Common ) { KLU_symbolic<Entry, Int> *Symbolic ; Int *P, *Q, *R ; double *Lnz ; Int nz, i, j, p, pend ; if (Common == NULL) { return (NULL) ; } Common->status = KLU_OK ; /* A is n-by-n, with n > 0. Ap [0] = 0 and nz = Ap [n] >= 0 required. * Ap [j] <= Ap [j+1] must hold for all j = 0 to n-1. Row indices in Ai * must be in the range 0 to n-1, and no duplicate entries can be present. * The list of row indices in each column of A need not be sorted. */ if (n <= 0 || Ap == NULL || Ai == NULL) { /* Ap and Ai must be present, and n must be > 0 */ Common->status = KLU_INVALID ; return (NULL) ; } nz = Ap [n] ; if (Ap [0] != 0 || nz < 0) { /* nz must be >= 0 and Ap [0] must equal zero */ Common->status = KLU_INVALID ; return (NULL) ; } for (j = 0 ; j < n ; j++) { if (Ap [j] > Ap [j+1]) { /* column pointers must be non-decreasing */ Common->status = KLU_INVALID ; return (NULL) ; } } P = (Int *) KLU_malloc (n, sizeof (Int), Common) ; if (Common->status < KLU_OK) { /* out of memory */ Common->status = KLU_OUT_OF_MEMORY ; return (NULL) ; } for (i = 0 ; i < n ; i++) { P [i] = EMPTY ; } for (j = 0 ; j < n ; j++) { pend = Ap [j+1] ; for (p = Ap [j] ; p < pend ; p++) { i = Ai [p] ; if (i < 0 || i >= n || P [i] == j) { /* row index out of range, or duplicate entry */ KLU_free (P, n, sizeof (Int), Common) ; Common->status = KLU_INVALID ; return (NULL) ; } /* flag row i as appearing in column j */ P [i] = j ; } } /* ---------------------------------------------------------------------- */ /* allocate the Symbolic object */ /* ---------------------------------------------------------------------- */ Symbolic = (KLU_symbolic<Entry, Int> *) KLU_malloc (sizeof (KLU_symbolic<Entry, Int>), 1, Common) ; if (Common->status < KLU_OK) { /* out of memory */ KLU_free (P, n, sizeof (Int), Common) ; Common->status = KLU_OUT_OF_MEMORY ; return (NULL) ; } Q = (Int *) KLU_malloc (n, sizeof (Int), Common) ; R = (Int *) KLU_malloc (n+1, sizeof (Int), Common) ; Lnz = (double *) KLU_malloc (n, sizeof (double), Common) ; Symbolic->n = n ; Symbolic->nz = nz ; Symbolic->P = P ; Symbolic->Q = Q ; Symbolic->R = R ; Symbolic->Lnz = Lnz ; if (Common->status < KLU_OK) { /* out of memory */ KLU_free_symbolic (&Symbolic, Common) ; Common->status = KLU_OUT_OF_MEMORY ; return (NULL) ; } return (Symbolic) ; }
KLU_symbolic<Entry, Int> *KLU_analyze_given /* returns NULL if error, or a valid KLU_symbolic object if successful */ ( /* inputs, not modified */ Int n, /* A is n-by-n */ Int Ap [ ], /* size n+1, column pointers */ Int Ai [ ], /* size nz, row indices */ Int Puser [ ], /* size n, user's row permutation (may be NULL) */ Int Quser [ ], /* size n, user's column permutation (may be NULL) */ /* -------------------- */ KLU_common<Entry, Int> *Common ) { KLU_symbolic<Entry, Int> *Symbolic ; double *Lnz ; Int nblocks, nz, block, maxblock, *P, *Q, *R, nzoff, p, pend, do_btf, k ; /* ---------------------------------------------------------------------- */ /* determine if input matrix is valid, and get # of nonzeros */ /* ---------------------------------------------------------------------- */ Symbolic = KLU_alloc_symbolic (n, Ap, Ai, Common) ; if (Symbolic == NULL) { return (NULL) ; } P = Symbolic->P ; Q = Symbolic->Q ; R = Symbolic->R ; Lnz = Symbolic->Lnz ; nz = Symbolic->nz ; /* ---------------------------------------------------------------------- */ /* Q = Quser, or identity if Quser is NULL */ /* ---------------------------------------------------------------------- */ if (Quser == (Int *) NULL) { for (k = 0 ; k < n ; k++) { Q [k] = k ; } } else { for (k = 0 ; k < n ; k++) { Q [k] = Quser [k] ; } } /* ---------------------------------------------------------------------- */ /* get the control parameters for BTF and ordering method */ /* ---------------------------------------------------------------------- */ do_btf = Common->btf ; do_btf = (do_btf) ? TRUE : FALSE ; Symbolic->ordering = 2 ; Symbolic->do_btf = do_btf ; /* ---------------------------------------------------------------------- */ /* find the block triangular form, if requested */ /* ---------------------------------------------------------------------- */ if (do_btf) { /* ------------------------------------------------------------------ */ /* get workspace for BTF_strongcomp */ /* ------------------------------------------------------------------ */ Int *Pinv, *Work, *Bi, k1, k2, nk, oldcol ; Work = (Int *) KLU_malloc (4*n, sizeof (Int), Common) ; Pinv = (Int *) KLU_malloc (n, sizeof (Int), Common) ; if (Puser != (Int *) NULL) { Bi = (Int *) KLU_malloc (nz+1, sizeof (Int), Common) ; } else { Bi = Ai ; } if (Common->status < KLU_OK) { /* out of memory */ KLU_free (Work, 4*n, sizeof (Int), Common) ; KLU_free (Pinv, n, sizeof (Int), Common) ; if (Puser != (Int *) NULL) { KLU_free (Bi, nz+1, sizeof (Int), Common) ; } KLU_free_symbolic (&Symbolic, Common) ; Common->status = KLU_OUT_OF_MEMORY ; return (NULL) ; } /* ------------------------------------------------------------------ */ /* B = Puser * A */ /* ------------------------------------------------------------------ */ if (Puser != (Int *) NULL) { for (k = 0 ; k < n ; k++) { Pinv [Puser [k]] = k ; } for (p = 0 ; p < nz ; p++) { Bi [p] = Pinv [Ai [p]] ; } } /* ------------------------------------------------------------------ */ /* find the strongly-connected components */ /* ------------------------------------------------------------------ */ /* TODO : Correct version of BTF */ /* modifies Q, and determines P and R */ /*nblocks = BTF_strongcomp (n, Ap, Bi, Q, P, R, Work) ;*/ nblocks = KLU_OrdinalTraits<Int>::btf_strongcomp (n, Ap, Bi, Q, P, R, Work) ; /* ------------------------------------------------------------------ */ /* P = P * Puser */ /* ------------------------------------------------------------------ */ if (Puser != (Int *) NULL) { for (k = 0 ; k < n ; k++) { Work [k] = Puser [P [k]] ; } for (k = 0 ; k < n ; k++) { P [k] = Work [k] ; } } /* ------------------------------------------------------------------ */ /* Pinv = inverse of P */ /* ------------------------------------------------------------------ */ for (k = 0 ; k < n ; k++) { Pinv [P [k]] = k ; } /* ------------------------------------------------------------------ */ /* analyze each block */ /* ------------------------------------------------------------------ */ nzoff = 0 ; /* nz in off-diagonal part */ maxblock = 1 ; /* size of the largest block */ for (block = 0 ; block < nblocks ; block++) { /* -------------------------------------------------------------- */ /* the block is from rows/columns k1 to k2-1 */ /* -------------------------------------------------------------- */ k1 = R [block] ; k2 = R [block+1] ; nk = k2 - k1 ; PRINTF (("BLOCK %d, k1 %d k2-1 %d nk %d\n", block, k1, k2-1, nk)) ; maxblock = MAX (maxblock, nk) ; /* -------------------------------------------------------------- */ /* scan the kth block, C */ /* -------------------------------------------------------------- */ for (k = k1 ; k < k2 ; k++) { oldcol = Q [k] ; pend = Ap [oldcol+1] ; for (p = Ap [oldcol] ; p < pend ; p++) { if (Pinv [Ai [p]] < k1) { nzoff++ ; } } } /* fill-in not estimated */ Lnz [block] = EMPTY ; } /* ------------------------------------------------------------------ */ /* free all workspace */ /* ------------------------------------------------------------------ */ KLU_free (Work, 4*n, sizeof (Int), Common) ; KLU_free (Pinv, n, sizeof (Int), Common) ; if (Puser != (Int *) NULL) { KLU_free (Bi, nz+1, sizeof (Int), Common) ; } } else { /* ------------------------------------------------------------------ */ /* BTF not requested */ /* ------------------------------------------------------------------ */ nzoff = 0 ; nblocks = 1 ; maxblock = n ; R [0] = 0 ; R [1] = n ; Lnz [0] = EMPTY ; /* ------------------------------------------------------------------ */ /* P = Puser, or identity if Puser is NULL */ /* ------------------------------------------------------------------ */ for (k = 0 ; k < n ; k++) { P [k] = (Puser == NULL) ? k : Puser [k] ; } } /* ---------------------------------------------------------------------- */ /* return the symbolic object */ /* ---------------------------------------------------------------------- */ Symbolic->nblocks = nblocks ; Symbolic->maxblock = maxblock ; Symbolic->lnz = EMPTY ; Symbolic->unz = EMPTY ; Symbolic->nzoff = nzoff ; return (Symbolic) ; }
Int KLU_free_numeric ( KLU_numeric **NumericHandle, KLU_common *Common ) { KLU_numeric *Numeric ; Unit **LUbx ; size_t *LUsize ; Int block, n, nzoff, nblocks ; if (Common == NULL) { return (FALSE) ; } if (NumericHandle == NULL || *NumericHandle == NULL) { return (TRUE) ; } Numeric = *NumericHandle ; n = Numeric->n ; nzoff = Numeric->nzoff ; nblocks = Numeric->nblocks ; LUsize = Numeric->LUsize ; LUbx = (Unit **) Numeric->LUbx ; if (LUbx != NULL) { for (block = 0 ; block < nblocks ; block++) { KLU_free (LUbx [block], LUsize ? LUsize [block] : 0, sizeof (Unit), Common) ; } } KLU_free (Numeric->Pnum, n, sizeof (Int), Common) ; KLU_free (Numeric->Offp, n+1, sizeof (Int), Common) ; KLU_free (Numeric->Offi, nzoff+1, sizeof (Int), Common) ; KLU_free (Numeric->Offx, nzoff+1, sizeof (Entry), Common) ; KLU_free (Numeric->Lip, n, sizeof (Int), Common) ; KLU_free (Numeric->Llen, n, sizeof (Int), Common) ; KLU_free (Numeric->Uip, n, sizeof (Int), Common) ; KLU_free (Numeric->Ulen, n, sizeof (Int), Common) ; KLU_free (Numeric->LUsize, nblocks, sizeof (size_t), Common) ; KLU_free (Numeric->LUbx, nblocks, sizeof (Unit *), Common) ; KLU_free (Numeric->Udiag, n, sizeof (Entry), Common) ; KLU_free (Numeric->Rs, n, sizeof (double), Common) ; KLU_free (Numeric->Pinv, n, sizeof (Int), Common) ; KLU_free (Numeric->Work, Numeric->worksize, 1, Common) ; KLU_free (Numeric, 1, sizeof (KLU_numeric), Common) ; *NumericHandle = NULL ; return (TRUE) ; }
Int KLU_refactor /* returns TRUE if successful, FALSE otherwise */ ( /* inputs, not modified */ Int Ap [ ], /* size n+1, column pointers */ Int Ai [ ], /* size nz, row indices */ double Ax [ ], KLU_symbolic<Entry, Int> *Symbolic, /* input/output */ KLU_numeric<Entry, Int> *Numeric, KLU_common<Entry, Int> *Common ) { Entry ukk, ujk, s ; Entry *Offx, *Lx, *Ux, *X, *Az, *Udiag ; double *Rs ; Int *P, *Q, *R, *Pnum, *Offp, *Offi, *Ui, *Li, *Pinv, *Lip, *Uip, *Llen, *Ulen ; Unit **LUbx ; Unit *LU ; Int k1, k2, nk, k, block, oldcol, pend, oldrow, n, p, newrow, scale, nblocks, poff, i, j, up, ulen, llen, maxblock, nzoff ; /* ---------------------------------------------------------------------- */ /* check inputs */ /* ---------------------------------------------------------------------- */ if (Common == NULL) { return (FALSE) ; } Common->status = KLU_OK ; if (Numeric == NULL) { /* invalid Numeric object */ Common->status = KLU_INVALID ; return (FALSE) ; } Common->numerical_rank = EMPTY ; Common->singular_col = EMPTY ; Az = (Entry *) Ax ; /* ---------------------------------------------------------------------- */ /* get the contents of the Symbolic object */ /* ---------------------------------------------------------------------- */ n = Symbolic->n ; P = Symbolic->P ; Q = Symbolic->Q ; R = Symbolic->R ; nblocks = Symbolic->nblocks ; maxblock = Symbolic->maxblock ; /* ---------------------------------------------------------------------- */ /* get the contents of the Numeric object */ /* ---------------------------------------------------------------------- */ Pnum = Numeric->Pnum ; Offp = Numeric->Offp ; Offi = Numeric->Offi ; Offx = (Entry *) Numeric->Offx ; LUbx = (Unit **) Numeric->LUbx ; scale = Common->scale ; if (scale > 0) { /* factorization was not scaled, but refactorization is scaled */ if (Numeric->Rs == NULL) { Numeric->Rs = (double *)KLU_malloc (n, sizeof (double), Common) ; if (Common->status < KLU_OK) { Common->status = KLU_OUT_OF_MEMORY ; return (FALSE) ; } } } else { /* no scaling for refactorization; ensure Numeric->Rs is freed. This * does nothing if Numeric->Rs is already NULL. */ Numeric->Rs = (double *) KLU_free (Numeric->Rs, n, sizeof (double), Common) ; } Rs = Numeric->Rs ; Pinv = Numeric->Pinv ; X = (Entry *) Numeric->Xwork ; Common->nrealloc = 0 ; Udiag = (Entry *) Numeric->Udiag ; nzoff = Symbolic->nzoff ; /* ---------------------------------------------------------------------- */ /* check the input matrix compute the row scale factors, Rs */ /* ---------------------------------------------------------------------- */ /* do no scale, or check the input matrix, if scale < 0 */ if (scale >= 0) { /* check for out-of-range indices, but do not check for duplicates */ if (!KLU_scale (scale, n, Ap, Ai, Ax, Rs, NULL, Common)) { return (FALSE) ; } } /* ---------------------------------------------------------------------- */ /* clear workspace X */ /* ---------------------------------------------------------------------- */ for (k = 0 ; k < maxblock ; k++) { /* X [k] = 0 */ CLEAR (X [k]) ; } poff = 0 ; /* ---------------------------------------------------------------------- */ /* factor each block */ /* ---------------------------------------------------------------------- */ if (scale <= 0) { /* ------------------------------------------------------------------ */ /* no scaling */ /* ------------------------------------------------------------------ */ for (block = 0 ; block < nblocks ; block++) { /* -------------------------------------------------------------- */ /* the block is from rows/columns k1 to k2-1 */ /* -------------------------------------------------------------- */ k1 = R [block] ; k2 = R [block+1] ; nk = k2 - k1 ; if (nk == 1) { /* ---------------------------------------------------------- */ /* singleton case */ /* ---------------------------------------------------------- */ oldcol = Q [k1] ; pend = Ap [oldcol+1] ; CLEAR (s) ; for (p = Ap [oldcol] ; p < pend ; p++) { newrow = Pinv [Ai [p]] - k1 ; if (newrow < 0 && poff < nzoff) { /* entry in off-diagonal block */ Offx [poff] = Az [p] ; poff++ ; } else { /* singleton */ s = Az [p] ; } } Udiag [k1] = s ; } else { /* ---------------------------------------------------------- */ /* construct and factor the kth block */ /* ---------------------------------------------------------- */ Lip = Numeric->Lip + k1 ; Llen = Numeric->Llen + k1 ; Uip = Numeric->Uip + k1 ; Ulen = Numeric->Ulen + k1 ; LU = LUbx [block] ; for (k = 0 ; k < nk ; k++) { /* ------------------------------------------------------ */ /* scatter kth column of the block into workspace X */ /* ------------------------------------------------------ */ oldcol = Q [k+k1] ; pend = Ap [oldcol+1] ; for (p = Ap [oldcol] ; p < pend ; p++) { newrow = Pinv [Ai [p]] - k1 ; if (newrow < 0 && poff < nzoff) { /* entry in off-diagonal block */ Offx [poff] = Az [p] ; poff++ ; } else { /* (newrow,k) is an entry in the block */ X [newrow] = Az [p] ; } } /* ------------------------------------------------------ */ /* compute kth column of U, and update kth column of A */ /* ------------------------------------------------------ */ GET_POINTER (LU, Uip, Ulen, Ui, Ux, k, ulen) ; for (up = 0 ; up < ulen ; up++) { j = Ui [up] ; ujk = X [j] ; /* X [j] = 0 */ CLEAR (X [j]) ; Ux [up] = ujk ; GET_POINTER (LU, Lip, Llen, Li, Lx, j, llen) ; for (p = 0 ; p < llen ; p++) { /* X [Li [p]] -= Lx [p] * ujk */ MULT_SUB (X [Li [p]], Lx [p], ujk) ; } } /* get the diagonal entry of U */ ukk = X [k] ; /* X [k] = 0 */ CLEAR (X [k]) ; /* singular case */ if (IS_ZERO (ukk)) { /* matrix is numerically singular */ Common->status = KLU_SINGULAR ; if (Common->numerical_rank == EMPTY) { Common->numerical_rank = k+k1 ; Common->singular_col = Q [k+k1] ; } if (Common->halt_if_singular) { /* do not continue the factorization */ return (FALSE) ; } } Udiag [k+k1] = ukk ; /* gather and divide by pivot to get kth column of L */ GET_POINTER (LU, Lip, Llen, Li, Lx, k, llen) ; for (p = 0 ; p < llen ; p++) { i = Li [p] ; DIV (Lx [p], X [i], ukk) ; CLEAR (X [i]) ; } } } } } else { /* ------------------------------------------------------------------ */ /* scaling */ /* ------------------------------------------------------------------ */ for (block = 0 ; block < nblocks ; block++) { /* -------------------------------------------------------------- */ /* the block is from rows/columns k1 to k2-1 */ /* -------------------------------------------------------------- */ k1 = R [block] ; k2 = R [block+1] ; nk = k2 - k1 ; if (nk == 1) { /* ---------------------------------------------------------- */ /* singleton case */ /* ---------------------------------------------------------- */ oldcol = Q [k1] ; pend = Ap [oldcol+1] ; CLEAR (s) ; for (p = Ap [oldcol] ; p < pend ; p++) { oldrow = Ai [p] ; newrow = Pinv [oldrow] - k1 ; if (newrow < 0 && poff < nzoff) { /* entry in off-diagonal block */ /* Offx [poff] = Az [p] / Rs [oldrow] */ SCALE_DIV_ASSIGN (Offx [poff], Az [p], Rs [oldrow]) ; poff++ ; } else { /* singleton */ /* s = Az [p] / Rs [oldrow] */ SCALE_DIV_ASSIGN (s, Az [p], Rs [oldrow]) ; } } Udiag [k1] = s ; } else { /* ---------------------------------------------------------- */ /* construct and factor the kth block */ /* ---------------------------------------------------------- */ Lip = Numeric->Lip + k1 ; Llen = Numeric->Llen + k1 ; Uip = Numeric->Uip + k1 ; Ulen = Numeric->Ulen + k1 ; LU = LUbx [block] ; for (k = 0 ; k < nk ; k++) { /* ------------------------------------------------------ */ /* scatter kth column of the block into workspace X */ /* ------------------------------------------------------ */ oldcol = Q [k+k1] ; pend = Ap [oldcol+1] ; for (p = Ap [oldcol] ; p < pend ; p++) { oldrow = Ai [p] ; newrow = Pinv [oldrow] - k1 ; if (newrow < 0 && poff < nzoff) { /* entry in off-diagonal part */ /* Offx [poff] = Az [p] / Rs [oldrow] */ SCALE_DIV_ASSIGN (Offx [poff], Az [p], Rs [oldrow]); poff++ ; } else { /* (newrow,k) is an entry in the block */ /* X [newrow] = Az [p] / Rs [oldrow] */ SCALE_DIV_ASSIGN (X [newrow], Az [p], Rs [oldrow]) ; } } /* ------------------------------------------------------ */ /* compute kth column of U, and update kth column of A */ /* ------------------------------------------------------ */ GET_POINTER (LU, Uip, Ulen, Ui, Ux, k, ulen) ; for (up = 0 ; up < ulen ; up++) { j = Ui [up] ; ujk = X [j] ; /* X [j] = 0 */ CLEAR (X [j]) ; Ux [up] = ujk ; GET_POINTER (LU, Lip, Llen, Li, Lx, j, llen) ; for (p = 0 ; p < llen ; p++) { /* X [Li [p]] -= Lx [p] * ujk */ MULT_SUB (X [Li [p]], Lx [p], ujk) ; } } /* get the diagonal entry of U */ ukk = X [k] ; /* X [k] = 0 */ CLEAR (X [k]) ; /* singular case */ if (IS_ZERO (ukk)) { /* matrix is numerically singular */ Common->status = KLU_SINGULAR ; if (Common->numerical_rank == EMPTY) { Common->numerical_rank = k+k1 ; Common->singular_col = Q [k+k1] ; } if (Common->halt_if_singular) { /* do not continue the factorization */ return (FALSE) ; } } Udiag [k+k1] = ukk ; /* gather and divide by pivot to get kth column of L */ GET_POINTER (LU, Lip, Llen, Li, Lx, k, llen) ; for (p = 0 ; p < llen ; p++) { i = Li [p] ; DIV (Lx [p], X [i], ukk) ; CLEAR (X [i]) ; } } } } } /* ---------------------------------------------------------------------- */ /* permute scale factors Rs according to pivotal row order */ /* ---------------------------------------------------------------------- */ if (scale > 0) { for (k = 0 ; k < n ; k++) { /* TODO : Check. REAL(X[k]) Can be just X[k] */ /* REAL (X [k]) = Rs [Pnum [k]] ; */ X [k] = Rs [Pnum [k]] ; } for (k = 0 ; k < n ; k++) { Rs [k] = REAL (X [k]) ; } } #ifndef NDEBUGKLU2 ASSERT (Offp [n] == poff) ; ASSERT (Symbolic->nzoff == poff) ; PRINTF (("\n------------------- Off diagonal entries, new:\n")) ; ASSERT (KLU_valid (n, Offp, Offi, Offx)) ; if (Common->status == KLU_OK) { PRINTF (("\n ########### KLU_BTF_REFACTOR done, nblocks %d\n",nblocks)); for (block = 0 ; block < nblocks ; block++) { k1 = R [block] ; k2 = R [block+1] ; nk = k2 - k1 ; PRINTF (( "\n================KLU_refactor output: k1 %d k2 %d nk %d\n", k1, k2, nk)) ; if (nk == 1) { PRINTF (("singleton ")) ; PRINT_ENTRY (Udiag [k1]) ; } else { Lip = Numeric->Lip + k1 ; Llen = Numeric->Llen + k1 ; LU = (Unit *) Numeric->LUbx [block] ; PRINTF (("\n---- L block %d\n", block)) ; ASSERT (KLU_valid_LU (nk, TRUE, Lip, Llen, LU)) ; Uip = Numeric->Uip + k1 ; Ulen = Numeric->Ulen + k1 ; PRINTF (("\n---- U block %d\n", block)) ; ASSERT (KLU_valid_LU (nk, FALSE, Uip, Ulen, LU)) ; } } } #endif return (TRUE) ; }
Int KLU_sort ( KLU_symbolic<Entry, Int> *Symbolic, KLU_numeric<Entry, Int> *Numeric, KLU_common<Entry, Int> *Common ) { Int *R, *W, *Tp, *Ti, *Lip, *Uip, *Llen, *Ulen ; Entry *Tx ; Unit **LUbx ; Int n, nk, nz, block, nblocks, maxblock, k1 ; size_t m1 ; if (Common == NULL) { return (FALSE) ; } Common->status = KLU_OK ; n = Symbolic->n ; R = Symbolic->R ; nblocks = Symbolic->nblocks ; maxblock = Symbolic->maxblock ; Lip = Numeric->Lip ; Llen = Numeric->Llen ; Uip = Numeric->Uip ; Ulen = Numeric->Ulen ; LUbx = (Unit **) Numeric->LUbx ; m1 = ((size_t) maxblock) + 1 ; /* allocate workspace */ nz = MAX (Numeric->max_lnz_block, Numeric->max_unz_block) ; W = (Int *) KLU_malloc (maxblock, sizeof (Int), Common) ; Tp = (Int *) KLU_malloc (m1, sizeof (Int), Common) ; Ti = (Int *) KLU_malloc (nz, sizeof (Int), Common) ; Tx = (Entry *) KLU_malloc (nz, sizeof (Entry), Common) ; PRINTF (("\n======================= Start sort:\n")) ; if (Common->status == KLU_OK) { /* sort each block of L and U */ for (block = 0 ; block < nblocks ; block++) { k1 = R [block] ; nk = R [block+1] - k1 ; if (nk > 1) { PRINTF (("\n-------------------block: %d nk %d\n", block, nk)) ; sort (nk, Lip + k1, Llen + k1, LUbx [block], Tp, Ti, Tx, W) ; sort (nk, Uip + k1, Ulen + k1, LUbx [block], Tp, Ti, Tx, W) ; } } } PRINTF (("\n======================= sort done.\n")) ; /* free workspace */ KLU_free (W, maxblock, sizeof (Int), Common) ; KLU_free (Tp, m1, sizeof (Int), Common) ; KLU_free (Ti, nz, sizeof (Int), Common) ; KLU_free (Tx, nz, sizeof (Entry), Common) ; return (Common->status == KLU_OK) ; }