PLearn 0.1
TVec_decl.h
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 
00003 // PLearn (A C++ Machine Learning Library)
00004 // Copyright (C) 1998 Pascal Vincent
00005 // Copyright (C) 1999-2002 Pascal Vincent, Yoshua Bengio and University of Montreal
00006 //
00007 
00008 // Redistribution and use in source and binary forms, with or without
00009 // modification, are permitted provided that the following conditions are met:
00010 // 
00011 //  1. Redistributions of source code must retain the above copyright
00012 //     notice, this list of conditions and the following disclaimer.
00013 // 
00014 //  2. Redistributions in binary form must reproduce the above copyright
00015 //     notice, this list of conditions and the following disclaimer in the
00016 //     documentation and/or other materials provided with the distribution.
00017 // 
00018 //  3. The name of the authors may not be used to endorse or promote
00019 //     products derived from this software without specific prior written
00020 //     permission.
00021 // 
00022 // THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
00023 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00024 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
00025 // NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00026 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
00027 // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00028 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00029 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00030 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00031 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00032 // 
00033 // This file is part of the PLearn library. For more information on the PLearn
00034 // library, go to the PLearn Web site at www.plearn.org
00035 
00036 
00037  
00038 
00039 /* *******************************************************      
00040  * $Id: TVec_decl.h 10143 2009-04-23 17:00:27Z nouiz $
00041  * AUTHORS: Pascal Vincent & Yoshua Bengio
00042  * This file is part of the PLearn library.
00043  ******************************************************* */
00044 
00045 
00046 
00047 #ifndef TVec_decl_INC
00048 #define TVec_decl_INC
00049 
00050 #include <algorithm>
00051 #include <iterator>
00052 #include <numeric>
00053 #include <functional>
00054 #include <sstream>
00055 
00056 #include <plearn/base/general.h>
00057 #include <plearn/base/Storage.h>
00058 #include <plearn/base/Range.h>
00059 #include <plearn/io/plstreams.h>
00060 #include <plearn/io/PStream.h>
00061 #include <plearn/io/openString.h>
00062 
00063 namespace PLearn {
00064 using namespace std;
00065 
00066 // predeclarations
00067 template<class T> class TMat;
00068 class Variable;
00069 class VarArray;
00070 class QRchunker;
00071 class QCchunker;
00072 
00073 template <class T>
00074 class TVec
00075 {
00076     friend class TMat<T>;
00077 
00078     friend class Variable; 
00079     friend class VarArray; 
00080 
00082     friend class QRchunker;
00083     friend class QCchunker;
00084 
00085 protected:
00086     int      length_;  
00087     int      offset_;  
00088     PP< Storage<T> > storage; 
00090 public:
00091 
00092     typedef T value_type;
00093     typedef int size_type;
00094     typedef T* iterator;
00095     typedef const T* const_iterator;
00096 
00097     inline iterator begin() const 
00098     { 
00099         if (storage.isNull()) return 0;
00100         return storage->data+offset_; 
00101     }
00102 
00103     inline iterator end() const 
00104     { return begin()+length(); }
00105 
00106     // norman: added explicit cast before vec.size()
00107     //         but beware if you're creating a constructor for storage that takes size_type
00108     //         because int could be different from size_type!
00109     inline TVec(const vector<T> & vec)
00110         :length_((int)vec.size()), offset_(0),
00111          storage(new Storage<T>((int)vec.size()))
00112     {
00113         for(int i=0;i<length_;i++)
00114             (*this)[i]=vec[i];
00115     }
00116 
00117     inline TVec() 
00118         :length_(0),offset_(0)
00119     {}
00120 
00121     inline explicit TVec(int the_length) 
00122         :length_(the_length), offset_(0),
00123          storage(new Storage<T>(the_length))
00124     {}
00125 
00127     inline TVec(int the_length, const T& init_value) 
00128         :length_(the_length), offset_(0),
00129          storage(new Storage<T>(the_length))
00130     { fill(init_value); }
00131 
00135     TVec(const T& start, const T& stop, const T& step);
00136 
00138     inline TVec(int the_length, T* the_data)
00139         :length_(the_length), offset_(0),
00140          storage(new Storage<T>(the_length, the_data))
00141     {}
00142 
00144     inline TVec(const TVec<T>& other)
00145         :length_(other.length()), offset_(other.offset()),
00146          storage(other.storage)
00147     {}
00148 
00150     inline const TVec<T>& operator=(const TVec<T>& other)
00151     {
00152         storage = other.storage;
00153         length_ = other.length_;
00154         offset_ = other.offset_;
00155         return *this;
00156     }
00157 
00158     operator vector<T>() const
00159     {    
00160         int n = length_;
00161         vector<T> res(n);
00162         if(n>0)
00163         {
00164             T* ptr = data();
00165             for(int i=0; i<n; i++)
00166                 res[i] = *ptr++;
00167         }
00168         return res;
00169     }
00170 
00171     bool hasMissing() const
00172     {
00173         iterator it = begin();
00174         iterator itend = end();
00175         for(; it!=itend; ++it)
00176             if(is_missing(*it))
00177                 return true;
00178         return false;
00179     }
00180 
00181     inline int size() const { return length_; }
00182     inline int length() const { return length_; }
00183     inline int capacity() const { return storage.isNotNull() ? storage->length()-offset_ : 0; }
00184     inline int offset() const { return offset_; }
00185 
00186     inline PP< Storage<T> > getStorage() const { return storage; }
00187 
00189     void compact()
00190     {
00191         if(storage && storage->length() != length())
00192         {
00193             if(storage->usage()>1)
00194                 PLERROR("IN Mat::compact() compact operation not allowed when matrix storage is shared (for obvious reasons)");
00195             operator=(copy());
00196         }
00197     }
00198 
00200     inline operator char*() const { if(isNull()) return 0; else return (char*)data(); }
00201 
00202     // norman: removed const. With inline is useless (and .NET doesn't like it)
00203     // Old code:
00204     //inline const size_t byteLength() const { return length()*sizeof(T); }
00205     inline size_t byteLength() const { return length()*sizeof(T); }
00206 
00212     inline void resize(int newlength, int extra=0)
00213     {
00214 #ifdef BOUNDCHECK
00215         if (newlength<0 || extra<0)
00216             PLERROR("IN TVec::resize(int newlength)\nInvalid argument (<0)");
00217 #endif
00218         if (newlength == length_ && extra == 0) {
00219             // No need to do anything.
00220             return;
00221         }
00222         if (storage.isNull() && (newlength>0 || extra>0))
00223         {
00224             offset_ = 0;
00225             length_ = newlength;
00226             Storage<T>* s = new Storage<T>(newlength + extra);          
00227             storage = s;
00228         }
00229         else
00230         {
00231             if (storage.isNotNull() && (newlength > capacity()))
00232                 storage->resize (offset_ + newlength + extra);
00233             length_ = newlength;
00234         }
00235     }
00236 
00239     void write(PStream& out) const
00240     {
00241         const TVec<T>& v = *this; // simple alias
00242         if(storage && 
00243            ( out.implicit_storage 
00244              || out.outmode==PStream::raw_ascii
00245              || out.outmode==PStream::raw_binary
00246              || out.outmode==PStream::pretty_ascii ) )
00247             writeSequence(out,v);
00248         else if(storage.isNull() && out.outmode!=PStream::plearn_binary)
00249             out.write("[]\n");
00250         else // write explicit storage
00251         {
00252             out.write("TVec("); 
00253             out << v.length();
00254             out << v.offset();
00255             out << v.getStorage();
00256             out.write(")\n");
00257         }
00258     }
00259 
00262     void read(PStream& in)
00263     {
00264         TVec<T>& v = *this; // simple alias
00265         switch(in.inmode)
00266         {
00267         case PStream::raw_ascii:
00268         case PStream::raw_binary:      
00269             readSequence(in, v);
00270 
00271         case PStream::plearn_ascii:
00272         case PStream::plearn_binary:
00273         {
00274             in.skipBlanksAndComments();
00275             int c = in.peek();
00276             if(c!='T') // implicit storage
00277                 readSequence(in,v);
00278             else // explicit storage
00279             {
00280                 char word[6];
00281                 // !!!! BUG: For some reason, this hangs!!!
00282                 // in.read(word,5);
00283                 for(int i=0; i<5; i++)
00284                     in.get(word[i]);
00285                 word[5]='\0';
00286                 if(strcmp(word,"TVec(")!=0)
00287                     PLERROR("In operator>>(PStream&, TVec&) '%s' not a proper header for a TVec!",word);
00288                 // v.storage = 0;
00289                 in.skipBlanksAndCommentsAndSeparators();
00290                 in >> v.length_;
00291                 in.skipBlanksAndCommentsAndSeparators();
00292                 in >> v.offset_;
00293                 in.skipBlanksAndCommentsAndSeparators();
00294                 in >> v.storage;
00295                 in.skipBlanksAndCommentsAndSeparators();
00296                 int c = in.get(); // skip ')'
00297                 if(c!=')')
00298                     PLERROR("In operator>>(PStream&, TVec&) expected a closing parenthesis, found '%c'",c);
00299             }
00300         }
00301         break;
00302       
00303         default:
00304             PLERROR("In TVec<T>::read(PStream& in)  unknown inmode!!!!!!!!!");
00305             break;
00306         }
00307     }
00308 
00309     // The following methods are deprecated, and just call corresponding functions.
00310     // Please call those functions directly in new code
00311     void save(const string& filename) const { savePVec(filename, *this); }
00312     void load(const string& filename) { loadPVec(filename, *this); }
00313     
00315     TVec<T> subVec(int newstart, int newlength) const
00316     {
00317 #ifdef BOUNDCHECK
00318         if(newstart+newlength>length() || newlength<0)
00319             PLERROR("TVec::subVec(int newstart, int newlength) OUT OF BOUNDS OR <0 length()"
00320                     " length()=%d; newstart=%d; newlength=%d.", length(), newstart, newlength);
00321 #endif
00322         TVec<T> subv = *this;
00323         subv.length_ = newlength;
00324         subv.offset_ += newstart;
00325         return subv;
00326     }
00327 
00333     void subVecSelf(int newstart, int newlength)
00334     {
00335 #ifdef BOUNDCHECK
00336         if(newstart+newlength>length() || newlength<0)
00337             PLERROR("TVec::subVecSelf(int newstart, int newlength) OUT OF BOUNDS OR <0 length()"
00338                     " length()=%d; newstart=%d; newlength=%d.", length(), newstart, newlength);
00339 #endif
00340         length_ = newlength;
00341         offset_ += newstart;
00342     }
00343 
00348     void makeDeepCopyFromShallowCopy(CopiesMap& copies);
00349 
00354     TVec<T> deepCopy(CopiesMap& copies) const;
00355 
00356 
00357     inline TVec<T> subVec(Range r) { return subVec(r.start, r.length); }
00358     
00360     void concat(const TVec<T>& input1, const TVec<T>& input2)
00361     {  
00362         int l1 = input1.length();
00363         int l2 = input2.length();
00364         resize(l1+l2);
00365         for(int i=0;i<l1;i++) (*this)[i] = input1[i];
00366         for(int i=0;i<l2;i++) (*this)[l1+i] = input2[i];
00367     }
00368 
00369     void concat(const TVec<T>& input1, const TVec<T>& input2, const TVec<T>& input3)
00370     {
00371         int l1 = input1.length();
00372         int l2 = input2.length();
00373         int l3 = input3.length();
00374         resize(l1+l2+l3);
00375         for(int i=0;i<l1;i++) (*this)[i] = input1[i];
00376         for(int i=0;i<l2;i++) (*this)[l1+i] = input2[i];
00377         for(int i=0;i<l3;i++) (*this)[l1+l2+i] = input3[i];
00378     }
00379 
00380     void concat(const TVec<T>& input1, const TVec<T>& input2, const TVec<T>& input3, const TVec<T>& input4)
00381     {
00382         int l1 = input1.length();
00383         int l2 = input2.length();
00384         int l3 = input3.length();
00385         int l4 = input4.length();
00386         resize(l1+l2+l3+l4);
00387         for(int i=0;i<l1;i++) (*this)[i] = input1[i];
00388         for(int i=0;i<l2;i++) (*this)[l1+i] = input2[i];
00389         for(int i=0;i<l3;i++) (*this)[l1+l2+i] = input3[i];
00390         for(int i=0;i<l4;i++) (*this)[l1+l2+l3+i] = input4[i];
00391     }
00392 
00394     inline TMat<T> toMat(int newlength, int newwidth) const;
00395 
00397     inline TVec<T> copy() const
00398     {
00399         TVec<T> freshcopy(length());
00400         freshcopy << *this;
00401         return freshcopy;
00402     }
00403 
00405     void copyFrom(const T* x, int n) const
00406     {  
00407 #ifdef BOUNDCHECK
00408         if(n != length())
00409             PLERROR("IN TVec::copyFrom(T* x, int n)\nVecs do not have the same length()");
00410 #endif
00411         if (n == 0)
00412             return; // Nothing to copy.
00413         T* v1 = data(); 
00414 
00415         // The following was compiled into an inefficient loop.  Modern C++
00416         // compilers transform 'copy' into memmove whenever possible, so use
00417         // that.
00418         //
00419         // for(int i=0; i<n; i++)
00420         //    v1[i] = x[i];
00421 
00422         std::copy(x, x+n, v1);
00423     }
00424 
00426     void copyTo(T* x) const
00427     {
00428         T* v1 = data(); // get data start
00429         if (! v1)
00430             return;
00431 
00432         // The following was compiled into an inefficient loop.  Modern C++
00433         // compilers transform 'copy' into memmove whenever possible, so use
00434         // that.
00435         //
00436         // for(int i=0; i<length(); i++)
00437         //     x[i] = v1[i];
00438 
00439         std::copy(v1, v1+length(), x);
00440     }
00441 
00446     void makeSharedValue(T* x, int n)
00447     {
00448 #ifdef BOUNDCHECK
00449         if(n != length())
00450             PLERROR("IN TVec::makeSharedValue(T* x, int n)\nn(%d)!=length_(%d)",
00451                     n,length());
00452         if(offset_!=0)
00453             PLERROR("IN TVec::makeSharedValue(T* x, int n)\noffset should be 0.");
00454 #endif
00455         T* v = data(); 
00456         for(int i=0; i<n; i++)
00457             x[i] = v[i];
00458         storage->pointTo(n,x);
00459     }
00460 
00461     bool isNull() const 
00462     { return storage.isNull(); }
00463 
00464     bool isNotNull() const
00465     { return storage.isNotNull(); }
00466 
00467     bool isEmpty() const
00468     { return length_==0; }
00469 
00470     bool isNotEmpty() const
00471     { return length_!=0; }
00472       
00476     /*
00478     operator bool() const
00479     { return isNotEmpty(); }
00480     */
00481       
00483     bool operator!() const
00484     { return isEmpty(); }
00485 
00486     // for compatibility with Array
00487     TVec<T>* operator->()
00488     { return this; }
00489 
00491     inline void fill(const T& value) const
00492     {
00493         if (isNotEmpty())
00494             fill_n(data(), length(), value);
00495     }
00496 
00499     void fill(const T& startval, const T& step)
00500     {
00501         iterator it = begin();
00502         iterator itend = end();
00503         for(T val=startval; it!=itend; ++it, val+=step)
00504             *it = val;
00505     }
00506 
00507     inline void clear() const
00508     { if(isNotEmpty()) clear_n(data(),length()); }
00509 
00511     inline void insert(int position, T value)
00512     {
00513 #ifdef BOUNDCHECK
00514         if(position<0 || position>length())
00515             PLERROR("OUT OF BOUNDS in TVec::insert");
00516 #endif
00517         resize(length()+1);
00518         T* v = data();
00519         for(int i=length()-1; i>position; i--)
00520             v[i] = v[i-1];
00521         v[position] = value;
00522     }
00523 
00525     inline void remove(int position)
00526     {
00527 #ifdef BOUNDCHECK
00528         if(position<0 || position>=length())
00529             PLERROR("OUT OF BOUNDS in Vec::remove");
00530 #endif
00531         T* v = data();
00532         for(int i=position; i<length()-1; i++)
00533             v[i] = v[i+1];
00534         resize(length()-1);
00535     }
00536 
00539     TVec<int> sortingPermutation(bool stable = false, bool missing = false) const;
00540     
00544     int findSorted(T value) const
00545     {
00546         if (isEmpty())
00547             return 0;
00548  
00549         pair<iterator, iterator> range =
00550             equal_range(begin(), end(), value);
00551         
00552         return int(range.first - begin());
00553     }
00554   
00555     inline void insertSorted(T value, bool uniq)
00556     {
00557         int i = findSorted(value);
00558         if(!uniq || i==length() || (*this)[i]!=value)
00559             insert(i,value);
00560     }
00561 
00562     inline void removeSorted(T value)
00563     {
00564         int i = findSorted(value);
00565         if(i<length() && (*this)[i]==value)
00566             remove(i);
00567     }
00568 
00569 
00570     inline void append(const T& newval)
00571     {
00572         //we do this as an speed optimization. I see a 3.5% speed up...
00573         //g++4.1 don't seam to inline resize event in heavy loop of append.
00574         //maybe this is the cause of the speed up?
00575         if (storage.isNotNull() && (length() < capacity())){
00576             length_++;
00577         }else
00578             resize(length()+1, length());
00579         lastElement() = newval;
00580     }
00581 
00583     void append(const vector<T>& newvec)
00584     {
00585         int currentsize = length();
00586         if (currentsize + newvec.size() == 0)
00587             return;
00588         resize(currentsize + newvec.size(), currentsize + newvec.size());
00589         T* v = data();
00590         for (unsigned int i=0; i<newvec.size(); ++i)
00591             v[currentsize+i] = newvec[i];
00592     }
00593 
00595     inline void appendIfNotThereAlready(const T& newval)
00596     {
00597         if(length()>0) {
00598             T* v = data();
00599             for (int i=0;i<length();i++)
00600                 if (newval==v[i]) return;
00601         }
00602         append(newval);
00603     }
00604 
00606     inline void push_back(const T& newval)
00607     { append(newval); }
00608 
00609     inline void pop_back()
00610     {
00611         if(length_ <= 0)
00612             PLERROR("In TVec::pop_back already empty!");
00613         length_ -= 1; 
00614     } 
00615 
00617     inline void push(const T& newval)
00618     { append(newval); }
00619 
00620     inline T pop()
00621     { T res = lastElement(); pop_back(); return res; }
00622 
00623     inline T& top() const
00624     { return lastElement(); }
00625 
00626     inline void append(const TVec<T>& values)
00627     {
00628         int oldLength = length();
00629         if (values.length() == 0)
00630             return;
00631         resize(oldLength+values.length(), oldLength+values.length());
00632         T* v = data()+oldLength;
00633         T* newv = values.data();
00634         for(int i=0; i<values.length(); i++)
00635             v[i] = newv[i];
00636     }
00637 
00638     inline T& operator[](int i) const
00639     {
00640 #ifdef BOUNDCHECK
00641         if(i<0 || i>=length())
00642             PLERROR("OUT OF BOUND ACCESS %d IN TVec(%d)::operator[]",i,length());
00643 #endif
00644         return storage->data[i+offset_]; 
00645     }
00646 
00647     // norman: added operator[] for unsigned int
00648     inline T& operator[](unsigned int i) const
00649     {
00650 #ifdef BOUNDCHECK
00651         // norman: added explicit cast
00652         if(i<0 || i>=(unsigned int)length())
00653             PLERROR("OUT OF BOUND ACCESS %d IN TVec(%d)::operator[]",i,length());
00654 #endif
00655         return storage->data[i+offset_]; 
00656     }
00657 
00658     inline T& lastElement() const
00659     { 
00660 #ifdef BOUNDCHECK
00661         if(length()==0)
00662             PLERROR("TVec::lastElement() - can't access last"
00663                     " element of TVec as there is 0 element!");
00664 #endif
00665         return storage->data[offset_+length()-1];
00666     }
00667 
00668     inline T& firstElement() const
00669     { 
00670 #ifdef BOUNDCHECK
00671         if(length()==0)
00672             PLERROR("TVec::firstElement() - can't access first"
00673                     " element of TVec as there is 0 element!");
00674 #endif 
00675         return storage->data[offset_]; 
00676     }
00677 
00678     inline T& front() const { return firstElement(); }
00679     inline T& back() const { return lastElement(); }
00680 
00681     // for compatibility with Array
00682     inline T& first() const { return firstElement(); }
00683     inline T& last() const { return lastElement(); }
00684 
00685 
00687     template<class I>
00688     inline void operator()(const TVec<I>& indices, TVec<T>& destination) const
00689     { selectElements(*this, indices, destination); }
00690 
00696     template<class I>
00697     inline TVec<T> operator()(const TVec<I>& indices) const
00698     {
00699         TVec<T> result(indices.length());
00700         selectElements(*this, indices, result);
00701         return result;
00702     }
00703 
00705     inline T* data() const
00706     {
00707 #ifdef BOUNDCHECK
00708         if(storage.isNull())
00709             PLERROR("IN TVec::operator()\nAttempted to get a pointer to the data of an empty TVec");
00710 #endif
00711         return storage->data+offset_; 
00712     }
00713 
00715     inline void swap()
00716     {
00717         if (isEmpty()) return;
00718         int half = length()/2;
00719         T* ptr = data();
00720         for(int i=0; i<half; i++)
00721             std::swap(ptr[i],ptr[length()-i-1]);
00722     }
00723 
00725     TVec<bool> operator==(const T& value) const
00726     {
00727         TVec<bool> r(length(), false);
00728         //elementsEqualTo(*this,value,r);
00729         for (int i=0; i<length(); i++)
00730         {
00731             if ((*this)[i] == value) r[i] = true;
00732         }
00733         return r;
00734     }
00735 
00737     bool operator==(const TVec<T>& value) const
00738     {
00739         if (value.isEmpty() && isEmpty()) return true;
00740         if (value.length()!=length()) return false;
00741         T* x=data();
00742         T* y=value.data();
00743         for (int i=0;i<length();i++)
00744             if (x[i]!=y[i]) return false;
00745         return true;
00746     }
00747     bool operator!=(const TVec<T>& value) const { return !((*this)==value); }
00748 
00750     bool isEqual(const TVec<T>& value, bool ignore_missing=false) const
00751     {
00752         if (value.isEmpty() && isEmpty()) return true;
00753         if (value.length() != length())   return false;
00754         if (!ignore_missing) return ((*this)==value);
00755 
00756         T* x = data();
00757         T* y = value.data();
00758         for (int i=0;  i<length();  i++)
00759         {
00760             real x_i = x[i];
00761             real y_i = y[i];
00762 
00763             // For NaN values
00764             if (isnan(x_i))
00765             {
00766                 if (isnan(y_i))
00767                     continue;
00768                 else
00769                     return false;
00770             }
00771             else if (isnan(x_i)) return false;
00772 
00773             // For Inf values
00774             if (isinf(x_i))
00775             {
00776                 if (isinf(y_i))
00777                     continue;
00778                 else
00779                     return false;
00780             }
00781             else if (isinf(x_i)) return false;
00782 
00783             if (x_i != y_i) return false;
00784         }
00785         return true;
00786     }
00787 
00789     bool contains(const T& element) const
00790     {
00791         return find(element) != -1;
00792     }
00793 
00795     TVec<int> findIndices(const T& element)
00796     {
00797         TVec<int> indices(0);
00798         if (!isEmpty())
00799         {
00800             T *v = data();
00801             for (int i=0; i<length(); i++)
00802                 if (v[i]==element)
00803                     indices.append(i);
00804         }
00805         return indices;
00806     }
00807 
00808     TVec<int> findIndices(const TVec<T>& elements)
00809     {
00810         TVec<int> indices(0);
00811         if (!isEmpty())
00812         {
00813             T *v = data();
00814             for (int i=0; i<length(); i++)
00815                 for (int j=0, m=elements.length(); j<m; j++)
00816                     if (v[i] == elements[j])
00817                     {
00818                         indices.append(i);
00819                         break;
00820                     }
00821         }
00822         return indices;
00823     }
00824 
00827     int find(const T& element, int start=0) const
00828     {
00829         if (length()==0) return -1;
00830         T *v = data();
00831         for (int i=start; i<length(); i++)
00832             if(v[i]==element)
00833                 return i;
00834         return -1;
00835     }
00836 
00837     TVec<int> find(TVec<T> elements)
00838     {
00839         TVec<int> indices(elements.length(),-1);
00840         if (length()==0) return indices;
00841         T *v = data();
00842         for (int i=0, m=elements.length(); i<m; i++)
00843             for (int j=0; j<length(); j++)
00844                 if (v[j] == elements[i])
00845                 {
00846                     indices[i] = j;
00847                     break;
00848                 }
00849         return indices;
00850     }
00851 
00853     int count(const T& element)
00854     {
00855         int result = 0;
00856         if (!isEmpty())
00857         {
00858             T *v = data();
00859             for (int i=0; i<length(); i++)
00860                 if (v[i]==element)
00861                     result++;
00862         }
00863         return result;
00864     }
00865 
00866     int count(const TVec<T>& elements)
00867     {
00868         int result = 0;
00869         if (!isEmpty())
00870         {
00871             T *v = data();
00872             for (int i=0; i<length(); i++)
00873                 for (int j=0, m=elements.length(); j<m; j++)
00874                     if (v[i]==elements[j])
00875                     {
00876                         result++;
00877                         break;
00878                     }
00879         }
00880         return result;
00881     }
00882 
00883 
00885     void print(ostream& out = cout) const; 
00886     void println(ostream& out = cout) const { print(out); out<<endl; } 
00887     void printcol(ostream& out = cout) const; 
00888     void print(ostream& out, const string& separator) const; 
00889 
00890     void input(istream& in=cin) const;
00891     void input(PStream& in) const;
00892 
00893     // calls print with cerr, usefull with gdb (> call obj.debugprint() )
00894     void debugPrint(){print(cerr);}
00895 
00896 
00897     void operator<<(const string& datastring) const
00898     {
00899         // istrstream in(datastring.c_str());
00900         PStream in = openString(datastring,PStream::plearn_ascii);
00901         input(in);
00902     }
00903 
00904 };
00905 
00906 typedef TVec<real> Vec;
00907 
00910 inline void operator<<(const Vec& v, real f)
00911 { v.fill(f); }
00912 
00913 template<class T>
00914 class TypeTraits< TVec<T> >
00915 {
00916 public:
00917     static inline string name()
00918     { return string("TVec< ") + TypeTraits<T>::name()+" >"; }
00919 
00920     static inline unsigned char little_endian_typecode()
00921     { return 0xFF; }
00922 
00923     static inline unsigned char big_endian_typecode()
00924     { return 0xFF; }
00925 };
00926 
00927 
00928 template <class T>
00929 inline int sizeInBytes(const TVec<T>& x) { 
00930     int n=x.length();
00931     int s=sizeof(TVec<T>);
00932     if (n>0) s+=n*sizeInBytes(x[0]); 
00933     return s;
00934 }
00935 
00937 template<class T>
00938 TVec<T> concat(const TVec<T>& v1, const TVec<T>& v2);
00939 
00941 template<class T>
00942 TVec<T> concat(const TVec<T>& v1, const TVec<T>& v2, const TVec<T>& v3);
00943 
00945 template<class T>
00946 TVec<T> concat(const TVec<T>& v1, const TVec<T>& v2, const TVec<T>& v3, const TVec<T>& v4);
00947 
00948 } // end of namespace PLearn
00949 
00950 
00951 #endif
00952 
00953 
00954 /*
00955   Local Variables:
00956   mode:c++
00957   c-basic-offset:4
00958   c-file-style:"stroustrup"
00959   c-file-offsets:((innamespace . 0)(inline-open . 0))
00960   indent-tabs-mode:nil
00961   fill-column:79
00962   End:
00963 */
00964 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=79 :
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines