matrix.h

00001 /* MLPACK 0.2
00002  *
00003  * Copyright (c) 2008, 2009 Alexander Gray,
00004  *                          Garry Boyer,
00005  *                          Ryan Riegel,
00006  *                          Nikolaos Vasiloglou,
00007  *                          Dongryeol Lee,
00008  *                          Chip Mappus, 
00009  *                          Nishant Mehta,
00010  *                          Hua Ouyang,
00011  *                          Parikshit Ram,
00012  *                          Long Tran,
00013  *                          Wee Chin Wong
00014  *
00015  * Copyright (c) 2008, 2009 Georgia Institute of Technology
00016  *
00017  * This program is free software; you can redistribute it and/or
00018  * modify it under the terms of the GNU General Public License as
00019  * published by the Free Software Foundation; either version 2 of the
00020  * License, or (at your option) any later version.
00021  *
00022  * This program is distributed in the hope that it will be useful, but
00023  * WITHOUT ANY WARRANTY; without even the implied warranty of
00024  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00025  * General Public License for more details.
00026  *
00027  * You should have received a copy of the GNU General Public License
00028  * along with this program; if not, write to the Free Software
00029  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00030  * 02110-1301, USA.
00031  */
00038 #ifndef LA_MATRIX_H
00039 #define LA_MATRIX_H
00040 
00041 #include "fastlib/base/base.h"
00042 #ifndef DISABLE_DISK_MATRIX
00043 #include "fastlib/mmanager/memory_manager.h"
00044 #endif
00045 
00046 #include <stdlib.h>
00047 #include <string.h>
00048 #include <math.h>
00049 
00073 template<typename T>
00074 class GenVector {
00075  private:
00077   T *ptr_;
00079   index_t length_;
00081   bool should_free_;
00082   
00083   OBJECT_TRAVERSAL_ONLY(GenVector) {
00084     OT_OBJ(length_);
00085     OT_ALLOC(ptr_, length_);
00086   }
00087   OT_REFILL_TRANSIENTS(GenVector) {
00088     should_free_ = true;
00089   }
00090   
00091  public:
00095   GenVector() {
00096     DEBUG_ONLY(Uninitialize_());
00097   }
00098   
00102   GenVector(const GenVector& other) {
00103     DEBUG_ONLY(Uninitialize_());
00104     Copy(other);
00105   }
00106   ASSIGN_VIA_COPY_CONSTRUCTION(GenVector);
00107   
00111   ~GenVector() {
00112     Destruct();
00113   }
00114   
00118   void Destruct() {
00119     DEBUG_ASSERT_MSG(ptr_ != BIG_BAD_POINTER(T),
00120        "You forgot to initialize a Vector before it got automatically freed.");
00121     
00122     /* mark slow case as "unlikely" even if it might be the likely case */
00123     if (unlikely(should_free_)) {
00124       mem::DebugPoison(ptr_, length_);
00125       mem::Free(ptr_);
00126     }
00127     
00128     DEBUG_ONLY(Uninitialize_());
00129   }
00130 
00135   void Init(index_t in_length) {
00136     ptr_ = mem::Alloc<T>(in_length);
00137     length_ = in_length;
00138     should_free_ = true;
00139   }
00140   
00145   void StaticInit(index_t in_length) {
00146 #ifndef DISABLE_DISK_MATRIX
00147     ptr_ = mmapmm::MemoryManager<false>::allocator_->Alloc<T>(in_length);
00148     length_ = in_length;
00149     should_free_ = false;
00150 #else
00151     Init(in_length);
00152 #endif
00153   }
00154 
00158   void SetAll(T d) {
00159     mem::RepeatConstruct(ptr_, d, length_);
00160   }
00161   
00165   void SetZero() {
00166     // TODO: if IEEE is used, this can be done efficiently with memset
00167     SetAll(0);
00168   }
00169 
00175   void Copy(const GenVector& other) {
00176     Copy(other.ptr(), other.length());
00177   }
00178 
00185   void Copy(const T *doubles, index_t in_length) {
00186     DEBUG_ONLY(AssertUninitialized_());
00187     
00188     ptr_ = mem::AllocCopy(doubles, in_length);
00189     length_ = in_length;
00190     should_free_ = true;
00191   }
00192 
00199   void StaticCopy(const GenVector& other) {
00200     StaticCopy(other.ptr(), other.length());
00201   }
00202 
00210   void StaticCopy(const T *doubles, index_t in_length) {
00211 #ifndef DISABLE_DISK_MATRIX
00212     DEBUG_ONLY(AssertUninitialized_());
00213     
00214     ptr_ = mmapmm::MemoryManager<false>::allocator_->Alloc<T>(in_length);
00215     mem::Copy<T, T, T>(ptr_, doubles, in_length);
00216     length_ = in_length;
00217     should_free_ = false;
00218 #else
00219     Copy(doubles, in_length);
00220 #endif
00221   }
00222   
00226   void Alias(T *in_ptr, index_t in_length) {
00227     DEBUG_ONLY(AssertUninitialized_());
00228     
00229     ptr_ = in_ptr;
00230     length_ = in_length;
00231     should_free_ = false;
00232   }
00233   
00237   void WeakCopy(const GenVector& other) {
00238     Alias(other);
00239   }
00240   
00246   void Alias(const GenVector& other) {
00247     // we trust in good faith that a const vector won't be abused
00248     Alias(other.ptr_, other.length());
00249   }
00250   
00259   void Own(GenVector* other) {
00260     Own(other->ptr_, other->length());
00261     
00262     DEBUG_ASSERT(other->should_free_);
00263     other->should_free_ = false;
00264   }
00265   
00270   void Own(T *in_ptr, index_t in_length) {
00271     DEBUG_ONLY(AssertUninitialized_());
00272     
00273     ptr_ = in_ptr;
00274     length_ = in_length;
00275     should_free_ = true;
00276   }
00277   
00286   void StaticOwn(GenVector* other) {
00287 #ifndef DISABLE_DISK_MATRIX
00288     StaticOwn(other->ptr_, other->length());
00289 #else
00290     Own(other);
00291 #endif
00292   }
00293   
00298   void StaticOwn(T *in_ptr, index_t in_length) {
00299 #ifndef DISABLE_DISK_MATRIX
00300     DEBUG_ONLY(AssertUninitialized_());
00301     
00302     ptr_ = in_ptr;
00303     length_ = in_length;
00304     should_free_ = false;
00305 #else
00306     Own(in_ptr, in_length);
00307 #endif
00308   }
00309   
00318   void MakeSubvector(index_t start_index, index_t len, GenVector* dest) {
00319     DEBUG_BOUNDS(start_index, length_);
00320     DEBUG_BOUNDS(start_index + len, length_ + 1);
00321     
00322     dest->Alias(ptr_ + start_index, len);
00323   }
00324   
00333   void SwapValues(GenVector* other) {
00334     DEBUG_ASSERT(length() == other->length());
00335     mem::Swap(ptr_, other->ptr_, length_);
00336   }
00337   
00343   void CopyValues(const GenVector& other) {
00344     DEBUG_ASSERT(length() == other.length());
00345     mem::Copy(ptr_, other.ptr_, length_);
00346   }
00347 
00354   void CopyValues(const T *src_ptr) {
00355     mem::Copy(ptr_, src_ptr, length_);
00356   }
00357   
00364   void PrintDebug(const char *name = "", FILE *stream = stderr) const {
00365     fprintf(stream, "----- VECTOR %s ------\n", name);
00366     for (index_t i = 0; i < length(); i++) {
00367       fprintf(stream, "%+3.3f ", get(i));
00368     }
00369     fprintf(stream, "\n");
00370   }
00371   
00372  public:
00374   index_t length() const {
00375     return length_;
00376   }
00377   
00381   T *ptr() {
00382     return ptr_;
00383   }
00384   
00388   const T *ptr() const {
00389     return ptr_;
00390   }
00391   
00395   T operator [] (index_t i) const {
00396     DEBUG_BOUNDS(i, length_);
00397     return ptr_[i];
00398   }
00399   
00403   T &operator [] (index_t i) {
00404     DEBUG_BOUNDS(i, length_);
00405     return ptr_[i];
00406   }
00407   
00421   T get(index_t i) const {
00422     DEBUG_BOUNDS(i, length_);
00423     return ptr_[i];
00424   }
00425   
00426  private:
00427   void AssertUninitialized_() const {
00428     DEBUG_ASSERT_MSG(length_ == BIG_BAD_NUMBER, "Cannot re-init vectors.");
00429   }
00430   
00431   void Uninitialize_() {
00432     DEBUG_ONLY(ptr_ = BIG_BAD_POINTER(T));
00433     DEBUG_ONLY(length_ = BIG_BAD_NUMBER);
00434   }
00435   
00436   void AssertInitialized_() {
00437     DEBUG_ASSERT_MSG(ptr_ != BIG_BAD_POINTER(T),
00438         "Vector was not initialized.");
00439   }
00440 };
00441 
00444 typedef GenVector<double> Vector;
00445 
00456 template<typename T>
00457 class GenMatrix {
00458  private:
00460   T *ptr_;
00462   index_t n_rows_;
00464   index_t n_cols_;
00466   bool should_free_;
00467 
00468   OBJECT_TRAVERSAL_ONLY(GenMatrix) {
00469     OT_OBJ(n_rows_);
00470     OT_OBJ(n_cols_);
00471     OT_ALLOC(ptr_, n_elements());
00472   }
00473   OT_REFILL_TRANSIENTS(GenMatrix) {
00474     should_free_ = false;
00475   }
00476 
00477  public:
00481   GenMatrix(index_t in_rows, index_t in_cols) {
00482     DEBUG_ONLY(Uninitialize_());
00483     Init(in_rows, in_cols);
00484   }
00485 
00489   GenMatrix(const GenMatrix<T>& other) {
00490     DEBUG_ONLY(Uninitialize_());
00491     Copy(other);
00492   }
00493   ASSIGN_VIA_COPY_CONSTRUCTION(GenMatrix);
00494 
00498   GenMatrix() {
00499     DEBUG_ONLY(Uninitialize_());
00500   }
00501 
00505   ~GenMatrix() {
00506     Destruct();
00507   }
00508   
00513   void Destruct() {
00514     DEBUG_ASSERT_MSG(ptr_ != BIG_BAD_POINTER(T),
00515        "You forgot to initialize a Matrix before it got automatically freed.");
00516     if (unlikely(should_free_)) {
00517       mem::DebugPoison(ptr_, n_rows_ * n_cols_);
00518       mem::Free(ptr_);
00519       DEBUG_ONLY(Uninitialize_());
00520     }
00521     DEBUG_POISON_PTR(ptr_);
00522     DEBUG_ONLY(n_rows_ = BIG_BAD_NUMBER);
00523     DEBUG_ONLY(n_cols_ = BIG_BAD_NUMBER);
00524   }
00525 
00529   void Init(index_t in_rows, index_t in_cols) {
00530     DEBUG_ONLY(AssertUninitialized_());
00531     ptr_ = mem::Alloc<T>(in_rows * in_cols);
00532     n_rows_ = in_rows;
00533     n_cols_ = in_cols;
00534     should_free_ = true;
00535   }
00536 
00540   void InitDiagonal(const GenVector<T>& v) {
00541     Init(v.length(), v.length());
00542     SetDiagonal(v);
00543   }
00544 
00549   void StaticInit(index_t in_rows, index_t in_cols) {
00550 #ifndef DISABLE_DISK_MATRIX
00551     DEBUG_ONLY(AssertUninitialized_());
00552     ptr_ = mmapmm::MemoryManager<false>::allocator_->Alloc<T>
00553       (in_rows * in_cols);
00554     n_rows_ = in_rows;
00555     n_cols_ = in_cols;
00556     should_free_ = false;
00557 #else
00558     Init(in_rows, in_cols);
00559 #endif
00560   }
00561 
00565   void StaticInitDiagonal(const GenVector<T>& v) {
00566     StaticInit(v.length(), v.length());
00567     SetDiagonal(v);
00568   }
00569 
00573   void SetAll(T d) {
00574     mem::RepeatConstruct(ptr_, d, n_elements());
00575   }
00576 
00580   void SetZero() {
00581     // TODO: If IEEE floating point is used, this can just be a memset to
00582     // zero
00583     SetAll(0);
00584   }
00585 
00589   void SetDiagonal(const GenVector<T>& v) {
00590     DEBUG_ASSERT(n_rows() == v.length());
00591     DEBUG_ASSERT(n_cols() == v.length());
00592     SetZero();
00593     index_t n = v.length();
00594     for (index_t i = 0; i < n; i++) {
00595       set(i, i, v[i]);
00596     }
00597   }
00598 
00604   void Copy(const GenMatrix& other) {
00605     Copy(other.ptr(), other.n_rows(), other.n_cols());    
00606   }
00607 
00615   void Copy(const T *ptr_in, index_t n_rows_in, index_t n_cols_in) {
00616     DEBUG_ONLY(AssertUninitialized_());
00617     
00618     ptr_ = mem::AllocCopy(ptr_in, n_rows_in * n_cols_in);
00619     n_rows_ = n_rows_in;
00620     n_cols_ = n_cols_in;
00621     should_free_ = true;
00622   }
00623 
00630   void StaticCopy(const GenMatrix& other) {
00631     StaticCopy(other.ptr(), other.n_rows(), other.n_cols());    
00632   }
00633 
00642   void StaticCopy(const T *ptr_in, index_t n_rows_in, index_t n_cols_in) {
00643 #ifndef DISABLE_DISK_MATRIX
00644     DEBUG_ONLY(AssertUninitialized_());
00645 
00646     ptr_ = mmapmm::MemoryManager<false>::allocator_->Alloc<T>
00647       (n_rows_in * n_cols_in);
00648     mem::Copy<T, T, T>(ptr_, ptr_in, n_rows_in * n_cols_in);
00649 
00650     n_rows_ = n_rows_in;
00651     n_cols_ = n_cols_in;
00652     should_free_ = false;
00653 #else
00654     Copy(ptr_in, n_rows_in, n_cols_in);
00655 #endif
00656   }
00657  
00665   void Alias(const GenMatrix& other) {
00666     // we trust in good faith that const-ness won't be abused
00667     Alias(other.ptr_, other.n_rows(), other.n_cols());
00668   }
00669   
00677   void Alias(T *ptr_in, index_t n_rows_in, index_t n_cols_in) {
00678     DEBUG_ONLY(AssertUninitialized_());
00679     
00680     ptr_ = ptr_in;
00681     n_rows_ = n_rows_in;
00682     n_cols_ = n_cols_in;
00683     should_free_ = false;
00684   }
00685   
00691   void AliasRowVector(const GenVector<T>& row_vector) {
00692     Alias(const_cast<T*>(row_vector.ptr()), 1, row_vector.length());
00693   }
00694   
00700   void AliasColVector(const GenVector<T>& col_vector) {
00701     Alias(const_cast<T*>(col_vector.ptr()), col_vector.length(), 1);
00702   }
00703   
00709   void WeakCopy(const GenMatrix& other) {
00710     Alias(other);
00711   }
00712   
00722   void Own(GenMatrix* other) {
00723     Own(other->ptr(), other->n_rows(), other->n_cols());
00724     
00725     DEBUG_ASSERT(other->should_free_);
00726     other->should_free_ = false;
00727   }
00728   
00738   void Own(T *ptr_in, index_t n_rows_in, index_t n_cols_in) {
00739     DEBUG_ONLY(AssertUninitialized_());
00740     
00741     ptr_ = ptr_in;
00742     n_rows_ = n_rows_in;
00743     n_cols_ = n_cols_in;
00744     should_free_ = true;
00745   }
00746 
00756   void StaticOwn(GenMatrix* other) {
00757 #ifndef DISABLE_DISK_MATRIX
00758     StaticOwn(other->ptr(), other->n_rows(), other->n_cols());
00759 #else
00760     Own(other);
00761 #endif
00762   }
00763   
00773   void StaticOwn(T *ptr_in, index_t n_rows_in, index_t n_cols_in) {
00774 #ifndef DISABLE_DISK_MATRIX
00775     DEBUG_ONLY(AssertUninitialized_());
00776     
00777     ptr_ = ptr_in;
00778     n_rows_ = n_rows_in;
00779     n_cols_ = n_cols_in;
00780     should_free_ = false;
00781 #else
00782     Own(ptr_in, n_rows_in, n_cols_in);
00783 #endif
00784   }
00785 
00793   void MakeColumnSlice(index_t start_col, index_t n_cols_new,
00794       GenMatrix *dest) const {
00795     DEBUG_BOUNDS(start_col, n_cols_);
00796     DEBUG_BOUNDS(start_col + n_cols_new, n_cols_ + 1);
00797     dest->Alias(ptr_ + start_col * n_rows_,
00798         n_rows_, n_cols_new);
00799   }
00800   
00821   void MakeReshaped(index_t n_rows_in, index_t n_cols_in,
00822       GenMatrix *dest) const {
00823     DEBUG_ASSERT(n_rows_in * n_cols_in == n_rows() * n_cols());
00824     dest->Alias(ptr_, n_rows_in, n_cols_in);
00825   }
00826   
00834   void MakeColumnVector(index_t col, GenVector<T> *dest) const {
00835     DEBUG_BOUNDS(col, n_cols_);
00836     dest->Alias(n_rows_ * col + ptr_, n_rows_);
00837   }
00838   
00848   void MakeColumnSubvector(index_t col, index_t start_row, index_t n_rows_new,
00849       GenVector<T> *dest) const {
00850     DEBUG_BOUNDS(col, n_cols_);
00851     DEBUG_BOUNDS(start_row, n_rows_);
00852     DEBUG_BOUNDS(start_row + n_rows_new, n_rows_ + 1);
00853     dest->Alias(n_rows_ * col + start_row + ptr_, n_rows_new);
00854   }
00855   
00864   T *GetColumnPtr(index_t col) {
00865     DEBUG_BOUNDS(col, n_cols_);
00866     return n_rows_ * col + ptr_;
00867   }
00868   
00877   const T *GetColumnPtr(index_t col) const {
00878     DEBUG_BOUNDS(col, n_cols_);
00879     return n_rows_ * col + ptr_;
00880   }
00881   
00889    void CopyColumnFromMat(index_t col1, index_t col2, GenMatrix<T> &mat) {
00890      DEBUG_BOUNDS(col1, n_cols_);
00891      DEBUG_BOUNDS(col2, mat.n_cols());
00892      DEBUG_ASSERT(n_rows_==mat.n_rows());
00893      memcpy(ptr_ + n_rows_ * col1, mat.GetColumnPtr(col2), n_rows_*sizeof(T));
00894    }
00903    void CopyColumnFromMat(index_t col1, index_t col2, index_t ncols, GenMatrix<T> &mat) {
00904      DEBUG_BOUNDS(col1, n_cols_);
00905      DEBUG_BOUNDS(col2, mat.n_cols());
00906      DEBUG_BOUNDS(col1+ncols-1, n_cols_);
00907      DEBUG_BOUNDS(col2+ncols-1, mat.n_cols());
00908      DEBUG_ASSERT(n_rows_==mat.n_rows());
00909      memcpy(ptr_ + n_rows_ * col1, mat.GetColumnPtr(col2), ncols*n_rows_*sizeof(T));
00910    }
00911 
00917    void CopyVectorToColumn(index_t col, GenVector<T> &vec) {
00918      DEBUG_BOUNDS(col, n_cols_);
00919      memcpy(ptr_ + n_rows_ * col, vec.ptr(), n_rows_*sizeof(T));
00920    }
00921  
00930   void ResizeNoalias(index_t new_n_cols) {
00931     DEBUG_ASSERT(should_free_); // the best assert we can do
00932     n_cols_ = new_n_cols;
00933     ptr_ = mem::Realloc(ptr_, n_elements());
00934   }
00935   
00944   void SwapValues(GenMatrix* other) {
00945     DEBUG_ASSERT(n_cols() == other->n_cols());
00946     DEBUG_ASSERT(n_rows() == other->n_rows());
00947     mem::Swap(ptr_, other->ptr_, n_elements());
00948   }
00949   
00955   void CopyValues(const GenMatrix& other) {
00956     DEBUG_ASSERT(n_rows() == other.n_rows());
00957     DEBUG_ASSERT(n_cols() == other.n_cols());
00958     mem::Copy(ptr_, other.ptr_, n_elements());
00959   }
00960 
00967   void PrintDebug(const char *name = "", FILE *stream = stderr) const {
00968     fprintf(stream, "----- MATRIX %s ------\n", name);
00969     for (index_t r = 0; r < n_rows(); r++) {
00970       for (index_t c = 0; c < n_cols(); c++) {
00971         fprintf(stream, "%+3.3f ", get(r, c));
00972       }
00973       fprintf(stream, "\n");
00974     }
00975   }
00976   
00977  public:
00984   const T *ptr() const {
00985     return ptr_;
00986   }
00987   
00994   T *ptr() {
00995     return ptr_;
00996   }
00997   
01004   T get(index_t r, index_t c) const {
01005     DEBUG_BOUNDS(r, n_rows_);
01006     DEBUG_BOUNDS(c, n_cols_);
01007     return ptr_[c * n_rows_ + r];
01008   }
01009  
01017   void set(index_t r, index_t c, T v) {
01018     DEBUG_BOUNDS(r, n_rows_);
01019     DEBUG_BOUNDS(c, n_cols_);
01020     ptr_[c * n_rows_ + r] = v;
01021   }
01022   
01030   T &ref(index_t r, index_t c) {
01031     DEBUG_BOUNDS(r, n_rows_);
01032     DEBUG_BOUNDS(c, n_cols_);
01033     return ptr_[c * n_rows_ + r];
01034   }
01035   
01037   index_t n_cols() const {
01038     return n_cols_;
01039   }
01040   
01042   index_t n_rows() const {
01043     return n_rows_;
01044   }
01045   
01052   size_t n_elements() const {
01053     // TODO: putting the size_t on the outside may be faster (32-bit
01054     // versus 64-bit multiplication in cases) but is more likely to result
01055     // in bugs
01056     return size_t(n_rows_) * size_t(n_cols_);
01057   }
01058   
01059  private:
01060   void AssertUninitialized_() const {
01061     DEBUG_ASSERT_MSG(n_rows_ == BIG_BAD_NUMBER, "Cannot re-init matrices.");
01062   }
01063   
01064   void Uninitialize_() {
01065     DEBUG_POISON_PTR(ptr_);
01066     DEBUG_ONLY(n_rows_ = BIG_BAD_NUMBER);
01067     DEBUG_ONLY(n_cols_ = BIG_BAD_NUMBER);
01068   } 
01069 
01070 };
01071 
01075 template<int t_length>
01076 class SmallVector : public Vector {
01077  private:
01078   double array_[t_length];
01079   
01080  public:
01081   SmallVector() {
01082     Alias(array_, t_length);
01083   }
01084   ~SmallVector() {}
01085   
01086  public:
01087   index_t length() const {
01088     return t_length;
01089   }
01090 
01091   double *ptr() {
01092     return array_;
01093   }
01094   
01095   const double *ptr() const {
01096     return array_;
01097   }
01098   
01099   double operator [] (index_t i) const {
01100     DEBUG_BOUNDS(i, t_length);
01101     return array_[i];
01102   }
01103   
01104   double &operator [] (index_t i) {
01105     DEBUG_BOUNDS(i, t_length);
01106     return array_[i];
01107   }
01108   
01109   double get(index_t i) const {
01110     DEBUG_BOUNDS(i, t_length);
01111     return array_[i];
01112   }
01113 };
01114 
01117 typedef GenMatrix<double> Matrix;
01118 
01122 template<int t_rows, int t_cols>
01123 class SmallMatrix : public Matrix {
01124  private:
01125   double array_[t_cols][t_rows];
01126 
01127  public:
01128   SmallMatrix() {
01129     Alias(array_[0], t_rows, t_cols);
01130   }
01131   ~SmallMatrix() {}
01132 
01133  public:
01134   const double *ptr() const {
01135     return array_[0];
01136   }
01137 
01138   double *ptr() {
01139     return array_[0];
01140   }
01141 
01142   double get(index_t r, index_t c) const {
01143     DEBUG_BOUNDS(r, t_rows);
01144     DEBUG_BOUNDS(c, t_cols);
01145     return array_[c][r];
01146   }
01147 
01148   void set(index_t r, index_t c, double v) {
01149     DEBUG_BOUNDS(r, t_rows);
01150     DEBUG_BOUNDS(c, t_cols);
01151     array_[c][r] = v;
01152   }
01153 
01154   double &ref(index_t r, index_t c) {
01155     DEBUG_BOUNDS(r, t_rows);
01156     DEBUG_BOUNDS(c, t_cols);
01157     return array_[c][r];
01158   }
01159 
01160   index_t n_cols() const {
01161     return t_cols;
01162   }
01163 
01164   index_t n_rows() const {
01165     return t_rows;
01166   }
01167 
01168   size_t n_elements() const {
01169     // TODO: putting the size_t on the outside may be faster (32-bit
01170     // versus 64-bit multiplication in cases) but is more likely to result
01171     // in bugs
01172     return size_t(t_rows) * size_t(t_cols);
01173   }
01174 
01175   double *GetColumnPtr(index_t col) {
01176     DEBUG_BOUNDS(col, t_cols);
01177     return array_[col];
01178   }
01179 
01180   const double *GetColumnPtr(index_t col) const {
01181     DEBUG_BOUNDS(col, t_cols);
01182     return array_[col];
01183   }
01184 };
01185 
01186 #endif
Generated on Mon Jan 24 12:04:37 2011 for FASTlib by  doxygen 1.6.3