Matrix $Rev: 2718 $ at $LastChangedDate: 2011-10-06 11:45:17 +0200 (Thu, 06 Oct 2011) $
Tsparse.c
Go to the documentation of this file.
00001                                 /* Sparse matrices in triplet form */
00002 #include "Tsparse.h"
00003 #include "chm_common.h"
00004 
00005 SEXP Tsparse_validate(SEXP x)
00006 {
00007     /* NB: we do *NOT* check a potential 'x' slot here, at all */
00008     SEXP
00009         islot = GET_SLOT(x, Matrix_iSym),
00010         jslot = GET_SLOT(x, Matrix_jSym),
00011         dimslot = GET_SLOT(x, Matrix_DimSym);
00012     int j,
00013         nrow = INTEGER(dimslot)[0],
00014         ncol = INTEGER(dimslot)[1],
00015         nnz = length(islot),
00016         *xj = INTEGER(jslot),
00017         *xi = INTEGER(islot);
00018 
00019     if (length(jslot) != nnz)
00020         return mkString(_("lengths of slots i and j must match"));
00021     /* FIXME: this is checked in super class -- no need to do here: */
00022     if (length(dimslot) != 2)
00023         return mkString(_("slot Dim must have length 2"));
00024 
00025     for (j = 0; j < nnz; j++) {
00026         if (xi[j] < 0 || xi[j] >= nrow)
00027             return mkString(_("all row indices (slot 'i') must be between 0 and nrow-1 in a TsparseMatrix"));
00028         if (xj[j] < 0 || xj[j] >= ncol)
00029             return mkString(_("all column indices (slot 'j') must be between 0 and ncol-1 in a TsparseMatrix"));
00030     }
00031     return ScalarLogical(1);
00032 }
00033 
00034 SEXP Tsparse_to_Csparse(SEXP x, SEXP tri)
00035 {
00036     CHM_TR chxt = AS_CHM_TR__(x); /* << should *preserve*  diag = "U" ! */
00037     CHM_SP chxs = cholmod_triplet_to_sparse(chxt, chxt->nnz, &c);
00038     int tr = asLogical(tri);
00039     int Rkind = (chxt->xtype != CHOLMOD_PATTERN) ? Real_kind(x) : 0;
00040     R_CheckStack();
00041 
00042     return chm_sparse_to_SEXP(chxs, 1,
00043                               tr ? ((*uplo_P(x) == 'U') ? 1 : -1) : 0,
00044                               Rkind, tr ? diag_P(x) : "",
00045                               GET_SLOT(x, Matrix_DimNamesSym));
00046 }
00047 
00048 /* speedup utility, needed e.g. after subsetting: */
00049 SEXP Tsparse_to_tCsparse(SEXP x, SEXP uplo, SEXP diag)
00050 {
00051     CHM_TR chxt = AS_CHM_TR__(x);
00052     CHM_SP chxs = cholmod_triplet_to_sparse(chxt, chxt->nnz, &c);
00053     int Rkind = (chxt->xtype != CHOLMOD_PATTERN) ? Real_kind(x) : 0;
00054     R_CheckStack();
00055 
00056     return chm_sparse_to_SEXP(chxs, 1,
00057                               /* uploT = */ (*CHAR(asChar(uplo)) == 'U')? 1: -1,
00058                               Rkind,
00059                               /* diag = */ CHAR(STRING_ELT(diag, 0)),
00060                               GET_SLOT(x, Matrix_DimNamesSym));
00061 }
00062 
00063 SEXP Tsparse_diagU2N(SEXP x)
00064 {
00065     static const char *valid[] = {
00066         "dtTMatrix", /* 0 */
00067         "ltTMatrix", /* 1 */
00068         "ntTMatrix", /* 2 : no x slot */
00069         "ztTMatrix", /* 3 */
00070         ""};
00071 /* #define xSXP(iTyp) ((iTyp == 0) ? REALSXP : ((iTyp == 1) ? LGLSXP : /\* else *\/ CPLXSXP)); */
00072 /* #define xTYPE(iTyp) ((iTyp == 0) ? double : ((iTyp == 1) ? int : /\* else *\/ Rcomplex)); */
00073     int ctype = Matrix_check_class_etc(x, valid);
00074 
00075     if (ctype < 0 || *diag_P(x) != 'U') {
00076         /* "trivially fast" when not triangular (<==> no 'diag' slot),
00077            or not *unit* triangular */
00078         return (x);
00079     }
00080     else { /* instead of going to Csparse -> Cholmod -> Csparse -> Tsparse, work directly: */
00081         int i, n = INTEGER(GET_SLOT(x, Matrix_DimSym))[0],
00082             nnz = length(GET_SLOT(x, Matrix_iSym)),
00083             new_n = nnz + n;
00084         SEXP ans = PROTECT(NEW_OBJECT(MAKE_CLASS(class_P(x))));
00085         int *islot = INTEGER(ALLOC_SLOT(ans, Matrix_iSym, INTSXP, new_n)),
00086             *jslot = INTEGER(ALLOC_SLOT(ans, Matrix_jSym, INTSXP, new_n));
00087 
00088         slot_dup(ans, x, Matrix_DimSym);
00089         SET_DimNames(ans, x);
00090         slot_dup(ans, x, Matrix_uploSym);
00091         SET_SLOT(ans, Matrix_diagSym, mkString("N"));
00092 
00093         /* Build the new i- and j- slots : first copy the current : */
00094         Memcpy(islot, INTEGER(GET_SLOT(x, Matrix_iSym)), nnz);
00095         Memcpy(jslot, INTEGER(GET_SLOT(x, Matrix_jSym)), nnz);
00096         /* then, add the new (i,j) slot entries: */
00097         for(i = 0; i < n; i++) {
00098             islot[i + nnz] = i;
00099             jslot[i + nnz] = i;
00100         }
00101 
00102         /* build the new x-slot : */
00103         switch(ctype) {
00104         case 0: { /* "d" */
00105             double *x_new = REAL(ALLOC_SLOT(ans, Matrix_xSym,
00106                                             REALSXP, new_n));
00107             Memcpy(x_new, REAL(GET_SLOT(x, Matrix_xSym)), nnz);
00108             for(i = 0; i < n; i++) /* add  x[i,i] = 1. */
00109                 x_new[i + nnz] = 1.;
00110             break;
00111         }
00112         case 1: { /* "l" */
00113             int *x_new = LOGICAL(ALLOC_SLOT(ans, Matrix_xSym,
00114                                             LGLSXP, new_n));
00115             Memcpy(x_new, LOGICAL(GET_SLOT(x, Matrix_xSym)), nnz);
00116             for(i = 0; i < n; i++) /* add  x[i,i] = 1 (= TRUE) */
00117                 x_new[i + nnz] = 1;
00118             break;
00119         }
00120         case 2: /* "n" */
00121                 /* nothing to do here */
00122             break;
00123 
00124         case 3: { /* "z" */
00125             Rcomplex *x_new = COMPLEX(ALLOC_SLOT(ans, Matrix_xSym,
00126                                                  CPLXSXP, new_n));
00127             Memcpy(x_new, COMPLEX(GET_SLOT(x, Matrix_xSym)), nnz);
00128             for(i = 0; i < n; i++) /* add  x[i,i] = 1 (= TRUE) */
00129                 x_new[i + nnz] = (Rcomplex) {1., 0.};
00130             break;
00131         }
00132 
00133         }/* switch() */
00134 
00135         UNPROTECT(1);
00136         return ans;
00137     }
00138 }