Amesos Package Browser (Single Doxygen Collection) Development
amesos_cholmod_l_factor.c
Go to the documentation of this file.
00001 /* ========================================================================== */
00002 /* === Core/cholmod_factor ================================================== */
00003 /* ========================================================================== */
00004 
00005 /* -----------------------------------------------------------------------------
00006  * CHOLMOD/Core Module.  Copyright (C) 2005-2006,
00007  * Univ. of Florida.  Author: Timothy A. Davis
00008  * The CHOLMOD/Core Module is licensed under Version 2.1 of the GNU
00009  * Lesser General Public License.  See lesser.txt for a text of the license.
00010  * CHOLMOD is also available under other licenses; contact authors for details.
00011  * http://www.cise.ufl.edu/research/sparse
00012  * -------------------------------------------------------------------------- */
00013 
00014 /* Core utility routines for the cholmod_factor object:
00015  *
00016  * The data structure for an LL' or LDL' factorization is too complex to
00017  * describe in one sentence.  This object can hold the symbolic analysis alone,
00018  * or in combination with a "simplicial" (similar to a sparse matrix) or
00019  * "supernodal" form of the numerical factorization.  Only the routine to free
00020  * a factor is primary, since a factor object is created by the factorization
00021  * routine (cholmod_factorize).  It must be freed with cholmod_free_factor.
00022  *
00023  * Primary routine:
00024  * ----------------
00025  * cholmod_free_factor    free a factor
00026  *
00027  * Secondary routines:
00028  * -------------------
00029  * cholmod_allocate_factor  allocate a symbolic factor (LL' or LDL')
00030  * cholmod_reallocate_factor  change the # entries in a factor 
00031  * cholmod_change_factor  change the type of factor (e.g., LDL' to LL')
00032  * cholmod_pack_factor    pack the columns of a factor
00033  * cholmod_reallocate_column  resize a single column of a factor
00034  * cholmod_factor_to_sparse create a sparse matrix copy of a factor
00035  * cholmod_copy_factor    create a copy of a factor
00036  *
00037  * Note that there is no cholmod_sparse_to_factor routine to create a factor
00038  * as a copy of a sparse matrix.  It could be done, after a fashion, but a
00039  * lower triangular sparse matrix would not necessarily have a chordal graph,
00040  * which would break the many CHOLMOD routines that rely on this property.
00041  *
00042  * The cholmod_factor_to_sparse routine is provided so that matrix operations
00043  * in the MatrixOps module may be applied to L.  Those operations operate on
00044  * cholmod_sparse objects, and they are not guaranteed to maintain the chordal
00045  * property of L.  Such a modified L cannot be safely converted back to a
00046  * cholmod_factor object.
00047  */
00048 
00049 /* This file should make the long int version of CHOLMOD */
00050 #define DLONG 1
00051 
00052 #include "amesos_cholmod_internal.h"
00053 #include "amesos_cholmod_core.h"
00054 
00055 
00056 /* ========================================================================== */
00057 /* === cholmod_allocate_factor ============================================== */
00058 /* ========================================================================== */
00059 
00060 /* Allocate a simplicial symbolic factor, with L->Perm and L->ColCount allocated
00061  * and initialized to "empty" values (Perm [k] = k, and ColCount[k] = 1).
00062  * The integer and numerical parts of L are not allocated.  L->xtype is returned
00063  * as CHOLMOD_PATTERN and L->is_super are returned as FALSE.  L->is_ll is also
00064  * returned FALSE, but this may be modified when the matrix is factorized.
00065  *
00066  * This is sufficient (but far from ideal) for input to cholmod_factorize,
00067  * since the simplicial LL' or LDL' factorization (cholmod_rowfac) can
00068  * reallocate the columns of L as needed.  The primary purpose of this routine
00069  * is to allocate space for a symbolic factorization, for the "expert" user to
00070  * do his or her own symbolic analysis.  The typical user should use
00071  * cholmod_analyze instead of this routine.
00072  *
00073  * workspace: none
00074  */
00075 
00076 cholmod_factor *CHOLMOD(allocate_factor)
00077 (
00078     /* ---- input ---- */
00079     size_t n,   /* L is n-by-n */
00080     /* --------------- */
00081     cholmod_common *Common
00082 )
00083 {
00084     Int j ;
00085     Int *Perm, *ColCount ;
00086     cholmod_factor *L ;
00087     int ok = TRUE ;
00088 
00089     RETURN_IF_NULL_COMMON (FALSE) ;
00090     Common->status = CHOLMOD_OK ;
00091 
00092     /* ensure the dimension does not cause integer overflow */
00093     (void) CHOLMOD(add_size_t) (n, 2, &ok) ;
00094     if (!ok || n > Int_max)
00095     {
00096   ERROR (CHOLMOD_TOO_LARGE, "problem too large") ;
00097   return (NULL) ;
00098     }
00099 
00100     L = CHOLMOD(malloc) (sizeof (cholmod_factor), 1, Common) ;
00101     if (Common->status < CHOLMOD_OK)
00102     {
00103   return (NULL) ;     /* out of memory */
00104     }
00105     L->n = n ;
00106     L->is_ll = FALSE ;
00107     L->is_super = FALSE ;
00108     L->is_monotonic = TRUE ;
00109     L->itype = ITYPE ;
00110     L->xtype = CHOLMOD_PATTERN ;
00111     L->dtype = DTYPE ;
00112 
00113     /* allocate the purely symbolic part of L */
00114     L->ordering = CHOLMOD_NATURAL ;
00115     L->Perm = CHOLMOD(malloc) (n, sizeof (Int), Common) ;
00116     L->ColCount = CHOLMOD(malloc) (n, sizeof (Int), Common) ;
00117 
00118     /* simplicial part of L is empty */
00119     L->nzmax = 0 ;
00120     L->p = NULL ;
00121     L->i = NULL ;
00122     L->x = NULL ;
00123     L->z = NULL ;
00124     L->nz = NULL ;
00125     L->next = NULL ;
00126     L->prev = NULL ;
00127 
00128     /* supernodal part of L is also empty */
00129     L->nsuper = 0 ;
00130     L->ssize = 0 ;
00131     L->xsize = 0 ;
00132     L->maxesize = 0 ;
00133     L->maxcsize = 0 ;
00134     L->super = NULL ;
00135     L->pi = NULL ;
00136     L->px = NULL ;
00137     L->s = NULL ;
00138 
00139     /* L has not been factorized */
00140     L->minor = n ;
00141 
00142     if (Common->status < CHOLMOD_OK)
00143     {
00144   CHOLMOD(free_factor) (&L, Common) ;
00145   return (NULL) ;   /* out of memory */
00146     }
00147 
00148     /* initialize Perm and ColCount */
00149     Perm = L->Perm ;
00150     for (j = 0 ; j < ((Int) n) ; j++)
00151     {
00152   Perm [j] = j ;
00153     }
00154     ColCount = L->ColCount ;
00155     for (j = 0 ; j < ((Int) n) ; j++)
00156     {
00157   ColCount [j] = 1 ;
00158     }
00159 
00160     return (L) ;
00161 }
00162 
00163 
00164 /* ========================================================================== */
00165 /* === cholmod_free_factor ================================================== */
00166 /* ========================================================================== */
00167 
00168 /* Free a factor object.
00169  *
00170  * workspace: none
00171  */
00172 
00173 int CHOLMOD(free_factor)
00174 (
00175     /* ---- in/out --- */
00176     cholmod_factor **LHandle, /* factor to free, NULL on output */
00177     /* --------------- */
00178     cholmod_common *Common
00179 )
00180 {
00181     Int n, lnz, xs, ss, s ;
00182     cholmod_factor *L ;
00183 
00184     RETURN_IF_NULL_COMMON (FALSE) ;
00185 
00186     if (LHandle == NULL)
00187     {
00188   /* nothing to do */
00189   return (TRUE) ;
00190     }
00191     L = *LHandle ;
00192     if (L == NULL)
00193     {
00194   /* nothing to do */
00195   return (TRUE) ;
00196     }
00197 
00198     n = L->n ;
00199     lnz = L->nzmax ;
00200     s = L->nsuper + 1 ;
00201     xs = (L->is_super) ? ((Int) (L->xsize)) : (lnz) ;
00202     ss = L->ssize ;
00203 
00204     /* symbolic part of L */
00205     CHOLMOD(free) (n,   sizeof (Int), L->Perm,     Common) ;
00206     CHOLMOD(free) (n,   sizeof (Int), L->ColCount, Common) ;
00207 
00208     /* simplicial form of L */
00209     CHOLMOD(free) (n+1, sizeof (Int), L->p,        Common) ;
00210     CHOLMOD(free) (lnz, sizeof (Int), L->i,        Common) ;
00211     CHOLMOD(free) (n,   sizeof (Int), L->nz,       Common) ;
00212     CHOLMOD(free) (n+2, sizeof (Int), L->next,     Common) ;
00213     CHOLMOD(free) (n+2, sizeof (Int), L->prev,     Common) ;
00214 
00215     /* supernodal form of L */
00216     CHOLMOD(free) (s,   sizeof (Int), L->pi,       Common) ;
00217     CHOLMOD(free) (s,   sizeof (Int), L->px,       Common) ;
00218     CHOLMOD(free) (s,   sizeof (Int), L->super,    Common) ;
00219     CHOLMOD(free) (ss,  sizeof (Int), L->s,        Common) ;
00220 
00221     /* numerical values for both simplicial and supernodal L */
00222     if (L->xtype == CHOLMOD_REAL)
00223     {
00224   CHOLMOD(free) (xs, sizeof (double), L->x, Common) ;
00225     }
00226     else if (L->xtype == CHOLMOD_COMPLEX)
00227     {
00228   CHOLMOD(free) (xs, 2*sizeof (double), L->x, Common) ;
00229     }
00230     else if (L->xtype == CHOLMOD_ZOMPLEX)
00231     {
00232   CHOLMOD(free) (xs, sizeof (double), L->x, Common) ;
00233   CHOLMOD(free) (xs, sizeof (double), L->z, Common) ;
00234     }
00235 
00236     *LHandle = CHOLMOD(free) (1, sizeof (cholmod_factor), (*LHandle), Common) ;
00237     return (TRUE) ;
00238 }
00239 
00240 
00241 /* ========================================================================== */
00242 /* === cholmod_reallocate_factor ============================================ */
00243 /* ========================================================================== */
00244 
00245 /* Change the size of L->i and L->x, or allocate them if their current size
00246  * is zero.  L must be simplicial.
00247  *
00248  * workspace: none
00249  */
00250 
00251 int CHOLMOD(reallocate_factor)
00252 (
00253     /* ---- input ---- */
00254     size_t nznew, /* new # of entries in L */
00255     /* ---- in/out --- */
00256     cholmod_factor *L,  /* factor to modify */
00257     /* --------------- */
00258     cholmod_common *Common
00259 )
00260 {
00261     /* ---------------------------------------------------------------------- */
00262     /* get inputs */
00263     /* ---------------------------------------------------------------------- */
00264 
00265     RETURN_IF_NULL_COMMON (FALSE) ;
00266     RETURN_IF_NULL (L, FALSE) ;
00267     RETURN_IF_XTYPE_INVALID (L, CHOLMOD_REAL, CHOLMOD_ZOMPLEX, FALSE) ;
00268     PRINT1 (("realloc factor: xtype %d\n", L->xtype)) ;
00269     if (L->is_super)
00270     {
00271   /* L must be simplicial, and not symbolic */
00272   ERROR (CHOLMOD_INVALID, "L invalid") ;
00273   return (FALSE) ;
00274     }
00275     Common->status = CHOLMOD_OK ;
00276     PRINT1 (("realloc factor %g to %g\n", (double) L->nzmax, (double) nznew)) ;
00277 
00278     /* ---------------------------------------------------------------------- */
00279     /* resize (or allocate) the L->i and L->x components of the factor */
00280     /* ---------------------------------------------------------------------- */
00281 
00282     CHOLMOD(realloc_multiple) (nznew, 1, L->xtype, &(L->i), NULL,
00283       &(L->x), &(L->z), &(L->nzmax), Common) ;
00284     return (Common->status == CHOLMOD_OK) ;
00285 }
00286 
00287 
00288 /* ========================================================================== */
00289 /* === cholmod_reallocate_column =========================================== */
00290 /* ========================================================================== */
00291 
00292 /* Column j needs more space, reallocate it at the end of L->i and L->x.
00293  * If the reallocation fails, the factor is converted to a simplicial
00294  * symbolic factor (no pattern, just L->Perm and L->ColCount).
00295  *
00296  * workspace: none
00297  */
00298 
00299 int CHOLMOD(reallocate_column)
00300 (
00301     /* ---- input ---- */
00302     size_t j,   /* the column to reallocate */
00303     size_t need,  /* required size of column j */
00304     /* ---- in/out --- */
00305     cholmod_factor *L,  /* factor to modify */
00306     /* --------------- */
00307     cholmod_common *Common
00308 )
00309 {
00310     double xneed ;
00311     double *Lx, *Lz ;
00312     Int *Lp, *Lprev, *Lnext, *Li, *Lnz ;
00313     Int n, pold, pnew, len, k, tail ;
00314 
00315     /* ---------------------------------------------------------------------- */
00316     /* get inputs */
00317     /* ---------------------------------------------------------------------- */
00318 
00319     RETURN_IF_NULL_COMMON (FALSE) ;
00320     RETURN_IF_NULL (L, FALSE) ;
00321     RETURN_IF_XTYPE_INVALID (L, CHOLMOD_REAL, CHOLMOD_ZOMPLEX, FALSE) ;
00322     if (L->is_super)
00323     {
00324   ERROR (CHOLMOD_INVALID, "L must be simplicial") ;
00325   return (FALSE) ;
00326     }
00327     n = L->n ;
00328     if (j >= L->n || need == 0)
00329     {
00330   ERROR (CHOLMOD_INVALID, "j invalid") ;
00331   return (FALSE) ;      /* j out of range */
00332     }
00333     Common->status = CHOLMOD_OK ;
00334 
00335     DEBUG (CHOLMOD(dump_factor) (L, "start colrealloc", Common)) ;
00336 
00337     /* ---------------------------------------------------------------------- */
00338     /* increase the size of L if needed */
00339     /* ---------------------------------------------------------------------- */
00340 
00341     /* head = n+1 ; */
00342     tail = n ;
00343     Lp = L->p ;
00344     Lnz = L->nz ;
00345     Lprev = L->prev ;
00346     Lnext = L->next ;
00347 
00348     ASSERT (Lnz != NULL) ;
00349     ASSERT (Lnext != NULL && Lprev != NULL) ;
00350     PRINT1 (("col %g need %g\n", (double) j, (double) need)) ;
00351 
00352     /* column j cannot have more than n-j entries if all entries are present */
00353     need = MIN (need, n-j) ;
00354 
00355     /* compute need in double to avoid integer overflow */
00356     if (Common->grow1 >= 1.0)
00357     {
00358   xneed = (double) need ;
00359   xneed = Common->grow1 * xneed + Common->grow2 ;
00360   xneed = MIN (xneed, n-j) ;
00361   need = (Int) xneed ;
00362     }
00363     PRINT1 (("really new need %g current %g\n", (double) need,
00364       (double) (Lp [Lnext [j]] - Lp [j]))) ;
00365     ASSERT (need >= 1 && need <= n-j) ;
00366 
00367     if (Lp [Lnext [j]] - Lp [j] >= (Int) need)
00368     {
00369   /* no need to reallocate the column, it's already big enough */
00370   PRINT1 (("colrealloc: quick return %g %g\n",
00371       (double) (Lp [Lnext [j]] - Lp [j]), (double) need)) ;
00372   return (TRUE) ;
00373 
00374     }
00375 
00376     if (Lp [tail] + need > L->nzmax)
00377     {
00378   /* use double to avoid integer overflow */
00379   xneed = (double) need ;
00380   if (Common->grow0 < 1.2)      /* fl. pt. compare, false if NaN */
00381   {
00382       /* if grow0 is less than 1.2 or NaN, don't use it */
00383       xneed = 1.2 * (((double) L->nzmax) + xneed + 1) ;
00384   }
00385   else
00386   {
00387       xneed = Common->grow0 * (((double) L->nzmax) + xneed + 1) ;
00388   }
00389   if (xneed > Size_max ||
00390     !CHOLMOD(reallocate_factor) ((Int) xneed, L, Common))
00391   {
00392       /* out of memory, convert to simplicial symbolic */
00393       CHOLMOD(change_factor) (CHOLMOD_PATTERN, L->is_ll, FALSE, TRUE,
00394         TRUE, L, Common) ;
00395       ERROR (CHOLMOD_OUT_OF_MEMORY, "out of memory; L now symbolic") ;
00396       return (FALSE) ;      /* out of memory */
00397   }
00398   PRINT1 (("\n=== GROW L from %g to %g\n",
00399         (double) L->nzmax, (double) xneed)) ;
00400   /* pack all columns so that each column has at most grow2 free space */
00401   CHOLMOD(pack_factor) (L, Common) ;
00402   ASSERT (Common->status == CHOLMOD_OK) ;
00403   Common->nrealloc_factor++ ;
00404     }
00405 
00406     /* ---------------------------------------------------------------------- */
00407     /* reallocate the column */
00408     /* ---------------------------------------------------------------------- */
00409 
00410     Common->nrealloc_col++ ;
00411 
00412     Li = L->i ;
00413     Lx = L->x ;
00414     Lz = L->z ;
00415 
00416     /* remove j from its current position in the list */
00417     Lnext [Lprev [j]] = Lnext [j] ;
00418     Lprev [Lnext [j]] = Lprev [j] ;
00419 
00420     /* place j at the end of the list */
00421     Lnext [Lprev [tail]] = j ;
00422     Lprev [j] = Lprev [tail] ;
00423     Lnext [j] = n ;
00424     Lprev [tail] = j ;
00425 
00426     /* L is no longer monotonic; columns are out-of-order */
00427     L->is_monotonic = FALSE ;
00428 
00429     /* allocate space for column j */
00430     pold = Lp [j] ;
00431     pnew = Lp [tail] ;
00432     Lp [j] = pnew  ;
00433     Lp [tail] += need ;
00434 
00435     /* copy column j to the new space */
00436     len = Lnz [j] ;
00437     for (k = 0 ; k < len ; k++)
00438     {
00439   Li [pnew + k] = Li [pold + k] ;
00440     }
00441 
00442     if (L->xtype == CHOLMOD_REAL)
00443     {
00444   for (k = 0 ; k < len ; k++)
00445   {
00446       Lx [pnew + k] = Lx [pold + k] ;
00447   }
00448     }
00449     else if (L->xtype == CHOLMOD_COMPLEX)
00450     {
00451   for (k = 0 ; k < len ; k++)
00452   {
00453       Lx [2*(pnew + k)  ] = Lx [2*(pold + k)  ] ;
00454       Lx [2*(pnew + k)+1] = Lx [2*(pold + k)+1] ;
00455   }
00456     }
00457     else if (L->xtype == CHOLMOD_ZOMPLEX)
00458     {
00459   for (k = 0 ; k < len ; k++)
00460   {
00461       Lx [pnew + k] = Lx [pold + k] ;
00462       Lz [pnew + k] = Lz [pold + k] ;
00463   }
00464     }
00465 
00466     DEBUG (CHOLMOD(dump_factor) (L, "colrealloc done", Common)) ;
00467 
00468     /* successful reallocation of column j of L */
00469     return (TRUE) ;
00470 }
00471 
00472 
00473 /* ========================================================================== */
00474 /* === cholmod_pack_factor ================================================== */
00475 /* ========================================================================== */
00476 
00477 /* Pack the columns of a simplicial LDL' or LL' factor.  This can be followed
00478  * by a call to cholmod_reallocate_factor to reduce the size of L to the exact
00479  * size required by the factor, if desired.  Alternatively, you can leave the
00480  * size of L->i and L->x the same, to allow space for future updates/rowadds.
00481  *
00482  * Each column is reduced in size so that it has at most Common->grow2 free
00483  * space at the end of the column.
00484  *
00485  * Does nothing and returns silently if given any other type of factor.
00486  *
00487  * Does NOT force the columns of L to be monotonic.  It thus differs from
00488  * cholmod_change_factor (xtype, -, FALSE, TRUE, TRUE, L, Common), which
00489  * packs the columns and ensures that they appear in monotonic order.
00490  */
00491 
00492 int CHOLMOD(pack_factor)
00493 (
00494     /* ---- in/out --- */
00495     cholmod_factor *L,  /* factor to modify */
00496     /* --------------- */
00497     cholmod_common *Common
00498 )
00499 {
00500     double *Lx, *Lz ;
00501     Int *Lp, *Li, *Lnz, *Lnext ;
00502     Int pnew, j, k, pold, len, n, head, tail, grow2 ;
00503 
00504     /* ---------------------------------------------------------------------- */
00505     /* get inputs */
00506     /* ---------------------------------------------------------------------- */
00507 
00508     RETURN_IF_NULL_COMMON (FALSE) ;
00509     RETURN_IF_NULL (L, FALSE) ;
00510     RETURN_IF_XTYPE_INVALID (L, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, FALSE) ;
00511     Common->status = CHOLMOD_OK ;
00512     DEBUG (CHOLMOD(dump_factor) (L, "start pack", Common)) ;
00513     PRINT1 (("PACK factor %d\n", L->is_super)) ;
00514 
00515     if (L->xtype == CHOLMOD_PATTERN || L->is_super)
00516     {
00517   /* nothing to do unless L is simplicial numeric */
00518   return (TRUE) ;
00519     }
00520 
00521     /* ---------------------------------------------------------------------- */
00522     /* pack */
00523     /* ---------------------------------------------------------------------- */
00524 
00525     grow2 = Common->grow2 ;
00526     PRINT1 (("\nPACK grow2 "ID"\n", grow2)) ;
00527 
00528     pnew = 0 ;
00529     n = L->n ;
00530     Lp = L->p ;
00531     Li = L->i ;
00532     Lx = L->x ;
00533     Lz = L->z ;
00534     Lnz = L->nz ;
00535     Lnext = L->next ;
00536 
00537     head = n+1 ;
00538     tail = n ;
00539 
00540     for (j = Lnext [head] ; j != tail ; j = Lnext [j])
00541     {
00542   /* pack column j */
00543   pold = Lp [j] ;
00544   len = Lnz [j] ;
00545   ASSERT (len > 0) ;
00546   PRINT2 (("col "ID" pnew "ID" pold "ID"\n", j, pnew, pold)) ;
00547   if (pnew < pold)
00548   {
00549       PRINT2 (("    pack this column\n")) ;
00550 
00551       for (k = 0 ; k < len ; k++)
00552       {
00553     Li [pnew + k] = Li [pold + k] ;
00554       }
00555 
00556       if (L->xtype == CHOLMOD_REAL)
00557       {
00558     for (k = 0 ; k < len ; k++)
00559     {
00560         Lx [pnew + k] = Lx [pold + k] ;
00561     }
00562       }
00563       else if (L->xtype == CHOLMOD_COMPLEX)
00564       {
00565     for (k = 0 ; k < len ; k++)
00566     {
00567         Lx [2*(pnew + k)  ] = Lx [2*(pold + k)  ] ;
00568         Lx [2*(pnew + k)+1] = Lx [2*(pold + k)+1] ;
00569     }
00570       }
00571       else if (L->xtype == CHOLMOD_ZOMPLEX)
00572       {
00573     for (k = 0 ; k < len ; k++)
00574     {
00575         Lx [pnew + k] = Lx [pold + k] ;
00576         Lz [pnew + k] = Lz [pold + k] ;
00577     }
00578       }
00579 
00580       Lp [j] = pnew ;
00581   }
00582   len = MIN (len + grow2, n - j) ;
00583   pnew = MIN (Lp [j] + len, Lp [Lnext [j]]) ;
00584     }
00585     PRINT2 (("final pnew = "ID"\n", pnew)) ;
00586     return (TRUE) ;
00587 }
00588 
00589 
00590 /* ========================================================================== */
00591 /* === cholmod_factor_to_sparse ============================================= */
00592 /* ========================================================================== */
00593 
00594 /* Constructs a column-oriented sparse matrix containing the pattern and values
00595  * of a simplicial or supernodal numerical factor, and then converts the factor
00596  * into a simplicial symbolic factor.  If L is already packed, monotonic,
00597  * and simplicial (which is the case when cholmod_factorize uses the simplicial
00598  * Cholesky factorization algorithm) then this routine requires only O(1)
00599  * memory and takes O(1) time.
00600  *
00601  * Only operates on numeric factors (real, complex, or zomplex).  Does not
00602  * change the numeric L->xtype (the resulting sparse matrix has the same xtype
00603  * as L).  If this routine fails, L is left unmodified.
00604  */
00605 
00606 cholmod_sparse *CHOLMOD(factor_to_sparse)
00607 (
00608     /* ---- in/out --- */
00609     cholmod_factor *L,  /* factor to copy, converted to symbolic on output */
00610     /* --------------- */
00611     cholmod_common *Common
00612 )
00613 {
00614     cholmod_sparse *Lsparse ;
00615 
00616     /* ---------------------------------------------------------------------- */
00617     /* get inputs */
00618     /* ---------------------------------------------------------------------- */
00619 
00620     RETURN_IF_NULL_COMMON (NULL) ;
00621     RETURN_IF_NULL (L, NULL) ;
00622     RETURN_IF_XTYPE_INVALID (L, CHOLMOD_REAL, CHOLMOD_ZOMPLEX, NULL) ;
00623     Common->status = CHOLMOD_OK ;
00624     DEBUG (CHOLMOD(dump_factor) (L, "start convert to matrix", Common)) ;
00625 
00626     /* ---------------------------------------------------------------------- */
00627     /* convert to packed, monotonic, simplicial, numeric */
00628     /* ---------------------------------------------------------------------- */
00629 
00630     /* leave as LL or LDL' */
00631     if (!CHOLMOD(change_factor) (L->xtype, L->is_ll, FALSE, TRUE, TRUE, L,
00632     Common))
00633     {
00634   ERROR (CHOLMOD_INVALID, "cannot convert L") ;
00635   return (NULL) ;
00636     }
00637 
00638     /* ---------------------------------------------------------------------- */
00639     /* create Lsparse */
00640     /* ---------------------------------------------------------------------- */
00641 
00642     /* allocate the header for Lsparse, the sparse matrix version of L */
00643     Lsparse = CHOLMOD(malloc) (sizeof (cholmod_sparse), 1, Common) ;
00644     if (Common->status < CHOLMOD_OK)
00645     {
00646   return (NULL) ;   /* out of memory */
00647     }
00648 
00649     /* transfer the contents from L to Lsparse */
00650     Lsparse->nrow = L->n ;
00651     Lsparse->ncol = L->n ;
00652     Lsparse->p = L->p ;
00653     Lsparse->i = L->i ;
00654     Lsparse->x = L->x ;
00655     Lsparse->z = L->z ;
00656     Lsparse->nz = NULL ;
00657     Lsparse->stype = 0 ;
00658     Lsparse->itype = L->itype ;
00659     Lsparse->xtype = L->xtype ;
00660     Lsparse->dtype = L->dtype ;
00661     Lsparse->sorted = TRUE ;
00662     Lsparse->packed = TRUE ;
00663     Lsparse->nzmax = L->nzmax ;
00664     ASSERT (CHOLMOD(dump_sparse) (Lsparse, "Lsparse", Common) >= 0) ;
00665 
00666     /* ---------------------------------------------------------------------- */
00667     /* convert L to symbolic, but do not free contents transfered to Lsparse */
00668     /* ---------------------------------------------------------------------- */
00669 
00670     L->p = NULL ;
00671     L->i = NULL ;
00672     L->x = NULL ;
00673     L->z = NULL ;
00674     L->xtype = CHOLMOD_PATTERN ;
00675     CHOLMOD(change_factor) (CHOLMOD_PATTERN, FALSE, FALSE, TRUE, TRUE, L,
00676       Common) ;
00677 
00678     return (Lsparse) ;
00679 }
00680 
00681 
00682 /* ========================================================================== */
00683 /* === cholmod_copy_factor ================================================== */
00684 /* ========================================================================== */
00685 
00686 /* Create an exact copy of a factor, with one exception:
00687  *
00688  * Entries in unused space are not copied (they might not be initialized,
00689  *  and copying them would cause program checkers such as purify and
00690  *  valgrind to complain).
00691  *
00692  * Note that a supernodal L cannot be zomplex.
00693  */
00694 
00695 cholmod_factor *CHOLMOD(copy_factor)
00696 (
00697     /* ---- input ---- */
00698     cholmod_factor *L,  /* factor to copy */
00699     /* --------------- */
00700     cholmod_common *Common
00701 )
00702 {
00703     cholmod_factor *L2 ;
00704     double *Lx, *L2x, *Lz, *L2z ;
00705     Int *Perm, *ColCount, *Lp, *Li, *Lnz, *Lnext, *Lprev, *Lsuper, *Lpi, *Lpx,
00706   *Ls, *Perm2, *ColCount2, *L2p, *L2i, *L2nz, *L2next, *L2prev, *L2super,
00707   *L2pi, *L2px, *L2s ;
00708     Int n, j, p, pend, s, xsize, ssize, nsuper ;
00709 
00710     /* ---------------------------------------------------------------------- */
00711     /* get inputs */
00712     /* ---------------------------------------------------------------------- */
00713 
00714     RETURN_IF_NULL_COMMON (NULL) ;
00715     RETURN_IF_NULL (L, NULL) ;
00716     RETURN_IF_XTYPE_INVALID (L, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, NULL) ;
00717     Common->status = CHOLMOD_OK ;
00718     DEBUG (CHOLMOD(dump_factor) (L, "start copy", Common)) ;
00719 
00720     n = L->n ;
00721 
00722     /* ---------------------------------------------------------------------- */
00723     /* allocate a simplicial symbolic factor  */
00724     /* ---------------------------------------------------------------------- */
00725 
00726     /* allocates L2->Perm and L2->ColCount */
00727     L2 = CHOLMOD(allocate_factor) (n, Common) ;
00728     if (Common->status < CHOLMOD_OK)
00729     {
00730   return (NULL) ;     /* out of memory */
00731     }
00732     ASSERT (L2->xtype == CHOLMOD_PATTERN && !(L2->is_super)) ;
00733 
00734     Perm = L->Perm ;
00735     ColCount = L->ColCount ;
00736     Perm2 = L2->Perm ;
00737     ColCount2 = L2->ColCount ;
00738     L2->ordering = L->ordering ;
00739 
00740     for (j = 0 ; j < n ; j++)
00741     {
00742   Perm2 [j] = Perm [j] ;
00743     }
00744     for (j = 0 ; j < n ; j++)
00745     {
00746   ColCount2 [j] = ColCount [j] ;
00747     }
00748     L2->is_ll = L->is_ll ;
00749 
00750     /* ---------------------------------------------------------------------- */
00751     /* copy the rest of the factor */
00752     /* ---------------------------------------------------------------------- */
00753 
00754     if (L->xtype != CHOLMOD_PATTERN && !(L->super))
00755     {
00756 
00757   /* ------------------------------------------------------------------ */
00758   /* allocate a simplicial numeric factor */
00759   /* ------------------------------------------------------------------ */
00760 
00761   /* allocate L2->p, L2->nz, L2->prev, L2->next, L2->i, and L2->x.
00762    * packed = -1 so that cholmod_change_factor allocates space of
00763    * size L2->nzmax */
00764   L2->nzmax = L->nzmax ;
00765   if (!CHOLMOD(change_factor) (L->xtype, L->is_ll, FALSE, -1, TRUE,
00766         L2, Common))
00767   {
00768       CHOLMOD(free_factor) (&L2, Common) ;
00769       return (NULL) ; /* out of memory */
00770   }
00771   ASSERT (L->nzmax == L2->nzmax) ;
00772 
00773   /* ------------------------------------------------------------------ */
00774   /* copy the contents of a simplicial numeric factor */
00775   /* ------------------------------------------------------------------ */
00776 
00777   Lp = L->p ;
00778   Li = L->i ;
00779   Lx = L->x ;
00780   Lz = L->z ;
00781   Lnz = L->nz ;
00782   Lnext = L->next ;
00783   Lprev = L->prev ;
00784 
00785   L2p = L2->p ;
00786   L2i = L2->i ;
00787   L2x = L2->x ;
00788   L2z = L2->z ;
00789   L2nz = L2->nz ;
00790   L2next = L2->next ;
00791   L2prev = L2->prev ;
00792   L2->xtype = L->xtype ;
00793   L2->dtype = L->dtype ;
00794 
00795   for (j = 0 ; j <= n ; j++)
00796   {
00797       L2p [j] = Lp [j] ;
00798   }
00799 
00800   for (j = 0 ; j < n+2 ; j++)
00801   {
00802       L2prev [j] = Lprev [j] ;
00803   }
00804 
00805   for (j = 0 ; j < n+2 ; j++)
00806   {
00807       L2next [j] = Lnext [j] ;
00808   }
00809 
00810   for (j = 0 ; j < n ; j++)
00811   {
00812       L2nz [j] = Lnz [j] ;
00813   }
00814 
00815   for (j = 0 ; j < n ; j++)
00816   {
00817       p = Lp [j] ;
00818       pend = p + Lnz [j] ;
00819       for ( ; p < pend ; p++)
00820       {
00821     L2i [p] = Li [p] ;
00822       }
00823       p = Lp [j] ;
00824 
00825       if (L->xtype == CHOLMOD_REAL)
00826       {
00827     for ( ; p < pend ; p++)
00828     {
00829         L2x [p] = Lx [p] ;
00830     }
00831       }
00832       else if (L->xtype == CHOLMOD_COMPLEX)
00833       {
00834     for ( ; p < pend ; p++)
00835     {
00836         L2x [2*p  ] = Lx [2*p  ] ;
00837         L2x [2*p+1] = Lx [2*p+1] ;
00838     }
00839       }
00840       else if (L->xtype == CHOLMOD_ZOMPLEX)
00841       {
00842     for ( ; p < pend ; p++)
00843     {
00844         L2x [p] = Lx [p] ;
00845         L2z [p] = Lz [p] ;
00846     }
00847       }
00848 
00849   }
00850 
00851     }
00852     else if (L->is_super)
00853     {
00854 
00855   /* ------------------------------------------------------------------ */
00856   /* copy a supernodal factor */
00857   /* ------------------------------------------------------------------ */
00858 
00859   xsize = L->xsize ;
00860   ssize = L->ssize ;
00861   nsuper = L->nsuper ;
00862 
00863   L2->xsize = xsize ;
00864   L2->ssize = ssize ;
00865   L2->nsuper = nsuper ;
00866 
00867   /* allocate L2->super, L2->pi, L2->px, and L2->s.  Allocate L2->x if
00868    * L is numeric */
00869   if (!CHOLMOD(change_factor) (L->xtype, TRUE, TRUE, TRUE, TRUE, L2,
00870         Common))
00871   {
00872       CHOLMOD(free_factor) (&L2, Common) ;
00873       return (NULL) ; /* out of memory */
00874   }
00875 
00876   ASSERT (L2->s != NULL) ;
00877 
00878   /* ------------------------------------------------------------------ */
00879   /* copy the contents of a supernodal factor */
00880   /* ------------------------------------------------------------------ */
00881 
00882   Lsuper = L->super ;
00883   Lpi = L->pi ;
00884   Lpx = L->px ;
00885   Ls = L->s ;
00886   Lx = L->x ;
00887 
00888   L2super = L2->super ;
00889   L2pi = L2->pi ;
00890   L2px = L2->px ;
00891   L2s = L2->s ;
00892   L2x = L2->x ;
00893 
00894   L2->maxcsize = L->maxcsize ;
00895   L2->maxesize = L->maxesize ;
00896 
00897   for (s = 0 ; s <= nsuper ; s++)
00898   {
00899       L2super [s] = Lsuper [s] ;
00900   }
00901   for (s = 0 ; s <= nsuper ; s++)
00902   {
00903       L2pi [s] = Lpi [s] ;
00904   }
00905   for (s = 0 ; s <= nsuper ; s++)
00906   {
00907       L2px [s] = Lpx [s] ;
00908   }
00909 
00910   L2s [0] = 0 ;
00911   for (p = 0 ; p < ssize ; p++)
00912   {
00913       L2s [p] = Ls [p] ;
00914   }
00915 
00916   if (L->xtype == CHOLMOD_REAL)
00917   {
00918       for (p = 0 ; p < xsize ; p++)
00919       {
00920     L2x [p] = Lx [p] ;
00921       }
00922   }
00923   else if (L->xtype == CHOLMOD_COMPLEX)
00924   {
00925       for (p = 0 ; p < 2*xsize ; p++)
00926       {
00927     L2x [p] = Lx [p] ;
00928       }
00929   }
00930     }
00931 
00932     L2->minor = L->minor ;
00933     L2->is_monotonic = L->is_monotonic ;
00934 
00935     DEBUG (CHOLMOD(dump_factor) (L2, "L2 got copied", Common)) ;
00936     ASSERT (L2->xtype == L->xtype && L2->is_super == L->is_super) ;
00937     return (L2) ;
00938 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines