SCM

SCM Repository

[matrix] Annotation of /pkg/src/dgeMatrix.c
ViewVC logotype

Annotation of /pkg/src/dgeMatrix.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 694 - (view) (download) (as text)

1 : bates 478 #include "dgeMatrix.h"
2 : bates 10
3 : bates 478 SEXP dgeMatrix_validate(SEXP obj)
4 : bates 10 {
5 :     SEXP x = GET_SLOT(obj, Matrix_xSym),
6 : bates 332 Dim = GET_SLOT(obj, Matrix_DimSym),
7 : bates 476 fact = GET_SLOT(obj, Matrix_factorSym),
8 : maechler 534 rc = GET_SLOT(obj, Matrix_rcondSym);
9 : bates 10 int m, n;
10 :    
11 :     if (length(Dim) != 2)
12 : bates 582 return mkString(_("Dim slot must have length 2"));
13 : bates 10 m = INTEGER(Dim)[0]; n = INTEGER(Dim)[1];
14 :     if (m < 0 || n < 0)
15 : bates 582 return mkString(_("Negative value(s) in Dim"));
16 : bates 10 if (length(x) != m * n)
17 : maechler 604 return mkString(_("length of x slot != prod(Dim)"));
18 :     if (!isReal(x))
19 :     return mkString(_("x slot must be numeric \"double\""));
20 : bates 332 if (length(fact) > 0 && getAttrib(fact, R_NamesSymbol) == R_NilValue)
21 : bates 582 return mkString(_("factors slot must be named list"));
22 : bates 332 if (length(rc) > 0 && getAttrib(rc, R_NamesSymbol) == R_NilValue)
23 : bates 582 return mkString(_("rcond slot must be named numeric vector"));
24 : bates 10 return ScalarLogical(1);
25 :     }
26 :    
27 :     static
28 :     double get_norm(SEXP obj, char *typstr)
29 : maechler 534 {
30 : bates 10 char typnm[] = {'\0', '\0'};
31 :     int *dims = INTEGER(GET_SLOT(obj, Matrix_DimSym));
32 :     double *work = (double *) NULL;
33 :    
34 :     typnm[0] = norm_type(typstr);
35 :     if (*typnm == 'I') {
36 :     work = (double *) R_alloc(dims[0], sizeof(double));
37 :     }
38 :     return F77_CALL(dlange)(typstr, dims, dims+1,
39 :     REAL(GET_SLOT(obj, Matrix_xSym)),
40 :     dims, work);
41 :     }
42 :    
43 : bates 478 SEXP dgeMatrix_norm(SEXP obj, SEXP type)
44 : bates 10 {
45 :     return ScalarReal(get_norm(obj, CHAR(asChar(type))));
46 :     }
47 :    
48 :     static
49 :     double set_rcond(SEXP obj, char *typstr)
50 :     {
51 :     char typnm[] = {'\0', '\0'};
52 : bates 332 SEXP rcv = GET_SLOT(obj, Matrix_rcondSym);
53 : bates 10 double rcond = get_double_by_name(rcv, typnm);
54 :    
55 :     typnm[0] = rcond_type(typstr);
56 :     if (R_IsNA(rcond)) {
57 : bates 478 SEXP LU = dgeMatrix_LU(obj);
58 : bates 10 int *dims = INTEGER(GET_SLOT(LU, Matrix_DimSym)), info;
59 :     double anorm = get_norm(obj, typstr);
60 :    
61 :     if (dims[0] != dims[1] || dims[0] < 1)
62 : bates 582 error(_("rcond requires a square, non-empty matrix"));
63 : bates 10 F77_CALL(dgecon)(typnm,
64 :     dims, REAL(GET_SLOT(LU, Matrix_xSym)),
65 :     dims, &anorm, &rcond,
66 :     (double *) R_alloc(4*dims[0], sizeof(double)),
67 :     (int *) R_alloc(dims[0], sizeof(int)), &info);
68 : bates 332 SET_SLOT(obj, Matrix_rcondSym,
69 : bates 10 set_double_by_name(rcv, rcond, typnm));
70 :     }
71 :     return rcond;
72 :     }
73 :    
74 : bates 478 SEXP dgeMatrix_rcond(SEXP obj, SEXP type)
75 : bates 10 {
76 :     return ScalarReal(set_rcond(obj, CHAR(asChar(type))));
77 :     }
78 :    
79 : bates 686 SEXP dgeMatrix_crossprod(SEXP x, SEXP trans)
80 : bates 10 {
81 : bates 686 int tr = asLogical(trans);
82 : bates 478 SEXP val = PROTECT(NEW_OBJECT(MAKE_CLASS("dpoMatrix")));
83 : bates 10 int *Dims = INTEGER(GET_SLOT(x, Matrix_DimSym)),
84 : bates 686 *vDims = INTEGER(ALLOC_SLOT(val, Matrix_DimSym, INTSXP, 2));
85 :     int i, k = tr ? Dims[1] : Dims[0], n = tr ? Dims[0] : Dims[1];
86 : bates 343 double one = 1.0, *xvals, zero = 0.0;
87 : bates 10
88 : maechler 534 SET_SLOT(val, Matrix_uploSym, mkString("U"));
89 : bates 332 vDims[0] = vDims[1] = n;
90 : bates 686 F77_CALL(dsyrk)("U", tr ? "N" : "T", &n, &k,
91 :     &one, REAL(GET_SLOT(x, Matrix_xSym)), Dims, &zero,
92 :     REAL(ALLOC_SLOT(val, Matrix_xSym, REALSXP, n * n)), &n);
93 : bates 10 UNPROTECT(1);
94 :     return val;
95 :     }
96 :    
97 : bates 478 SEXP dgeMatrix_dgeMatrix_crossprod(SEXP x, SEXP y)
98 : bates 10 {
99 : bates 478 SEXP val = PROTECT(NEW_OBJECT(MAKE_CLASS("dgeMatrix")));
100 : bates 10 int *xDims = INTEGER(GET_SLOT(x, Matrix_DimSym)),
101 :     *yDims = INTEGER(GET_SLOT(y, Matrix_DimSym)),
102 : bates 332 *vDims;
103 : bates 10 int m = xDims[1], n = yDims[1];
104 :     double one = 1.0, zero = 0.0;
105 :    
106 : bates 332 SET_SLOT(val, Matrix_rcondSym, allocVector(REALSXP, 0));
107 : bates 476 SET_SLOT(val, Matrix_factorSym, allocVector(VECSXP, 0));
108 : bates 332 SET_SLOT(val, Matrix_DimSym, allocVector(INTSXP, 2));
109 :     vDims = INTEGER(GET_SLOT(val, Matrix_DimSym));
110 : bates 10 if ((*xDims) > 0 && (*yDims) > 0 && n > 0 && m > 0) {
111 :     if (*xDims != *yDims)
112 : bates 582 error(_("Dimensions of x and y are not compatible for crossprod"));
113 : bates 10 vDims[0] = m; vDims[1] = n;
114 :     SET_SLOT(val, Matrix_xSym, allocVector(REALSXP, m * n));
115 :     F77_CALL(dgemm)("T", "N", xDims + 1, yDims + 1, xDims, &one,
116 :     REAL(GET_SLOT(x, Matrix_xSym)), xDims,
117 :     REAL(GET_SLOT(y, Matrix_xSym)), yDims,
118 :     &zero, REAL(GET_SLOT(val, Matrix_xSym)),
119 :     xDims + 1);
120 :     }
121 :     UNPROTECT(1);
122 :     return val;
123 :     }
124 :    
125 : bates 478 SEXP dgeMatrix_matrix_crossprod(SEXP x, SEXP y)
126 : bates 10 {
127 : bates 478 SEXP val = PROTECT(NEW_OBJECT(MAKE_CLASS("dgeMatrix")));
128 : bates 10 int *xDims = INTEGER(GET_SLOT(x, Matrix_DimSym)),
129 :     *yDims = INTEGER(getAttrib(y, R_DimSymbol)),
130 : bates 332 *vDims;
131 : bates 10 int m = xDims[1], n = yDims[1];
132 :     double one = 1.0, zero = 0.0;
133 :    
134 :     if (!(isMatrix(y) && isReal(y)))
135 : bates 582 error(_("Argument y must be a numeric (real) matrix"));
136 : bates 332 SET_SLOT(val, Matrix_rcondSym, allocVector(REALSXP, 0));
137 : bates 476 SET_SLOT(val, Matrix_factorSym, allocVector(VECSXP, 0));
138 : bates 332 SET_SLOT(val, Matrix_DimSym, allocVector(INTSXP, 2));
139 :     vDims = INTEGER(GET_SLOT(val, Matrix_DimSym));
140 : bates 10 if ((*xDims) > 0 && (*yDims) > 0 && n > 0 && m > 0) {
141 :     if (*xDims != *yDims)
142 : bates 582 error(_("Dimensions of x and y are not compatible for crossprod"));
143 : bates 10 vDims[0] = m; vDims[1] = n;
144 :     SET_SLOT(val, Matrix_xSym, allocVector(REALSXP, m * n));
145 :     F77_CALL(dgemm)("T", "N", xDims + 1, yDims + 1, xDims, &one,
146 :     REAL(GET_SLOT(x, Matrix_xSym)), xDims,
147 :     REAL(y), yDims,
148 :     &zero, REAL(GET_SLOT(val, Matrix_xSym)),
149 :     xDims + 1);
150 :     }
151 :     UNPROTECT(1);
152 :     return val;
153 :     }
154 :    
155 : bates 478 SEXP dgeMatrix_getDiag(SEXP x)
156 : bates 10 {
157 :     int *dims = INTEGER(GET_SLOT(x, Matrix_DimSym));
158 :     int i, m = dims[0], nret = (m < dims[1]) ? m : dims[1];
159 :     SEXP ret = PROTECT(allocVector(REALSXP, nret)),
160 :     xv = GET_SLOT(x, Matrix_xSym);
161 :    
162 :     for (i = 0; i < nret; i++) {
163 :     REAL(ret)[i] = REAL(xv)[i * (m + 1)];
164 :     }
165 :     UNPROTECT(1);
166 :     return ret;
167 :     }
168 :    
169 : bates 478 SEXP dgeMatrix_LU(SEXP x)
170 : bates 10 {
171 : bates 476 SEXP val = get_factors(x, "LU");
172 : bates 10 int *dims, npiv, info;
173 : maechler 534
174 : bates 10 if (val != R_NilValue) return val;
175 :     dims = INTEGER(GET_SLOT(x, Matrix_DimSym));
176 :     if (dims[0] < 1 || dims[1] < 1)
177 : bates 582 error(_("Cannot factor a matrix with zero extents"));
178 : bates 10 npiv = (dims[0] <dims[1]) ? dims[0] : dims[1];
179 :     val = PROTECT(NEW_OBJECT(MAKE_CLASS("LU")));
180 :     SET_SLOT(val, Matrix_xSym, duplicate(GET_SLOT(x, Matrix_xSym)));
181 :     SET_SLOT(val, Matrix_DimSym, duplicate(GET_SLOT(x, Matrix_DimSym)));
182 :     F77_CALL(dgetrf)(dims, dims + 1, REAL(GET_SLOT(val, Matrix_xSym)),
183 : bates 652 dims,
184 :     INTEGER(ALLOC_SLOT(val, Matrix_permSym, INTSXP, npiv)),
185 : bates 10 &info);
186 : bates 694 if (info < 0)
187 : bates 652 error(_("Lapack routine %s returned error code %d"), "dgetrf", info);
188 : bates 694 else if (info > 0)
189 :     warning(_("Exact singularity detected during LU decomposition."));
190 : bates 10 UNPROTECT(1);
191 : bates 476 return set_factors(x, val, "LU");
192 : bates 10 }
193 :    
194 : bates 478 SEXP dgeMatrix_determinant(SEXP x, SEXP logarithm)
195 : bates 10 {
196 :     int lg = asLogical(logarithm);
197 : bates 478 SEXP lu = dgeMatrix_LU(x);
198 : bates 10 int *dims = INTEGER(GET_SLOT(lu, Matrix_DimSym)),
199 : bates 652 *jpvt = INTEGER(GET_SLOT(lu, Matrix_permSym)),
200 : bates 10 i, n = dims[0], sign = 1;
201 :     double *luvals = REAL(GET_SLOT(lu, Matrix_xSym)), modulus;
202 :    
203 :     if (n != dims[1])
204 : bates 582 error(_("Determinant requires a square matrix"));
205 : bates 10 for (i = 0; i < n; i++) if (jpvt[i] != (i + 1)) sign = -sign;
206 :     if (lg) {
207 :     modulus = 0.0;
208 :     for (i = 0; i < n; i++) {
209 :     double dii = luvals[i*(n + 1)]; /* ith diagonal element */
210 :     modulus += log(dii < 0 ? -dii : dii);
211 :     if (dii < 0) sign = -sign;
212 :     }
213 :     } else {
214 :     modulus = 1.0;
215 :     for (i = 0; i < n; i++)
216 :     modulus *= luvals[i*(n + 1)];
217 :     if (modulus < 0) {
218 :     modulus = -modulus;
219 :     sign = -sign;
220 :     }
221 :     }
222 :     return as_det_obj(modulus, lg, sign);
223 :     }
224 :    
225 : bates 478 SEXP dgeMatrix_solve(SEXP a)
226 : bates 10 {
227 : bates 478 SEXP val = PROTECT(NEW_OBJECT(MAKE_CLASS("dgeMatrix"))),
228 :     lu = dgeMatrix_LU(a);
229 : bates 10 int *dims = INTEGER(GET_SLOT(lu, Matrix_DimSym)),
230 : bates 652 *pivot = INTEGER(GET_SLOT(lu, Matrix_permSym));
231 : bates 10 double *x, tmp;
232 :     int info, lwork = -1;
233 :    
234 :    
235 : bates 582 if (dims[0] != dims[1]) error(_("Solve requires a square matrix"));
236 : bates 10 SET_SLOT(val, Matrix_xSym, duplicate(GET_SLOT(lu, Matrix_xSym)));
237 :     x = REAL(GET_SLOT(val, Matrix_xSym));
238 :     SET_SLOT(val, Matrix_DimSym, duplicate(GET_SLOT(lu, Matrix_DimSym)));
239 :     F77_CALL(dgetri)(dims, x, dims, pivot, &tmp, &lwork, &info);
240 :     lwork = (int) tmp;
241 :     F77_CALL(dgetri)(dims, x, dims, pivot,
242 :     (double *) R_alloc((size_t) lwork, sizeof(double)),
243 :     &lwork, &info);
244 :     UNPROTECT(1);
245 :     return val;
246 :     }
247 :    
248 : bates 652 SEXP dgeMatrix_matrix_solve(SEXP a, SEXP b, SEXP classed)
249 : bates 10 {
250 : bates 652 int cl = asLogical(classed);
251 :     SEXP val = PROTECT(NEW_OBJECT(MAKE_CLASS("dgeMatrix"))),
252 :     lu = dgeMatrix_LU(a);
253 :     int *adims = INTEGER(GET_SLOT(lu, Matrix_DimSym)),
254 :     *bdims = INTEGER(cl ? GET_SLOT(b, Matrix_DimSym) :
255 :     getAttrib(b, R_DimSymbol));
256 :     int info, n = bdims[0], nrhs = bdims[1];
257 :     int sz = n * nrhs;
258 :    
259 :     if (*adims != *bdims || bdims[1] < 1 || *adims < 1 || *adims != adims[1])
260 :     error(_("Dimensions of system to be solved are inconsistent"));
261 :     Memcpy(INTEGER(ALLOC_SLOT(val, Matrix_DimSym, INTSXP, 2)), bdims, 2);
262 : bates 692 F77_CALL(dgetrs)("N", &n, &nrhs, REAL(GET_SLOT(lu, Matrix_xSym)), &n,
263 : maechler 655 INTEGER(GET_SLOT(lu, Matrix_permSym)),
264 : bates 652 Memcpy(REAL(ALLOC_SLOT(val, Matrix_xSym, REALSXP, sz)),
265 :     REAL(cl ? GET_SLOT(b, Matrix_xSym):b), sz),
266 :     &n, &info);
267 :     UNPROTECT(1);
268 :     return val;
269 :     }
270 :    
271 :     SEXP dgeMatrix_matrix_mm(SEXP a, SEXP b, SEXP classed, SEXP right)
272 :     {
273 : maechler 655 int cl = asLogical(classed);
274 : bates 652 SEXP val = PROTECT(NEW_OBJECT(MAKE_CLASS("dgeMatrix")));
275 : bates 10 int *adims = INTEGER(GET_SLOT(a, Matrix_DimSym)),
276 : bates 652 *bdims = INTEGER(cl ? GET_SLOT(b, Matrix_DimSym) :
277 :     getAttrib(b, R_DimSymbol)),
278 :     *cdims = INTEGER(ALLOC_SLOT(val, Matrix_DimSym, INTSXP, 2));
279 : bates 10 double one = 1., zero = 0.;
280 : maechler 534
281 : bates 652 if (asLogical(right)) {
282 :     int m = bdims[0], n = adims[1], k = bdims[1];
283 :     if (adims[0] != k)
284 :     error(_("Matrices are not conformable for multiplication"));
285 :     if (m < 1 || n < 1 || k < 1)
286 :     error(_("Matrices with zero extents cannot be multiplied"));
287 :     cdims[0] = m; cdims[1] = n;
288 :     F77_CALL(dgemm) ("N", "N", &m, &n, &k, &one,
289 :     REAL(cl ? GET_SLOT(b, Matrix_xSym) : b), &m,
290 :     REAL(GET_SLOT(a, Matrix_xSym)), &k, &zero,
291 :     REAL(ALLOC_SLOT(val, Matrix_xSym, REALSXP, m * n)),
292 :     &m);
293 :     } else {
294 :     int m = adims[0], n = bdims[1], k = adims[1];
295 :    
296 :     if (bdims[0] != k)
297 :     error(_("Matrices are not conformable for multiplication"));
298 :     if (m < 1 || n < 1 || k < 1)
299 :     error(_("Matrices with zero extents cannot be multiplied"));
300 :     cdims[0] = m; cdims[1] = n;
301 :     F77_CALL(dgemm)
302 :     ("N", "N", &m, &n, &k, &one, REAL(GET_SLOT(a, Matrix_xSym)),
303 :     &m, REAL(cl ? GET_SLOT(b, Matrix_xSym) : b), &k, &zero,
304 :     REAL(ALLOC_SLOT(val, Matrix_xSym, REALSXP, m * n)), &m);
305 :     }
306 : bates 10 UNPROTECT(1);
307 :     return val;
308 :     }
309 : bates 301
310 : bates 652
311 : bates 478 SEXP dgeMatrix_svd(SEXP x, SEXP nnu, SEXP nnv)
312 : bates 301 {
313 : bates 377 int /* nu = asInteger(nnu),
314 :     nv = asInteger(nnv), */
315 : bates 301 *dims = INTEGER(GET_SLOT(x, Matrix_DimSym));
316 :     double *xx = REAL(GET_SLOT(x, Matrix_xSym));
317 :     SEXP val = PROTECT(allocVector(VECSXP, 3));
318 :    
319 :     if (dims[0] && dims[1]) {
320 :     int m = dims[0], n = dims[1], mm = (m < n)?m:n,
321 :     lwork = -1, info;
322 :     int *iwork = Calloc(8 * mm, int);
323 :     double tmp, *work;
324 : bates 306 /* int bdspac = 3*m*m + 4*m, */
325 :     /* wrkbl, maxwrk, minwrk, itmp, */
326 :     /* ione = 1, iminus1 = -1; */
327 :     /* int i1, i2, i3; */
328 : bates 301
329 :     SET_VECTOR_ELT(val, 0, allocVector(REALSXP, mm));
330 :     SET_VECTOR_ELT(val, 1, allocMatrix(REALSXP, m, mm));
331 :     SET_VECTOR_ELT(val, 2, allocMatrix(REALSXP, mm, n));
332 :     F77_CALL(dgesdd)("S", &m, &n, xx, &m,
333 :     REAL(VECTOR_ELT(val, 0)),
334 :     REAL(VECTOR_ELT(val, 1)), &m,
335 :     REAL(VECTOR_ELT(val, 2)), &mm,
336 :     &tmp, &lwork, iwork, &info);
337 :     lwork = (int) tmp;
338 : bates 306 /* F77_CALL(foo)(&i1, &i2, &i3); */
339 :     /* wrkbl = 3*m+(m+n)*i1; */
340 :     /* if (wrkbl < (itmp = 3*m + m*i2)) wrkbl = itmp; */
341 :     /* if (wrkbl < (itmp = 3*m + m*i3)) wrkbl = itmp; */
342 :     /* itmp = bdspac+3*m; */
343 :     /* maxwrk = (wrkbl > itmp) ? wrkbl : itmp; */
344 :     /* minwrk = 3*m + ((bdspac > n) ? bdspac : n); */
345 : bates 301 work = Calloc(lwork, double);
346 :     F77_CALL(dgesdd)("S", &m, &n, xx, &m,
347 :     REAL(VECTOR_ELT(val, 0)),
348 :     REAL(VECTOR_ELT(val, 1)), &m,
349 :     REAL(VECTOR_ELT(val, 2)), &mm,
350 :     work, &lwork, iwork, &info);
351 :     Free(iwork); Free(work);
352 :     }
353 :     UNPROTECT(1);
354 :     return val;
355 :     }
356 : bates 461
357 :     static double padec [] = /* Constants for matrix exponential calculation. */
358 :     {
359 :     5.0000000000000000e-1,
360 :     1.1666666666666667e-1,
361 :     1.6666666666666667e-2,
362 :     1.6025641025641026e-3,
363 :     1.0683760683760684e-4,
364 :     4.8562548562548563e-6,
365 :     1.3875013875013875e-7,
366 :     1.9270852604185938e-9,
367 :     };
368 :    
369 : maechler 534 /**
370 : bates 461 * Matrix exponential - based on the code for Octave's expm function.
371 : maechler 534 *
372 : bates 461 * @param x real square matrix to exponentiate
373 : maechler 534 *
374 : bates 461 * @return matrix exponential of x
375 :     */
376 : bates 478 SEXP dgeMatrix_exp(SEXP x)
377 : bates 461 {
378 :     SEXP val = PROTECT(duplicate(x));
379 :     int *Dims = INTEGER(GET_SLOT(x, Matrix_DimSym));
380 :     int i, ilo, ilos, ihi, ihis, j, nc = Dims[1], sqpow;
381 :     int ncp1 = Dims[1] + 1, ncsqr = nc * nc;
382 :     int *pivot = Calloc(nc, int);
383 :     int *iperm = Calloc(nc, int);
384 :     double *dpp = Calloc(ncsqr, double), /* denominator power Pade' */
385 :     *npp = Calloc(ncsqr, double), /* numerator power Pade' */
386 :     *perm = Calloc(nc, double),
387 :     *scale = Calloc(nc, double),
388 :     *v = REAL(GET_SLOT(val, Matrix_xSym)),
389 :     *work = Calloc(ncsqr, double), inf_norm, m1_j, /* (-1)^j */
390 :     one = 1., trshift, zero = 0.;
391 : maechler 534
392 : bates 461 if (nc < 1 || Dims[0] != nc)
393 : bates 582 error(_("Matrix exponential requires square, non-null matrix"));
394 : bates 461
395 :     /* FIXME: Add special treatment for nc == 1 */
396 : maechler 534
397 : bates 461 /* Preconditioning 1. Shift diagonal by average diagonal if positive. */
398 :     trshift = 0; /* determine average diagonal element */
399 :     for (i = 0; i < nc; i++) trshift += v[i * ncp1];
400 :     trshift /= nc;
401 :     if (trshift > 0.) { /* shift diagonal by -trshift */
402 :     for (i = 0; i < nc; i++) v[i * ncp1] -= trshift;
403 :     }
404 :    
405 :     /* Preconditioning 2. Balancing with dgebal. */
406 :     F77_CALL(dgebal)("P", &nc, v, &nc, &ilo, &ihi, perm, &j);
407 : bates 582 if (j) error(_("dgeMatrix_exp: LAPACK routine dgebal returned %d"), j);
408 : bates 461 F77_CALL(dgebal)("S", &nc, v, &nc, &ilos, &ihis, scale, &j);
409 : bates 582 if (j) error(_("dgeMatrix_exp: LAPACK routine dgebal returned %d"), j);
410 : bates 461
411 :     /* Preconditioning 3. Scaling according to infinity norm */
412 :     inf_norm = F77_CALL(dlange)("I", &nc, &nc, v, &nc, work);
413 :     sqpow = (inf_norm > 0) ? (int) (1 + log(inf_norm)/log(2.)) : 0;
414 :     if (sqpow < 0) sqpow = 0;
415 :     if (sqpow > 0) {
416 :     double scale_factor = 1.0;
417 :     for (i = 0; i < sqpow; i++) scale_factor *= 2.;
418 :     for (i = 0; i < ncsqr; i++) v[i] /= scale_factor;
419 :     }
420 :    
421 :     /* Pade' approximation. Powers v^8, v^7, ..., v^1 */
422 :     AZERO(npp, ncsqr);
423 :     AZERO(dpp, ncsqr);
424 :     m1_j = -1;
425 :     for (j = 7; j >=0; j--) {
426 :     double mult = padec[j];
427 :     /* npp = m * npp + padec[j] *m */
428 :     F77_CALL(dgemm)("N", "N", &nc, &nc, &nc, &one, v, &nc, npp, &nc,
429 :     &zero, work, &nc);
430 :     for (i = 0; i < ncsqr; i++) npp[i] = work[i] + mult * v[i];
431 :     /* dpp = m * dpp * (m1_j * padec[j]) * m */
432 :     mult *= m1_j;
433 :     F77_CALL(dgemm)("N", "N", &nc, &nc, &nc, &one, v, &nc, dpp, &nc,
434 :     &zero, work, &nc);
435 :     for (i = 0; i < ncsqr; i++) dpp[i] = work[i] + mult * v[i];
436 :     m1_j *= -1;
437 :     }
438 :     /* Zero power */
439 :     for (i = 0; i < ncsqr; i++) dpp[i] *= -1.;
440 :     for (j = 0; j < nc; j++) {
441 :     npp[j * ncp1] += 1.;
442 :     dpp[j * ncp1] += 1.;
443 :     }
444 : maechler 534
445 : bates 461 /* Pade' approximation is solve(dpp, npp) */
446 :     F77_CALL(dgetrf)(&nc, &nc, dpp, &nc, pivot, &j);
447 : bates 582 if (j) error(_("dgeMatrix_exp: dgetrf returned error code %d"), j);
448 : bates 461 F77_CALL(dgetrs)("N", &nc, &nc, dpp, &nc, pivot, npp, &nc, &j);
449 : bates 582 if (j) error(_("dgeMatrix_exp: dgetrs returned error code %d"), j);
450 : bates 461 Memcpy(v, npp, ncsqr);
451 :    
452 :     /* Now undo all of the preconditioning */
453 :     /* Preconditioning 3: square the result for every power of 2 */
454 :     while (sqpow--) {
455 :     F77_CALL(dgemm)("N", "N", &nc, &nc, &nc, &one, v, &nc, v, &nc,
456 :     &zero, work, &nc);
457 :     Memcpy(v, work, ncsqr);
458 :     }
459 :     /* Preconditioning 2: apply inverse scaling */
460 :     for (j = 0; j < nc; j++)
461 :     for (i = 0; i < nc; i++)
462 :     v[i + j * nc] *= scale[i]/scale[j];
463 :     /* Construct balancing permutation vector */
464 :     for (i = 0; i < nc; i++) iperm[i] = i; /* identity permutation */
465 :     /* Leading permutations applied in forward order */
466 :     for (i = 0; i < (ilo - 1); i++) {
467 :     int swapidx = (int) (perm[i]) - 1;
468 :     int tmp = iperm[i];
469 :     iperm[i] = iperm[swapidx];
470 :     iperm[swapidx] = tmp;
471 :     }
472 :     /* Trailing permutations applied in reverse order */
473 :     for (i = nc - 1; i >= ihi; i--) {
474 :     int swapidx = (int) (perm[i]) - 1;
475 :     int tmp = iperm[i];
476 :     iperm[i] = iperm[swapidx];
477 :     iperm[swapidx] = tmp;
478 :     }
479 :     /* Construct inverse balancing permutation vector */
480 :     Memcpy(pivot, iperm, nc);
481 :     for (i = 0; i < nc; i++) iperm[pivot[i]] = i;
482 :     /* Apply inverse permutation */
483 :     Memcpy(work, v, ncsqr);
484 :     for (j = 0; j < nc; j++)
485 :     for (i = 0; i < nc; i++)
486 :     v[i + j * nc] = work[iperm[i] + iperm[j] * nc];
487 : maechler 534
488 : bates 461 /* Preconditioning 1: Trace normalization */
489 :     if (trshift > 0.) {
490 :     double mult = exp(trshift);
491 :     for (i = 0; i < ncsqr; i++) v[i] *= mult;
492 :     }
493 : maechler 534
494 : bates 461 /* Clean up */
495 :     Free(dpp); Free(npp); Free(perm); Free(iperm); Free(pivot); Free(scale); Free(work);
496 :     UNPROTECT(1);
497 :     return val;
498 :     }
499 : bates 495
500 :     SEXP dgeMatrix_Schur(SEXP x, SEXP vectors)
501 :     {
502 :     int *dims = INTEGER(GET_SLOT(x, Matrix_DimSym));
503 :     int vecs = asLogical(vectors), info, izero = 0, lwork = -1, n = dims[0];
504 :     double *work, tmp;
505 :     char *nms[] = {"WR", "WI", "T", "Z", ""};
506 :     SEXP val = PROTECT(Matrix_make_named(VECSXP, nms));
507 : maechler 534
508 : bates 495 if (n != dims[1] || n < 1)
509 : bates 582 error(_("dgeMatrix_Schur: argument x must be a non-null square matrix"));
510 : bates 495 SET_VECTOR_ELT(val, 0, allocVector(REALSXP, n));
511 :     SET_VECTOR_ELT(val, 1, allocVector(REALSXP, n));
512 :     SET_VECTOR_ELT(val, 2, allocMatrix(REALSXP, n, n));
513 :     Memcpy(REAL(VECTOR_ELT(val, 2)), REAL(GET_SLOT(x, Matrix_xSym)), n * n);
514 :     SET_VECTOR_ELT(val, 3, allocMatrix(REALSXP, vecs ? n : 0, vecs ? n : 0));
515 :     F77_CALL(dgees)(vecs ? "V" : "N", "N", NULL, dims, (double *) NULL, dims, &izero,
516 :     (double *) NULL, (double *) NULL, (double *) NULL, dims,
517 :     &tmp, &lwork, (int *) NULL, &info);
518 : bates 582 if (info) error(_("dgeMatrix_Schur: first call to dgees failed"));
519 : bates 495 lwork = (int) tmp;
520 :     work = Calloc(lwork, double);
521 :     F77_CALL(dgees)(vecs ? "V" : "N", "N", NULL, dims, REAL(VECTOR_ELT(val, 2)), dims,
522 :     &izero, REAL(VECTOR_ELT(val, 0)), REAL(VECTOR_ELT(val, 1)),
523 : maechler 534 REAL(VECTOR_ELT(val, 3)), dims, work, &lwork,
524 : bates 495 (int *) NULL, &info);
525 : bates 582 if (info) error(_("dgeMatrix_Schur: dgees returned code %d"), info);
526 : bates 495 Free(work);
527 :     UNPROTECT(1);
528 :     return val;
529 :     }

root@r-forge.r-project.org
ViewVC Help
Powered by ViewVC 1.0.0  
Thanks to:
Vienna University of Economics and Business Powered By FusionForge