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

TMat_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: TMat_decl.h,v 1.4 2004/07/22 17:19:47 lapalmej Exp $ 00041 * AUTHORS: Pascal Vincent & Yoshua Bengio 00042 * This file is part of the PLearn library. 00043 ******************************************************* */ 00044 00045 00048 #ifndef TMat_decl_INC 00049 #define TMat_decl_INC 00050 00051 #include "TVec_impl.h" 00052 00053 namespace PLearn { 00054 using namespace std; 00055 00056 // predeclarations 00057 template<class T> class TMatElementIterator; 00058 template<class T> class TMatRowsIterator; 00059 template<class T> class TMatColRowsIterator; 00060 template<class T> class TMatRowsAsArraysIterator; 00061 00062 00063 template <class T> 00064 class TMat 00065 { 00066 friend class TVec<T>; 00067 friend class Variable; 00068 friend class VarArray; 00069 00070 protected: 00071 int offset_; 00072 int mod_; 00073 int length_; 00074 int width_; 00075 PP< Storage<T> > storage; 00077 public: 00078 00080 int nrows() const { return length_; } 00081 int ncols() const { return width_; } 00082 00083 public: 00084 00085 typedef T value_type; 00086 typedef int size_type; 00087 typedef TMatElementIterator<T> iterator; // iterator over elements 00088 typedef TMatElementIterator<T> const_iterator; // iterator over elements 00089 typedef T* compact_iterator; // super-efficient iterator over elements but works reliably only for compact matrices 00090 typedef T* rowelements_iterator; // iterator over elements of a 00091 // particular row 00092 typedef TMatRowsIterator<T> rows_iterator; 00093 typedef TMatRowsAsArraysIterator<T> rows_as_arrays_iterator; 00094 typedef TMatColRowsIterator<T> colrows_iterator; 00095 00096 TMat<T>() 00097 :offset_(0), mod_(0), length_(0), width_(0) 00098 {} 00099 00100 TMat<T>(int the_length, int the_width) 00101 :offset_(0), mod_(0), length_(0), width_(0) 00102 { resize(the_length, the_width); } 00103 00104 TMat<T>(int the_length, int the_width, const T& init_value) 00105 :offset_(0), mod_(0), length_(0), width_(0) 00106 { 00107 resize(the_length, the_width); 00108 fill(init_value); 00109 } 00110 00111 TMat<T>(int the_length, int the_width, T* the_data) 00112 :offset_(0), mod_(the_width), length_(the_length), width_(the_width), 00113 storage(new Storage<T>(the_length*the_width, the_data)) 00114 {} 00115 00116 TMat<T>(int the_length, int the_width, const TVec<T>& v); 00117 00119 inline const TMat<T>& operator=(const TMat<T>& other) 00120 { 00121 storage = other.storage; 00122 offset_ = other.offset_; 00123 mod_ = other.mod_; 00124 length_ = other.length_; 00125 width_ = other.width_; 00126 return *this; 00127 } 00128 00130 inline iterator begin() const; 00131 inline iterator end() const; 00132 00134 inline compact_iterator compact_begin() const 00135 { 00136 #ifdef BOUNDCHECK 00137 if(mod()!=width()) 00138 PLERROR("You cannot use a compact iterator to iterate over the elements of a non compact matrix"); 00139 #endif 00140 return data(); 00141 } 00142 00143 inline compact_iterator compact_end() const 00144 { return data()+size(); } 00145 00147 inline rowelements_iterator rowelements_begin(int rownum) const 00148 { 00149 #ifdef BOUNDCHECK 00150 if(rownum<0 || rownum>=length()) 00151 PLERROR("OUT OF RANGE rownum in rowelements_begin"); 00152 #endif 00153 return data()+rownum*mod(); 00154 } 00155 00158 inline rowelements_iterator rowelements_end(int rownum) const 00159 { return data()+rownum*mod()+width(); } 00160 00163 TMatRowsIterator<T> rows_begin(); 00164 TMatRowsIterator<T> rows_end(); 00165 00168 TMatRowsAsArraysIterator<T> rows_as_arrays_begin(); 00169 TMatRowsAsArraysIterator<T> rows_as_arrays_end(); 00170 00171 00175 TMatColRowsIterator<T> col_begin(int column); 00176 00180 TMatColRowsIterator<T> col_end(int column); 00181 00182 00189 void resize(int newlength, int newwidth, int extrabytes=0) 00190 { 00191 #ifdef BOUNDCHECK 00192 if(newlength<0 || newwidth<0) 00193 PLERROR("IN TMat::resize(int newlength, int newwidth)\nInvalid arguments (<0)"); 00194 #endif 00195 if (newlength==length_ && newwidth==width_) return; 00196 if(storage.isNull()) 00197 { 00198 offset_ = 0; 00199 length_ = newlength; 00200 width_ = newwidth; 00201 mod_ = newwidth; 00202 storage = new Storage<T>(length()*mod()); 00203 } 00204 else 00205 { 00206 if(storage->usage()>1 && newwidth > mod()-offset_%mod()) 00207 PLERROR("IN TMat::resize(int newlength, int newwidth)\nFor safety reasons, increasing the width() beyond mod() - offset_%mod() is not allowed when the storage is shared with others"); 00208 00209 int newsize = offset_+newlength*MAX(mod(),newwidth); 00210 if(offset_+newsize>storage->length()) 00211 storage->resize(offset_+newsize+extrabytes); 00212 length_ = newlength; 00213 width_ = newwidth; 00214 if(newwidth>mod()) 00215 mod_ = newwidth; 00216 } 00217 } 00218 00219 inline int length() const 00220 { return length_; } 00221 00222 inline int width() const 00223 { return width_; } 00224 00225 inline int size() const 00226 { return length_*width_; } 00227 00228 inline int mod() const 00229 { return mod_; } 00230 00231 inline PP< Storage<T> > getStorage() const 00232 { return storage; } 00233 00234 inline bool isSquare() const 00235 { return length() == width(); } 00236 00237 bool hasMissing() const 00238 { 00239 iterator it = begin(); 00240 iterator itend = end(); 00241 for(; it!=itend; ++it) 00242 if(is_missing(*it)) 00243 return true; 00244 return false; 00245 } 00246 00248 inline T* data() const 00249 { 00250 #ifdef BOUNDCHECK 00251 if(storage.isNull()) 00252 PLERROR("IN TMat::data()\nAttempted to get a pointer to the data of an empty matrix"); 00253 #endif 00254 return storage->data+offset_; 00255 } 00256 00258 inline T* operator[](int rownum) const 00259 { 00260 #ifdef BOUNDCHECK 00261 if(rownum<0 || rownum>=length()) 00262 PLERROR("OUT OF BOUND ACCESS IN TMat::operator[](int rownum=%d), length=%d",rownum,length()); 00263 #endif 00264 return storage->data + offset_ + mod()*rownum; 00265 } 00266 00267 inline T* rowdata(int i) const { return (*this)[i]; } 00268 00269 inline T& operator()(int rownum, int colnum) const 00270 { 00271 #ifdef BOUNDCHECK 00272 if(rownum<0 || rownum>=length() || colnum<0 || colnum>=width()) 00273 PLERROR("OUT OF BOUND ACCESS IN TMat::operator()(int rownum, int colnum)" 00274 " width=%d; length=%d; colnum=%d; rownum=%d;", width(), length(), colnum, rownum); 00275 #endif 00276 return storage->data[offset_ + mod()*rownum + colnum]; 00277 } 00278 00279 inline TVec<T> operator()(int rownum) const 00280 { 00281 #ifdef BOUNDCHECK 00282 if(rownum<0 || rownum>=length()) 00283 PLERROR("OUT OF BOUND ACCESS IN TMat_impl::operator()(int rownum)"); 00284 #endif 00285 TVec<T> tv; 00286 tv.length_ = width(); 00287 tv.offset_ = offset_ + mod()*rownum; 00288 tv.storage = storage; 00289 return tv; 00290 } 00291 00294 void write(PStream& out) const 00295 { 00296 T* ptr = 0; 00297 if(storage) 00298 ptr = data(); 00299 00300 switch(out.outmode) 00301 { 00302 case PStream::raw_ascii: 00303 case PStream::pretty_ascii: 00304 for(int i=0; i<length_; i++, ptr+=mod_) 00305 { 00306 for(int j=0; j<width_; j++) 00307 { 00308 out << ptr[j]; 00309 out.put('\t'); 00310 } 00311 out.put('\n'); 00312 } 00313 break; 00314 00315 case PStream::raw_binary: 00316 for(int i=0; i<length_; i++, ptr+=mod_) 00317 binwrite_(out, ptr, width_); 00318 break; 00319 00320 case PStream::plearn_ascii: 00321 { 00322 if(!out.implicit_storage) 00323 { 00324 out.write("TMat("); 00325 out << length_ << width_ << mod_ << offset_ << storage; 00326 out.write(")\n"); 00327 } 00328 else // implicit storage 00329 { 00330 out << length_; 00331 out.put(' '); 00332 out << width_; 00333 out.write(" [ \n"); 00334 for(int i=0; i<length_; i++, ptr+=mod_) 00335 { 00336 for(int j=0; j<width_; j++) 00337 { 00338 out << ptr[j]; 00339 out.put('\t'); 00340 } 00341 out.put('\n'); 00342 } 00343 out.write("]\n"); 00344 } 00345 } 00346 break; 00347 00348 case PStream::plearn_binary: 00349 { 00350 if(!out.implicit_storage) 00351 { 00352 out.write("TMat("); 00353 out << length_ << width_ << mod_ << offset_ << storage; 00354 out.write(")\n"); 00355 } 00356 else // implicit storage 00357 { 00358 unsigned char typecode; 00359 if(byte_order()==LITTLE_ENDIAN_ORDER) 00360 { 00361 out.put(0x14); // 2D little-endian 00362 typecode = TypeTraits<T>::little_endian_typecode(); 00363 } 00364 else 00365 { 00366 out.put(0x15); // 2D big-endian 00367 typecode = TypeTraits<T>::big_endian_typecode(); 00368 } 00369 00370 // write typecode 00371 out.put(typecode); 00372 00373 // write length and width in raw_binary 00374 out.write((char*)&length_, sizeof(length_)); 00375 out.write((char*)&width_, sizeof(width_)); 00376 00377 // write the data 00378 for(int i=0; i<length_; i++, ptr+=mod_) 00379 binwrite_(out, ptr, width_); 00380 } 00381 } 00382 break; 00383 00384 default: 00385 PLERROR("In TMat::write(PStream& out) unknown outmode!!!!!!!!!"); 00386 break; 00387 } 00388 } 00389 00390 00391 00394 void read(PStream& in) 00395 { 00396 switch(in.inmode) 00397 { 00398 case PStream::raw_ascii: 00399 case PStream::raw_binary: 00400 { 00401 T* ptr = data(); 00402 for(int i=0; i<length_; i++, ptr+=mod_) 00403 for(int j=0; j<width_; j++) 00404 in >> ptr[j]; 00405 } 00406 break; 00407 00408 case PStream::plearn_ascii: 00409 case PStream::plearn_binary: 00410 { 00411 in.skipBlanksAndComments(); 00412 int c = in.peek(); 00413 if(c=='T') // explicit storage 00414 { 00415 char word[6]; 00416 // !!!! BUG: For some reason, this hangs!!! 00417 // in.read(word,5); 00418 00419 for(int i=0; i<5; i++) 00420 in.get(word[i]); 00421 00422 word[5]='\0'; 00423 if(strcmp(word,"TMat(")!=0) 00424 PLERROR("In operator>>(PStream&, TMat&) '%s' not a proper header for a TMat!",word); 00425 // v.storage = 0; 00426 in >> length_ >> width_ >> mod_ >> offset_; 00427 in >> storage; 00428 in.skipBlanksAndCommentsAndSeparators(); 00429 int c = in.get(); // skip ')' 00430 if(c!=')') 00431 PLERROR("In operator>>(PStream&, TMat&) expected a closing parenthesis, found '%c'",c); 00432 } 00433 else // implicit storage 00434 { 00435 if(isdigit(c)) // ascii mode with length and width given 00436 { 00437 int l,w; 00438 in >> l >> w; 00439 in.skipBlanksAndComments(); 00440 c = in.get(); 00441 if(c!='[') 00442 PLERROR("Error in TMat::read(PStream& in), expected '[', read '%c'",c); 00443 in.skipBlanksAndCommentsAndSeparators(); 00444 resize(l,w); 00445 T* ptr = (l>0 && w>0)? data():0; 00446 for(int i=0; i<length_; i++, ptr+=mod_) 00447 for(int j=0; j<width_; j++) 00448 { 00449 in.skipBlanksAndCommentsAndSeparators(); 00450 in >> ptr[j]; 00451 } 00452 in.skipBlanksAndCommentsAndSeparators(); 00453 c = in.get(); 00454 if(c!=']') 00455 PLERROR("Error in TMat::read(PStream& in), expected ']', read '%c'",c); 00456 } 00457 else if(c==0x14 || c==0x15) // it's a binary 2D sequence 00458 { 00459 in.get(); // eat c 00460 unsigned char typecode = in.get(); 00461 int l, w; 00462 in.read((char*)&l,sizeof(l)); 00463 in.read((char*)&w,sizeof(w)); 00464 bool inverted_byte_order = ((c==0x14 && byte_order()==BIG_ENDIAN_ORDER) 00465 || (c==0x15 && byte_order()==LITTLE_ENDIAN_ORDER) ); 00466 if(inverted_byte_order) 00467 { 00468 endianswap(&l); 00469 endianswap(&w); 00470 } 00471 resize(l,w); 00472 T* ptr = data(); 00473 for(int i=0; i<length_; i++, ptr+=mod_) 00474 binread_(in, ptr, width_, typecode); 00475 } 00476 else 00477 PLERROR("In TMat::read(PStream& in) Char with ascii code %d not a proper first character in the header of a TMat!",c); 00478 } 00479 } 00480 break; 00481 00482 default: 00483 PLERROR("In TMat<T>::read(PStream& in) unknown inmode!!!!!!!!!"); 00484 break; 00485 } 00486 } 00487 00488 // The following methods are deprecated, and just call corresponding functions. 00489 // Please call those functions directly in new code 00490 //void write(ostream& out) const { PLearn::write(out, *this); } 00491 //void read(istream& in) { PLearn::read(in, *this); } 00492 void save(const string& filename) const { savePMat(filename, *this); } 00493 void load(const string& filename) { loadPMat(filename, *this); } 00494 00496 inline TMat<T> column(int colnum) const 00497 { return subMatColumns(colnum, 1); } 00498 00499 inline TMat<T> firstColumn() const 00500 { return column(0); } 00501 00502 inline TMat<T> lastColumn() const 00503 { return column(width()-1); } 00504 00506 inline TMat<T> row(int row) const 00507 { return subMatRows(row, 1); } 00508 00509 inline T& firstElement() const { return *data(); } 00510 inline T& lastElement() const { return operator()(length-1,width-1); } 00511 00512 inline TVec<T> firstRow() const { return operator()(0); } 00513 inline TVec<T> lastRow() const { return operator()(length_ - 1); } 00514 inline TVec<T> front() const { return firstRow(); } 00515 inline TVec<T> back() const { return lastRow(); } 00516 00519 template<class I> 00520 inline TMat<T> columns(const TVec<I>& columns) const 00521 { 00522 TMat<T> result(length(),columns.length()); 00523 selectColumns(*this,columns,result); 00524 return result; 00525 } 00526 00529 template<class I> 00530 inline TMat<T> rows(const TVec<I>& rows) const 00531 { 00532 TMat<T> result(rows.length(),width()); 00533 selectRows(*this,rows,result); 00534 return result; 00535 } 00536 00537 inline bool operator==(const TMat<T>& other) const 00538 { 00539 if(length() != other.length() || width() != other.width()) 00540 return false; 00541 00542 iterator it = begin(); 00543 iterator end = end(); 00544 iterator otherIt = other.begin(); 00545 for(; it != end; ++it) 00546 if(*it == *otherIt) 00547 ++otherIt; 00548 else 00549 return false; 00550 00551 return true; 00552 } 00553 00554 template<class I> 00555 inline TMat<T> operator()(const TVec<I>& rows, const TVec<I>& columns) const 00556 { 00557 TMat<T> result(rows.length(),columns.length()); 00558 select(*this,rows,columns,result); 00559 return result; 00560 } 00561 00563 inline TMat<T> subMat(int rowstart, int colstart, int newlength, int newwidth) const 00564 { 00565 #ifdef BOUNDCHECK 00566 if(rowstart<0 || newlength<0 || rowstart+newlength>length() 00567 || colstart<0 || newwidth<0 || colstart+newwidth>width()) 00568 PLERROR("Mat::subMat(int rowstart, int colstart, int newlength, int newwidth) OUT OF BOUNDS" 00569 " rowstart=%d colstart=%d newlength=%d newwidth=%d length()=%d width()=%d", 00570 rowstart, colstart, newlength, newwidth, length(), width()); 00571 #endif 00572 TMat<T> subm = *this; 00573 subm.length_ = newlength; 00574 subm.width_ = newwidth; 00575 subm.offset_ += rowstart*mod() + colstart; 00576 return subm; 00577 } 00578 00580 inline TMat<T> subMatRows(int rowstart, int newlength) const 00581 { 00582 #ifdef BOUNDCHECK 00583 if(rowstart<0 || newlength<0 || rowstart+newlength>length()) 00584 PLERROR("TMat::subMatRows(int rowstart, int newlength) OUT OF BOUNDS"); 00585 #endif 00586 TMat<T> subm = *this; 00587 subm.length_ = newlength; 00588 subm.offset_ += rowstart*mod(); 00589 return subm; 00590 } 00591 00593 inline TMat<T> subMatColumns(int colstart, int newwidth) const 00594 { 00595 #ifdef BOUNDCHECK 00596 if(colstart<0 || newwidth<0 || colstart+newwidth>width()) 00597 PLERROR("Mat::subMatColumns(int colstart, int newwidth) OUT OF BOUNDS"); 00598 #endif 00599 TMat<T> subm = *this; 00600 subm.width_ = newwidth; 00601 subm.offset_ += colstart; 00602 return subm; 00603 } 00604 00606 TMat<T> copy() const 00607 { 00608 TMat<T> freshcopy(length(),width()); 00609 freshcopy << *this; 00610 return freshcopy; 00611 } 00612 00614 void copyTo(T* x) const 00615 { 00616 T* row = data(); // get data start 00617 int k=0; 00618 for(int i=0; i<length(); i++,row+=mod()) 00619 for (int j=0;j<width();j++,k++) 00620 x[k] = row[j]; 00621 } 00622 00628 void makeDeepCopyFromShallowCopy(map<const void*, void*>& copies); 00629 00634 TMat<T> deepCopy(map<const void*, void*>& copies) const; 00635 00636 00638 TVec<T> toVecCopy() const; 00639 00641 TVec<T> toVec() const; 00642 00643 bool isNull() const 00644 { return storage.isNull(); } 00645 00646 bool isNotNull() const 00647 { return storage.isNotNull(); } 00648 00649 bool isEmpty() const 00650 { return length_==0; } 00651 00652 bool isNotEmpty() const 00653 { return length_!=0; } 00654 00658 /* 00660 inline operator bool() const 00661 { return isNotEmpty(); } 00662 */ 00663 00665 inline bool operator!() const 00666 { return isEmpty(); } 00667 00668 void fill(const T& value) const 00669 { 00670 if (isNotNull()) { 00671 if(isCompact()) 00672 fill_n(data(),size(),value); 00673 else 00674 { 00675 int l = length(); 00676 T* ptr = data(); 00677 while(l--) 00678 { 00679 fill_n(ptr, width(), value); 00680 ptr += mod(); 00681 } 00682 } 00683 } 00684 } 00685 00686 inline void operator=(const T& f) const 00687 { fill(f); } 00688 00689 inline void clear() const 00690 { 00691 if(isCompact()) 00692 clear_n(data(),size()); 00693 else 00694 { 00695 int l = length(); 00696 T* ptr = data(); 00697 while(l--) 00698 { 00699 clear_n(ptr, width()); 00700 ptr += mod(); 00701 } 00702 } 00703 } 00704 00706 void swapRows(int i, int j) const 00707 { 00708 if(i!=j) 00709 { 00710 //T* Mi = rowdata(i); 00711 //T* Mj = rowdata(j); 00712 T* Mi = (*this)[i]; 00713 T* Mj = (*this)[j]; 00714 for (int k=0;k<width();k++) 00715 { 00716 T tmp = Mi[k]; 00717 Mi[k] = Mj[k]; 00718 Mj[k] = tmp; 00719 } 00720 } 00721 } 00722 00723 int findRow(const TVec<T>& row) const; 00724 00725 inline void appendRow(const TVec<T>& newrow); 00726 00728 inline void push_back(const TVec<T>& newrow) { appendRow(newrow); } 00729 inline void pop_back() { length_ -= 1; } 00730 00731 00732 bool isCompact() const 00733 { return mod() == width(); } 00734 00735 bool isSymmetric() const 00736 { 00737 if (!isSquare()) 00738 return false; 00739 00740 if (length() == 0) 00741 { 00742 PLWARNING("at bool TMat::isSymmetric(), the size of the matrix is 0\n"); 00743 return false; 00744 } 00745 00746 for (int i = 0; i < length() - 1 ; i++) 00747 for (int j = i + 1; j < width(); j++) 00748 if ( (*this)[i][j] != (*this)[j][i] ) 00749 return false; 00750 00751 return true; 00752 } 00753 00755 void compact() 00756 { 00757 if(storage->length() != length()*width()) 00758 { 00759 if(storage->usage()>1) 00760 PLERROR("IN Mat::compact() compact operation not allowed when matrix storage is shared (for obvious reasons)"); 00761 operator=(copy()); 00762 } 00763 } 00764 00765 void transpose() 00766 { 00767 if(mod()!=width()) 00768 PLERROR("In transpose() can transpose in place only compact matrices whose mod()==width() (that is often not the case for submatrices"); 00769 for(int i=0; i<length(); i++) 00770 { 00771 //T* rowi = rowdata(i); 00772 T* rowi = (*this)[i]; 00773 T* colielem = rowi+i+mod(); 00774 for(int j=i+1; j<width(); j++, colielem+=mod()) 00775 swap(rowi[j], *colielem); 00776 } 00777 } 00778 00779 void swapUpsideDown() const 00780 { 00781 int half = length()/2; 00782 for(int i=0; i<half; i++) 00783 swapRows(i, length()-i-1); 00784 } 00785 00787 void print(ostream& out = cout) const; 00788 void input(istream& in = cin) const; 00789 00790 // calls print with cerr, usefull with gdb (> call obj.debugprint() ) 00791 void debugPrint(){print(cerr);} 00792 00793 00794 inline void operator<<(const string& datastring) const 00795 { 00796 istrstream in(datastring.c_str()); 00797 input(in); 00798 } 00799 00800 }; 00801 00802 typedef TMat<real> Mat; 00803 00804 00805 // Type traits (especially type "names" for displaying optionHelp() ) 00806 00807 template<class T> 00808 class TypeTraits< TMat<T> > 00809 { 00810 public: 00811 static inline string name() 00812 { return string("TMat< ") + TypeTraits<T>::name()+" >"; } 00813 00814 static inline unsigned char little_endian_typecode() 00815 { return 0xFF; } 00816 00817 static inline unsigned char big_endian_typecode() 00818 { return 0xFF; } 00819 }; 00820 00821 } // end of namespace PLearn 00822 #endif

Generated on Tue Aug 17 16:08:43 2004 for PLearn by doxygen 1.3.7