TooN 2.1
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     typedef Slice<SliceRowStride,SliceColStride> SliceBase;
00091 
00092     int rowstride() const {
00093         if(RowStride == -2) { //Normal tied stride
00094             return num_cols();
00095         } else {
00096             return RowStrideHolder<RowStride>::stride();
00097         }
00098     }
00099 
00100     int colstride() const {
00101         if(ColStride == -2) { //Normal tied stride
00102             return num_rows();
00103         } else {
00104             return ColStrideHolder<ColStride>::stride();
00105         }
00106     }
00107 
00108     //Optional constructors
00109     GenericMBase(){}
00110 
00111     GenericMBase(Precision* p)
00112     :Mem(p)
00113     {}
00114 
00115 
00116     GenericMBase(Precision* p, int r, int c, int rowstride, int colstride)
00117     :Mem(p, r, c),
00118      RowStrideHolder<RowStride>(rowstride),
00119      ColStrideHolder<ColStride>(colstride) 
00120     {}
00121 
00122     GenericMBase(int r, int c)
00123     :Mem(r, c) {}
00124 
00125     template<class Op>
00126     GenericMBase(const Operator<Op>& op)
00127         : Mem(op),
00128           RowStrideHolder<RowStride>(op),
00129           ColStrideHolder<ColStride>(op)
00130     {}
00131 
00132     using Mem::my_data;
00133     using Mem::num_cols;
00134     using Mem::num_rows;
00135 
00136     Precision& operator()(int r, int c){
00137         Internal::check_index(num_rows(), r);
00138         Internal::check_index(num_cols(), c);
00139         return my_data[r*rowstride() + c*colstride()];
00140     }
00141 
00142     const Precision& operator()(int r, int c) const {
00143         Internal::check_index(num_rows(), r);
00144         Internal::check_index(num_cols(), c);
00145         return my_data[r*rowstride() + c*colstride()];
00146     }
00147 
00148     Precision& operator[](const std::pair<int, int>& index) {
00149         Internal::check_index(num_rows(), index.first);
00150         Internal::check_index(num_cols(), index.second);
00151         return (*this)(index.first, index.second);
00152     }
00153 
00154     const Precision& operator[](const std::pair<int, int>& index) const {
00155         Internal::check_index(num_rows(), index.first);
00156         Internal::check_index(num_cols(), index.second);
00157         return (*this)(index.first, index.second);
00158     }
00159 
00160     // this is the type of vector obtained by [ ]
00161     typedef Vector<Cols, Precision, SliceVBase<SliceColStride> > Vec;
00162     typedef Vector<Cols, const Precision, SliceVBase<SliceColStride> > CVec;
00163     
00164     Vec operator[](int r) {
00165         Internal::check_index(num_rows(), r);
00166         return Vec(my_data + rowstride()* r, num_cols(), colstride(), Slicing());
00167     }
00168 
00169     const CVec operator[](int r) const {
00170         Internal::check_index(num_rows(), r);
00171         return CVec(my_data + rowstride()* r, num_cols(), colstride(), Slicing());
00172     }
00173 
00174     
00175     //Generic matrix slicing
00176     template<int Rstart, int Cstart, int Rlength, int Clength>
00177     Matrix<Rlength, Clength, Precision, Slice<SliceRowStride,SliceColStride> > slice(int rs, int cs, int rl, int cl){
00178         Internal::CheckSlice<Rows, Rstart, Rlength>::check(num_rows(), rs, rl);
00179         Internal::CheckSlice<Cols, Cstart, Clength>::check(num_cols(), cs, cl);
00180 
00181         //Always pass the size and stride as a run-time parameter. It will be ignored
00182         //by SliceHolder (above) if it is statically determined.
00183         return Matrix<Rlength, Clength, Precision, Slice<SliceRowStride,SliceColStride> >(
00184                my_data+rowstride()*(Rstart==Dynamic?rs:Rstart) + colstride()*(Cstart==Dynamic?cs:Cstart), 
00185                Rlength==Dynamic?rl:Rlength, 
00186                Clength==Dynamic?cl:Clength, 
00187                rowstride(), colstride(), Slicing());
00188     }
00189 
00190     template<int Rstart, int Cstart, int Rlength, int Clength>
00191     const Matrix<Rlength, Clength, const Precision, Slice<SliceRowStride,SliceColStride> > slice(int rs, int cs, int rl, int cl) const{
00192         Internal::CheckSlice<Rows, Rstart, Rlength>::check(num_rows(), rs, rl);
00193         Internal::CheckSlice<Cols, Cstart, Clength>::check(num_cols(), cs, cl);
00194 
00195         //Always pass the size and stride as a run-time parameter. It will be ignored
00196         //by SliceHolder (above) if it is statically determined.
00197         return Matrix<Rlength, Clength, const Precision, Slice<SliceRowStride,SliceColStride> >(
00198                my_data+rowstride()*(Rstart==Dynamic?rs:Rstart) + colstride()*(Cstart==Dynamic?cs:Cstart), 
00199                Rlength==Dynamic?rl:Rlength, 
00200                Clength==Dynamic?cl:Clength, 
00201                rowstride(), colstride(), Slicing());
00202     }
00203 
00204     //Special cases of slicing
00205     template<int Rstart, int Cstart, int Rlength, int Clength>
00206     Matrix<Rlength, Clength, Precision, Slice<SliceRowStride,SliceColStride> > slice()
00207     {
00208         //Extra checking in the static case
00209         Internal::CheckSlice<Rows, Rstart, Rlength>::check();
00210         Internal::CheckSlice<Cols, Cstart, Clength>::check();
00211         return slice<Rstart, Cstart, Rlength, Clength>(Rstart, Cstart, Rlength, Clength);
00212     }
00213 
00214     template<int Rstart, int Cstart, int Rlength, int Clength>
00215     const Matrix<Rlength, Clength, const Precision, Slice<SliceRowStride,SliceColStride> > slice() const
00216     {
00217         Internal::CheckSlice<Rows, Rstart, Rlength>::check();
00218         Internal::CheckSlice<Cols, Cstart, Clength>::check();
00219         return slice<Rstart, Cstart, Rlength, Clength>(Rstart, Cstart, Rlength, Clength);
00220     }
00221 
00222     Matrix<-1, -1, Precision, Slice<SliceRowStride,SliceColStride> > slice(int rs, int cs, int rl, int cl){
00223         return slice<Dynamic, Dynamic, Dynamic, Dynamic>(rs, cs, rl, cl);
00224     }
00225 
00226     const Matrix<-1, -1, const Precision, Slice<SliceRowStride,SliceColStride> > slice(int rs, int cs, int rl, int cl) const {
00227         return slice<Dynamic, Dynamic, Dynamic, Dynamic>(rs, cs, rl, cl);
00228     }
00229 
00230     //Other slice related functions.
00231     Matrix<Cols, Rows, Precision, Slice<SliceColStride,SliceRowStride> > T(){
00232         return Matrix<Cols, Rows, Precision, Slice<SliceColStride,SliceRowStride> >(my_data, num_cols(), num_rows(), colstride(), rowstride(), Slicing());
00233     }
00234 
00235     const Matrix<Cols, Rows, const Precision, Slice<SliceColStride,SliceRowStride> > T() const{
00236         return Matrix<Cols, Rows, const Precision, Slice<SliceColStride,SliceRowStride> >(my_data, num_cols(), num_rows(), colstride(), rowstride(), Slicing());
00237     }
00238 
00239     static const int DiagSize = Internal::DiagSize<Rows, Cols>::size;
00240     static const int DiagStride = Internal::DiagStride<SliceRowStride, SliceColStride>::stride;
00241 
00242     Vector<DiagSize, Precision, SliceVBase<DiagStride> > diagonal_slice()
00243     {
00244         return Vector<DiagSize, Precision, SliceVBase<DiagStride> >(my_data, std::min(num_cols(), num_rows()), rowstride() + colstride(), Slicing());
00245     }
00246 
00247     Vector<DiagSize, const Precision, SliceVBase<DiagStride> > diagonal_slice() const 
00248     {
00249         return Vector<DiagSize, const Precision, SliceVBase<DiagStride> >(my_data, std::min(num_cols(), num_rows()), rowstride() + colstride(), Slicing());
00250     }
00251 };
00252 
00253 }
00254 
00255 ////////////////////////////////////////////////////////////////////////////////
00256 //
00257 // Classes for Matrices owning memory
00258 //
00259 //
00260 struct RowMajor
00261 {
00262     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> >
00263     {
00264         //Optional constructors.
00265         
00266         MLayout(){}
00267 
00268         MLayout(int rows, int cols)
00269             :Internal::GenericMBase<Rows, Cols, Precision, (Cols == -1 ? -2 : Cols), 1, Internal::MatrixAlloc<Rows, Cols, Precision> >(rows, cols)
00270         {}
00271 
00272         template<class Op>
00273         MLayout(const Operator<Op>& op)
00274             :Internal::GenericMBase<Rows, Cols, Precision, (Cols == -1 ? -2 : Cols), 1, Internal::MatrixAlloc<Rows, Cols, Precision> >(op)
00275         {}
00276 
00277     };
00278 };
00279 
00280 struct ColMajor
00281 {
00282     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> >
00283     {
00284         //Optional constructors.
00285         
00286         MLayout(){}
00287 
00288         MLayout(int rows, int cols)
00289         :Internal::GenericMBase<Rows, Cols, Precision, 1, (Rows == -1 ? -2 : Rows), Internal::MatrixAlloc<Rows, Cols, Precision> >(rows, cols)
00290         {}
00291 
00292         template<class Op>
00293         MLayout(const Operator<Op>& op)
00294             :Internal::GenericMBase<Rows, Cols, Precision, 1, (Rows == -1 ? -2 : Rows), Internal::MatrixAlloc<Rows, Cols, Precision> >(op)
00295         {}
00296 
00297     };
00298 };
00299 
00300 }
00301