Amesos Package Browser (Single Doxygen Collection)  Development
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
amesos_cholmod_factor.c
Go to the documentation of this file.
1 /* ========================================================================== */
2 /* === Core/cholmod_factor ================================================== */
3 /* ========================================================================== */
4 
5 /* -----------------------------------------------------------------------------
6  * CHOLMOD/Core Module. Copyright (C) 2005-2006,
7  * Univ. of Florida. Author: Timothy A. Davis
8  * The CHOLMOD/Core Module is licensed under Version 2.1 of the GNU
9  * Lesser General Public License. See lesser.txt for a text of the license.
10  * CHOLMOD is also available under other licenses; contact authors for details.
11  * http://www.cise.ufl.edu/research/sparse
12  * -------------------------------------------------------------------------- */
13 
14 /* Core utility routines for the cholmod_factor object:
15  *
16  * The data structure for an LL' or LDL' factorization is too complex to
17  * describe in one sentence. This object can hold the symbolic analysis alone,
18  * or in combination with a "simplicial" (similar to a sparse matrix) or
19  * "supernodal" form of the numerical factorization. Only the routine to free
20  * a factor is primary, since a factor object is created by the factorization
21  * routine (cholmod_factorize). It must be freed with cholmod_free_factor.
22  *
23  * Primary routine:
24  * ----------------
25  * cholmod_free_factor free a factor
26  *
27  * Secondary routines:
28  * -------------------
29  * cholmod_allocate_factor allocate a symbolic factor (LL' or LDL')
30  * cholmod_reallocate_factor change the # entries in a factor
31  * cholmod_change_factor change the type of factor (e.g., LDL' to LL')
32  * cholmod_pack_factor pack the columns of a factor
33  * cholmod_reallocate_column resize a single column of a factor
34  * cholmod_factor_to_sparse create a sparse matrix copy of a factor
35  * cholmod_copy_factor create a copy of a factor
36  *
37  * Note that there is no cholmod_sparse_to_factor routine to create a factor
38  * as a copy of a sparse matrix. It could be done, after a fashion, but a
39  * lower triangular sparse matrix would not necessarily have a chordal graph,
40  * which would break the many CHOLMOD routines that rely on this property.
41  *
42  * The cholmod_factor_to_sparse routine is provided so that matrix operations
43  * in the MatrixOps module may be applied to L. Those operations operate on
44  * cholmod_sparse objects, and they are not guaranteed to maintain the chordal
45  * property of L. Such a modified L cannot be safely converted back to a
46  * cholmod_factor object.
47  */
48 
50 #include "amesos_cholmod_core.h"
51 
52 
53 /* ========================================================================== */
54 /* === cholmod_allocate_factor ============================================== */
55 /* ========================================================================== */
56 
57 /* Allocate a simplicial symbolic factor, with L->Perm and L->ColCount allocated
58  * and initialized to "empty" values (Perm [k] = k, and ColCount[k] = 1).
59  * The integer and numerical parts of L are not allocated. L->xtype is returned
60  * as CHOLMOD_PATTERN and L->is_super are returned as FALSE. L->is_ll is also
61  * returned FALSE, but this may be modified when the matrix is factorized.
62  *
63  * This is sufficient (but far from ideal) for input to cholmod_factorize,
64  * since the simplicial LL' or LDL' factorization (cholmod_rowfac) can
65  * reallocate the columns of L as needed. The primary purpose of this routine
66  * is to allocate space for a symbolic factorization, for the "expert" user to
67  * do his or her own symbolic analysis. The typical user should use
68  * cholmod_analyze instead of this routine.
69  *
70  * workspace: none
71  */
72 
74 (
75  /* ---- input ---- */
76  size_t n, /* L is n-by-n */
77  /* --------------- */
78  cholmod_common *Common
79 )
80 {
81  Int j ;
82  Int *Perm, *ColCount ;
83  cholmod_factor *L ;
84  int ok = TRUE ;
85 
87  Common->status = CHOLMOD_OK ;
88 
89  /* ensure the dimension does not cause integer overflow */
90  (void) CHOLMOD(add_size_t) (n, 2, &ok) ;
91  if (!ok || n > Int_max)
92  {
93  ERROR (CHOLMOD_TOO_LARGE, "problem too large") ;
94  return (NULL) ;
95  }
96 
97  L = CHOLMOD(malloc) (sizeof (cholmod_factor), 1, Common) ;
98  if (Common->status < CHOLMOD_OK)
99  {
100  return (NULL) ; /* out of memory */
101  }
102  L->n = n ;
103  L->is_ll = FALSE ;
104  L->is_super = FALSE ;
105  L->is_monotonic = TRUE ;
106  L->itype = ITYPE ;
107  L->xtype = CHOLMOD_PATTERN ;
108  L->dtype = DTYPE ;
109 
110  /* allocate the purely symbolic part of L */
112  L->Perm = CHOLMOD(malloc) (n, sizeof (Int), Common) ;
113  L->ColCount = CHOLMOD(malloc) (n, sizeof (Int), Common) ;
114 
115  /* simplicial part of L is empty */
116  L->nzmax = 0 ;
117  L->p = NULL ;
118  L->i = NULL ;
119  L->x = NULL ;
120  L->z = NULL ;
121  L->nz = NULL ;
122  L->next = NULL ;
123  L->prev = NULL ;
124 
125  /* supernodal part of L is also empty */
126  L->nsuper = 0 ;
127  L->ssize = 0 ;
128  L->xsize = 0 ;
129  L->maxesize = 0 ;
130  L->maxcsize = 0 ;
131  L->super = NULL ;
132  L->pi = NULL ;
133  L->px = NULL ;
134  L->s = NULL ;
135 
136  /* L has not been factorized */
137  L->minor = n ;
138 
139  if (Common->status < CHOLMOD_OK)
140  {
141  CHOLMOD(free_factor) (&L, Common) ;
142  return (NULL) ; /* out of memory */
143  }
144 
145  /* initialize Perm and ColCount */
146  Perm = L->Perm ;
147  for (j = 0 ; j < ((Int) n) ; j++)
148  {
149  Perm [j] = j ;
150  }
151  ColCount = L->ColCount ;
152  for (j = 0 ; j < ((Int) n) ; j++)
153  {
154  ColCount [j] = 1 ;
155  }
156 
157  return (L) ;
158 }
159 
160 
161 /* ========================================================================== */
162 /* === cholmod_free_factor ================================================== */
163 /* ========================================================================== */
164 
165 /* Free a factor object.
166  *
167  * workspace: none
168  */
169 
170 int CHOLMOD(free_factor)
171 (
172  /* ---- in/out --- */
173  cholmod_factor **LHandle, /* factor to free, NULL on output */
174  /* --------------- */
175  cholmod_common *Common
176 )
177 {
178  Int n, lnz, xs, ss, s ;
179  cholmod_factor *L ;
180 
182 
183  if (LHandle == NULL)
184  {
185  /* nothing to do */
186  return (TRUE) ;
187  }
188  L = *LHandle ;
189  if (L == NULL)
190  {
191  /* nothing to do */
192  return (TRUE) ;
193  }
194 
195  n = L->n ;
196  lnz = L->nzmax ;
197  s = L->nsuper + 1 ;
198  xs = (L->is_super) ? ((Int) (L->xsize)) : (lnz) ;
199  ss = L->ssize ;
200 
201  /* symbolic part of L */
202  CHOLMOD(free) (n, sizeof (Int), L->Perm, Common) ;
203  CHOLMOD(free) (n, sizeof (Int), L->ColCount, Common) ;
204 
205  /* simplicial form of L */
206  CHOLMOD(free) (n+1, sizeof (Int), L->p, Common) ;
207  CHOLMOD(free) (lnz, sizeof (Int), L->i, Common) ;
208  CHOLMOD(free) (n, sizeof (Int), L->nz, Common) ;
209  CHOLMOD(free) (n+2, sizeof (Int), L->next, Common) ;
210  CHOLMOD(free) (n+2, sizeof (Int), L->prev, Common) ;
211 
212  /* supernodal form of L */
213  CHOLMOD(free) (s, sizeof (Int), L->pi, Common) ;
214  CHOLMOD(free) (s, sizeof (Int), L->px, Common) ;
215  CHOLMOD(free) (s, sizeof (Int), L->super, Common) ;
216  CHOLMOD(free) (ss, sizeof (Int), L->s, Common) ;
217 
218  /* numerical values for both simplicial and supernodal L */
219  if (L->xtype == CHOLMOD_REAL)
220  {
221  CHOLMOD(free) (xs, sizeof (double), L->x, Common) ;
222  }
223  else if (L->xtype == CHOLMOD_COMPLEX)
224  {
225  CHOLMOD(free) (xs, 2*sizeof (double), L->x, Common) ;
226  }
227  else if (L->xtype == CHOLMOD_ZOMPLEX)
228  {
229  CHOLMOD(free) (xs, sizeof (double), L->x, Common) ;
230  CHOLMOD(free) (xs, sizeof (double), L->z, Common) ;
231  }
232 
233  *LHandle = CHOLMOD(free) (1, sizeof (cholmod_factor), (*LHandle), Common) ;
234  return (TRUE) ;
235 }
236 
237 
238 /* ========================================================================== */
239 /* === cholmod_reallocate_factor ============================================ */
240 /* ========================================================================== */
241 
242 /* Change the size of L->i and L->x, or allocate them if their current size
243  * is zero. L must be simplicial.
244  *
245  * workspace: none
246  */
247 
249 (
250  /* ---- input ---- */
251  size_t nznew, /* new # of entries in L */
252  /* ---- in/out --- */
253  cholmod_factor *L, /* factor to modify */
254  /* --------------- */
255  cholmod_common *Common
256 )
257 {
258  /* ---------------------------------------------------------------------- */
259  /* get inputs */
260  /* ---------------------------------------------------------------------- */
261 
263  RETURN_IF_NULL (L, FALSE) ;
265  PRINT1 (("realloc factor: xtype %d\n", L->xtype)) ;
266  if (L->is_super)
267  {
268  /* L must be simplicial, and not symbolic */
269  ERROR (CHOLMOD_INVALID, "L invalid") ;
270  return (FALSE) ;
271  }
272  Common->status = CHOLMOD_OK ;
273  PRINT1 (("realloc factor %g to %g\n", (double) L->nzmax, (double) nznew)) ;
274 
275  /* ---------------------------------------------------------------------- */
276  /* resize (or allocate) the L->i and L->x components of the factor */
277  /* ---------------------------------------------------------------------- */
278 
279  CHOLMOD(realloc_multiple) (nznew, 1, L->xtype, &(L->i), NULL,
280  &(L->x), &(L->z), &(L->nzmax), Common) ;
281  return (Common->status == CHOLMOD_OK) ;
282 }
283 
284 
285 /* ========================================================================== */
286 /* === cholmod_reallocate_column =========================================== */
287 /* ========================================================================== */
288 
289 /* Column j needs more space, reallocate it at the end of L->i and L->x.
290  * If the reallocation fails, the factor is converted to a simplicial
291  * symbolic factor (no pattern, just L->Perm and L->ColCount).
292  *
293  * workspace: none
294  */
295 
297 (
298  /* ---- input ---- */
299  size_t j, /* the column to reallocate */
300  size_t need, /* required size of column j */
301  /* ---- in/out --- */
302  cholmod_factor *L, /* factor to modify */
303  /* --------------- */
304  cholmod_common *Common
305 )
306 {
307  double xneed ;
308  double *Lx, *Lz ;
309  Int *Lp, *Lprev, *Lnext, *Li, *Lnz ;
310  Int n, pold, pnew, len, k, tail ;
311 
312  /* ---------------------------------------------------------------------- */
313  /* get inputs */
314  /* ---------------------------------------------------------------------- */
315 
317  RETURN_IF_NULL (L, FALSE) ;
319  if (L->is_super)
320  {
321  ERROR (CHOLMOD_INVALID, "L must be simplicial") ;
322  return (FALSE) ;
323  }
324  n = L->n ;
325  if (j >= L->n || need == 0)
326  {
327  ERROR (CHOLMOD_INVALID, "j invalid") ;
328  return (FALSE) ; /* j out of range */
329  }
330  Common->status = CHOLMOD_OK ;
331 
332  DEBUG (CHOLMOD(dump_factor) (L, "start colrealloc", Common)) ;
333 
334  /* ---------------------------------------------------------------------- */
335  /* increase the size of L if needed */
336  /* ---------------------------------------------------------------------- */
337 
338  /* head = n+1 ; */
339  tail = n ;
340  Lp = L->p ;
341  Lnz = L->nz ;
342  Lprev = L->prev ;
343  Lnext = L->next ;
344 
345  ASSERT (Lnz != NULL) ;
346  ASSERT (Lnext != NULL && Lprev != NULL) ;
347  PRINT1 (("col %g need %g\n", (double) j, (double) need)) ;
348 
349  /* column j cannot have more than n-j entries if all entries are present */
350  need = MIN (need, n-j) ;
351 
352  /* compute need in double to avoid integer overflow */
353  if (Common->grow1 >= 1.0)
354  {
355  xneed = (double) need ;
356  xneed = Common->grow1 * xneed + Common->grow2 ;
357  xneed = MIN (xneed, n-j) ;
358  need = (Int) xneed ;
359  }
360  PRINT1 (("really new need %g current %g\n", (double) need,
361  (double) (Lp [Lnext [j]] - Lp [j]))) ;
362  ASSERT (need >= 1 && need <= n-j) ;
363 
364  if (Lp [Lnext [j]] - Lp [j] >= (Int) need)
365  {
366  /* no need to reallocate the column, it's already big enough */
367  PRINT1 (("colrealloc: quick return %g %g\n",
368  (double) (Lp [Lnext [j]] - Lp [j]), (double) need)) ;
369  return (TRUE) ;
370 
371  }
372 
373  if (Lp [tail] + need > L->nzmax)
374  {
375  /* use double to avoid integer overflow */
376  xneed = (double) need ;
377  if (Common->grow0 < 1.2) /* fl. pt. compare, false if NaN */
378  {
379  /* if grow0 is less than 1.2 or NaN, don't use it */
380  xneed = 1.2 * (((double) L->nzmax) + xneed + 1) ;
381  }
382  else
383  {
384  xneed = Common->grow0 * (((double) L->nzmax) + xneed + 1) ;
385  }
386  if (xneed > Size_max ||
387  !CHOLMOD(reallocate_factor) ((Int) xneed, L, Common))
388  {
389  /* out of memory, convert to simplicial symbolic */
391  TRUE, L, Common) ;
392  ERROR (CHOLMOD_OUT_OF_MEMORY, "out of memory; L now symbolic") ;
393  return (FALSE) ; /* out of memory */
394  }
395  PRINT1 (("\n=== GROW L from %g to %g\n",
396  (double) L->nzmax, (double) xneed)) ;
397  /* pack all columns so that each column has at most grow2 free space */
398  CHOLMOD(pack_factor) (L, Common) ;
399  ASSERT (Common->status == CHOLMOD_OK) ;
400  Common->nrealloc_factor++ ;
401  }
402 
403  /* ---------------------------------------------------------------------- */
404  /* reallocate the column */
405  /* ---------------------------------------------------------------------- */
406 
407  Common->nrealloc_col++ ;
408 
409  Li = L->i ;
410  Lx = L->x ;
411  Lz = L->z ;
412 
413  /* remove j from its current position in the list */
414  Lnext [Lprev [j]] = Lnext [j] ;
415  Lprev [Lnext [j]] = Lprev [j] ;
416 
417  /* place j at the end of the list */
418  Lnext [Lprev [tail]] = j ;
419  Lprev [j] = Lprev [tail] ;
420  Lnext [j] = n ;
421  Lprev [tail] = j ;
422 
423  /* L is no longer monotonic; columns are out-of-order */
424  L->is_monotonic = FALSE ;
425 
426  /* allocate space for column j */
427  pold = Lp [j] ;
428  pnew = Lp [tail] ;
429  Lp [j] = pnew ;
430  Lp [tail] += need ;
431 
432  /* copy column j to the new space */
433  len = Lnz [j] ;
434  for (k = 0 ; k < len ; k++)
435  {
436  Li [pnew + k] = Li [pold + k] ;
437  }
438 
439  if (L->xtype == CHOLMOD_REAL)
440  {
441  for (k = 0 ; k < len ; k++)
442  {
443  Lx [pnew + k] = Lx [pold + k] ;
444  }
445  }
446  else if (L->xtype == CHOLMOD_COMPLEX)
447  {
448  for (k = 0 ; k < len ; k++)
449  {
450  Lx [2*(pnew + k) ] = Lx [2*(pold + k) ] ;
451  Lx [2*(pnew + k)+1] = Lx [2*(pold + k)+1] ;
452  }
453  }
454  else if (L->xtype == CHOLMOD_ZOMPLEX)
455  {
456  for (k = 0 ; k < len ; k++)
457  {
458  Lx [pnew + k] = Lx [pold + k] ;
459  Lz [pnew + k] = Lz [pold + k] ;
460  }
461  }
462 
463  DEBUG (CHOLMOD(dump_factor) (L, "colrealloc done", Common)) ;
464 
465  /* successful reallocation of column j of L */
466  return (TRUE) ;
467 }
468 
469 
470 /* ========================================================================== */
471 /* === cholmod_pack_factor ================================================== */
472 /* ========================================================================== */
473 
474 /* Pack the columns of a simplicial LDL' or LL' factor. This can be followed
475  * by a call to cholmod_reallocate_factor to reduce the size of L to the exact
476  * size required by the factor, if desired. Alternatively, you can leave the
477  * size of L->i and L->x the same, to allow space for future updates/rowadds.
478  *
479  * Each column is reduced in size so that it has at most Common->grow2 free
480  * space at the end of the column.
481  *
482  * Does nothing and returns silently if given any other type of factor.
483  *
484  * Does NOT force the columns of L to be monotonic. It thus differs from
485  * cholmod_change_factor (xtype, -, FALSE, TRUE, TRUE, L, Common), which
486  * packs the columns and ensures that they appear in monotonic order.
487  */
488 
489 int CHOLMOD(pack_factor)
490 (
491  /* ---- in/out --- */
492  cholmod_factor *L, /* factor to modify */
493  /* --------------- */
494  cholmod_common *Common
495 )
496 {
497  double *Lx, *Lz ;
498  Int *Lp, *Li, *Lnz, *Lnext ;
499  Int pnew, j, k, pold, len, n, head, tail, grow2 ;
500 
501  /* ---------------------------------------------------------------------- */
502  /* get inputs */
503  /* ---------------------------------------------------------------------- */
504 
506  RETURN_IF_NULL (L, FALSE) ;
508  Common->status = CHOLMOD_OK ;
509  DEBUG (CHOLMOD(dump_factor) (L, "start pack", Common)) ;
510  PRINT1 (("PACK factor %d\n", L->is_super)) ;
511 
512  if (L->xtype == CHOLMOD_PATTERN || L->is_super)
513  {
514  /* nothing to do unless L is simplicial numeric */
515  return (TRUE) ;
516  }
517 
518  /* ---------------------------------------------------------------------- */
519  /* pack */
520  /* ---------------------------------------------------------------------- */
521 
522  grow2 = Common->grow2 ;
523  PRINT1 (("\nPACK grow2 "ID"\n", grow2)) ;
524 
525  pnew = 0 ;
526  n = L->n ;
527  Lp = L->p ;
528  Li = L->i ;
529  Lx = L->x ;
530  Lz = L->z ;
531  Lnz = L->nz ;
532  Lnext = L->next ;
533 
534  head = n+1 ;
535  tail = n ;
536 
537  for (j = Lnext [head] ; j != tail ; j = Lnext [j])
538  {
539  /* pack column j */
540  pold = Lp [j] ;
541  len = Lnz [j] ;
542  ASSERT (len > 0) ;
543  PRINT2 (("col "ID" pnew "ID" pold "ID"\n", j, pnew, pold)) ;
544  if (pnew < pold)
545  {
546  PRINT2 ((" pack this column\n")) ;
547 
548  for (k = 0 ; k < len ; k++)
549  {
550  Li [pnew + k] = Li [pold + k] ;
551  }
552 
553  if (L->xtype == CHOLMOD_REAL)
554  {
555  for (k = 0 ; k < len ; k++)
556  {
557  Lx [pnew + k] = Lx [pold + k] ;
558  }
559  }
560  else if (L->xtype == CHOLMOD_COMPLEX)
561  {
562  for (k = 0 ; k < len ; k++)
563  {
564  Lx [2*(pnew + k) ] = Lx [2*(pold + k) ] ;
565  Lx [2*(pnew + k)+1] = Lx [2*(pold + k)+1] ;
566  }
567  }
568  else if (L->xtype == CHOLMOD_ZOMPLEX)
569  {
570  for (k = 0 ; k < len ; k++)
571  {
572  Lx [pnew + k] = Lx [pold + k] ;
573  Lz [pnew + k] = Lz [pold + k] ;
574  }
575  }
576 
577  Lp [j] = pnew ;
578  }
579  len = MIN (len + grow2, n - j) ;
580  pnew = MIN (Lp [j] + len, Lp [Lnext [j]]) ;
581  }
582  PRINT2 (("final pnew = "ID"\n", pnew)) ;
583  return (TRUE) ;
584 }
585 
586 
587 /* ========================================================================== */
588 /* === cholmod_factor_to_sparse ============================================= */
589 /* ========================================================================== */
590 
591 /* Constructs a column-oriented sparse matrix containing the pattern and values
592  * of a simplicial or supernodal numerical factor, and then converts the factor
593  * into a simplicial symbolic factor. If L is already packed, monotonic,
594  * and simplicial (which is the case when cholmod_factorize uses the simplicial
595  * Cholesky factorization algorithm) then this routine requires only O(1)
596  * memory and takes O(1) time.
597  *
598  * Only operates on numeric factors (real, complex, or zomplex). Does not
599  * change the numeric L->xtype (the resulting sparse matrix has the same xtype
600  * as L). If this routine fails, L is left unmodified.
601  */
602 
604 (
605  /* ---- in/out --- */
606  cholmod_factor *L, /* factor to copy, converted to symbolic on output */
607  /* --------------- */
608  cholmod_common *Common
609 )
610 {
611  cholmod_sparse *Lsparse ;
612 
613  /* ---------------------------------------------------------------------- */
614  /* get inputs */
615  /* ---------------------------------------------------------------------- */
616 
618  RETURN_IF_NULL (L, NULL) ;
620  Common->status = CHOLMOD_OK ;
621  DEBUG (CHOLMOD(dump_factor) (L, "start convert to matrix", Common)) ;
622 
623  /* ---------------------------------------------------------------------- */
624  /* convert to packed, monotonic, simplicial, numeric */
625  /* ---------------------------------------------------------------------- */
626 
627  /* leave as LL or LDL' */
628  if (!CHOLMOD(change_factor) (L->xtype, L->is_ll, FALSE, TRUE, TRUE, L,
629  Common))
630  {
631  ERROR (CHOLMOD_INVALID, "cannot convert L") ;
632  return (NULL) ;
633  }
634 
635  /* ---------------------------------------------------------------------- */
636  /* create Lsparse */
637  /* ---------------------------------------------------------------------- */
638 
639  /* allocate the header for Lsparse, the sparse matrix version of L */
640  Lsparse = CHOLMOD(malloc) (sizeof (cholmod_sparse), 1, Common) ;
641  if (Common->status < CHOLMOD_OK)
642  {
643  return (NULL) ; /* out of memory */
644  }
645 
646  /* transfer the contents from L to Lsparse */
647  Lsparse->nrow = L->n ;
648  Lsparse->ncol = L->n ;
649  Lsparse->p = L->p ;
650  Lsparse->i = L->i ;
651  Lsparse->x = L->x ;
652  Lsparse->z = L->z ;
653  Lsparse->nz = NULL ;
654  Lsparse->stype = 0 ;
655  Lsparse->itype = L->itype ;
656  Lsparse->xtype = L->xtype ;
657  Lsparse->dtype = L->dtype ;
658  Lsparse->sorted = TRUE ;
659  Lsparse->packed = TRUE ;
660  Lsparse->nzmax = L->nzmax ;
661  ASSERT (CHOLMOD(dump_sparse) (Lsparse, "Lsparse", Common) >= 0) ;
662 
663  /* ---------------------------------------------------------------------- */
664  /* convert L to symbolic, but do not free contents transfered to Lsparse */
665  /* ---------------------------------------------------------------------- */
666 
667  L->p = NULL ;
668  L->i = NULL ;
669  L->x = NULL ;
670  L->z = NULL ;
671  L->xtype = CHOLMOD_PATTERN ;
673  Common) ;
674 
675  return (Lsparse) ;
676 }
677 
678 
679 /* ========================================================================== */
680 /* === cholmod_copy_factor ================================================== */
681 /* ========================================================================== */
682 
683 /* Create an exact copy of a factor, with one exception:
684  *
685  * Entries in unused space are not copied (they might not be initialized,
686  * and copying them would cause program checkers such as purify and
687  * valgrind to complain).
688  *
689  * Note that a supernodal L cannot be zomplex.
690  */
691 
693 (
694  /* ---- input ---- */
695  cholmod_factor *L, /* factor to copy */
696  /* --------------- */
697  cholmod_common *Common
698 )
699 {
700  cholmod_factor *L2 ;
701  double *Lx, *L2x, *Lz, *L2z ;
702  Int *Perm, *ColCount, *Lp, *Li, *Lnz, *Lnext, *Lprev, *Lsuper, *Lpi, *Lpx,
703  *Ls, *Perm2, *ColCount2, *L2p, *L2i, *L2nz, *L2next, *L2prev, *L2super,
704  *L2pi, *L2px, *L2s ;
705  Int n, j, p, pend, s, xsize, ssize, nsuper ;
706 
707  /* ---------------------------------------------------------------------- */
708  /* get inputs */
709  /* ---------------------------------------------------------------------- */
710 
712  RETURN_IF_NULL (L, NULL) ;
714  Common->status = CHOLMOD_OK ;
715  DEBUG (CHOLMOD(dump_factor) (L, "start copy", Common)) ;
716 
717  n = L->n ;
718 
719  /* ---------------------------------------------------------------------- */
720  /* allocate a simplicial symbolic factor */
721  /* ---------------------------------------------------------------------- */
722 
723  /* allocates L2->Perm and L2->ColCount */
724  L2 = CHOLMOD(allocate_factor) (n, Common) ;
725  if (Common->status < CHOLMOD_OK)
726  {
727  return (NULL) ; /* out of memory */
728  }
729  ASSERT (L2->xtype == CHOLMOD_PATTERN && !(L2->is_super)) ;
730 
731  Perm = L->Perm ;
732  ColCount = L->ColCount ;
733  Perm2 = L2->Perm ;
734  ColCount2 = L2->ColCount ;
735  L2->ordering = L->ordering ;
736 
737  for (j = 0 ; j < n ; j++)
738  {
739  Perm2 [j] = Perm [j] ;
740  }
741  for (j = 0 ; j < n ; j++)
742  {
743  ColCount2 [j] = ColCount [j] ;
744  }
745  L2->is_ll = L->is_ll ;
746 
747  /* ---------------------------------------------------------------------- */
748  /* copy the rest of the factor */
749  /* ---------------------------------------------------------------------- */
750 
751  if (L->xtype != CHOLMOD_PATTERN && !(L->super))
752  {
753 
754  /* ------------------------------------------------------------------ */
755  /* allocate a simplicial numeric factor */
756  /* ------------------------------------------------------------------ */
757 
758  /* allocate L2->p, L2->nz, L2->prev, L2->next, L2->i, and L2->x.
759  * packed = -1 so that cholmod_change_factor allocates space of
760  * size L2->nzmax */
761  L2->nzmax = L->nzmax ;
762  if (!CHOLMOD(change_factor) (L->xtype, L->is_ll, FALSE, -1, TRUE,
763  L2, Common))
764  {
765  CHOLMOD(free_factor) (&L2, Common) ;
766  return (NULL) ; /* out of memory */
767  }
768  ASSERT (L->nzmax == L2->nzmax) ;
769 
770  /* ------------------------------------------------------------------ */
771  /* copy the contents of a simplicial numeric factor */
772  /* ------------------------------------------------------------------ */
773 
774  Lp = L->p ;
775  Li = L->i ;
776  Lx = L->x ;
777  Lz = L->z ;
778  Lnz = L->nz ;
779  Lnext = L->next ;
780  Lprev = L->prev ;
781 
782  L2p = L2->p ;
783  L2i = L2->i ;
784  L2x = L2->x ;
785  L2z = L2->z ;
786  L2nz = L2->nz ;
787  L2next = L2->next ;
788  L2prev = L2->prev ;
789  L2->xtype = L->xtype ;
790  L2->dtype = L->dtype ;
791 
792  for (j = 0 ; j <= n ; j++)
793  {
794  L2p [j] = Lp [j] ;
795  }
796 
797  for (j = 0 ; j < n+2 ; j++)
798  {
799  L2prev [j] = Lprev [j] ;
800  }
801 
802  for (j = 0 ; j < n+2 ; j++)
803  {
804  L2next [j] = Lnext [j] ;
805  }
806 
807  for (j = 0 ; j < n ; j++)
808  {
809  L2nz [j] = Lnz [j] ;
810  }
811 
812  for (j = 0 ; j < n ; j++)
813  {
814  p = Lp [j] ;
815  pend = p + Lnz [j] ;
816  for ( ; p < pend ; p++)
817  {
818  L2i [p] = Li [p] ;
819  }
820  p = Lp [j] ;
821 
822  if (L->xtype == CHOLMOD_REAL)
823  {
824  for ( ; p < pend ; p++)
825  {
826  L2x [p] = Lx [p] ;
827  }
828  }
829  else if (L->xtype == CHOLMOD_COMPLEX)
830  {
831  for ( ; p < pend ; p++)
832  {
833  L2x [2*p ] = Lx [2*p ] ;
834  L2x [2*p+1] = Lx [2*p+1] ;
835  }
836  }
837  else if (L->xtype == CHOLMOD_ZOMPLEX)
838  {
839  for ( ; p < pend ; p++)
840  {
841  L2x [p] = Lx [p] ;
842  L2z [p] = Lz [p] ;
843  }
844  }
845 
846  }
847 
848  }
849  else if (L->is_super)
850  {
851 
852  /* ------------------------------------------------------------------ */
853  /* copy a supernodal factor */
854  /* ------------------------------------------------------------------ */
855 
856  xsize = L->xsize ;
857  ssize = L->ssize ;
858  nsuper = L->nsuper ;
859 
860  L2->xsize = xsize ;
861  L2->ssize = ssize ;
862  L2->nsuper = nsuper ;
863 
864  /* allocate L2->super, L2->pi, L2->px, and L2->s. Allocate L2->x if
865  * L is numeric */
866  if (!CHOLMOD(change_factor) (L->xtype, TRUE, TRUE, TRUE, TRUE, L2,
867  Common))
868  {
869  CHOLMOD(free_factor) (&L2, Common) ;
870  return (NULL) ; /* out of memory */
871  }
872 
873  ASSERT (L2->s != NULL) ;
874 
875  /* ------------------------------------------------------------------ */
876  /* copy the contents of a supernodal factor */
877  /* ------------------------------------------------------------------ */
878 
879  Lsuper = L->super ;
880  Lpi = L->pi ;
881  Lpx = L->px ;
882  Ls = L->s ;
883  Lx = L->x ;
884 
885  L2super = L2->super ;
886  L2pi = L2->pi ;
887  L2px = L2->px ;
888  L2s = L2->s ;
889  L2x = L2->x ;
890 
891  L2->maxcsize = L->maxcsize ;
892  L2->maxesize = L->maxesize ;
893 
894  for (s = 0 ; s <= nsuper ; s++)
895  {
896  L2super [s] = Lsuper [s] ;
897  }
898  for (s = 0 ; s <= nsuper ; s++)
899  {
900  L2pi [s] = Lpi [s] ;
901  }
902  for (s = 0 ; s <= nsuper ; s++)
903  {
904  L2px [s] = Lpx [s] ;
905  }
906 
907  L2s [0] = 0 ;
908  for (p = 0 ; p < ssize ; p++)
909  {
910  L2s [p] = Ls [p] ;
911  }
912 
913  if (L->xtype == CHOLMOD_REAL)
914  {
915  for (p = 0 ; p < xsize ; p++)
916  {
917  L2x [p] = Lx [p] ;
918  }
919  }
920  else if (L->xtype == CHOLMOD_COMPLEX)
921  {
922  for (p = 0 ; p < 2*xsize ; p++)
923  {
924  L2x [p] = Lx [p] ;
925  }
926  }
927  }
928 
929  L2->minor = L->minor ;
930  L2->is_monotonic = L->is_monotonic ;
931 
932  DEBUG (CHOLMOD(dump_factor) (L2, "L2 got copied", Common)) ;
933  ASSERT (L2->xtype == L->xtype && L2->is_super == L->is_super) ;
934  return (L2) ;
935 }
int CHOLMOD() reallocate_column(size_t j, size_t need, cholmod_factor *L, cholmod_common *Common)
#define CHOLMOD_TOO_LARGE
int CHOLMOD() realloc_multiple(size_t nnew, int nint, int xtype, void **I, void **J, void **X, void **Z, size_t *nold_p, cholmod_common *Common)
#define Int
size_t CHOLMOD() add_size_t(size_t a, size_t b, int *ok)
#define CHOLMOD_COMPLEX
#define FALSE
#define PRINT1(params)
#define RETURN_IF_NULL_COMMON(result)
int CHOLMOD() pack_factor(cholmod_factor *L, cholmod_common *Common)
struct cholmod_factor_struct cholmod_factor
int CHOLMOD() reallocate_factor(size_t nznew, cholmod_factor *L, cholmod_common *Common)
#define CHOLMOD_PATTERN
#define CHOLMOD(name)
cholmod_factor *CHOLMOD() copy_factor(cholmod_factor *L, cholmod_common *Common)
#define CHOLMOD_REAL
#define NULL
#define Int_max
#define ASSERT(expression)
#define PRINT2(params)
#define ID
int CHOLMOD() free_factor(cholmod_factor **LHandle, cholmod_common *Common)
#define DTYPE
#define CHOLMOD_INVALID
#define CHOLMOD_OK
#define CHOLMOD_OUT_OF_MEMORY
#define Size_max
struct cholmod_sparse_struct cholmod_sparse
#define RETURN_IF_NULL(A, result)
#define DEBUG(statement)
int CHOLMOD() change_factor(int to_xtype, int to_ll, int to_super, int to_packed, int to_monotonic, cholmod_factor *L, cholmod_common *Common)
#define MIN(a, b)
int CHOLMOD() dump_factor(cholmod_factor *L, char *name, cholmod_common *Common)
cholmod_sparse *CHOLMOD() factor_to_sparse(cholmod_factor *L, cholmod_common *Common)
int n
#define ERROR(status, msg)
#define TRUE
#define RETURN_IF_XTYPE_INVALID(A, xtype1, xtype2, result)
#define CHOLMOD_ZOMPLEX
#define CHOLMOD_NATURAL
cholmod_factor *CHOLMOD() allocate_factor(size_t n, cholmod_common *Common)
#define ITYPE