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