Amesos Package Browser (Single Doxygen Collection)  Development
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
amesos_cholmod_solve.c
Go to the documentation of this file.
1 /* ========================================================================== */
2 /* === Cholesky/cholmod_solve =============================================== */
3 /* ========================================================================== */
4 
5 /* -----------------------------------------------------------------------------
6  * CHOLMOD/Cholesky Module. Copyright (C) 2005-2006, Timothy A. Davis
7  * The CHOLMOD/Cholesky Module is licensed under Version 2.1 of the GNU
8  * Lesser General Public License. See lesser.txt for a text of the license.
9  * CHOLMOD is also available under other licenses; contact authors for details.
10  * http://www.cise.ufl.edu/research/sparse
11  * -------------------------------------------------------------------------- */
12 
13 /* Solve one of the following systems:
14  *
15  * Ax=b 0: CHOLMOD_A also applies the permutation L->Perm
16  * LDL'x=b 1: CHOLMOD_LDLt does not apply L->Perm
17  * LDx=b 2: CHOLMOD_LD
18  * DL'x=b 3: CHOLMOD_DLt
19  * Lx=b 4: CHOLMOD_L
20  * L'x=b 5: CHOLMOD_Lt
21  * Dx=b 6: CHOLMOD_D
22  * x=Pb 7: CHOLMOD_P apply a permutation (P is L->Perm)
23  * x=P'b 8: CHOLMOD_Pt apply an inverse permutation
24  *
25  * The factorization can be simplicial LDL', simplicial LL', or supernodal LL'.
26  * For an LL' factorization, D is the identity matrix. Thus CHOLMOD_LD and
27  * CHOLMOD_L solve the same system if an LL' factorization was performed,
28  * for example.
29  *
30  * The supernodal solver uses BLAS routines dtrsv, dgemv, dtrsm, and dgemm,
31  * or their complex counterparts ztrsv, zgemv, ztrsm, and zgemm.
32  *
33  * If both L and B are real, then X is returned real. If either is complex
34  * or zomplex, X is returned as either complex or zomplex, depending on the
35  * Common->prefer_zomplex parameter.
36  *
37  * Supports any numeric xtype (pattern-only matrices not supported).
38  *
39  * This routine does not check to see if the diagonal of L or D is zero,
40  * because sometimes a partial solve can be done with indefinite or singular
41  * matrix. If you wish to check in your own code, test L->minor. If
42  * L->minor == L->n, then the matrix has no zero diagonal entries.
43  * If k = L->minor < L->n, then L(k,k) is zero for an LL' factorization, or
44  * D(k,k) is zero for an LDL' factorization.
45  *
46  * This routine returns X as NULL only if it runs out of memory. If L is
47  * indefinite or singular, then X may contain Inf's or NaN's, but it will
48  * exist on output.
49  */
50 
51 #ifndef NCHOLESKY
52 
55 
56 
57 /* ========================================================================== */
58 /* === TEMPLATE ============================================================= */
59 /* ========================================================================== */
60 
61 #define REAL
62 #include "amesos_t_cholmod_solve.c"
63 
64 #define COMPLEX
65 #include "amesos_t_cholmod_solve.c"
66 
67 #define ZOMPLEX
68 #include "amesos_t_cholmod_solve.c"
69 
70 /* ========================================================================== */
71 /* === Permutation macro ==================================================== */
72 /* ========================================================================== */
73 
74 /* If Perm is NULL, it is interpretted as the identity permutation */
75 
76 #define P(k) ((Perm == NULL) ? (k) : Perm [k])
77 
78 
79 /* ========================================================================== */
80 /* === perm ================================================================= */
81 /* ========================================================================== */
82 
83 /* Y = B (P (1:nrow), k1 : min (k1+ncols,ncol)-1) where B is nrow-by-ncol.
84  *
85  * Creates a permuted copy of a contiguous set of columns of B.
86  * Y is already allocated on input. Y must be of sufficient size. Let nk be
87  * the number of columns accessed in B. Y->xtype determines the complexity of
88  * the result.
89  *
90  * If B is real and Y is complex (or zomplex), only the real part of B is
91  * copied into Y. The imaginary part of Y is set to zero.
92  *
93  * If B is complex (or zomplex) and Y is real, both the real and imaginary and
94  * parts of B are returned in Y. Y is returned as nrow-by-2*nk. The even
95  * columns of Y contain the real part of B and the odd columns contain the
96  * imaginary part of B. Y->nzmax must be >= 2*nrow*nk. Otherise, Y is
97  * returned as nrow-by-nk with leading dimension nrow. Y->nzmax must be >=
98  * nrow*nk.
99  *
100  * The case where the input (B) is real and the output (Y) is zomplex is
101  * not used.
102  */
103 
104 static void amesos_perm
105 (
106  /* ---- input ---- */
107  cholmod_dense *B, /* input matrix B */
108  Int *Perm, /* optional input permutation (can be NULL) */
109  Int k1, /* first column of B to copy */
110  Int ncols, /* last column to copy is min(k1+ncols,B->ncol)-1 */
111  /* ---- in/out --- */
112  cholmod_dense *Y /* output matrix Y, already allocated */
113 )
114 {
115  double *Yx, *Yz, *Bx, *Bz ;
116  Int k2, nk, p, k, j, nrow, ncol, d, dual, dj, j2 ;
117 
118  /* ---------------------------------------------------------------------- */
119  /* get inputs */
120  /* ---------------------------------------------------------------------- */
121 
122  ncol = B->ncol ;
123  nrow = B->nrow ;
124  k2 = MIN (k1+ncols, ncol) ;
125  nk = MAX (k2 - k1, 0) ;
126  dual = (Y->xtype == CHOLMOD_REAL && B->xtype != CHOLMOD_REAL) ? 2 : 1 ;
127  d = B->d ;
128  Bx = B->x ;
129  Bz = B->z ;
130  Yx = Y->x ;
131  Yz = Y->z ;
132  Y->nrow = nrow ;
133  Y->ncol = dual*nk ;
134  Y->d = nrow ;
135  ASSERT (((Int) Y->nzmax) >= nrow*nk*dual) ;
136 
137  /* ---------------------------------------------------------------------- */
138  /* Y = B (P (1:nrow), k1:k2-1) */
139  /* ---------------------------------------------------------------------- */
140 
141  switch (Y->xtype)
142  {
143 
144  case CHOLMOD_REAL:
145 
146  switch (B->xtype)
147  {
148 
149  case CHOLMOD_REAL:
150  /* Y real, B real */
151  for (j = k1 ; j < k2 ; j++)
152  {
153  dj = d*j ;
154  j2 = nrow * (j-k1) ;
155  for (k = 0 ; k < nrow ; k++)
156  {
157  p = P(k) + dj ;
158  Yx [k + j2] = Bx [p] ; /* real */
159  }
160  }
161  break ;
162 
163  case CHOLMOD_COMPLEX:
164  /* Y real, B complex. Y is nrow-by-2*nk */
165  for (j = k1 ; j < k2 ; j++)
166  {
167  dj = d*j ;
168  j2 = nrow * 2 * (j-k1) ;
169  for (k = 0 ; k < nrow ; k++)
170  {
171  p = P(k) + dj ;
172  Yx [k + j2 ] = Bx [2*p ] ; /* real */
173  Yx [k + j2 + nrow] = Bx [2*p+1] ; /* imag */
174  }
175  }
176  break ;
177 
178  case CHOLMOD_ZOMPLEX:
179  /* Y real, B zomplex. Y is nrow-by-2*nk */
180  for (j = k1 ; j < k2 ; j++)
181  {
182  dj = d*j ;
183  j2 = nrow * 2 * (j-k1) ;
184  for (k = 0 ; k < nrow ; k++)
185  {
186  p = P(k) + dj ;
187  Yx [k + j2 ] = Bx [p] ; /* real */
188  Yx [k + j2 + nrow] = Bz [p] ; /* imag */
189  }
190  }
191  break ;
192 
193  }
194  break ;
195 
196  case CHOLMOD_COMPLEX:
197 
198  switch (B->xtype)
199  {
200 
201  case CHOLMOD_REAL:
202  /* Y complex, B real */
203  for (j = k1 ; j < k2 ; j++)
204  {
205  dj = d*j ;
206  j2 = nrow * 2 * (j-k1) ;
207  for (k = 0 ; k < nrow ; k++)
208  {
209  p = P(k) + dj ;
210  Yx [2*k + j2] = Bx [p] ; /* real */
211  Yx [2*k+1 + j2] = 0 ; /* imag */
212  }
213  }
214  break ;
215 
216  case CHOLMOD_COMPLEX:
217  /* Y complex, B complex */
218  for (j = k1 ; j < k2 ; j++)
219  {
220  dj = d*j ;
221  j2 = nrow * 2 * (j-k1) ;
222  for (k = 0 ; k < nrow ; k++)
223  {
224  p = P(k) + dj ;
225  Yx [2*k + j2] = Bx [2*p ] ; /* real */
226  Yx [2*k+1 + j2] = Bx [2*p+1] ; /* imag */
227  }
228  }
229  break ;
230 
231  case CHOLMOD_ZOMPLEX:
232  /* Y complex, B zomplex */
233  for (j = k1 ; j < k2 ; j++)
234  {
235  dj = d*j ;
236  j2 = nrow * 2 * (j-k1) ;
237  for (k = 0 ; k < nrow ; k++)
238  {
239  p = P(k) + dj ;
240  Yx [2*k + j2] = Bx [p] ; /* real */
241  Yx [2*k+1 + j2] = Bz [p] ; /* imag */
242  }
243  }
244  break ;
245 
246  }
247  break ;
248 
249  case CHOLMOD_ZOMPLEX:
250 
251  switch (B->xtype)
252  {
253 
254 #if 0
255  case CHOLMOD_REAL:
256  /* this case is not used */
257  break ;
258 #endif
259 
260  case CHOLMOD_COMPLEX:
261  /* Y zomplex, B complex */
262  for (j = k1 ; j < k2 ; j++)
263  {
264  dj = d*j ;
265  j2 = nrow * (j-k1) ;
266  for (k = 0 ; k < nrow ; k++)
267  {
268  p = P(k) + dj ;
269  Yx [k + j2] = Bx [2*p ] ; /* real */
270  Yz [k + j2] = Bx [2*p+1] ; /* imag */
271  }
272  }
273  break ;
274 
275  case CHOLMOD_ZOMPLEX:
276  /* Y zomplex, B zomplex */
277  for (j = k1 ; j < k2 ; j++)
278  {
279  dj = d*j ;
280  j2 = nrow * (j-k1) ;
281  for (k = 0 ; k < nrow ; k++)
282  {
283  p = P(k) + dj ;
284  Yx [k + j2] = Bx [p] ; /* real */
285  Yz [k + j2] = Bz [p] ; /* imag */
286  }
287  }
288  break ;
289 
290  }
291  break ;
292 
293  }
294 }
295 
296 
297 /* ========================================================================== */
298 /* === iperm ================================================================ */
299 /* ========================================================================== */
300 
301 /* X (P (1:nrow), k1 : min (k1+ncols,ncol)-1) = Y where X is nrow-by-ncol.
302  *
303  * Copies and permutes Y into a contiguous set of columns of X. X is already
304  * allocated on input. Y must be of sufficient size. Let nk be the number
305  * of columns accessed in X. X->xtype determines the complexity of the result.
306  *
307  * If X is real and Y is complex (or zomplex), only the real part of B is
308  * copied into X. The imaginary part of Y is ignored.
309  *
310  * If X is complex (or zomplex) and Y is real, both the real and imaginary and
311  * parts of Y are returned in X. Y is nrow-by-2*nk. The even
312  * columns of Y contain the real part of B and the odd columns contain the
313  * imaginary part of B. Y->nzmax must be >= 2*nrow*nk. Otherise, Y is
314  * nrow-by-nk with leading dimension nrow. Y->nzmax must be >= nrow*nk.
315  *
316  * The case where the input (Y) is complex and the output (X) is real,
317  * and the case where the input (Y) is zomplex and the output (X) is real,
318  * are not used.
319  */
320 
321 static void amesos_iperm
322 (
323  /* ---- input ---- */
324  cholmod_dense *Y, /* input matrix Y */
325  Int *Perm, /* optional input permutation (can be NULL) */
326  Int k1, /* first column of B to copy */
327  Int ncols, /* last column to copy is min(k1+ncols,B->ncol)-1 */
328  /* ---- in/out --- */
329  cholmod_dense *X /* output matrix X, already allocated */
330 )
331 {
332  double *Yx, *Yz, *Xx, *Xz ;
333  Int k2, nk, p, k, j, nrow, ncol, d, dj, j2 ;
334 
335  /* ---------------------------------------------------------------------- */
336  /* get inputs */
337  /* ---------------------------------------------------------------------- */
338 
339  ncol = X->ncol ;
340  nrow = X->nrow ;
341  k2 = MIN (k1+ncols, ncol) ;
342  nk = MAX (k2 - k1, 0) ;
343  d = X->d ;
344  Xx = X->x ;
345  Xz = X->z ;
346  Yx = Y->x ;
347  Yz = Y->z ;
348  ASSERT (((Int) Y->nzmax) >= nrow*nk*
349  ((X->xtype != CHOLMOD_REAL && Y->xtype == CHOLMOD_REAL) ? 2:1)) ;
350 
351  /* ---------------------------------------------------------------------- */
352  /* X (P (1:nrow), k1:k2-1) = Y */
353  /* ---------------------------------------------------------------------- */
354 
355  switch (Y->xtype)
356  {
357 
358  case CHOLMOD_REAL:
359 
360  switch (X->xtype)
361  {
362 
363  case CHOLMOD_REAL:
364  /* Y real, X real */
365  for (j = k1 ; j < k2 ; j++)
366  {
367  dj = d*j ;
368  j2 = nrow * (j-k1) ;
369  for (k = 0 ; k < nrow ; k++)
370  {
371  p = P(k) + dj ;
372  Xx [p] = Yx [k + j2] ; /* real */
373  }
374  }
375  break ;
376 
377  case CHOLMOD_COMPLEX:
378  /* Y real, X complex. Y is nrow-by-2*nk */
379  for (j = k1 ; j < k2 ; j++)
380  {
381  dj = d*j ;
382  j2 = nrow * 2 * (j-k1) ;
383  for (k = 0 ; k < nrow ; k++)
384  {
385  p = P(k) + dj ;
386  Xx [2*p ] = Yx [k + j2 ] ; /* real */
387  Xx [2*p+1] = Yx [k + j2 + nrow] ; /* imag */
388  }
389  }
390  break ;
391 
392  case CHOLMOD_ZOMPLEX:
393  /* Y real, X zomplex. Y is nrow-by-2*nk */
394  for (j = k1 ; j < k2 ; j++)
395  {
396  dj = d*j ;
397  j2 = nrow * 2 * (j-k1) ;
398  for (k = 0 ; k < nrow ; k++)
399  {
400  p = P(k) + dj ;
401  Xx [p] = Yx [k + j2 ] ; /* real */
402  Xz [p] = Yx [k + j2 + nrow] ; /* imag */
403  }
404  }
405  break ;
406 
407  }
408  break ;
409 
410  case CHOLMOD_COMPLEX:
411 
412  switch (X->xtype)
413  {
414 
415 #if 0
416  case CHOLMOD_REAL:
417  /* this case is not used */
418  break ;
419 #endif
420 
421  case CHOLMOD_COMPLEX:
422  /* Y complex, X complex */
423  for (j = k1 ; j < k2 ; j++)
424  {
425  dj = d*j ;
426  j2 = nrow * 2 * (j-k1) ;
427  for (k = 0 ; k < nrow ; k++)
428  {
429  p = P(k) + dj ;
430  Xx [2*p ] = Yx [2*k + j2] ; /* real */
431  Xx [2*p+1] = Yx [2*k+1 + j2] ; /* imag */
432  }
433  }
434  break ;
435 
436  case CHOLMOD_ZOMPLEX:
437  /* Y complex, X zomplex */
438  for (j = k1 ; j < k2 ; j++)
439  {
440  dj = d*j ;
441  j2 = nrow * 2 * (j-k1) ;
442  for (k = 0 ; k < nrow ; k++)
443  {
444  p = P(k) + dj ;
445  Xx [p] = Yx [2*k + j2] ; /* real */
446  Xz [p] = Yx [2*k+1 + j2] ; /* imag */
447  }
448  }
449  break ;
450 
451  }
452  break ;
453 
454  case CHOLMOD_ZOMPLEX:
455 
456  switch (X->xtype)
457  {
458 
459 #if 0
460  case CHOLMOD_REAL:
461  /* this case is not used */
462  break ;
463 #endif
464 
465  case CHOLMOD_COMPLEX:
466  /* Y zomplex, X complex */
467  for (j = k1 ; j < k2 ; j++)
468  {
469  dj = d*j ;
470  j2 = nrow * (j-k1) ;
471  for (k = 0 ; k < nrow ; k++)
472  {
473  p = P(k) + dj ;
474  Xx [2*p ] = Yx [k + j2] ; /* real */
475  Xx [2*p+1] = Yz [k + j2] ; /* imag */
476  }
477  }
478  break ;
479 
480  case CHOLMOD_ZOMPLEX:
481  /* Y zomplex, X zomplex */
482  for (j = k1 ; j < k2 ; j++)
483  {
484  dj = d*j ;
485  j2 = nrow * (j-k1) ;
486  for (k = 0 ; k < nrow ; k++)
487  {
488  p = P(k) + dj ;
489  Xx [p] = Yx [k + j2] ; /* real */
490  Xz [p] = Yz [k + j2] ; /* imag */
491  }
492  }
493  break ;
494 
495  }
496  break ;
497 
498  }
499 }
500 
501 
502 /* ========================================================================== */
503 /* === ptrans =============================================================== */
504 /* ========================================================================== */
505 
506 /* Y = B (P (1:nrow), k1 : min (k1+ncols,ncol)-1)' where B is nrow-by-ncol.
507  *
508  * Creates a permuted and transposed copy of a contiguous set of columns of B.
509  * Y is already allocated on input. Y must be of sufficient size. Let nk be
510  * the number of columns accessed in B. Y->xtype determines the complexity of
511  * the result.
512  *
513  * If B is real and Y is complex (or zomplex), only the real part of B is
514  * copied into Y. The imaginary part of Y is set to zero.
515  *
516  * If B is complex (or zomplex) and Y is real, both the real and imaginary and
517  * parts of B are returned in Y. Y is returned as 2*nk-by-nrow. The even
518  * rows of Y contain the real part of B and the odd rows contain the
519  * imaginary part of B. Y->nzmax must be >= 2*nrow*nk. Otherise, Y is
520  * returned as nk-by-nrow with leading dimension nk. Y->nzmax must be >=
521  * nrow*nk.
522  *
523  * The array transpose is performed, not the complex conjugate transpose.
524  */
525 
526 static void amesos_ptrans
527 (
528  /* ---- input ---- */
529  cholmod_dense *B, /* input matrix B */
530  Int *Perm, /* optional input permutation (can be NULL) */
531  Int k1, /* first column of B to copy */
532  Int ncols, /* last column to copy is min(k1+ncols,B->ncol)-1 */
533  /* ---- in/out --- */
534  cholmod_dense *Y /* output matrix Y, already allocated */
535 )
536 {
537  double *Yx, *Yz, *Bx, *Bz ;
538  Int k2, nk, p, k, j, nrow, ncol, d, dual, dj, j2 ;
539 
540  /* ---------------------------------------------------------------------- */
541  /* get inputs */
542  /* ---------------------------------------------------------------------- */
543 
544  ncol = B->ncol ;
545  nrow = B->nrow ;
546  k2 = MIN (k1+ncols, ncol) ;
547  nk = MAX (k2 - k1, 0) ;
548  dual = (Y->xtype == CHOLMOD_REAL && B->xtype != CHOLMOD_REAL) ? 2 : 1 ;
549  d = B->d ;
550  Bx = B->x ;
551  Bz = B->z ;
552  Yx = Y->x ;
553  Yz = Y->z ;
554  Y->nrow = dual*nk ;
555  Y->ncol = nrow ;
556  Y->d = dual*nk ;
557  ASSERT (((Int) Y->nzmax) >= nrow*nk*dual) ;
558 
559  /* ---------------------------------------------------------------------- */
560  /* Y = B (P (1:nrow), k1:k2-1)' */
561  /* ---------------------------------------------------------------------- */
562 
563  switch (Y->xtype)
564  {
565 
566  case CHOLMOD_REAL:
567 
568  switch (B->xtype)
569  {
570 
571  case CHOLMOD_REAL:
572  /* Y real, B real */
573  for (j = k1 ; j < k2 ; j++)
574  {
575  dj = d*j ;
576  j2 = j-k1 ;
577  for (k = 0 ; k < nrow ; k++)
578  {
579  p = P(k) + dj ;
580  Yx [j2 + k*nk] = Bx [p] ; /* real */
581  }
582  }
583  break ;
584 
585  case CHOLMOD_COMPLEX:
586  /* Y real, B complex. Y is 2*nk-by-nrow */
587  for (j = k1 ; j < k2 ; j++)
588  {
589  dj = d*j ;
590  j2 = 2*(j-k1) ;
591  for (k = 0 ; k < nrow ; k++)
592  {
593  p = P(k) + dj ;
594  Yx [j2 + k*2*nk] = Bx [2*p ] ; /* real */
595  Yx [j2+1 + k*2*nk] = Bx [2*p+1] ; /* imag */
596  }
597  }
598  break ;
599 
600  case CHOLMOD_ZOMPLEX:
601  /* Y real, B zomplex. Y is 2*nk-by-nrow */
602  for (j = k1 ; j < k2 ; j++)
603  {
604  dj = d*j ;
605  j2 = 2*(j-k1) ;
606  for (k = 0 ; k < nrow ; k++)
607  {
608  p = P(k) + dj ;
609  Yx [j2 + k*2*nk] = Bx [p] ; /* real */
610  Yx [j2+1 + k*2*nk] = Bz [p] ; /* imag */
611  }
612  }
613  break ;
614 
615  }
616  break ;
617 
618  case CHOLMOD_COMPLEX:
619 
620  switch (B->xtype)
621  {
622 
623  case CHOLMOD_REAL:
624  /* Y complex, B real */
625  for (j = k1 ; j < k2 ; j++)
626  {
627  dj = d*j ;
628  j2 = 2*(j-k1) ;
629  for (k = 0 ; k < nrow ; k++)
630  {
631  p = P(k) + dj ;
632  Yx [j2 + k*2*nk] = Bx [p] ; /* real */
633  Yx [j2+1 + k*2*nk] = 0 ; /* imag */
634  }
635  }
636  break ;
637 
638  case CHOLMOD_COMPLEX:
639  /* Y complex, B complex */
640  for (j = k1 ; j < k2 ; j++)
641  {
642  dj = d*j ;
643  j2 = 2*(j-k1) ;
644  for (k = 0 ; k < nrow ; k++)
645  {
646  p = P(k) + dj ;
647  Yx [j2 + k*2*nk] = Bx [2*p ] ; /* real */
648  Yx [j2+1 + k*2*nk] = Bx [2*p+1] ; /* imag */
649  }
650  }
651  break ;
652 
653  case CHOLMOD_ZOMPLEX:
654  /* Y complex, B zomplex */
655  for (j = k1 ; j < k2 ; j++)
656  {
657  dj = d*j ;
658  j2 = 2*(j-k1) ;
659  for (k = 0 ; k < nrow ; k++)
660  {
661  p = P(k) + dj ;
662  Yx [j2 + k*2*nk] = Bx [p] ; /* real */
663  Yx [j2+1 + k*2*nk] = Bz [p] ; /* imag */
664  }
665  }
666  break ;
667 
668  }
669  break ;
670 
671  case CHOLMOD_ZOMPLEX:
672 
673  switch (B->xtype)
674  {
675 
676  case CHOLMOD_REAL:
677  /* Y zomplex, B real */
678  for (j = k1 ; j < k2 ; j++)
679  {
680  dj = d*j ;
681  j2 = j-k1 ;
682  for (k = 0 ; k < nrow ; k++)
683  {
684  p = P(k) + dj ;
685  Yx [j2 + k*nk] = Bx [p] ; /* real */
686  Yz [j2 + k*nk] = 0 ; /* imag */
687  }
688  }
689  break ;
690 
691  case CHOLMOD_COMPLEX:
692  /* Y zomplex, B complex */
693  for (j = k1 ; j < k2 ; j++)
694  {
695  dj = d*j ;
696  j2 = j-k1 ;
697  for (k = 0 ; k < nrow ; k++)
698  {
699  p = P(k) + dj ;
700  Yx [j2 + k*nk] = Bx [2*p ] ; /* real */
701  Yz [j2 + k*nk] = Bx [2*p+1] ; /* imag */
702  }
703  }
704  break ;
705 
706  case CHOLMOD_ZOMPLEX:
707  /* Y zomplex, B zomplex */
708  for (j = k1 ; j < k2 ; j++)
709  {
710  dj = d*j ;
711  j2 = j-k1 ;
712  for (k = 0 ; k < nrow ; k++)
713  {
714  p = P(k) + dj ;
715  Yx [j2 + k*nk] = Bx [p] ; /* real */
716  Yz [j2 + k*nk] = Bz [p] ; /* imag */
717  }
718  }
719  break ;
720 
721  }
722  break ;
723 
724  }
725 }
726 
727 
728 /* ========================================================================== */
729 /* === iptrans ============================================================== */
730 /* ========================================================================== */
731 
732 /* X (P (1:nrow), k1 : min (k1+ncols,ncol)-1) = Y' where X is nrow-by-ncol.
733  *
734  * Copies into a permuted and transposed contiguous set of columns of X.
735  * X is already allocated on input. Y must be of sufficient size. Let nk be
736  * the number of columns accessed in X. X->xtype determines the complexity of
737  * the result.
738  *
739  * If X is real and Y is complex (or zomplex), only the real part of Y is
740  * copied into X. The imaginary part of Y is ignored.
741  *
742  * If X is complex (or zomplex) and Y is real, both the real and imaginary and
743  * parts of X are returned in Y. Y is 2*nk-by-nrow. The even
744  * rows of Y contain the real part of X and the odd rows contain the
745  * imaginary part of X. Y->nzmax must be >= 2*nrow*nk. Otherise, Y is
746  * nk-by-nrow with leading dimension nk. Y->nzmax must be >= nrow*nk.
747  *
748  * The case where Y is complex or zomplex, and X is real, is not used.
749  *
750  * The array transpose is performed, not the complex conjugate transpose.
751  */
752 
753 static void amesos_iptrans
754 (
755  /* ---- input ---- */
756  cholmod_dense *Y, /* input matrix Y */
757  Int *Perm, /* optional input permutation (can be NULL) */
758  Int k1, /* first column of X to copy into */
759  Int ncols, /* last column to copy is min(k1+ncols,X->ncol)-1 */
760  /* ---- in/out --- */
761  cholmod_dense *X /* output matrix X, already allocated */
762 )
763 {
764  double *Yx, *Yz, *Xx, *Xz ;
765  Int k2, nk, p, k, j, nrow, ncol, d, dj, j2 ;
766 
767  /* ---------------------------------------------------------------------- */
768  /* get inputs */
769  /* ---------------------------------------------------------------------- */
770 
771  ncol = X->ncol ;
772  nrow = X->nrow ;
773  k2 = MIN (k1+ncols, ncol) ;
774  nk = MAX (k2 - k1, 0) ;
775  d = X->d ;
776  Xx = X->x ;
777  Xz = X->z ;
778  Yx = Y->x ;
779  Yz = Y->z ;
780  ASSERT (((Int) Y->nzmax) >= nrow*nk*
781  ((X->xtype != CHOLMOD_REAL && Y->xtype == CHOLMOD_REAL) ? 2:1)) ;
782 
783  /* ---------------------------------------------------------------------- */
784  /* X (P (1:nrow), k1:k2-1) = Y' */
785  /* ---------------------------------------------------------------------- */
786 
787  switch (Y->xtype)
788  {
789 
790  case CHOLMOD_REAL:
791 
792  switch (X->xtype)
793  {
794 
795  case CHOLMOD_REAL:
796  /* Y real, X real */
797  for (j = k1 ; j < k2 ; j++)
798  {
799  dj = d*j ;
800  j2 = j-k1 ;
801  for (k = 0 ; k < nrow ; k++)
802  {
803  p = P(k) + dj ;
804  Xx [p] = Yx [j2 + k*nk] ; /* real */
805  }
806  }
807  break ;
808 
809  case CHOLMOD_COMPLEX:
810  /* Y real, X complex. Y is 2*nk-by-nrow */
811  for (j = k1 ; j < k2 ; j++)
812  {
813  dj = d*j ;
814  j2 = 2*(j-k1) ;
815  for (k = 0 ; k < nrow ; k++)
816  {
817  p = P(k) + dj ;
818  Xx [2*p ] = Yx [j2 + k*2*nk] ; /* real */
819  Xx [2*p+1] = Yx [j2+1 + k*2*nk] ; /* imag */
820  }
821  }
822  break ;
823 
824  case CHOLMOD_ZOMPLEX:
825  /* Y real, X zomplex. Y is 2*nk-by-nrow */
826  for (j = k1 ; j < k2 ; j++)
827  {
828  dj = d*j ;
829  j2 = 2*(j-k1) ;
830  for (k = 0 ; k < nrow ; k++)
831  {
832  p = P(k) + dj ;
833  Xx [p] = Yx [j2 + k*2*nk] ; /* real */
834  Xz [p] = Yx [j2+1 + k*2*nk] ; /* imag */
835  }
836  }
837  break ;
838 
839  }
840  break ;
841 
842  case CHOLMOD_COMPLEX:
843 
844  switch (X->xtype)
845  {
846 
847 #if 0
848  case CHOLMOD_REAL:
849  /* this case is not used */
850  break ;
851 #endif
852 
853  case CHOLMOD_COMPLEX:
854  /* Y complex, X complex */
855  for (j = k1 ; j < k2 ; j++)
856  {
857  dj = d*j ;
858  j2 = 2*(j-k1) ;
859  for (k = 0 ; k < nrow ; k++)
860  {
861  p = P(k) + dj ;
862  Xx [2*p ] = Yx [j2 + k*2*nk] ; /* real */
863  Xx [2*p+1] = Yx [j2+1 + k*2*nk] ; /* imag */
864  }
865  }
866  break ;
867 
868  case CHOLMOD_ZOMPLEX:
869  /* Y complex, X zomplex */
870  for (j = k1 ; j < k2 ; j++)
871  {
872  dj = d*j ;
873  j2 = 2*(j-k1) ;
874  for (k = 0 ; k < nrow ; k++)
875  {
876  p = P(k) + dj ;
877  Xx [p] = Yx [j2 + k*2*nk] ; /* real */
878  Xz [p] = Yx [j2+1 + k*2*nk] ; /* imag */
879  }
880  }
881  break ;
882 
883  }
884  break ;
885 
886  case CHOLMOD_ZOMPLEX:
887 
888  switch (X->xtype)
889  {
890 
891 #if 0
892  case CHOLMOD_REAL:
893  /* this case is not used */
894  break ;
895 #endif
896 
897  case CHOLMOD_COMPLEX:
898  /* Y zomplex, X complex */
899  for (j = k1 ; j < k2 ; j++)
900  {
901  dj = d*j ;
902  j2 = j-k1 ;
903  for (k = 0 ; k < nrow ; k++)
904  {
905  p = P(k) + dj ;
906  Xx [2*p ] = Yx [j2 + k*nk] ; /* real */
907  Xx [2*p+1] = Yz [j2 + k*nk] ; /* imag */
908  }
909  }
910  break ;
911 
912  case CHOLMOD_ZOMPLEX:
913  /* Y zomplex, X zomplex */
914  for (j = k1 ; j < k2 ; j++)
915  {
916  dj = d*j ;
917  j2 = j-k1 ;
918  for (k = 0 ; k < nrow ; k++)
919  {
920  p = P(k) + dj ;
921  Xx [p] = Yx [j2 + k*nk] ; /* real */
922  Xz [p] = Yz [j2 + k*nk] ; /* imag */
923  }
924  }
925  break ;
926 
927  }
928  break ;
929 
930  }
931 }
932 
933 
934 /* ========================================================================== */
935 /* === cholmod_solve ======================================================== */
936 /* ========================================================================== */
937 
938 /* Solve a linear system.
939  *
940  * The factorization can be simplicial LDL', simplicial LL', or supernodal LL'.
941  * The Dx=b solve returns silently for the LL' factorizations (it is implicitly
942  * identity).
943  */
944 
946 (
947  /* ---- input ---- */
948  int sys, /* system to solve */
949  cholmod_factor *L, /* factorization to use */
950  cholmod_dense *B, /* right-hand-side */
951  /* --------------- */
952  cholmod_common *Common
953 )
954 {
955  cholmod_dense *Y = NULL, *X = NULL ;
956  Int *Perm ;
957  Int n, nrhs, ncols, ctype, xtype, k1, nr, ytype ;
958 
959  /* ---------------------------------------------------------------------- */
960  /* check inputs */
961  /* ---------------------------------------------------------------------- */
962 
964  RETURN_IF_NULL (L, NULL) ;
965  RETURN_IF_NULL (B, NULL) ;
968  if (sys < CHOLMOD_A || sys > CHOLMOD_Pt)
969  {
970  ERROR (CHOLMOD_INVALID, "invalid system") ;
971  return (NULL) ;
972  }
973  if (B->d < L->n || B->nrow != L->n)
974  {
975  ERROR (CHOLMOD_INVALID, "dimensions of L and B do not match") ;
976  return (NULL) ;
977  }
978  DEBUG (CHOLMOD(dump_factor) (L, "L", Common)) ;
979  DEBUG (CHOLMOD(dump_dense) (B, "B", Common)) ;
980  Common->status = CHOLMOD_OK ;
981 
982  /* ---------------------------------------------------------------------- */
983  /* get inputs */
984  /* ---------------------------------------------------------------------- */
985 
986  if ((sys == CHOLMOD_P || sys == CHOLMOD_Pt || sys == CHOLMOD_A)
987  && L->ordering != CHOLMOD_NATURAL)
988  {
989  Perm = L->Perm ;
990  }
991  else
992  {
993  /* do not use L->Perm; use the identity permutation instead */
994  Perm = NULL ;
995  }
996 
997  nrhs = B->ncol ;
998  n = L->n ;
999 
1000  /* ---------------------------------------------------------------------- */
1001  /* allocate the result X */
1002  /* ---------------------------------------------------------------------- */
1003 
1004  ctype = (Common->prefer_zomplex) ? CHOLMOD_ZOMPLEX : CHOLMOD_COMPLEX ;
1005 
1006  if (sys == CHOLMOD_P || sys == CHOLMOD_Pt)
1007  {
1008  /* x=Pb and x=P'b return X real if B is real; X is the preferred
1009  * complex/zcomplex type if B is complex or zomplex */
1010  xtype = (B->xtype == CHOLMOD_REAL) ? CHOLMOD_REAL : ctype ;
1011  }
1012  else if (L->xtype == CHOLMOD_REAL && B->xtype == CHOLMOD_REAL)
1013  {
1014  /* X is real if both L and B are real */
1015  xtype = CHOLMOD_REAL ;
1016  }
1017  else
1018  {
1019  /* X is complex, use the preferred complex/zomplex type */
1020  xtype = ctype ;
1021  }
1022 
1023  X = CHOLMOD(allocate_dense) (n, nrhs, n, xtype, Common) ;
1024  if (Common->status < CHOLMOD_OK)
1025  {
1026  return (NULL) ;
1027  }
1028 
1029  /* ---------------------------------------------------------------------- */
1030  /* solve using L, D, L', P, or some combination */
1031  /* ---------------------------------------------------------------------- */
1032 
1033  if (sys == CHOLMOD_P)
1034  {
1035 
1036  /* ------------------------------------------------------------------ */
1037  /* x = P*b */
1038  /* ------------------------------------------------------------------ */
1039 
1040  amesos_perm (B, Perm, 0, nrhs, X) ;
1041 
1042  }
1043  else if (sys == CHOLMOD_Pt)
1044  {
1045 
1046  /* ------------------------------------------------------------------ */
1047  /* x = P'*b */
1048  /* ------------------------------------------------------------------ */
1049 
1050  amesos_iperm (B, Perm, 0, nrhs, X) ;
1051 
1052  }
1053  else if (L->is_super)
1054  {
1055 
1056  /* ------------------------------------------------------------------ */
1057  /* solve using a supernodal LL' factorization */
1058  /* ------------------------------------------------------------------ */
1059 
1060 #ifndef NSUPERNODAL
1061  Int blas_ok = TRUE ;
1062 
1063  /* allocate workspace */
1064  cholmod_dense *E ;
1065  Int dual ;
1066  dual = (L->xtype == CHOLMOD_REAL && B->xtype != CHOLMOD_REAL) ? 2 : 1 ;
1067  Y = CHOLMOD(allocate_dense) (n, dual*nrhs, n, L->xtype, Common) ;
1068  E = CHOLMOD(allocate_dense) (dual*nrhs, L->maxesize, dual*nrhs,
1069  L->xtype, Common) ;
1070 
1071  if (Common->status < CHOLMOD_OK)
1072  {
1073  /* out of memory */
1074  CHOLMOD(free_dense) (&X, Common) ;
1075  CHOLMOD(free_dense) (&Y, Common) ;
1076  CHOLMOD(free_dense) (&E, Common) ;
1077  return (NULL) ;
1078  }
1079 
1080  amesos_perm (B, Perm, 0, nrhs, Y) ; /* Y = P*B */
1081 
1082  if (sys == CHOLMOD_A || sys == CHOLMOD_LDLt)
1083  {
1084  blas_ok = CHOLMOD(super_lsolve) (L, Y, E, Common) ; /* Y = L\Y */
1085  blas_ok = blas_ok &&
1086  CHOLMOD(super_ltsolve) (L, Y, E, Common) ; /* Y = L'\Y*/
1087  }
1088  else if (sys == CHOLMOD_L || sys == CHOLMOD_LD)
1089  {
1090  blas_ok = CHOLMOD(super_lsolve) (L, Y, E, Common) ; /* Y = L\Y */
1091  }
1092  else if (sys == CHOLMOD_Lt || sys == CHOLMOD_DLt)
1093  {
1094  blas_ok = CHOLMOD(super_ltsolve) (L, Y, E, Common) ; /* Y = L'\Y*/
1095  }
1096  CHOLMOD(free_dense) (&E, Common) ;
1097 
1098  amesos_iperm (Y, Perm, 0, nrhs, X) ; /* X = P'*Y */
1099 
1100  if (CHECK_BLAS_INT && !blas_ok)
1101  {
1102  /* Integer overflow in the BLAS. This is probably impossible,
1103  * since the BLAS were used to create the supernodal factorization.
1104  * It might be possible for the calls to the BLAS to differ between
1105  * factorization and forward/backsolves, however. This statement
1106  * is untested; it does not appear in the compiled code if
1107  * CHECK_BLAS_INT is true (when the same integer is used in CHOLMOD
1108  * and the BLAS. */
1109  CHOLMOD(free_dense) (&X, Common) ;
1110  }
1111 
1112 #else
1113  /* CHOLMOD Supernodal module not installed */
1114  ERROR (CHOLMOD_NOT_INSTALLED,"Supernodal module not installed") ;
1115 #endif
1116 
1117  }
1118  else
1119  {
1120 
1121  /* ------------------------------------------------------------------ */
1122  /* solve using a simplicial LL' or LDL' factorization */
1123  /* ------------------------------------------------------------------ */
1124 
1125  if (L->xtype == CHOLMOD_REAL && B->xtype == CHOLMOD_REAL)
1126  {
1127  /* L, B, and Y are all real */
1128  /* solve with up to 4 columns of B at a time */
1129  ncols = 4 ;
1130  nr = MAX (4, nrhs) ;
1131  ytype = CHOLMOD_REAL ;
1132  }
1133  else if (L->xtype == CHOLMOD_REAL)
1134  {
1135  /* solve with one column of B (real/imag), at a time */
1136  ncols = 1 ;
1137  nr = 2 ;
1138  ytype = CHOLMOD_REAL ;
1139  }
1140  else
1141  {
1142  /* L is complex or zomplex, B is real/complex/zomplex, Y has the
1143  * same complexity as L. Solve with one column of B at a time. */
1144  ncols = 1 ;
1145  nr = 1 ;
1146  ytype = L->xtype ;
1147  }
1148 
1149  Y = CHOLMOD(allocate_dense) (nr, n, nr, ytype, Common) ;
1150 
1151  if (Common->status < CHOLMOD_OK)
1152  {
1153  /* out of memory */
1154  CHOLMOD(free_dense) (&X, Common) ;
1155  CHOLMOD(free_dense) (&Y, Common) ;
1156  return (NULL) ;
1157  }
1158 
1159  for (k1 = 0 ; k1 < nrhs ; k1 += ncols)
1160  {
1161  /* -------------------------------------------------------------- */
1162  /* Y = B (P, k1:k1+ncols-1)' = (P * B (:,...))' */
1163  /* -------------------------------------------------------------- */
1164 
1165  amesos_ptrans (B, Perm, k1, ncols, Y) ;
1166 
1167  /* -------------------------------------------------------------- */
1168  /* solve Y = (L' \ (L \ Y'))', or other system, with template */
1169  /* -------------------------------------------------------------- */
1170 
1171  switch (L->xtype)
1172  {
1173  case CHOLMOD_REAL:
1174  r_simplicial_solver (sys, L, Y) ;
1175  break ;
1176 
1177  case CHOLMOD_COMPLEX:
1178  c_simplicial_solver (sys, L, Y) ;
1179  break ;
1180 
1181  case CHOLMOD_ZOMPLEX:
1182  z_simplicial_solver (sys, L, Y) ;
1183  break ;
1184  }
1185 
1186  /* -------------------------------------------------------------- */
1187  /* X (P, k1:k2+ncols-1) = Y' */
1188  /* -------------------------------------------------------------- */
1189 
1190  amesos_iptrans (Y, Perm, k1, ncols, X) ;
1191  }
1192  }
1193 
1194  CHOLMOD(free_dense) (&Y, Common) ;
1195  DEBUG (CHOLMOD(dump_dense) (X, "X result", Common)) ;
1196  return (X) ;
1197 }
1198 #endif
#define CHOLMOD_A
#define CHOLMOD_NOT_INSTALLED
static void amesos_iperm(cholmod_dense *Y, Int *Perm, Int k1, Int ncols, cholmod_dense *X)
#define Int
#define CHOLMOD_COMPLEX
#define RETURN_IF_NULL_COMMON(result)
static void amesos_iptrans(cholmod_dense *Y, Int *Perm, Int k1, Int ncols, cholmod_dense *X)
#define P(k)
#define CHOLMOD(name)
#define MAX(a, b)
#define CHOLMOD_P
#define CHECK_BLAS_INT
#define CHOLMOD_REAL
#define NULL
int CHOLMOD() dump_dense(cholmod_dense *X, char *name, cholmod_common *Common)
#define ASSERT(expression)
#define CHOLMOD_L
#define CHOLMOD_LD
#define CHOLMOD_LDLt
#define CHOLMOD_DLt
#define CHOLMOD_Lt
int CHOLMOD() free_dense(cholmod_dense **XHandle, cholmod_common *Common)
static void amesos_ptrans(cholmod_dense *B, Int *Perm, Int k1, Int ncols, cholmod_dense *Y)
#define CHOLMOD_INVALID
#define CHOLMOD_OK
#define CHOLMOD_Pt
cholmod_dense *CHOLMOD() solve(int sys, cholmod_factor *L, cholmod_dense *B, cholmod_common *Common)
#define RETURN_IF_NULL(A, result)
#define DEBUG(statement)
cholmod_dense *CHOLMOD() allocate_dense(size_t nrow, size_t ncol, size_t d, int xtype, cholmod_common *Common)
#define MIN(a, b)
int CHOLMOD() dump_factor(cholmod_factor *L, char *name, cholmod_common *Common)
static void amesos_perm(cholmod_dense *B, Int *Perm, Int k1, Int ncols, cholmod_dense *Y)
int n
#define ERROR(status, msg)
#define TRUE
#define RETURN_IF_XTYPE_INVALID(A, xtype1, xtype2, result)
#define CHOLMOD_ZOMPLEX
#define CHOLMOD_NATURAL