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