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 692 - (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 652 if (info)
187 :     error(_("Lapack routine %s returned error code %d"), "dgetrf", info);
188 : bates 10 UNPROTECT(1);
189 : bates 476 return set_factors(x, val, "LU");
190 : bates 10 }
191 :    
192 : bates 478 SEXP dgeMatrix_determinant(SEXP x, SEXP logarithm)
193 : bates 10 {
194 :     int lg = asLogical(logarithm);
195 : bates 478 SEXP lu = dgeMatrix_LU(x);
196 : bates 10 int *dims = INTEGER(GET_SLOT(lu, Matrix_DimSym)),
197 : bates 652 *jpvt = INTEGER(GET_SLOT(lu, Matrix_permSym)),
198 : bates 10 i, n = dims[0], sign = 1;
199 :     double *luvals = REAL(GET_SLOT(lu, Matrix_xSym)), modulus;
200 :    
201 :     if (n != dims[1])
202 : bates 582 error(_("Determinant requires a square matrix"));
203 : bates 10 for (i = 0; i < n; i++) if (jpvt[i] != (i + 1)) sign = -sign;
204 :     if (lg) {
205 :     modulus = 0.0;
206 :     for (i = 0; i < n; i++) {
207 :     double dii = luvals[i*(n + 1)]; /* ith diagonal element */
208 :     modulus += log(dii < 0 ? -dii : dii);
209 :     if (dii < 0) sign = -sign;
210 :     }
211 :     } else {
212 :     modulus = 1.0;
213 :     for (i = 0; i < n; i++)
214 :     modulus *= luvals[i*(n + 1)];
215 :     if (modulus < 0) {
216 :     modulus = -modulus;
217 :     sign = -sign;
218 :     }
219 :     }
220 :     return as_det_obj(modulus, lg, sign);
221 :     }
222 :    
223 : bates 478 SEXP dgeMatrix_solve(SEXP a)
224 : bates 10 {
225 : bates 478 SEXP val = PROTECT(NEW_OBJECT(MAKE_CLASS("dgeMatrix"))),
226 :     lu = dgeMatrix_LU(a);
227 : bates 10 int *dims = INTEGER(GET_SLOT(lu, Matrix_DimSym)),
228 : bates 652 *pivot = INTEGER(GET_SLOT(lu, Matrix_permSym));
229 : bates 10 double *x, tmp;
230 :     int info, lwork = -1;
231 :    
232 :    
233 : bates 582 if (dims[0] != dims[1]) error(_("Solve requires a square matrix"));
234 : bates 10 SET_SLOT(val, Matrix_xSym, duplicate(GET_SLOT(lu, Matrix_xSym)));
235 :     x = REAL(GET_SLOT(val, Matrix_xSym));
236 :     SET_SLOT(val, Matrix_DimSym, duplicate(GET_SLOT(lu, Matrix_DimSym)));
237 :     F77_CALL(dgetri)(dims, x, dims, pivot, &tmp, &lwork, &info);
238 :     lwork = (int) tmp;
239 :     F77_CALL(dgetri)(dims, x, dims, pivot,
240 :     (double *) R_alloc((size_t) lwork, sizeof(double)),
241 :     &lwork, &info);
242 :     UNPROTECT(1);
243 :     return val;
244 :     }
245 :    
246 : bates 652 SEXP dgeMatrix_matrix_solve(SEXP a, SEXP b, SEXP classed)
247 : bates 10 {
248 : bates 652 int cl = asLogical(classed);
249 :     SEXP val = PROTECT(NEW_OBJECT(MAKE_CLASS("dgeMatrix"))),
250 :     lu = dgeMatrix_LU(a);
251 :     int *adims = INTEGER(GET_SLOT(lu, Matrix_DimSym)),
252 :     *bdims = INTEGER(cl ? GET_SLOT(b, Matrix_DimSym) :
253 :     getAttrib(b, R_DimSymbol));
254 :     int info, n = bdims[0], nrhs = bdims[1];
255 :     int sz = n * nrhs;
256 :    
257 :     if (*adims != *bdims || bdims[1] < 1 || *adims < 1 || *adims != adims[1])
258 :     error(_("Dimensions of system to be solved are inconsistent"));
259 :     Memcpy(INTEGER(ALLOC_SLOT(val, Matrix_DimSym, INTSXP, 2)), bdims, 2);
260 : bates 692 F77_CALL(dgetrs)("N", &n, &nrhs, REAL(GET_SLOT(lu, Matrix_xSym)), &n,
261 : maechler 655 INTEGER(GET_SLOT(lu, Matrix_permSym)),
262 : bates 652 Memcpy(REAL(ALLOC_SLOT(val, Matrix_xSym, REALSXP, sz)),
263 :     REAL(cl ? GET_SLOT(b, Matrix_xSym):b), sz),
264 :     &n, &info);
265 :     UNPROTECT(1);
266 :     return val;
267 :     }
268 :    
269 :     SEXP dgeMatrix_matrix_mm(SEXP a, SEXP b, SEXP classed, SEXP right)
270 :     {
271 : maechler 655 int cl = asLogical(classed);
272 : bates 652 SEXP val = PROTECT(NEW_OBJECT(MAKE_CLASS("dgeMatrix")));
273 : bates 10 int *adims = INTEGER(GET_SLOT(a, Matrix_DimSym)),
274 : bates 652 *bdims = INTEGER(cl ? GET_SLOT(b, Matrix_DimSym) :
275 :     getAttrib(b, R_DimSymbol)),
276 :     *cdims = INTEGER(ALLOC_SLOT(val, Matrix_DimSym, INTSXP, 2));
277 : bates 10 double one = 1., zero = 0.;
278 : maechler 534
279 : bates 652 if (asLogical(right)) {
280 :     int m = bdims[0], n = adims[1], k = bdims[1];
281 :     if (adims[0] != k)
282 :     error(_("Matrices are not conformable for multiplication"));
283 :     if (m < 1 || n < 1 || k < 1)
284 :     error(_("Matrices with zero extents cannot be multiplied"));
285 :     cdims[0] = m; cdims[1] = n;
286 :     F77_CALL(dgemm) ("N", "N", &m, &n, &k, &one,
287 :     REAL(cl ? GET_SLOT(b, Matrix_xSym) : b), &m,
288 :     REAL(GET_SLOT(a, Matrix_xSym)), &k, &zero,
289 :     REAL(ALLOC_SLOT(val, Matrix_xSym, REALSXP, m * n)),
290 :     &m);
291 :     } else {
292 :     int m = adims[0], n = bdims[1], k = adims[1];
293 :    
294 :     if (bdims[0] != k)
295 :     error(_("Matrices are not conformable for multiplication"));
296 :     if (m < 1 || n < 1 || k < 1)
297 :     error(_("Matrices with zero extents cannot be multiplied"));
298 :     cdims[0] = m; cdims[1] = n;
299 :     F77_CALL(dgemm)
300 :     ("N", "N", &m, &n, &k, &one, REAL(GET_SLOT(a, Matrix_xSym)),
301 :     &m, REAL(cl ? GET_SLOT(b, Matrix_xSym) : b), &k, &zero,
302 :     REAL(ALLOC_SLOT(val, Matrix_xSym, REALSXP, m * n)), &m);
303 :     }
304 : bates 10 UNPROTECT(1);
305 :     return val;
306 :     }
307 : bates 301
308 : bates 652
309 : bates 478 SEXP dgeMatrix_svd(SEXP x, SEXP nnu, SEXP nnv)
310 : bates 301 {
311 : bates 377 int /* nu = asInteger(nnu),
312 :     nv = asInteger(nnv), */
313 : bates 301 *dims = INTEGER(GET_SLOT(x, Matrix_DimSym));
314 :     double *xx = REAL(GET_SLOT(x, Matrix_xSym));
315 :     SEXP val = PROTECT(allocVector(VECSXP, 3));
316 :    
317 :     if (dims[0] && dims[1]) {
318 :     int m = dims[0], n = dims[1], mm = (m < n)?m:n,
319 :     lwork = -1, info;
320 :     int *iwork = Calloc(8 * mm, int);
321 :     double tmp, *work;
322 : bates 306 /* int bdspac = 3*m*m + 4*m, */
323 :     /* wrkbl, maxwrk, minwrk, itmp, */
324 :     /* ione = 1, iminus1 = -1; */
325 :     /* int i1, i2, i3; */
326 : bates 301
327 :     SET_VECTOR_ELT(val, 0, allocVector(REALSXP, mm));
328 :     SET_VECTOR_ELT(val, 1, allocMatrix(REALSXP, m, mm));
329 :     SET_VECTOR_ELT(val, 2, allocMatrix(REALSXP, mm, n));
330 :     F77_CALL(dgesdd)("S", &m, &n, xx, &m,
331 :     REAL(VECTOR_ELT(val, 0)),
332 :     REAL(VECTOR_ELT(val, 1)), &m,
333 :     REAL(VECTOR_ELT(val, 2)), &mm,
334 :     &tmp, &lwork, iwork, &info);
335 :     lwork = (int) tmp;
336 : bates 306 /* F77_CALL(foo)(&i1, &i2, &i3); */
337 :     /* wrkbl = 3*m+(m+n)*i1; */
338 :     /* if (wrkbl < (itmp = 3*m + m*i2)) wrkbl = itmp; */
339 :     /* if (wrkbl < (itmp = 3*m + m*i3)) wrkbl = itmp; */
340 :     /* itmp = bdspac+3*m; */
341 :     /* maxwrk = (wrkbl > itmp) ? wrkbl : itmp; */
342 :     /* minwrk = 3*m + ((bdspac > n) ? bdspac : n); */
343 : bates 301 work = Calloc(lwork, double);
344 :     F77_CALL(dgesdd)("S", &m, &n, xx, &m,
345 :     REAL(VECTOR_ELT(val, 0)),
346 :     REAL(VECTOR_ELT(val, 1)), &m,
347 :     REAL(VECTOR_ELT(val, 2)), &mm,
348 :     work, &lwork, iwork, &info);
349 :     Free(iwork); Free(work);
350 :     }
351 :     UNPROTECT(1);
352 :     return val;
353 :     }
354 : bates 461
355 :     static double padec [] = /* Constants for matrix exponential calculation. */
356 :     {
357 :     5.0000000000000000e-1,
358 :     1.1666666666666667e-1,
359 :     1.6666666666666667e-2,
360 :     1.6025641025641026e-3,
361 :     1.0683760683760684e-4,
362 :     4.8562548562548563e-6,
363 :     1.3875013875013875e-7,
364 :     1.9270852604185938e-9,
365 :     };
366 :    
367 : maechler 534 /**
368 : bates 461 * Matrix exponential - based on the code for Octave's expm function.
369 : maechler 534 *
370 : bates 461 * @param x real square matrix to exponentiate
371 : maechler 534 *
372 : bates 461 * @return matrix exponential of x
373 :     */
374 : bates 478 SEXP dgeMatrix_exp(SEXP x)
375 : bates 461 {
376 :     SEXP val = PROTECT(duplicate(x));
377 :     int *Dims = INTEGER(GET_SLOT(x, Matrix_DimSym));
378 :     int i, ilo, ilos, ihi, ihis, j, nc = Dims[1], sqpow;
379 :     int ncp1 = Dims[1] + 1, ncsqr = nc * nc;
380 :     int *pivot = Calloc(nc, int);
381 :     int *iperm = Calloc(nc, int);
382 :     double *dpp = Calloc(ncsqr, double), /* denominator power Pade' */
383 :     *npp = Calloc(ncsqr, double), /* numerator power Pade' */
384 :     *perm = Calloc(nc, double),
385 :     *scale = Calloc(nc, double),
386 :     *v = REAL(GET_SLOT(val, Matrix_xSym)),
387 :     *work = Calloc(ncsqr, double), inf_norm, m1_j, /* (-1)^j */
388 :     one = 1., trshift, zero = 0.;
389 : maechler 534
390 : bates 461 if (nc < 1 || Dims[0] != nc)
391 : bates 582 error(_("Matrix exponential requires square, non-null matrix"));
392 : bates 461
393 :     /* FIXME: Add special treatment for nc == 1 */
394 : maechler 534
395 : bates 461 /* Preconditioning 1. Shift diagonal by average diagonal if positive. */
396 :     trshift = 0; /* determine average diagonal element */
397 :     for (i = 0; i < nc; i++) trshift += v[i * ncp1];
398 :     trshift /= nc;
399 :     if (trshift > 0.) { /* shift diagonal by -trshift */
400 :     for (i = 0; i < nc; i++) v[i * ncp1] -= trshift;
401 :     }
402 :    
403 :     /* Preconditioning 2. Balancing with dgebal. */
404 :     F77_CALL(dgebal)("P", &nc, v, &nc, &ilo, &ihi, perm, &j);
405 : bates 582 if (j) error(_("dgeMatrix_exp: LAPACK routine dgebal returned %d"), j);
406 : bates 461 F77_CALL(dgebal)("S", &nc, v, &nc, &ilos, &ihis, scale, &j);
407 : bates 582 if (j) error(_("dgeMatrix_exp: LAPACK routine dgebal returned %d"), j);
408 : bates 461
409 :     /* Preconditioning 3. Scaling according to infinity norm */
410 :     inf_norm = F77_CALL(dlange)("I", &nc, &nc, v, &nc, work);
411 :     sqpow = (inf_norm > 0) ? (int) (1 + log(inf_norm)/log(2.)) : 0;
412 :     if (sqpow < 0) sqpow = 0;
413 :     if (sqpow > 0) {
414 :     double scale_factor = 1.0;
415 :     for (i = 0; i < sqpow; i++) scale_factor *= 2.;
416 :     for (i = 0; i < ncsqr; i++) v[i] /= scale_factor;
417 :     }
418 :    
419 :     /* Pade' approximation. Powers v^8, v^7, ..., v^1 */
420 :     AZERO(npp, ncsqr);
421 :     AZERO(dpp, ncsqr);
422 :     m1_j = -1;
423 :     for (j = 7; j >=0; j--) {
424 :     double mult = padec[j];
425 :     /* npp = m * npp + padec[j] *m */
426 :     F77_CALL(dgemm)("N", "N", &nc, &nc, &nc, &one, v, &nc, npp, &nc,
427 :     &zero, work, &nc);
428 :     for (i = 0; i < ncsqr; i++) npp[i] = work[i] + mult * v[i];
429 :     /* dpp = m * dpp * (m1_j * padec[j]) * m */
430 :     mult *= m1_j;
431 :     F77_CALL(dgemm)("N", "N", &nc, &nc, &nc, &one, v, &nc, dpp, &nc,
432 :     &zero, work, &nc);
433 :     for (i = 0; i < ncsqr; i++) dpp[i] = work[i] + mult * v[i];
434 :     m1_j *= -1;
435 :     }
436 :     /* Zero power */
437 :     for (i = 0; i < ncsqr; i++) dpp[i] *= -1.;
438 :     for (j = 0; j < nc; j++) {
439 :     npp[j * ncp1] += 1.;
440 :     dpp[j * ncp1] += 1.;
441 :     }
442 : maechler 534
443 : bates 461 /* Pade' approximation is solve(dpp, npp) */
444 :     F77_CALL(dgetrf)(&nc, &nc, dpp, &nc, pivot, &j);
445 : bates 582 if (j) error(_("dgeMatrix_exp: dgetrf returned error code %d"), j);
446 : bates 461 F77_CALL(dgetrs)("N", &nc, &nc, dpp, &nc, pivot, npp, &nc, &j);
447 : bates 582 if (j) error(_("dgeMatrix_exp: dgetrs returned error code %d"), j);
448 : bates 461 Memcpy(v, npp, ncsqr);
449 :    
450 :     /* Now undo all of the preconditioning */
451 :     /* Preconditioning 3: square the result for every power of 2 */
452 :     while (sqpow--) {
453 :     F77_CALL(dgemm)("N", "N", &nc, &nc, &nc, &one, v, &nc, v, &nc,
454 :     &zero, work, &nc);
455 :     Memcpy(v, work, ncsqr);
456 :     }
457 :     /* Preconditioning 2: apply inverse scaling */
458 :     for (j = 0; j < nc; j++)
459 :     for (i = 0; i < nc; i++)
460 :     v[i + j * nc] *= scale[i]/scale[j];
461 :     /* Construct balancing permutation vector */
462 :     for (i = 0; i < nc; i++) iperm[i] = i; /* identity permutation */
463 :     /* Leading permutations applied in forward order */
464 :     for (i = 0; i < (ilo - 1); i++) {
465 :     int swapidx = (int) (perm[i]) - 1;
466 :     int tmp = iperm[i];
467 :     iperm[i] = iperm[swapidx];
468 :     iperm[swapidx] = tmp;
469 :     }
470 :     /* Trailing permutations applied in reverse order */
471 :     for (i = nc - 1; i >= ihi; i--) {
472 :     int swapidx = (int) (perm[i]) - 1;
473 :     int tmp = iperm[i];
474 :     iperm[i] = iperm[swapidx];
475 :     iperm[swapidx] = tmp;
476 :     }
477 :     /* Construct inverse balancing permutation vector */
478 :     Memcpy(pivot, iperm, nc);
479 :     for (i = 0; i < nc; i++) iperm[pivot[i]] = i;
480 :     /* Apply inverse permutation */
481 :     Memcpy(work, v, ncsqr);
482 :     for (j = 0; j < nc; j++)
483 :     for (i = 0; i < nc; i++)
484 :     v[i + j * nc] = work[iperm[i] + iperm[j] * nc];
485 : maechler 534
486 : bates 461 /* Preconditioning 1: Trace normalization */
487 :     if (trshift > 0.) {
488 :     double mult = exp(trshift);
489 :     for (i = 0; i < ncsqr; i++) v[i] *= mult;
490 :     }
491 : maechler 534
492 : bates 461 /* Clean up */
493 :     Free(dpp); Free(npp); Free(perm); Free(iperm); Free(pivot); Free(scale); Free(work);
494 :     UNPROTECT(1);
495 :     return val;
496 :     }
497 : bates 495
498 :     SEXP dgeMatrix_Schur(SEXP x, SEXP vectors)
499 :     {
500 :     int *dims = INTEGER(GET_SLOT(x, Matrix_DimSym));
501 :     int vecs = asLogical(vectors), info, izero = 0, lwork = -1, n = dims[0];
502 :     double *work, tmp;
503 :     char *nms[] = {"WR", "WI", "T", "Z", ""};
504 :     SEXP val = PROTECT(Matrix_make_named(VECSXP, nms));
505 : maechler 534
506 : bates 495 if (n != dims[1] || n < 1)
507 : bates 582 error(_("dgeMatrix_Schur: argument x must be a non-null square matrix"));
508 : bates 495 SET_VECTOR_ELT(val, 0, allocVector(REALSXP, n));
509 :     SET_VECTOR_ELT(val, 1, allocVector(REALSXP, n));
510 :     SET_VECTOR_ELT(val, 2, allocMatrix(REALSXP, n, n));
511 :     Memcpy(REAL(VECTOR_ELT(val, 2)), REAL(GET_SLOT(x, Matrix_xSym)), n * n);
512 :     SET_VECTOR_ELT(val, 3, allocMatrix(REALSXP, vecs ? n : 0, vecs ? n : 0));
513 :     F77_CALL(dgees)(vecs ? "V" : "N", "N", NULL, dims, (double *) NULL, dims, &izero,
514 :     (double *) NULL, (double *) NULL, (double *) NULL, dims,
515 :     &tmp, &lwork, (int *) NULL, &info);
516 : bates 582 if (info) error(_("dgeMatrix_Schur: first call to dgees failed"));
517 : bates 495 lwork = (int) tmp;
518 :     work = Calloc(lwork, double);
519 :     F77_CALL(dgees)(vecs ? "V" : "N", "N", NULL, dims, REAL(VECTOR_ELT(val, 2)), dims,
520 :     &izero, REAL(VECTOR_ELT(val, 0)), REAL(VECTOR_ELT(val, 1)),
521 : maechler 534 REAL(VECTOR_ELT(val, 3)), dims, work, &lwork,
522 : bates 495 (int *) NULL, &info);
523 : bates 582 if (info) error(_("dgeMatrix_Schur: dgees returned code %d"), info);
524 : bates 495 Free(work);
525 :     UNPROTECT(1);
526 :     return val;
527 :     }

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