#include "square_mat.h" using namespace itpp; using std::endl; void fsqmat::opupdt ( const vec &v, double w ) {M+=outer_product ( v,v*w );}; mat fsqmat::to_mat() const {return M;}; void fsqmat::mult_sym ( const mat &C) {M=C *M*C.T();}; void fsqmat::mult_sym_t ( const mat &C) {M=C.T() *M*C;}; void fsqmat::mult_sym ( const mat &C, fsqmat &U) const { U.M = ( C *(M*C.T()) );}; void fsqmat::mult_sym_t ( const mat &C, fsqmat &U) const { U.M = ( C.T() *(M*C) );}; void fsqmat::inv ( fsqmat &Inv ) {mat IM = itpp::inv ( M ); Inv=IM;}; void fsqmat::clear() {M.clear();}; fsqmat::fsqmat ( const mat &M0 ) : sqmat(M0.cols()) { it_assert_debug ( ( M0.cols() ==M0.rows() ),"M0 must be square" ); M=M0; }; //fsqmat::fsqmat() {}; fsqmat::fsqmat(const int dim0): sqmat(dim0), M(dim0,dim0) {}; std::ostream &operator<< ( std::ostream &os, const fsqmat &ld ) { os << ld.M << endl; return os; } ldmat::ldmat( const mat &exL, const vec &exD ) : sqmat(exD.length()) { D = exD; L = exL; } ldmat::ldmat() :sqmat(0) {} ldmat::ldmat(const int dim0): sqmat(dim0), D(dim0),L(dim0,dim0) {} ldmat::ldmat(const vec D0):sqmat(D0.length()) { D = D0; L = eye(dim); } ldmat::ldmat( const mat &V ):sqmat(V.cols()) { //TODO check if correct!! Based on heuristic observation of lu() it_assert_debug( dim == V.rows(),"ldmat::ldmat matrix V is not square!" ); // L and D will be allocated by ldform() //Chol is unstable this->ldform(chol(V),ones(dim)); // this->ldform(ul(V),ones(dim)); } 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, const ldmat &ld ) { os << "L:" << ld.L << endl; os << "D:" << ld.D << endl; return os; } mat ldmat::to_mat() const { 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;ildform(A,D); } void ldmat::mult_sym_t( const mat &C) { mat A = L*C; this->ldform(A,D); } void ldmat::mult_sym( const mat &C, ldmat &U) const { mat A=L*C.T(); //could be done more efficiently using BLAS U.ldform(A,D); } void ldmat::mult_sym_t( const mat &C, ldmat &U) const { mat A=L*C; /* vec nD=zeros(U.rows()); nD.replace_mid(0, D); //I case that D < nD*/ U.ldform(A,D); } double ldmat::logdet() const { double ldet = 0.0; int i; // sum logarithms of diagobal elements for ( i=0; in-mn-cc) && (i>0) ) { i--; sum = 0.0; int last_v = m+i-n+cc+1; vec v = zeros( last_v + 1 ); //prepare v for ( ii=n-cc-1;ii=0;j-- ) { double w_elem = 0; for ( ii=n- cc;ii<=m+i+1;ii++ ) w_elem+= v( ii-n+cc )*L( ii-1,j ); w(j)=w_elem*pom; } for ( ii=n-cc-1;ii<=m+i;ii++ ) for ( jj=0;jj=0 ) 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; } }