#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; } ldmat::ldmat() { vec D ; mat L; } ldmat::ldmat( const mat V ) { //TODO check if correct!! Based on heuristic observation of lu() int dim = V.cols(); it_assert_debug( dim == V.rows(),"ldmat::ldmat matrix V is not square!" ); mat U( dim,dim ); L = V; //Allocate space for L ivec p = ivec( dim ); //not clear why? lu( V,L,U,p ); //Now, if V is symmetric, L is what we seek and D is on diagonal of U D = diag( U ); //check if V was symmetric //TODO How? norm of L-U'? //it_assert_debug(); } 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, sqmat &sq ) { os << sq.to_mat() << 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;}; } } return V; } 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 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; } }