include/matrixdata.h

Go to the documentation of this file.
00001 /********************************************************************************
00002  *  Neural Network Framework.                                                   *
00003  *  Copyright (C) 2005-2008 Gianluca Massera <emmegian@yahoo.it>                *
00004  *                                                                              *
00005  *  This program is free software; you can redistribute it and/or modify        *
00006  *  it under the terms of the GNU General Public License as published by        *
00007  *  the Free Software Foundation; either version 2 of the License, or           *
00008  *  (at your option) any later version.                                         *
00009  *                                                                              *
00010  *  This program is distributed in the hope that it will be useful,             *
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of              *
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               *
00013  *  GNU General Public License for more details.                                *
00014  *                                                                              *
00015  *  You should have received a copy of the GNU General Public License           *
00016  *  along with this program; if not, write to the Free Software                 *
00017  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA  *
00018  ********************************************************************************/
00019 
00020 // --- You can't include it directly
00021 #ifndef TYPES_INCLUDES
00022 #error "You can't include matrixdata.h directly; Instead, You have to include types.h"
00023 // --- follow define avoid to get a lot of understandable error !
00024 #define MATRIXDATA_H
00025 #endif
00026 
00027 #ifndef MATRIXDATA_H
00028 #define MATRIXDATA_H
00029 
00034 #include "memutils.h"
00035 #include "vectordata.h"
00036 
00037 
00038 namespace nnfw {
00039 
00046 template<class T, class Vec = VectorData<T> >
00047 class NNFW_TEMPLATE MatrixData : private Observer, private Observable {
00048 public:
00051 
00054     MatrixData( u_int rows, u_int cols )
00055         : Observer(), Observable(), data(rows*cols), rowView(rows) {
00056         data.zeroing();
00057         nrows = rows;
00058         ncols = cols;
00059         tsize = nrows*ncols;
00060         for( u_int i=0; i<nrows; i++ ) {
00061             rowView[i].convertToView( data, i*ncols, (i+1)*ncols );
00062         }
00063         // --- view attributes
00064         view = false;
00065     };
00066 
00080     MatrixData( Vec& src, u_int rstart, u_int rend, u_int rows, u_int cols )
00081         : Observer(), Observable(), data(src, rstart, rend), rowView() {
00082         // --- Check the validity of dimensions
00083         if ( data.size() != rows*cols ) {
00084             nError() << "Wrongs dimensions specified in MatrixData view constructor; This MatrixData will be invalidate" ;
00085             rows = 0;
00086             cols = 0;
00087         }
00088         // --- view constructing
00089         view = true;
00090         // the local variable data is observed by this object
00091         data.addObserver( this );
00092         nrows = rows;
00093         ncols = cols;
00094         tsize = nrows*ncols;
00095         rowView.resize( tsize );
00096         for( u_int i=0; i<nrows; i++ ) {
00097             rowView[i].convertToView( data, i*ncols, (i+1)*ncols );
00098         }
00099     };
00100 
00103     ~MatrixData() {
00104         // --- nothing to do
00105     };
00106 
00108 
00110 
00112     u_int rows() const {
00113         return nrows;
00114     };
00116     u_int cols() const {
00117         return ncols;
00118     };
00120     u_int size() const {
00121         return tsize;
00122     };
00123 
00126     bool isView() const {
00127         return view;
00128     };
00129 
00132     bool operator==( const MatrixData<T,Vec>& b ) {
00133         // --- WARNING: don't implement this method using the operator== of private data vector
00134         // ---    perche' se la MatrixData e' una view, dopo un resizing sbagliato del vettore origine
00135         // ---    potrebbe rimanere una inconsistenza critica nei dati
00136         if ( this->size() != b.size() ) return false;
00137         for( u_int i=0; i<size(); i++ ) {
00138             if ( this->data[i] != b.data[i] ) {
00139                 return false;
00140             }
00141         }
00142         return true;
00143     };
00144 
00147     bool operator!=( const VectorData<T>& b ) {
00148         return !( *this == b );
00149     };
00150 
00152     void resize( u_int rows, u_int cols ) {
00153         if ( view ) {
00154             nError() << "you can't resize a MatrixData view - use setView instead" ;
00155             return;
00156         }
00157         nrows = rows;
00158         ncols = cols;
00159         tsize = nrows*ncols;
00160         data.resize( tsize );
00161         rowView.resize( nrows );
00162         // --- Adjust the view of rows
00163         for( u_int i=0; i<nrows; i++ ) {
00164             if ( rowView[i].isView() ) {
00165                 rowView[i].setView( i*ncols, (i+1)*ncols );
00166             } else {
00167                 rowView[i].convertToView( data, i*ncols, (i+1)*ncols );
00168             }
00169         }
00170         // --- Notify the viewers
00171         // at this time, the notification has been launched by data.resize calling
00172         // the following methods will make sense only when Matrix-to-Matrix view will be implemented
00173         //notifyAll( NotifyEvent( datachanged ) );
00174     };
00175 
00177 
00179 
00181     T& at( u_int row, u_int col ) {
00182 #ifdef NNFW_DEBUG
00183         if ( row >= nrows ) {
00184             nError() << "Accessing an element beyond Row boundary of matrix" ;
00185             return data[0];
00186         }
00187         if ( col >= ncols ) {
00188             nError() << "Accessing an element beyond Column boundary of matrix" ;
00189             return data[0];
00190         }
00191 #endif
00192         return rowView[row][col];
00193     };
00194 
00196     const T& at( u_int row, u_int col ) const {
00197 #ifdef NNFW_DEBUG
00198         if ( row >= nrows ) {
00199             nError() << "Accessing an element beyond Row boundary of matrix" ;
00200             return data[0];
00201         }
00202         if ( col >= ncols ) {
00203             nError() << "Accessing an element beyond Column boundary of matrix" ;
00204             return data[0];
00205         }
00206 #endif
00207         return rowView[row][col];
00208     };
00209 
00213     Vec& operator[]( u_int row ) {
00214 #ifdef NNFW_DEBUG
00215         if( row >= nrows ) {
00216             nError() << "Accessing elements outside boundary" ;
00217             return rowView[0];
00218         }
00219 #endif
00220         return rowView[row];
00221     };
00222 
00226     const Vec& operator[]( u_int row ) const {
00227 #ifdef NNFW_DEBUG
00228         if( row >= nrows ) {
00229             nError() << "Accessing elements outside boundary" ;
00230             return rowView[0];
00231         }
00232 #endif
00233         return rowView[row];
00234     };
00235 
00238     MatrixData& assign( const MatrixData& src ) {
00239 #ifdef NNFW_DEBUG
00240         if( rows() != src.rows() || cols() != src.cols() ) {
00241             nError() << "Different dimension" ;
00242             return (*this);
00243         }
00244 #endif
00245         data.assign( src.data, tsize );
00246         return (*this);
00247     };
00248 
00251     void zeroing() {
00252         data.zeroing();
00253     };
00254 
00255 
00257 
00259 
00260     class matrixdataIterator;
00261     friend class matrixdataIterator;
00262 
00264     typedef T value_type;
00266     typedef T& reference;
00268     typedef const T& const_reference;
00270     typedef matrixdataIterator iterator;
00272     typedef const matrixdataIterator const_iterator;
00274     typedef size_t size_type;
00276     typedef ptrdiff_t difference_type;
00277 
00280     size_type max_size() {
00281         return 300000; // <- FIXME it must return the maximum space of memory allocable
00282     };
00283 
00286     bool empty() {
00287         return (tsize==0);
00288     };
00289 
00292     void clear() {
00293         if ( view ) {
00294             nError() << "you can't clear a MatrixData view" ;
00295         } else {
00296             resize( 0, 0 );
00297         }
00298     };
00299 
00302     iterator begin() {
00303         return matrixdataIterator( *this );
00304     };
00307     const_iterator begin() const {
00308         return matrixdataIterator( ((MatrixData&)*this) );
00309     };
00310 
00313     iterator end() {
00314         return matrixdataIterator( *this, tsize );
00315     };
00318     const_iterator end() const {
00319         return matrixdataIterator( ((MatrixData&)*this), tsize );
00320     };
00321 
00324     class matrixdataIterator : public std::iterator<std::bidirectional_iterator_tag,T,ptrdiff_t> {
00325     public:
00327         matrixdataIterator( MatrixData& data, u_int startId = 0 ) : vecdata(data.data), id(startId), tsize(data.tsize) { /*nothing to do*/ };
00329         matrixdataIterator( const matrixdataIterator& src ) : vecdata(src.vecdata), id(src.id), tsize(src.tsize) { /* nothing to do */  };
00331         matrixdataIterator& operator=( const matrixdataIterator& src ) {
00332             vecdata = src.vecdata;
00333             id = src.id;
00334             tsize = src.tsize;
00335             return (*this);
00336         };
00338         bool operator==( const matrixdataIterator& x ) const {
00339             return ( &vecdata == &(x.vecdata) && id == x.id );
00340         };
00342         bool operator!=( const matrixdataIterator& x ) const {
00343             return ( &vecdata != &(x.vecdata) || id != x.id );
00344         };
00346         const T& operator*() const {
00347             return vecdata[id];
00348         };
00350         T& operator*() {
00351             return vecdata[id];
00352         };
00354         matrixdataIterator& operator++() {
00355             id = (id < tsize) ? id+1 : tsize;
00356             return (*this);
00357         };
00359         const matrixdataIterator& operator++() const {
00360             id = (id < tsize) ? id+1 : tsize;
00361             return (*this);
00362         };
00364         matrixdataIterator& operator--() {
00365             id = ( id > 0 ) ? id-1 : 0;
00366             return (*this);
00367         };
00369         const matrixdataIterator& operator--() const {
00370             id = ( id > 0 ) ? id-1 : 0;
00371             return (*this);
00372         };
00374         u_int getIndex() {
00375             return id;
00376         };
00377     private:
00379         Vec& vecdata;
00381         u_int id;
00383         u_int tsize;
00384     };
00386 
00387 protected:
00388     friend class RealVec;
00389 
00392     Vec& rawdata() const {
00393         return (Vec&)data;
00394     };
00395 
00396 private:
00398     u_int nrows;
00400     u_int ncols;
00402     u_int tsize;
00404     Vec data;
00406     VectorData< Vec > rowView;
00407 
00409     bool view;
00410 
00412     virtual void notify( const NotifyEvent& event ) {
00413         switch( event.type() ) {
00414         case Vec::datachanged:
00415 #ifdef NNFW_DEBUG
00416             nWarning() << "Arrange a MatrixData view after a VectorData resizing can lead to inconsistent settings - see documentation if you not sure" ;
00417 #endif
00418             ncols = data.size() / nrows ;
00419             if ( ncols == 0 ) {
00420                 nrows = 0;
00421                 ncols = 0;
00422                 tsize = 0;
00423                 rowView.clear();
00424             } else {
00425                 tsize = ncols*nrows;
00426                 // --- Adjust the view of rows
00427                 for( u_int i=0; i<nrows; i++ ) {
00428                     rowView[i].setView( i*ncols, (i+1)*ncols );
00429                 }
00430             }
00431             break;
00432         case Vec::datadestroying:
00433 #ifdef NNFW_DEBUG
00434             nWarning() << "Destroying a VectorData before its views!!!" ;
00435 #endif
00436             // --- reconvert to a regular MatrixData with size zero
00437             view = false;
00438             nrows = 0;
00439             ncols = 0;
00440             tsize = 0;
00441             rowView.clear();
00442             break;
00443         default:
00444             break;
00445         }
00446         // --- Propagate Notify to sub-viewers
00447         // --- Inutile fino a che non si implementano le viste tra Matrici
00448         //notifyAll( matdatachanged );
00449     };
00450 
00452     MatrixData( const MatrixData& src )
00453         : Observer(), Observable(), data(0), rowView(0) {
00454     };
00455 
00456 };
00457 
00458 }
00459 
00460 #endif
00461 
BerliOS Developer Logo Valid XHTML 1.0 Transitional Valid CSS!