41 #ifndef KLU2_FACTOR_HPP 
   42 #define KLU2_FACTOR_HPP 
   44 #include "klu2_internal.h" 
   46 #include "klu2_memory.hpp" 
   47 #include "klu2_scale.hpp" 
   54 template <
typename Entry, 
typename Int>
 
   61     KLU_symbolic<Entry, Int> *Symbolic,
 
   64     KLU_numeric<Entry, Int> *Numeric,
 
   65     KLU_common<Entry, Int> *Common
 
   70     Int *P, *Q, *R, *Pnum, *Offp, *Offi, *Pblock, *Pinv, *Iwork,
 
   71         *Lip, *Uip, *Llen, *Ulen ;
 
   72     Entry *Offx, *X, s, *Udiag ;
 
   74     Int k1, k2, nk, k, block, oldcol, pend, oldrow, n, lnz, unz, p, newrow,
 
   75         nblocks, poff, nzoff, lnz_block, unz_block, 
scale, max_lnz_block,
 
   88     nblocks = Symbolic->nblocks ;
 
   89     nzoff = Symbolic->nzoff ;
 
   91     Pnum = Numeric->Pnum ;
 
   92     Offp = Numeric->Offp ;
 
   93     Offi = Numeric->Offi ;
 
   94     Offx = (Entry *) Numeric->Offx ;
 
   98     Llen = Numeric->Llen ;
 
   99     Ulen = Numeric->Ulen ;
 
  100     LUbx = (Unit **) Numeric->LUbx ;
 
  101     Udiag = (Entry *) Numeric->Udiag ;
 
  104     Pinv = Numeric->Pinv ;
 
  105     X = (Entry *) Numeric->Xwork ;              
 
  106     Iwork = Numeric->Iwork ;                    
 
  108     Pblock = Iwork + 5*((size_t) Symbolic->maxblock) ;
 
  109     Common->nrealloc = 0 ;
 
  110     scale = Common->scale ;
 
  118     for (k = 0 ; k < n ; k++)
 
  123     for (k = 0 ; k < n ; k++)
 
  125         ASSERT (P [k] >= 0 && P [k] < n) ;
 
  129     for (k = 0 ; k < n ; k++) ASSERT (Pinv [k] != EMPTY) ;
 
  134     Common->noffdiag = 0 ;
 
  151         KLU_scale (
scale, n, Ap, Ai, Ax, Rs, Pnum, Common) ;
 
  152         if (Common->status < KLU_OK)
 
  162         for (k = 0 ; k < n ; k++) PRINTF ((
"Rs [%d] %g\n", k, Rs [k])) ;
 
  170     for (block = 0 ; block < nblocks ; block++)
 
  180         PRINTF ((
"FACTOR BLOCK %d, k1 %d k2-1 %d nk %d\n", block, k1,k2-1,nk)) ;
 
  191             pend = Ap [oldcol+1] ;
 
  197                 for (p = Ap [oldcol] ; p < pend ; p++)
 
  200                     newrow = Pinv [oldrow] ;
 
  203                         Offi [poff] = oldrow ;
 
  204                         Offx [poff] = Ax [p] ;
 
  209                         ASSERT (newrow == k1) ;
 
  210                         PRINTF ((
"singleton block %d", block)) ;
 
  211                         PRINT_ENTRY (Ax [p]) ;
 
  223                 for (p = Ap [oldcol] ; p < pend ; p++)
 
  226                     newrow = Pinv [oldrow] ;
 
  229                         Offi [poff] = oldrow ;
 
  231                         SCALE_DIV_ASSIGN (Offx [poff], Ax [p], Rs [oldrow]) ;
 
  236                         ASSERT (newrow == k1) ;
 
  237                         PRINTF ((
"singleton block %d ", block)) ;
 
  238                         PRINT_ENTRY (Ax[p]) ;
 
  239                         SCALE_DIV_ASSIGN (s, Ax [p], Rs [oldrow]) ;
 
  249                 Common->status = KLU_SINGULAR ;
 
  250                 Common->numerical_rank = k1 ;
 
  251                 Common->singular_col = oldcol ;
 
  252                 if (Common->halt_if_singular)
 
  275                 lsize = -(Common->initmem) ;
 
  279                 lsize = Common->initmem_amd * Lnz [block] + nk ;
 
  283             Numeric->LUsize [block] = KLU_kernel_factor (nk, Ap, Ai, Ax, Q,
 
  284                     lsize, &LUbx [block], Udiag + k1, Llen + k1, Ulen + k1,
 
  285                     Lip + k1, Uip + k1, Pblock, &lnz_block, &unz_block,
 
  286                     X, Iwork, k1, Pinv, Rs, Offp, Offi, Offx, Common) ;
 
  288             if (Common->status < KLU_OK ||
 
  289                (Common->status == KLU_SINGULAR && Common->halt_if_singular))
 
  295             PRINTF ((
"\n----------------------- L %d:\n", block)) ;
 
  296             ASSERT (KLU_valid_LU (nk, TRUE, Lip+k1, Llen+k1, LUbx [block])) ;
 
  297             PRINTF ((
"\n----------------------- U %d:\n", block)) ;
 
  298             ASSERT (KLU_valid_LU (nk, FALSE, Uip+k1, Ulen+k1, LUbx [block])) ;
 
  306             max_lnz_block = MAX (max_lnz_block, lnz_block) ;
 
  307             max_unz_block = MAX (max_unz_block, unz_block) ;
 
  309             if (Lnz [block] == EMPTY)
 
  312                 Lnz [block] = MAX (lnz_block, unz_block) ;
 
  319             PRINTF ((
"Pnum, 1-based:\n")) ;
 
  320             for (k = 0 ; k < nk ; k++)
 
  322                 ASSERT (k + k1 < n) ;
 
  323                 ASSERT (Pblock [k] + k1 < n) ;
 
  324                 Pnum [k + k1] = P [Pblock [k] + k1] ;
 
  325                 PRINTF ((
"Pnum (%d + %d + 1 = %d) = %d + 1 = %d\n",
 
  326                     k, k1, k+k1+1, Pnum [k+k1], Pnum [k+k1]+1)) ;
 
  332     ASSERT (nzoff == Offp [n]) ;
 
  333     PRINTF ((
"\n------------------- Off diagonal entries:\n")) ;
 
  334     ASSERT (KLU_valid (n, Offp, Offi, Offx)) ;
 
  338     Numeric->max_lnz_block = max_lnz_block ;
 
  339     Numeric->max_unz_block = max_unz_block ;
 
  343     for (k = 0 ; k < n ; k++)
 
  348     for (k = 0 ; k < n ; k++)
 
  350         ASSERT (Pnum [k] >= 0 && Pnum [k] < n) ;
 
  351         Pinv [Pnum [k]] = k ;
 
  354     for (k = 0 ; k < n ; k++) ASSERT (Pinv [k] != EMPTY) ;
 
  360         for (k = 0 ; k < n ; k++)
 
  364             X [k] = Rs [Pnum [k]] ;
 
  366         for (k = 0 ; k < n ; k++)
 
  368             Rs [k] = REAL (X [k]) ;
 
  372     PRINTF ((
"\n------------------- Off diagonal entries, old:\n")) ;
 
  373     ASSERT (KLU_valid (n, Offp, Offi, Offx)) ;
 
  376     for (p = 0 ; p < nzoff ; p++)
 
  378         ASSERT (Offi [p] >= 0 && Offi [p] < n) ;
 
  379         Offi [p] = Pinv [Offi [p]] ;
 
  382     PRINTF ((
"\n------------------- Off diagonal entries, new:\n")) ;
 
  383     ASSERT (KLU_valid (n, Offp, Offi, Offx)) ;
 
  387         PRINTF ((
"\n ############# KLU_BTF_FACTOR done, nblocks %d\n",nblocks));
 
  388         Entry ss, *Udiag = Numeric->Udiag ;
 
  389         for (block = 0 ; block < nblocks && Common->status == KLU_OK ; block++)
 
  394             PRINTF ((
"\n======================KLU_factor output: k1 %d k2 %d nk %d\n",k1,k2,nk)) ;
 
  397                 PRINTF ((
"singleton  ")) ;
 
  404                 Int *Lip, *Uip, *Llen, *Ulen ;
 
  406                 Lip = Numeric->Lip + k1 ;
 
  407                 Llen = Numeric->Llen + k1 ;
 
  408                 LU = (Unit *) Numeric->LUbx [block] ;
 
  409                 PRINTF ((
"\n---- L block %d\n", block));
 
  410                 ASSERT (KLU_valid_LU (nk, TRUE, Lip, Llen, LU)) ;
 
  411                 Uip = Numeric->Uip + k1 ;
 
  412                 Ulen = Numeric->Ulen + k1 ;
 
  413                 PRINTF ((
"\n---- U block %d\n", block)) ;
 
  414                 ASSERT (KLU_valid_LU (nk, FALSE, Uip, Ulen, LU)) ;
 
  427 template <
typename Entry, 
typename Int>
 
  428 KLU_numeric<Entry, Int> *KLU_factor         
 
  436     KLU_symbolic<Entry, Int> *Symbolic,
 
  438     KLU_common<Entry, Int> *Common
 
  441     Int n, nzoff, nblocks, maxblock, k, ok = TRUE ;
 
  443     KLU_numeric<Entry, Int> *Numeric ;
 
  444     size_t n1, nzoff1, s, b6, n3 ;
 
  450     Common->status = KLU_OK ;
 
  451     Common->numerical_rank = EMPTY ;
 
  452     Common->singular_col = EMPTY ;
 
  459     if (Symbolic == NULL)
 
  461         Common->status = KLU_INVALID ;
 
  466     nzoff = Symbolic->nzoff ;
 
  467     nblocks = Symbolic->nblocks ;
 
  468     maxblock = Symbolic->maxblock ;
 
  470     PRINTF ((
"KLU_factor:  n %d nzoff %d nblocks %d maxblock %d\n",
 
  471         n, nzoff, nblocks, maxblock)) ;
 
  477     Common->initmem_amd = MAX (1.0, Common->initmem_amd) ;
 
  478     Common->initmem = MAX (1.0, Common->initmem) ;
 
  479     Common->tol = MIN (Common->tol, 1.0) ;
 
  480     Common->tol = MAX (0.0, Common->tol) ;
 
  481     Common->memgrow = MAX (1.0, Common->memgrow) ;
 
  488     n1 = ((size_t) n) + 1 ;
 
  489     nzoff1 = ((size_t) nzoff) + 1 ;
 
  491     Numeric = (KLU_numeric<Entry, Int> *) KLU_malloc (
sizeof (KLU_numeric<Entry, Int>), 1, Common) ;
 
  492     if (Common->status < KLU_OK)
 
  495         Common->status = KLU_OUT_OF_MEMORY ;
 
  499     Numeric->nblocks = nblocks ;
 
  500     Numeric->nzoff = nzoff ;
 
  501     Numeric->Pnum = (Int *) KLU_malloc (n, 
sizeof (Int), Common) ;
 
  502     Numeric->Offp = (Int *) KLU_malloc (n1, 
sizeof (Int), Common) ;
 
  503     Numeric->Offi = (Int *) KLU_malloc (nzoff1, 
sizeof (Int), Common) ;
 
  504     Numeric->Offx = KLU_malloc (nzoff1, 
sizeof (Entry), Common) ;
 
  506     Numeric->Lip  = (Int *) KLU_malloc (n, 
sizeof (Int), Common) ;
 
  507     Numeric->Uip  = (Int *) KLU_malloc (n, 
sizeof (Int), Common) ;
 
  508     Numeric->Llen = (Int *) KLU_malloc (n, 
sizeof (Int), Common) ;
 
  509     Numeric->Ulen = (Int *) KLU_malloc (n, 
sizeof (Int), Common) ;
 
  511     Numeric->LUsize = (
size_t *) KLU_malloc (nblocks, 
sizeof (
size_t), Common) ;
 
  513     Numeric->LUbx = (
void **) KLU_malloc (nblocks, 
sizeof (Unit *), Common) ;
 
  514     if (Numeric->LUbx != NULL)
 
  516         for (k = 0 ; k < nblocks ; k++)
 
  518             Numeric->LUbx [k] = NULL ;
 
  522     Numeric->Udiag = KLU_malloc (n, 
sizeof (Entry), Common) ;
 
  524     if (Common->scale > 0)
 
  526         Numeric->Rs = (
double *) KLU_malloc (n, 
sizeof (
double), Common) ;
 
  534     Numeric->Pinv = (Int *) KLU_malloc (n, 
sizeof (Int), Common) ;
 
  543     s = KLU_mult_size_t (n, 
sizeof (Entry), &ok) ;
 
  544     n3 = KLU_mult_size_t (n, 3 * 
sizeof (Entry), &ok) ;
 
  545     b6 = KLU_mult_size_t (maxblock, 6 * 
sizeof (Int), &ok) ;
 
  546     Numeric->worksize = KLU_add_size_t (s, MAX (n3, b6), &ok) ;
 
  547     Numeric->Work = KLU_malloc (Numeric->worksize, 1, Common) ;
 
  548     Numeric->Xwork = Numeric->Work ;
 
  549     Numeric->Iwork = (Int *) ((Entry *) Numeric->Xwork + n) ;
 
  550     if (!ok || Common->status < KLU_OK)
 
  553         Common->status = ok ? KLU_OUT_OF_MEMORY : KLU_TOO_LARGE ;
 
  554         KLU_free_numeric (&Numeric, Common) ;
 
  562     factor2 (Ap, Ai, (Entry *) Ax, Symbolic, Numeric, Common) ;
 
  568     if (Common->status < KLU_OK)
 
  571         KLU_free_numeric (&Numeric, Common) ;
 
  573     else if (Common->status == KLU_SINGULAR)
 
  575         if (Common->halt_if_singular)
 
  580             KLU_free_numeric (&Numeric, Common) ;
 
  583     else if (Common->status == KLU_OK)
 
  586         Common->numerical_rank = n ;
 
  587         Common->singular_col = n ;
 
void scale(ArrayView< Scalar1 > vals, size_t l, size_t ld, ArrayView< Scalar2 > s)
Scales a 1-D representation of a multivector.