TooN 2.1
|
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