21 const double one = 1.0, zero = 0.0;
24 const int n = Dims[1];
25 const R_xlen_t n_ = n, np1 = n + 1, nsqr = n_ * n_;
27 SEXP val = PROTECT(duplicate(x));
28 int i, ilo, ilos, ihi, ihis, j, sqpow;
29 int *pivot = R_Calloc(n,
int);
30 double *dpp = R_Calloc(nsqr,
double),
31 *npp = R_Calloc(nsqr,
double),
32 *perm = R_Calloc(n,
double),
33 *scale = R_Calloc(n,
double),
35 *work = R_Calloc(nsqr,
double), inf_norm, m1_j, trshift;
38 if (n < 1 || Dims[0] != n)
39 error(
_(
"Matrix exponential requires square, non-null matrix"));
48 for (i = 0; i < n; i++) trshift += v[i * np1];
51 for (i = 0; i < n; i++) v[i * np1] -= trshift;
55 F77_CALL(dgebal)(
"P", &n, v, &n, &ilo, &ihi, perm, &j
FCONE);
56 if (j) error(
_(
"dgeMatrix_exp: LAPACK routine dgebal returned %d"), j);
57 F77_CALL(dgebal)(
"S", &n, v, &n, &ilos, &ihis, scale, &j
FCONE);
58 if (j) error(
_(
"dgeMatrix_exp: LAPACK routine dgebal returned %d"), j);
61 inf_norm = F77_CALL(dlange)(
"I", &n, &n, v, &n, work
FCONE);
62 sqpow = (inf_norm > 0) ? (
int) (1 + log(inf_norm)/log(2.)) : 0;
63 if (sqpow < 0) sqpow = 0;
65 double scale_factor = 1.0;
66 for (i = 0; i < sqpow; i++) scale_factor *= 2.;
67 for (R_xlen_t i = 0; i < nsqr; i++) v[i] /= scale_factor;
74 for (j = 7; j >=0; j--) {
75 double mult =
padec[j];
77 F77_CALL(dgemm)(
"N",
"N", &n, &n, &n, &one, v, &n, npp, &n,
79 for (R_xlen_t i = 0; i < nsqr; i++) npp[i] = work[i] + mult * v[i];
82 F77_CALL(dgemm)(
"N",
"N", &n, &n, &n, &one, v, &n, dpp, &n,
84 for (R_xlen_t i = 0; i < nsqr; i++) dpp[i] = work[i] + mult * v[i];
88 for (R_xlen_t i = 0; i < nsqr; i++) dpp[i] *= -1.;
89 for (j = 0; j < n; j++) {
95 F77_CALL(dgetrf)(&n, &n, dpp, &n, pivot, &j);
96 if (j) error(
_(
"dgeMatrix_exp: dgetrf returned error code %d"), j);
97 F77_CALL(dgetrs)(
"N", &n, &n, dpp, &n, pivot, npp, &n, &j
FCONE);
98 if (j) error(
_(
"dgeMatrix_exp: dgetrs returned error code %d"), j);
104 F77_CALL(dgemm)(
"N",
"N", &n, &n, &n, &one, v, &n, v, &n,
106 Memcpy(v, work, nsqr);
109 for (j = 0; j < n; j++) {
110 R_xlen_t jn = j * n_;
111 for (i = 0; i < n; i++)
112 v[i + jn] *= scale[i]/scale[j];
117 if (ilo != 1 || ihi != n) {
120#define SWAP_ROW(I,J) F77_CALL(dswap)(&n, &v[(I)], &n, &v[(J)], &n)
122#define SWAP_COL(I,J) F77_CALL(dswap)(&n, &v[(I)*n_], &i1, &v[(J)*n_], &i1)
124#define RE_PERMUTE(I) \
125 int p_I = (int) (perm[I]) - 1; \
130 for (i = (ilo - 1) - 1; i >= 0; i--) {
135 for (i = (ihi + 1) - 1; i < n; i++) {
142 double mult = exp(trshift);
143 for (R_xlen_t i = 0; i < nsqr; i++) v[i] *= mult;
147 R_Free(work); R_Free(scale); R_Free(perm); R_Free(npp); R_Free(dpp); R_Free(pivot);