1 /* ========================================================================== */
2 /* === MatrixOps/cholmod_horzcat ============================================ */
3 /* ========================================================================== */
4
5 /* -----------------------------------------------------------------------------
6 * CHOLMOD/MatrixOps Module. Copyright (C) 2005-2006, Timothy A. Davis
7 * http://www.suitesparse.com
8 * -------------------------------------------------------------------------- */
9
10 /* Horizontal concatenation, C = [A , B] in MATLAB notation.
11 *
12 * A and B can be up/lo/unsym; C is unsymmetric and packed.
13 * A and B must have the same number of rows.
14 * C is sorted if both A and B are sorted.
15 *
16 * workspace: Iwork (max (A->nrow, A->ncol, B->nrow, B->ncol)).
17 * allocates temporary copies of A and B if they are symmetric.
18 *
19 * A and B must have the same numeric xtype, unless values is FALSE.
20 * A and B cannot be complex or zomplex, unless values is FALSE.
21 */
22
23 #ifndef NGPL
24 #ifndef NMATRIXOPS
25
26 #include "cholmod_internal.h"
27 #include "cholmod_matrixops.h"
28
29
30 /* ========================================================================== */
31 /* === cholmod_horzcat ====================================================== */
32 /* ========================================================================== */
33
CHOLMOD(horzcat)34 cholmod_sparse *CHOLMOD(horzcat)
35 (
36 /* ---- input ---- */
37 cholmod_sparse *A, /* left matrix to concatenate */
38 cholmod_sparse *B, /* right matrix to concatenate */
39 int values, /* if TRUE compute the numerical values of C */
40 /* --------------- */
41 cholmod_common *Common
42 )
43 {
44 double *Ax, *Bx, *Cx ;
45 Int *Ap, *Ai, *Anz, *Bp, *Bi, *Bnz, *Cp, *Ci ;
46 cholmod_sparse *C, *A2, *B2 ;
47 Int apacked, bpacked, ancol, bncol, ncol, nrow, anz, bnz, nz, j, p, pend,
48 pdest ;
49
50 /* ---------------------------------------------------------------------- */
51 /* check inputs */
52 /* ---------------------------------------------------------------------- */
53
54 RETURN_IF_NULL_COMMON (NULL) ;
55 RETURN_IF_NULL (A, NULL) ;
56 RETURN_IF_NULL (B, NULL) ;
57 values = values &&
58 (A->xtype != CHOLMOD_PATTERN) && (B->xtype != CHOLMOD_PATTERN) ;
59 RETURN_IF_XTYPE_INVALID (A, CHOLMOD_PATTERN,
60 values ? CHOLMOD_REAL : CHOLMOD_ZOMPLEX, NULL) ;
61 RETURN_IF_XTYPE_INVALID (B, CHOLMOD_PATTERN,
62 values ? CHOLMOD_REAL : CHOLMOD_ZOMPLEX, NULL) ;
63 if (A->nrow != B->nrow)
64 {
65 /* A and B must have the same number of rows */
66 ERROR (CHOLMOD_INVALID, "A and B must have same # rows") ;
67 return (NULL) ;
68 }
69 /* A and B must have the same numerical type if values is TRUE (both must
70 * be CHOLMOD_REAL, this is implicitly checked above) */
71
72 Common->status = CHOLMOD_OK ;
73
74 /* ---------------------------------------------------------------------- */
75 /* allocate workspace */
76 /* ---------------------------------------------------------------------- */
77
78 ancol = A->ncol ;
79 bncol = B->ncol ;
80 nrow = A->nrow ;
81 CHOLMOD(allocate_work) (0, MAX3 (nrow, ancol, bncol), 0, Common) ;
82 if (Common->status < CHOLMOD_OK)
83 {
84 /* out of memory */
85 return (NULL) ;
86 }
87
88 /* ---------------------------------------------------------------------- */
89 /* get inputs */
90 /* ---------------------------------------------------------------------- */
91
92 /* convert A to unsymmetric, if necessary */
93 A2 = NULL ;
94 if (A->stype != 0)
95 {
96 /* workspace: Iwork (max (A->nrow,A->ncol)) */
97 A2 = CHOLMOD(copy) (A, 0, values, Common) ;
98 if (Common->status < CHOLMOD_OK)
99 {
100 /* out of memory */
101 return (NULL) ;
102 }
103 A = A2 ;
104 }
105
106 /* convert B to unsymmetric, if necessary */
107 B2 = NULL ;
108 if (B->stype != 0)
109 {
110 /* workspace: Iwork (max (B->nrow,B->ncol)) */
111 B2 = CHOLMOD(copy) (B, 0, values, Common) ;
112 if (Common->status < CHOLMOD_OK)
113 {
114 /* out of memory */
115 CHOLMOD(free_sparse) (&A2, Common) ;
116 return (NULL) ;
117 }
118 B = B2 ;
119 }
120
121 Ap = A->p ;
122 Anz = A->nz ;
123 Ai = A->i ;
124 Ax = A->x ;
125 apacked = A->packed ;
126
127 Bp = B->p ;
128 Bnz = B->nz ;
129 Bi = B->i ;
130 Bx = B->x ;
131 bpacked = B->packed ;
132
133 /* ---------------------------------------------------------------------- */
134 /* allocate C */
135 /* ---------------------------------------------------------------------- */
136
137 anz = CHOLMOD(nnz) (A, Common) ;
138 bnz = CHOLMOD(nnz) (B, Common) ;
139 ncol = ancol + bncol ;
140 nz = anz + bnz ;
141
142 C = CHOLMOD(allocate_sparse) (nrow, ncol, nz, A->sorted && B->sorted, TRUE,
143 0, values ? A->xtype : CHOLMOD_PATTERN, Common) ;
144 if (Common->status < CHOLMOD_OK)
145 {
146 /* out of memory */
147 CHOLMOD(free_sparse) (&A2, Common) ;
148 CHOLMOD(free_sparse) (&B2, Common) ;
149 return (NULL) ;
150 }
151 Cp = C->p ;
152 Ci = C->i ;
153 Cx = C->x ;
154
155 /* ---------------------------------------------------------------------- */
156 /* C = [A , B] */
157 /* ---------------------------------------------------------------------- */
158
159 pdest = 0 ;
160
161 /* copy A as the first A->ncol columns of C */
162 for (j = 0 ; j < ancol ; j++)
163 {
164 /* A(:,j) is the jth column of C */
165 p = Ap [j] ;
166 pend = (apacked) ? (Ap [j+1]) : (p + Anz [j]) ;
167 Cp [j] = pdest ;
168 for ( ; p < pend ; p++)
169 {
170 Ci [pdest] = Ai [p] ;
171 if (values) Cx [pdest] = Ax [p] ;
172 pdest++ ;
173 }
174 }
175
176 /* copy B as the next B->ncol columns of C */
177 for (j = 0 ; j < bncol ; j++)
178 {
179 /* B(:,j) is the (ancol+j)th column of C */
180 p = Bp [j] ;
181 pend = (bpacked) ? (Bp [j+1]) : (p + Bnz [j]) ;
182 Cp [ancol + j] = pdest ;
183 for ( ; p < pend ; p++)
184 {
185 Ci [pdest] = Bi [p] ;
186 if (values) Cx [pdest] = Bx [p] ;
187 pdest++ ;
188 }
189 }
190 Cp [ncol] = pdest ;
191 ASSERT (pdest == anz + bnz) ;
192
193 /* ---------------------------------------------------------------------- */
194 /* free the unsymmetric copies of A and B, and return C */
195 /* ---------------------------------------------------------------------- */
196
197 CHOLMOD(free_sparse) (&A2, Common) ;
198 CHOLMOD(free_sparse) (&B2, Common) ;
199 return (C) ;
200 }
201 #endif
202 #endif
203