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 // 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 void swap(VectorAlloc& s) 00281 { 00282 numbers.swap(s.numbers); 00283 } 00284 00285 protected: 00286 00287 Precision* data() { 00288 return &numbers[0]; 00289 } 00290 00291 const Precision* data()const { 00292 return &numbers[0]; 00293 } 00294 00295 private: 00296 //Dymmy class for implementing sfinae 00297 //in order to test for a .size() member 00298 template<int S> struct SFINAE_dummy{typedef void type;}; 00299 00300 protected: 00301 00302 //SFINAE implementation of try_destructive_resize 00303 //to avoid calling .size if it does not exist! 00304 00305 //Force the function TYPE to depend on a property 00306 //of the Operator<Op> type, so that it simply does 00307 //not exist if the property is missing. 00308 //Therefore this method only uses .size() if it exists. 00309 template<class Op> 00310 typename SFINAE_dummy<sizeof(&Operator<Op>::size)>::type try_destructive_resize(const Operator<Op>& op) 00311 { 00312 try_destructive_resize(op.size()); 00313 } 00314 00315 //Catch-all do nothing for operators with no size method. 00316 template<class Op> 00317 void try_destructive_resize(const Op&) 00318 {} 00319 00320 void try_destructive_resize(int newsize) 00321 { 00322 numbers.resize(newsize); 00323 debug_initialize(data(), newsize); 00324 } 00325 00326 public: 00327 00328 void resize(int s) 00329 { 00330 int old_size = size(); 00331 numbers.resize(s); 00332 if(s > old_size) 00333 debug_initialize(data()+old_size, s-old_size); 00334 } 00335 }; 00336 00337 ///@internal 00338 ///@brief Hold a pointer to yield a statically sized slice of a Vector. 00339 ///Not resizable. 00340 ///@ingroup gInternal 00341 //template<int S, class Precision, class PtrType=Precision*, class ConstPtrType=const Precision*, class RefType=Precision&, class ConstRefType=const Precision&> struct VectorSlice 00342 template<int S, class Precision, class PtrType=Precision*, class ConstPtrType=const Precision*, class RefType=Precision&, class ConstRefType=const Precision&> struct VectorSlice 00343 { 00344 int size() const { 00345 return S; 00346 } 00347 00348 //Optional Constructors 00349 00350 const PtrType my_data; 00351 VectorSlice(PtrType p) 00352 :my_data(p){} 00353 00354 VectorSlice(PtrType p, int /*size*/) 00355 :my_data(p){} 00356 00357 template<class Op> 00358 VectorSlice(const Operator<Op>& op) : my_data(op.data()) {} 00359 00360 protected: 00361 PtrType data() 00362 { 00363 return my_data; 00364 }; 00365 00366 ConstPtrType data() const 00367 { 00368 return my_data; 00369 }; 00370 00371 void try_destructive_resize(int) 00372 {} 00373 00374 template<class Op> void try_destructive_resize(const Operator<Op>&) 00375 {} 00376 00377 public: 00378 typedef PtrType PointerType; 00379 typedef ConstPtrType ConstPointerType; 00380 typedef RefType ReferenceType; 00381 typedef ConstRefType ConstReferenceType; 00382 }; 00383 00384 ///@internal 00385 ///@brief Hold a pointer to yield a dynamically sized slice of a Vector. 00386 ///Not resizable. 00387 ///@ingroup gInternal 00388 template<class Precision, class PtrType, class ConstPtrType, class RefType, class ConstRefType> struct VectorSlice<Dynamic, Precision, PtrType, ConstPtrType, RefType, ConstRefType> 00389 { 00390 const PtrType my_data; 00391 const int my_size; 00392 00393 VectorSlice(PtrType d, int s) 00394 :my_data(d), my_size(s) 00395 { } 00396 00397 template<class Op> 00398 VectorSlice(const Operator<Op>& op) : my_data(op.data()), my_size(op.size()) {} 00399 00400 int size() const { 00401 return my_size; 00402 } 00403 00404 protected: 00405 00406 PtrType data() 00407 { 00408 return my_data; 00409 }; 00410 00411 ConstPtrType data() const 00412 { 00413 return my_data; 00414 }; 00415 00416 void try_destructive_resize(int) 00417 {} 00418 00419 template<class Op> void try_destructive_resize(const Operator<Op>&) 00420 {} 00421 00422 public: 00423 typedef PtrType PointerType; 00424 typedef ConstPtrType ConstPointerType; 00425 typedef RefType ReferenceType; 00426 typedef ConstRefType ConstReferenceType; 00427 }; 00428 00429 //////////////////////////////////////////////////////////////////////////////// 00430 // 00431 // A class similar to StrideHolder, but to hold the size information for matrices. 00432 00433 ///@internal 00434 ///@brief This struct holds a size using no data for static sizes. 00435 ///This struct holds a size is the size is dynamic, 00436 ///or simply recorcs the number in the type system if 00437 ///the size is static. 00438 ///@ingroup gInternal 00439 template<int s> struct SizeHolder 00440 { 00441 //Constructors ignore superfluous arguments 00442 SizeHolder(){} ///<Default constrution 00443 SizeHolder(int){} ///<Construct from an int and discard it. 00444 00445 ///Simply return the statcally known size 00446 int size() const{ 00447 return s; 00448 } 00449 }; 00450 00451 ///@internal 00452 ///@brief This struct holds a size integer for dynamic sizes. 00453 ///@ingroup gInternal 00454 template<> struct SizeHolder<-1> 00455 { 00456 ///@name Construction 00457 ///@{ 00458 SizeHolder(int s) 00459 :my_size(s){} 00460 ///@} 00461 00462 const int my_size; ///<The size 00463 ///Return the size 00464 int size() const { 00465 return my_size; 00466 } 00467 }; 00468 00469 ///@internal 00470 ///This struct holds the number of rows, only allocating space if 00471 ///necessary. 00472 ///@ingroup gInternal 00473 template<int S> struct RowSizeHolder: private SizeHolder<S> 00474 { 00475 ///Construct from an int to provide a run time size if 00476 ///necessary. 00477 ///@param i The size, which is discarded for the static case. 00478 RowSizeHolder(int i) 00479 :SizeHolder<S>(i){} 00480 00481 RowSizeHolder() 00482 {} 00483 00484 ///Construct from an Operator, taking the size from the operator. 00485 ///The size is only used in the dynamic case. 00486 ///@param op Operator from which to determine the size. 00487 template<typename Op> 00488 RowSizeHolder(const Operator<Op>& op) : SizeHolder<S>(op.num_rows()) {} 00489 00490 ///Return the number of rows. 00491 int num_rows() const {return SizeHolder<S>::size();} 00492 }; 00493 00494 00495 ///@internal 00496 ///This struct holds the number of columns, only allocating space if 00497 ///necessary. 00498 ///@ingroup gInternal 00499 template<int S> struct ColSizeHolder: private SizeHolder<S> 00500 { 00501 ///Construct from an int to provide a run time size if 00502 ///necessary. 00503 ///@param i The size, which is discarded for the static case. 00504 ColSizeHolder(int i) 00505 :SizeHolder<S>(i){} 00506 00507 ColSizeHolder() 00508 {} 00509 00510 ///Construct from an Operator, taking the size from the operator. 00511 ///The size is only used in the dynamic case. 00512 ///@param op Operator from which to determine the size. 00513 template<typename Op> 00514 ColSizeHolder(const Operator<Op>& op) : SizeHolder<S>(op.num_cols()) {} 00515 00516 ///Return the number of columns. 00517 int num_cols() const {return SizeHolder<S>::size();} 00518 }; 00519 00520 00521 00522 template<int R, int C, class Precision, bool FullyStatic=(R>=0 && C>=0)> 00523 struct MatrixAlloc: public StaticSizedAllocator<R*C, Precision> 00524 { 00525 MatrixAlloc(int,int) 00526 {} 00527 00528 MatrixAlloc() 00529 {} 00530 00531 template <class Op> 00532 MatrixAlloc(const Operator<Op>&) 00533 {} 00534 00535 int num_rows() const { 00536 return R; 00537 } 00538 00539 int num_cols() const { 00540 return C; 00541 } 00542 00543 using StaticSizedAllocator<R*C, Precision>::my_data; 00544 00545 Precision* get_data_ptr() 00546 { 00547 return my_data; 00548 } 00549 00550 const Precision* get_data_ptr() const 00551 { 00552 return my_data; 00553 } 00554 }; 00555 00556 00557 template<int R, int C, class Precision> struct MatrixAlloc<R, C, Precision, false> 00558 : public RowSizeHolder<R>, 00559 ColSizeHolder<C> 00560 { 00561 Precision* const my_data; 00562 00563 using RowSizeHolder<R>::num_rows; 00564 using ColSizeHolder<C>::num_cols; 00565 00566 // copy constructor so guaranteed contiguous 00567 MatrixAlloc(const MatrixAlloc& m) 00568 :RowSizeHolder<R>(m.num_rows()), 00569 ColSizeHolder<C>(m.num_cols()), 00570 my_data(new Precision[num_rows()*num_cols()]) { 00571 const int size=num_rows()*num_cols(); 00572 for(int i=0; i < size; i++) { 00573 my_data[i] = m.my_data[i]; 00574 } 00575 } 00576 00577 MatrixAlloc(int r, int c) 00578 :RowSizeHolder<R>(r), 00579 ColSizeHolder<C>(c), 00580 my_data(new Precision[num_rows()*num_cols()]) 00581 { 00582 debug_initialize(my_data, num_rows()*num_cols()); 00583 } 00584 00585 template <class Op> MatrixAlloc(const Operator<Op>& op) 00586 :RowSizeHolder<R>(op), 00587 ColSizeHolder<C>(op), 00588 my_data(new Precision[num_rows()*num_cols()]) 00589 { 00590 debug_initialize(my_data, num_rows()*num_cols()); 00591 } 00592 00593 ~MatrixAlloc() { 00594 delete[] my_data; 00595 } 00596 00597 Precision* get_data_ptr() 00598 { 00599 return my_data; 00600 } 00601 00602 const Precision* get_data_ptr() const 00603 { 00604 return my_data; 00605 } 00606 }; 00607 00608 00609 template<int R, int C, class Precision> struct MatrixSlice 00610 : public RowSizeHolder<R>, 00611 ColSizeHolder<C> 00612 { 00613 Precision* const my_data; 00614 00615 using RowSizeHolder<R>::num_rows; 00616 using ColSizeHolder<C>::num_cols; 00617 00618 //Optional Constructors 00619 MatrixSlice(Precision* p) 00620 :my_data(p){} 00621 00622 MatrixSlice(Precision* p, int r, int c) 00623 :RowSizeHolder<R>(r), 00624 ColSizeHolder<C>(c), 00625 my_data(p){} 00626 00627 template<class Op> 00628 MatrixSlice(const Operator<Op>& op) 00629 :RowSizeHolder<R>(op), 00630 ColSizeHolder<C>(op), 00631 my_data(op.data()) 00632 {} 00633 }; 00634 00635 00636 //////////////////////////////////////////////////////////////////////////////// 00637 // 00638 // A class similar to mem, but to hold the stride information. It is only needed 00639 // for -1. For +int and -2, the stride is part fo teh type, or implicit. 00640 00641 template<int s> struct StrideHolder 00642 { 00643 //Constructos ignore superfluous arguments 00644 StrideHolder(){} 00645 StrideHolder(int){} 00646 00647 template<class Op> 00648 StrideHolder(const Operator<Op>&) {} 00649 00650 int stride() const{ 00651 return s; 00652 } 00653 }; 00654 00655 template<> struct StrideHolder<-1> 00656 { 00657 StrideHolder(int s) 00658 :my_stride(s){} 00659 00660 template<class Op> 00661 StrideHolder(const Operator<Op>& op) : my_stride(op.stride()) {} 00662 00663 const int my_stride; 00664 int stride() const { 00665 return my_stride; 00666 } 00667 }; 00668 00669 00670 template<int S> struct RowStrideHolder: public StrideHolder<S> 00671 { 00672 RowStrideHolder(int i) 00673 :StrideHolder<S>(i){} 00674 00675 RowStrideHolder() 00676 {} 00677 00678 template<class Op> 00679 RowStrideHolder(const Operator<Op>& op) 00680 : StrideHolder<S>(op) 00681 {} 00682 00683 }; 00684 00685 00686 template<int S> struct ColStrideHolder: public StrideHolder<S> 00687 { 00688 ColStrideHolder(int i) 00689 :StrideHolder<S>(i){} 00690 00691 ColStrideHolder() 00692 {} 00693 00694 template<class Op> 00695 ColStrideHolder(const Operator<Op>& op) 00696 : StrideHolder<S>(op) 00697 {} 00698 }; 00699 00700 } 00701 00702 } 00703 00704 00705 #undef TOON_ALIGN8