Sleipnir
src/fullmatrix.h
00001 /*****************************************************************************
00002 * This file is provided under the Creative Commons Attribution 3.0 license.
00003 *
00004 * You are free to share, copy, distribute, transmit, or adapt this work
00005 * PROVIDED THAT you attribute the work to the authors listed below.
00006 * For more information, please see the following web page:
00007 * http://creativecommons.org/licenses/by/3.0/
00008 *
00009 * This file is a component of the Sleipnir library for functional genomics,
00010 * authored by:
00011 * Curtis Huttenhower (chuttenh@princeton.edu)
00012 * Mark Schroeder
00013 * Maria D. Chikina
00014 * Olga G. Troyanskaya (ogt@princeton.edu, primary contact)
00015 *
00016 * If you use this library, the included executable tools, or any related
00017 * code in your work, please cite the following publication:
00018 * Curtis Huttenhower, Mark Schroeder, Maria D. Chikina, and
00019 * Olga G. Troyanskaya.
00020 * "The Sleipnir library for computational functional genomics"
00021 *****************************************************************************/
00022 #ifndef FULLMATRIX_H
00023 #define FULLMATRIX_H
00024 
00025 #undef int64_t
00026 #include <stdint.h>
00027 
00028 #include <cstring>
00029 #include <fstream>
00030 #include <iostream>
00031 #include <limits>
00032 #include <sstream>
00033 #include <vector>
00034 
00035 namespace Sleipnir {
00036 
00051 template<class tType>
00052 class CFullMatrix {
00053 public:
00054     CFullMatrix( ) : m_iR(0), m_iC(0), m_aaData(NULL) { }
00055 
00056     virtual ~CFullMatrix( ) {
00057 
00058         Reset( ); }
00059 
00064     void Reset( ) {
00065         size_t  i;
00066 
00067         if( m_aaData && m_fMemory ) {
00068             for( i = 0; i < GetRows( ); ++i )
00069                 delete[] m_aaData[ i ];
00070             delete[] m_aaData; }
00071 
00072         m_iR = m_iC = 0;
00073         m_aaData = NULL; }
00074 
00082     tType** const Get( ) const {
00083 
00084         return m_aaData; }
00085 
00103     tType* Get( size_t iY ) const {
00104 
00105         return m_aaData[ iY ]; }
00106 
00127     tType& Get( size_t iY, size_t iX ) const {
00128 
00129         return m_aaData[ iY ][ iX ]; }
00130 
00151     void Set( size_t iY, size_t iX, const tType& Value ) {
00152 
00153         m_aaData[ iY ][ iX ] = Value; }
00154 
00172     void Set( size_t iY, const tType* aValues ) {
00173 
00174         memcpy( m_aaData[ iY ], aValues, GetColumns( ) * sizeof(*aValues) ); }
00175 
00187     void Initialize( const CFullMatrix& Mat ) {
00188 
00189         Initialize( Mat.GetRows( ), Mat.GetColumns( ), Mat.m_aaData ); }
00190 
00208     virtual void Initialize( size_t iR, size_t iC, tType** aaData = NULL ) {
00209         size_t  i;
00210 
00211         Reset( );
00212         m_iR = iR;
00213         m_iC = iC;
00214         if( m_fMemory = !( m_aaData = aaData ) ) {
00215             m_aaData = new tType*[ GetRows( ) ];
00216             for( i = 0; i < GetRows( ); ++i )
00217                 m_aaData[ i ] = new tType[ GetColumns( ) ]; } }
00218 
00229     size_t GetRows( ) const {
00230 
00231         return m_iR; }
00232 
00243     size_t GetColumns( ) const {
00244 
00245         return m_iC; }
00246 
00264     bool Open( std::istream& istm, bool fBinary ) {
00265 
00266         return ( fBinary ? OpenBinary( istm ) : OpenText( istm ) ); }
00267 
00281     bool Open( const char* szFile ) {
00282 
00283         if( szFile ) {
00284             std::ifstream   ifsm;
00285 
00286             ifsm.open( szFile, ios_base::binary );
00287             return Open( ifsm, true ); }
00288 
00289         return Open( std::cin, false ); }
00290 
00307     bool Open( const CFullMatrix& Mat ) {
00308         size_t  i;
00309 
00310         if( ( GetRows( ) != Mat.GetRows( ) ) || ( GetColumns( ) != Mat.GetColumns( ) ) )
00311             Initialize( Mat.GetRows( ), Mat.GetColumns( ) );
00312 
00313         for( i = 0; i < GetRows( ); ++i )
00314             memcpy( Get( i ), Mat.Get( i ), GetColumns( ) * sizeof(*Get( i )) );
00315 
00316         return true; }
00317 
00338     bool Save( std::ostream& ostm, bool fBinary ) const {
00339 
00340         return ( fBinary ? SaveBinary( ostm ) : SaveText( ostm ) ); }
00341 
00355     bool Save( const char* szFile ) const {
00356 
00357         if( szFile ) {
00358             std::ofstream   ofsm;
00359 
00360             ofsm.open( szFile, ios_base::binary );
00361             return Save( ofsm, true ); }
00362 
00363         return Save( cout, false ); }
00364 
00385     bool Save( const char* szFile, bool fBinary ) const {
00386         std::ofstream   ofsm;
00387 
00388         ofsm.open( szFile, ( fBinary ? ios_base::binary : ios_base::out ) | ios_base::out );
00389         return Save( ofsm, fBinary ); }
00390 
00395     void Clear( ) {
00396         size_t  i;
00397 
00398         if( !m_aaData )
00399             return;
00400 
00401         for( i = 0; i < GetRows( ); ++i )
00402             memset( m_aaData[ i ], 0, sizeof(*m_aaData[ i ]) * GetColumns( ) ); }
00403 
00421     bool AddRows( size_t iR, bool fClear = false ) {
00422         tType** m_aaNew;
00423         size_t  i;
00424 
00425         if( !m_fMemory )
00426             return false;
00427 
00428         m_aaNew = new tType*[ GetRows( ) + iR ];
00429         memcpy( m_aaNew, m_aaData, GetRows( ) * sizeof(*m_aaData) );
00430         delete[] m_aaData;
00431         m_aaData = m_aaNew;
00432         for( i = 0; i < iR; ++i ) {
00433             m_aaNew[ GetRows( ) + i ] = new tType[ GetColumns( ) ];
00434             if( fClear )
00435                 memset( m_aaNew[ GetRows( ) + i ], 0, GetColumns( ) * sizeof(**m_aaNew) ); }
00436         m_iR += iR;
00437 
00438         return true; }
00439 
00456     bool Multiply( std::vector<tType>& vecRight ) {
00457         size_t  i, j;
00458 
00459         if( vecRight.size( ) != GetColumns( ) )
00460             return false;
00461 
00462         for( i = 0; i < GetColumns( ); ++i )
00463             for( j = 0; j < GetRows( ); ++j )
00464                 Set( j, i, vecRight[ i ] * Get( j, i ) );
00465 
00466         return true; }
00467 
00488     bool Multiply( const CFullMatrix& MatRight, bool fTranspose = false ) {
00489         CFullMatrix MatTmp;
00490         size_t      i, j, k, iRR, iRC;
00491 
00492         iRR = fTranspose ? MatRight.GetColumns( ) : MatRight.GetRows( );
00493         if( GetColumns( ) != iRR )
00494             return false;
00495 
00496         MatTmp.Initialize( GetRows( ), iRC = fTranspose ? MatRight.GetRows( ) : MatRight.GetColumns( ) );
00497         MatTmp.Clear( );
00498         for( i = 0; i < iRC; ++i )
00499             for( j = 0; j < GetRows( ); ++j )
00500                 for( k = 0; k < iRR; ++k )
00501                     MatTmp.Get( j, i ) += Get( j, k ) * ( fTranspose ? MatRight.Get( i, k ) :
00502                         MatRight.Get( k, i ) );
00503 
00504         return Open( MatTmp ); }
00505 
00529     bool SVD( CFullMatrix<tType>& MatU, CFullMatrix<tType>& MatV, std::vector<tType>& vecS ) const {
00530         size_t              i, j, k, iNU, iCT, iRT;
00531         vector<tType>       vecE, vecWork;
00532         CFullMatrix<tType>  MatA;
00533         bool                fU, fV;
00534         ESVD                eCase;
00535         tType               F;
00536         int                 iMarker, iP, iPP;
00537 
00538         iNU = min( GetRows( ), GetColumns( ) );
00539         vecS.resize( min( GetRows( ) + 1, GetColumns( ) ) );
00540         MatU.Initialize( GetRows( ), iNU );
00541         MatU.Clear( );
00542         MatV.Initialize( GetColumns( ), GetColumns( ) );
00543 
00544         vecE.resize( GetColumns( ) );
00545         vecWork.resize( GetRows( ) );
00546         MatA.Open( *this );
00547 
00548         // Reduce A to bidiagonal form, storing the diagonal elements
00549         // in s and the super-diagonal elements in e.
00550         fU = fV = true;
00551         iCT = min( GetRows( ) - 1, GetColumns( ) );
00552         iRT = max( (size_t)0, min( GetColumns( ) - 2, GetRows( ) ) );
00553         for( k = 0; k < max( iCT, iRT ); ++k ) {
00554             if( k < iCT ) {
00555                 // Compute the transformation for the k-th column and
00556                 // place the k-th diagonal in s[k].
00557                 // Compute 2-norm of k-th column without under/overflow.
00558                 vecS[ k ] = 0;
00559                 for( i = k; i < GetRows( ); ++i )
00560                     vecS[ k ] = Hypotenuse( vecS[ k ], MatA.Get( i, k ) );
00561                 if( vecS[ k ] ) {
00562                     if( MatA.Get( k, k ) < 0 )
00563                         vecS[ k ] *= -1;
00564                     for( i = k; i < GetRows( ); ++i )
00565                         MatA.Get( i, k ) /= vecS[ k ];
00566                     MatA.Get( k, k ) += 1; }
00567                 vecS[ k ] *= -1; }
00568 
00569             for( j = ( k + 1 ); j < GetColumns( ); ++j ) {
00570                 if( ( k < iCT ) && vecS[ k ] ) {
00571                     tType   T;
00572 
00573                     // Apply the transformation.
00574                     T = 0;
00575                     for( i = k; i < GetRows( ); ++i )
00576                         T += MatA.Get( i, k ) * MatA.Get( i, j );
00577                     T /= -MatA.Get( k, k );
00578                     for( i = k; i < GetRows( ); ++i )
00579                         MatA.Get( i, j ) += T * MatA.Get( i, k ); }
00580 
00581                 // Place the k-th row of A into e for the
00582                 // subsequent calculation of the row transformation.
00583                 vecE[ j ] = MatA.Get( k, j ); }
00584 
00585             if( fU && ( k < iCT ) )
00586                 // Place the transformation in U for subsequent back
00587                 // multiplication.
00588                 for( i = k; i < GetRows( ); ++i )
00589                     MatU.Set( i, k, MatA.Get( i, k ) );
00590             if( k < iRT ) {
00591                 // Compute the k-th row transformation and place the
00592                 // k-th super-diagonal in e[k].
00593                 // Compute 2-norm without under/overflow.
00594                 vecE[ k ] = 0;
00595                 for( i = ( k + 1 ); i < GetColumns( ); ++i )
00596                     vecE[ k ] = Hypotenuse( vecE[ k ], vecE[ i ] );
00597                 if( vecE[ k ] ) {
00598                     if( vecE[ k + 1 ] < 0 )
00599                         vecE[ k ] *= -1;
00600                     for( i = ( k + 1 ); i < GetColumns( ); ++i )
00601                         vecE[ i ] /= vecE[ k ];
00602                     vecE[ k + 1 ] += 1; }
00603                 vecE[ k ] *= -1;
00604 
00605                 if( ( ( k + 1 ) < GetRows( ) ) && vecE[ k ] ) {
00606                     // Apply the transformation.
00607                     for( i = ( k + 1 ); i < GetRows( ); ++i )
00608                         vecWork[ i ] = 0;
00609                     for( j = ( k + 1 ); j < GetColumns( ); ++j )
00610                         for( i = ( k + 1 ); i < GetRows( ); ++i )
00611                             vecWork[ i ] += vecE[ j ] * MatA.Get( i, j );
00612                     for( j = ( k + 1 ); j < GetColumns( ); ++j ) {
00613                         tType   T;
00614 
00615                         T = -vecE[ j ] / vecE[ k + 1 ];
00616                         for( i = ( k + 1 ); i < GetRows( ); ++i )
00617                             MatA.Get( i, j ) += T * vecWork[ i ]; } }
00618 
00619                 if( fV )
00620                     // Place the transformation in V for subsequent
00621                     // back multiplication.
00622                     for( i = ( k + 1 ); i < GetColumns( ); ++i )
00623                         MatV.Set( i, k, vecE[ i ] ); } }
00624 
00625         // Set up the final bidiagonal matrix or order p.
00626         iP = (int)min( GetColumns( ), GetRows( ) + 1 );
00627         if( iCT < GetColumns( ) )
00628             vecS[ iCT ] = MatA.Get( iCT, iCT );
00629         if( GetRows( ) < (size_t)iP )
00630             vecS[ iP - 1 ] = 0;
00631         if( ( iRT + 1 ) < (size_t)iP )
00632             vecE[ iRT ] = MatA.Get( iRT, iP - 1 );
00633         vecE[ iP - 1 ] = 0;
00634 
00635         // If required, generate U.
00636         if( fU ) {
00637             for( j = iCT; j < iNU; ++j ) {
00638                 for( i = 0; i < GetRows( ); ++i )
00639                     MatU.Set( i, j, 0 );
00640                 MatU.Set( j, j, 1 ); }
00641             for( size_t iTmp = 0; iTmp < iCT; ++iTmp ) {
00642                 k = iCT - 1 - iTmp;
00643                 if( vecS[ k ] ) {
00644                     for( j = ( k + 1 ); j < iNU; ++j ) {
00645                         tType   T;
00646 
00647                         T = 0;
00648                         for( i = k; i < GetRows( ); ++i )
00649                             T += MatU.Get( i, k ) * MatU.Get( i, j );
00650                         T /= -MatU.Get( k, k );
00651                         for( i = k; i < GetRows( ); ++i )
00652                             MatU.Get( i, j ) += T * MatU.Get( i, k ); }
00653                     for( i = k; i < GetRows( ); ++i )
00654                         MatU.Get( i, k ) *= -1;
00655                     MatU.Get( k, k ) += 1;
00656                     for( i = 0; ( i + 1 ) < k; ++i )
00657                         MatU.Set( i, k, 0 ); }
00658                 else {
00659                     for( i = 0; i < GetRows( ); ++i )
00660                         MatU.Set( i, k, 0 );
00661                     MatU.Set( k, k, 1 ); } } }
00662 
00663         // If required, generate V.
00664         if( fV ) {
00665             for( size_t iTmp = 0; iTmp < GetColumns( ); ++iTmp ) {
00666                 k = GetColumns( ) - 1 - iTmp;
00667                 if( ( k < iRT ) && vecE[ k ] )
00668                     for( j = ( k + 1 ); j < iNU; ++j ) {
00669                         tType   T;
00670 
00671                         T = 0;
00672                         for( i = ( k + 1 ); i < GetColumns( ); ++i )
00673                             T += MatV.Get( i, k ) * MatV.Get( i, j );
00674                         T /= -MatV.Get( k + 1, k );
00675                         for( i = ( k + 1 ); i < GetColumns( ); ++i )
00676                             MatV.Get( i, j ) += T * MatV.Get( i, k ); }
00677                 for( i = 0; i < GetColumns( ); ++i )
00678                     MatV.Set( i, k, 0 );
00679                 MatV.Set( k, k, 1 ); } }
00680 
00681         // Main iteration loop for the singular values.
00682         iPP = iP - 1;
00683         while( iP ) {
00684             // Here is where a test for too many iterations would go.
00685             // This section of the program inspects for
00686             // negligible elements in the s and e arrays.  On
00687             // completion the variables kase and k are set as follows.
00688             for( iMarker = ( iP - 2 ); iMarker >= 0; --iMarker )
00689                 if( fabs( vecE[ iMarker ] ) <= ( std::numeric_limits<tType>::epsilon( ) *
00690                     ( fabs( vecS[ iMarker ] ) + fabs( vecS[ iMarker + 1 ] ) ) ) ) {
00691                     vecE[ iMarker ] = 0;
00692                     break; }
00693             if( iMarker == ( iP - 2 ) )
00694                 eCase = ESVDConverged;
00695             else {
00696                 int iKS;
00697 
00698                 for( iKS = ( iP - 1 ); iKS > iMarker; --iKS ) {
00699                     tType   T;
00700 
00701                     T = ( ( iKS != iP ) ? fabs( vecE[ iKS ] ) : 0 ) + 
00702                         ( ( iKS != ( iMarker + 1 ) ) ? fabs( vecE[ iKS - 1 ] ) : 0 );
00703                     if( fabs( vecS[ iKS ] ) <= ( std::numeric_limits<tType>::epsilon( ) * T ) ) {
00704                         vecS[ iKS ] = 0;
00705                         break; } }
00706                 if( iKS == iMarker )
00707                     eCase = ESVDSmallE;
00708                 else if( iKS == ( iP - 1 ) )
00709                     eCase = ESVDSmallSE;
00710                 else {
00711                     eCase = ESVDSmallS;
00712                     iMarker = iKS; } }
00713             iMarker++;
00714 
00715         switch( eCase ) {
00716             // Deflate negligible s(p).
00717             case ESVDSmallSE:
00718                 F = vecE[ iP - 2 ];
00719                 vecE[ iP - 2 ] = 0;
00720                 for( int iTmp = ( iP - 2 ); iTmp >= iMarker; --iTmp ) {
00721                     tType   T, CS, SN;
00722 
00723                     T = Hypotenuse( vecS[ iTmp ], F );
00724                     CS = vecS[ iTmp ] / T;
00725                     SN = F / T;
00726                     vecS[ iTmp ] = T;
00727                     if( iTmp != iMarker ) {
00728                         F = -SN * vecE[ iTmp - 1 ];
00729                         vecE[ iTmp - 1 ] = CS * vecE[ iTmp - 1 ]; }
00730                     if( fV )
00731                         for( i = 0; i < GetColumns( ); ++i ) {
00732                             T = ( CS * MatV.Get( i, iTmp ) ) + ( SN * MatV.Get( i, iP - 1 ) );
00733                             MatV.Set( i, iP - 1, ( -SN * MatV.Get( i, iTmp ) ) +
00734                                 ( CS * MatV.Get( i, iP - 1 ) ) );
00735                             MatV.Set( i, iTmp, T ); } }
00736                 break;
00737 
00738             // Split at negligible s(k).
00739             case ESVDSmallS:
00740                 F = vecE[ iMarker - 1 ];
00741                 vecE[ iMarker - 1 ] = 0;
00742                 for( j = iMarker; (int)j < iP; ++j ) {
00743                     tType   T, CS, SN;
00744 
00745                     T = Hypotenuse( vecS[ j ], F );
00746                     CS = vecS[ j ] / T;
00747                     SN = F / T;
00748                     vecS[ j ] = T;
00749                     F = -SN * vecE[ j ];
00750                     vecE[ j ] *= CS;
00751                     if( fU )
00752                         for( i = 0; i < GetRows( ); ++i ) {
00753                             T = ( CS * MatU.Get( i, j ) ) + ( SN * MatU.Get( i, iMarker - 1 ) );
00754                             MatU.Set( i, iMarker - 1, ( -SN * MatU.Get( i, j ) ) +
00755                                 ( CS * MatU.Get( i, iMarker - 1 ) ) );
00756                             MatU.Set( i, j, T ); } }
00757                 break;
00758 
00759             // Perform one qr step.
00760             case ESVDSmallE:
00761                 // Calculate the shift.
00762                 tType   Scale, SP, SPM1, EPM1, SK, EK, B, C, Shift, G;
00763 
00764                 Scale = Max( fabs( vecS[ iP - 1 ] ), fabs( vecS[ iP - 2 ] ), fabs( vecE[ iP - 2 ] ),
00765                     fabs( vecS[ iMarker ] ), fabs( vecE[ iMarker ] ) );
00766                 SP = vecS[ iP - 1 ] / Scale;
00767                 SPM1 = vecS[ iP - 2 ] / Scale;
00768                 EPM1 = vecE[ iP - 2 ] / Scale;
00769                 SK = vecS[ iMarker ] / Scale;
00770                 EK = vecE[ iMarker ] / Scale;
00771                 B = ( ( ( SPM1 + SP ) * ( SPM1 - SP ) ) + ( EPM1 * EPM1 ) ) / 2;
00772                 C = SP * SP * EPM1 * EPM1;
00773                 Shift = 0;
00774                 if( B || C ) {
00775                     Shift = sqrt( ( B * B ) + C );
00776                     if( B < 0 )
00777                         Shift *= -1;
00778                     Shift = C / ( B + Shift ); }
00779                 F = ( ( SK + SP ) * ( SK - SP ) ) + Shift;
00780                 G = SK * EK;
00781 
00782                 // Chase zeros.
00783                 for( j = iMarker; (int)( j + 1 ) < iP; ++j ) {
00784                     tType   T, CS, SN;
00785 
00786                     T = Hypotenuse( F, G );
00787                     CS = F / T;
00788                     SN = G / T;
00789                     if( j != iMarker )
00790                         vecE[ j - 1 ] = T;
00791                     F = ( CS * vecS[ j ] ) + ( SN * vecE[ j ] );
00792                     vecE[ j ] = ( CS * vecE[ j ] ) - ( SN * vecS[ j ] );
00793                     G = SN * vecS[ j + 1 ];
00794                     vecS[ j + 1 ] = CS * vecS[ j + 1 ];
00795                     if( fV )
00796                         for( i = 0; i < GetColumns( ); ++i ) {
00797                             T = ( CS * MatV.Get( i, j ) ) + ( SN * MatV.Get( i, j + 1 ) );
00798                             MatV.Set( i, j + 1, ( -SN * MatV.Get( i, j ) ) + ( CS * MatV.Get( i, j + 1 ) ) );
00799                             MatV.Set( i, j, T ); }
00800                     T = Hypotenuse( F, G );
00801                     CS = F / T;
00802                     SN = G / T;
00803                     vecS[ j ] = T;
00804                     F = ( CS * vecE[ j ] ) + ( SN * vecS[ j + 1 ] );
00805                     vecS[ j + 1 ] = ( -SN * vecE[ j ] ) + ( CS * vecS[ j + 1 ] );
00806                     G = SN * vecE[ j + 1 ];
00807                     vecE[ j + 1 ] = CS * vecE[ j + 1 ];
00808                     if( fU && ( ( j + 1 ) < GetRows( ) ) )
00809                         for( i = 0; i < GetRows( ); ++i ) {
00810                             T = ( CS * MatU.Get( i, j ) ) + ( SN * MatU.Get( i, j + 1 ) );
00811                             MatU.Set( i, j + 1, ( -SN * MatU.Get( i, j ) ) + ( CS * MatU.Get( i, j + 1 ) ) );
00812                             MatU.Set( i, j, T ); } }
00813                 vecE[ iP - 2 ] = F;
00814                 break;
00815 
00816             // Convergence.
00817             case ESVDConverged:
00818                 // Make the singular values positive.
00819                 if( vecS[ iMarker ] < 0 ) {
00820                     vecS[ iMarker ] = ( vecS[ iMarker ] < 0 ) ? -vecS[ iMarker ] : 0;
00821                     if( fV )
00822                         for( i = 0; (int)i <= iPP; ++i )
00823                             MatV.Get( i, iMarker ) *= -1; }
00824 
00825                 // Order the singular values.
00826                 while( iMarker < iPP ) {
00827                     tType   T;
00828 
00829                     if( vecS[ iMarker ] >= vecS[ iMarker + 1 ] )
00830                         break;
00831                     std::swap( vecS[ iMarker ], vecS[ iMarker + 1 ] );
00832                     if( fV && ( ( iMarker + 1 ) < (int)GetColumns( ) ) )
00833                         for( i = 0; i < GetColumns( ); ++i ) {
00834                             T = MatV.Get( i, iMarker + 1 );
00835                             MatV.Set( i, iMarker + 1, MatV.Get( i, iMarker ) );
00836                             MatV.Set( i, k, T ); }
00837                     if( fU && ( ( iMarker + 1 ) < (int)GetRows( ) ) )
00838                         for( i = 0; i < GetRows( ); ++i ) {
00839                             T = MatU.Get( i, iMarker + 1 );
00840                             MatU.Set( i, iMarker + 1, MatU.Get( i, iMarker ) );
00841                             MatU.Set( i, iMarker, T ); }
00842                     iMarker++; }
00843                 iP--;
00844                 break; } }
00845 
00846         return true; }
00847 
00848 private:
00849     static const size_t c_iBuffer   = 131072;
00850 
00851     enum ESVD {
00852         ESVDSmallSE,    // s(p) and e[k-1] are negligible and k<p
00853         ESVDSmallS,     // s(k) is negligible and k<p
00854         ESVDSmallE,     // e[k-1] is negligible, k<p, s(k), ..., s(p) are not negligible (qr step)
00855         ESVDConverged   // e(p-1) is negligible (convergence).
00856     };
00857 
00858     static tType Max( const tType& A, const tType& B, const tType& C, const tType& D, const tType& E ) {
00859 
00860         return max( A, max( B, max( C, max( D, E ) ) ) ); }
00861 
00862     static tType Hypotenuse( const tType& A, const tType& B ) {
00863 
00864         return sqrt( ( A * A ) + ( B * B ) ); }
00865 
00866     bool OpenBinary( std::istream& istm ) {
00867         size_t      i;
00868         uint32_t    iSize;
00869 
00870         Reset( );
00871         if( !istm.good( ) || istm.eof( ) )
00872             return false;
00873         istm.read( (char*)&iSize, sizeof(iSize) );
00874         m_iR = iSize;
00875         istm.read( (char*)&iSize, sizeof(iSize) );
00876         m_iC = iSize;
00877         m_fMemory = true;
00878         m_aaData = new tType*[ GetRows( ) ];
00879         for( i = 0; i < GetRows( ); ++i ) {
00880             m_aaData[ i ] = new tType[ GetColumns( ) ];
00881             istm.read( (char*)m_aaData[ i ], (std::streamsize)( sizeof(*m_aaData[ i ]) * GetColumns( ) ) ); }
00882 
00883         return true; }
00884 
00885     bool OpenText( std::istream& istm ) {
00886         char                szLine[ c_iBuffer ];
00887         std::vector<tType>  vecRow;
00888         std::vector<tType*> vecpRows;
00889         std::stringstream   sstm;
00890         tType               Cur;
00891         tType*              aCur;
00892         size_t              i;
00893 
00894         Reset( );
00895         m_fMemory = true;
00896         while( istm.peek( ) != EOF ) {
00897             istm.getline( szLine, c_iBuffer - 1 );
00898             if( !szLine[ 0 ] )
00899                 break;
00900             sstm.clear( );
00901             sstm.str( szLine );
00902             vecRow.clear( );
00903             while( sstm.peek( ) != EOF ) {
00904                 sstm >> Cur;
00905                 vecRow.push_back( Cur ); }
00906             if( !GetColumns( ) )
00907                 m_iC = vecRow.size( );
00908             else if( GetColumns( ) != vecRow.size( ) )
00909                 return false;
00910 
00911             aCur = new tType[ GetColumns( ) ];
00912             for( i = 0; i < GetColumns( ); ++i )
00913                 aCur[ i ] = vecRow[ i ];
00914             vecpRows.push_back( aCur ); }
00915 
00916         m_aaData = new tType*[ m_iR = vecpRows.size( ) ];
00917         for( i = 0; i < GetRows( ); ++i )
00918             m_aaData[ i ] = vecpRows[ i ];
00919 
00920         return true; }
00921 
00922     bool SaveBinary( std::ostream& ostm ) const {
00923         size_t      i;
00924         uint32_t    iSize;
00925 
00926         iSize = (uint32_t)GetRows( );
00927         ostm.write( (const char*)&iSize, sizeof(iSize) );
00928         iSize = (uint32_t)GetColumns( );
00929         ostm.write( (const char*)&iSize, sizeof(iSize) );
00930         for( i = 0; i < GetRows( ); ++i )
00931             ostm.write( (const char*)m_aaData[ i ], (std::streamsize)( sizeof(*m_aaData[ i ]) *
00932                 GetColumns( ) ) );
00933 
00934         return true; }
00935 
00936     bool SaveText( std::ostream& ostm ) const {
00937         size_t  i, j;
00938 
00939         if( !( GetRows( ) && GetColumns( ) ) )
00940             return false;
00941 
00942         for( i = 0; i < GetRows( ); ++i ) {
00943             ostm << m_aaData[ i ][ 0 ];
00944             for( j = 1; j < GetColumns( ); ++j )
00945                 ostm << '\t' << m_aaData[ i ][ j ];
00946             ostm << std::endl; }
00947 
00948         return true; }
00949 
00950     size_t  m_iR;
00951     size_t  m_iC;
00952     bool    m_fMemory;
00953     tType** m_aaData;
00954 };
00955 
00960 typedef CFullMatrix<float>  CDataMatrix;
00961 
00962 }
00963 
00964 #endif // FULLMATRIX_H