1 /* ========================================================================== */
2 /* === Supernodal/cholmod_super_solve ======================================= */
3 /* ========================================================================== */
4 
5 /* -----------------------------------------------------------------------------
6  * CHOLMOD/Supernodal Module.  Copyright (C) 2005-2006, Timothy A. Davis
7  * http://www.suitesparse.com
8  * -------------------------------------------------------------------------- */
9 
10 /* Solve Lx=b or L'x=b for a supernodal factorization.  These routines do not
11  * apply the permutation L->Perm.  See cholmod_solve for a more general
12  * interface that performs that operation.
13  */
14 
15 #ifndef NGPL
16 #ifndef NSUPERNODAL
17 
18 #include "cholmod_internal.h"
19 #include "cholmod_supernodal.h"
20 
21 /* ========================================================================== */
22 /* === TEMPLATE ============================================================= */
23 /* ========================================================================== */
24 
25 #define REAL
26 #include "t_cholmod_super_solve.c"
27 #define COMPLEX
28 #include "t_cholmod_super_solve.c"
29 
30 /* ========================================================================== */
31 /* === cholmod_super_lsolve ================================================= */
32 /* ========================================================================== */
33 
34 /* Solve Lx=b where x and b are of size n-by-nrhs.  b is overwritten by the
35  * solution x.  On input, b is stored in col-major order with leading dimension
36  * of d, and on output x is stored in the same manner.
37  *
38  * The contents of the workspace E are undefined on both input and output.
39  *
40  * workspace: none
41  */
42 
CHOLMOD(super_lsolve)43 int CHOLMOD(super_lsolve)   /* TRUE if OK, FALSE if BLAS overflow occured */
44 (
45     /* ---- input ---- */
46     cholmod_factor *L,	/* factor to use for the forward solve */
47     /* ---- output ---- */
48     cholmod_dense *X,	/* b on input, solution to Lx=b on output */
49     /* ---- workspace ---- */
50     cholmod_dense *E,	/* workspace of size nrhs*(L->maxesize) */
51     /* --------------- */
52     cholmod_common *Common
53 )
54 {
55     /* ---------------------------------------------------------------------- */
56     /* check inputs */
57     /* ---------------------------------------------------------------------- */
58 
59     RETURN_IF_NULL_COMMON (FALSE) ;
60     RETURN_IF_NULL (L, FALSE) ;
61     RETURN_IF_NULL (X, FALSE) ;
62     RETURN_IF_NULL (E, FALSE) ;
63     RETURN_IF_XTYPE_INVALID (L, CHOLMOD_REAL, CHOLMOD_COMPLEX, FALSE) ;
64     RETURN_IF_XTYPE_INVALID (X, CHOLMOD_REAL, CHOLMOD_COMPLEX, FALSE) ;
65     RETURN_IF_XTYPE_INVALID (E, CHOLMOD_REAL, CHOLMOD_COMPLEX, FALSE) ;
66     if (L->xtype != X->xtype)
67     {
68 	ERROR (CHOLMOD_INVALID, "L and X must have the same xtype") ;
69 	return (FALSE) ;
70     }
71     if (L->xtype != E->xtype)
72     {
73 	ERROR (CHOLMOD_INVALID, "L and E must have the same xtype") ;
74 	return (FALSE) ;
75     }
76     if (X->d < X->nrow || L->n != X->nrow)
77     {
78 	ERROR (CHOLMOD_INVALID, "X and L dimensions must match") ;
79 	return (FALSE) ;
80     }
81     if (E->nzmax < X->ncol * (L->maxesize))
82     {
83 	ERROR (CHOLMOD_INVALID, "workspace E not large enough") ;
84 	return (FALSE) ;
85     }
86     if (!(L->is_ll) || !(L->is_super))
87     {
88 	ERROR (CHOLMOD_INVALID, "L not supernodal") ;
89 	return (FALSE) ;
90     }
91     Common->status = CHOLMOD_OK ;
92     ASSERT (IMPLIES (L->n == 0, L->nsuper == 0)) ;
93     if (L->n == 0 || X->ncol == 0)
94     {
95 	/* nothing to do */
96 	return (TRUE) ;
97     }
98 
99     /* ---------------------------------------------------------------------- */
100     /* solve Lx=b using template routine */
101     /* ---------------------------------------------------------------------- */
102 
103     switch (L->xtype)
104     {
105 
106 	case CHOLMOD_REAL:
107 	    r_cholmod_super_lsolve (L, X, E, Common) ;
108 	    break ;
109 
110 	case CHOLMOD_COMPLEX:
111 	    c_cholmod_super_lsolve (L, X, E, Common) ;
112 	    break ;
113     }
114 
115     if (CHECK_BLAS_INT && !Common->blas_ok)
116     {
117 	ERROR (CHOLMOD_TOO_LARGE, "problem too large for the BLAS") ;
118     }
119     return (Common->blas_ok) ;
120 }
121 
122 
123 /* ========================================================================== */
124 /* === cholmod_super_ltsolve ================================================ */
125 /* ========================================================================== */
126 
127 /* Solve L'x=b where x and b are of size n-by-nrhs.  b is overwritten by the
128  * solution x.  On input, b is stored in col-major order with leading dimension
129  * of d, and on output x is stored in the same manner.
130  *
131  * The contents of the workspace E are undefined on both input and output.
132  *
133  * workspace: none
134  */
135 
CHOLMOD(super_ltsolve)136 int CHOLMOD(super_ltsolve)  /* TRUE if OK, FALSE if BLAS overflow occured */
137 (
138     /* ---- input ---- */
139     cholmod_factor *L,	/* factor to use for the backsolve */
140     /* ---- output ---- */
141     cholmod_dense *X,	/* b on input, solution to L'x=b on output */
142     /* ---- workspace ---- */
143     cholmod_dense *E,	/* workspace of size nrhs*(L->maxesize) */
144     /* --------------- */
145     cholmod_common *Common
146 )
147 {
148     /* ---------------------------------------------------------------------- */
149     /* check inputs */
150     /* ---------------------------------------------------------------------- */
151 
152     RETURN_IF_NULL_COMMON (FALSE) ;
153     RETURN_IF_NULL (L, FALSE) ;
154     RETURN_IF_NULL (X, FALSE) ;
155     RETURN_IF_NULL (E, FALSE) ;
156     RETURN_IF_XTYPE_INVALID (L, CHOLMOD_REAL, CHOLMOD_COMPLEX, FALSE) ;
157     RETURN_IF_XTYPE_INVALID (X, CHOLMOD_REAL, CHOLMOD_COMPLEX, FALSE) ;
158     RETURN_IF_XTYPE_INVALID (E, CHOLMOD_REAL, CHOLMOD_COMPLEX, FALSE) ;
159     if (L->xtype != X->xtype)
160     {
161 	ERROR (CHOLMOD_INVALID, "L and X must have the same xtype") ;
162 	return (FALSE) ;
163     }
164     if (L->xtype != E->xtype)
165     {
166 	ERROR (CHOLMOD_INVALID, "L and E must have the same xtype") ;
167 	return (FALSE) ;
168     }
169     if (X->d < X->nrow || L->n != X->nrow)
170     {
171 	ERROR (CHOLMOD_INVALID, "X and L dimensions must match") ;
172 	return (FALSE) ;
173     }
174     if (E->nzmax < X->ncol * (L->maxesize))
175     {
176 	ERROR (CHOLMOD_INVALID, "workspace E not large enough") ;
177 	return (FALSE) ;
178     }
179     if (!(L->is_ll) || !(L->is_super))
180     {
181 	ERROR (CHOLMOD_INVALID, "L not supernodal") ;
182 	return (FALSE) ;
183     }
184     Common->status = CHOLMOD_OK ;
185     ASSERT (IMPLIES (L->n == 0, L->nsuper == 0)) ;
186     if (L->n == 0 || X->ncol == 0)
187     {
188 	/* nothing to do */
189 	return (TRUE) ;
190     }
191 
192     /* ---------------------------------------------------------------------- */
193     /* solve Lx=b using template routine */
194     /* ---------------------------------------------------------------------- */
195 
196     switch (L->xtype)
197     {
198 
199 	case CHOLMOD_REAL:
200 	    r_cholmod_super_ltsolve (L, X, E, Common) ;
201 	    break ;
202 
203 	case CHOLMOD_COMPLEX:
204 	    c_cholmod_super_ltsolve (L, X, E, Common) ;
205 	    break ;
206     }
207 
208     if (CHECK_BLAS_INT && !Common->blas_ok)
209     {
210 	ERROR (CHOLMOD_TOO_LARGE, "problem too large for the BLAS") ;
211     }
212     return (Common->blas_ok) ;
213 }
214 #endif
215 #endif
216