PLearn 0.1
|
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 :