Matrix r5059
Loading...
Searching...
No Matches
Cholesky.c
Go to the documentation of this file.
1#include "Lapack-etc.h"
2#include "cholmod-etc.h"
3#include "Mdefines.h"
4
5/* defined in ./coerce.c : */
6SEXP dense_as_kind(SEXP, const char *, char, int);
7SEXP sparse_as_kind(SEXP, const char *, char);
8SEXP sparse_as_general(SEXP, const char *);
9SEXP sparse_as_Csparse(SEXP, const char *);
10
11/* defined in ./forceCanonical.c : */
12SEXP dense_force_canonical(SEXP, const char *, int);
13
14/* defined in ./forceSymmetric.c : */
15SEXP sparse_force_symmetric(SEXP, const char *, char, char);
16
17/* defined in ./t.c : */
18SEXP sparse_transpose(SEXP, const char *, char, int);
19
20SEXP dense_cholesky(SEXP obj, const char *class, int warn, int pivot,
21 double tol, char ul)
22{
23 int *pdim = DIM(obj), n = pdim[1];
24 if (pdim[0] != n)
25 Rf_error(_("matrix is not square"));
26 ul = (class[1] != 'g') ? UPLO(obj) : (ul == '\0') ? 'U' : ul;
27 char cl[] = ".denseCholesky";
28 cl[0] = (class[0] == 'z') ? 'z' : 'd';
29 SEXP ans = PROTECT(newObject(cl));
30 SET_DIM(ans, n, n);
31 SET_DIMNAMES(ans, -(class[1] == 's'), DIMNAMES(obj, 0));
32 if (ul != 'U')
33 SET_UPLO(ans);
34 if (n > 0) {
35 PROTECT_INDEX pid;
36 PROTECT_WITH_INDEX(obj, &pid);
37 if (class[0] != 'z' && class[0] != 'd') {
38 REPROTECT(obj = dense_as_kind(obj, class, ',', 1), pid);
39 class = Matrix_class(obj, valid_dense, 6, __func__);
40 }
41 if (class[1] == 't' && DIAG(obj) != 'N')
42 REPROTECT(obj = dense_force_canonical(obj, class, 0), pid);
43 SEXP x = PROTECT(GET_SLOT(obj, Matrix_xSym)),
44 y = PROTECT(Rf_allocVector(TYPEOF(x), XLENGTH(x)));
45 int info;
46 if (class[2] != 'p') {
47 if (TYPEOF(x) == CPLXSXP) {
48 Rcomplex *px = COMPLEX(x), *py = COMPLEX(y);
49 memset(py, 0, sizeof(Rcomplex) * (size_t) XLENGTH(y));
50 F77_CALL(zlacpy)(&ul, &n, &n, px, &n, py, &n FCONE);
51 if (!pivot) {
52 F77_CALL(zpotrf)(&ul, &n, py, &n, &info FCONE);
53 ERROR_LAPACK_3(zpotrf, info, warn);
54 } else {
55 SEXP perm = PROTECT(Rf_allocVector(INTSXP, n));
56 int *pperm = INTEGER(perm), rank;
57 double *work = (double *) R_alloc((size_t) n * 2, sizeof(double));
58 F77_CALL(zpstrf)(&ul, &n, py, &n, pperm, &rank, &tol, work,
59 &info FCONE);
60 ERROR_LAPACK_4(zpstrf, info, warn, rank);
61 if (info > 0) {
62 int j, d = n - rank;
63 py += (R_xlen_t) rank * n + rank;
64 for (j = rank; j < n; ++j) {
65 memset(py, 0, sizeof(Rcomplex) * (size_t) d);
66 py += n;
67 }
68 }
69 SET_SLOT(ans, Matrix_permSym, perm);
70 UNPROTECT(1); /* perm */
71 }
72 } else {
73 double *px = REAL(x), *py = REAL(y);
74 memset(py, 0, sizeof(double) * (size_t) XLENGTH(y));
75 F77_CALL(dlacpy)(&ul, &n, &n, px, &n, py, &n FCONE);
76 if (!pivot) {
77 F77_CALL(dpotrf)(&ul, &n, py, &n, &info FCONE);
78 ERROR_LAPACK_3(dpotrf, info, warn);
79 } else {
80 SEXP perm = PROTECT(Rf_allocVector(INTSXP, n));
81 int *pperm = INTEGER(perm), rank;
82 double *work = (double *) R_alloc((size_t) n * 2, sizeof(double));
83 F77_CALL(dpstrf)(&ul, &n, py, &n, pperm, &rank, &tol, work,
84 &info FCONE);
85 ERROR_LAPACK_4(dpstrf, info, warn, rank);
86 if (info > 0) {
87 int j, d = n - rank;
88 py += (R_xlen_t) rank * n + rank;
89 for (j = rank; j < n; ++j) {
90 memset(py, 0, sizeof(double) * (size_t) d);
91 py += n;
92 }
93 }
94 SET_SLOT(ans, Matrix_permSym, perm);
95 UNPROTECT(1); /* perm */
96 }
97 }
98 } else {
99 if (TYPEOF(x) == CPLXSXP) {
100 Rcomplex *px = COMPLEX(x), *py = COMPLEX(y);
101 memcpy(py, px, sizeof(Rcomplex) * (size_t) XLENGTH(y));
102 F77_CALL(zpptrf)(&ul, &n, py, &info FCONE);
103 ERROR_LAPACK_3(zpptrf, info, warn);
104 } else {
105 double *px = REAL(x), *py = REAL(y);
106 memcpy(py, px, sizeof(double) * (size_t) XLENGTH(y));
107 F77_CALL(dpptrf)(&ul, &n, py, &info FCONE);
108 ERROR_LAPACK_3(dpptrf, info, warn);
109 }
110 }
111 SET_SLOT(ans, Matrix_xSym, y);
112 UNPROTECT(3); /* y, x, obj */
113 }
114 UNPROTECT(1); /* ans */
115 return ans;
116}
117
118SEXP sparse_cholesky(SEXP obj, const char *class, int warn, int order,
119 int *ll, int *super, Rcomplex beta, int force,
120 char ul, SEXP trf)
121{
122 PROTECT_INDEX pid;
123 PROTECT_WITH_INDEX(obj, &pid);
124 if (class[0] != 'z' && class[0] != 'd') {
125 REPROTECT(obj = sparse_as_kind(obj, class, ','), pid);
126 class = Matrix_class(obj, valid_sparse, 6, __func__);
127 }
128 if (class[1] == 's' && (class[0] != 'z' || TRANS(obj) == 'C'))
129 ;
130 else {
131 if (force)
132 REPROTECT(obj = sparse_force_symmetric(obj, class, ul, 'C'), pid);
133 else
134 REPROTECT(obj = sparse_as_general(obj, class), pid);
135 class = Matrix_class(obj, valid_sparse, 6, __func__);
136 }
137 if (class[2] != 'C') {
138 if (class[2] == 'R' && class[1] == 's')
139 REPROTECT(obj = sparse_transpose(obj, class, 'C', 1), pid);
140 else
141 REPROTECT(obj = sparse_as_Csparse(obj, class), pid);
142 class = Matrix_class(obj, valid_sparse, 6, __func__);
143 }
144
145 cholmod_sparse *A = M2CHS(obj, 1);
146 cholmod_factor *L = (trf == R_NilValue) ? NULL : M2CHF(trf, 1);
147 double b[2]; b[0] = beta.r; b[1] = beta.i;
148
149 A->stype = (class[1] != 's') ? 0 : (UPLO(obj) == 'U') ? 1 : -1;
150
151 if (L)
152 L = cholmod_copy_factor(L, &c);
153 else {
154 if (order == 0) {
155 c.nmethods = 1;
156 c.method[0].ordering = CHOLMOD_NATURAL;
157 c.postorder = 0;
158 }
159 c.supernodal = (!super || *super == NA_LOGICAL) ? CHOLMOD_AUTO :
160 ((*super != 0) ? CHOLMOD_SUPERNODAL : CHOLMOD_SIMPLICIAL);
161 L = cholmod_analyze(A, &c);
162 }
163
164 if (super)
165 *super = L->is_super != 0;
166 if (ll)
167 *ll = L->is_super != 0 || L->is_ll != 0;
168
169 c.final_asis = 0;
170 c.final_ll = ((ll) ? *ll : L->is_ll) != 0;
171 c.final_super = ((super) ? *super : L->is_super) != 0;
172 c.final_pack = 1;
173 c.final_monotonic = 1;
174
175 cholmod_factorize_p(A, b, NULL, 0, L, &c);
176 cholmod_defaults(&c);
177
178 SEXP ans = PROTECT(CHF2M(L, 1));
179 cholmod_free_factor(&L, &c);
180 if (TYPEOF(ans) == CHARSXP) {
181 if (warn > 1)
182 Rf_error ("%s", CHAR(ans));
183 else if (warn > 0)
184 Rf_warning("%s", CHAR(ans));
185 ans = R_NilValue;
186 } else {
187 SEXP adimnames = PROTECT(Rf_allocVector(VECSXP, 2)),
188 odimnames = PROTECT(DIMNAMES(obj, 0));
189 symDN(adimnames, odimnames, (class[1] != 's') ? 0 : -1);
190 SET_DIMNAMES(ans, 0, adimnames);
191 UNPROTECT(2); /* odimnames, adimnames */
192 }
193 UNPROTECT(2); /* ans, obj */
194 return ans;
195}
196
197SEXP R_dense_cholesky(SEXP s_obj, SEXP s_warn, SEXP s_pivot,
198 SEXP s_tol, SEXP s_uplo)
199{
200 const char *class = Matrix_class(s_obj, valid_dense, 6, __func__);
201 int pivot = Rf_asLogical(s_pivot);
202 double tol = Rf_asReal(s_tol);
203 if (ISNAN(tol))
204 Rf_error(_("'%s' is not a number"), "tol");
205 char ul = '\0';
206 if (s_uplo != R_NilValue)
207 VALID_UPLO(s_uplo, ul);
208 int cache = (class[1] == 's') &&
209 ((class[0] == 'z' && TRANS(s_obj) == 'C') || class[0] == 'd');
210 char nm[] = "denseCholesky..";
211 if (class[1] == 's' && class[2] == 'p')
212 nm[13] = nm[14] = '-';
213 else {
214 nm[13] = '+';
215 nm[14] = (!pivot) ? '-' : '+';
216 }
217 SEXP ans = (cache) ? get_factor(s_obj, nm) : R_NilValue;
218 if (ans == R_NilValue) {
219 int warn = Rf_asInteger(s_warn);
220 ans = dense_cholesky(s_obj, class, warn, pivot, tol, ul);
221 if (cache) {
222 PROTECT(ans);
223 set_factor(s_obj, nm, ans);
224 UNPROTECT(1);
225 }
226 }
227 return ans;
228}
229
230SEXP R_sparse_cholesky(SEXP s_obj, SEXP s_warn, SEXP s_order,
231 SEXP s_ll, SEXP s_super, SEXP s_beta,
232 SEXP s_force, SEXP s_uplo)
233{
234 const char *class = Matrix_class(s_obj, valid_sparse, 6, __func__);
235 int warn = Rf_asInteger(s_warn), order = Rf_asInteger(s_order),
236 ll = Rf_asLogical(s_ll), super = Rf_asLogical(s_super),
237 force = Rf_asLogical(s_force);
238 Rcomplex beta = Rf_asComplex(s_beta);
239 if (order < 0 || order > 1)
240 order = 0;
241 if (!R_FINITE(beta.r) || !R_FINITE(beta.i))
242 Rf_error(_("'%s' is not a number or not finite"), "beta");
243 char ul = '\0';
244 if (s_uplo != R_NilValue)
245 VALID_UPLO(s_uplo, ul);
246 int cache = (class[1] == 's') &&
247 ((class[0] == 'z' && TRANS(s_obj) == 'C') || class[0] == 'd');
248 char nm[] = "..........Cholesky.";
249 nm[18] = (order == 0) ? '-' : '+';
250 SEXP ans = R_NilValue;
251 if (cache) {
252 if (super == NA_LOGICAL || super == 0) {
253 memcpy(nm, "simplicial", 10);
254 ans = get_factor(s_obj, nm);
255 if (ans != R_NilValue) super = 0;
256 }
257 if (ans == R_NilValue && (super == NA_LOGICAL || super != 0)) {
258 memcpy(nm, "supernodal", 10);
259 ans = get_factor(s_obj, nm);
260 if (ans != R_NilValue) super = 1;
261 }
262 }
263 if (beta.r != 0.0 || beta.i != 0.0 || ans == R_NilValue ||
264 (super == 0 && ll != 0)) {
265 if (beta.r != 0.0 || beta.i != 0.0) {
266 PROTECT(ans);
267 ans = sparse_cholesky(s_obj, class, warn,
268 order, &ll, &super, beta,
269 force, ul, ans);
270 UNPROTECT(1);
271 } else {
272 if (ans == R_NilValue) {
273 int zz = 0;
274 ans = sparse_cholesky(s_obj, class, warn,
275 order, &zz, &super, beta,
276 force, ul, ans);
277 if (cache && ans != R_NilValue) {
278 memcpy(nm, (super == 0) ? "simplicial" : "supernodal", 10);
279 PROTECT(ans);
280 set_factor(s_obj, nm, ans);
281 UNPROTECT(1);
282 }
283 }
284 if (ans != R_NilValue && super == 0 && ll != 0) {
285 PROTECT(ans);
286 cholmod_factor *L = M2CHF(ans, 1);
287 L = cholmod_copy_factor(L, &c);
288 cholmod_change_factor(L->xtype, 1, 0, 1, 1, L, &c);
289 SEXP tmp = PROTECT(CHF2M(L, 1));
290 cholmod_free_factor(&L, &c);
291 if (TYPEOF(tmp) == CHARSXP) {
292 if (warn > 1)
293 Rf_error ("%s", CHAR(tmp));
294 else if (warn > 0)
295 Rf_warning("%s", CHAR(tmp));
296 ans = R_NilValue;
297 } else {
298 SET_DIMNAMES(tmp, 0, DIMNAMES(ans, 0));
299 ans = tmp;
300 }
301 UNPROTECT(2); /* tmp, ans */
302 }
303 }
304 }
305 return ans;
306}
SEXP sparse_transpose(SEXP, const char *, char, int)
Definition t.c:52
SEXP sparse_as_general(SEXP, const char *)
Definition coerce.c:2298
SEXP dense_force_canonical(SEXP, const char *, int)
SEXP dense_cholesky(SEXP obj, const char *class, int warn, int pivot, double tol, char ul)
Definition Cholesky.c:20
SEXP R_dense_cholesky(SEXP s_obj, SEXP s_warn, SEXP s_pivot, SEXP s_tol, SEXP s_uplo)
Definition Cholesky.c:197
SEXP sparse_as_kind(SEXP, const char *, char)
Definition coerce.c:2076
SEXP sparse_cholesky(SEXP obj, const char *class, int warn, int order, int *ll, int *super, Rcomplex beta, int force, char ul, SEXP trf)
Definition Cholesky.c:118
SEXP R_sparse_cholesky(SEXP s_obj, SEXP s_warn, SEXP s_order, SEXP s_ll, SEXP s_super, SEXP s_beta, SEXP s_force, SEXP s_uplo)
Definition Cholesky.c:230
SEXP sparse_force_symmetric(SEXP, const char *, char, char)
SEXP sparse_as_Csparse(SEXP, const char *)
Definition coerce.c:2731
SEXP dense_as_kind(SEXP, const char *, char, int)
Definition coerce.c:2000
#define FCONE
Definition Lapack-etc.h:13
#define ERROR_LAPACK_3(_ROUTINE_, _INFO_, _WARN_)
Definition Lapack-etc.h:38
#define ERROR_LAPACK_4(_ROUTINE_, _INFO_, _WARN_, _RANK_)
Definition Lapack-etc.h:51
#define SET_DIM(x, m, n)
Definition Mdefines.h:87
const char * valid_dense[]
Definition objects.c:3
#define _(String)
Definition Mdefines.h:66
#define SET_UPLO(x)
Definition Mdefines.h:103
#define DIAG(x)
Definition Mdefines.h:111
#define UPLO(x)
Definition Mdefines.h:101
#define SET_DIMNAMES(x, mode, value)
Definition Mdefines.h:98
#define VALID_UPLO(s, c)
Definition Mdefines.h:158
const char * Matrix_class(SEXP, const char **, int, const char *)
Definition objects.c:112
#define DIMNAMES(x, mode)
Definition Mdefines.h:96
#define TRANS(x)
Definition Mdefines.h:106
#define DIM(x)
Definition Mdefines.h:85
#define GET_SLOT(x, name)
Definition Mdefines.h:72
SEXP newObject(const char *)
Definition objects.c:13
const char * valid_sparse[]
Definition Mdefines.h:328
#define SET_SLOT(x, name, value)
Definition Mdefines.h:73
#define TYPEOF(s)
Definition Mdefines.h:123
void symDN(SEXP dest, SEXP src, int J)
Definition attrib.c:69
SEXP get_factor(SEXP obj, const char *nm)
Definition attrib.c:180
void set_factor(SEXP obj, const char *nm, SEXP val)
Definition attrib.c:192
cholmod_factor * M2CHF(SEXP obj, int values)
Definition cholmod-etc.c:39
cholmod_sparse * M2CHS(SEXP obj, int values)
SEXP CHF2M(cholmod_factor *L, int values)
cholmod_common c
Definition cholmod-etc.c:5
cholmod_common cl
Definition cholmod-etc.c:6
SEXP Matrix_permSym
Definition init.c:623
SEXP Matrix_xSym
Definition init.c:635