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 // 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