1 /* ========================================================================== */
2 /* === CHOLMOD/MATLAB/analyze mexFunction =================================== */
3 /* ========================================================================== */
4 
5 /* -----------------------------------------------------------------------------
6  * CHOLMOD/MATLAB Module.  Copyright (C) 2005-2006, Timothy A. Davis
7  * http://www.suitesparse.com
8  * MATLAB(tm) is a Trademark of The MathWorks, Inc.
9  * -------------------------------------------------------------------------- */
10 
11 /* Order a matrix and then analyze it, using CHOLMOD's best-effort ordering.
12  * Returns the count of the number of nonzeros in each column of L for the
13  * permuted matrix A.
14  *
15  * Usage:
16  *
17  *	[p count] = analyze (A)		orders A, using just tril(A)
18  *	[p count] = analyze (A,'sym')	orders A, using just tril(A)
19  *	[p count] = analyze (A,'row')	orders A*A'
20  *	[p count] = analyze (A,'col')	orders A'*A
21  *
22  * with an optional 3rd parameter:
23  *
24  *	[p count] = analyze (A,'sym',k)	orders A, using just tril(A)
25  *	[p count] = analyze (A,'row',k)	orders A*A'
26  *	[p count] = analyze (A,'col',k)	orders A'*A
27  *
28  *	k=0 is the default.  k != 0 selects the ordering strategy.
29  *
30  * See analyze.m for more details.
31  */
32 
33 #include "cholmod_matlab.h"
34 
mexFunction(int nargout,mxArray * pargout[],int nargin,const mxArray * pargin[])35 void mexFunction
36 (
37     int nargout,
38     mxArray *pargout [ ],
39     int nargin,
40     const mxArray *pargin [ ]
41 )
42 {
43     double dummy = 0 ;
44     cholmod_factor *L ;
45     cholmod_sparse *A, Amatrix, *C, *S ;
46     cholmod_common Common, *cm ;
47     Long n, transpose, c ;
48     char buf [LEN] ;
49 
50     /* ---------------------------------------------------------------------- */
51     /* start CHOLMOD and set defaults */
52     /* ---------------------------------------------------------------------- */
53 
54     cm = &Common ;
55     cholmod_l_start (cm) ;
56     sputil_config (SPUMONI, cm) ;
57 
58     /* only do the simplicial analysis (L->Perm and L->ColCount) */
59     cm->supernodal = CHOLMOD_SIMPLICIAL ;
60 
61     /* ---------------------------------------------------------------------- */
62     /* get inputs */
63     /* ---------------------------------------------------------------------- */
64 
65     if (nargout > 2 || nargin < 1 || nargin > 3)
66     {
67 	mexErrMsgTxt ("Usage: [p count] = analyze (A, mode)") ;
68     }
69     if (nargin == 3)
70     {
71 	cm->nmethods = mxGetScalar (pargin [2]) ;
72 	if (cm->nmethods == -1)
73 	{
74 	    /* use AMD only */
75 	    cm->nmethods = 1 ;
76 	    cm->method [0].ordering = CHOLMOD_AMD ;
77 	    cm->postorder = TRUE ;
78 	}
79 	else if (cm->nmethods == -2)
80 	{
81 	    /* use METIS only */
82 	    cm->nmethods = 1 ;
83 	    cm->method [0].ordering = CHOLMOD_METIS ;
84 	    cm->postorder = TRUE ;
85 	}
86 	else if (cm->nmethods == -3)
87 	{
88 	    /* use NESDIS only */
89 	    cm->nmethods = 1 ;
90 	    cm->method [0].ordering = CHOLMOD_NESDIS ;
91 	    cm->postorder = TRUE ;
92 	}
93     }
94 
95     /* ---------------------------------------------------------------------- */
96     /* get input matrix A */
97     /* ---------------------------------------------------------------------- */
98 
99     A = sputil_get_sparse_pattern (pargin [0], &Amatrix, &dummy, cm) ;
100     S = (A == &Amatrix) ? NULL : A ;
101 
102     /* ---------------------------------------------------------------------- */
103     /* get A->stype, default is to use tril(A) */
104     /* ---------------------------------------------------------------------- */
105 
106     A->stype = -1 ;
107     transpose = FALSE ;
108 
109     if (nargin > 1)
110     {
111 	buf [0] = '\0' ;
112 	if (mxIsChar (pargin [1]))
113 	{
114 	    mxGetString (pargin [1], buf, LEN) ;
115 	}
116 	c = buf [0] ;
117 	if (tolower (c) == 'r')
118 	{
119 	    /* unsymmetric case (A*A') if string starts with 'r' */
120 	    transpose = FALSE ;
121 	    A->stype = 0 ;
122 	}
123 	else if (tolower (c) == 'c')
124 	{
125 	    /* unsymmetric case (A'*A) if string starts with 'c' */
126 	    transpose = TRUE ;
127 	    A->stype = 0 ;
128 	}
129 	else if (tolower (c) == 's')
130 	{
131 	    /* symmetric case (A) if string starts with 's' */
132 	    transpose = FALSE ;
133 	    A->stype = -1 ;
134 	}
135 	else
136 	{
137 	    mexErrMsgTxt ("analyze: unrecognized mode") ;
138 	}
139     }
140 
141     if (A->stype && A->nrow != A->ncol)
142     {
143 	mexErrMsgTxt ("analyze: A must be square") ;
144     }
145 
146     C = NULL ;
147     if (transpose)
148     {
149 	/* C = A', and then order C*C' */
150 	C = cholmod_l_transpose (A, 0, cm) ;
151 	if (C == NULL)
152 	{
153 	    mexErrMsgTxt ("analyze failed") ;
154 	}
155 	A = C ;
156     }
157 
158     n = A->nrow ;
159 
160     /* ---------------------------------------------------------------------- */
161     /* analyze and order the matrix */
162     /* ---------------------------------------------------------------------- */
163 
164     L = cholmod_l_analyze (A, cm) ;
165 
166     /* ---------------------------------------------------------------------- */
167     /* return Perm */
168     /* ---------------------------------------------------------------------- */
169 
170     pargout [0] = sputil_put_int (L->Perm, n, 1) ;
171     if (nargout > 1)
172     {
173 	pargout [1] = sputil_put_int (L->ColCount, n, 0) ;
174     }
175 
176     /* ---------------------------------------------------------------------- */
177     /* free workspace */
178     /* ---------------------------------------------------------------------- */
179 
180     cholmod_l_free_factor (&L, cm) ;
181     cholmod_l_free_sparse (&C, cm) ;
182     cholmod_l_free_sparse (&S, cm) ;
183     cholmod_l_finish (cm) ;
184     cholmod_l_print_common (" ", cm) ;
185     /* if (cm->malloc_count != 0) mexErrMsgTxt ("!") ; */
186 }
187