Matrix $Rev: 2718 $ at $LastChangedDate: 2011-10-06 11:45:17 +0200 (Thu, 06 Oct 2011) $
dgeMatrix.c
Go to the documentation of this file.
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 }