Sleipnir
|
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