TooN 2.0.0-beta8
|
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