Rev 3484 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
#include "sparseQR.h"SEXP sparseQR_validate(SEXP x){CSP V = AS_CSP(GET_SLOT(x, install("V"))),R = AS_CSP(GET_SLOT(x, install("R")));SEXP beta = GET_SLOT(x, install("beta")),p = GET_SLOT(x, Matrix_pSym),q = GET_SLOT(x, install("q"));int lq = LENGTH(q);R_CheckStack();if (LENGTH(p) != V->m)return mkString(_("length(p) must match nrow(V)"));if (LENGTH(beta) != V->m)return mkString(_("length(beta) must match nrow(V)"));if (lq && lq != R->n)return mkString(_("length(q) must be zero or ncol(R)"));if (V->n != R->n)return mkString(_("ncol(V) != ncol(R)"));/* FIXME: Check that the permutations are permutations */return ScalarLogical(1);}/*** Apply Householder transformations and the row permutation P to y** @param a sparse matrix containing the vectors defining the* Householder transformations* @param beta scaling factors for the Householder transformations* @param y contents of a V->m by nrhs dense matrix* @param p 0-based permutation vector of length V->m* @param nrhs number of right hand sides (i.e. ncol(y))* @param trans logical value - if TRUE create Q'y[p] otherwise Qy[p]*/staticvoid sparseQR_Qmult(cs *V, double *beta, int *p, int trans,double *y, int *ydims){int j, k, m = V->m, n = V->n;double *x = Alloca(m, double); /* workspace */R_CheckStack();if (ydims[0] != m)error(_("Dimensions of system are inconsistent"));for (j = 0; j < ydims[1]; j++) {double *yj = y + j * m;if (trans) {cs_pvec(p, yj, x, m); /* x(0:m-1) = y(p(0:m-1, j)) */Memcpy(yj, x, m); /* replace it */for (k = 0 ; k < n ; k++) /* apply H[1]...H[n] */cs_happly(V, k, beta[k], yj);} else {for (k = n - 1 ; k >= 0 ; k--) /* apply H[n]...H[1] */cs_happly(V, k, beta[k], yj);cs_ipvec(p, yj, x, m); /* inverse permutation */Memcpy(yj, x, m);}}}SEXP sparseQR_qty(SEXP qr, SEXP y, SEXP trans){SEXP ans = PROTECT(dup_mMatrix_as_dgeMatrix(y));CSP V = AS_CSP(GET_SLOT(qr, install("V")));R_CheckStack();sparseQR_Qmult(V, REAL(GET_SLOT(qr, install("beta"))),INTEGER(GET_SLOT(qr, Matrix_pSym)),asLogical(trans),REAL(GET_SLOT(ans, Matrix_xSym)),INTEGER(GET_SLOT(ans, Matrix_DimSym)));UNPROTECT(1);return ans;}SEXP sparseQR_coef(SEXP qr, SEXP y){SEXP ans = PROTECT(dup_mMatrix_as_dgeMatrix(y)),qslot = GET_SLOT(qr, install("q"));CSP V = AS_CSP(GET_SLOT(qr, install("V"))),R = AS_CSP(GET_SLOT(qr, install("R")));int *ydims = INTEGER(GET_SLOT(ans, Matrix_DimSym)),*q = INTEGER(qslot),j, lq = LENGTH(qslot), m = R->m, n = R->n;double *ax = REAL(GET_SLOT(ans, Matrix_xSym)),*x = Alloca(m, double);R_CheckStack();R_CheckStack();/* apply row permutation and multiply by Q' */sparseQR_Qmult(V, REAL(GET_SLOT(qr, install("beta"))),INTEGER(GET_SLOT(qr, Matrix_pSym)), 1,REAL(GET_SLOT(ans, Matrix_xSym)), ydims);for (j = 0; j < ydims[1]; j++) {double *aj = ax + j * m;cs_usolve(R, aj);if (lq) {cs_ipvec(q, aj, x, n);Memcpy(aj, x, n);}}UNPROTECT(1);return ans;}SEXP sparseQR_resid_fitted(SEXP qr, SEXP y, SEXP resid){SEXP ans = PROTECT(dup_mMatrix_as_dgeMatrix(y));CSP V = AS_CSP(GET_SLOT(qr, install("V")));int *ydims = INTEGER(GET_SLOT(ans, Matrix_DimSym)),*p = INTEGER(GET_SLOT(qr, Matrix_pSym)),i, j, m = V->m, n = V->n, res = asLogical(resid);double *ax = REAL(GET_SLOT(ans, Matrix_xSym)),*beta = REAL(GET_SLOT(qr, install("beta")));R_CheckStack();/* apply row permutation and multiply by Q' */sparseQR_Qmult(V, beta, p, 1, ax, ydims);for (j = 0; j < ydims[1]; j++) {if (res) /* zero first n rows */for (i = 0; i < n; i++) ax[i + j * m] = 0;else /* zero last m - n rows */for (i = n; i < m; i++) ax[i + j * m] = 0;}/* multiply by Q and apply inverse row permutation */sparseQR_Qmult(V, beta, p, 0, ax, ydims);UNPROTECT(1);return ans;}