Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members

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,v 1.16 2004/08/11 07:18:45 chapados Exp $ 00041 * AUTHORS: Pascal Vincent & Yoshua Bengio 00042 * This file is part of the PLearn library. 00043 ******************************************************* */ 00044 00045 00048 #ifndef TVec_decl_INC 00049 #define TVec_decl_INC 00050 00051 #include <iterator> 00052 #include <numeric> 00053 #include <functional> 00054 #include <strstream> 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 00061 namespace PLearn { 00062 using namespace std; 00063 00064 // predeclarations 00065 template<class T> class TMat; 00066 class Variable; 00067 class VarArray; 00068 class QRchunker; 00069 class QCchunker; 00070 00071 template <class T> 00072 class TVec 00073 { 00074 friend class TMat<T>; 00075 00076 friend class Variable; 00077 friend class VarArray; 00078 00080 friend class QRchunker; 00081 friend class QCchunker; 00082 00083 protected: 00084 int length_; 00085 int offset_; 00086 PP< Storage<T> > storage; 00088 public: 00089 00090 typedef T value_type; 00091 typedef int size_type; 00092 typedef T* iterator; 00093 typedef const T* const_iterator; 00094 00095 inline iterator begin() const 00096 { 00097 if (storage.isNull()) return 0; 00098 return storage->data+offset_; 00099 } 00100 00101 inline iterator end() const 00102 { return begin()+length(); } 00103 00104 // norman: added explicit cast before vec.size() 00105 // but beware if you're creating a constructor for storage that takes size_type 00106 // because int could be different from size_type! 00107 inline TVec(const vector<T> & vec) 00108 :length_((int)vec.size()), offset_(0), 00109 storage(new Storage<T>((int)vec.size())) 00110 { 00111 for(int i=0;i<length_;i++) 00112 (*this)[i]=vec[i]; 00113 } 00114 00115 inline TVec() 00116 :length_(0),offset_(0) 00117 {} 00118 00119 inline explicit TVec(int the_length) 00120 :length_(the_length), offset_(0), 00121 storage(new Storage<T>(the_length)) 00122 {} 00123 00125 inline TVec(int the_length, const T& init_value) 00126 :length_(the_length), offset_(0), 00127 storage(new Storage<T>(the_length)) 00128 { fill(init_value); } 00129 00133 TVec(const T& start, const T& stop, const T& step); 00134 00136 inline TVec(int the_length, T* the_data) 00137 :length_(the_length), offset_(0), 00138 storage(new Storage<T>(the_length, the_data)) 00139 {} 00140 00142 inline TVec(const TVec<T>& other) 00143 :length_(other.length()), offset_(other.offset()), 00144 storage(other.storage) 00145 {} 00146 00148 inline const TVec<T>& operator=(const TVec<T>& other) 00149 { 00150 storage = other.storage; 00151 length_ = other.length_; 00152 offset_ = other.offset_; 00153 return *this; 00154 } 00155 00156 operator vector<T>() const 00157 { 00158 int n = length_; 00159 vector<T> res(n); 00160 if(n>0) 00161 { 00162 T* ptr = data(); 00163 for(int i=0; i<n; i++) 00164 res[i] = *ptr++; 00165 } 00166 return res; 00167 } 00168 00169 bool hasMissing() const 00170 { 00171 iterator it = begin(); 00172 iterator itend = end(); 00173 for(; it!=itend; ++it) 00174 if(is_missing(*it)) 00175 return true; 00176 return false; 00177 } 00178 00179 inline int size() const { return length_; } 00180 inline int length() const { return length_; } 00181 inline int capacity() const { return storage.isNotNull() ? storage->length()-offset_ : 0; } 00182 inline int offset() const { return offset_; } 00183 00184 inline PP< Storage<T> > getStorage() const { return storage; } 00185 00187 void compact() 00188 { 00189 if(storage && storage->length() != length()) 00190 { 00191 if(storage->usage()>1) 00192 PLERROR("IN Mat::compact() compact operation not allowed when matrix storage is shared (for obvious reasons)"); 00193 operator=(copy()); 00194 } 00195 } 00196 00198 inline operator char*() const { if(isNull()) return 0; else return (char*)data(); } 00199 00200 // norman: removed const. With inline is useless (and .NET doesn't like it) 00201 // Old code: 00202 //inline const size_t byteLength() const { return length()*sizeof(T); } 00203 inline size_t byteLength() const { return length()*sizeof(T); } 00204 00210 inline void resize(int newlength, int extrabytes=0) 00211 { 00212 #ifdef BOUNDCHECK 00213 if (newlength<0 || extrabytes<0) 00214 PLERROR("IN TVec::resize(int newlength)\nInvalid argument (<0)"); 00215 #endif 00216 if (newlength == length_) { 00217 // No need to do anything. 00218 return; 00219 } 00220 if (storage.isNull() && newlength>0) 00221 { 00222 offset_ = 0; 00223 length_ = newlength; 00224 Storage<T>* s = new Storage<T>(newlength + extrabytes); 00225 storage = s; 00226 } 00227 else 00228 { 00229 if (storage.isNotNull() && (newlength > capacity())) 00230 storage->resize (offset_ + newlength + extrabytes); 00231 length_ = newlength; 00232 } 00233 } 00234 00237 void write(PStream& out) const 00238 { 00239 const TVec<T>& v = *this; // simple alias 00240 if(storage && 00241 ( out.implicit_storage 00242 || out.outmode==PStream::raw_ascii 00243 || out.outmode==PStream::raw_binary 00244 || out.outmode==PStream::pretty_ascii ) ) 00245 writeSequence(out,v); 00246 else // write explicit storage 00247 { 00248 out.write("TVec("); 00249 out << v.length(); 00250 out << v.offset(); 00251 out << v.getStorage(); 00252 out.write(")\n"); 00253 } 00254 } 00255 00258 void read(PStream& in) 00259 { 00260 TVec<T>& v = *this; // simple alias 00261 switch(in.inmode) 00262 { 00263 case PStream::raw_ascii: 00264 case PStream::raw_binary: 00265 readSequence(in, v); 00266 00267 case PStream::plearn_ascii: 00268 case PStream::plearn_binary: 00269 { 00270 in.skipBlanksAndComments(); 00271 int c = in.peek(); 00272 if(c!='T') // implicit storage 00273 readSequence(in,v); 00274 else // explicit storage 00275 { 00276 char word[6]; 00277 // !!!! BUG: For some reason, this hangs!!! 00278 // in.read(word,5); 00279 for(int i=0; i<5; i++) 00280 in.get(word[i]); 00281 word[5]='\0'; 00282 if(strcmp(word,"TVec(")!=0) 00283 PLERROR("In operator>>(PStream&, TVec&) '%s' not a proper header for a TVec!",word); 00284 // v.storage = 0; 00285 in.skipBlanksAndCommentsAndSeparators(); 00286 in >> v.length_; 00287 in.skipBlanksAndCommentsAndSeparators(); 00288 in >> v.offset_; 00289 in.skipBlanksAndCommentsAndSeparators(); 00290 in >> v.storage; 00291 in.skipBlanksAndCommentsAndSeparators(); 00292 int c = in.get(); // skip ')' 00293 if(c!=')') 00294 PLERROR("In operator>>(PStream&, TVec&) expected a closing parenthesis, found '%c'",c); 00295 } 00296 } 00297 break; 00298 00299 default: 00300 PLERROR("In TVec<T>::read(PStream& in) unknown inmode!!!!!!!!!"); 00301 break; 00302 } 00303 } 00304 00305 // The following methods are deprecated, and just call corresponding functions. 00306 // Please call those functions directly in new code 00307 void save(const string& filename) const { savePVec(filename, *this); } 00308 void load(const string& filename) { loadPVec(filename, *this); } 00309 00311 TVec<T> subVec(int newstart, int newlength) const 00312 { 00313 #ifdef BOUNDCHECK 00314 if(newstart+newlength>length() || newlength<0) 00315 PLERROR("TVec::subVec(int newstart, int newlength) OUT OF BOUNDS OR <0 length()" 00316 " length()=%d; newstart=%d; newlength=%d.", length(), newstart, newlength); 00317 #endif 00318 TVec<T> subv = *this; 00319 subv.length_ = newlength; 00320 subv.offset_ += newstart; 00321 return subv; 00322 } 00323 00328 void makeDeepCopyFromShallowCopy(map<const void*, void*>& copies); 00329 00334 TVec<T> deepCopy(map<const void*, void*>& copies) const; 00335 00336 00337 inline TVec<T> subVec(Range r) { return subVec(r.start, r.length); } 00338 00340 void concat(const TVec<T>& input1, const TVec<T>& input2) 00341 { 00342 int l1 = input1.length(); 00343 int l2 = input2.length(); 00344 resize(l1+l2); 00345 for(int i=0;i<l1;i++) (*this)[i] = input1[i]; 00346 for(int i=0;i<l2;i++) (*this)[l1+i] = input2[i]; 00347 } 00348 00349 void concat(const TVec<T>& input1, const TVec<T>& input2, const TVec<T>& input3) 00350 { 00351 int l1 = input1.length(); 00352 int l2 = input2.length(); 00353 int l3 = input3.length(); 00354 resize(l1+l2+l3); 00355 for(int i=0;i<l1;i++) (*this)[i] = input1[i]; 00356 for(int i=0;i<l2;i++) (*this)[l1+i] = input2[i]; 00357 for(int i=0;i<l3;i++) (*this)[l1+l2+i] = input3[i]; 00358 } 00359 00360 void concat(const TVec<T>& input1, const TVec<T>& input2, const TVec<T>& input3, const TVec<T>& input4) 00361 { 00362 int l1 = input1.length(); 00363 int l2 = input2.length(); 00364 int l3 = input3.length(); 00365 int l4 = input4.length(); 00366 resize(l1+l2+l3+l4); 00367 for(int i=0;i<l1;i++) (*this)[i] = input1[i]; 00368 for(int i=0;i<l2;i++) (*this)[l1+i] = input2[i]; 00369 for(int i=0;i<l3;i++) (*this)[l1+l2+i] = input3[i]; 00370 for(int i=0;i<l4;i++) (*this)[l1+l2+l3+i] = input4[i]; 00371 } 00372 00374 inline TMat<T> toMat(int newlength, int newwidth) const; 00375 00377 inline TVec<T> copy() const 00378 { 00379 TVec<T> freshcopy(length()); 00380 freshcopy << *this; 00381 return freshcopy; 00382 } 00383 00385 void copyFrom(const T* x, int n) const 00386 { 00387 #ifdef BOUNDCHECK 00388 if(n != length()) 00389 PLERROR("IN TVec::copyFrom(T* x, int n)\nVecs do not have the same length()"); 00390 #endif 00391 T* v1 = data(); 00392 for(int i=0; i<n; i++) 00393 v1[i] = x[i]; 00394 } 00395 00397 void copyTo(T* x) const 00398 { 00399 T* v1 = data(); // get data start 00400 for(int i=0; i<length(); i++) 00401 x[i] = v1[i]; 00402 } 00403 00408 void makeSharedValue(T* x, int n) 00409 { 00410 #ifdef BOUNDCHECK 00411 if(n != length()) 00412 PLERROR("IN TVec::makeSharedValue(T* x, int n)\nn(%d)!=length_(%d)", 00413 n,length()); 00414 #endif 00415 T* v = data(); 00416 for(int i=0; i<n; i++) 00417 x[i] = v[i]; 00418 storage->pointTo(n,x); 00419 } 00420 00421 bool isNull() const 00422 { return storage.isNull(); } 00423 00424 bool isNotNull() const 00425 { return storage.isNotNull(); } 00426 00427 bool isEmpty() const 00428 { return length_==0; } 00429 00430 bool isNotEmpty() const 00431 { return length_!=0; } 00432 00436 /* 00438 operator bool() const 00439 { return isNotEmpty(); } 00440 */ 00441 00443 bool operator!() const 00444 { return isEmpty(); } 00445 00446 // for compatibility with Array 00447 TVec<T>* operator->() 00448 { return this; } 00449 00451 inline void fill(const T& value) const 00452 { 00453 if (storage) 00454 fill_n(data(), length(), value); 00455 } 00456 00459 void fill(const T& startval, const T& step) 00460 { 00461 iterator it = begin(); 00462 iterator itend = end(); 00463 for(T val=startval; it!=itend; ++it, val+=step) 00464 *it = val; 00465 } 00466 00468 inline void operator=(const T& f) const 00469 { fill(f); } 00470 00471 inline void clear() const 00472 { if(!isNull()) clear_n(data(),length()); } 00473 00475 inline void insert(int position, T value) 00476 { 00477 #ifdef BOUNDCHECK 00478 if(position<0 || position>length()) 00479 PLERROR("OUT OF BOUNDS in TVec::insert"); 00480 #endif 00481 resize(length()+1); 00482 T* v = data(); 00483 for(int i=length()-1; i>position; i--) 00484 v[i] = v[i-1]; 00485 v[position] = value; 00486 } 00487 00489 inline void remove(int position) 00490 { 00491 #ifdef BOUNDCHECK 00492 if(position<0 || position>=length()) 00493 PLERROR("OUT OF BOUNDS in Vec::remove"); 00494 #endif 00495 T* v = data(); 00496 for(int i=position; i<length()-1; i++) 00497 v[i] = v[i+1]; 00498 resize(length()-1); 00499 } 00500 00501 int findSorted(T value) 00502 { 00503 if (isEmpty()) 00504 return 0; 00505 00506 pair<iterator, iterator> range = 00507 equal_range(begin(), end(), value); 00508 00509 return int(range.first - begin()); 00510 } 00511 00512 inline void insertSorted(T value, bool uniq) 00513 { 00514 int i = findSorted(value); 00515 if(!uniq || i==length() || (*this)[i]!=value) 00516 insert(i,value); 00517 } 00518 00519 inline void removeSorted(T value) 00520 { 00521 int i = findSorted(value); 00522 if(i<length() && (*this)[i]==value) 00523 remove(i); 00524 } 00525 00526 00527 inline void append(const T& newval) 00528 { 00529 resize(length()+1, length()); 00530 lastElement() = newval; 00531 } 00532 00534 void append(const vector<T>& newvec) 00535 { 00536 int currentsize = length(); 00537 if (currentsize + newvec.size() == 0) 00538 return; 00539 resize(currentsize + newvec.size()); 00540 T* v = data(); 00541 for (unsigned int i=0; i<newvec.size(); ++i) 00542 v[currentsize+i] = newvec[i]; 00543 } 00544 00546 inline void appendIfNotThereAlready(const T& newval) 00547 { 00548 T* v = data(); 00549 for (int i=0;i<length();i++) 00550 if (newval==v[i]) return; 00551 append(newval); 00552 } 00553 00555 inline void push_back(const T& newval) 00556 { append(newval); } 00557 00558 inline void pop_back() 00559 { 00560 if(length_ <= 0) 00561 PLERROR("In TVec::pop_back already empty!"); 00562 length_ -= 1; 00563 } 00564 00566 inline void push(const T& newval) 00567 { append(newval); } 00568 00569 inline T pop() 00570 { T res = lastElement(); pop_back(); return res; } 00571 00572 inline T& top() const 00573 { return lastElement(); } 00574 00575 inline void append(const TVec<T>& values) 00576 { 00577 int oldLength = length(); 00578 if (values.length() == 0) 00579 return; 00580 resize(oldLength+values.length()); 00581 T* v = data()+oldLength; 00582 T* newv = values.data(); 00583 for(int i=0; i<values.length(); i++) 00584 v[i] = newv[i]; 00585 } 00586 00587 inline T& operator[](int i) const 00588 { 00589 #ifdef BOUNDCHECK 00590 if(i<0 || i>=length()) 00591 PLERROR("OUT OF BOUND ACCESS %d IN TVec(%d)::operator[]",i,length()); 00592 #endif 00593 return storage->data[i+offset_]; 00594 } 00595 00596 // norman: added operator[] for unsigned int 00597 inline T& operator[](unsigned int i) const 00598 { 00599 #ifdef BOUNDCHECK 00600 // norman: added explicit cast 00601 if(i<0 || i>=(unsigned int)length()) 00602 PLERROR("OUT OF BOUND ACCESS %d IN TVec(%d)::operator[]",i,length()); 00603 #endif 00604 return storage->data[i+offset_]; 00605 } 00606 00607 inline T& lastElement() const 00608 { return storage->data[offset_+length()-1]; } 00609 00610 inline T& firstElement() const 00611 { return storage->data[offset_]; } 00612 00613 inline T& front() const { return firstElement(); } 00614 inline T& back() const { return lastElement(); } 00615 00616 // for compatibility with Array 00617 inline T& first() const { return firstElement(); } 00618 inline T& last() const { return lastElement(); } 00619 00620 00622 template<class I> 00623 inline void operator()(const TVec<I>& indices, TVec<T>& destination) const 00624 { selectElements(*this, indices, destination); } 00625 00631 template<class I> 00632 inline TVec<T> operator()(const TVec<I>& indices) const 00633 { 00634 TVec<T> result(indices.length()); 00635 selectElements(*this, indices, result); 00636 return result; 00637 } 00638 00640 inline T* data() const 00641 { 00642 #ifdef BOUNDCHECK 00643 if(storage.isNull()) 00644 PLERROR("IN TVec::operator()\nAttempted to get a pointer to the data of an empty TVec"); 00645 #endif 00646 return storage->data+offset_; 00647 } 00648 00650 inline void swap() 00651 { 00652 int half = length()/2; 00653 T* ptr = data(); 00654 for(int i=0; i<half; i++) 00655 std::swap(ptr[i],ptr[length()-i-1]); 00656 } 00657 00659 TVec<bool> operator==(const T& value) const 00660 { 00661 TVec<bool> r(length(), false); 00662 //elementsEqualTo(*this,value,r); 00663 for (int i=0; i<length(); i++) 00664 { 00665 if ((*this)[i] == value) r[i] = true; 00666 } 00667 return r; 00668 } 00669 00671 bool operator==(const TVec<T>& value) const 00672 { 00673 if (value.isEmpty() && isEmpty()) return true; 00674 if (value.length()!=length()) return false; 00675 T* x=data(); 00676 T* y=value.data(); 00677 for (int i=0;i<length();i++) 00678 if (x[i]!=y[i]) return false; 00679 return true; 00680 } 00681 bool operator!=(const TVec<T>& value) const { return !((*this)==value); } 00682 00684 bool contains(const T& element) const 00685 { 00686 if (length()==0) return false; 00687 bool contained=false; 00688 T *v = data(); 00689 for (int i=0; i<length() && !contained; i++) 00690 if (v[i]==element) 00691 contained=true; 00692 return contained; 00693 } 00694 00697 TVec<T> findIndices(const T& element) 00698 { 00699 TVec<T> indices(0); 00700 if (!isEmpty()) 00701 { 00702 T *v = data(); 00703 for (int i=0; i<length(); i++) 00704 if (v[i]==element) 00705 indices.append(i); 00706 } 00707 return indices; 00708 } 00709 00710 TVec<T> findIndices(const TVec<T>& elements) 00711 { 00712 TVec<T> indices(0); 00713 if (!isEmpty()) 00714 { 00715 T *v = data(); 00716 for (int i=0; i<length(); i++) 00717 for (int j=0, m=elements.length(); j<m; j++) 00718 if (v[i] == elements[j]) 00719 { 00720 indices.append(i); 00721 break; 00722 } 00723 } 00724 return indices; 00725 } 00726 00729 int find(const T& element, int start=0) const 00730 { 00731 if (length()==0) return -1; 00732 T *v = data(); 00733 for (int i=start; i<length(); i++) 00734 if(v[i]==element) 00735 return i; 00736 return -1; 00737 } 00738 00739 TVec<T> find(TVec<T> elements) 00740 { 00741 TVec<T> indices(elements.length(),-1); 00742 if (length()==0) return indices; 00743 T *v = data(); 00744 for (int i=0, m=elements.length(); i<m; i++) 00745 for (int j=0; j<length(); j++) 00746 if (v[j] == elements[i]) 00747 { 00748 indices[i] = j; 00749 break; 00750 } 00751 return indices; 00752 } 00753 00755 void print(ostream& out = cout) const; 00756 void println(ostream& out = cout) const { print(out); out<<endl; } 00757 void printcol(ostream& out = cout) const; 00758 void print(ostream& out, const string& separator) const; 00759 00760 void input(istream& in=cin) const; 00761 00762 // calls print with cerr, usefull with gdb (> call obj.debugprint() ) 00763 void debugPrint(){print(cerr);} 00764 00765 00766 void operator<<(const string& datastring) const 00767 { 00768 istrstream in(datastring.c_str()); 00769 input(in); 00770 } 00771 00772 }; 00773 00774 typedef TVec<real> Vec; 00775 00778 inline void operator<<(const Vec& v, real f) 00779 { v.fill(f); } 00780 00781 template<class T> 00782 class TypeTraits< TVec<T> > 00783 { 00784 public: 00785 static inline string name() 00786 { return string("TVec< ") + TypeTraits<T>::name()+" >"; } 00787 00788 static inline unsigned char little_endian_typecode() 00789 { return 0xFF; } 00790 00791 static inline unsigned char big_endian_typecode() 00792 { return 0xFF; } 00793 }; 00794 00795 00796 } // end of namespace PLearn 00797 00798 00799 #endif

Generated on Tue Aug 17 16:09:14 2004 for PLearn by doxygen 1.3.7