[R] off topic: C/C++ codes for pseudo inverse
Torsten Hothorn
Torsten.Hothorn at rzmail.uni-erlangen.de
Wed Jun 16 12:06:02 CEST 2004
On Wed, 16 Jun 2004, Mahbub Latif wrote:
> Hi,
>
> I am looking for C/C++ codes for computing generalized
> inverse of a matrix. Can anyone help me in this
> regard?
>
experimental, undocumented and for square matrices only:
SEXP svd (SEXP x) {
/* experimental */
SEXP jobu, jobv, u, v, method, dummy, ans;
int i, p;
if (!isMatrix(x) || !isReal(x))
error("x is not a real matrix");
PROTECT(method = allocVector(STRSXP, 1));
SET_STRING_ELT(method, 0, mkChar("dgesdd"));
PROTECT(jobu = allocVector(STRSXP, 1));
SET_STRING_ELT(jobu, 0, mkChar("S"));
PROTECT(jobv = allocVector(STRSXP, 1));
SET_STRING_ELT(jobv, 0, mkChar(""));
p = INTEGER(getAttrib(x, R_DimSymbol))[0];
PROTECT(u = allocMatrix(REALSXP, p, p));
PROTECT(v = allocMatrix(REALSXP, p, p));
for (i = 0; i < p*p; i++) {
REAL(u)[i] = 0;
REAL(v)[i] = 0;
}
PROTECT(dummy = allocVector(REALSXP, p));
PROTECT(ans = La_svd(jobu, jobv, x, dummy, u, v, method));
UNPROTECT(7);
return(ans);
}
void cMPinv (SEXP x, double tol, double *ans, double *rank) {
SEXP svdx, d, u, vt;
int i, j, p, k, *positive;
double *dd, *du, *dvt;
PROTECT(svdx = svd(x));
d = VECTOR_ELT(svdx, 0);
dd = REAL(d);
u = VECTOR_ELT(svdx, 1);
du = REAL(u);
vt = VECTOR_ELT(svdx, 2);
dvt = REAL(vt);
p = LENGTH(d);
tol = tol * dd[0];
if (tol < 0.0) tol = 0.0;
positive = Calloc(p, int);
rank[0] = 0.0;
for (i = 0; i < p; i++) {
if (dd[i] > tol) {
positive[i] = 1;
rank[0]++;
}
}
for (j = 0; j < p; j++) {
if (positive[j]) {
for (i = 0; i < p; i++)
du[j * p + i] *= (1 / dd[j]);
}
}
for (i = 0; i < p; i++) {
for (j = 0; j < p; j++) {
ans[j * p + i] = 0.0;
for (k = 0; k < p; k++) {
if (positive[k])
ans[j * p + i] += dvt[i * p + k] * du[p * k + j];
}
}
}
Free(positive);
UNPROTECT(1);
}
SEXP MPinv (SEXP x, SEXP tol) {
SEXP ans, mp, rank;
int p;
if (!isMatrix(x) || !isReal(x))
error("x is not a real matrix");
if (INTEGER(getAttrib(x, R_DimSymbol))[0] !=
INTEGER(getAttrib(x, R_DimSymbol))[1])
error("x is not a square matrix");
if (!isReal(tol) || LENGTH(tol) != 1)
error("tol is not a scalar real");
p = INTEGER(getAttrib(x, R_DimSymbol))[0];
PROTECT(ans = allocVector(VECSXP, 2));
SET_VECTOR_ELT(ans, 0, mp = allocMatrix(REALSXP, p, p));
SET_VECTOR_ELT(ans, 1, rank = allocVector(REALSXP, 1));
cMPinv(x, REAL(tol)[0], REAL(mp), REAL(rank));
UNPROTECT(1);
return(ans);
}
you need to include `La_svd' from R.
Torsten
> Thanks,
>
> Mahbub.
>
> ______________________________________________
> R-help at stat.math.ethz.ch mailing list
> https://www.stat.math.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide! http://www.R-project.org/posting-guide.html
>
>
More information about the R-help
mailing list