TooN: internal/allocator.hh Source File

TooN 2.0.0-beta8

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List

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<class Precision> struct DefaultTypes
    00052 {
    00053     typedef Precision* PointerType;
    00054     typedef const Precision* ConstPointerType;
    00055     typedef Precision& ReferenceType;
    00056     typedef const Precision& ConstReferenceType;
    00057 };
    00058
    00059
    00060 template<int Size, class Precision, bool heap> class StackOrHeap;
    00061
    00062 template<int Size, class Precision> class StackOrHeap<Size,Precision,0>
    00063 {
    00064 public:
    00065     StackOrHeap()
    00066     {
    00067         debug_initialize(my_data, Size);
    00068     }
    00069     Precision my_data[Size];
    00070 };
    00071
    00072 template<int Size> class StackOrHeap<Size,double,0>
    00073 {
    00074 public:
    00075     StackOrHeap()
    00076     {
    00077         debug_initialize(my_data, Size);
    00078     }
    00079     double my_data[Size] TOON_ALIGN8 ;
    00080 };
    00081
    00082
    00083 template<int Size, class Precision> class StackOrHeap<Size, Precision, 1>
    00084 {
    00085     public:
    00086         StackOrHeap()
    00087         :my_data(new Precision[Size])
    00088         {
    00089             debug_initialize(my_data, Size);
    00090         }
    00091
    00092
    00093         ~StackOrHeap()
    00094         {
    00095             delete[] my_data;
    00096         }
    00097
    00098         Precision *my_data;
    00099
    00100         StackOrHeap(const StackOrHeap& from)
    00101         :my_data(new Precision[Size])
    00102         {
    00103             for(int i=0; i < Size; i++)
    00104                 my_data[i] = from.my_data[i];
    00105         }
    00106 };
    00107
    00108 ///@internal
    00109 ///@brief This allocator object sets aside memory for a statically sized object.
    00110 ///It will
    00111 ///put all the data on the stack if there are less then TooN::max_bytes_on_stack of
    00112 ///data, otherwise it will use new/delete.
    00113 ///@ingroup gInternal
    00114 template<int Size, class Precision> class StaticSizedAllocator: public StackOrHeap<Size, Precision, (sizeof(Precision)*Size>max_bytes_on_stack) >
    00115 {
    00116 };
    00117
    00118
    00119 ///@internal
    00120 ///@brief Allocate memory for a static sized Vector.
    00121 ///The class switches to heap allocation automatically for large Vectors.
    00122 ///Naturally, the vector is not resizable.
    00123 ///@ingroup gInternal
    00124 template<int Size, class Precision> struct VectorAlloc : public StaticSizedAllocator<Size, Precision>, DefaultTypes<Precision> {
    00125
    00126     ///Default constructor (only for statically sized vectors)
    00127     VectorAlloc() { }
    00128
    00129     ///Construction from a size (required by damic vectors, ignored otherwise).
    00130     VectorAlloc(int /*s*/) { }
    00131
    00132     ///Construction from an Operator. See Operator::size().
    00133     template<class Op>
    00134     VectorAlloc(const Operator<Op>&) {}
    00135
    00136     ///Return the size of the vector.
    00137     int size() const {
    00138         return Size;
    00139     }
    00140
    00141     using StaticSizedAllocator<Size, Precision>::my_data;
    00142
    00143     Precision *get_data_ptr()
    00144     {
    00145         return my_data;
    00146     };
    00147
    00148     const Precision *get_data_ptr() const
    00149     {
    00150         return my_data;
    00151     }
    00152
    00153     protected:
    00154
    00155         Precision *data()
    00156         {
    00157             return my_data;
    00158         };
    00159
    00160         const Precision *data() const
    00161         {
    00162             return my_data;
    00163         };
    00164
    00165         void try_destructive_resize(int)
    00166         {}
    00167
    00168         template<class Op> void try_destructive_resize(const Operator<Op>&)
    00169         {}
    00170 };
    00171
    00172 ///@internal
    00173 ///@brief Allocate memory for a dynamic sized Vector.
    00174 ///This is not resizable.
    00175 ///@ingroup gInternal
    00176 template<class Precision> struct VectorAlloc<Dynamic, Precision>: public DefaultTypes<Precision> {
    00177     Precision * const my_data;
    00178     const int my_size;
    00179
    00180     VectorAlloc(const VectorAlloc& v)
    00181     :my_data(new Precision[v.my_size]), my_size(v.my_size)
    00182     {
    00183         for(int i=0; i < my_size; i++)
    00184             my_data[i] = v.my_data[i];
    00185     }
    00186
    00187     VectorAlloc(int s)
    00188     :my_data(new Precision[s]), my_size(s)
    00189     {
    00190         debug_initialize(my_data, my_size);
    00191     }
    00192
    00193     template <class Op>
    00194     VectorAlloc(const Operator<Op>& op)
    00195     : my_data(new Precision[op.size()]), my_size(op.size())
    00196     {
    00197         debug_initialize(my_data, my_size);
    00198     }
    00199
    00200     int size() const {
    00201         return my_size;
    00202     }
    00203
    00204     ~VectorAlloc(){
    00205         delete[] my_data;
    00206     }
    00207
    00208     Precision *get_data_ptr()
    00209     {
    00210         return my_data;
    00211     };
    00212
    00213     const Precision *get_data_ptr() const
    00214     {
    00215         return my_data;
    00216     }
    00217
    00218     protected:
    00219
    00220         Precision *data()
    00221         {
    00222             return my_data;
    00223         };
    00224
    00225         const Precision *data() const
    00226         {
    00227             return my_data;
    00228         };
    00229
    00230         void try_destructive_resize(int)
    00231         {}
    00232
    00233         template<class Op> void try_destructive_resize(const Operator<Op>&)
    00234         {}
    00235 };
    00236
    00237
    00238 ///@internal
    00239 ///@brief Allocate memory for a resizable Vector.
    00240 ///New elements available after a resize are treated as
    00241 ///uninitialized.
    00242 ///@ingroup gInternal
    00243 template<class Precision> struct VectorAlloc<Resizable, Precision>: public DefaultTypes<Precision> {
    00244     protected:
    00245         std::vector<Precision> numbers;
    00246
    00247     public:
    00248
    00249         VectorAlloc()
    00250         {
    00251         }
    00252
    00253         VectorAlloc(int s)
    00254         :numbers(s)
    00255         {
    00256             debug_initialize(data(), size());
    00257         }
    00258
    00259         template <class Op>
    00260         VectorAlloc(const Operator<Op>& op)
    00261         :numbers(op.size())
    00262         {
    00263             debug_initialize(data(), size());
    00264         }
    00265
    00266         int size() const {
    00267             return numbers.size();
    00268         }
    00269
    00270         Precision *get_data_ptr()
    00271         {
    00272             return data();
    00273         };
    00274
    00275         const Precision *get_data_ptr() const
    00276         {
    00277             return data();
    00278         }
    00279
    00280     protected:
    00281
    00282         Precision* data() {
    00283             return &numbers[0];
    00284         }
    00285
    00286         const Precision* data()const  {
    00287             return &numbers[0];
    00288         }
    00289
    00290     private:
    00291         //Dymmy class for implementing sfinae
    00292         //in order to test for a .size() member
    00293         template<int S> struct SFINAE_dummy{typedef void type;};
    00294
    00295     protected:
    00296
    00297         //SFINAE implementation of try_destructive_resize
    00298         //to avoid calling .size if it does not exist!
    00299
    00300         //Force the function TYPE to depend on a property
    00301         //of the Operator<Op> type, so that it simply does
    00302         //not exist if the property is missing.
    00303         //Therefore this method only uses .size() if it exists.
    00304         template<class Op>
    00305         typename SFINAE_dummy<sizeof(&Operator<Op>::size)>::type try_destructive_resize(const Operator<Op>& op)
    00306         {
    00307             try_destructive_resize(op.size());
    00308         }
    00309
    00310         //Catch-all do nothing for operators with no size method.
    00311         template<class Op>
    00312         void try_destructive_resize(const Op&)
    00313         {}
    00314
    00315         void try_destructive_resize(int newsize)
    00316         {
    00317             numbers.resize(newsize);
    00318             debug_initialize(data(), newsize);
    00319         }
    00320
    00321     public:
    00322
    00323         void resize(int s)
    00324         {
    00325             int old_size = size();
    00326             numbers.resize(s);
    00327             if(s > old_size)
    00328                 debug_initialize(data()+old_size, s-old_size);
    00329         }
    00330 };
    00331
    00332 ///@internal
    00333 ///@brief Hold a pointer to yield a statically sized slice of a Vector.
    00334 ///Not resizable.
    00335 ///@ingroup gInternal
    00336 //template<int S, class Precision, class PtrType=Precision*, class ConstPtrType=const Precision*, class RefType=Precision&, class ConstRefType=const Precision&> struct VectorSlice
    00337 template<int S, class Precision, class PtrType=Precision*, class ConstPtrType=const Precision*, class RefType=Precision&, class ConstRefType=const Precision&> struct VectorSlice
    00338 {
    00339     int size() const {
    00340         return S;
    00341     }
    00342
    00343     //Optional Constructors
    00344
    00345     const PtrType my_data;
    00346     VectorSlice(PtrType p)
    00347     :my_data(p){}
    00348
    00349     VectorSlice(PtrType p, int /*size*/)
    00350     :my_data(p){}
    00351
    00352     template<class Op>
    00353     VectorSlice(const Operator<Op>& op) : my_data(op.data()) {}
    00354
    00355     protected:
    00356         PtrType data()
    00357         {
    00358             return my_data;
    00359         };
    00360
    00361         ConstPtrType data() const
    00362         {
    00363             return my_data;
    00364         };
    00365
    00366         void try_destructive_resize(int)
    00367         {}
    00368
    00369         template<class Op> void try_destructive_resize(const Operator<Op>&)
    00370         {}
    00371
    00372     public:
    00373         typedef PtrType PointerType;
    00374         typedef ConstPtrType ConstPointerType;
    00375         typedef RefType ReferenceType;
    00376         typedef ConstRefType ConstReferenceType;
    00377 };
    00378
    00379 ///@internal
    00380 ///@brief Hold a pointer to yield a dynamically sized slice of a Vector.
    00381 ///Not resizable.
    00382 ///@ingroup gInternal
    00383 template<class Precision, class PtrType, class ConstPtrType, class RefType, class ConstRefType> struct VectorSlice<Dynamic, Precision, PtrType, ConstPtrType, RefType, ConstRefType>
    00384 {
    00385     const PtrType my_data;
    00386     const int my_size;
    00387
    00388     VectorSlice(PtrType d, int s)
    00389     :my_data(d), my_size(s)
    00390     { }
    00391
    00392     template<class Op>
    00393     VectorSlice(const Operator<Op>& op) : my_data(op.data()), my_size(op.size()) {}
    00394
    00395     int size() const {
    00396         return my_size;
    00397     }
    00398
    00399     protected:
    00400
    00401         PtrType data()
    00402         {
    00403             return my_data;
    00404         };
    00405
    00406         ConstPtrType data() const
    00407         {
    00408             return my_data;
    00409         };
    00410
    00411         void try_destructive_resize(int)
    00412         {}
    00413
    00414         template<class Op> void try_destructive_resize(const Operator<Op>&)
    00415         {}
    00416
    00417     public:
    00418         typedef PtrType PointerType;
    00419         typedef ConstPtrType ConstPointerType;
    00420         typedef RefType ReferenceType;
    00421         typedef ConstRefType ConstReferenceType;
    00422 };
    00423
    00424 ////////////////////////////////////////////////////////////////////////////////
    00425 //
    00426 // A class similar to StrideHolder, but to hold the size information for matrices.
    00427
    00428 ///@internal
    00429 ///@brief This struct holds a size using no data for static sizes.
    00430 ///This struct holds a size is the size is dynamic,
    00431 ///or simply recorcs the number in the type system if
    00432 ///the size is static.
    00433 ///@ingroup gInternal
    00434 template<int s> struct SizeHolder
    00435 {
    00436     //Constructors ignore superfluous arguments
    00437     SizeHolder(){}    ///<Default constrution
    00438     SizeHolder(int){} ///<Construct from an int and discard it.
    00439
    00440     ///Simply return the statcally known size
    00441     int size() const{
    00442         return s;
    00443     }
    00444 };
    00445
    00446 ///@internal
    00447 ///@brief This struct holds a size integer for dynamic sizes.
    00448 ///@ingroup gInternal
    00449 template<> struct SizeHolder<-1>
    00450 {
    00451     ///@name Construction
    00452     ///@{
    00453     SizeHolder(int s)
    00454     :my_size(s){}
    00455     ///@}
    00456
    00457     const int my_size; ///<The size
    00458     ///Return the size
    00459     int size() const {
    00460         return my_size;
    00461     }
    00462 };
    00463
    00464 ///@internal
    00465 ///This struct holds the number of rows, only allocating space if
    00466 ///necessary.
    00467 ///@ingroup gInternal
    00468 template<int S> struct RowSizeHolder: private SizeHolder<S>
    00469 {
    00470     ///Construct from an int to provide a run time size if
    00471     ///necessary.
    00472     ///@param i The size, which is discarded for the static case.
    00473     RowSizeHolder(int i)
    00474     :SizeHolder<S>(i){}
    00475
    00476     RowSizeHolder()
    00477     {}
    00478
    00479     ///Construct from an Operator, taking the size from the operator.
    00480     ///The size is only used in the dynamic case.
    00481     ///@param op Operator from which to determine the size.
    00482     template<typename Op>
    00483     RowSizeHolder(const Operator<Op>& op) : SizeHolder<S>(op.num_rows()) {}
    00484
    00485     ///Return the number of rows.
    00486     int num_rows() const {return SizeHolder<S>::size();}
    00487 };
    00488
    00489
    00490 ///@internal
    00491 ///This struct holds the number of columns, only allocating space if
    00492 ///necessary.
    00493 ///@ingroup gInternal
    00494 template<int S> struct ColSizeHolder: private SizeHolder<S>
    00495 {
    00496     ///Construct from an int to provide a run time size if
    00497     ///necessary.
    00498     ///@param i The size, which is discarded for the static case.
    00499     ColSizeHolder(int i)
    00500     :SizeHolder<S>(i){}
    00501
    00502     ColSizeHolder()
    00503     {}
    00504
    00505     ///Construct from an Operator, taking the size from the operator.
    00506     ///The size is only used in the dynamic case.
    00507     ///@param op Operator from which to determine the size.
    00508     template<typename Op>
    00509     ColSizeHolder(const Operator<Op>& op) : SizeHolder<S>(op.num_cols()) {}
    00510
    00511     ///Return the number of columns.
    00512     int num_cols() const {return SizeHolder<S>::size();}
    00513 };
    00514
    00515
    00516
    00517 template<int R, int C, class Precision, bool FullyStatic=(R>=0 && C>=0)>
    00518 struct MatrixAlloc: public StaticSizedAllocator<R*C, Precision>
    00519 {
    00520     MatrixAlloc(int,int)
    00521     {}
    00522
    00523     MatrixAlloc()
    00524     {}
    00525
    00526     template <class Op>
    00527     MatrixAlloc(const Operator<Op>&)
    00528     {}
    00529
    00530     int num_rows() const {
    00531         return R;
    00532     }
    00533
    00534     int num_cols() const {
    00535         return C;
    00536     }
    00537
    00538     using  StaticSizedAllocator<R*C, Precision>::my_data;
    00539
    00540     Precision* get_data_ptr()
    00541     {
    00542         return my_data;
    00543     }
    00544
    00545     const Precision* get_data_ptr() const
    00546     {
    00547         return my_data;
    00548     }
    00549 };
    00550
    00551
    00552 template<int R, int C, class Precision> struct MatrixAlloc<R, C, Precision, false>
    00553     : public RowSizeHolder<R>,
    00554     ColSizeHolder<C>
    00555 {
    00556     Precision* const my_data;
    00557
    00558     using RowSizeHolder<R>::num_rows;
    00559     using ColSizeHolder<C>::num_cols;
    00560
    00561     // copy constructor so guaranteed contiguous
    00562     MatrixAlloc(const MatrixAlloc& m)
    00563         :RowSizeHolder<R>(m.num_rows()),
    00564          ColSizeHolder<C>(m.num_cols()),
    00565          my_data(new Precision[num_rows()*num_cols()]) {
    00566         const int size=num_rows()*num_cols();
    00567         for(int i=0; i < size; i++) {
    00568             my_data[i] = m.my_data[i];
    00569         }
    00570     }
    00571
    00572     MatrixAlloc(int r, int c)
    00573     :RowSizeHolder<R>(r),
    00574      ColSizeHolder<C>(c),
    00575      my_data(new Precision[num_rows()*num_cols()])
    00576     {
    00577         debug_initialize(my_data, num_rows()*num_cols());
    00578     }
    00579
    00580     template <class Op> MatrixAlloc(const Operator<Op>& op)
    00581         :RowSizeHolder<R>(op),
    00582          ColSizeHolder<C>(op),
    00583          my_data(new Precision[num_rows()*num_cols()])
    00584     {
    00585         debug_initialize(my_data, num_rows()*num_cols());
    00586     }
    00587
    00588     ~MatrixAlloc() {
    00589         delete[] my_data;
    00590     }
    00591
    00592     Precision* get_data_ptr()
    00593     {
    00594         return my_data;
    00595     }
    00596
    00597     const Precision* get_data_ptr() const
    00598     {
    00599         return my_data;
    00600     }
    00601 };
    00602
    00603
    00604 template<int R, int C, class Precision> struct MatrixSlice
    00605     : public RowSizeHolder<R>,
    00606     ColSizeHolder<C>
    00607 {
    00608     Precision* const my_data;
    00609
    00610     using RowSizeHolder<R>::num_rows;
    00611     using ColSizeHolder<C>::num_cols;
    00612
    00613     //Optional Constructors
    00614     MatrixSlice(Precision* p)
    00615     :my_data(p){}
    00616
    00617     MatrixSlice(Precision* p, int r, int c)
    00618         :RowSizeHolder<R>(r),
    00619          ColSizeHolder<C>(c),
    00620          my_data(p){}
    00621
    00622     template<class Op>
    00623     MatrixSlice(const Operator<Op>& op)
    00624         :RowSizeHolder<R>(op),
    00625          ColSizeHolder<C>(op),
    00626          my_data(op.data())
    00627     {}
    00628 };
    00629
    00630
    00631 ////////////////////////////////////////////////////////////////////////////////
    00632 //
    00633 // A class similar to mem, but to hold the stride information. It is only needed
    00634 // for -1. For +int and -2, the stride is part fo teh type, or implicit.
    00635
    00636 template<int s> struct StrideHolder
    00637 {
    00638     //Constructos ignore superfluous arguments
    00639     StrideHolder(){}
    00640     StrideHolder(int){}
    00641
    00642     template<class Op>
    00643     StrideHolder(const Operator<Op>&) {}
    00644
    00645     int stride() const{
    00646         return s;
    00647     }
    00648 };
    00649
    00650 template<> struct StrideHolder<-1>
    00651 {
    00652     StrideHolder(int s)
    00653     :my_stride(s){}
    00654
    00655     template<class Op>
    00656     StrideHolder(const Operator<Op>& op) : my_stride(op.stride()) {}
    00657
    00658     const int my_stride;
    00659     int stride() const {
    00660         return my_stride;
    00661     }
    00662 };
    00663
    00664
    00665 template<int S> struct RowStrideHolder: public StrideHolder<S>
    00666 {
    00667     RowStrideHolder(int i)
    00668     :StrideHolder<S>(i){}
    00669
    00670     RowStrideHolder()
    00671     {}
    00672
    00673     template<class Op>
    00674     RowStrideHolder(const Operator<Op>& op)
    00675         : StrideHolder<S>(op)
    00676     {}
    00677
    00678 };
    00679
    00680
    00681 template<int S> struct ColStrideHolder: public StrideHolder<S>
    00682 {
    00683     ColStrideHolder(int i)
    00684     :StrideHolder<S>(i){}
    00685
    00686     ColStrideHolder()
    00687     {}
    00688
    00689     template<class Op>
    00690     ColStrideHolder(const Operator<Op>& op)
    00691         : StrideHolder<S>(op)
    00692     {}
    00693 };
    00694
    00695 }
    00696
    00697 }
    00698
    00699
    00700 #undef TOON_ALIGN8