The R Project SVN R-packages

Rev

Rev 4529 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4529 Rev 4530
Line 1... Line 1...
1
#include "dsCMatrix.h"
1
#include "dsCMatrix.h"
2
 
2
 
3
SEXP dsCMatrix_chol(SEXP x, SEXP pivot)
3
SEXP dsCMatrix_chol(SEXP x, SEXP pivot)
4
{
4
{
5
    cholmod_factor
-
 
6
	*N = as_cholmod_factor(dsCMatrix_Cholesky(x, pivot,
5
    CHM_FR N = AS_CHM_FR(dsCMatrix_Cholesky(x, pivot, ScalarLogical(FALSE),
7
						  ScalarLogical(FALSE),
-
 
8
						  ScalarLogical(FALSE)));
6
					    ScalarLogical(FALSE)));
9
    /* Must use a copy; cholmod_factor_to_sparse modifies first arg. */
7
    /* Must use a copy; cholmod_factor_to_sparse modifies first arg. */
10
    cholmod_factor *Ncp = cholmod_copy_factor(N, &c);
8
    CHM_FR Ncp = cholmod_copy_factor(N, &c);
11
    cholmod_sparse *L, *R;
-
 
12
    SEXP ans;
-
 
13
 
-
 
14
    L = cholmod_factor_to_sparse(Ncp, &c); cholmod_free_factor(&Ncp, &c);
9
    CHM_SP L = cholmod_factor_to_sparse(Ncp, &c);
15
    R = cholmod_transpose(L, /*values*/ 1, &c); cholmod_free_sparse(&L, &c);
10
    CHM_SP R = cholmod_transpose(L, /*values*/ 1, &c); 
16
    ans = PROTECT(chm_sparse_to_SEXP(R, /*cholmod_free*/ 1,
11
    SEXP ans = PROTECT(chm_sparse_to_SEXP(R, 1/*do_free*/, 1/*uploT*/, 0/*Rkind*/,
17
				     /*uploT*/ 1, /*Rkind*/ 0, /*diag*/ "N",
12
					  "N"/*diag*/, GET_SLOT(x, Matrix_DimNamesSym)));
18
				     GET_SLOT(x, Matrix_DimNamesSym)));
13
    cholmod_free_factor(&Ncp, &c);
-
 
14
    cholmod_free_sparse(&L, &c);
19
    if (asLogical(pivot)) {
15
    if (asLogical(pivot)) {
20
	SEXP piv = PROTECT(allocVector(INTSXP, N->n));
16
	SEXP piv = PROTECT(allocVector(INTSXP, N->n));
21
	int *dest = INTEGER(piv), *src = (int*)N->Perm, i;
17
	int *dest = INTEGER(piv), *src = (int*)N->Perm, i;
22
 
18
 
23
	for (i = 0; i < N->n; i++) dest[i] = src[i] + 1;
19
	for (i = 0; i < N->n; i++) dest[i] = src[i] + 1;
Line 28... Line 24...
28
	 * chm_factor_to_SEXP to keep track of Minor.
24
	 * chm_factor_to_SEXP to keep track of Minor.
29
	 */
25
	 */
30
	setAttrib(ans, install("rank"), ScalarInteger((size_t) N->minor));
26
	setAttrib(ans, install("rank"), ScalarInteger((size_t) N->minor));
31
	UNPROTECT(1);
27
	UNPROTECT(1);
32
    }
28
    }
33
    Free(N);
-
 
34
    UNPROTECT(1);
29
    UNPROTECT(1);
35
    return ans;
30
    return ans;
36
}
31
}
37
 
32
 
38
SEXP dsCMatrix_Cholesky(SEXP Ap, SEXP permP, SEXP LDLp, SEXP superP)
33
SEXP dsCMatrix_Cholesky(SEXP Ap, SEXP permP, SEXP LDLp, SEXP superP)
Line 40... Line 35...
40
    char fname[12] = "spdCholesky"; /* template for factorization name */
35
    char fname[12] = "spdCholesky"; /* template for factorization name */
41
    /* S|s : super or not
36
    /* S|s : super or not
42
     * P|p : permuted or not
37
     * P|p : permuted or not
43
     * D|d :  LDL' or not (= LL')
38
     * D|d :  LDL' or not (= LL')
44
     */
39
     */
45
    int perm = asLogical(permP),
40
    int perm = asLogical(permP), LDL = asLogical(LDLp), super = asLogical(superP);
46
	LDL = asLogical(LDLp),
-
 
47
	super = asLogical(superP);
-
 
48
    SEXP Chol;
41
    SEXP Chol;
49
    cholmod_sparse *A;
42
    CHM_SP A;
50
    cholmod_factor *L;
43
    CHM_FR L;
51
    int sup, ll;
44
    int sup, ll;
52
 
45
 
53
    if (super) fname[0] = 'S';
46
    if (super) fname[0] = 'S';
54
    if (perm) fname[1] = 'P';
47
    if (perm) fname[1] = 'P';
55
    if (LDL) fname[2] = 'D';
48
    if (LDL) fname[2] = 'D';
56
    Chol = get_factors(Ap, fname);
49
    Chol = get_factors(Ap, fname);
57
    /* If Ap has already cached the factor, we return it immediately */
-
 
58
    if (Chol != R_NilValue) return Chol;
50
    if (Chol != R_NilValue) return Chol; /* return a cached factor */
-
 
51
 
59
    A = as_cholmod_sparse(Ap);
52
    A = AS_CHM_SP(Ap);
60
    if (!A->stype)
53
    if (!A->stype)
61
	error("Non-symmetric matrix passed to dsCMatrix_chol");
54
	error("Non-symmetric matrix passed to dsCMatrix_chol");
62
 
55
 
63
    sup = c.supernodal;
56
    sup = c.supernodal;
64
    ll = c.final_ll;
57
    ll = c.final_ll;
Line 80... Line 73...
80
    }
73
    }
81
    if (!cholmod_factorize(A, L, &c))
74
    if (!cholmod_factorize(A, L, &c))
82
	error(_("Cholesky factorization failed"));
75
	error(_("Cholesky factorization failed"));
83
    c.supernodal = sup;	/* restore previous setting */
76
    c.supernodal = sup;	/* restore previous setting */
84
    c.final_ll = ll;
77
    c.final_ll = ll;
85
    Free(A);
-
 
86
    Chol = set_factors(Ap, chm_factor_to_SEXP(L, 1), fname);
78
    Chol = set_factors(Ap, chm_factor_to_SEXP(L, 1), fname);
87
    return Chol;
79
    return Chol;
88
}
80
}
89
 
81
 
90
static
82
static
Line 105... Line 97...
105
}
97
}
106
 
98
 
107
SEXP dsCMatrix_Csparse_solve(SEXP a, SEXP b)
99
SEXP dsCMatrix_Csparse_solve(SEXP a, SEXP b)
108
{
100
{
109
    SEXP Chol = get_factor_pattern(a, "...Cholesky", 3);
101
    SEXP Chol = get_factor_pattern(a, "...Cholesky", 3);
110
    cholmod_factor *L;
102
    CHM_FR L;
111
    cholmod_sparse *cx, *cb = as_cholmod_sparse(b);
103
    CHM_SP cx, cb = AS_CHM_SP(b);
112
 
104
 
113
    if (Chol == R_NilValue) /* compute (and cache) "sPDCholesky" */
105
    if (Chol == R_NilValue) /* compute (and cache) "sPDCholesky" */
114
	Chol = dsCMatrix_Cholesky(a,
106
	Chol = dsCMatrix_Cholesky(a,
115
				  ScalarLogical(1),  /* permuted  : "P" */
107
				  ScalarLogical(1),  /* permuted  : "P" */
116
				  ScalarLogical(1),  /* LDL'	  : "D" */
108
				  ScalarLogical(1),  /* LDL'	  : "D" */
117
				  ScalarLogical(0)); /* simplicial: "s" */
109
				  ScalarLogical(0)); /* simplicial: "s" */
118
    L = as_cholmod_factor(Chol);
110
    L = AS_CHM_FR(Chol);
119
    cx = cholmod_spsolve(CHOLMOD_A, L, cb, &c);
111
    cx = cholmod_spsolve(CHOLMOD_A, L, cb, &c);
120
    Free(cb); Free(L);
-
 
121
    return chm_sparse_to_SEXP(cx, /*cholmod_free*/ 1, /*uploT*/ 0,
112
    return chm_sparse_to_SEXP(cx, /*do_free*/ 1, /*uploT*/ 0,
122
			      /*Rkind*/ 0, /*diag*/ "N",
113
			      /*Rkind*/ 0, /*diag*/ "N",
123
			      /*dimnames = */ R_NilValue);
114
			      /*dimnames = */ R_NilValue);
124
}
115
}
125
 
116
 
126
SEXP dsCMatrix_matrix_solve(SEXP a, SEXP b)
117
SEXP dsCMatrix_matrix_solve(SEXP a, SEXP b)
127
{
118
{
128
    SEXP Chol = get_factor_pattern(a, "...Cholesky", 3);
119
    SEXP Chol = get_factor_pattern(a, "...Cholesky", 3);
129
    cholmod_factor *L;
120
    CHM_FR L;
130
    cholmod_dense  *cx,
-
 
131
	*cb = as_cholmod_dense(PROTECT(mMatrix_as_dgeMatrix(b)));
121
    CHM_DN cx, cb = AS_CHM_DN(PROTECT(mMatrix_as_dgeMatrix(b)));
132
 
122
 
133
    if (Chol == R_NilValue) /* compute (and cache) "sPDCholesky" */
123
    if (Chol == R_NilValue) /* compute (and cache) "sPDCholesky" */
134
	Chol = dsCMatrix_Cholesky(a,
124
	Chol = dsCMatrix_Cholesky(a,
135
				  ScalarLogical(1),  /* permuted  : "P" */
125
				  ScalarLogical(1),  /* permuted  : "P" */
136
				  ScalarLogical(1),  /* LDL'      : "D" */
126
				  ScalarLogical(1),  /* LDL'      : "D" */
137
				  ScalarLogical(0)); /* simplicial: "s" */
127
				  ScalarLogical(0)); /* simplicial: "s" */
138
    L = as_cholmod_factor(Chol);
128
    L = AS_CHM_FR(Chol);
139
    cx = cholmod_solve(CHOLMOD_A, L, cb, &c);
129
    cx = cholmod_solve(CHOLMOD_A, L, cb, &c);
140
    Free(cb); Free(L);
-
 
141
    UNPROTECT(1);
130
    UNPROTECT(1);
142
    return chm_dense_to_SEXP(cx, 1, 0, /*dimnames = */ R_NilValue);
131
    return chm_dense_to_SEXP(cx, 1, 0, /*dimnames = */ R_NilValue);
143
}
132
}
144
 
133
 
145
/* Needed for printing dsCMatrix objects */
134
/* Needed for printing dsCMatrix objects */
146
/* FIXME: Create a more general version of this operation: also for lsC, (dsR?),..
135
/* FIXME: Create a more general version of this operation: also for lsC, (dsR?),..
147
*         e.g. make  compressed_to_dgTMatrix() in ./dgCMatrix.c work for dsC */
136
*         e.g. make  compressed_to_dgTMatrix() in ./dgCMatrix.c work for dsC */
148
SEXP dsCMatrix_to_dgTMatrix(SEXP x)
137
SEXP dsCMatrix_to_dgTMatrix(SEXP x)
149
{
138
{
150
    cholmod_sparse *A = as_cholmod_sparse(x);
139
    CHM_SP A = AS_CHM_SP(x);
151
    cholmod_sparse *Afull = cholmod_copy(A, /*stype*/ 0, /*mode*/ 1, &c);
140
    CHM_SP Afull = cholmod_copy(A, /*stype*/ 0, /*mode*/ 1, &c);
152
    cholmod_triplet *At = cholmod_sparse_to_triplet(Afull, &c);
141
    CHM_TR At = cholmod_sparse_to_triplet(Afull, &c);
153
 
142
 
154
    if (!A->stype)
143
    if (!A->stype)
155
	error("Non-symmetric matrix passed to dsCMatrix_to_dgTMatrix");
144
	error("Non-symmetric matrix passed to dsCMatrix_to_dgTMatrix");
156
    Free(A); cholmod_free_sparse(&Afull, &c);
145
    cholmod_free_sparse(&Afull, &c);
157
    return chm_triplet_to_SEXP(At, 1, /*uploT*/ 0, /*Rkind*/ 0, "",
146
    return chm_triplet_to_SEXP(At, 1, /*uploT*/ 0, /*Rkind*/ 0, "",
158
			       GET_SLOT(x, Matrix_DimNamesSym));
147
			       GET_SLOT(x, Matrix_DimNamesSym));
159
}
148
}