|
Matrix $Rev: 2718 $ at $LastChangedDate: 2011-10-06 11:45:17 +0200 (Thu, 06 Oct 2011) $
|
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 }