TooN 2.0.0-beta8
internal/mbase.hh
00001 // -*- c++ -*-
00002 
00003 // Copyright (C) 2009 Tom Drummond (twd20@cam.ac.uk),
00004 // Ed Rosten (er258@cam.ac.uk)
00005 //
00006 // This file is part of the TooN Library.  This library is free
00007 // software; you can redistribute it and/or modify it under the
00008 // terms of the GNU General Public License as published by the
00009 // Free Software Foundation; either version 2, or (at your option)
00010 // any later version.
00011 
00012 // This library is distributed in the hope that it will be useful,
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 // GNU General Public License for more details.
00016 
00017 // You should have received a copy of the GNU General Public License along
00018 // with this library; see the file COPYING.  If not, write to the Free
00019 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
00020 // USA.
00021 
00022 // As a special exception, you may use this file as part of a free software
00023 // library without restriction.  Specifically, if other files instantiate
00024 // templates or use macros or inline functions from this file, or you compile
00025 // this file and link it with other files to produce an executable, this
00026 // file does not by itself cause the resulting executable to be covered by
00027 // the GNU General Public License.  This exception does not however
00028 // invalidate any other reasons why the executable file might be covered by
00029 // the GNU General Public License.
00030 
00031 namespace TooN {
00032 
00033 namespace Internal
00034 {
00035 // As usual, a positive integer means static and -1 means dynamic.
00036 // The new case is that for strides, -2 means that the stride is 
00037 // the same as num_cols/num_rows, which must be dynamically sized.
00038 
00039 template<int, int, class, int, int, class> struct GenericMBase;
00040 
00041 ////////////////////////////////////////////////////////////////////////////////
00042 //Closure used to acquire strides
00043 //-1 means dynamic stride
00044 //-2 means dynamic stride is tied to size for a normal matrix
00045 template<int RowStride, int ColStride> struct Slice
00046 {
00047   
00048     template<int Rows, int Cols, class Precision> struct MLayout: public GenericMBase<Rows, Cols, Precision, RowStride, ColStride, MatrixSlice<Rows, Cols, Precision> >
00049     {
00050         MLayout(Precision* p, int rows, int cols, int rowstride, int colstride)
00051             :GenericMBase<Rows,Cols,Precision,RowStride,ColStride,MatrixSlice<Rows, Cols, Precision> >(p, rows, cols, rowstride, colstride)
00052         {
00053         }
00054     };
00055 };
00056 
00057 
00058 template<int Rows, int Cols, bool D = (Rows == Dynamic || Cols == Dynamic)>
00059 struct DiagSize
00060 {
00061     static const int size = Dynamic;
00062 };
00063 template<int Rows, int Cols>
00064 struct DiagSize<Rows, Cols, 0>
00065 {
00066     static const int size = (Rows<Cols?Rows:Cols);
00067 };
00068 
00069 template<int Rs, int Cs, bool D = (Rs == Dynamic || Cs == Dynamic)>
00070 struct DiagStride
00071 {
00072     static const int stride = Dynamic;
00073 };
00074 template<int Rs, int Cs>
00075 struct DiagStride<Rs, Cs, 0>
00076 {
00077     static const int stride = Rs + Cs;
00078 };
00079 
00080 
00081 template<int Rows, int Cols, class Precision, int RowStride, int ColStride, class Mem> struct GenericMBase
00082     : public Mem, 
00083     RowStrideHolder<RowStride>,
00084     ColStrideHolder<ColStride>
00085 {
00086     //Slices can never have tied strides
00087     static const int SliceRowStride = RowStride == -2?-1: RowStride;
00088     static const int SliceColStride = ColStride == -2?-1: ColStride;
00089 
00090     int rowstride() const {
00091         if(RowStride == -2) { //Normal tied stride
00092             return num_cols();
00093         } else {
00094             return RowStrideHolder<RowStride>::stride();
00095         }
00096     }
00097 
00098     int colstride() const {
00099         if(ColStride == -2) { //Normal tied stride
00100             return num_rows();
00101         } else {
00102             return ColStrideHolder<ColStride>::stride();
00103         }
00104     }
00105 
00106     //Optional constructors
00107     GenericMBase(){}
00108 
00109     GenericMBase(Precision* p)
00110     :Mem(p)
00111     {}
00112 
00113 
00114     GenericMBase(Precision* p, int r, int c, int rowstride, int colstride)
00115     :Mem(p, r, c),
00116      RowStrideHolder<RowStride>(rowstride),
00117      ColStrideHolder<ColStride>(colstride) 
00118     {}
00119 
00120     GenericMBase(int r, int c)
00121     :Mem(r, c) {}
00122 
00123     template<class Op>
00124     GenericMBase(const Operator<Op>& op)
00125         : Mem(op),
00126           RowStrideHolder<RowStride>(op),
00127           ColStrideHolder<ColStride>(op)
00128     {}
00129 
00130     using Mem::my_data;
00131     using Mem::num_cols;
00132     using Mem::num_rows;
00133 
00134     Precision& operator()(int r, int c){
00135         Internal::check_index(num_rows(), r);
00136         Internal::check_index(num_cols(), c);
00137         return my_data[r*rowstride() + c*colstride()];
00138     }
00139 
00140     const Precision& operator()(int r, int c) const {
00141         Internal::check_index(num_rows(), r);
00142         Internal::check_index(num_cols(), c);
00143         return my_data[r*rowstride() + c*colstride()];
00144     }
00145 
00146     Precision& operator[](const std::pair<int, int>& index) {
00147         Internal::check_index(num_rows(), index.first);
00148         Internal::check_index(num_cols(), index.second);
00149         return (*this)(index.first, index.second);
00150     }
00151 
00152     const Precision& operator[](const std::pair<int, int>& index) const {
00153         Internal::check_index(num_rows(), index.first);
00154         Internal::check_index(num_cols(), index.second);
00155         return (*this)(index.first, index.second);
00156     }
00157 
00158     // this is the type of vector obtained by [ ]
00159     typedef Vector<Cols, Precision, SliceVBase<SliceColStride> > Vec;
00160     typedef Vector<Cols, const Precision, SliceVBase<SliceColStride> > CVec;
00161     
00162     Vec operator[](int r) {
00163         Internal::check_index(num_rows(), r);
00164         return Vec(my_data + rowstride()* r, num_cols(), colstride(), Slicing());
00165     }
00166 
00167     const CVec operator[](int r) const {
00168         Internal::check_index(num_rows(), r);
00169         return CVec(my_data + rowstride()* r, num_cols(), colstride(), Slicing());
00170     }
00171 
00172     
00173     //Generic matrix slicing
00174     template<int Rstart, int Cstart, int Rlength, int Clength>
00175     Matrix<Rlength, Clength, Precision, Slice<SliceRowStride,SliceColStride> > slice(int rs, int cs, int rl, int cl){
00176         Internal::CheckSlice<Rows, Rstart, Rlength>::check(num_rows(), rs, rl);
00177         Internal::CheckSlice<Cols, Cstart, Clength>::check(num_cols(), cs, cl);
00178 
00179         //Always pass the size and stride as a run-time parameter. It will be ignored
00180         //by SliceHolder (above) if it is statically determined.
00181         return Matrix<Rlength, Clength, Precision, Slice<SliceRowStride,SliceColStride> >(
00182                my_data+rowstride()*(Rstart==Dynamic?rs:Rstart) + colstride()*(Cstart==Dynamic?cs:Cstart), 
00183                Rlength==Dynamic?rl:Rlength, 
00184                Clength==Dynamic?cl:Clength, 
00185                rowstride(), colstride(), Slicing());
00186     }
00187 
00188     template<int Rstart, int Cstart, int Rlength, int Clength>
00189     const Matrix<Rlength, Clength, const Precision, Slice<SliceRowStride,SliceColStride> > slice(int rs, int cs, int rl, int cl) const{
00190         Internal::CheckSlice<Rows, Rstart, Rlength>::check(num_rows(), rs, rl);
00191         Internal::CheckSlice<Cols, Cstart, Clength>::check(num_cols(), cs, cl);
00192 
00193         //Always pass the size and stride as a run-time parameter. It will be ignored
00194         //by SliceHolder (above) if it is statically determined.
00195         return Matrix<Rlength, Clength, const Precision, Slice<SliceRowStride,SliceColStride> >(
00196                my_data+rowstride()*(Rstart==Dynamic?rs:Rstart) + colstride()*(Cstart==Dynamic?cs:Cstart), 
00197                Rlength==Dynamic?rl:Rlength, 
00198                Clength==Dynamic?cl:Clength, 
00199                rowstride(), colstride(), Slicing());
00200     }
00201 
00202     //Special cases of slicing
00203     template<int Rstart, int Cstart, int Rlength, int Clength>
00204     Matrix<Rlength, Clength, Precision, Slice<SliceRowStride,SliceColStride> > slice()
00205     {
00206         //Extra checking in the static case
00207         Internal::CheckSlice<Rows, Rstart, Rlength>::check();
00208         Internal::CheckSlice<Cols, Cstart, Clength>::check();
00209         return slice<Rstart, Cstart, Rlength, Clength>(Rstart, Cstart, Rlength, Clength);
00210     }
00211 
00212     template<int Rstart, int Cstart, int Rlength, int Clength>
00213     const Matrix<Rlength, Clength, const Precision, Slice<SliceRowStride,SliceColStride> > slice() const
00214     {
00215         Internal::CheckSlice<Rows, Rstart, Rlength>::check();
00216         Internal::CheckSlice<Cols, Cstart, Clength>::check();
00217         return slice<Rstart, Cstart, Rlength, Clength>(Rstart, Cstart, Rlength, Clength);
00218     }
00219 
00220     Matrix<-1, -1, Precision, Slice<SliceRowStride,SliceColStride> > slice(int rs, int cs, int rl, int cl){
00221         return slice<Dynamic, Dynamic, Dynamic, Dynamic>(rs, cs, rl, cl);
00222     }
00223 
00224     const Matrix<-1, -1, const Precision, Slice<SliceRowStride,SliceColStride> > slice(int rs, int cs, int rl, int cl) const {
00225         return slice<Dynamic, Dynamic, Dynamic, Dynamic>(rs, cs, rl, cl);
00226     }
00227 
00228     //Other slice related functions.
00229     Matrix<Cols, Rows, Precision, Slice<SliceColStride,SliceRowStride> > T(){
00230         return Matrix<Cols, Rows, Precision, Slice<SliceColStride,SliceRowStride> >(my_data, num_cols(), num_rows(), colstride(), rowstride(), Slicing());
00231     }
00232 
00233     const Matrix<Cols, Rows, const Precision, Slice<SliceColStride,SliceRowStride> > T() const{
00234         return Matrix<Cols, Rows, const Precision, Slice<SliceColStride,SliceRowStride> >(my_data, num_cols(), num_rows(), colstride(), rowstride(), Slicing());
00235     }
00236 
00237     static const int DiagSize = Internal::DiagSize<Rows, Cols>::size;
00238     static const int DiagStride = Internal::DiagStride<SliceRowStride, SliceColStride>::stride;
00239 
00240     Vector<DiagSize, Precision, SliceVBase<DiagStride> > diagonal_slice()
00241     {
00242         return Vector<DiagSize, Precision, SliceVBase<DiagStride> >(my_data, std::min(num_cols(), num_rows()), rowstride() + colstride(), Slicing());
00243     }
00244 
00245     Vector<DiagSize, const Precision, SliceVBase<DiagStride> > diagonal_slice() const 
00246     {
00247         return Vector<DiagSize, const Precision, SliceVBase<DiagStride> >(my_data, std::min(num_cols(), num_rows()), rowstride() + colstride(), Slicing());
00248     }
00249 };
00250 
00251 }
00252 
00253 ////////////////////////////////////////////////////////////////////////////////
00254 //
00255 // Classes for Matrices owning memory
00256 //
00257 //
00258 struct RowMajor
00259 {
00260     template<int Rows, int Cols, class Precision> struct MLayout: public Internal::GenericMBase<Rows, Cols, Precision, (Cols==-1?-2:Cols), 1, Internal::MatrixAlloc<Rows, Cols, Precision> >
00261     {
00262         //Optional constructors.
00263         
00264         MLayout(){}
00265 
00266         MLayout(int rows, int cols)
00267             :Internal::GenericMBase<Rows, Cols, Precision, (Cols == -1 ? -2 : Cols), 1, Internal::MatrixAlloc<Rows, Cols, Precision> >(rows, cols)
00268         {}
00269 
00270         template<class Op>
00271         MLayout(const Operator<Op>& op)
00272             :Internal::GenericMBase<Rows, Cols, Precision, (Cols == -1 ? -2 : Cols), 1, Internal::MatrixAlloc<Rows, Cols, Precision> >(op)
00273         {}
00274 
00275     };
00276 };
00277 
00278 struct ColMajor
00279 {
00280     template<int Rows, int Cols, class Precision> struct MLayout: public Internal::GenericMBase<Rows, Cols, Precision, 1, (Rows==-1?-2:Rows), Internal::MatrixAlloc<Rows, Cols, Precision> >
00281     {
00282         //Optional constructors.
00283         
00284         MLayout(){}
00285 
00286         MLayout(int rows, int cols)
00287         :Internal::GenericMBase<Rows, Cols, Precision, 1, (Rows == -1 ? -2 : Rows), Internal::MatrixAlloc<Rows, Cols, Precision> >(rows, cols)
00288         {}
00289 
00290         template<class Op>
00291         MLayout(const Operator<Op>& op)
00292             :Internal::GenericMBase<Rows, Cols, Precision, 1, (Rows == -1 ? -2 : Rows), Internal::MatrixAlloc<Rows, Cols, Precision> >(op)
00293         {}
00294 
00295     };
00296 };
00297 
00298 }
00299