|
Matrix $Rev: 2718 $ at $LastChangedDate: 2011-10-06 11:45:17 +0200 (Thu, 06 Oct 2011) $
|
00001 #include "dgeMatrix.h" 00002 00003 SEXP dMatrix_validate(SEXP obj) 00004 { 00005 SEXP x = GET_SLOT(obj, Matrix_xSym), 00006 Dim = GET_SLOT(obj, Matrix_DimSym); 00007 int m, n; 00008 00009 if (length(Dim) != 2) 00010 return mkString(_("Dim slot must have length 2")); 00011 m = INTEGER(Dim)[0]; n = INTEGER(Dim)[1]; 00012 if (m < 0 || n < 0) 00013 #if defined(R_VERSION) && R_VERSION >= R_Version(2, 10, 0) 00014 return mkString(dngettext("Matrix", 00015 "Negative value in Dim", 00016 "Negative values in Dim", 00017 (m*n > 0) ? 2 : 1)); 00018 #else 00019 return mkString(_("Negative value(s) in Dim")); 00020 #endif 00021 if (!isReal(x)) 00022 return mkString(_("x slot must be numeric \"double\"")); 00023 return ScalarLogical(1); 00024 } 00025 00026 SEXP dgeMatrix_validate(SEXP obj) 00027 { 00028 SEXP val, 00029 fact = GET_SLOT(obj, Matrix_factorSym); 00030 00031 if (isString(val = dense_nonpacked_validate(obj))) 00032 return(val); 00033 00034 if (length(fact) > 0 && getAttrib(fact, R_NamesSymbol) == R_NilValue) 00035 return mkString(_("factors slot must be named list")); 00036 return ScalarLogical(1); 00037 } 00038 00039 static 00040 double get_norm(SEXP obj, const char *typstr) 00041 { 00042 if(any_NA_in_x(obj)) 00043 return NA_REAL; 00044 else { 00045 char typnm[] = {'\0', '\0'}; 00046 int *dims = INTEGER(GET_SLOT(obj, Matrix_DimSym)); 00047 double *work = (double *) NULL; 00048 00049 typnm[0] = La_norm_type(typstr); 00050 if (*typnm == 'I') { 00051 work = (double *) R_alloc(dims[0], sizeof(double)); 00052 } 00053 return F77_CALL(dlange)(typstr, dims, dims+1, 00054 REAL(GET_SLOT(obj, Matrix_xSym)), 00055 dims, work); 00056 } 00057 } 00058 00059 SEXP dgeMatrix_norm(SEXP obj, SEXP type) 00060 { 00061 return ScalarReal(get_norm(obj, CHAR(asChar(type)))); 00062 } 00063 00064 SEXP dgeMatrix_rcond(SEXP obj, SEXP type) 00065 { 00066 SEXP LU = PROTECT(dgeMatrix_LU_(obj, FALSE));/* <- not warning about singularity */ 00067 char typnm[] = {'\0', '\0'}; 00068 int *dims = INTEGER(GET_SLOT(LU, Matrix_DimSym)), info; 00069 double anorm, rcond; 00070 00071 if (dims[0] != dims[1] || dims[0] < 1) { 00072 UNPROTECT(1); 00073 error(_("rcond requires a square, non-empty matrix")); 00074 } 00075 typnm[0] = La_rcond_type(CHAR(asChar(type))); 00076 anorm = get_norm(obj, typnm); 00077 F77_CALL(dgecon)(typnm, 00078 dims, REAL(GET_SLOT(LU, Matrix_xSym)), 00079 dims, &anorm, &rcond, 00080 (double *) R_alloc(4*dims[0], sizeof(double)), 00081 (int *) R_alloc(dims[0], sizeof(int)), &info); 00082 UNPROTECT(1); 00083 return ScalarReal(rcond); 00084 } 00085 00086 SEXP dgeMatrix_crossprod(SEXP x, SEXP trans) 00087 { 00088 int tr = asLogical(trans);/* trans=TRUE: tcrossprod(x) */ 00089 SEXP val = PROTECT(NEW_OBJECT(MAKE_CLASS("dpoMatrix"))), 00090 nms = VECTOR_ELT(GET_SLOT(x, Matrix_DimNamesSym), tr ? 0 : 1), 00091 vDnms = ALLOC_SLOT(val, Matrix_DimNamesSym, VECSXP, 2); 00092 int *Dims = INTEGER(GET_SLOT(x, Matrix_DimSym)), 00093 *vDims = INTEGER(ALLOC_SLOT(val, Matrix_DimSym, INTSXP, 2)); 00094 int k = tr ? Dims[1] : Dims[0], n = tr ? Dims[0] : Dims[1]; 00095 double *vx = REAL(ALLOC_SLOT(val, Matrix_xSym, REALSXP, n * n)), 00096 one = 1.0, zero = 0.0; 00097 00098 AZERO(vx, n * n); 00099 SET_SLOT(val, Matrix_uploSym, mkString("U")); 00100 ALLOC_SLOT(val, Matrix_factorSym, VECSXP, 0); 00101 vDims[0] = vDims[1] = n; 00102 SET_VECTOR_ELT(vDnms, 0, duplicate(nms)); 00103 SET_VECTOR_ELT(vDnms, 1, duplicate(nms)); 00104 if(n) 00105 F77_CALL(dsyrk)("U", tr ? "N" : "T", &n, &k, 00106 &one, REAL(GET_SLOT(x, Matrix_xSym)), Dims, 00107 &zero, vx, &n); 00108 SET_SLOT(val, Matrix_factorSym, allocVector(VECSXP, 0)); 00109 UNPROTECT(1); 00110 return val; 00111 } 00112 00113 SEXP dgeMatrix_dgeMatrix_crossprod(SEXP x, SEXP y, SEXP trans) 00114 { 00115 int tr = asLogical(trans);/* trans=TRUE: tcrossprod(x,y) */ 00116 SEXP val = PROTECT(NEW_OBJECT(MAKE_CLASS("dgeMatrix"))); 00117 int *xDims = INTEGER(GET_SLOT(x, Matrix_DimSym)), 00118 *yDims = INTEGER(GET_SLOT(y, Matrix_DimSym)), 00119 *vDims; 00120 int m = xDims[!tr], n = yDims[!tr];/* -> result dim */ 00121 int xd = xDims[ tr], yd = yDims[ tr];/* the conformable dims */ 00122 double one = 1.0, zero = 0.0; 00123 00124 SET_SLOT(val, Matrix_factorSym, allocVector(VECSXP, 0)); 00125 SET_SLOT(val, Matrix_DimSym, allocVector(INTSXP, 2)); 00126 vDims = INTEGER(GET_SLOT(val, Matrix_DimSym)); 00127 if (xd > 0 && yd > 0 && n > 0 && m > 0) { 00128 if (xd != yd) 00129 error(_("Dimensions of x and y are not compatible for %s"), 00130 tr ? "tcrossprod" : "crossprod"); 00131 vDims[0] = m; vDims[1] = n; 00132 SET_SLOT(val, Matrix_xSym, allocVector(REALSXP, m * n)); 00133 F77_CALL(dgemm)(tr ? "N" : "T", tr ? "T" : "N", &m, &n, &xd, &one, 00134 REAL(GET_SLOT(x, Matrix_xSym)), xDims, 00135 REAL(GET_SLOT(y, Matrix_xSym)), yDims, 00136 &zero, REAL(GET_SLOT(val, Matrix_xSym)), &m); 00137 } 00138 UNPROTECT(1); 00139 return val; 00140 } 00141 00142 SEXP dgeMatrix_matrix_crossprod(SEXP x, SEXP y, SEXP trans) 00143 { 00144 int tr = asLogical(trans);/* trans=TRUE: tcrossprod(x,y) */ 00145 SEXP val = PROTECT(NEW_OBJECT(MAKE_CLASS("dgeMatrix"))); 00146 int *xDims = INTEGER(GET_SLOT(x, Matrix_DimSym)), 00147 *yDims = INTEGER(getAttrib(y, R_DimSymbol)), 00148 *vDims, nprot = 1; 00149 int m = xDims[!tr], n = yDims[!tr];/* -> result dim */ 00150 int xd = xDims[ tr], yd = yDims[ tr];/* the conformable dims */ 00151 double one = 1.0, zero = 0.0; 00152 00153 if (isInteger(y)) { 00154 y = PROTECT(coerceVector(y, REALSXP)); 00155 nprot++; 00156 } 00157 if (!(isMatrix(y) && isReal(y))) 00158 error(_("Argument y must be a numeric matrix")); 00159 SET_SLOT(val, Matrix_factorSym, allocVector(VECSXP, 0)); 00160 SET_SLOT(val, Matrix_DimSym, allocVector(INTSXP, 2)); 00161 vDims = INTEGER(GET_SLOT(val, Matrix_DimSym)); 00162 if (xd > 0 && yd > 0 && n > 0 && m > 0) { 00163 if (xd != yd) 00164 error(_("Dimensions of x and y are not compatible for %s"), 00165 tr ? "tcrossprod" : "crossprod"); 00166 vDims[0] = m; vDims[1] = n; 00167 SET_SLOT(val, Matrix_xSym, allocVector(REALSXP, m * n)); 00168 F77_CALL(dgemm)(tr ? "N" : "T", tr ? "T" : "N", &m, &n, &xd, &one, 00169 REAL(GET_SLOT(x, Matrix_xSym)), xDims, 00170 REAL(y), yDims, 00171 &zero, REAL(GET_SLOT(val, Matrix_xSym)), &m); 00172 } 00173 UNPROTECT(nprot); 00174 return val; 00175 } 00176 00177 00178 SEXP dgeMatrix_getDiag(SEXP x) 00179 { 00180 #define geMatrix_getDiag_1 \ 00181 int *dims = INTEGER(GET_SLOT(x, Matrix_DimSym)); \ 00182 int i, m = dims[0], nret = (m < dims[1]) ? m : dims[1]; \ 00183 SEXP x_x = GET_SLOT(x, Matrix_xSym) 00184 00185 geMatrix_getDiag_1; 00186 SEXP ret = PROTECT(allocVector(REALSXP, nret)); 00187 double *rv = REAL(ret), 00188 *xv = REAL(x_x); 00189 00190 #define geMatrix_getDiag_2 \ 00191 for (i = 0; i < nret; i++) { \ 00192 rv[i] = xv[i * (m + 1)]; \ 00193 } \ 00194 UNPROTECT(1); \ 00195 return ret 00196 00197 geMatrix_getDiag_2; 00198 } 00199 00200 SEXP lgeMatrix_getDiag(SEXP x) 00201 { 00202 geMatrix_getDiag_1; 00203 00204 SEXP ret = PROTECT(allocVector(LGLSXP, nret)); 00205 int *rv = LOGICAL(ret), 00206 *xv = LOGICAL(x_x); 00207 00208 geMatrix_getDiag_2; 00209 } 00210 00211 #undef geMatrix_getDiag_1 00212 #undef geMatrix_getDiag_2 00213 00214 00215 SEXP dgeMatrix_LU_(SEXP x, Rboolean warn_sing) 00216 { 00217 SEXP val = get_factors(x, "LU"); 00218 int *dims, npiv, info; 00219 00220 if (val != R_NilValue) /* nothing to do if it's there in 'factors' slot */ 00221 return val; 00222 dims = INTEGER(GET_SLOT(x, Matrix_DimSym)); 00223 if (dims[0] < 1 || dims[1] < 1) 00224 error(_("Cannot factor a matrix with zero extents")); 00225 npiv = (dims[0] < dims[1]) ? dims[0] : dims[1]; 00226 val = PROTECT(NEW_OBJECT(MAKE_CLASS("denseLU"))); 00227 slot_dup(val, x, Matrix_xSym); 00228 slot_dup(val, x, Matrix_DimSym); 00229 F77_CALL(dgetrf)(dims, dims + 1, REAL(GET_SLOT(val, Matrix_xSym)), 00230 dims, 00231 INTEGER(ALLOC_SLOT(val, Matrix_permSym, INTSXP, npiv)), 00232 &info); 00233 if (info < 0) 00234 error(_("Lapack routine %s returned error code %d"), "dgetrf", info); 00235 else if (info > 0 && warn_sing) 00236 warning(_("Exact singularity detected during LU decomposition: %s, i=%d."), 00237 "U[i,i]=0", info); 00238 UNPROTECT(1); 00239 return set_factors(x, val, "LU"); 00240 } 00241 00242 SEXP dgeMatrix_LU(SEXP x, SEXP warn_singularity) 00243 { 00244 return dgeMatrix_LU_(x, asLogical(warn_singularity)); 00245 } 00246 00247 SEXP dgeMatrix_determinant(SEXP x, SEXP logarithm) 00248 { 00249 int lg = asLogical(logarithm); 00250 int *dims = INTEGER(GET_SLOT(x, Matrix_DimSym)), 00251 n = dims[0], sign = 1; 00252 double modulus = lg ? 0. : 1; /* initialize; = result for n == 0 */ 00253 00254 if (n != dims[1]) 00255 error(_("Determinant requires a square matrix")); 00256 if (n > 0) { 00257 SEXP lu = dgeMatrix_LU_(x, /* do not warn about singular LU: */ FALSE); 00258 int i, *jpvt = INTEGER(GET_SLOT(lu, Matrix_permSym)); 00259 double *luvals = REAL(GET_SLOT(lu, Matrix_xSym)); 00260 00261 for (i = 0; i < n; i++) if (jpvt[i] != (i + 1)) sign = -sign; 00262 if (lg) { 00263 for (i = 0; i < n; i++) { 00264 double dii = luvals[i*(n + 1)]; /* ith diagonal element */ 00265 modulus += log(dii < 0 ? -dii : dii); 00266 if (dii < 0) sign = -sign; 00267 } 00268 } else { 00269 for (i = 0; i < n; i++) 00270 modulus *= luvals[i*(n + 1)]; 00271 if (modulus < 0) { 00272 modulus = -modulus; 00273 sign = -sign; 00274 } 00275 } 00276 } 00277 return as_det_obj(modulus, lg, sign); 00278 } 00279 00280 SEXP dgeMatrix_solve(SEXP a) 00281 { 00282 /* compute the 1-norm of the matrix, which is needed 00283 later for the computation of the reciprocal condition number. */ 00284 double aNorm = get_norm(a, "1"); 00285 00286 /* the LU decomposition : */ 00287 SEXP val = PROTECT(NEW_OBJECT(MAKE_CLASS("dgeMatrix"))), 00288 lu = dgeMatrix_LU_(a, TRUE); 00289 int *dims = INTEGER(GET_SLOT(lu, Matrix_DimSym)), 00290 *pivot = INTEGER(GET_SLOT(lu, Matrix_permSym)); 00291 00292 /* prepare variables for the dgetri calls */ 00293 double *x, tmp; 00294 int info, lwork = -1; 00295 00296 00297 if (dims[0] != dims[1]) error(_("Solve requires a square matrix")); 00298 slot_dup(val, lu, Matrix_xSym); 00299 x = REAL(GET_SLOT(val, Matrix_xSym)); 00300 slot_dup(val, lu, Matrix_DimSym); 00301 00302 if(dims[0]) /* the dimension is not zero */ 00303 { 00304 /* is the matrix is *computationally* singular ? */ 00305 double rcond; 00306 F77_CALL(dgecon)("1", dims, x, dims, &aNorm, &rcond, 00307 (double *) R_alloc(4*dims[0], sizeof(double)), 00308 (int *) R_alloc(dims[0], sizeof(int)), &info); 00309 if (info) 00310 error(_("error [%d] from Lapack 'dgecon()'"), info); 00311 if(rcond < DOUBLE_EPS) 00312 error(_("Lapack dgecon(): system computationally singular, reciprocal condition number = %g"), 00313 rcond); 00314 00315 /* only now try the inversion and check if the matrix is *exactly* singular: */ 00316 F77_CALL(dgetri)(dims, x, dims, pivot, &tmp, &lwork, &info); 00317 lwork = (int) tmp; 00318 F77_CALL(dgetri)(dims, x, dims, pivot, 00319 (double *) R_alloc((size_t) lwork, sizeof(double)), 00320 &lwork, &info); 00321 if (info) 00322 error(_("Lapack routine dgetri: system is exactly singular")); 00323 } 00324 UNPROTECT(1); 00325 return val; 00326 } 00327 00328 SEXP dgeMatrix_matrix_solve(SEXP a, SEXP b) 00329 { 00330 SEXP val = PROTECT(dup_mMatrix_as_dgeMatrix(b)), 00331 lu = PROTECT(dgeMatrix_LU_(a, TRUE)); 00332 int *adims = INTEGER(GET_SLOT(lu, Matrix_DimSym)), 00333 *bdims = INTEGER(GET_SLOT(val, Matrix_DimSym)); 00334 int info, n = bdims[0], nrhs = bdims[1]; 00335 00336 if (*adims != *bdims || bdims[1] < 1 || *adims < 1 || *adims != adims[1]) 00337 error(_("Dimensions of system to be solved are inconsistent")); 00338 F77_CALL(dgetrs)("N", &n, &nrhs, REAL(GET_SLOT(lu, Matrix_xSym)), &n, 00339 INTEGER(GET_SLOT(lu, Matrix_permSym)), 00340 REAL(GET_SLOT(val, Matrix_xSym)), &n, &info); 00341 if (info) 00342 error(_("Lapack routine dgetrs: system is exactly singular")); 00343 UNPROTECT(2); 00344 return val; 00345 } 00346 00347 SEXP dgeMatrix_matrix_mm(SEXP a, SEXP bP, SEXP right) 00348 { 00349 SEXP b = PROTECT(mMatrix_as_dgeMatrix(bP)), 00350 val = PROTECT(NEW_OBJECT(MAKE_CLASS("dgeMatrix"))); 00351 int *adims = INTEGER(GET_SLOT(a, Matrix_DimSym)), 00352 *bdims = INTEGER(GET_SLOT(b, Matrix_DimSym)), 00353 *cdims = INTEGER(ALLOC_SLOT(val, Matrix_DimSym, INTSXP, 2)); 00354 double one = 1., zero = 0.; 00355 00356 if (asLogical(right)) { 00357 int m = bdims[0], n = adims[1], k = bdims[1]; 00358 if (adims[0] != k) 00359 error(_("Matrices are not conformable for multiplication")); 00360 cdims[0] = m; cdims[1] = n; 00361 if (m < 1 || n < 1 || k < 1) { 00362 /* error(_("Matrices with zero extents cannot be multiplied")); */ 00363 ALLOC_SLOT(val, Matrix_xSym, REALSXP, m * n); 00364 } else 00365 F77_CALL(dgemm) ("N", "N", &m, &n, &k, &one, 00366 REAL(GET_SLOT(b, Matrix_xSym)), &m, 00367 REAL(GET_SLOT(a, Matrix_xSym)), &k, &zero, 00368 REAL(ALLOC_SLOT(val, Matrix_xSym, REALSXP, m * n)), 00369 &m); 00370 } else { 00371 int m = adims[0], n = bdims[1], k = adims[1]; 00372 00373 if (bdims[0] != k) 00374 error(_("Matrices are not conformable for multiplication")); 00375 cdims[0] = m; cdims[1] = n; 00376 if (m < 1 || n < 1 || k < 1) { 00377 /* error(_("Matrices with zero extents cannot be multiplied")); */ 00378 ALLOC_SLOT(val, Matrix_xSym, REALSXP, m * n); 00379 } else 00380 F77_CALL(dgemm) 00381 ("N", "N", &m, &n, &k, &one, REAL(GET_SLOT(a, Matrix_xSym)), 00382 &m, REAL(GET_SLOT(b, Matrix_xSym)), &k, &zero, 00383 REAL(ALLOC_SLOT(val, Matrix_xSym, REALSXP, m * n)), &m); 00384 } 00385 ALLOC_SLOT(val, Matrix_DimNamesSym, VECSXP, 2); 00386 UNPROTECT(2); 00387 return val; 00388 } 00389 00390 00391 SEXP dgeMatrix_svd(SEXP x, SEXP nnu, SEXP nnv) 00392 { 00393 int /* nu = asInteger(nnu), 00394 nv = asInteger(nnv), */ 00395 *dims = INTEGER(GET_SLOT(x, Matrix_DimSym)); 00396 double *xx = REAL(GET_SLOT(x, Matrix_xSym)); 00397 SEXP val = PROTECT(allocVector(VECSXP, 3)); 00398 00399 if (dims[0] && dims[1]) { 00400 int m = dims[0], n = dims[1], mm = (m < n)?m:n, 00401 lwork = -1, info; 00402 double tmp, *work; 00403 int *iwork = Alloca(8 * mm, int); 00404 R_CheckStack(); 00405 00406 SET_VECTOR_ELT(val, 0, allocVector(REALSXP, mm)); 00407 SET_VECTOR_ELT(val, 1, allocMatrix(REALSXP, m, mm)); 00408 SET_VECTOR_ELT(val, 2, allocMatrix(REALSXP, mm, n)); 00409 F77_CALL(dgesdd)("S", &m, &n, xx, &m, 00410 REAL(VECTOR_ELT(val, 0)), 00411 REAL(VECTOR_ELT(val, 1)), &m, 00412 REAL(VECTOR_ELT(val, 2)), &mm, 00413 &tmp, &lwork, iwork, &info); 00414 lwork = (int) tmp; 00415 work = Alloca(lwork, double); 00416 R_CheckStack(); 00417 F77_CALL(dgesdd)("S", &m, &n, xx, &m, 00418 REAL(VECTOR_ELT(val, 0)), 00419 REAL(VECTOR_ELT(val, 1)), &m, 00420 REAL(VECTOR_ELT(val, 2)), &mm, 00421 work, &lwork, iwork, &info); 00422 00423 } 00424 UNPROTECT(1); 00425 return val; 00426 } 00427 00428 const static double padec [] = /* for matrix exponential calculation. */ 00429 { 00430 5.0000000000000000e-1, 00431 1.1666666666666667e-1, 00432 1.6666666666666667e-2, 00433 1.6025641025641026e-3, 00434 1.0683760683760684e-4, 00435 4.8562548562548563e-6, 00436 1.3875013875013875e-7, 00437 1.9270852604185938e-9, 00438 }; 00439 00447 SEXP dgeMatrix_exp(SEXP x) 00448 { 00449 const double one = 1.0, zero = 0.0; 00450 const int i1 = 1; 00451 int *Dims = INTEGER(GET_SLOT(x, Matrix_DimSym)); 00452 const int n = Dims[1], nsqr = n * n, np1 = n + 1; 00453 00454 SEXP val = PROTECT(duplicate(x)); 00455 int i, ilo, ilos, ihi, ihis, j, sqpow; 00456 int *pivot = Calloc(n, int); 00457 double *dpp = Calloc(nsqr, double), /* denominator power Pade' */ 00458 *npp = Calloc(nsqr, double), /* numerator power Pade' */ 00459 *perm = Calloc(n, double), 00460 *scale = Calloc(n, double), 00461 *v = REAL(GET_SLOT(val, Matrix_xSym)), 00462 *work = Calloc(nsqr, double), inf_norm, m1_j/*= (-1)^j */, trshift; 00463 R_CheckStack(); 00464 00465 if (n < 1 || Dims[0] != n) 00466 error(_("Matrix exponential requires square, non-null matrix")); 00467 if(n == 1) { 00468 v[0] = exp(v[0]); 00469 UNPROTECT(1); 00470 return val; 00471 } 00472 00473 /* Preconditioning 1. Shift diagonal by average diagonal if positive. */ 00474 trshift = 0; /* determine average diagonal element */ 00475 for (i = 0; i < n; i++) trshift += v[i * np1]; 00476 trshift /= n; 00477 if (trshift > 0.) { /* shift diagonal by -trshift */ 00478 for (i = 0; i < n; i++) v[i * np1] -= trshift; 00479 } 00480 00481 /* Preconditioning 2. Balancing with dgebal. */ 00482 F77_CALL(dgebal)("P", &n, v, &n, &ilo, &ihi, perm, &j); 00483 if (j) error(_("dgeMatrix_exp: LAPACK routine dgebal returned %d"), j); 00484 F77_CALL(dgebal)("S", &n, v, &n, &ilos, &ihis, scale, &j); 00485 if (j) error(_("dgeMatrix_exp: LAPACK routine dgebal returned %d"), j); 00486 00487 /* Preconditioning 3. Scaling according to infinity norm */ 00488 inf_norm = F77_CALL(dlange)("I", &n, &n, v, &n, work); 00489 sqpow = (inf_norm > 0) ? (int) (1 + log(inf_norm)/log(2.)) : 0; 00490 if (sqpow < 0) sqpow = 0; 00491 if (sqpow > 0) { 00492 double scale_factor = 1.0; 00493 for (i = 0; i < sqpow; i++) scale_factor *= 2.; 00494 for (i = 0; i < nsqr; i++) v[i] /= scale_factor; 00495 } 00496 00497 /* Pade' approximation. Powers v^8, v^7, ..., v^1 */ 00498 AZERO(npp, nsqr); 00499 AZERO(dpp, nsqr); 00500 m1_j = -1; 00501 for (j = 7; j >=0; j--) { 00502 double mult = padec[j]; 00503 /* npp = m * npp + padec[j] *m */ 00504 F77_CALL(dgemm)("N", "N", &n, &n, &n, &one, v, &n, npp, &n, 00505 &zero, work, &n); 00506 for (i = 0; i < nsqr; i++) npp[i] = work[i] + mult * v[i]; 00507 /* dpp = m * dpp + (m1_j * padec[j]) * m */ 00508 mult *= m1_j; 00509 F77_CALL(dgemm)("N", "N", &n, &n, &n, &one, v, &n, dpp, &n, 00510 &zero, work, &n); 00511 for (i = 0; i < nsqr; i++) dpp[i] = work[i] + mult * v[i]; 00512 m1_j *= -1; 00513 } 00514 /* Zero power */ 00515 for (i = 0; i < nsqr; i++) dpp[i] *= -1.; 00516 for (j = 0; j < n; j++) { 00517 npp[j * np1] += 1.; 00518 dpp[j * np1] += 1.; 00519 } 00520 00521 /* Pade' approximation is solve(dpp, npp) */ 00522 F77_CALL(dgetrf)(&n, &n, dpp, &n, pivot, &j); 00523 if (j) error(_("dgeMatrix_exp: dgetrf returned error code %d"), j); 00524 F77_CALL(dgetrs)("N", &n, &n, dpp, &n, pivot, npp, &n, &j); 00525 if (j) error(_("dgeMatrix_exp: dgetrs returned error code %d"), j); 00526 Memcpy(v, npp, nsqr); 00527 00528 /* Now undo all of the preconditioning */ 00529 /* Preconditioning 3: square the result for every power of 2 */ 00530 while (sqpow--) { 00531 F77_CALL(dgemm)("N", "N", &n, &n, &n, &one, v, &n, v, &n, 00532 &zero, work, &n); 00533 Memcpy(v, work, nsqr); 00534 } 00535 /* Preconditioning 2: apply inverse scaling */ 00536 for (j = 0; j < n; j++) 00537 for (i = 0; i < n; i++) 00538 v[i + j * n] *= scale[i]/scale[j]; 00539 00540 00541 /* 2 b) Inverse permutation (if not the identity permutation) */ 00542 if (ilo != 1 || ihi != n) { 00543 /* Martin Maechler's code */ 00544 00545 #define SWAP_ROW(I,J) F77_CALL(dswap)(&n, &v[(I)], &n, &v[(J)], &n) 00546 00547 #define SWAP_COL(I,J) F77_CALL(dswap)(&n, &v[(I)*n], &i1, &v[(J)*n], &i1) 00548 00549 #define RE_PERMUTE(I) \ 00550 int p_I = (int) (perm[I]) - 1; \ 00551 SWAP_COL(I, p_I); \ 00552 SWAP_ROW(I, p_I) 00553 00554 /* reversion of "leading permutations" : in reverse order */ 00555 for (i = (ilo - 1) - 1; i >= 0; i--) { 00556 RE_PERMUTE(i); 00557 } 00558 00559 /* reversion of "trailing permutations" : applied in forward order */ 00560 for (i = (ihi + 1) - 1; i < n; i++) { 00561 RE_PERMUTE(i); 00562 } 00563 } 00564 00565 /* Preconditioning 1: Trace normalization */ 00566 if (trshift > 0.) { 00567 double mult = exp(trshift); 00568 for (i = 0; i < nsqr; i++) v[i] *= mult; 00569 } 00570 00571 /* Clean up */ 00572 Free(work); Free(scale); Free(perm); Free(npp); Free(dpp); Free(pivot); 00573 UNPROTECT(1); 00574 return val; 00575 } 00576 00577 SEXP dgeMatrix_Schur(SEXP x, SEXP vectors) 00578 { 00579 int *dims = INTEGER(GET_SLOT(x, Matrix_DimSym)); 00580 int vecs = asLogical(vectors), info, izero = 0, lwork = -1, n = dims[0]; 00581 double *work, tmp; 00582 const char *nms[] = {"WR", "WI", "T", "Z", ""}; 00583 SEXP val = PROTECT(Rf_mkNamed(VECSXP, nms)); 00584 00585 if (n != dims[1] || n < 1) 00586 error(_("dgeMatrix_Schur: argument x must be a non-null square matrix")); 00587 SET_VECTOR_ELT(val, 0, allocVector(REALSXP, n)); 00588 SET_VECTOR_ELT(val, 1, allocVector(REALSXP, n)); 00589 SET_VECTOR_ELT(val, 2, allocMatrix(REALSXP, n, n)); 00590 Memcpy(REAL(VECTOR_ELT(val, 2)), REAL(GET_SLOT(x, Matrix_xSym)), n * n); 00591 SET_VECTOR_ELT(val, 3, allocMatrix(REALSXP, vecs ? n : 0, vecs ? n : 0)); 00592 F77_CALL(dgees)(vecs ? "V" : "N", "N", NULL, dims, (double *) NULL, dims, &izero, 00593 (double *) NULL, (double *) NULL, (double *) NULL, dims, 00594 &tmp, &lwork, (int *) NULL, &info); 00595 if (info) error(_("dgeMatrix_Schur: first call to dgees failed")); 00596 lwork = (int) tmp; 00597 work = Alloca(lwork, double); 00598 R_CheckStack(); 00599 F77_CALL(dgees)(vecs ? "V" : "N", "N", NULL, dims, REAL(VECTOR_ELT(val, 2)), dims, 00600 &izero, REAL(VECTOR_ELT(val, 0)), REAL(VECTOR_ELT(val, 1)), 00601 REAL(VECTOR_ELT(val, 3)), dims, work, &lwork, 00602 (int *) NULL, &info); 00603 if (info) error(_("dgeMatrix_Schur: dgees returned code %d"), info); 00604 UNPROTECT(1); 00605 return val; 00606 } 00607 00608 SEXP dgeMatrix_colsums(SEXP x, SEXP naRmP, SEXP cols, SEXP mean) 00609 { 00610 int keepNA = !asLogical(naRmP); 00611 int doMean = asLogical(mean); 00612 int useCols = asLogical(cols); 00613 int *dims = INTEGER(GET_SLOT(x, Matrix_DimSym)); 00614 int i, j, m = dims[0], n = dims[1]; 00615 SEXP ans = PROTECT(allocVector(REALSXP, (useCols) ? n : m)); 00616 double *aa = REAL(ans), *xx = REAL(GET_SLOT(x, Matrix_xSym)); 00617 00618 if (useCols) { /* col(Sums|Means) : */ 00619 int cnt = m; 00620 for (j = 0; j < n; j++) { 00621 double *rx = xx + m * j; 00622 00623 aa[j] = 0; 00624 if (keepNA) 00625 for (i = 0; i < m; i++) aa[j] += rx[i]; 00626 else { 00627 cnt = 0; 00628 for (i = 0; i < m; i++) 00629 if (!ISNAN(rx[i])) {cnt++; aa[j] += rx[i];} 00630 } 00631 if (doMean) { 00632 if (cnt > 0) aa[j] /= cnt; else aa[j] = NA_REAL; 00633 } 00634 } 00635 } else { /* row(Sums|Means) : */ 00636 double *Count = ((!keepNA) && doMean) ? 00637 Alloca(m, double) : (double*)NULL ; 00638 R_CheckStack(); 00639 00640 for (i = 0; i < m; i++) aa[i] = 0.0; 00641 for (j = 0; j < n; j++) { 00642 if (keepNA) 00643 for (i = 0; i < m; i++) aa[i] += xx[i + j * m]; 00644 else 00645 for (i = 0; i < m; i++) { 00646 double el = xx[i + j * m]; 00647 if (!ISNAN(el)) { 00648 aa[i] += el; 00649 if (doMean) Count[i]++; 00650 } 00651 } 00652 } 00653 if (doMean) { 00654 if (keepNA) 00655 for (i = 0; i < m; i++) aa[i] /= n; 00656 else 00657 for (i = 0; i < m; i++) 00658 aa[i] = (Count[i]>0)? aa[i]/Count[i]: NA_REAL; 00659 } 00660 } 00661 00662 UNPROTECT(1); 00663 return ans; 00664 }