include/vectordata.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 vectordata.h directly; Instead, You have to include types.h"
00023 // --- follow define avoid to get a lot of understandable error !
00024 #define VECTORDATA_H
00025 #endif
00026 
00027 #ifndef VECTORDATA_H
00028 #define VECTORDATA_H
00029 
00037 #include "memutils.h"
00038 #include <vector>
00039 
00040 
00041 namespace nnfw {
00042 
00049 template<class T>
00050 class NNFW_TEMPLATE VectorData : private Observer, public Observable {
00051 public:
00053     typedef enum { datachanged = 1, datadestroying = 2 } t_notify;
00054 
00057 
00059     VectorData()
00060         : Observer(), Observable() {
00061         vsize = 0;
00062         allocated = 0;
00063         data = 0;
00064         view = false;
00065         observed = 0;
00066         idstart = 0;
00067         idend = 0;
00068     };
00069 
00071     VectorData( u_int size ) 
00072         : Observer(), Observable() {
00073         vsize = size;
00074         allocated = size;
00075         if ( vsize == 0 ) {
00076             data = 0;
00077         } else {
00078             data = new T[vsize];
00079             memoryZeroing( data, vsize );
00080         }
00081         // --- view attribute
00082         view = false;
00083         observed = 0;
00084         idstart = 0;
00085         idend = 0;
00086     };
00087 
00089     VectorData( u_int size, T& value )
00090         : Observer(), Observable() {
00091         vsize = size;
00092         allocated = size;
00093         (vsize==0) ? (data = 0) : (data = new T[vsize]);
00094         for(u_int i = 0; i<size; i++) {
00095             data[i] = value;
00096         }
00097         // --- view attribute
00098         view = false;
00099         observed = 0;
00100         idstart = 0;
00101         idend = 0;
00102     };
00103     
00105     VectorData( VectorData<T>& src, u_int idStart, u_int idEnd )
00106         : Observer(), Observable() {
00107         if ( idStart > src.vsize || idEnd > src.vsize || idStart >= idEnd ) {
00108             nError() << "Wrongs indexes specified in VectorData constructor; using 0 and src.size()" ;
00109             idstart = 0;
00110             idend = src.size();
00111         } else {
00112             idstart = idStart;
00113             idend = idEnd;
00114         }
00115         data = (src.data) + idstart;
00116         vsize = idend - idstart;
00117         allocated = 0;
00118         view = true;
00119         src.addObserver( this );
00120         observed = &src;
00121     };
00122 
00124     VectorData( const T* r, u_int dim )
00125         : Observer(), Observable() {
00126         data = new T[dim];
00127         vsize = dim;
00128         allocated = dim;
00129         memoryCopy( data, r, dim );
00130         // --- view attribute
00131         view = false;
00132         observed = 0;
00133         idstart = 0;
00134         idend = 0;
00135     };
00136 
00142     VectorData( const VectorData& src )
00143         : Observer(), Observable() {
00144         /* --- even if the source VectorData is a view,
00145            --- the copy-constructor create a new fresh copy of data */
00146         vsize = src.vsize;
00147         allocated = vsize;
00148         data = new T[allocated];
00149         memoryCopy( data, src.data, vsize );
00150         view = false;
00151         observed = 0;
00152     };
00153 
00160     VectorData& operator=( const VectorData& src ) {
00161         VectorData& self = *this;
00162         self.resize( src.size() );
00163         self.assign( src );
00164         return self;
00165     };
00166 
00169     ~VectorData() {
00170         notifyAll( NotifyEvent( datadestroying ) );
00171         if ( view ) {
00172             observed->delObserver( this );
00173         } else {
00174             delete []data;
00175         }
00176     };
00178 
00180 
00183     u_int size() const {
00184         return vsize;
00185     };
00186 
00189     bool isView() const {
00190         return view;
00191     };
00192 
00195     bool operator==( const VectorData<T>& b ) {
00196         if ( this->size() != b.size() ) return false;
00197         VectorData<T>& self = *this;
00198         for( u_int i=0; i<size(); i++ ) {
00199             if ( self[i] != b[i] ) {
00200                 return false;
00201             }
00202         }
00203         return true;
00204     };
00205 
00208     bool operator!=( const VectorData<T>& b ) {
00209         return !( *this == b );
00210     };
00211 
00213 
00215 
00217     void zeroing() {
00218         memoryZeroing( data, vsize );
00219     };
00220 
00222     void setAll( const T& value ) {
00223         for( u_int i=0; i<vsize; i++ ) {
00224             data[i] = value;
00225         }
00226     };
00227 
00229     void erase( int id ) {
00230         if ( view ) {
00231             nError() << "you can't erase element from a VectorData view" ;
00232         } else {
00233             if ( id < 0 || id >= (int)vsize ) return;
00234             for( u_int i=(u_int)id; i<vsize-1; i++ ) {
00235                 data[id] = data[id+1];
00236             }
00237             vsize = vsize-1;
00238             notifyAll( NotifyEvent( datachanged ) );
00239         }
00240     };
00241 
00243     VectorData<T>& assign( u_int num, const T& value ) {
00244 #ifdef NNFW_DEBUG
00245         if ( num > vsize ) {
00246             nError() << "Wrong number of elements passed to assign method" ;
00247             num = vsize;
00248         }
00249 #endif
00250         for( u_int i=0; i<num; i++ ) {
00251             data[i] = value;
00252         }
00253         return (*this);
00254     };
00255 
00257     VectorData<T>& assign( const VectorData<T>& src ) {
00258 #ifdef NNFW_DEBUG
00259         if ( vsize != src.vsize ) {
00260             nError() << "Wrong number of elements between VectorData to assign method" ;
00261             return (*this);
00262         }
00263 #endif
00264         memoryCopy( data, src.data, vsize );
00265         return (*this);
00266     };
00267 
00271     VectorData<T>& assign( const VectorData<T>& src, u_int sizec ) {
00272 #ifdef NNFW_DEBUG
00273         if ( vsize < sizec || src.size() < sizec ) {
00274             nError() << "Wrong size specified in assign method" ;
00275             return (*this);
00276         }
00277 #endif
00278         memoryCopy( data, src.data, sizec );
00279         return (*this);
00280     };
00281 
00283     VectorData<T>& assign_reverse( const VectorData<T>& src ) {
00284 #ifdef NNFW_DEBUG
00285         if ( vsize != src.vsize ) {
00286             nError() << "Wrong number of elements between VectorData to assign method" ;
00287             return (*this);
00288         }
00289 #endif
00290         for( u_int i=0, j=vsize-1; i<vsize; i++, j-- ) {
00291             data[i] = src.data[j];
00292         }
00293         return (*this);
00294     };
00295 
00304     VectorData<int>& compare( const VectorData<T>& b, VectorData<int>& comparison ) {
00305 #ifdef NNFW_DEBUG
00306         if ( vsize != b.vsize ) {
00307             nError() << "Wrong number of elements between VectorData to compare method" ;
00308             return (*this);
00309         }
00310 #endif
00311         VectorData<T>& self = *this;
00312         comparison.resize(size());
00313         for( u_int i=0; i<size(); i++ ) {
00314             if ( self[i] == b[i] ) {
00315                 comparison[i] = true;
00316             }
00317             else {
00318                 comparison[i] = false;
00319             }
00320         }
00321         return comparison;
00322     };
00323 
00327     T& operator[]( u_int index ) {
00328 #ifdef NNFW_DEBUG
00329         if( index >= vsize ) {
00330             nError() << "Accessing elements outside boundary" ;
00331             return data[0];
00332         }
00333 #endif
00334         return data[index];
00335     };
00336 
00340     const T& operator[]( u_int index ) const {
00341 #ifdef NNFW_DEBUG
00342         if( index >= vsize ) {
00343             nError() << "Accessing elements outside boundary" ;
00344             return data[0];
00345         }
00346 #endif
00347         return data[index];
00348     };
00349 
00353     T& at( u_int index ) {
00354 #ifdef NNFW_DEBUG
00355         if( index >= vsize ) {
00356             nError() << "Accessing elements outside boundary" ;
00357             return data[0];
00358         }
00359 #endif
00360         return data[index];
00361     };
00362 
00366     const T& at( u_int index ) const {
00367 #ifdef NNFW_DEBUG
00368         if( index >= vsize ) {
00369             nError() << "Accessing elements outside boundary" ;
00370             return data[0];
00371         }
00372 #endif
00373         return data[index];
00374     };
00375 
00377     void resize( u_int newsize ) {
00378         if ( view ) {
00379             nError() << "It's not possible resize RealVec views" ;
00380             return;
00381         }
00382         if ( allocated < newsize ) {
00383             if ( allocated == 0 ) {
00384                 allocated = newsize+20;
00385                 data = new T[allocated];
00386             } else {
00387                 allocated = newsize+20;
00388                 T* tmp = new T[allocated];
00389                 memoryCopy( tmp, data, vsize );
00390                 delete []data;
00391                 data = tmp;
00392             }
00393         }
00394         if ( newsize > vsize ) {
00395             memoryZeroing( data+vsize, newsize-vsize );
00396         }
00397         vsize = newsize;
00398         // --- Notify the viewers
00399         notifyAll( NotifyEvent( datachanged ) );
00400     };
00401 
00403     void append( const T& value ) {
00404         resize( vsize+1 );
00405         data[vsize-1] = value;
00406     };
00407 
00409     VectorData<T>& operator<<( const T& value ) {
00410         append( value );
00411         return (*this);
00412     };
00414 
00416 
00420     void setView( u_int idStart, u_int idEnd ) {
00421         if ( !view ) {
00422             nError() << "setView can be called only if VectorData is a view" ;
00423             return;
00424         }
00425         if ( idStart > observed->vsize || idEnd > observed->vsize || idStart >= idEnd ) {
00426             nError() << "Wrongs indexes specified in VectorData setView; using 0 and observed->size()" ;
00427             idstart = 0;
00428             idend = observed->size();
00429         }
00430         idstart = idStart;
00431         idend = idEnd;
00432         data = (observed->data) + idstart;
00433         vsize = idend - idstart;
00434         // --- Propagate Notify to sub-viewers
00435         notifyAll( NotifyEvent( datachanged ) );
00436     };
00437 
00440     void convertToView( VectorData<T>& src, u_int idStart, u_int idEnd ) {
00441         if ( observed == (&src) ) {
00442             setView( idStart, idEnd );
00443             return;
00444         }
00445         if ( view ) {
00446             // detach previous view
00447             observed->delObserver( this );
00448         } else if ( allocated > 0 ) {
00449             // remove previous data allocated
00450             delete []data;
00451         }
00452     
00453         if ( idStart > src.vsize || idEnd > src.vsize || idStart >= idEnd ) {
00454             nError() << "Wrongs indexes specified in convertToView; using 0 and src.size()" ;
00455             idstart = 0;
00456             idend = src.size();
00457         } else {
00458             idstart = idStart;
00459             idend = idEnd;
00460         }
00461         data = (src.data) + idstart;
00462         vsize = idend - idstart;
00463         allocated = 0;
00464         view = true;
00465         observed = &src;
00466         observed->addObserver( this );
00467     };
00468 
00470 
00472 
00473     class vectordataIterator;
00474     friend class vectordataIterator;
00475 
00477     typedef T value_type;
00479     typedef T& reference;
00481     typedef const T& const_reference;
00483     typedef vectordataIterator iterator;
00485     typedef const vectordataIterator const_iterator;
00487     typedef size_t size_type;
00489     typedef ptrdiff_t difference_type;
00490 
00492     size_type max_size() {
00493         return 300000; // <- FIXME it must return the maximum space of memory allocable
00494     };
00495 
00497     bool empty() {
00498         return (vsize==0);
00499     };
00500 
00502     void push_back( const T& value ) {
00503         resize( vsize+1 );
00504         data[vsize-1] = value;
00505     };
00506 
00508     iterator begin() {
00509         return vectordataIterator( *this );
00510     };
00512     const_iterator begin() const {
00513         return vectordataIterator( ((VectorData&)*this) );
00514     };
00515 
00517     iterator end() {
00518         return vectordataIterator( *this, vsize );
00519     };
00521     const_iterator end() const {
00522         return vectordataIterator( ((VectorData&)*this), vsize );
00523     };
00524 
00526     iterator erase( iterator pos ) {
00527         if ( view ) {
00528             nError() << "you can't erase element from a VectorData view" ;
00529         } else {
00530             u_int id = pos.getIndex();
00531             for( u_int i=id; i<vsize-1; i++ ) {
00532                 data[id] = data[id+1];
00533             }
00534             vsize = vsize-1;
00535             notifyAll( NotifyEvent( datachanged ) );
00536         }
00537         return (pos);
00538     };
00539 
00541     void clear() {
00542         if ( view ) {
00543             nError() << "you can't clear a VectorData view" ;
00544         } else {
00545             vsize = 0;
00546             notifyAll( NotifyEvent( datachanged ) );
00547         }
00548     };
00549 
00551     class vectordataIterator : public std::iterator<std::bidirectional_iterator_tag,T,ptrdiff_t> {
00552     public:
00554         vectordataIterator( VectorData& data, u_int startId = 0 ) : vecdata(data), id(startId) { /*nothing to do*/ };
00556         vectordataIterator( const vectordataIterator& src ) : vecdata(src.vecdata), id(src.id) { /* nothing to do */  };
00558         vectordataIterator& operator=( const vectordataIterator& src ) {
00559             vecdata = src.vecdata;
00560             id = src.id;
00561             return (*this);
00562         };
00564         bool operator==( const vectordataIterator& x ) const {
00565             return ( &vecdata == &(x.vecdata) && id == x.id );
00566         };
00568         bool operator!=( const vectordataIterator& x ) const {
00569             return ( &vecdata != &(x.vecdata) || id != x.id );
00570         };
00572         const T& operator*() const {
00573             return vecdata[id];
00574         };
00576         T& operator*() {
00577             return vecdata[id];
00578         };
00580         vectordataIterator& operator++() {
00581             id = (id < vecdata.size()) ? id+1 : vecdata.size();
00582             return (*this);
00583         };
00585         const vectordataIterator& operator++() const {
00586             id = (id < vecdata.size()) ? id+1 : vecdata.size();
00587             return (*this);
00588         };
00590         vectordataIterator& operator--() {
00591             id = ( id > 0 ) ? id-1 : 0;
00592             return (*this);
00593         };
00595         const vectordataIterator& operator--() const {
00596             id = ( id > 0 ) ? id-1 : 0;
00597             return (*this);
00598         };
00600         u_int getIndex() {
00601             return id;
00602         };
00603     private:
00605         VectorData& vecdata;
00607         u_int id;
00608     };
00610 
00611 protected:
00612 
00614     T* rawdata() const {
00615         return data;
00616     };
00617 
00619     u_int vsize;
00621     u_int allocated;
00623     T* data;
00624 
00626     bool view;
00628     u_int idstart;
00630     u_int idend;
00632     VectorData* observed;
00633 
00635     virtual void notify( const NotifyEvent& event ) {
00636         switch( event.type() ) {
00637         case datachanged:
00638             if ( idstart > observed->vsize || idend > observed->vsize ) {
00639                 nError() << "Indexes become invalid after data changing; using 0 and viewed->size()" ;
00640                 idstart = 0;
00641                 idend = observed->size();
00642             }
00643             data = (observed->data) + idstart;
00644             vsize = idend - idstart;
00645             allocated = 0;
00646             break;
00647         case datadestroying:
00648 #ifdef NNFW_DEBUG
00649             nWarning() << "Destroying a VectorData before its views!!!" ;
00650 #endif
00651             // --- reconvert to a regular VectorData with size zero
00652             view = false;
00653             data = 0;
00654             vsize = 0;
00655             allocated = 0;
00656             observed = 0;
00657             idstart = 0;
00658             idend = 0;
00659             break;
00660         default:
00661             break;
00662         }
00663         // --- Propagate Notify to sub-viewers
00664         notifyAll( NotifyEvent( datachanged ) );
00665     };
00666 
00667 };
00668 
00669 }
00670 
00671 #endif
BerliOS Developer Logo Valid XHTML 1.0 Transitional Valid CSS!