Sleipnir
src/compactmatrixi.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 COMPACTMATRIXI_H
00023 #define COMPACTMATRIXI_H
00024 
00025 //may need to enable the following lines for Cygwin compilation
00026 //#ifndef SIZE_MAX
00027 //#define SIZE_MAX (4294967295U) //assumes 32bit GCC
00028 //#endif
00029 
00030 #include "halfmatrixi.h"
00031 
00032 namespace Sleipnir {
00033 
00034 class CCompactMatrixBase {
00035 protected:
00036     CCompactMatrixBase( ) : m_cBits(0), m_aiData(NULL), m_fMemory(true) { }
00037 
00038     ~CCompactMatrixBase( ) {
00039 
00040         if( m_fMemory && m_aiData )
00041             delete[] m_aiData; }
00042 
00043     void Initialize( unsigned char, bool );
00044 
00045     unsigned char Get( size_t iX, size_t iY ) const {
00046         size_t*         pi;
00047         unsigned char   cRet, cShift;
00048 
00049         if( !( m_cBits && m_aiData ) )
00050             return 0;
00051         pi = GetWord( iX, iY, cShift );
00052         // Bits starting at Shift, mask m_cBits long
00053         cRet = (unsigned char)( ( *pi >> cShift ) & ( SIZE_MAX >> ( ( 8 * sizeof(*m_aiData) ) - m_cBits ) ) );
00054         // If we overflow a boundary...
00055         if( ( cShift + m_cBits ) > ( 8 * sizeof(*m_aiData) ) )
00056         // Bits starting at 0, mask (m_cBits-Shift) long, shift left by bits we got
00057             cRet |= ( *( pi + 1 ) & ( SIZE_MAX >> ( ( 16 * sizeof(*m_aiData) ) - m_cBits -
00058                 cShift ) ) ) << ( ( 8 * sizeof(*m_aiData) ) - cShift );
00059 
00060         return cRet;
00061     }
00062 
00063     void Set( size_t iX, size_t iY, unsigned char cValue ) {
00064         unsigned char   cShift;
00065         size_t          iMask;
00066         size_t*         pi;
00067 
00068         if( !( m_cBits && m_aiData ) )
00069             return;
00070         pi = GetWord( iX, iY, cShift );
00071         iMask = ( SIZE_MAX >> ( ( 8 * sizeof(*m_aiData) ) - m_cBits ) ) << cShift;
00072         *pi = ( *pi & ~iMask ) | ( ( (size_t)cValue << cShift ) & iMask );
00073         if( ( cShift + m_cBits ) > ( 8 * sizeof(*m_aiData) ) ) {
00074             pi++;
00075             iMask = SIZE_MAX >> ( ( 16 * sizeof(*m_aiData) ) - m_cBits - cShift );
00076             *pi = ( *pi & ~iMask ) |
00077                 ( ( cValue >> ( ( 8 * sizeof(*m_aiData) ) - cShift ) ) & iMask );
00078         }
00079     }
00080 
00081     virtual size_t CountWords( ) const = 0;
00082     virtual size_t* GetWord( size_t, size_t, unsigned char& ) const = 0;
00083 
00084     bool            m_fMemory;
00085     unsigned char   m_cBits;
00086     size_t*         m_aiData;
00087 };
00088 
00089 class CCompactMatrixImpl : protected CHalfMatrixBase, protected CCompactMatrixBase {
00090 protected:
00091     CCompactMatrixImpl( ) : m_iSize(0) { }
00092 
00093     size_t* GetWord( size_t iX, size_t iY, unsigned char& cShift ) const {
00094         size_t  iIndex;
00095 
00096         // Closed form for sum(m_iSize - i - 1, i=0..(iX-1)) + iY
00097         iIndex = ( iX * ( m_iSize - 1 ) ) - ( iX * ( iX - 1 ) / 2 ) + iY;
00098         iIndex *= m_cBits;
00099         cShift = (unsigned char)( iIndex % ( 8 * sizeof(*m_aiData) ) );
00100         iIndex /= 8 * sizeof(*m_aiData);
00101 
00102         return &m_aiData[ iIndex ]; }
00103 
00104     size_t CountWords( ) const {
00105         size_t  iRet;
00106 
00107         return ( ( m_cBits && ( iRet = m_iSize * ( m_iSize - 1 ) / 2 ) ) ?
00108             ( ( ( ( iRet * m_cBits ) - 1 ) / ( 8 * sizeof(*m_aiData) ) ) + 1 ) : 0 ); }
00109 
00110     uint32_t    m_iSize;
00111 };
00112 
00113 class CCompactFullMatrixImpl : protected CCompactMatrixBase {
00114 protected:
00115     CCompactFullMatrixImpl( ) : m_iRows(0), m_iColumns(0) { }
00116 
00117     size_t CountWords( ) const {
00118         size_t  iRet;
00119         iRet = m_iRows * m_iColumns;
00120         return ( ( ( ( iRet * m_cBits ) - 1 ) / ( 8 * sizeof(*m_aiData) ) ) + 1 );
00121     }
00122 
00123     size_t* GetWord( size_t iY, size_t iX, unsigned char& cShift ) const {
00124         size_t  iIndex;
00125 
00126         iIndex = ( ( iY * m_iColumns ) + iX ) * m_cBits;
00127         cShift = (unsigned char)( iIndex % ( 8 * sizeof(*m_aiData) ) );
00128         iIndex /= 8 * sizeof(*m_aiData);
00129 
00130         return &m_aiData[ iIndex ]; }
00131 
00132     uint32_t    m_iRows;
00133     uint32_t    m_iColumns;
00134 };
00135 
00136 }
00137 
00138 #endif // COMPACTMATRIXI_H