1 /* ========================================================================== */
2 /* === UMFPACK_triplet_to_col =============================================== */
3 /* ========================================================================== */
4 
5 /* -------------------------------------------------------------------------- */
6 /* UMFPACK Copyright (c) Timothy A. Davis, CISE,                              */
7 /* Univ. of Florida.  All Rights Reserved.  See ../Doc/License for License.   */
8 /* web: http://www.cise.ufl.edu/research/sparse/umfpack                       */
9 /* -------------------------------------------------------------------------- */
10 
11 /*
12     User callable.  Converts triplet input to column-oriented form.  Duplicate
13     entries may exist (they are summed in the output).  The columns of the
14     column-oriented form are in sorted order.  The input is not modified.
15     Returns 1 if OK, 0 if an error occurred.  See umfpack_triplet_to_col.h for
16     details.
17 
18     If Map is present (a non-NULL pointer to an Int array of size nz), then on
19     output it holds the position of the triplets in the column-form matrix.
20     That is, suppose p = Map [k], and the k-th triplet is i=Ti[k], j=Tj[k], and
21     aij=Tx[k].  Then i=Ai[p], and aij will have been summed into Ax[p].  Also,
22     Ap[j] <= p < Ap[j+1].  The Map array is not computed if it is (Int *) NULL.
23 
24     Dynamic memory usage:
25 
26 	If numerical values are present, then one (two for complex version)
27 	workspace of size (nz+1)*sizeof(double) is allocated via UMF_malloc.
28 	Next, 4 calls to UMF_malloc are made to obtain workspace of size
29 	((nz+1) + (n_row+1) + n_row + MAX (n_row,n_col)) * sizeof(Int).  All of
30 	this workspace (4 to 6 objects) are free'd via UMF_free on return.
31 
32 	For the complex version, additional space is allocated.
33 
34 	An extra array of size nz*sizeof(Int) is allocated if Map is present.
35 */
36 
37 #include "umf_internal.h"
38 #include "umf_malloc.h"
39 #include "umf_free.h"
40 #include "umf_triplet.h"
41 
42 #ifndef NDEBUG
43 PRIVATE Int init_count ;
44 #endif
45 
46 /* ========================================================================== */
47 
UMFPACK_triplet_to_col(Int n_row,Int n_col,Int nz,const Int Ti[],const Int Tj[],const double Tx[],const double Tz[],Int Ap[],Int Ai[],double Ax[],double Az[],Int Map[])48 GLOBAL Int UMFPACK_triplet_to_col
49 (
50     Int n_row,
51     Int n_col,
52     Int nz,
53     const Int Ti [ ],		/* size nz */
54     const Int Tj [ ],		/* size nz */
55     const double Tx [ ],	/* size nz */
56 #ifdef COMPLEX
57     const double Tz [ ],	/* size nz */
58 #endif
59     Int Ap [ ],			/* size n_col + 1 */
60     Int Ai [ ],			/* size nz */
61     double Ax [ ]		/* size nz */
62 #ifdef COMPLEX
63     , double Az [ ]		/* size nz */
64 #endif
65     , Int Map [ ]		/* size nz */
66 )
67 {
68 
69     /* ---------------------------------------------------------------------- */
70     /* local variables */
71     /* ---------------------------------------------------------------------- */
72 
73     Int *RowCount, *Rp, *Rj, *W, nn, do_values, do_map, *Map2, status ;
74     double *Rx ;
75 #ifdef COMPLEX
76     double *Rz ;
77     Int split ;
78 #endif
79 
80 #ifndef NDEBUG
81     UMF_dump_start ( ) ;
82     init_count = UMF_malloc_count ;
83 #endif
84 
85     /* ---------------------------------------------------------------------- */
86     /* check inputs */
87     /* ---------------------------------------------------------------------- */
88 
89     if (!Ai || !Ap || !Ti || !Tj)
90     {
91 	return (UMFPACK_ERROR_argument_missing) ;
92     }
93 
94     if (n_row <= 0 || n_col <= 0)		/* must be > 0 */
95     {
96 	return (UMFPACK_ERROR_n_nonpositive) ;
97     }
98 
99     if (nz < 0)		/* nz must be >= 0 (singular matrices are OK) */
100     {
101 	return (UMFPACK_ERROR_invalid_matrix) ;
102     }
103 
104     nn = MAX (n_row, n_col) ;
105 
106     /* ---------------------------------------------------------------------- */
107     /* allocate workspace */
108     /* ---------------------------------------------------------------------- */
109 
110     Rx = (double *) NULL ;
111 
112     do_values = Ax && Tx ;
113 
114     if (do_values)
115     {
116 #ifdef COMPLEX
117 	Rx = (double *) UMF_malloc (2*nz+2, sizeof (double)) ;
118 	split = SPLIT (Tz) && SPLIT (Az) ;
119 	if (split)
120 	{
121 	    Rz = Rx + nz ;
122 	}
123 	else
124 	{
125 	    Rz = (double *) NULL ;
126 	}
127 #else
128 	Rx = (double *) UMF_malloc (nz+1, sizeof (double)) ;
129 #endif
130 	if (!Rx)
131 	{
132 	    DEBUGm4 (("out of memory: triplet work \n")) ;
133 	    ASSERT (UMF_malloc_count == init_count) ;
134 	    return (UMFPACK_ERROR_out_of_memory) ;
135 	}
136     }
137 
138     do_map = (Map != (Int *) NULL) ;
139     Map2 = (Int *) NULL ;
140     if (do_map)
141     {
142 	DEBUG0 (("Do map:\n")) ;
143 	Map2 = (Int *) UMF_malloc (nz+1, sizeof (Int)) ;
144 	if (!Map2)
145 	{
146 	    DEBUGm4 (("out of memory: triplet map\n")) ;
147 	    (void) UMF_free ((void *) Rx) ;
148 	    ASSERT (UMF_malloc_count == init_count) ;
149 	    return (UMFPACK_ERROR_out_of_memory) ;
150 	}
151     }
152 
153     Rj = (Int *) UMF_malloc (nz+1, sizeof (Int)) ;
154     Rp = (Int *) UMF_malloc (n_row+1, sizeof (Int)) ;
155     RowCount = (Int *) UMF_malloc (n_row, sizeof (Int)) ;
156     W = (Int *) UMF_malloc (nn, sizeof (Int)) ;
157     if (!Rj || !Rp || !RowCount || !W)
158     {
159 	DEBUGm4 (("out of memory: triplet work (int)\n")) ;
160 	(void) UMF_free ((void *) Rx) ;
161 	(void) UMF_free ((void *) Map2) ;
162 	(void) UMF_free ((void *) Rp) ;
163 	(void) UMF_free ((void *) Rj) ;
164 	(void) UMF_free ((void *) RowCount) ;
165 	(void) UMF_free ((void *) W) ;
166 	ASSERT (UMF_malloc_count == init_count) ;
167 	return (UMFPACK_ERROR_out_of_memory) ;
168     }
169 
170     ASSERT (UMF_malloc_count == init_count + 4 +
171 	(Rx != (double *) NULL) + do_map) ;
172 
173     /* ---------------------------------------------------------------------- */
174     /* convert from triplet to column form */
175     /* ---------------------------------------------------------------------- */
176 
177     if (do_map)
178     {
179 	if (do_values)
180 	{
181 	    status = UMF_triplet_map_x (n_row, n_col, nz, Ti, Tj, Ap, Ai, Rp,
182 		Rj, W, RowCount, Tx, Ax, Rx
183 #ifdef COMPLEX
184 		, Tz, Az, Rz
185 #endif
186 		, Map, Map2) ;
187 	}
188 	else
189 	{
190 	    status = UMF_triplet_map_nox (n_row, n_col, nz, Ti, Tj, Ap, Ai, Rp,
191 		Rj, W, RowCount, Map, Map2) ;
192 	}
193     }
194     else
195     {
196 	if (do_values)
197 	{
198 	    status = UMF_triplet_nomap_x (n_row, n_col, nz, Ti, Tj, Ap, Ai, Rp,
199 		Rj, W, RowCount , Tx, Ax, Rx
200 #ifdef COMPLEX
201 		, Tz, Az, Rz
202 #endif
203 		) ;
204 	}
205 	else
206 	{
207 	    status = UMF_triplet_nomap_nox (n_row, n_col, nz, Ti, Tj, Ap, Ai,
208 		Rp, Rj, W, RowCount) ;
209 	}
210     }
211 
212     /* ---------------------------------------------------------------------- */
213     /* free the workspace */
214     /* ---------------------------------------------------------------------- */
215 
216     (void) UMF_free ((void *) Rx) ;
217     (void) UMF_free ((void *) Map2) ;
218     (void) UMF_free ((void *) Rp) ;
219     (void) UMF_free ((void *) Rj) ;
220     (void) UMF_free ((void *) RowCount) ;
221     (void) UMF_free ((void *) W) ;
222     ASSERT (UMF_malloc_count == init_count) ;
223 
224     return (status) ;
225 }
226