Amesos Package Browser (Single Doxygen Collection)  Development
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
amesos_t_cholmod_change_factor.c
Go to the documentation of this file.
1 /* ========================================================================== */
2 /* === Core/t_cholmod_change_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 /* Template routine for cholmod_change_factor. All xtypes supported. */
15 
17 
18 /* ========================================================================== */
19 /* === t_change_simplicial_numeric ========================================== */
20 /* ========================================================================== */
21 
22 static void TEMPLATE (change_simplicial_numeric)
23 (
24  cholmod_factor *L,
25  Int to_ll,
26  Int to_packed,
27  Int *newLi,
28  double *newLx,
29  double *newLz,
30  Int lnz,
31  Int grow,
32  double grow1,
33  Int grow2,
34  Int make_ll,
35  Int make_monotonic,
36  Int make_ldl,
37  cholmod_common *Common
38 )
39 {
40  double xlen, dj [1], ljj [1], lj2 [1] ;
41  double *Lx, *Lz ;
42  Int *Lp, *Li, *Lnz ;
43  Int n, j, len, pnew, pold, k, p, pend ;
44 
45  n = L->n ;
46  Lp = L->p ;
47  Li = L->i ;
48  Lx = L->x ;
49  Lz = L->z ;
50  Lnz = L->nz ;
51 
52  if (make_ll)
53  {
54  L->minor = n ;
55  }
56 
57  if (make_monotonic)
58  {
59 
60  /* ------------------------------------------------------------------ */
61  /* reorder the columns to make them monotonic */
62  /* ------------------------------------------------------------------ */
63 
64  pnew = 0 ;
65  for (j = 0 ; j < n ; j++)
66  {
67  /* copy and pack column j */
68  len = Lnz [j] ;
69  PRINT2 (("j: "ID" Lnz[j] "ID" len "ID" p "ID"\n",
70  j, Lnz [j], len, pnew)) ;
71  pold = Lp [j] ;
72  ASSERT (Li [pold] == j) ;
73 
74  if (make_ll)
75  {
76 
77  /* ---------------------------------------------------------- */
78  /* copy and convert LDL' to LL' */
79  /* ---------------------------------------------------------- */
80 
81  /* dj = Lx [pold] ; */
82  ASSIGN_REAL (dj,0, Lx,pold) ;
83 
84  if (IS_LE_ZERO (dj [0]))
85  {
86  /* Conversion has failed; matrix is not positive definite.
87  * Do not modify the column so that the LDL' factorization
88  * can be restored if desired, by converting back to LDL'.
89  * Continue the conversion, but flag the error. */
90  if (L->minor == (size_t) n)
91  {
92  ERROR (CHOLMOD_NOT_POSDEF, "L not positive definite") ;
93  L->minor = j ;
94  }
95  for (k = 0 ; k < len ; k++)
96  {
97  newLi [pnew + k] = Li [pold + k] ;
98  /* newLx [pnew + k] = Lx [pold + k] ; */
99  ASSIGN (newLx, newLz, pnew+k, Lx, Lz, pold+k) ;
100  }
101  }
102  else
103  {
104  ljj [0] = sqrt (dj [0]) ;
105  newLi [pnew] = j ;
106  /* newLx [pnew] = ljj ; */
107  ASSIGN_REAL (newLx, pnew, ljj, 0) ;
108  CLEAR_IMAG (newLx, newLz, pnew) ;
109 
110  for (k = 1 ; k < len ; k++)
111  {
112  newLi [pnew + k] = Li [pold + k] ;
113  /* newLx [pnew + k] = Lx [pold + k] * ljj ; */
114  MULT_REAL (newLx, newLz, pnew+k, Lx, Lz, pold+k, ljj,0);
115  }
116  }
117 
118  }
119  else if (make_ldl)
120  {
121 
122  /* ---------------------------------------------------------- */
123  /* copy and convert LL' to LDL' */
124  /* ---------------------------------------------------------- */
125 
126  /* ljj = Lx [pold] ; */
127  ASSIGN_REAL (ljj, 0, Lx, pold) ;
128 
129  if (ljj [0] <= 0)
130  {
131  /* matrix is not positive-definite; copy column as-is */
132  for (k = 0 ; k < len ; k++)
133  {
134  newLi [pnew + k] = Li [pold + k] ;
135  /* newLx [pnew + k] = Lx [pold + k] ; */
136  ASSIGN (newLx, newLz, pnew+k, Lx, Lz, pold+k) ;
137  }
138  }
139  else
140  {
141  newLi [pnew] = j ;
142  /* newLx [pnew] = ljj*ljj ; */
143  lj2 [0] = ljj [0] * ljj [0] ;
144  ASSIGN_REAL (newLx, pnew, lj2, 0) ;
145  CLEAR_IMAG (newLx, newLz, pnew) ;
146 
147  for (k = 1 ; k < len ; k++)
148  {
149  newLi [pnew + k] = Li [pold + k] ;
150  /* newLx [pnew + k] = Lx [pold + k] / ljj ; */
151  DIV_REAL (newLx, newLz, pnew+k, Lx, Lz, pold+k, ljj,0) ;
152  }
153  }
154 
155  }
156  else
157  {
158 
159  /* ---------------------------------------------------------- */
160  /* copy and leave LL' or LDL' as-is */
161  /* ---------------------------------------------------------- */
162 
163  for (k = 0 ; k < len ; k++)
164  {
165  newLi [pnew + k] = Li [pold + k] ;
166  /* newLx [pnew + k] = Lx [pold + k] ; */
167  ASSIGN (newLx, newLz, pnew+k, Lx, Lz, pold+k) ;
168  }
169  }
170 
171  Lp [j] = pnew ;
172 
173  /* compute len in double to avoid integer overflow */
174  if (grow)
175  {
176  xlen = (double) len ;
177  xlen = grow1 * xlen + grow2 ;
178  xlen = MIN (xlen, n-j) ;
179  len = (Int) xlen ;
180  }
181  ASSERT (len >= Lnz [j] && len <= n-j) ;
182  pnew += len ;
183  ASSERT (pnew > 0) ; /* integer overflow case already covered */
184  }
185  Lp [n] = pnew ;
186  PRINT1 (("final pnew = "ID", lnz "ID" lnzmax %g\n",
187  pnew, lnz, (double) L->nzmax)) ;
188  ASSERT (pnew <= lnz) ;
189 
190  /* free the old L->i and L->x and replace with the new ones */
191  CHOLMOD(free) (L->nzmax, sizeof (Int), L->i, Common) ;
192 
193 #ifdef REAL
194  CHOLMOD(free) (L->nzmax, sizeof (double), L->x, Common) ;
195 #elif defined (COMPLEX)
196  CHOLMOD(free) (L->nzmax, 2*sizeof (double), L->x, Common) ;
197 #else
198  CHOLMOD(free) (L->nzmax, sizeof (double), L->x, Common) ;
199  CHOLMOD(free) (L->nzmax, sizeof (double), L->z, Common) ;
200 #endif
201 
202  L->i = newLi ;
203  L->x = newLx ;
204  L->z = newLz ;
205  L->nzmax = lnz ;
206 
207  /* reconstruct the link list */
208  natural_list (L) ;
209 
210  }
211  else if (to_packed)
212  {
213 
214  /* ------------------------------------------------------------------ */
215  /* already monotonic, just pack the columns of L */
216  /* ------------------------------------------------------------------ */
217 
218  pnew = 0 ;
219 
220  if (make_ll)
221  {
222 
223  /* -------------------------------------------------------------- */
224  /* pack and convert LDL' to LL' */
225  /* -------------------------------------------------------------- */
226 
227  for (j = 0 ; j < n ; j++)
228  {
229  /* pack column j */
230  pold = Lp [j] ;
231  len = Lnz [j] ;
232  ASSERT (len > 0) ;
233  ASSERT (Li [pold] == j) ;
234  PRINT2 (("col "ID" pnew "ID" pold "ID"\n", j, pnew, pold)) ;
235 
236  /* dj = Lx [pold] ; */
237  ASSIGN_REAL (dj,0, Lx,pold) ;
238 
239  if (IS_LE_ZERO (dj [0]))
240  {
241  /* Conversion has failed; matrix is not positive definite.
242  * Do not modify the column so that the LDL' factorization
243  * can be restored if desired, by converting back to LDL'.
244  * Continue the conversion, but flag the error. */
245  if (L->minor == (size_t) n)
246  {
247  ERROR (CHOLMOD_NOT_POSDEF, "L not positive definite") ;
248  L->minor = j ;
249  }
250  for (k = 0 ; k < len ; k++)
251  {
252  Li [pnew + k] = Li [pold + k] ;
253  /* Lx [pnew + k] = Lx [pold + k] ; */
254  ASSIGN (Lx, Lz, pnew+k, Lx, Lz, pold+k) ;
255  }
256  }
257  else
258  {
259  ljj [0] = sqrt (dj [0]) ;
260  Li [pnew] = j ;
261 
262  /* Lx [pnew] = ljj ; */
263  ASSIGN_REAL (Lx, pnew, ljj, 0) ;
264  CLEAR_IMAG (Lx, Lz, pnew) ;
265 
266  for (k = 1 ; k < len ; k++)
267  {
268  Li [pnew + k] = Li [pold + k] ;
269  /* Lx [pnew + k] = Lx [pold + k] * ljj ; */
270  MULT_REAL (Lx, Lz, pnew+k, Lx, Lz, pold+k, ljj,0) ;
271  }
272  }
273  Lp [j] = pnew ;
274  pnew += len ;
275  }
276 
277  }
278  else if (make_ldl)
279  {
280 
281  /* -------------------------------------------------------------- */
282  /* pack and convert LL' to LDL' */
283  /* -------------------------------------------------------------- */
284 
285  for (j = 0 ; j < n ; j++)
286  {
287  /* pack column j */
288  pold = Lp [j] ;
289  len = Lnz [j] ;
290 
291  /* ljj = Lx [pold] ; */
292  ASSIGN_REAL (ljj, 0, Lx, pold) ;
293 
294  ASSERT (len > 0) ;
295  PRINT2 (("col "ID" pnew "ID" pold "ID"\n", j, pnew, pold)) ;
296  if (ljj [0] <= 0)
297  {
298  /* matrix is not positive-definite; pack column as-is */
299  for (k = 0 ; k < len ; k++)
300  {
301  Li [pnew + k] = Li [pold + k] ;
302  /* Lx [pnew + k] = Lx [pold + k] ; */
303  ASSIGN (Lx, Lz, pnew+k, Lx, Lz, pold+k) ;
304  }
305  }
306  else
307  {
308  Li [pnew] = Li [pold] ;
309 
310  /* Lx [pnew] = ljj*ljj ; */
311  lj2 [0] = ljj [0] * ljj [0] ;
312  ASSIGN_REAL (Lx, pnew, lj2, 0) ;
313  CLEAR_IMAG (Lx, Lz, pnew) ;
314 
315  for (k = 1 ; k < len ; k++)
316  {
317  Li [pnew + k] = Li [pold + k] ;
318  /* Lx [pnew + k] = Lx [pold + k] / ljj ; */
319  DIV_REAL (Lx, Lz, pnew+k, Lx, Lz, pold+k, ljj,0) ;
320  }
321  }
322  Lp [j] = pnew ;
323  pnew += len ;
324  }
325 
326  }
327  else
328  {
329 
330  /* ---------------------------------------------------------- */
331  /* pack and leave LL' or LDL' as-is */
332  /* ---------------------------------------------------------- */
333 
334  for (j = 0 ; j < n ; j++)
335  {
336  /* pack column j */
337  pold = Lp [j] ;
338  len = Lnz [j] ;
339  ASSERT (len > 0) ;
340  PRINT2 (("col "ID" pnew "ID" pold "ID"\n", j, pnew, pold)) ;
341  if (pnew < pold)
342  {
343  PRINT2 ((" pack this column\n")) ;
344  for (k = 0 ; k < len ; k++)
345  {
346  Li [pnew + k] = Li [pold + k] ;
347  /* Lx [pnew + k] = Lx [pold + k] ; */
348  ASSIGN (Lx, Lz, pnew+k, Lx, Lz, pold+k) ;
349  }
350  Lp [j] = pnew ;
351  }
352  pnew += len ;
353  }
354  }
355 
356  Lp [n] = pnew ;
357  PRINT2 (("Lp [n] = "ID"\n", pnew)) ;
358 
359  }
360  else if (make_ll)
361  {
362 
363  /* ------------------------------------------------------------------ */
364  /* convert LDL' to LL', but do so in-place */
365  /* ------------------------------------------------------------------ */
366 
367  for (j = 0 ; j < n ; j++)
368  {
369  p = Lp [j] ;
370  pend = p + Lnz [j] ;
371 
372  /* dj = Lx [p] ; */
373  ASSIGN_REAL (dj,0, Lx,p) ;
374 
375  if (IS_LE_ZERO (dj [0]))
376  {
377  /* Conversion has failed; matrix is not positive definite.
378  * Do not modify the column so that the LDL' factorization
379  * can be restored if desired, by converting back to LDL'.
380  * Continue the conversion, but flag the error. */
381  if (L->minor == (size_t) n)
382  {
383  ERROR (CHOLMOD_NOT_POSDEF, "L not positive definite") ;
384  L->minor = j ;
385  }
386  }
387  else
388  {
389  ljj [0] = sqrt (dj [0]) ;
390  /* Lx [p] = ljj ; */
391  ASSIGN_REAL (Lx,p, ljj,0) ;
392  CLEAR_IMAG (Lx, Lz, p) ;
393 
394  for (p++ ; p < pend ; p++)
395  {
396  /* Lx [p] *= ljj ; */
397  MULT_REAL (Lx,Lz,p, Lx,Lz,p, ljj,0) ;
398  }
399  }
400  }
401 
402  }
403  else if (make_ldl)
404  {
405 
406  /* ------------------------------------------------------------------ */
407  /* convert LL' to LDL', but do so in-place */
408  /* ------------------------------------------------------------------ */
409 
410  for (j = 0 ; j < n ; j++)
411  {
412  p = Lp [j] ;
413  pend = p + Lnz [j] ;
414 
415  /* ljj = Lx [p] ; */
416  ASSIGN_REAL (ljj, 0, Lx, p) ;
417 
418  if (ljj [0] > 0)
419  {
420  /* Lx [p] = ljj*ljj ; */
421  lj2 [0] = ljj [0] * ljj [0] ;
422  ASSIGN_REAL (Lx, p, lj2, 0) ;
423  CLEAR_IMAG (Lx, Lz, p) ;
424 
425  for (p++ ; p < pend ; p++)
426  {
427  /* Lx [p] /= ljj ; */
428  DIV_REAL (Lx,Lz,p, Lx,Lz,p, ljj,0) ;
429  }
430  }
431  }
432  }
433 
434  L->is_ll = to_ll ;
435 
436  DEBUG (CHOLMOD(dump_factor) (L, "done change simplicial numeric", Common)) ;
437 }
438 
439 
440 /* ========================================================================== */
441 /* === t_ll_super_to_simplicial_numeric ===================================== */
442 /* ========================================================================== */
443 
444 /* A supernodal L can only be real or complex, not zomplex */
445 
446 #ifndef ZOMPLEX
447 
448 static void TEMPLATE (ll_super_to_simplicial_numeric)
449 (
450  cholmod_factor *L,
451  Int to_packed,
452  Int to_ll,
453  cholmod_common *Common
454 )
455 {
456  double ljj [1], lj2 [1] ;
457  double *Lx ;
458  Int *Ls, *Lpi, *Lpx, *Super, *Lp, *Li, *Lnz ;
459  Int n, lnz, s, nsuper, p, psi, psx, psend, nsrow, nscol, ii, jj, j, k1, k2,
460  q ;
461 
462  L->is_ll = to_ll ;
463 
464  Lp = L->p ;
465  Li = L->i ;
466  Lx = L->x ;
467  Lnz = L->nz ;
468  lnz = L->nzmax ;
469 
470  n = L->n ;
471  nsuper = L->nsuper ;
472  Lpi = L->pi ;
473  Lpx = L->px ;
474  Ls = L->s ;
475  Super = L->super ;
476 
477  p = 0 ;
478 
479  for (s = 0 ; s < nsuper ; s++)
480  {
481  k1 = Super [s] ;
482  k2 = Super [s+1] ;
483  psi = Lpi [s] ;
484  psend = Lpi [s+1] ;
485  psx = Lpx [s] ;
486  nsrow = psend - psi ;
487  nscol = k2 - k1 ;
488 
489  for (jj = 0 ; jj < nscol ; jj++)
490  {
491  /* column j of L starts here */
492  j = jj + k1 ;
493 
494  if (to_ll)
495  {
496  if (to_packed)
497  {
498 
499  /* ------------------------------------------------------ */
500  /* convert to LL' packed */
501  /* ------------------------------------------------------ */
502 
503  Lp [j] = p ;
504  PRINT2 (("Col j "ID" p "ID"\n", j, p)) ;
505  for (ii = jj ; ii < nsrow ; ii++)
506  {
507  /* get L(i,j) from supernode and store in column j */
508  ASSERT (p < (Int) (L->xsize) && p <= psx+ii+jj*nsrow) ;
509  Li [p] = Ls [psi + ii] ;
510  /* Lx [p] = Lx [psx + ii + jj*nsrow] ; */
511  q = psx + ii + jj*nsrow ;
512  ASSIGN (Lx,-,p, Lx,-,q) ;
513  PRINT2 ((" i "ID" ", Li [p])) ;
514  XPRINT2 (Lx,-,q) ;
515  PRINT2 (("\n")) ;
516  p++ ;
517  }
518  Lnz [j] = p - Lp [j] ;
519 
520  }
521  else
522  {
523 
524  /* ------------------------------------------------------ */
525  /* convert to LL' unpacked */
526  /* ------------------------------------------------------ */
527 
528  p = psx + jj + jj*nsrow ;
529  Lp [j] = p ;
530  Li [p] = j ;
531  Lnz [j] = nsrow - jj ;
532  p++ ;
533  for (ii = jj + 1 ; ii < nsrow ; ii++)
534  {
535  /* get L(i,j) from supernode and store in column j */
536  Li [psx + ii + jj*nsrow] = Ls [psi + ii] ;
537  }
538 
539  }
540  }
541  else
542  {
543  if (to_packed)
544  {
545 
546  /* ------------------------------------------------------ */
547  /* convert to LDL' packed */
548  /* ------------------------------------------------------ */
549 
550  Lp [j] = p ;
551  PRINT2 (("Col j "ID" p "ID"\n", Lp [j], p)) ;
552  /* ljj = Lx [psx + jj + jj*nsrow] ; */
553  ASSIGN_REAL (ljj, 0, Lx, psx + jj + jj*nsrow) ;
554 
555  if (ljj [0] <= 0)
556  {
557  /* the matrix is not positive definite; do not divide */
558  /* Lx [p] = ljj ; */
559  ASSIGN_REAL (Lx, p, ljj, 0) ;
560  CLEAR_IMAG (Lx, Lz, p) ;
561  ljj [0] = 1 ;
562  }
563  else
564  {
565  lj2 [0] = ljj [0] * ljj [0] ;
566  /* Lx [p] = ljj*ljj ; */
567  ASSIGN_REAL (Lx, p, lj2, 0) ;
568  CLEAR_IMAG (Lx, Lz, p) ;
569  }
570  Li [p] = j ;
571  p++ ;
572  for (ii = jj + 1 ; ii < nsrow ; ii++)
573  {
574  /* get L(i,j) from supernode and store in column j */
575  ASSERT (p < (Int) (L->xsize) && p <= psx+ii+jj*nsrow) ;
576  Li [p] = Ls [psi + ii] ;
577 
578  /* Lx [p] = Lx [psx + ii + jj*nsrow] / ljj ; */
579  q = psx + ii + jj*nsrow ;
580  DIV_REAL (Lx, Lz, p, Lx, Lz, q, ljj,0) ;
581 
582  PRINT2 ((" i "ID" %g\n", Li [p], Lx [p])) ;
583  p++ ;
584  }
585  Lnz [j] = p - Lp [j] ;
586 
587  }
588  else
589  {
590 
591  /* ------------------------------------------------------ */
592  /* convert to LDL' unpacked */
593  /* ------------------------------------------------------ */
594 
595  p = psx + jj + jj*nsrow ;
596  Lp [j] = p ;
597 
598  /* ljj = Lx [p] ; */
599  ASSIGN_REAL (ljj,0, Lx,p) ;
600 
601  if (ljj [0] <= 0)
602  {
603  /* the matrix is not positive definite; do not divide */
604  /* Lx [p] = ljj ; */
605  ASSIGN_REAL (Lx, p, ljj, 0) ;
606  CLEAR_IMAG (Lx, Lz, p) ;
607  ljj [0] = 1 ;
608  }
609  else
610  {
611  lj2 [0] = ljj [0] * ljj [0] ;
612  /* Lx [p] = ljj*ljj ; */
613  ASSIGN_REAL (Lx, p, lj2, 0) ;
614  CLEAR_IMAG (Lx, Lz, p) ;
615  }
616  Li [p] = j ;
617  Lnz [j] = nsrow - jj ;
618  p++ ;
619  for (ii = jj + 1 ; ii < nsrow ; ii++)
620  {
621  /* get L(i,j) from supernode and store in column j */
622  Li [psx + ii + jj*nsrow] = Ls [psi + ii] ;
623 
624  /* Lx [psx + ii + jj*nsrow] /= ljj ; */
625  q = psx + ii + jj*nsrow ;
626  DIV_REAL (Lx, Lz, q, Lx, Lz, q, ljj,0) ;
627  }
628  }
629  }
630  }
631  }
632 
633  if (to_packed)
634  {
635  Lp [n] = p ;
636  PRINT1 (("Final Lp "ID" n "ID" lnz "ID"\n", p, n, lnz)) ;
637  ASSERT (Lp [n] == lnz) ;
638  ASSERT (lnz <= (Int) (L->xsize)) ;
639  /* reduce size of L->x to match L->i. This cannot fail. */
640  L->x = CHOLMOD(realloc) (lnz,
641 #ifdef COMPLEX
642  2 *
643 #endif
644  sizeof (double), L->x, &(L->xsize), Common) ;
645  ASSERT (lnz == (Int) (L->xsize)) ;
646  Common->status = CHOLMOD_OK ;
647  }
648  else
649  {
650  Lp [n] = Lpx [nsuper] ;
651  ASSERT (MAX (1,Lp [n]) == (Int) (L->xsize)) ;
652  ASSERT (MAX (1,Lp [n]) == (Int) (L->nzmax)) ;
653  }
654 }
655 
656 #endif
657 
658 #undef PATTERN
659 #undef REAL
660 #undef COMPLEX
661 #undef ZOMPLEX
#define Int
#define PRINT1(params)
#define CHOLMOD(name)
static void TEMPLATE() ll_super_to_simplicial_numeric(cholmod_factor *L, Int to_packed, Int to_ll, cholmod_common *Common)
#define MAX(a, b)
#define ASSERT(expression)
#define PRINT2(params)
#define ID
#define CHOLMOD_NOT_POSDEF
#define CHOLMOD_OK
#define DEBUG(statement)
#define MIN(a, b)
int CHOLMOD() dump_factor(cholmod_factor *L, char *name, cholmod_common *Common)
#define IS_LE_ZERO(x)
static void TEMPLATE() change_simplicial_numeric(cholmod_factor *L, Int to_ll, Int to_packed, Int *newLi, double *newLx, double *newLz, Int lnz, Int grow, double grow1, Int grow2, Int make_ll, Int make_monotonic, Int make_ldl, cholmod_common *Common)
static void natural_list(cholmod_factor *L)
int n
#define ERROR(status, msg)
#define ASSIGN(c, s1, s2, p, split)