Amesos Package Browser (Single Doxygen Collection)  Development
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
amesos_cholmod_l_transpose.c
Go to the documentation of this file.
1 /* ========================================================================== */
2 /* === Core/cholmod_transpose =============================================== */
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_sparse object to
15  * compute the transpose or permuted transpose of a matrix:
16  *
17  * Primary routines:
18  * -----------------
19  * cholmod_transpose transpose sparse matrix
20  * cholmod_ptranspose transpose and permute sparse matrix
21  * cholmod_sort sort row indices in each column of sparse matrix
22  *
23  * Secondary routines:
24  * -------------------
25  * cholmod_transpose_unsym transpose unsymmetric sparse matrix
26  * cholmod_transpose_sym transpose symmetric sparse matrix
27  *
28  * All xtypes (pattern, real, complex, and zomplex) are supported.
29  *
30  * ---------------------------------------
31  * Unsymmetric case: A->stype is zero.
32  * ---------------------------------------
33  *
34  * Computes F = A', F = A (:,f)' or F = A (p,f)', except that the indexing by
35  * f does not work the same as the MATLAB notation (see below). A->stype
36  * is zero, which denotes that both the upper and lower triangular parts of
37  * A are present (and used). A may in fact be symmetric in pattern and/or
38  * value; A->stype just denotes which part of A are stored. A may be
39  * rectangular.
40  *
41  * p is a permutation of 0:m-1, and f is a subset of 0:n-1, where A is m-by-n.
42  * There can be no duplicate entries in p or f.
43  *
44  * The set f is held in fset and fsize.
45  * fset = NULL means ":" in MATLAB. fsize is ignored.
46  * fset != NULL means f = fset [0..fsize-1].
47  * fset != NULL and fsize = 0 means f is the empty set.
48  *
49  * Columns not in the set f are considered to be zero. That is,
50  * if A is 5-by-10 then F = A (:,[3 4])' is not 2-by-5, but 10-by-5, and rows
51  * 3 and 4 of F are equal to columns 3 and 4 of A (the other rows of F are
52  * zero). More precisely, in MATLAB notation:
53  *
54  * [m n] = size (A) ;
55  * F = A ;
56  * notf = ones (1,n) ;
57  * notf (f) = 0 ;
58  * F (:, find (notf)) = 0
59  * F = F'
60  *
61  * If you want the MATLAB equivalent F=A(p,f) operation, use cholmod_submatrix
62  * instead (which does not compute the transpose).
63  *
64  * F->nzmax must be large enough to hold the matrix F. It is not modified.
65  * If F->nz is present then F->nz [j] = # of entries in column j of F.
66  *
67  * A can be sorted or unsorted, with packed or unpacked columns.
68  *
69  * If f is present and not sorted in ascending order, then F is unsorted
70  * (that is, it may contain columns whose row indices do not appear in
71  * ascending order). Otherwise, F is sorted (the row indices in each
72  * column of F appear in strictly ascending order).
73  *
74  * F is returned in packed or unpacked form, depending on F->packed on input.
75  * If F->packed is false, then F is returned in unpacked form (F->nz must be
76  * present). Each row i of F is large enough to hold all the entries in row i
77  * of A, even if f is provided. That is, F->i and
78  * F->x [F->p [i] .. F->p [i] + F->nz [i] - 1] contain all entries in A (i,f),
79  * but F->p [i+1] - F->p [i] is equal to the number of nonzeros in A (i,:),
80  * not just A (i,f).
81  *
82  * The cholmod_transpose_unsym routine is the only operation in CHOLMOD that
83  * can produce an unpacked matrix.
84  *
85  * ---------------------------------------
86  * Symmetric case: A->stype is nonzero.
87  * ---------------------------------------
88  *
89  * Computes F = A' or F = A(p,p)', the transpose or permuted transpose, where
90  * A->stype is nonzero.
91  *
92  * If A->stype > 0, then A is a symmetric matrix where just the upper part
93  * of the matrix is stored. Entries in the lower triangular part may be
94  * present, but are ignored. A must be square. If F=A', then F is returned
95  * sorted; otherwise F is unsorted for the F=A(p,p)' case.
96  *
97  * There can be no duplicate entries in p.
98  * The fset and fsize parameters are not used.
99  *
100  * Three kinds of transposes are available, depending on the "values" parameter:
101  * 0: do not transpose the numerical values; create a CHOLMOD_PATTERN matrix
102  * 1: array transpose
103  * 2: complex conjugate transpose (same as 2 if input is real or pattern)
104  *
105  * -----------------------------------------------------------------------------
106  *
107  * For cholmod_transpose_unsym and cholmod_transpose_sym, the output matrix
108  * F must already be pre-allocated by the caller, with the correct dimensions.
109  * If F is not valid or has the wrong dimensions, it is not modified.
110  * Otherwise, if F is too small, the transpose is not computed; the contents
111  * of F->p contain the column pointers of the resulting matrix, where
112  * F->p [F->ncol] > F->nzmax. In this case, the remaining contents of F are
113  * not modified. F can still be properly free'd with cholmod_free_sparse.
114  */
115 
116 /* This file should make the long int version of CHOLMOD */
117 #define DLONG 1
118 
119 #include "amesos_cholmod_internal.h"
120 #include "amesos_cholmod_core.h"
121 
122 
123 /* ========================================================================== */
124 /* === TEMPLATE ============================================================= */
125 /* ========================================================================== */
126 
127 #define PATTERN
129 #define REAL
131 #define COMPLEX
133 #define COMPLEX
134 #define NCONJUGATE
136 #define ZOMPLEX
138 #define ZOMPLEX
139 #define NCONJUGATE
141 
142 
143 /* ========================================================================== */
144 /* === cholmod_transpose_unsym ============================================== */
145 /* ========================================================================== */
146 
147 /* Compute F = A', A (:,f)', or A (p,f)', where A is unsymmetric and F is
148  * already allocated. See cholmod_transpose for a simpler routine.
149  *
150  * workspace:
151  * Iwork (MAX (nrow,ncol)) if fset is present
152  * Iwork (nrow) if fset is NULL
153  *
154  * The xtype of A and F must match, unless values is zero or F->xtype is
155  * CHOLMOD_PATTERN (in which case only the pattern of A is transpose into F).
156  */
157 
159 (
160  /* ---- input ---- */
161  cholmod_sparse *A, /* matrix to transpose */
162  int values, /* 2: complex conj. transpose, 1: array transpose,
163  0: do not transpose the numerical values */
164  Int *Perm, /* size nrow, if present (can be NULL) */
165  Int *fset, /* subset of 0:(A->ncol)-1 */
166  size_t fsize, /* size of fset */
167  /* ---- output --- */
168  cholmod_sparse *F, /* F = A', A(:,f)', or A(p,f)' */
169  /* --------------- */
170  cholmod_common *Common
171 )
172 {
173  Int *Fp, *Fnz, *Ap, *Ai, *Anz, *Wi ;
174  Int nrow, ncol, permute, use_fset, Apacked, Fpacked, p, pend,
175  i, j, k, Fsorted, nf, jj, jlast ;
176  size_t s ;
177  int ok = TRUE ;
178 
179  /* ---------------------------------------------------------------------- */
180  /* check inputs */
181  /* ---------------------------------------------------------------------- */
182 
184  RETURN_IF_NULL (A, FALSE) ;
185  RETURN_IF_NULL (F, FALSE) ;
188  if (A->nrow != F->ncol || A->ncol != F->nrow)
189  {
190  ERROR (CHOLMOD_INVALID, "F has the wrong dimensions") ;
191  return (FALSE) ;
192  }
193  Common->status = CHOLMOD_OK ;
194 
195  /* ---------------------------------------------------------------------- */
196  /* get inputs */
197  /* ---------------------------------------------------------------------- */
198 
199  nf = fsize ;
200  use_fset = (fset != NULL) ;
201  nrow = A->nrow ;
202  ncol = A->ncol ;
203 
204  Ap = A->p ; /* size A->ncol+1, column pointers of A */
205  Ai = A->i ; /* size nz = Ap [A->ncol], row indices of A */
206  Anz = A->nz ;
207  Apacked = A->packed ;
208  ASSERT (IMPLIES (!Apacked, Anz != NULL)) ;
209 
210  permute = (Perm != NULL) ;
211 
212  Fp = F->p ; /* size A->nrow+1, row pointers of F */
213  Fnz = F->nz ;
214  Fpacked = F->packed ;
215  ASSERT (IMPLIES (!Fpacked, Fnz != NULL)) ;
216 
217  nf = (use_fset) ? nf : ncol ;
218 
219  /* ---------------------------------------------------------------------- */
220  /* allocate workspace */
221  /* ---------------------------------------------------------------------- */
222 
223  /* s = nrow + ((fset != NULL) ? ncol : 0) */
224  s = CHOLMOD(add_size_t) (nrow, ((fset != NULL) ? ncol : 0), &ok) ;
225  if (!ok)
226  {
227  ERROR (CHOLMOD_TOO_LARGE, "problem too large") ;
228  return (FALSE) ;
229  }
230 
231  CHOLMOD(allocate_work) (0, s, 0, Common) ;
232  if (Common->status < CHOLMOD_OK)
233  {
234  return (FALSE) ; /* out of memory */
235  }
236 
237  Wi = Common->Iwork ; /* size nrow (i/l/l) */
238 
239  /* ---------------------------------------------------------------------- */
240  /* check Perm and fset */
241  /* ---------------------------------------------------------------------- */
242 
243  if (permute)
244  {
245  for (i = 0 ; i < nrow ; i++)
246  {
247  Wi [i] = 1 ;
248  }
249  for (k = 0 ; k < nrow ; k++)
250  {
251  i = Perm [k] ;
252  if (i < 0 || i > nrow || Wi [i] == 0)
253  {
254  ERROR (CHOLMOD_INVALID, "invalid permutation") ;
255  return (FALSE) ;
256  }
257  Wi [i] = 0 ;
258  }
259  }
260 
261  if (use_fset)
262  {
263  for (j = 0 ; j < ncol ; j++)
264  {
265  Wi [j] = 1 ;
266  }
267  for (k = 0 ; k < nf ; k++)
268  {
269  j = fset [k] ;
270  if (j < 0 || j > ncol || Wi [j] == 0)
271  {
272  ERROR (CHOLMOD_INVALID, "invalid fset") ;
273  return (FALSE) ;
274  }
275  Wi [j] = 0 ;
276  }
277  }
278 
279  /* Perm and fset are now valid */
280  ASSERT (CHOLMOD(dump_perm) (Perm, nrow, nrow, "Perm", Common)) ;
281  ASSERT (CHOLMOD(dump_perm) (fset, nf, ncol, "fset", Common)) ;
282 
283  /* ---------------------------------------------------------------------- */
284  /* count the entries in each row of A or A(:,f) */
285  /* ---------------------------------------------------------------------- */
286 
287  for (i = 0 ; i < nrow ; i++)
288  {
289  Wi [i] = 0 ;
290  }
291 
292  jlast = EMPTY ;
293  Fsorted = TRUE ;
294 
295  if (use_fset)
296  {
297  /* count entries in each row of A(:,f) */
298  for (jj = 0 ; jj < nf ; jj++)
299  {
300  j = fset [jj] ;
301  if (j <= jlast)
302  {
303  Fsorted = FALSE ;
304  }
305  p = Ap [j] ;
306  pend = (Apacked) ? (Ap [j+1]) : (p + Anz [j]) ;
307  for ( ; p < pend ; p++)
308  {
309  Wi [Ai [p]]++ ;
310  }
311  jlast = j ;
312  }
313 
314  /* save the nz counts if F is unpacked, and recount all of A */
315  if (!Fpacked)
316  {
317  if (permute)
318  {
319  for (i = 0 ; i < nrow ; i++)
320  {
321  Fnz [i] = Wi [Perm [i]] ;
322  }
323  }
324  else
325  {
326  for (i = 0 ; i < nrow ; i++)
327  {
328  Fnz [i] = Wi [i] ;
329  }
330  }
331  for (i = 0 ; i < nrow ; i++)
332  {
333  Wi [i] = 0 ;
334  }
335 
336  /* count entries in each row of A */
337  for (j = 0 ; j < ncol ; j++)
338  {
339  p = Ap [j] ;
340  pend = (Apacked) ? (Ap [j+1]) : (p + Anz [j]) ;
341  for ( ; p < pend ; p++)
342  {
343  Wi [Ai [p]]++ ;
344  }
345  }
346  }
347 
348  }
349  else
350  {
351 
352  /* count entries in each row of A */
353  for (j = 0 ; j < ncol ; j++)
354  {
355  p = Ap [j] ;
356  pend = (Apacked) ? (Ap [j+1]) : (p + Anz [j]) ;
357  for ( ; p < pend ; p++)
358  {
359  Wi [Ai [p]]++ ;
360  }
361  }
362 
363  /* save the nz counts if F is unpacked */
364  if (!Fpacked)
365  {
366  if (permute)
367  {
368  for (i = 0 ; i < nrow ; i++)
369  {
370  Fnz [i] = Wi [Perm [i]] ;
371  }
372  }
373  else
374  {
375  for (i = 0 ; i < nrow ; i++)
376  {
377  Fnz [i] = Wi [i] ;
378  }
379  }
380  }
381  }
382 
383  /* ---------------------------------------------------------------------- */
384  /* compute the row pointers */
385  /* ---------------------------------------------------------------------- */
386 
387  p = 0 ;
388  if (permute)
389  {
390  for (i = 0 ; i < nrow ; i++)
391  {
392  Fp [i] = p ;
393  p += Wi [Perm [i]] ;
394  }
395  for (i = 0 ; i < nrow ; i++)
396  {
397  Wi [Perm [i]] = Fp [i] ;
398  }
399  }
400  else
401  {
402  for (i = 0 ; i < nrow ; i++)
403  {
404  Fp [i] = p ;
405  p += Wi [i] ;
406  }
407  for (i = 0 ; i < nrow ; i++)
408  {
409  Wi [i] = Fp [i] ;
410  }
411  }
412  Fp [nrow] = p ;
413 
414  if (p > (Int) (F->nzmax))
415  {
416  ERROR (CHOLMOD_INVALID, "F is too small") ;
417  return (FALSE) ;
418  }
419 
420  /* ---------------------------------------------------------------------- */
421  /* transpose matrix, using template routine */
422  /* ---------------------------------------------------------------------- */
423 
424  ok = FALSE ;
425  if (values == 0 || F->xtype == CHOLMOD_PATTERN)
426  {
427  ok = amesos_p_cholmod_transpose_unsym (A, Perm, fset, nf, F, Common) ;
428  }
429  else if (F->xtype == CHOLMOD_REAL)
430  {
431  ok = amesos_r_cholmod_transpose_unsym (A, Perm, fset, nf, F, Common) ;
432  }
433  else if (F->xtype == CHOLMOD_COMPLEX)
434  {
435  if (values == 1)
436  {
437  /* array transpose */
438  ok = amesos_ct_cholmod_transpose_unsym (A, Perm, fset, nf, F, Common) ;
439  }
440  else
441  {
442  /* complex conjugate transpose */
443  ok = amesos_c_cholmod_transpose_unsym (A, Perm, fset, nf, F, Common) ;
444  }
445  }
446  else if (F->xtype == CHOLMOD_ZOMPLEX)
447  {
448  if (values == 1)
449  {
450  /* array transpose */
451  ok = amesos_zt_cholmod_transpose_unsym (A, Perm, fset, nf, F, Common) ;
452  }
453  else
454  {
455  /* complex conjugate transpose */
456  ok = amesos_z_cholmod_transpose_unsym (A, Perm, fset, nf, F, Common) ;
457  }
458  }
459 
460  /* ---------------------------------------------------------------------- */
461  /* finalize result F */
462  /* ---------------------------------------------------------------------- */
463 
464  if (ok)
465  {
466  F->sorted = Fsorted ;
467  }
468  ASSERT (CHOLMOD(dump_sparse) (F, "output F unsym", Common) >= 0) ;
469  return (ok) ;
470 }
471 
472 
473 /* ========================================================================== */
474 /* === cholmod_transpose_sym ================================================ */
475 /* ========================================================================== */
476 
477 /* Compute F = A' or A (p,p)', where A is symmetric and F is already allocated.
478  * See cholmod_transpose for a simpler routine.
479  *
480  * workspace: Iwork (nrow) if Perm NULL, Iwork (2*nrow) if Perm non-NULL.
481  */
482 
484 (
485  /* ---- input ---- */
486  cholmod_sparse *A, /* matrix to transpose */
487  int values, /* 2: complex conj. transpose, 1: array transpose,
488  0: do not transpose the numerical values */
489  Int *Perm, /* size nrow, if present (can be NULL) */
490  /* ---- output --- */
491  cholmod_sparse *F, /* F = A' or A(p,p)' */
492  /* --------------- */
493  cholmod_common *Common
494 )
495 {
496  Int *Ap, *Anz, *Ai, *Fp, *Wi, *Pinv, *Iwork ;
497  Int p, pend, packed, upper, permute, jold, n, i, j, k, iold ;
498  size_t s ;
499  int ok = TRUE ;
500 
501  /* ---------------------------------------------------------------------- */
502  /* check inputs */
503  /* ---------------------------------------------------------------------- */
504 
506  RETURN_IF_NULL (A, FALSE) ;
507  RETURN_IF_NULL (F, FALSE) ;
510  if (A->nrow != A->ncol || A->stype == 0)
511  {
512  /* this routine handles square symmetric matrices only */
513  ERROR (CHOLMOD_INVALID, "matrix must be symmetric") ;
514  return (FALSE) ;
515  }
516  if (A->nrow != F->ncol || A->ncol != F->nrow)
517  {
518  ERROR (CHOLMOD_INVALID, "F has the wrong dimensions") ;
519  return (FALSE) ;
520  }
521  Common->status = CHOLMOD_OK ;
522 
523  /* ---------------------------------------------------------------------- */
524  /* get inputs */
525  /* ---------------------------------------------------------------------- */
526 
527  permute = (Perm != NULL) ;
528  n = A->nrow ;
529  Ap = A->p ; /* size A->ncol+1, column pointers of A */
530  Ai = A->i ; /* size nz = Ap [A->ncol], row indices of A */
531  Anz = A->nz ;
532  packed = A->packed ;
533  ASSERT (IMPLIES (!packed, Anz != NULL)) ;
534  upper = (A->stype > 0) ;
535 
536  Fp = F->p ; /* size A->nrow+1, row pointers of F */
537 
538  /* ---------------------------------------------------------------------- */
539  /* allocate workspace */
540  /* ---------------------------------------------------------------------- */
541 
542  /* s = (Perm != NULL) ? 2*n : n */
543  s = CHOLMOD(add_size_t) (n, ((Perm != NULL) ? n : 0), &ok) ;
544  if (!ok)
545  {
546  ERROR (CHOLMOD_TOO_LARGE, "problem too large") ;
547  return (FALSE) ;
548  }
549 
550  CHOLMOD(allocate_work) (0, s, 0, Common) ;
551  if (Common->status < CHOLMOD_OK)
552  {
553  return (FALSE) ; /* out of memory */
554  }
555 
556  /* ---------------------------------------------------------------------- */
557  /* get workspace */
558  /* ---------------------------------------------------------------------- */
559 
560  Iwork = Common->Iwork ;
561  Wi = Iwork ; /* size n (i/l/l) */
562  Pinv = Iwork + n ; /* size n (i/i/l) , unused if Perm NULL */
563 
564  /* ---------------------------------------------------------------------- */
565  /* check Perm and construct inverse permutation */
566  /* ---------------------------------------------------------------------- */
567 
568  if (permute)
569  {
570  for (i = 0 ; i < n ; i++)
571  {
572  Pinv [i] = EMPTY ;
573  }
574  for (k = 0 ; k < n ; k++)
575  {
576  i = Perm [k] ;
577  if (i < 0 || i > n || Pinv [i] != EMPTY)
578  {
579  ERROR (CHOLMOD_INVALID, "invalid permutation") ;
580  return (FALSE) ;
581  }
582  Pinv [i] = k ;
583  }
584  }
585 
586  /* Perm is now valid */
587  ASSERT (CHOLMOD(dump_perm) (Perm, n, n, "Perm", Common)) ;
588 
589  /* ---------------------------------------------------------------------- */
590  /* count the entries in each row of F */
591  /* ---------------------------------------------------------------------- */
592 
593  for (i = 0 ; i < n ; i++)
594  {
595  Wi [i] = 0 ;
596  }
597 
598  if (packed)
599  {
600  if (permute)
601  {
602  if (upper)
603  {
604  /* packed, permuted, upper */
605  for (j = 0 ; j < n ; j++)
606  {
607  jold = Perm [j] ;
608  pend = Ap [jold+1] ;
609  for (p = Ap [jold] ; p < pend ; p++)
610  {
611  iold = Ai [p] ;
612  if (iold <= jold)
613  {
614  i = Pinv [iold] ;
615  Wi [MIN (i, j)]++ ;
616  }
617  }
618  }
619  }
620  else
621  {
622  /* packed, permuted, lower */
623  for (j = 0 ; j < n ; j++)
624  {
625  jold = Perm [j] ;
626  pend = Ap [jold+1] ;
627  for (p = Ap [jold] ; p < pend ; p++)
628  {
629  iold = Ai [p] ;
630  if (iold >= jold)
631  {
632  i = Pinv [iold] ;
633  Wi [MAX (i, j)]++ ;
634  }
635  }
636  }
637  }
638  }
639  else
640  {
641  if (upper)
642  {
643  /* packed, unpermuted, upper */
644  for (j = 0 ; j < n ; j++)
645  {
646  pend = Ap [j+1] ;
647  for (p = Ap [j] ; p < pend ; p++)
648  {
649  i = Ai [p] ;
650  if (i <= j)
651  {
652  Wi [i]++ ;
653  }
654  }
655  }
656  }
657  else
658  {
659  /* packed, unpermuted, lower */
660  for (j = 0 ; j < n ; j++)
661  {
662  pend = Ap [j+1] ;
663  for (p = Ap [j] ; p < pend ; p++)
664  {
665  i = Ai [p] ;
666  if (i >= j)
667  {
668  Wi [i]++ ;
669  }
670  }
671  }
672  }
673  }
674  }
675  else
676  {
677  if (permute)
678  {
679  if (upper)
680  {
681  /* unpacked, permuted, upper */
682  for (j = 0 ; j < n ; j++)
683  {
684  jold = Perm [j] ;
685  p = Ap [jold] ;
686  pend = p + Anz [jold] ;
687  for ( ; p < pend ; p++)
688  {
689  iold = Ai [p] ;
690  if (iold <= jold)
691  {
692  i = Pinv [iold] ;
693  Wi [MIN (i, j)]++ ;
694  }
695  }
696  }
697  }
698  else
699  {
700  /* unpacked, permuted, lower */
701  for (j = 0 ; j < n ; j++)
702  {
703  jold = Perm [j] ;
704  p = Ap [jold] ;
705  pend = p + Anz [jold] ;
706  for ( ; p < pend ; p++)
707  {
708  iold = Ai [p] ;
709  if (iold >= jold)
710  {
711  i = Pinv [iold] ;
712  Wi [MAX (i, j)]++ ;
713  }
714  }
715  }
716  }
717  }
718  else
719  {
720  if (upper)
721  {
722  /* unpacked, unpermuted, upper */
723  for (j = 0 ; j < n ; j++)
724  {
725  p = Ap [j] ;
726  pend = p + Anz [j] ;
727  for ( ; p < pend ; p++)
728  {
729  i = Ai [p] ;
730  if (i <= j)
731  {
732  Wi [i]++ ;
733  }
734  }
735  }
736  }
737  else
738  {
739  /* unpacked, unpermuted, lower */
740  for (j = 0 ; j < n ; j++)
741  {
742  p = Ap [j] ;
743  pend = p + Anz [j] ;
744  for ( ; p < pend ; p++)
745  {
746  i = Ai [p] ;
747  if (i >= j)
748  {
749  Wi [i]++ ;
750  }
751  }
752  }
753  }
754  }
755  }
756 
757  /* ---------------------------------------------------------------------- */
758  /* compute the row pointers */
759  /* ---------------------------------------------------------------------- */
760 
761  p = 0 ;
762  for (i = 0 ; i < n ; i++)
763  {
764  Fp [i] = p ;
765  p += Wi [i] ;
766  }
767  Fp [n] = p ;
768  for (i = 0 ; i < n ; i++)
769  {
770  Wi [i] = Fp [i] ;
771  }
772 
773  if (p > (Int) (F->nzmax))
774  {
775  ERROR (CHOLMOD_INVALID, "F is too small") ;
776  return (FALSE) ;
777  }
778 
779  /* ---------------------------------------------------------------------- */
780  /* transpose matrix, using template routine */
781  /* ---------------------------------------------------------------------- */
782 
783  ok = FALSE ;
784  if (values == 0 || F->xtype == CHOLMOD_PATTERN)
785  {
786  PRINT2 (("\n:::: p_transpose_sym Perm %p\n", Perm)) ;
787  ok = amesos_p_cholmod_transpose_sym (A, Perm, F, Common) ;
788  }
789  else if (F->xtype == CHOLMOD_REAL)
790  {
791  PRINT2 (("\n:::: r_transpose_sym Perm %p\n", Perm)) ;
792  ok = amesos_r_cholmod_transpose_sym (A, Perm, F, Common) ;
793  }
794  else if (F->xtype == CHOLMOD_COMPLEX)
795  {
796  if (values == 1)
797  {
798  /* array transpose */
799  PRINT2 (("\n:::: ct_transpose_sym Perm %p\n", Perm)) ;
800  ok = amesos_ct_cholmod_transpose_sym (A, Perm, F, Common) ;
801  }
802  else
803  {
804  /* complex conjugate transpose */
805  PRINT2 (("\n:::: c_transpose_sym Perm %p\n", Perm)) ;
806  ok = amesos_c_cholmod_transpose_sym (A, Perm, F, Common) ;
807  }
808  }
809  else if (F->xtype == CHOLMOD_ZOMPLEX)
810  {
811  if (values == 1)
812  {
813  /* array transpose */
814  PRINT2 (("\n:::: zt_transpose_sym Perm %p\n", Perm)) ;
815  ok = amesos_zt_cholmod_transpose_sym (A, Perm, F, Common) ;
816  }
817  else
818  {
819  /* complex conjugate transpose */
820  PRINT2 (("\n:::: z_transpose_sym Perm %p\n", Perm)) ;
821  ok = amesos_z_cholmod_transpose_sym (A, Perm, F, Common) ;
822  }
823  }
824 
825  /* ---------------------------------------------------------------------- */
826  /* finalize result F */
827  /* ---------------------------------------------------------------------- */
828 
829  /* F is sorted if there is no permutation vector */
830  if (ok)
831  {
832  F->sorted = !permute ;
833  F->packed = TRUE ;
834  F->stype = - SIGN (A->stype) ; /* flip the stype */
835  ASSERT (CHOLMOD(dump_sparse) (F, "output F sym", Common) >= 0) ;
836  }
837  return (ok) ;
838 }
839 
840 
841 /* ========================================================================== */
842 /* === cholmod_transpose ==================================================== */
843 /* ========================================================================== */
844 
845 /* Returns A'. See also cholmod_ptranspose below. */
846 
848 (
849  /* ---- input ---- */
850  cholmod_sparse *A, /* matrix to transpose */
851  int values, /* 2: complex conj. transpose, 1: array transpose,
852  0: do not transpose the numerical values
853  (returns its result as CHOLMOD_PATTERN) */
854  /* --------------- */
855  cholmod_common *Common
856 )
857 {
858  return (CHOLMOD(ptranspose) (A, values, NULL, NULL, 0, Common)) ;
859 }
860 
861 
862 /* ========================================================================== */
863 /* === cholmod_ptranspose =================================================== */
864 /* ========================================================================== */
865 
866 /* Return A' or A(p,p)' if A is symmetric. Return A', A(:,f)', or A(p,f)' if
867  * A is unsymmetric.
868  *
869  * workspace:
870  * Iwork (MAX (nrow,ncol)) if unsymmetric and fset is non-NULL
871  * Iwork (nrow) if unsymmetric and fset is NULL
872  * Iwork (2*nrow) if symmetric and Perm is non-NULL.
873  * Iwork (nrow) if symmetric and Perm is NULL.
874  *
875  * A simple worst-case upper bound on the workspace is nrow+ncol.
876  */
877 
879 (
880  /* ---- input ---- */
881  cholmod_sparse *A, /* matrix to transpose */
882  int values, /* 2: complex conj. transpose, 1: array transpose,
883  0: do not transpose the numerical values */
884  Int *Perm, /* if non-NULL, F = A(p,f) or A(p,p) */
885  Int *fset, /* subset of 0:(A->ncol)-1 */
886  size_t fsize, /* size of fset */
887  /* --------------- */
888  cholmod_common *Common
889 )
890 {
891  Int *Ap, *Anz ;
892  cholmod_sparse *F ;
893  Int nrow, ncol, use_fset, j, jj, fnz, packed, stype, nf, xtype ;
894  size_t ineed ;
895  int ok = TRUE ;
896 
897  nf = fsize ;
898 
899  /* ---------------------------------------------------------------------- */
900  /* check inputs */
901  /* ---------------------------------------------------------------------- */
902 
904  RETURN_IF_NULL (A, FALSE) ;
906  stype = A->stype ;
907  Common->status = CHOLMOD_OK ;
908 
909  /* ---------------------------------------------------------------------- */
910  /* allocate workspace */
911  /* ---------------------------------------------------------------------- */
912 
913  nrow = A->nrow ;
914  ncol = A->ncol ;
915 
916  if (stype != 0)
917  {
918  use_fset = FALSE ;
919  if (Perm != NULL)
920  {
921  ineed = CHOLMOD(mult_size_t) (A->nrow, 2, &ok) ;
922  }
923  else
924  {
925  ineed = A->nrow ;
926  }
927  }
928  else
929  {
930  use_fset = (fset != NULL) ;
931  if (use_fset)
932  {
933  ineed = MAX (A->nrow, A->ncol) ;
934  }
935  else
936  {
937  ineed = A->nrow ;
938  }
939  }
940 
941  if (!ok)
942  {
943  ERROR (CHOLMOD_TOO_LARGE, "problem too large") ;
944  return (NULL) ;
945  }
946 
947  CHOLMOD(allocate_work) (0, ineed, 0, Common) ;
948  if (Common->status < CHOLMOD_OK)
949  {
950  return (NULL) ; /* out of memory */
951  }
952 
953  /* ---------------------------------------------------------------------- */
954  /* get inputs */
955  /* ---------------------------------------------------------------------- */
956 
957  Ap = A->p ;
958  Anz = A->nz ;
959  packed = A->packed ;
960  ASSERT (IMPLIES (!packed, Anz != NULL)) ;
961  xtype = values ? A->xtype : CHOLMOD_PATTERN ;
962 
963  /* ---------------------------------------------------------------------- */
964  /* allocate F */
965  /* ---------------------------------------------------------------------- */
966 
967  /* determine # of nonzeros in F */
968  if (stype != 0)
969  {
970  /* F=A' or F=A(p,p)', fset is ignored */
971  fnz = CHOLMOD(nnz) (A, Common) ;
972  }
973  else
974  {
975  nf = (use_fset) ? nf : ncol ;
976  if (use_fset)
977  {
978  fnz = 0 ;
979  /* F=A(:,f)' or F=A(p,f)' */
980  for (jj = 0 ; jj < nf ; jj++)
981  {
982  /* The fset is not yet checked; it will be thoroughly checked
983  * in cholmod_transpose_unsym. For now, just make sure we don't
984  * access Ap and Anz out of bounds. */
985  j = fset [jj] ;
986  if (j >= 0 && j < ncol)
987  {
988  fnz += packed ? (Ap [j+1] - Ap [j]) : MAX (0, Anz [j]) ;
989  }
990  }
991  }
992  else
993  {
994  /* F=A' or F=A(p,:)' */
995  fnz = CHOLMOD(nnz) (A, Common) ;
996  }
997  }
998 
999  /* F is ncol-by-nrow, fnz nonzeros, sorted unless f is present and unsorted,
1000  * packed, of opposite stype as A, and with/without numerical values */
1001  F = CHOLMOD(allocate_sparse) (ncol, nrow, fnz, TRUE, TRUE, -SIGN(stype),
1002  xtype, Common) ;
1003  if (Common->status < CHOLMOD_OK)
1004  {
1005  return (NULL) ; /* out of memory */
1006  }
1007 
1008  /* ---------------------------------------------------------------------- */
1009  /* transpose and optionally permute the matrix A */
1010  /* ---------------------------------------------------------------------- */
1011 
1012  if (stype != 0)
1013  {
1014  /* F = A (p,p)', using upper or lower triangular part of A only */
1015  ok = CHOLMOD(transpose_sym) (A, values, Perm, F, Common) ;
1016  }
1017  else
1018  {
1019  /* F = A (p,f)' */
1020  ok = CHOLMOD(transpose_unsym) (A, values, Perm, fset, nf, F, Common) ;
1021  }
1022 
1023  /* ---------------------------------------------------------------------- */
1024  /* return the matrix F, or NULL if an error occured */
1025  /* ---------------------------------------------------------------------- */
1026 
1027  if (!ok)
1028  {
1029  CHOLMOD(free_sparse) (&F, Common) ;
1030  }
1031  return (F) ;
1032 }
1033 
1034 
1035 /* ========================================================================== */
1036 /* === cholmod_sort ========================================================= */
1037 /* ========================================================================== */
1038 
1039 /* Sort the columns of A, in place. Returns A in packed form, even if it
1040  * starts as unpacked. Removes entries in the ignored part of a symmetric
1041  * matrix.
1042  *
1043  * workspace: Iwork (max (nrow,ncol)). Allocates additional workspace for a
1044  * temporary copy of A'.
1045  */
1046 
1047 int CHOLMOD(sort)
1049  /* ---- in/out --- */
1050  cholmod_sparse *A, /* matrix to sort */
1051  /* --------------- */
1052  cholmod_common *Common
1053 )
1054 {
1055  Int *Ap ;
1056  cholmod_sparse *F ;
1057  Int anz, ncol, nrow, stype ;
1058 
1059  /* ---------------------------------------------------------------------- */
1060  /* check inputs */
1061  /* ---------------------------------------------------------------------- */
1062 
1064  RETURN_IF_NULL (A, FALSE) ;
1066  Common->status = CHOLMOD_OK ;
1067  nrow = A->nrow ;
1068  if (nrow <= 1)
1069  {
1070  /* a 1-by-n sparse matrix must be sorted */
1071  A->sorted = TRUE ;
1072  return (TRUE) ;
1073  }
1074 
1075  /* ---------------------------------------------------------------------- */
1076  /* allocate workspace */
1077  /* ---------------------------------------------------------------------- */
1078 
1079  ncol = A->ncol ;
1080  CHOLMOD(allocate_work) (0, MAX (nrow, ncol), 0, Common) ;
1081  if (Common->status < CHOLMOD_OK)
1082  {
1083  return (FALSE) ; /* out of memory */
1084  }
1085 
1086  /* ---------------------------------------------------------------------- */
1087  /* get inputs */
1088  /* ---------------------------------------------------------------------- */
1089 
1090  anz = CHOLMOD(nnz) (A, Common) ;
1091  stype = A->stype ;
1092 
1093  /* ---------------------------------------------------------------------- */
1094  /* sort the columns of the matrix */
1095  /* ---------------------------------------------------------------------- */
1096 
1097  /* allocate workspace for transpose: ncol-by-nrow, same # of nonzeros as A,
1098  * sorted, packed, same stype as A, and of the same numeric type as A. */
1099  F = CHOLMOD(allocate_sparse) (ncol, nrow, anz, TRUE, TRUE, stype,
1100  A->xtype, Common) ;
1101  if (Common->status < CHOLMOD_OK)
1102  {
1103  return (FALSE) ; /* out of memory */
1104  }
1105 
1106  if (stype != 0)
1107  {
1108  /* F = A', upper or lower triangular part only */
1109  CHOLMOD(transpose_sym) (A, 1, NULL, F, Common) ;
1110  A->packed = TRUE ;
1111  /* A = F' */
1112  CHOLMOD(transpose_sym) (F, 1, NULL, A, Common) ;
1113  }
1114  else
1115  {
1116  /* F = A' */
1117  CHOLMOD(transpose_unsym) (A, 1, NULL, NULL, 0, F, Common) ;
1118  A->packed = TRUE ;
1119  /* A = F' */
1120  CHOLMOD(transpose_unsym) (F, 1, NULL, NULL, 0, A, Common) ;
1121  }
1122 
1123  ASSERT (A->sorted && A->packed) ;
1124  ASSERT (CHOLMOD(dump_sparse) (A, "Asorted", Common) >= 0) ;
1125 
1126  /* ---------------------------------------------------------------------- */
1127  /* reduce A in size, if needed. This must succeed. */
1128  /* ---------------------------------------------------------------------- */
1129 
1130  Ap = A->p ;
1131  anz = Ap [ncol] ;
1132  ASSERT ((size_t) anz <= A->nzmax) ;
1133  CHOLMOD(reallocate_sparse) (anz, A, Common) ;
1134  ASSERT (Common->status >= CHOLMOD_OK) ;
1135 
1136  /* ---------------------------------------------------------------------- */
1137  /* free workspace */
1138  /* ---------------------------------------------------------------------- */
1139 
1140  CHOLMOD(free_sparse) (&F, Common) ;
1141  return (TRUE) ;
1142 }
#define CHOLMOD_TOO_LARGE
#define EMPTY
UF_long CHOLMOD() nnz(cholmod_sparse *A, cholmod_common *Common)
int CHOLMOD() transpose_sym(cholmod_sparse *A, int values, Int *Perm, cholmod_sparse *F, cholmod_common *Common)
int CHOLMOD() transpose_unsym(cholmod_sparse *A, int values, Int *Perm, Int *fset, size_t fsize, cholmod_sparse *F, cholmod_common *Common)
#define Int
size_t CHOLMOD() add_size_t(size_t a, size_t b, int *ok)
#define CHOLMOD_COMPLEX
#define FALSE
cholmod_sparse *CHOLMOD() transpose(cholmod_sparse *A, int values, cholmod_common *Common)
int CHOLMOD() reallocate_sparse(size_t nznew, cholmod_sparse *A, cholmod_common *Common)
#define RETURN_IF_NULL_COMMON(result)
size_t CHOLMOD() mult_size_t(size_t a, size_t k, int *ok)
#define SIGN(x)
#define CHOLMOD_PATTERN
#define CHOLMOD(name)
#define MAX(a, b)
cholmod_sparse *CHOLMOD() ptranspose(cholmod_sparse *A, int values, Int *Perm, Int *fset, size_t fsize, cholmod_common *Common)
int CHOLMOD() sort(cholmod_sparse *A, cholmod_common *Common)
int CHOLMOD() free_sparse(cholmod_sparse **AHandle, cholmod_common *Common)
#define CHOLMOD_REAL
#define NULL
#define ASSERT(expression)
#define PRINT2(params)
int CHOLMOD() dump_perm(Int *Perm, size_t len, size_t n, char *name, cholmod_common *Common)
#define CHOLMOD_INVALID
#define CHOLMOD_OK
cholmod_sparse *CHOLMOD() allocate_sparse(size_t nrow, size_t ncol, size_t nzmax, int sorted, int packed, int stype, int xtype, cholmod_common *Common)
int CHOLMOD() allocate_work(size_t nrow, size_t iworksize, size_t xworksize, cholmod_common *Common)
#define RETURN_IF_NULL(A, result)
#define MIN(a, b)
#define IMPLIES(p, q)
int n
#define ERROR(status, msg)
#define TRUE
#define RETURN_IF_XTYPE_INVALID(A, xtype1, xtype2, result)
#define CHOLMOD_ZOMPLEX