8 typedef Type ScalarType;
14 return Block( this->A * other.A );
17 Block<Type> scale(Type c){
18 return Block( c * this->A );
21 Block<Type> addIdentity(){
25 return Block( this->A + I );
30 Aabs = A.array().abs();
32 return rsAabs.maxCoeff();
35 Block<Type> inverse(){
36 return Block( this->A.inverse() );
39 Block<Type>& operator+=(Block<Type> x){ this->A += x.A;
return *
this; }
40 Block<Type>& operator-=(Block<Type> x){ this->A -= x.A;
return *
this; }
42 typedef Eigen::SelfAdjointEigenSolver<
43 Eigen::Matrix<Type, Eigen::Dynamic, Eigen::Dynamic> > SAES_t;
45 Block<Type> sylvester(Block<Type> Y) {
52 for (
int i=0; i<Y_.rows(); i++)
53 for (
int j=0; j<Y_.cols(); j++)
54 Y_(i, j) /= (D(i) + D(j));
60 Block<Type> sylvester2(Block<Type> Y) {
67 for (
int i=0; i<Y_.rows(); i++) {
68 for (
int j=0; j<Y_.cols(); j++) {
69 Type denum = std::abs(D(i)) + std::abs(D(j));
70 if (denum == Type(0)) denum = 1;
71 Y_(i, j) *= (D(i) + D(j)) / denum;
89 matrix<Type> X = V * saes.eigenvalues().cwiseAbs().asDiagonal() * V.transpose();
104 template<
class BlockType>
107 typedef typename BlockType::ScalarType Type;
109 Triangle(BlockType A_, BlockType B_){A = A_; B = B_;}
111 Triangle<BlockType>
operator*(Triangle<BlockType> other){
113 A = (this->A) * (other.A);
114 B = (this->A) * (other.B);
115 B += (this->B) * (other.A);
116 return Triangle(A, B);
119 Triangle<BlockType> scale(Type c){
120 return Triangle(this->A.scale(c), this->B.scale(c));
123 Triangle<BlockType> addIdentity(){
124 return Triangle(this->A.addIdentity(), this->B);
130 return this->A.norm();
133 Triangle<BlockType> inverse(){
134 BlockType A = this->A.inverse();
135 BlockType B = (A * (this->B * A)).scale(-1);
136 return Triangle(A, B);
139 Triangle<BlockType>& operator+=(Triangle<BlockType> x){
144 Triangle<BlockType>& operator-=(Triangle<BlockType> x){
150 Triangle<BlockType> sylvester(Triangle<BlockType> Y) {
151 Triangle<BlockType> X;
152 X.A = (*this).A.sylvester(Y.A);
153 Y.B -= (*this).B * X.A;
154 Y.B -= X.A * (*this).B;
155 X.B = (*this).A.sylvester(Y.B);
159 Triangle<BlockType> sylvester2(Triangle<BlockType> Y) {
160 Triangle<BlockType> Y2 = (*this) * Y;
162 Triangle<BlockType> X = (*this).absm().sylvester(Y2);
165 Triangle<BlockType> sqrtm() {
166 BlockType A = (*this).A.sqrtm();
167 BlockType B = A.sylvester((*this).B);
168 return Triangle(A, B);
170 Triangle<BlockType> absm() {
171 BlockType A = (*this).A.absm();
172 BlockType B = (*this).A.sylvester2((*this).B);
173 return Triangle(A, B);
197 struct nestedTriangle : Triangle<nestedTriangle<n-1> >{
198 typedef double ScalarType;
199 typedef nestedTriangle<n-1> BlockType;
200 typedef Triangle<nestedTriangle<n-1> > Base;
202 nestedTriangle(Base x) : Base(x){}
204 int nargs=args.size();
208 for(
int i=0;i<nargs-1;i++)args2[i] = zero;
209 args2[0] = args[nargs-1];
210 Base::A = nestedTriangle<n-1>(args1);
211 Base::B = nestedTriangle<n-1>(args2);
215 return this->B.bottomLeftCorner();
219 struct nestedTriangle<0> : Block<double>{
220 typedef Block<double> Base;
221 nestedTriangle<0>(){}
222 nestedTriangle<0>(Base x) : Base(x){}
235 template<
class matrix_pade>
236 matrix_pade expm(matrix_pade A){
237 double log2NormInf = log( A.norm() );
238 log2NormInf /= log(
double(2.0));
239 double e = std::floor(log2NormInf) + 1.0;
242 matrix_pade AA = A.scale( 1.0 / pow( 2.0, s ) );
245 matrix_pade E = AA.scale( c).addIdentity();
246 matrix_pade D = AA.scale(-c).addIdentity();
249 for(
int k = 2; k<=q; ++k){
250 c *= double(q-k+1) / double(k*(2*q-k+1));
252 matrix_pade cX = X.scale(c);
254 if (p == 1) { D += cX; }
else { D -= cX; }
255 p = (p == 1) ? 0 : 1;
257 matrix_pade invD = D.inverse();
259 for(
int k = 1; k<=s; k++){
270 int nargs = args.size();
272 if (nargs==1) ans=expm(nestedTriangle<0>(args)).bottomLeftCorner();
273 else if (nargs==2) ans=expm(nestedTriangle<1>(args)).bottomLeftCorner();
274 else if (nargs==3) ans=expm(nestedTriangle<2>(args)).bottomLeftCorner();
275 else if (nargs==4) ans=expm(nestedTriangle<3>(args)).bottomLeftCorner();
276 else Rf_error(
"expm: order not implemented.");
285 int nargs = args.size();
286 int nkeep = nargs - (skip >= 0);
287 int blocksize = args[0].size();
288 int n = 1 + nkeep * blocksize;
289 CppAD::vector<Type> ans(n);
292 for(
int i=0; i<nargs; i++){
294 for(
int j=0; j < blocksize; j++){
327 (tx.size()-1)/CppAD::Integer(tx[0])
330 int nargs=CppAD::Integer(tx[0]);
331 int n=sqrt((
double)(tx.size()-1)/nargs);
333 for(
int i=0;i<nargs;i++){
334 args[i] = vec2mat(tx, n, n, 1 + i*n*n);
337 for(
int i=0;i<n*n;i++)ty[i] = res(i);
340 int nargs=CppAD::Integer(tx[0]);
341 int n=sqrt((
double)ty.size());
343 for(
int i=0;i<nargs;i++){
344 args[i] = vec2mat(tx, n, n, 1 + i*n*n).transpose();
346 args[nargs] = vec2mat(py,n,n);
348 res[0] = expm(args2vector(args));
349 for(
int i=1;i<nargs;i++){
350 res[i] = expm(args2vector(args, i));
353 for(
int j=0;j<res.size();j++){
354 for(
int i=0;i<n*n;i++){
355 px[1 + i + j*n*n] = res[j][i];
370 return vec2mat(expm(args2vector(args)),n,n);
373 template<
class matrix_pade>
374 matrix_pade sqrtm(matrix_pade A){
379 int nargs = args.size();
381 if (nargs==1) ans=sqrtm(nestedTriangle<0>(args)).bottomLeftCorner();
382 else if (nargs==2) ans=sqrtm(nestedTriangle<1>(args)).bottomLeftCorner();
383 else if (nargs==3) ans=sqrtm(nestedTriangle<2>(args)).bottomLeftCorner();
384 else if (nargs==4) ans=sqrtm(nestedTriangle<3>(args)).bottomLeftCorner();
385 else Rf_error(
"sqrtm: order not implemented.");
394 (tx.size()-1)/CppAD::Integer(tx[0])
397 int nargs=CppAD::Integer(tx[0]);
398 int n=sqrt((
double)(tx.size()-1)/nargs);
400 for(
int i=0;i<nargs;i++){
401 args[i] = vec2mat(tx, n, n, 1 + i*n*n);
404 for(
int i=0;i<n*n;i++)ty[i] = res(i);
407 int nargs=CppAD::Integer(tx[0]);
408 int n=sqrt((
double)ty.size());
410 for(
int i=0;i<nargs;i++){
411 args[i] = vec2mat(tx, n, n, 1 + i*n*n).transpose();
413 args[nargs] = vec2mat(py,n,n);
415 res[0] = sqrtm(args2vector(args));
416 for(
int i=1;i<nargs;i++){
417 res[i] = sqrtm(args2vector(args, i));
420 for(
int j=0;j<res.size();j++){
421 for(
int i=0;i<n*n;i++){
422 px[1 + i + j*n*n] = res[j][i];
436 for (
int i=0; i<n; i++)
437 for (
int j=0; j<i; j++)
441 return vec2mat(sqrtm(args2vector(args)),n,n);
444 template<
class matrix_pade>
445 matrix_pade absm(matrix_pade A){
450 int nargs = args.size();
452 if (nargs==1) ans=absm(nestedTriangle<0>(args)).bottomLeftCorner();
453 else if (nargs==2) ans=absm(nestedTriangle<1>(args)).bottomLeftCorner();
454 else if (nargs==3) ans=absm(nestedTriangle<2>(args)).bottomLeftCorner();
455 else if (nargs==4) ans=absm(nestedTriangle<3>(args)).bottomLeftCorner();
456 else Rf_error(
"absm: order not implemented.");
465 (tx.size()-1)/CppAD::Integer(tx[0])
468 int nargs=CppAD::Integer(tx[0]);
469 int n=sqrt((
double)(tx.size()-1)/nargs);
471 for(
int i=0;i<nargs;i++){
472 args[i] = vec2mat(tx, n, n, 1 + i*n*n);
475 for(
int i=0;i<n*n;i++)ty[i] = res(i);
478 int nargs=CppAD::Integer(tx[0]);
479 int n=sqrt((
double)ty.size());
481 for(
int i=0;i<nargs;i++){
482 args[i] = vec2mat(tx, n, n, 1 + i*n*n).transpose();
484 args[nargs] = vec2mat(py,n,n);
486 res[0] = absm(args2vector(args));
487 for(
int i=1;i<nargs;i++){
488 res[i] = absm(args2vector(args, i));
491 for(
int j=0;j<res.size();j++){
492 for(
int i=0;i<n*n;i++){
493 px[1 + i + j*n*n] = res[j][i];
509 for (
int i=0; i<n; i++)
510 for (
int j=0; j<i; j++)
514 return vec2mat(absm(args2vector(args)),n,n);
Vector class used by TMB.
Namespace with special functions and derivatives.
matrix< Type > expm(matrix< Type > x)
Matrix exponential.
vector< Type > operator*(matrix< Type > A, vector< Type > x)
Matrix class used by TMB.
#define TMB_ATOMIC_VECTOR_FUNCTION( ATOMIC_NAME, OUTPUT_DIM, ATOMIC_DOUBLE, ATOMIC_REVERSE)
Construct atomic vector function based on known derivatives.