Main Page | Class List | File List | Class Members

CS_ZZ_ICRS.hpp

00001 
00002 //#define _DEBUG
00003 
00004 #ifndef _H_CS_ZZ_ICRS
00005 #define _H_CS_ZZ_ICRS
00006 
00007 #include "Triplet.hpp"
00008 #include <vector>
00009 #include <algorithm>
00010 
00011 #include "CS_ELEMENT.hpp"
00012 #include "CS_ARRAY.hpp"
00013 
00014 //#_UNSIGNED
00015 
00016 #ifdef _DEBUG
00017 #include<iostream>
00018 #endif
00019 
00023 template< typename T >
00024 class CS_ZZ_ICRS {
00025 
00026   private:
00027 
00028 #ifdef _UNSIGNED
00029 
00030         typedef unsigned long int ULI;
00031 #else
00032 
00033         typedef long int ULI;
00034 #endif
00035 
00036   protected:
00037 
00039         CS_ELEMENT< ULI > nnz;
00040 
00042         CS_ELEMENT< ULI > nor;
00043 
00045         CS_ELEMENT< ULI > noc;
00046 
00048         CS_ARRAY< T >* nzs;
00049 
00051         CS_ARRAY< ULI >* c_ind;
00052 
00054         CS_ARRAY< ULI >* r_ind;
00055 
00057         CS_ELEMENT< T > zero_element;
00058 
00060         static bool compareTriplets( const Triplet< T >& one, const Triplet< T >& two ) {
00061                 if( one.i() < two.i() )
00062                         return true;
00063                 if ( one.i() > two.i() )
00064                         return false;
00065                 return one.j() < two.j();
00066         }
00067 
00068   public:
00069 
00079         CS_ZZ_ICRS( const ULI number_of_nonzeros, const ULI number_of_rows, const ULI number_of_cols, T zero ):
00080                 nnz( number_of_nonzeros ), noc( number_of_cols ), nor( number_of_rows ), zero_element( zero ) {
00081                 nzs = new CS_ARRAY< T >( nnz, "Nonzeros array( CS_ZZ_ICRS )" );
00082                 c_ind = new CS_ARRAY< ULI >( nnz.unrecorded_access(), "Array storing the column index differences (CS_ZZ_ICRS)" );
00083                 r_ind = new CS_ARRAY< ULI >( nnz.unrecorded_access(), "Array storing the row index differences (CS_ZZ_ICRS)" );
00084         }
00085 
00090         CS_ZZ_ICRS( CS_ZZ_ICRS< T >& toCopy ) {
00091                 zero_element = toCopy.zero_element;
00092                 nnz = toCopy.nnz;
00093                 noc = toCopy.noc;
00094                 nor = toCopy.nor;
00095                 nzs = new CS_ARRAY< T >( nnz, "Nonzeros array( CS_ZZ_ICRS, copied )" );
00096                 c_ind = new CS_ARRAY< T >( nnz, "Array storing the column index differences (CS_ZZ_ICRS, copied )" );
00097                 r_ind = new CS_ARRAY< T >( nnz, "Array storing the row index differences (CS_ZZ_ICRS, copied )" );
00098                 for( CS_ELEMENT< ULI > i=0; i<nnz; i = i + 1 ) {
00099                         nzs->access( i.const_access() ) = toCopy.nzs->const_access( i.const_access() );
00100                         c_ind->access( i.const_access() ) = toCopy.c_ind->const_access( i.const_access() );
00101                         r_ind->access( i.const_access() ) = toCopy.r_ind->const_access( i.const_access() );
00102                 }
00103         }
00104 
00115         CS_ZZ_ICRS( std::vector< Triplet< T > >& input, const ULI m, const ULI n, const T zero ) {
00116                 zero_element = zero;
00117 
00118                 nor = m;
00119                 noc = n;
00120         
00121                 typename std::vector< Triplet< T > >::iterator in_it;
00122 
00123                 //WARNING: noc*nor typically overflows on 32 bits!
00124                 //         immediately start recording differences
00125                 //         instead of trying to directly calculate
00126                 //         the index as i*noc+j.
00127         
00128                 sort( input.begin(), input.end(), compareTriplets );
00129 
00130                 //analyse the number of row jumps
00131                 unsigned long int prev_row = 0;
00132                 std::vector< ULI > r_ind_temp;
00133                 typename std::vector< Triplet< T > >::iterator it = input.begin();
00134                 for( ; it!=input.end(); it++ ) {
00135                         if( (*it).i() > prev_row ) {
00136                                 r_ind_temp.push_back( (*it).i() - prev_row );
00137                                 prev_row = (*it).i();
00138                         }
00139                 }
00140                 nnz = input.size();
00141 
00142                 //allocate arrays
00143                 nzs = new CS_ARRAY< T>( nnz.const_access(), "Array of nonzeros (CS_ZZ_ICRS)" );
00144                 c_ind = new CS_ARRAY< ULI >( nnz.const_access() + 1, "Array of column index differences (CS_ZZ_ICRS)" );
00145                 r_ind = new CS_ARRAY< ULI >( r_ind_temp.size() + 1, "Array of row index differences (CS_ZZ_ICRS)" );
00146 
00147                 //set last entry
00148                 c_ind->access( nnz.const_access() ) = noc.const_access();
00149                 //r_ind does not have to be set; altough the last element is read, it is actually never used.
00150 
00151                 //copy row-jump vector
00152                 for( unsigned long int i=0; i<r_ind_temp.size(); i++ )
00153                         r_ind->access( i ) = r_ind_temp[ i ];
00154 
00155                 //make ZZ-ICRS
00156                 ULI prev_col = 0;
00157                 prev_row = 0;
00158 
00159                 for( ULI i=0; i<nnz.const_access(); ++i ) {
00160                         const Triplet< T > cur = input[ i ];
00161                         const unsigned long int currow = cur.i();
00162                         const unsigned long int curcol = cur.j();
00163                         if( currow == prev_row ) {
00164                                 c_ind->access( i ) = curcol - prev_col;
00165 #ifdef _DEBUG
00166                                 std::cout << "1. c_ind[ " << i << " ] = " << c_ind->access( i ) << " = " << curcol << " - " << prev_col << ":\t\t " << currow << "," << curcol << std::endl;
00167 #endif
00168                                 nzs->access( i ) = cur.value;
00169                                 prev_col = curcol;
00170                         } else {
00171                                 //reverse = !reverse;
00172                                 prev_row = currow;
00173                                 ULI stop = i;
00174                                 ULI j = i;
00175                                 
00176                                 while( j < nnz.const_access() && input[ j ].i() == currow )
00177                                         j++; //go to next row
00178                                 j--; // j now points at last element at new row
00179 
00180                                 //process the first new element
00181                                 nzs->access( i ) = input[ j ].value;
00182                                 c_ind->access( i ) = noc.const_access() + ( input[ j ].j() - prev_col );
00183                                 prev_col = input[ j ].j();
00184 
00185 #ifdef _DEBUG
00186                                 std::cout << "2. c_ind[ " << i << " ] = " << c_ind->const_access( i ) << " = " << input[ j ].j() << " - " << input[ j-1 ].j() << ":\t\t " << input[ j ].i() << "," << input[ j ].j() << std::endl;
00187 #endif
00188                                 i++; //go to next indices
00189                                 j--;
00190 
00191                                 for( ; j>=stop; j-- ) { //reversively add the rest to data structure
00192                                         nzs->access( i ) = input[ j ].value;
00193                                         c_ind->access( i ) = prev_col - input[ j ].j();
00194                                         prev_col = input[ j ].j();
00195 #ifdef _DEBUG
00196                                         std::cout << "3. c_ind[ " << i << " ] = " << c_ind->const_access( i ) << " = " << input[ j ].j() << " - " << input[ j-1 ].j() << ":\t\t " << input[ j ].i() << "," << input[ j ].j() << std::endl;
00197 #endif
00198                                         i++; //increment target index
00199                                 }
00200 
00201                                 if( i >= nnz.const_access() ) break;
00202 
00203                                 //at this point, the reverse row is completely added
00204                                 //and i should be at the next row index.
00205 #ifdef _UNSIGNED
00206                                 c_ind->access( i ) = noc.const_access() + input[ i ].j();
00207 #else
00208                                 c_ind->access( i ) = noc.const_access() + ( prev_col - input[ i ].j() );
00209 #endif
00210 
00211 #ifdef _DEBUG
00212                                 std::cout << "4. c_ind[ " << i << " ] = " << c_ind->unrecorded_access( i ) << " = " << noc.unrecorded_access() << " + " << input[ i ].j() << " - " << input[ stop ].j() << ":\t\t " << input[ i ].i() << "," << input[ i ].j() << std::endl;
00213 #endif
00214                                 nzs->access( i ) = input[ i ].value;
00215                                 prev_col = input[ i ].j();
00216                                 prev_row = input[ i ].i();
00217                         }
00218                 }
00219         }
00220 
00231         /*T& random_access( const ULI& i, const ULI& j ) {
00232                 return zero_element; //TODO
00233         }*/
00234 
00243         T* zax( T* x_orig ) {
00244 
00245                 CS_ARRAY< T >* x = new CS_ARRAY< T >( noc.unrecorded_access(), "x-vector in CS_ZZ_ICRS::zax" );
00246                 x->unrecordedCopyFrom( x_orig );
00247 
00248                 T* true_ret = new T[ nor.unrecorded_access() ];
00249                 CS_ARRAY< T >* ret = new CS_ARRAY< T >( nor.unrecorded_access(), "z-vector in CS_ZZ_ICRS::zax" );
00250 
00251                 for( ULI i=0; i < nor.unrecorded_access(); ++i )
00252                         ret->access( i ) = zero_element.unrecorded_access();
00253 
00254                 //free variable in terms of cache because of pointer arithmatic
00255                 ULI row_ind_pointer = 0;//ULI* row_ind_pointer = r_ind;
00256                 ULI index = 0;
00257                 ULI row = 0;
00258                 ULI column = c_ind->const_access( 0 ); //ULI* column = c_ind;
00259                 //ULI* c_ind_p = &( c_ind[ 1 ] );
00260 
00261 #ifdef _DEBUG
00262                 std::cout << "nor = " << noc.unrecorded_access() << std::endl; std::cout << "noc = " << noc.unrecorded_access() << std::endl;
00263 #endif
00264 
00265                 while( index < nnz.unrecorded_access() ) {
00266                         while( column < noc.unrecorded_access() ) {
00267 #ifdef _DEBUG
00268                                 std::cout << "ret[ " << row << " ] += nzs[ " << index << " ] * x[ " << column << " ], \t(" << c_ind->unrecorded_access( index + 1 ) << ")" << std::endl;
00269 #endif
00270                                 ret->access( row ) += nzs->const_access( index ) * x->const_access( column );
00271                                 ++index;
00272                                 //*column++ simulation:
00273                                 column += c_ind->const_access( index );
00274                         }
00275 
00276                         if( index >= nnz.unrecorded_access() ) break;
00277 
00278                         //row += *row_ind_pointer++;
00279                         //*row++ simulation:
00280                         row += r_ind->const_access( row_ind_pointer++ );
00281 #ifdef _DEBUG
00282                         std::cout << column.unrecorded_access() << " > " << noc.unrecorded_access() << std::endl;
00283 #endif
00284                         column -= noc.unrecorded_access();
00285 #ifdef _UNSIGNED
00286                         while( column < noc.unrecorded_access() ) {
00287 #else
00288                         while( column >= 0 ) {
00289 #endif
00290 #ifdef _DEBUG
00291                                 std::cout << "ret[ " << row << " ] += nzs[ " << index << " ] * x[ " << column << " ], \t(-" << c_ind->unrecorded_access( index ) << ")" << std::endl;
00292 #endif
00293                                 ret->access( row ) += nzs->const_access( index ) * x->const_access( column ); //*column++
00294                                 ++index;
00295 #ifdef _UNSIGNED
00296                                 if( c_ind->const_access( index ) <= column ) //this takes waaaay too much time. seems unsolvable in unsigned, switch to signed ints
00297 #endif
00298                                         column -= c_ind->const_access( index );//*c_ind_p++;
00299 #ifdef _UNSIGNED
00300                                 else {
00301                                         column = c_ind->const_access( index ) - noc.unrecorded_access();//*c_ind_p++ - noc;
00302                                         break;
00303                                 }
00304                         }
00305 #else
00306                         }
00307 
00308                         column += noc.unrecorded_access();
00309 #endif
00310                         row += r_ind->const_access( row_ind_pointer++ );//*row_ind_pointer++;
00311                 }
00312 
00313                 ret->unrecordedCopyTo( true_ret );
00314                 delete ret;
00315                 delete x;
00316                 return true_ret;
00317         }
00318 
00320         ~CS_ZZ_ICRS() {
00321                 delete nzs;
00322                 delete c_ind;
00323                 delete r_ind;
00324         }
00325 
00326 };
00327 
00328 #endif
00329 

Generated on Fri Aug 15 18:12:22 2008 for Run-timeCacheSimulator by  doxygen 1.3.9.1