root/library/bdm/math/square_mat.cpp @ 1038

Revision 737, 9.3 kB (checked in by mido, 15 years ago)

ASTYLER RUN OVER THE WHOLE LIBRARY, JUPEE

  • Property svn:eol-style set to native
Line 
1
2#include "square_mat.h"
3
4namespace bdm {
5
6using namespace itpp;
7
8using std::endl;
9
10void fsqmat::opupdt ( const vec &v, double w ) {
11        M += outer_product ( v, v * w );
12};
13mat fsqmat::to_mat() const {
14        return M;
15};
16void fsqmat::mult_sym ( const mat &C ) {
17        M = C * M * C.T();
18};
19void fsqmat::mult_sym_t ( const mat &C ) {
20        M = C.T() * M * C;
21};
22void fsqmat::mult_sym ( const mat &C, fsqmat &U ) const {
23        U.M = ( C * ( M * C.T() ) );
24};
25void fsqmat::mult_sym_t ( const mat &C, fsqmat &U ) const {
26        U.M = ( C.T() * ( M * C ) );
27};
28void fsqmat::inv ( fsqmat &Inv ) const {
29        mat IM = itpp::inv ( M );
30        Inv = IM;
31};
32void fsqmat::clear() {
33        M.clear();
34};
35fsqmat::fsqmat ( const mat &M0 ) : sqmat ( M0.cols() ) {
36        bdm_assert_debug ( ( M0.cols() == M0.rows() ), "M0 must be square" );
37        M = M0;
38};
39
40//fsqmat::fsqmat() {};
41
42fsqmat::fsqmat ( const int dim0 ) : sqmat ( dim0 ), M ( dim0, dim0 ) {};
43
44std::ostream &operator<< ( std::ostream &os, const fsqmat &ld ) {
45        os << ld.M << endl;
46        return os;
47}
48
49
50ldmat::ldmat ( const mat &exL, const vec &exD ) : sqmat ( exD.length() ) {
51        D = exD;
52        L = exL;
53}
54
55ldmat::ldmat() : sqmat ( 0 ) {}
56
57ldmat::ldmat ( const int dim0 ) : sqmat ( dim0 ), D ( dim0 ), L ( dim0, dim0 ) {}
58
59ldmat::ldmat ( const vec D0 ) : sqmat ( D0.length() ) {
60        D = D0;
61        L = eye ( dim );
62}
63
64ldmat::ldmat ( const mat &V ) : sqmat ( V.cols() ) {
65
66        bdm_assert_debug ( dim == V.rows(), "ldmat::ldmat matrix V is not square!" );
67
68        // L and D will be allocated by ldform()
69        //Chol is unstable
70        this->ldform ( chol ( V ), ones ( dim ) );
71}
72
73void ldmat::opupdt ( const vec &v,  double w ) {
74        int dim = D.length();
75        double kr;
76        vec r = v;
77        //beware! it is potentionally dangerous, if ITpp change _behaviour of _data()!
78        double *Lraw = L._data();
79        double *Draw = D._data();
80        double *rraw = r._data();
81
82        bdm_assert_debug ( v.length() == dim, "LD::ldupdt vector v is not compatible with this ld." );
83
84        for ( int i = dim - 1; i >= 0; i-- ) {
85                dydr ( rraw, Lraw + i, &w, Draw + i, rraw + i, 0, i, &kr, 1, dim );
86        }
87}
88
89std::ostream &operator<< ( std::ostream &os, const ldmat &ld ) {
90        os << "L:" << ld.L << endl;
91        os << "D:" << ld.D << endl;
92        return os;
93}
94
95mat ldmat::to_mat() const {
96        int dim = D.length();
97        mat V ( dim, dim );
98        double sum;
99        int r, c, cc;
100
101        for ( r = 0; r < dim; r++ ) { //row cycle
102                for ( c = r; c < dim; c++ ) {
103                        //column cycle, using symmetricity => c=r!
104                        sum = 0.0;
105                        for ( cc = c; cc < dim; cc++ ) { //cycle over the remaining part of the vector
106                                sum += L ( cc, r ) * D ( cc ) * L ( cc, c );
107                                //here L(cc,r) = L(r,cc)';
108                        }
109                        V ( r, c ) = sum;
110                        // symmetricity
111                        if ( r != c ) {
112                                V ( c, r ) = sum;
113                        };
114                }
115        }
116        //mat V2 = L.transpose() * diag ( D ) * L;
117        return V;
118}
119
120
121void ldmat::add ( const ldmat &ld2, double w ) {
122        int dim = D.length();
123
124        bdm_assert_debug ( ld2.D.length() == dim, "LD.add() incompatible sizes of LDs" );
125
126        //Fixme can be done more efficiently either via dydr or ldform
127        for ( int r = 0; r < dim; r++ ) {
128                // Add columns of ld2.L' (i.e. rows of ld2.L) as dyads weighted by ld2.D
129                this->opupdt ( ld2.L.get_row ( r ), w*ld2.D ( r ) );
130        }
131}
132
133void ldmat::clear() {
134        L.clear();
135        for ( int i = 0; i < L.cols(); i++ ) {
136                L ( i, i ) = 1;
137        };
138        D.clear();
139}
140
141void ldmat::inv ( ldmat &Inv ) const {
142        Inv.clear();   //Inv = zero in LD
143        mat U = ltuinv ( L );
144
145        Inv.ldform ( U.transpose(), 1.0 / D );
146}
147
148void ldmat::mult_sym ( const mat &C ) {
149        mat A = L * C.T();
150        this->ldform ( A, D );
151}
152
153void ldmat::mult_sym_t ( const mat &C ) {
154        mat A = L * C;
155        this->ldform ( A, D );
156}
157
158void ldmat::mult_sym ( const mat &C, ldmat &U ) const {
159        mat A = L * C.T(); //could be done more efficiently using BLAS
160        U.ldform ( A, D );
161}
162
163void ldmat::mult_sym_t ( const mat &C, ldmat &U ) const {
164        mat A = L * C;
165        /*      vec nD=zeros(U.rows());
166                nD.replace_mid(0, D); //I case that D < nD*/
167        U.ldform ( A, D );
168}
169
170
171double ldmat::logdet() const {
172        double ldet = 0.0;
173        int i;
174// sum logarithms of diagobal elements
175        for ( i = 0; i < D.length(); i++ ) {
176                ldet += log ( D ( i ) );
177        };
178        return ldet;
179}
180
181double ldmat::qform ( const vec &v ) const {
182        double x = 0.0, sum;
183        int i, j;
184
185        for ( i = 0; i < D.length(); i++ ) { //rows of L
186                sum = 0.0;
187                for ( j = 0; j <= i; j++ ) {
188                        sum += L ( i, j ) * v ( j );
189                }
190                x += D ( i ) * sum * sum;
191        };
192        return x;
193}
194
195double ldmat::invqform ( const vec &v ) const {
196        double x = 0.0;
197        int i;
198        vec pom ( v.length() );
199
200        backward_substitution ( L.T(), v, pom );
201
202        for ( i = 0; i < D.length(); i++ ) { //rows of L
203                x += pom ( i ) * pom ( i ) / D ( i );
204        };
205        return x;
206}
207
208ldmat& ldmat::operator *= ( double x ) {
209        D *= x;
210        return *this;
211}
212
213vec ldmat::sqrt_mult ( const vec &x ) const {
214        int i, j;
215        vec res ( dim );
216        //double sum;
217        for ( i = 0; i < dim; i++ ) {//for each element of result
218                res ( i ) = 0.0;
219                for ( j = i; j < dim; j++ ) {//sum D(j)*L(:,i).*x
220                        res ( i ) += sqrt ( D ( j ) ) * L ( j, i ) * x ( j );
221                }
222        }
223//      vec res2 = L.transpose()*diag( sqrt( D ) )*x;
224        return res;
225}
226
227void ldmat::ldform ( const mat &A, const vec &D0 ) {
228        int m = A.rows();
229        int n = A.cols();
230        int mn = ( m < n ) ? m : n ;
231
232        bdm_assert_debug ( D0.length() == A.rows(), "ldmat::ldform Vector D must have the length as row count of A" );
233
234        L = concat_vertical ( zeros ( n, n ), diag ( sqrt ( D0 ) ) * A );
235        D = zeros ( n + m );
236
237        //unnecessary big L and D will be made smaller at the end of file
238        vec w = zeros ( n + m );
239
240        double sum, beta, pom;
241
242        int cc = 0;
243        int i = n; // indexovani o 1 niz, nez v matlabu
244        int ii, j, jj;
245        while ( ( i > n - mn - cc ) && ( i > 0 ) ) {
246                i--;
247                sum = 0.0;
248
249                int last_v = m + i - n + cc + 1;
250
251                vec v = zeros ( last_v + 1 ); //prepare v
252                for ( ii = n - cc - 1; ii < m + i + 1; ii++ ) {
253                        sum += L ( ii, i ) * L ( ii, i );
254                        v ( ii - n + cc + 1 ) = L ( ii, i ); //assign v
255                }
256
257                if ( L ( m + i, i ) == 0 )
258                        beta = sqrt ( sum );
259                else
260                        beta = L ( m + i, i ) + sign ( L ( m + i, i ) ) * sqrt ( sum );
261
262                if ( std::fabs ( beta ) < eps ) {
263                        cc++;
264                        L.set_row ( n - cc, L.get_row ( m + i ) );
265                        L.set_row ( m + i, zeros ( L.cols() ) );
266                        D ( m + i ) = 0;
267                        L ( m + i, i ) = 1;
268                        L.set_submatrix ( n - cc, m + i - 1, i, i, 0 );
269                        continue;
270                }
271
272                sum -= v ( last_v ) * v ( last_v );
273                sum /= beta * beta;
274                sum++;
275
276                v /= beta;
277                v ( last_v ) = 1;
278
279                pom = -2.0 / sum;
280                // echo to venca
281
282                for ( j = i; j >= 0; j-- ) {
283                        double w_elem = 0;
284                        for ( ii = n -  cc; ii <= m + i + 1; ii++ )
285                                w_elem += v ( ii - n + cc ) * L ( ii - 1, j );
286                        w ( j ) = w_elem * pom;
287                }
288
289                for ( ii = n - cc - 1; ii <= m + i; ii++ )
290                        for ( jj = 0; jj < i; jj++ )
291                                L ( ii, jj ) += v ( ii - n + cc + 1 ) * w ( jj );
292
293                for ( ii = n - cc - 1; ii < m + i; ii++ )
294                        L ( ii, i ) = 0;
295
296                L ( m + i, i ) += w ( i );
297                D ( m + i ) = L ( m + i, i ) * L ( m + i, i );
298
299                for ( ii = 0; ii <= i; ii++ )
300                        L ( m + i, ii ) /= L ( m + i, i );
301        }
302
303        if ( i >= 0 )
304                for ( ii = 0; ii < i; ii++ ) {
305                        jj = D.length() - 1 - n + ii;
306                        D ( jj ) = 0;
307                        L.set_row ( jj, zeros ( L.cols() ) ); //TODO: set_row accepts Num_T
308                        L ( jj, jj ) = 1;
309                }
310
311        L.del_rows ( 0, m - 1 );
312        D.del ( 0, m - 1 );
313
314        dim = L.rows();
315}
316
317//////// Auxiliary Functions
318
319mat ltuinv ( const mat &L ) {
320        int dim = L.cols();
321        mat Il = eye ( dim );
322        int i, j, k, m;
323        double s;
324
325//Fixme blind transcription of ltuinv.m
326        for ( k = 1; k < ( dim ); k++ ) {
327                for ( i = 0; i < ( dim - k ); i++ ) {
328                        j = i + k; //change in .m 1+1=2, here 0+0+1=1
329                        s = L ( j, i );
330                        for ( m = i + 1; m < ( j ); m++ ) {
331                                s += L ( m, i ) * Il ( j, m );
332                        }
333                        Il ( j, i ) = -s;
334                }
335        }
336
337        return Il;
338}
339
340void dydr ( double * r, double *f, double *Dr, double *Df, double *R, int jl, int jh, double *kr, int m, int mx )
341/********************************************************************
342
343   dydr = dyadic reduction, performs transformation of sum of
344          2 dyads r*Dr*r'+ f*Df*f' so that the element of r pointed
345          by R is zeroed. This version allows Dr to be NEGATIVE. Hence the name negdydr or dydr_withneg.
346
347   Parameters :
348     r ... pointer to reduced dyad
349     f ... pointer to reducing dyad
350     Dr .. pointer to the weight of reduced dyad
351     Df .. pointer to the weight of reducing dyad
352     R ... pointer to the element of r, which is to be reduced to
353           zero; the corresponding element of f is assumed to be 1.
354     jl .. lower index of the range within which the dyads are
355           modified
356     ju .. upper index of the range within which the dyads are
357           modified
358     kr .. pointer to the coefficient used in the transformation of r
359           rnew = r + kr*f
360     m  .. number of rows of modified matrix (part of which is r)
361  Remark : Constant mzero means machine zero and should be modified
362           according to the precision of particular machine
363
364                                                 V. Peterka 17-7-89
365
366  Added:
367     mx .. number of rows of modified matrix (part of which is f)  -PN
368
369********************************************************************/
370{
371        int j, jm;
372        double kD, r0;
373        double mzero = 2.2e-16;
374        double threshold = 1e-4;
375
376        if ( fabs ( *Dr ) < mzero ) *Dr = 0;
377        r0 = *R;
378        *R = 0.0;
379        kD = *Df;
380        *kr = r0 * *Dr;
381        *Df = kD + r0 * ( *kr );
382        if ( *Df > mzero ) {
383                kD /= *Df;
384                *kr /= *Df;
385        } else {
386                kD = 1.0;
387                *kr = 0.0;
388                if ( *Df < -threshold ) {
389                        bdm_warning ( "Problem in dydr: subraction of dyad results in negative definitness. Likely mistake in calling function." );
390                }
391                *Df = 0.0;
392        }
393        *Dr *= kD;
394        jm = mx * jl;
395        for ( j = m * jl; j < m*jh; j += m ) {
396                r[j] -=  r0 * f[jm];
397                f[jm] += *kr * r[j];
398                jm += mx;
399        }
400}
401
402}
Note: See TracBrowser for help on using the browser.