#include #include "libDC.h" using namespace itpp; using std::endl; //! Auxiliary function dydr; dyadic reduction void dydr( double * r, double *f, double *Dr, double *Df, double *R, int jl, int jh, double *kr, int m, int mx ); //! Auxiliary function ltuinv; inversion of a triangular matrix; //TODO can be done via: dtrtri.f from lapack mat ltuinv( const mat &L ); ldmat::ldmat( const mat &exL, const vec &exD ) { D = exD; L = exL; dim = exD.length(); } ldmat::ldmat() { vec D ; mat L; dim = 0; } ldmat::ldmat( const mat V ) { //TODO check if correct!! Based on heuristic observation of lu() dim = V.cols(); it_assert_debug( dim == V.rows(),"ldmat::ldmat matrix V is not square!" ); } void ldmat::opupdt( const vec &v, double w ) { int dim = D.length(); double kr; vec r = v; //beware! it is potentionally dangerous, if ITpp change _behaviour of _data()! double *Lraw = L._data(); double *Draw = D._data(); double *rraw = r._data(); it_assert_debug( v.length() == dim, "LD::ldupdt vector v is not compatible with this ld." ); for ( int i = dim - 1; i >= 0; i-- ) { dydr( rraw, Lraw + i, &w, Draw + i, rraw + i, 0, i, &kr, 1, dim ); } } std::ostream &operator<< ( std::ostream &os, ldmat &ld ) { os << "L:" << ld.L << endl; os << "D:" << ld.D << endl; } mat ldmat::to_mat() { int dim = D.length(); mat V( dim, dim ); double sum; int r, c, cc; for ( r = 0;r < dim;r++ ) { //row cycle for ( c = r;c < dim;c++ ) { //column cycle, using symmetricity => c=r! sum = 0.0; for ( cc = c;cc < dim;cc++ ) { //cycle over the remaining part of the vector sum += L( cc, r ) * D( cc ) * L( cc, c ); //here L(cc,r) = L(r,cc)'; } V( r, c ) = sum; // symmetricity if ( r != c ) {V( c, r ) = sum;}; } } mat V2 = L.transpose()*diag( D )*L; return V2; } void ldmat::add( const ldmat &ld2, double w ) { int dim = D.length(); it_assert_debug( ld2.D.length() == dim, "LD.add() incompatible sizes of LDs;" ); //Fixme can be done more efficiently either via dydr or ldform for ( int r = 0; r < dim; r++ ) { // Add columns of ld2.L' (i.e. rows of ld2.L) as dyads weighted by ld2.D this->opupdt( ld2.L.get_row( r ), w*ld2.D( r ) ); } } void ldmat::clear(){L.clear(); for ( int i=0;ito_mat(); Ct *= C.transpose(); } else { // return C'*this*C Ct = C.transpose(); Ct *= this->to_mat(); Ct *= C; } ldmat Lnew=ldmat( Ct ); L = Lnew.L; D = Lnew.D; } void ldmat::mult_sym( const mat &C, ldmat &U, bool trans ) { //TODO better //TODO input test mat Ct=C; if ( trans==false ) { // return C*this*C' Ct *= U.to_mat(); Ct *= C.transpose(); } else { // return C'*this*C Ct = C.transpose(); Ct *= U.to_mat(); Ct *= C; } ldmat Lnew=ldmat( Ct ); L = Lnew.L; D = Lnew.D; } double ldmat::logdet() { double ldet = 0.0; int i; // sum logarithms of diagobal elements for ( i=0; i ( n-mn+1-cc ) )&&( i>1 ) ) { i--; sum = 0.0; v.set_size( m+i-( n-cc ) ); //prepare v for ( ii=n-cc;ii=0;i-- ) { w( j )=0.0; for ( ii=n-cc;ii0 ) { for ( ii=0;ii mzero ) { kD /= *Df; *kr /= *Df; } else { kD = 1.0; *kr = 0.0; if ( *Df < -threshold ) { it_warning( "Problem in dydr: subraction of dyad results in negative definitness. Likely mistake in calling function." ); } *Df = 0.0; } *Dr *= kD; jm = mx * jl; for ( j = m * jl; j < m*jh; j += m ) { r[j] -= r0 * f[jm]; f[jm] += *kr * r[j]; jm += mx; } }