internal/allocator.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 // Allocators always copy data on copy construction.
00032 //
00033 // When a Vector/Matrix is constructed from a different, but compatible type
00034 // copying is done at a much higher level: above the level that knows how the
00035 // data is laid out in memory.
00036 //
00037 // At this level, copy construction is required since it is only known here 
00038 // whether data or a reference to data should be copied.
00039 
00040 #ifdef __GNUC__
00041 #define TOON_ALIGN8 __attribute__ ((aligned(8)))
00042 #else
00043 #define TOON_ALIGN8
00044 #endif
00045 
00046 namespace TooN {
00047 
00048 namespace Internal
00049 {
00050 
00051 template<int Size, class Precision, bool heap> class StackOrHeap;
00052 
00053 template<int Size, class Precision> class StackOrHeap<Size,Precision,0>
00054 {
00055 public:
00056     StackOrHeap()
00057     {
00058         debug_initialize(my_data, Size);    
00059     }
00060 
00061     Precision my_data[Size];
00062 };
00063 
00064 template<int Size> class StackOrHeap<Size,double,0>
00065 {
00066 public:
00067     StackOrHeap()
00068     {
00069         debug_initialize(my_data, Size);    
00070     }
00071 
00072     double my_data[Size] TOON_ALIGN8 ;
00073 };
00074 
00075 
00076 template<int Size, class Precision> class StackOrHeap<Size, Precision, 1>
00077 {
00078     public:
00079         StackOrHeap()
00080         :my_data(new Precision[Size])
00081         {
00082             debug_initialize(my_data, Size);    
00083         }
00084 
00085 
00086         ~StackOrHeap()
00087         {
00088             delete[] my_data;
00089         }
00090 
00091         Precision *my_data;
00092     
00093         StackOrHeap(const StackOrHeap& from)
00094         :my_data(new Precision[Size])
00095         {
00096             for(int i=0; i < Size; i++)
00097                 my_data[i] = from.my_data[i];
00098         }
00099 };
00100 
00101 
00102 template<int Size, class Precision> class StaticSizedAllocator: public StackOrHeap<Size, Precision, (sizeof(Precision)*Size>max_bytes_on_stack) >
00103 {
00104 };
00105 
00106 template<int Size, class Precision> struct VectorAlloc : public StaticSizedAllocator<Size, Precision> {
00107     
00108     VectorAlloc() { }
00109     
00110     VectorAlloc(int /*s*/) { }
00111 
00112     template<class Op>
00113     VectorAlloc(const Operator<Op>&) {}
00114 
00115     int size() const {
00116         return Size;
00117     }
00118 };
00119 
00120 template<class Precision> struct VectorAlloc<-1, Precision> {
00121     Precision * const my_data;
00122     const int my_size;
00123 
00124     VectorAlloc(const VectorAlloc& v)
00125     :my_data(new Precision[v.my_size]), my_size(v.my_size)
00126     { 
00127         for(int i=0; i < my_size; i++)
00128             my_data[i] = v.my_data[i];
00129     }
00130 
00131     VectorAlloc(int s)
00132     :my_data(new Precision[s]), my_size(s)
00133     { 
00134         debug_initialize(my_data, my_size); 
00135     }
00136 
00137     template <class Op>
00138     VectorAlloc(const Operator<Op>& op) 
00139     : my_data(new Precision[op.size()]), my_size(op.size()) 
00140     {
00141         debug_initialize(my_data, my_size); 
00142     }
00143 
00144     int size() const {
00145         return my_size;
00146     }
00147 
00148     ~VectorAlloc(){
00149         delete[] my_data;
00150     }
00151 
00152 };
00153 
00154 
00155 template<int S, class Precision> struct VectorSlice
00156 {
00157     int size() const {
00158         return S;
00159     }
00160 
00161     //Optional Constructors
00162     
00163     Precision* const my_data;
00164     VectorSlice(Precision* p)
00165     :my_data(p){}
00166 
00167     VectorSlice(Precision* p, int /*size*/)
00168     :my_data(p){}
00169 
00170     template<class Op>
00171     VectorSlice(const Operator<Op>& op) : my_data(op.data()) {}
00172 };
00173 
00174 template<class Precision> struct VectorSlice<-1, Precision>
00175 {
00176     Precision* const my_data;
00177     const int my_size;
00178 
00179     VectorSlice(Precision* d, int s)
00180     :my_data(d), my_size(s)
00181     { }
00182 
00183     template<class Op>
00184     VectorSlice(const Operator<Op>& op) : my_data(op.data()), my_size(op.size()) {}
00185 
00186     int size() const {
00187         return my_size;
00188     }
00189 };
00190 
00191 
00192 
00193 
00195 //
00196 // A class similar to StrideHolder, but to hold the size information for matrices.
00197 
00198 template<int s> struct SizeHolder
00199 {
00200     //Constructors ignore superfluous arguments
00201     SizeHolder(){}
00202     SizeHolder(int){}
00203 
00204     int size() const{
00205         return s;
00206     }
00207 };
00208 
00209 template<> struct SizeHolder<-1>
00210 {
00211     SizeHolder(int s)
00212     :my_size(s){}
00213 
00214     const int my_size;
00215     int size() const {
00216         return my_size;
00217     }
00218 };
00219 
00220 
00221 template<int S> struct RowSizeHolder: private SizeHolder<S>
00222 {
00223     RowSizeHolder(int i)
00224     :SizeHolder<S>(i){}
00225 
00226     RowSizeHolder()
00227     {}
00228 
00229     template<typename Op>
00230     RowSizeHolder(const Operator<Op>& op) : SizeHolder<S>(op.num_rows()) {}
00231 
00232     int num_rows() const {return SizeHolder<S>::size();}
00233 };
00234 
00235 
00236 template<int S> struct ColSizeHolder: private SizeHolder<S>
00237 {
00238     ColSizeHolder(int i)
00239     :SizeHolder<S>(i){}
00240 
00241     ColSizeHolder()
00242     {}
00243 
00244     template<typename Op>
00245     ColSizeHolder(const Operator<Op>& op) : SizeHolder<S>(op.num_cols()) {}
00246 
00247     int num_cols() const {return SizeHolder<S>::size();}    
00248 };
00249 
00250 
00251 
00252 template<int R, int C, class Precision, bool FullyStatic=(R>=0 && C>=0)> 
00253 struct MatrixAlloc: public StaticSizedAllocator<R*C, Precision>
00254 {
00255     MatrixAlloc(int,int)
00256     {}
00257 
00258     MatrixAlloc()
00259     {}
00260 
00261     template <class Op>
00262     MatrixAlloc(const Operator<Op>&)
00263     {}
00264 
00265     int num_rows() const {
00266         return R;
00267     }
00268 
00269     int num_cols() const {
00270         return C;
00271     }
00272 };
00273 
00274 
00275 template<int R, int C, class Precision> struct MatrixAlloc<R, C, Precision, false>
00276     : public RowSizeHolder<R>,
00277     ColSizeHolder<C>
00278 {
00279     Precision* const my_data;
00280 
00281     using RowSizeHolder<R>::num_rows;
00282     using ColSizeHolder<C>::num_cols;
00283     
00284     // copy constructor so guaranteed contiguous
00285     MatrixAlloc(const MatrixAlloc& m)
00286         :RowSizeHolder<R>(m.num_rows()),
00287          ColSizeHolder<C>(m.num_cols()),
00288          my_data(new Precision[num_rows()*num_cols()]) {
00289         const int size=num_rows()*num_cols();
00290         for(int i=0; i < size; i++) {
00291             my_data[i] = m.my_data[i];
00292         }
00293     }
00294 
00295     MatrixAlloc(int r, int c)
00296     :RowSizeHolder<R>(r),
00297      ColSizeHolder<C>(c),
00298      my_data(new Precision[num_rows()*num_cols()]) 
00299     {
00300         debug_initialize(my_data, num_rows()*num_cols());   
00301     }
00302 
00303     template <class Op> MatrixAlloc(const Operator<Op>& op)
00304         :RowSizeHolder<R>(op),
00305          ColSizeHolder<C>(op),
00306          my_data(new Precision[num_rows()*num_cols()])
00307     {
00308         debug_initialize(my_data, num_rows()*num_cols());   
00309     }
00310 
00311     ~MatrixAlloc() {
00312         delete[] my_data;
00313     }
00314 };
00315 
00316 
00317 template<int R, int C, class Precision> struct MatrixSlice
00318     : public RowSizeHolder<R>,
00319     ColSizeHolder<C>
00320 {
00321     Precision* const my_data;
00322 
00323     using RowSizeHolder<R>::num_rows;
00324     using ColSizeHolder<C>::num_cols;
00325 
00326     //Optional Constructors
00327     MatrixSlice(Precision* p)
00328     :my_data(p){}
00329 
00330     MatrixSlice(Precision* p, int r, int c)
00331         :RowSizeHolder<R>(r),
00332          ColSizeHolder<C>(c),
00333          my_data(p){}
00334     
00335     template<class Op>
00336     MatrixSlice(const Operator<Op>& op)
00337         :RowSizeHolder<R>(op),
00338          ColSizeHolder<C>(op),
00339          my_data(op.data())
00340     {}
00341 };
00342 
00343 
00345 //
00346 // A class similar to mem, but to hold the stride information. It is only needed
00347 // for -1. For +int and -2, the stride is part fo teh type, or implicit.
00348 
00349 template<int s> struct StrideHolder
00350 {
00351     //Constructos ignore superfluous arguments
00352     StrideHolder(){}
00353     StrideHolder(int){}
00354 
00355     template<class Op>
00356     StrideHolder(const Operator<Op>&) {}
00357 
00358     int stride() const{
00359         return s;
00360     }
00361 };
00362 
00363 template<> struct StrideHolder<-1>
00364 {
00365     StrideHolder(int s)
00366     :my_stride(s){}
00367 
00368     template<class Op>
00369     StrideHolder(const Operator<Op>& op) : my_stride(op.stride()) {}
00370 
00371     const int my_stride;
00372     int stride() const {
00373         return my_stride;
00374     }
00375 };
00376 
00377 
00378 template<int S> struct RowStrideHolder: public StrideHolder<S>
00379 {
00380     RowStrideHolder(int i)
00381     :StrideHolder<S>(i){}
00382 
00383     RowStrideHolder()
00384     {}
00385 
00386     template<class Op>
00387     RowStrideHolder(const Operator<Op>& op)
00388         : StrideHolder<S>(op)
00389     {}
00390 
00391 };
00392 
00393 
00394 template<int S> struct ColStrideHolder: public StrideHolder<S>
00395 {
00396     ColStrideHolder(int i)
00397     :StrideHolder<S>(i){}
00398 
00399     ColStrideHolder()
00400     {}
00401 
00402     template<class Op>
00403     ColStrideHolder(const Operator<Op>& op)
00404         : StrideHolder<S>(op)
00405     {}
00406 };
00407 
00408 }
00409 
00410 }
00411 
00412 
00413 #undef TOON_ALIGN8

Generated on Thu May 7 20:28:40 2009 for TooN by  doxygen 1.5.3