[ VIGRA Homepage | Class Index | Function Index | File Index | Main Page ]
![]() |
vigra/tinyvector.hxx | ![]() |
---|
00001 /************************************************************************/ 00002 /* */ 00003 /* Copyright 1998-2002 by Ullrich Koethe */ 00004 /* Cognitive Systems Group, University of Hamburg, Germany */ 00005 /* */ 00006 /* This file is part of the VIGRA computer vision library. */ 00007 /* ( Version 1.3.2, Jan 27 2005 ) */ 00008 /* You may use, modify, and distribute this software according */ 00009 /* to the terms stated in the LICENSE file included in */ 00010 /* the VIGRA distribution. */ 00011 /* */ 00012 /* The VIGRA Website is */ 00013 /* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ 00014 /* Please direct questions, bug reports, and contributions to */ 00015 /* koethe@informatik.uni-hamburg.de */ 00016 /* */ 00017 /* THIS SOFTWARE IS PROVIDED AS IS AND WITHOUT ANY EXPRESS OR */ 00018 /* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */ 00019 /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ 00020 /* */ 00021 /************************************************************************/ 00022 00023 00024 #ifndef VIGRA_TINYVECTOR_HXX 00025 #define VIGRA_TINYVECTOR_HXX 00026 00027 #include <cmath> // abs(double) 00028 #include <cstdlib> // abs(int) 00029 #include <iosfwd> // ostream 00030 #include "vigra/config.hxx" 00031 #include "vigra/error.hxx" 00032 #include "vigra/numerictraits.hxx" 00033 #include "vigra/error.hxx" 00034 00035 namespace vigra { 00036 00037 using VIGRA_CSTD::abs; 00038 using VIGRA_CSTD::ceil; 00039 using VIGRA_CSTD::floor; 00040 00041 namespace detail { 00042 00043 #define VIGRA_EXEC_LOOP(NAME, OPER) \ 00044 template <class T1, class T2> \ 00045 static void NAME(T1 * left, T2 const * right) \ 00046 { \ 00047 for(int i=0; i<LEVEL; ++i) \ 00048 (left[i]) OPER (right[i]); \ 00049 } 00050 00051 #define VIGRA_EXEC_LOOP_SCALAR(NAME, OPER) \ 00052 template <class T1, class T2> \ 00053 static void NAME(T1 * left, T2 right) \ 00054 { \ 00055 for(int i=0; i<LEVEL; ++i) \ 00056 (left[i]) OPER (right); \ 00057 } 00058 00059 template <int LEVEL> 00060 struct ExecLoop 00061 { 00062 template <class T1, class T2> 00063 static void assignCast(T1 * left, T2 const * right) 00064 { 00065 for(int i=0; i<LEVEL; ++i) 00066 left[i] = detail::RequiresExplicitCast<T1>::cast(right[i]); 00067 } 00068 00069 VIGRA_EXEC_LOOP(assign, =) 00070 VIGRA_EXEC_LOOP(add, +=) 00071 VIGRA_EXEC_LOOP(sub, -=) 00072 VIGRA_EXEC_LOOP(mul, *=) 00073 VIGRA_EXEC_LOOP(neg, = -) 00074 VIGRA_EXEC_LOOP(abs, = vigra::abs) 00075 VIGRA_EXEC_LOOP(floor, = vigra::floor) 00076 VIGRA_EXEC_LOOP(ceil, = vigra::ceil) 00077 VIGRA_EXEC_LOOP(fromPromote, = NumericTraits<T1>::fromPromote) 00078 VIGRA_EXEC_LOOP(fromRealPromote, = NumericTraits<T1>::fromRealPromote) 00079 VIGRA_EXEC_LOOP_SCALAR(assignScalar, =) 00080 VIGRA_EXEC_LOOP_SCALAR(mulScalar, *=) 00081 VIGRA_EXEC_LOOP_SCALAR(divScalar, /=) 00082 00083 template <class T1, class T2> 00084 static bool notEqual(T1 const * left, T2 const * right) 00085 { 00086 for(int i=0; i<LEVEL; ++i) 00087 if(left[i] != right[i]) 00088 return true; 00089 return false; 00090 } 00091 00092 template <class T> 00093 static typename NumericTraits<T>::Promote 00094 dot(T const * d) 00095 { 00096 typename NumericTraits<T>::Promote res(*d * *d); 00097 for(int i=1; i<LEVEL; ++i) 00098 res += d[i] * d[i]; 00099 return res; 00100 } 00101 00102 template <class T1, class T2> 00103 static typename PromoteTraits<T1, T2>::Promote 00104 dot(T1 const * left, T2 const * right) 00105 { 00106 typename PromoteTraits<T1, T2>::Promote res(*left * *right); 00107 for(int i=1; i<LEVEL; ++i) 00108 res += left[i] * right[i]; 00109 return res; 00110 } 00111 }; 00112 00113 template <int LEVEL> 00114 struct UnrollDot 00115 { 00116 template <class T> 00117 static typename NumericTraits<T>::Promote 00118 dot(T const * d) 00119 { 00120 return *d * *d + UnrollDot<LEVEL-1>::dot(d+1); 00121 } 00122 00123 template <class T1, class T2> 00124 static typename PromoteTraits<T1, T2>::Promote 00125 dot(T1 const * left, T2 const * right) 00126 { 00127 return *left * *right + UnrollDot<LEVEL-1>::dot(left+1, right+1); 00128 } 00129 }; 00130 00131 template <> 00132 struct UnrollDot<1> 00133 { 00134 template <class T> 00135 static typename NumericTraits<T>::Promote 00136 dot(T const * d) 00137 { 00138 return *d * *d ; 00139 } 00140 00141 template <class T1, class T2> 00142 static typename PromoteTraits<T1, T2>::Promote 00143 dot(T1 const * left, T2 const * right) 00144 { 00145 return *left * *right; 00146 } 00147 }; 00148 00149 #undef VIGRA_EXEC_LOOP 00150 #undef VIGRA_EXEC_LOOP_SCALAR 00151 00152 #define VIGRA_UNROLL_LOOP(NAME, OPER) \ 00153 template <class T1, class T2> \ 00154 static void NAME(T1 * left, T2 const * right) \ 00155 { \ 00156 (*left) OPER (*right); \ 00157 UnrollLoop<LEVEL-1>::NAME(left+1, right+1); \ 00158 } 00159 00160 #define VIGRA_UNROLL_LOOP_SCALAR(NAME, OPER) \ 00161 template <class T1, class T2> \ 00162 static void NAME(T1 * left, T2 right) \ 00163 { \ 00164 (*left) OPER (right); \ 00165 UnrollLoop<LEVEL-1>::NAME(left+1, right); \ 00166 } 00167 00168 00169 template <int LEVEL> 00170 struct UnrollLoop 00171 { 00172 template <class T1, class T2> 00173 static void assignCast(T1 * left, T2 const * right) 00174 { 00175 *left = detail::RequiresExplicitCast<T1>::cast(*right); 00176 UnrollLoop<LEVEL-1>::assignCast(left+1, right+1); 00177 } 00178 00179 VIGRA_UNROLL_LOOP(assign, =) 00180 VIGRA_UNROLL_LOOP(add, +=) 00181 VIGRA_UNROLL_LOOP(sub, -=) 00182 VIGRA_UNROLL_LOOP(mul, *=) 00183 VIGRA_UNROLL_LOOP(neg, = -) 00184 VIGRA_UNROLL_LOOP(abs, = vigra::abs) 00185 VIGRA_UNROLL_LOOP(floor, = vigra::floor) 00186 VIGRA_UNROLL_LOOP(ceil, = vigra::ceil) 00187 VIGRA_UNROLL_LOOP(fromPromote, = NumericTraits<T1>::fromPromote) 00188 VIGRA_UNROLL_LOOP(fromRealPromote, = NumericTraits<T1>::fromRealPromote) 00189 VIGRA_UNROLL_LOOP_SCALAR(assignScalar, =) 00190 VIGRA_UNROLL_LOOP_SCALAR(mulScalar, *=) 00191 VIGRA_UNROLL_LOOP_SCALAR(divScalar, /=) 00192 00193 template <class T1, class T2> 00194 static bool notEqual(T1 const * left, T2 const * right) 00195 { 00196 return (*left != *right) || UnrollLoop<LEVEL - 1>::notEqual(left+1, right+1); 00197 } 00198 00199 template <class T> 00200 static typename NumericTraits<T>::Promote 00201 dot(T const * d) 00202 { 00203 return UnrollDot<LEVEL>::dot(d); 00204 } 00205 00206 template <class T1, class T2> 00207 static typename PromoteTraits<T1, T2>::Promote 00208 dot(T1 const * left, T2 const * right) 00209 { 00210 return UnrollDot<LEVEL>::dot(left, right); 00211 } 00212 }; 00213 00214 #undef VIGRA_UNROLL_LOOP 00215 #undef VIGRA_UNROLL_LOOP_SCALAR 00216 00217 template <> 00218 struct UnrollLoop<0> 00219 { 00220 template <class T1, class T2> 00221 static void assignCast(T1, T2) {} 00222 template <class T1, class T2> 00223 static void assign(T1, T2) {} 00224 template <class T1, class T2> 00225 static void assignScalar(T1, T2) {} 00226 template <class T1, class T2> 00227 static void add(T1, T2) {} 00228 template <class T1, class T2> 00229 static void sub(T1, T2) {} 00230 template <class T1, class T2> 00231 static void mul(T1, T2) {} 00232 template <class T1, class T2> 00233 static void mulScalar(T1, T2) {} 00234 template <class T1, class T2> 00235 static void div(T1, T2) {} 00236 template <class T1, class T2> 00237 static void divScalar(T1, T2) {} 00238 template <class T1, class T2> 00239 static void fromPromote(T1, T2) {} 00240 template <class T1, class T2> 00241 static void fromRealPromote(T1, T2) {} 00242 template <class T1, class T2> 00243 static void neg(T1, T2) {} 00244 template <class T1, class T2> 00245 static void abs(T1, T2) {} 00246 template <class T1, class T2> 00247 static void floor(T1, T2) {} 00248 template <class T1, class T2> 00249 static void ceil(T1, T2) {} 00250 template <class T1, class T2> 00251 static bool notEqual(T1, T2) { return false; } 00252 }; 00253 00254 template <bool PREDICATE> 00255 struct TinyVectorIf 00256 { 00257 template <class T, class F> 00258 struct res 00259 { 00260 typedef T type; 00261 }; 00262 }; 00263 00264 template <> 00265 struct TinyVectorIf<false> 00266 { 00267 template <class T, class F> 00268 struct res 00269 { 00270 typedef F type; 00271 }; 00272 }; 00273 00274 template <int SIZE> 00275 struct LoopType 00276 { 00277 typedef typename TinyVectorIf<SIZE < 5>:: 00278 template res<UnrollLoop<SIZE>, ExecLoop<SIZE> >::type type; 00279 }; 00280 00281 struct DontInit {}; 00282 00283 inline DontInit dontInit() {return DontInit(); } 00284 00285 } // namespace detail 00286 00287 template <class T, int SIZE> 00288 class TinyVector; 00289 00290 template <class T, int SIZE> 00291 class TinyVectorView; 00292 00293 /********************************************************/ 00294 /* */ 00295 /* TinyVectorBase */ 00296 /* */ 00297 /********************************************************/ 00298 00299 /** \brief Base class for fixed size vectors. 00300 00301 This class contains functionality shared by 00302 \ref TinyVector and \ref TinyVectorView, and enables these classes 00303 to be freely mixed within expressions. It is typically not used directly. 00304 00305 <b>\#include</b> "<a href="tinyvector_8hxx-source.html">vigra/tinyvector.hxx</a>"<br> 00306 Namespace: vigra 00307 **/ 00308 template <class VALUETYPE, int SIZE, class DATA, class DERIVED> 00309 class TinyVectorBase 00310 { 00311 TinyVectorBase(TinyVectorBase const &); // do not use 00312 00313 TinyVectorBase & operator=(TinyVectorBase const & other); // do not use 00314 00315 protected: 00316 00317 typedef typename detail::LoopType<SIZE>::type Loop; 00318 00319 TinyVectorBase() 00320 {} 00321 00322 public: 00323 /** STL-compatible definition of valuetype 00324 */ 00325 typedef VALUETYPE value_type; 00326 00327 /** reference (return of operator[]). 00328 */ 00329 typedef VALUETYPE & reference; 00330 00331 /** const reference (return of operator[] const). 00332 */ 00333 typedef VALUETYPE const & const_reference; 00334 00335 /** pointer (return of operator->). 00336 */ 00337 typedef VALUETYPE * pointer; 00338 00339 /** const pointer (return of operator-> const). 00340 */ 00341 typedef VALUETYPE const * const_pointer; 00342 00343 /** STL-compatible definition of iterator 00344 */ 00345 typedef value_type * iterator; 00346 00347 /** STL-compatible definition of const iterator 00348 */ 00349 typedef value_type const * const_iterator; 00350 00351 /** STL-compatible definition of size_type 00352 */ 00353 typedef unsigned int size_type; 00354 00355 /** STL-compatible definition of difference_type 00356 */ 00357 typedef int difference_type; 00358 00359 /** the scalar type for the outer product 00360 */ 00361 typedef double scalar_multiplier; 00362 00363 /** the vector's size 00364 */ 00365 enum { static_size = SIZE }; 00366 00367 /** Initialize from another sequence (must have length SIZE!) 00368 */ 00369 template <class Iterator> 00370 void init(Iterator i, Iterator end) 00371 { 00372 vigra_precondition(end-i == SIZE, 00373 "TinyVector::init(): Sequence has wrong size."); 00374 Loop::assignCast(data_, i); 00375 } 00376 00377 /** Component-wise add-assignment 00378 */ 00379 template <class T1, class D1, class D2> 00380 DERIVED & operator+=(TinyVectorBase<T1, SIZE, D1, D2> const & r) 00381 { 00382 Loop::add(data_, r.begin()); 00383 return static_cast<DERIVED &>(*this); 00384 } 00385 00386 /** Component-wise subtract-assignment 00387 */ 00388 template <class T1, class D1, class D2> 00389 DERIVED & operator-=(TinyVectorBase<T1, SIZE, D1, D2> const & r) 00390 { 00391 Loop::sub(data_, r.begin()); 00392 return static_cast<DERIVED &>(*this); 00393 } 00394 00395 /** Component-wise multiply-assignment 00396 */ 00397 template <class T1, class D1, class D2> 00398 DERIVED & operator*=(TinyVectorBase<T1, SIZE, D1, D2> const & r) 00399 { 00400 Loop::mul(data_, r.begin()); 00401 return static_cast<DERIVED &>(*this); 00402 } 00403 00404 /** Component-wise scalar multiply-assignment 00405 */ 00406 DERIVED & operator*=(double r) 00407 { 00408 Loop::mulScalar(data_, r); 00409 return static_cast<DERIVED &>(*this); 00410 } 00411 00412 /** Component-wise scalar divide-assignment 00413 */ 00414 DERIVED & operator/=(double r) 00415 { 00416 Loop::divScalar(data_, r); 00417 return static_cast<DERIVED &>(*this); 00418 } 00419 00420 /** Calculate magnitude. 00421 */ 00422 typename NumericTraits<VALUETYPE>::RealPromote 00423 magnitude() const 00424 { 00425 return VIGRA_CSTD::sqrt( 00426 (typename NumericTraits<VALUETYPE>::RealPromote)squaredMagnitude()); 00427 } 00428 00429 /** Calculate squared magnitude. 00430 */ 00431 typename NumericTraits<VALUETYPE>::Promote 00432 squaredMagnitude() const 00433 { 00434 return Loop::dot(data_); 00435 } 00436 00437 /** Access component by index. 00438 */ 00439 reference operator[](difference_type i) { return data_[i]; } 00440 00441 /** Get component by index. 00442 */ 00443 const_reference operator[](difference_type i) const { return data_[i]; } 00444 00445 /** Get random access iterator to begin of vector. 00446 */ 00447 iterator begin() { return data_; } 00448 /** Get random access iterator past-the-end of vector. 00449 */ 00450 iterator end() { return data_ + SIZE; } 00451 00452 /** Get const random access iterator to begin of vector. 00453 */ 00454 const_iterator begin() const { return data_; } 00455 00456 /** Get const random access iterator past-the-end of vector. 00457 */ 00458 const_iterator end() const { return data_ + SIZE; } 00459 00460 /** Size of TinyVector vector always equals the template parameter SIZE. 00461 */ 00462 size_type size() const { return SIZE; } 00463 00464 pointer data() { return data_; } 00465 00466 const_pointer data() const { return data_; } 00467 00468 00469 protected: 00470 DATA data_; 00471 }; 00472 00473 /** \brief Class for fixed size vectors. 00474 00475 This class contains an array of size SIZE of the specified VALUETYPE. 00476 The interface conforms to STL vector, except that there are no functions 00477 that change the size of a TinyVector. 00478 00479 \ref TinyVectorOperators "Arithmetic operations" 00480 on TinyVectors are defined as component-wise applications of these 00481 operations. Addition and subtraction of two TinyVectors 00482 (+=, -=, +, -, unary -), multiplication and division of an 00483 TinyVector with a double, and NumericTraits/PromoteTraits are defined, 00484 so that TinyVector fulfills the requirements of \ref LinearAlgebra. 00485 00486 VIGRA algorithms typically use \ref vigra::VectorAccessor to access 00487 TinyVectors as a whole, or specific components of them. 00488 00489 See also:<br> 00490 <DL> 00491 <DT> 00492 <IMG BORDER=0 ALT="-" SRC="documents/bullet.gif"> 00493 \ref vigra::TinyVectorBase 00494 <DD> 00495 <DT> 00496 <IMG BORDER=0 ALT="-" SRC="documents/bullet.gif"> 00497 \ref vigra::TinyVectorView 00498 <DD> 00499 <DT> 00500 <IMG BORDER=0 ALT="-" SRC="documents/bullet.gif"> 00501 \ref TinyVectorTraits 00502 <DD> 00503 <DT> 00504 <IMG BORDER=0 ALT="-" SRC="documents/bullet.gif"> 00505 \ref TinyVectorOperators 00506 <DD> 00507 </DL> 00508 00509 <b>\#include</b> "<a href="tinyvector_8hxx-source.html">vigra/tinyvector.hxx</a>"<br> 00510 Namespace: vigra 00511 **/ 00512 template <class T, int SIZE> 00513 class TinyVector 00514 : public TinyVectorBase<T, SIZE, T[SIZE], TinyVector<T, SIZE> > 00515 { 00516 typedef TinyVectorBase<T, SIZE, T[SIZE], TinyVector<T, SIZE> > BaseType; 00517 typedef typename BaseType::Loop Loop; 00518 00519 public: 00520 00521 typedef typename BaseType::value_type value_type; 00522 typedef typename BaseType::reference reference; 00523 typedef typename BaseType::const_reference const_reference; 00524 typedef typename BaseType::pointer pointer; 00525 typedef typename BaseType::const_pointer const_pointer; 00526 typedef typename BaseType::iterator iterator; 00527 typedef typename BaseType::const_iterator const_iterator; 00528 typedef typename BaseType::size_type size_type; 00529 typedef typename BaseType::difference_type difference_type; 00530 typedef typename BaseType::scalar_multiplier scalar_multiplier; 00531 00532 /** Construction with constant value 00533 */ 00534 explicit TinyVector(value_type const & initial) 00535 : BaseType() 00536 { 00537 Loop::assignScalar(BaseType::begin(), initial); 00538 } 00539 00540 /** Construction with explicit values. 00541 Call only if SIZE == 2 00542 */ 00543 TinyVector(value_type const & i1, value_type const & i2) 00544 : BaseType() 00545 { 00546 BaseType::data_[0] = i1; 00547 BaseType::data_[1] = i2; 00548 } 00549 00550 /** Construction with explicit values. 00551 Call only if SIZE == 3 00552 */ 00553 TinyVector(value_type const & i1, value_type const & i2, value_type const & i3) 00554 : BaseType() 00555 { 00556 BaseType::data_[0] = i1; 00557 BaseType::data_[1] = i2; 00558 BaseType::data_[2] = i3; 00559 } 00560 00561 /** Construction with explicit values. 00562 Call only if SIZE == 4 00563 */ 00564 TinyVector(value_type const & i1, value_type const & i2, 00565 value_type const & i3, value_type const & i4) 00566 : BaseType() 00567 { 00568 BaseType::data_[0] = i1; 00569 BaseType::data_[1] = i2; 00570 BaseType::data_[2] = i3; 00571 BaseType::data_[3] = i4; 00572 } 00573 00574 /** Default constructor (initializes all components with zero) 00575 */ 00576 TinyVector() 00577 : BaseType() 00578 { 00579 Loop::assignScalar(BaseType::data_, NumericTraits<value_type>::zero()); 00580 } 00581 00582 /** Copy constructor. 00583 */ 00584 TinyVector(TinyVector const & r) 00585 : BaseType() 00586 { 00587 Loop::assign(BaseType::data_, r.data_); 00588 } 00589 00590 /** Copy assignment. 00591 */ 00592 TinyVector & operator=(TinyVector const & r) 00593 { 00594 Loop::assign(BaseType::data_, r.data_); 00595 return *this; 00596 } 00597 00598 /** Copy with type conversion. 00599 */ 00600 template <class U, class DATA, class DERIVED> 00601 TinyVector(TinyVectorBase<U, SIZE, DATA, DERIVED> const & r) 00602 : BaseType() 00603 { 00604 Loop::assignCast(BaseType::data_, r.begin()); 00605 } 00606 00607 /** Copy assignment with type conversion. 00608 */ 00609 template <class U, class DATA, class DERIVED> 00610 TinyVector & operator=(TinyVectorBase<U, SIZE, DATA, DERIVED> const & r) 00611 { 00612 Loop::assignCast(BaseType::data_, r.begin()); 00613 return *this; 00614 } 00615 00616 explicit TinyVector(detail::DontInit) 00617 : BaseType() 00618 {} 00619 }; 00620 00621 /** \brief Wrapper for fixed size vectors. 00622 00623 This class wraps an array of size SIZE of the specified VALUETYPE. 00624 Thus, the array can be accessed with an interface similar to 00625 that of std::vector (except that there are no functions 00626 that change the size of a TinyVectorView). The TinyVectorView 00627 does <em>not</em> assume ownership of the given memory. 00628 00629 \ref TinyVectorOperators "Arithmetic operations" 00630 on TinyVectorViews are defined as component-wise applications of these 00631 operations. Addition and subtraction of two TinyVectorViews 00632 (+=, -=, +, -, unary -), multiplication and division of an 00633 TinyVectorViews with a double, and NumericTraits/PromoteTraits are defined, 00634 so that TinyVectorView fulfills the requirements of \ref LinearAlgebra. 00635 00636 VIGRA algorithms typically use \ref vigra::VectorAccessor to access 00637 TinyVectorViews as a whole, or specific components of them. 00638 00639 <b>See also:</b> 00640 <ul> 00641 <li> \ref vigra::TinyVectorBase 00642 <li> \ref vigra::TinyVector 00643 <li> \ref TinyVectorTraits 00644 <li> \ref TinyVectorOperators 00645 </ul> 00646 00647 <b>\#include</b> "<a href="tinyvector_8hxx-source.html">vigra/tinyvector.hxx</a>"<br> 00648 Namespace: vigra 00649 **/ 00650 template <class T, int SIZE> 00651 class TinyVectorView 00652 : public TinyVectorBase<T, SIZE, T *, TinyVectorView<T, SIZE> > 00653 { 00654 typedef TinyVectorBase<T, SIZE, T *, TinyVectorView<T, SIZE> > BaseType; 00655 typedef typename BaseType::Loop Loop; 00656 00657 public: 00658 00659 typedef typename BaseType::value_type value_type; 00660 typedef typename BaseType::reference reference; 00661 typedef typename BaseType::const_reference const_reference; 00662 typedef typename BaseType::pointer pointer; 00663 typedef typename BaseType::const_pointer const_pointer; 00664 typedef typename BaseType::iterator iterator; 00665 typedef typename BaseType::const_iterator const_iterator; 00666 typedef typename BaseType::size_type size_type; 00667 typedef typename BaseType::difference_type difference_type; 00668 typedef typename BaseType::scalar_multiplier scalar_multiplier; 00669 00670 /** Default constructor 00671 (pointer to wrapped data is NULL). 00672 */ 00673 TinyVectorView() 00674 : BaseType() 00675 { 00676 BaseType::data_ = 0; 00677 } 00678 00679 /** Construct view for given data array 00680 */ 00681 TinyVectorView(const_pointer data) 00682 : BaseType() 00683 { 00684 BaseType::data_ = const_cast<pointer>(data); 00685 } 00686 00687 /** Copy constructor (shallow copy). 00688 */ 00689 TinyVectorView(TinyVectorView const & other) 00690 : BaseType() 00691 { 00692 BaseType::data_ = const_cast<pointer>(other.data_); 00693 } 00694 00695 /** Construct view from other TinyVector. 00696 */ 00697 template <class DATA, class DERIVED> 00698 TinyVectorView(TinyVectorBase<T, SIZE, DATA, DERIVED> const & other) 00699 : BaseType() 00700 { 00701 BaseType::data_ = const_cast<pointer>(other.data()); 00702 } 00703 00704 /** Copy the data (not the pointer) of the rhs. 00705 */ 00706 TinyVectorView & operator=(TinyVectorView const & r) 00707 { 00708 Loop::assign(BaseType::data_, r.begin()); 00709 return *this; 00710 } 00711 00712 /** Copy the data of the rhs with cast. 00713 */ 00714 template <class U, class DATA, class DERIVED> 00715 TinyVectorView & operator=(TinyVectorBase<U, SIZE, DATA, DERIVED> const & r) 00716 { 00717 Loop::assignCast(BaseType::data_, r.begin()); 00718 return *this; 00719 } 00720 }; 00721 00722 } // namespace vigra 00723 00724 /********************************************************/ 00725 /* */ 00726 /* TinyVector Output */ 00727 /* */ 00728 /********************************************************/ 00729 00730 /** \addtogroup TinyVectorOperators 00731 */ 00732 //@{ 00733 /// stream output 00734 template <class V1, int SIZE, class DATA, class DERIVED> 00735 std::ostream & 00736 operator<<(std::ostream & out, vigra::TinyVectorBase<V1, SIZE, DATA, DERIVED> const & l) 00737 { 00738 out << "("; 00739 int i; 00740 for(i=0; i<SIZE-1; ++i) 00741 out << l[i] << ", "; 00742 out << l[i] << ")"; 00743 return out; 00744 } 00745 00746 /********************************************************/ 00747 /* */ 00748 /* TinyVector Comparison */ 00749 /* */ 00750 /********************************************************/ 00751 00752 namespace vigra { 00753 00754 /** \addtogroup TinyVectorOperators Functions for TinyVector 00755 00756 \brief <b>\#include</b> "<a href="tinyvector_8hxx-source.html">vigra/tinyvector.hxx</a> 00757 00758 These functions fulfill the requirements of a Linear Space (vector space). 00759 Return types are determined according to \ref TinyVectorTraits. 00760 00761 Namespace: vigra 00762 <p> 00763 00764 */ 00765 //@{ 00766 /// component-wise equal 00767 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4> 00768 inline bool 00769 operator==(TinyVectorBase<V1, SIZE, D1, D2> const & l, 00770 TinyVectorBase<V2, SIZE, D3, D4> const & r) 00771 { 00772 return !(l != r); 00773 } 00774 00775 /// component-wise not equal 00776 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4> 00777 inline bool 00778 operator!=(TinyVectorBase<V1, SIZE, D1, D2> const & l, 00779 TinyVectorBase<V2, SIZE, D3, D4> const & r) 00780 { 00781 typedef typename detail::LoopType<SIZE>::type ltype; 00782 return ltype::notEqual(l.begin(), r.begin()); 00783 } 00784 00785 //@} 00786 00787 /********************************************************/ 00788 /* */ 00789 /* TinyVector-Traits */ 00790 /* */ 00791 /********************************************************/ 00792 00793 /** \page TinyVectorTraits Numeric and Promote Traits of TinyVector 00794 The numeric and promote traits for TinyVectors follow 00795 the general specifications for \ref NumericPromotionTraits. 00796 They are implemented in terms of the traits of the basic types by 00797 partial template specialization: 00798 00799 \code 00800 00801 template <class T, int SIZE> 00802 struct NumericTraits<TinyVector<T, SIZE> > 00803 { 00804 typedef TinyVector<typename NumericTraits<T>::Promote, SIZE> Promote; 00805 typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> RealPromote; 00806 00807 typedef typename NumericTraits<T>::isIntegral isIntegral; 00808 typedef VigraFalseType isScalar; 00809 00810 // etc. 00811 }; 00812 00813 template <class T1, class T2, SIZE> 00814 struct PromoteTraits<TinyVector<T1, SIZE>, TinyVector<T2, SIZE> > 00815 { 00816 typedef TinyVector<typename PromoteTraits<T1, T2>::Promote, SIZE> Promote; 00817 }; 00818 \endcode 00819 00820 <b>\#include</b> "<a href="tinyvector_8hxx-source.html">vigra/tinyvector.hxx</a>"<br> 00821 Namespace: vigra 00822 00823 On compilers that don't support pertial template specialization (e.g. 00824 MS VisualC++), the traits classes are explicitly specialized for 00825 <TT>TinyVector<VALUETYPE, SIZE></TT> with 00826 <TT>VALUETYPE = unsigned char | int | float | double</TT> and <TT>SIZE = 2 | 3 | 4</TT>. 00827 00828 */ 00829 00830 #if !defined(NO_PARTIAL_TEMPLATE_SPECIALIZATION) 00831 00832 template <class T, int SIZE> 00833 struct NumericTraits<TinyVector<T, SIZE> > 00834 { 00835 typedef TinyVector<T, SIZE> Type; 00836 typedef TinyVector<typename NumericTraits<T>::Promote, SIZE> Promote; 00837 typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> RealPromote; 00838 typedef TinyVector<typename NumericTraits<T>::ComplexPromote, SIZE> ComplexPromote; 00839 typedef T ValueType; 00840 00841 typedef typename NumericTraits<T>::isIntegral isIntegral; 00842 typedef VigraFalseType isScalar; 00843 typedef VigraFalseType isOrdered; 00844 typedef VigraFalseType isComplex; 00845 00846 static TinyVector<T, SIZE> zero() { 00847 return TinyVector<T, SIZE>(NumericTraits<T>::zero()); 00848 } 00849 static TinyVector<T, SIZE> one() { 00850 return TinyVector<T, SIZE>(NumericTraits<T>::one()); 00851 } 00852 static TinyVector<T, SIZE> nonZero() { 00853 return TinyVector<T, SIZE>(NumericTraits<T>::nonZero()); 00854 } 00855 00856 template <class D1, class D2> 00857 static Promote toPromote(TinyVectorBase<T, SIZE, D1, D2> const & v) 00858 { 00859 return Promote(v); 00860 } 00861 00862 template <class D1, class D2> 00863 static RealPromote toRealPromote(TinyVectorBase<T, SIZE, D1, D2> const & v) 00864 { 00865 return RealPromote(v); 00866 } 00867 00868 template <class D1, class D2> 00869 static TinyVector<T, SIZE> 00870 fromPromote(TinyVectorBase<typename NumericTraits<T>::Promote, SIZE, D1, D2> const & v) 00871 { 00872 TinyVector<T, SIZE> res(detail::dontInit()); 00873 typedef typename detail::LoopType<SIZE>::type ltype; 00874 ltype::fromPromote(res.begin(), v.begin()); 00875 return res; 00876 } 00877 00878 template <class D1, class D2> 00879 static TinyVector<T, SIZE> 00880 fromRealPromote(TinyVectorBase<typename NumericTraits<T>::RealPromote, SIZE, D1, D2> const & v) 00881 { 00882 TinyVector<T, SIZE> res(detail::dontInit()); 00883 typedef typename detail::LoopType<SIZE>::type ltype; 00884 ltype::fromRealPromote(res.begin(), v.begin()); 00885 return res; 00886 } 00887 }; 00888 00889 template <class T, int SIZE> 00890 struct NumericTraits<TinyVectorView<T, SIZE> > 00891 : public NumericTraits<TinyVector<T, SIZE> > 00892 { 00893 typedef TinyVector<T, SIZE> Type; 00894 typedef TinyVector<typename NumericTraits<T>::Promote, SIZE> Promote; 00895 typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> RealPromote; 00896 typedef TinyVector<typename NumericTraits<T>::ComplexPromote, SIZE> ComplexPromote; 00897 typedef T ValueType; 00898 00899 typedef typename NumericTraits<T>::isIntegral isIntegral; 00900 typedef VigraFalseType isScalar; 00901 typedef VigraFalseType isOrdered; 00902 typedef VigraFalseType isComplex; 00903 }; 00904 00905 template <class T1, class T2, int SIZE> 00906 struct PromoteTraits<TinyVector<T1, SIZE>, TinyVector<T2, SIZE> > 00907 { 00908 typedef TinyVector<typename PromoteTraits<T1, T2>::Promote, SIZE> Promote; 00909 }; 00910 00911 template <class T1, class T2, int SIZE> 00912 struct PromoteTraits<TinyVectorView<T1, SIZE>, TinyVectorView<T2, SIZE> > 00913 { 00914 typedef TinyVector<typename PromoteTraits<T1, T2>::Promote, SIZE> Promote; 00915 }; 00916 00917 template <class T1, class T2, int SIZE> 00918 struct PromoteTraits<TinyVectorView<T1, SIZE>, TinyVector<T2, SIZE> > 00919 { 00920 typedef TinyVector<typename PromoteTraits<T1, T2>::Promote, SIZE> Promote; 00921 }; 00922 00923 template <class T1, class T2, int SIZE> 00924 struct PromoteTraits<TinyVector<T1, SIZE>, TinyVectorView<T2, SIZE> > 00925 { 00926 typedef TinyVector<typename PromoteTraits<T1, T2>::Promote, SIZE> Promote; 00927 }; 00928 00929 template <class T, int SIZE> 00930 struct PromoteTraits<TinyVector<T, SIZE>, double > 00931 { 00932 typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> Promote; 00933 }; 00934 00935 template <class T, int SIZE> 00936 struct PromoteTraits<double, TinyVector<T, SIZE> > 00937 { 00938 typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> Promote; 00939 }; 00940 00941 template <class T, int SIZE> 00942 struct PromoteTraits<TinyVectorView<T, SIZE>, double > 00943 { 00944 typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> Promote; 00945 }; 00946 00947 template <class T, int SIZE> 00948 struct PromoteTraits<double, TinyVectorView<T, SIZE> > 00949 { 00950 typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> Promote; 00951 }; 00952 00953 #else // NO_PARTIAL_TEMPLATE_SPECIALIZATION 00954 00955 00956 #define TINYVECTOR_NUMTRAITS(T, SIZE) \ 00957 template<>\ 00958 struct NumericTraits<TinyVector<T, SIZE> >\ 00959 {\ 00960 typedef TinyVector<T, SIZE> Type;\ 00961 typedef TinyVector<NumericTraits<T>::Promote, SIZE> Promote;\ 00962 typedef TinyVector<NumericTraits<T>::RealPromote, SIZE> RealPromote;\ 00963 typedef TinyVector<NumericTraits<T>::ComplexPromote, SIZE> ComplexPromote;\ 00964 typedef T ValueType; \ 00965 typedef NumericTraits<T>::isIntegral isIntegral;\ 00966 typedef VigraFalseType isScalar;\ 00967 typedef VigraFalseType isOrdered;\ 00968 typedef VigraFalseType isComplex;\ 00969 \ 00970 static TinyVector<T, SIZE> zero() { \ 00971 return TinyVector<T, SIZE>(NumericTraits<T>::zero()); \ 00972 }\ 00973 static TinyVector<T, SIZE> one() { \ 00974 return TinyVector<T, SIZE>(NumericTraits<T>::one()); \ 00975 }\ 00976 static TinyVector<T, SIZE> nonZero() { \ 00977 return TinyVector<T, SIZE>(NumericTraits<T>::nonZero()); \ 00978 }\ 00979 \ 00980 static Promote toPromote(TinyVector<T, SIZE> const & v) { \ 00981 return Promote(v); \ 00982 }\ 00983 static RealPromote toRealPromote(TinyVector<T, SIZE> const & v) { \ 00984 return RealPromote(v); \ 00985 }\ 00986 static TinyVector<T, SIZE> fromPromote(Promote const & v) { \ 00987 TinyVector<T, SIZE> res;\ 00988 TinyVector<T, SIZE>::iterator d = res.begin(), dend = res.end();\ 00989 Promote::const_iterator s = v.begin();\ 00990 for(; d != dend; ++d, ++s)\ 00991 *d = NumericTraits<T>::fromPromote(*s);\ 00992 return res;\ 00993 }\ 00994 static TinyVector<T, SIZE> fromRealPromote(RealPromote const & v) {\ 00995 TinyVector<T, SIZE> res;\ 00996 TinyVector<T, SIZE>::iterator d = res.begin(), dend = res.end();\ 00997 RealPromote::const_iterator s = v.begin();\ 00998 for(; d != dend; ++d, ++s)\ 00999 *d = NumericTraits<T>::fromRealPromote(*s);\ 01000 return res;\ 01001 }\ 01002 }; 01003 01004 #define TINYVECTOR_PROMTRAITS1(type1, SIZE) \ 01005 template<> \ 01006 struct PromoteTraits<TinyVector<type1, SIZE>, TinyVector<type1, SIZE> > \ 01007 { \ 01008 typedef TinyVector<PromoteTraits<type1, type1>::Promote, SIZE> Promote; \ 01009 static Promote toPromote(TinyVector<type1, SIZE> const & v) { \ 01010 return static_cast<Promote>(v); } \ 01011 }; 01012 01013 #define TINYVECTOR_PROMTRAITS2(type1, type2, SIZE) \ 01014 template<> \ 01015 struct PromoteTraits<TinyVector<type1, SIZE>, TinyVector<type2, SIZE> > \ 01016 { \ 01017 typedef TinyVector<PromoteTraits<type1, type2>::Promote, SIZE> Promote; \ 01018 static Promote toPromote(TinyVector<type1, SIZE> const & v) { \ 01019 return static_cast<Promote>(v); } \ 01020 static Promote toPromote(TinyVector<type2, SIZE> const & v) { \ 01021 return static_cast<Promote>(v); } \ 01022 }; 01023 01024 #define TINYVECTOR_TRAITS(SIZE) \ 01025 TINYVECTOR_NUMTRAITS(unsigned char, SIZE)\ 01026 TINYVECTOR_NUMTRAITS(int, SIZE)\ 01027 TINYVECTOR_NUMTRAITS(float, SIZE)\ 01028 TINYVECTOR_NUMTRAITS(double, SIZE)\ 01029 TINYVECTOR_PROMTRAITS1(unsigned char, SIZE)\ 01030 TINYVECTOR_PROMTRAITS1(int, SIZE)\ 01031 TINYVECTOR_PROMTRAITS1(float, SIZE)\ 01032 TINYVECTOR_PROMTRAITS1(double, SIZE)\ 01033 TINYVECTOR_PROMTRAITS2(float, unsigned char, SIZE)\ 01034 TINYVECTOR_PROMTRAITS2(unsigned char, float, SIZE)\ 01035 TINYVECTOR_PROMTRAITS2(int, unsigned char, SIZE)\ 01036 TINYVECTOR_PROMTRAITS2(unsigned char, int, SIZE)\ 01037 TINYVECTOR_PROMTRAITS2(int, float, SIZE)\ 01038 TINYVECTOR_PROMTRAITS2(float, int, SIZE)\ 01039 TINYVECTOR_PROMTRAITS2(double, unsigned char, SIZE)\ 01040 TINYVECTOR_PROMTRAITS2(unsigned char, double, SIZE)\ 01041 TINYVECTOR_PROMTRAITS2(int, double, SIZE)\ 01042 TINYVECTOR_PROMTRAITS2(double, int, SIZE)\ 01043 TINYVECTOR_PROMTRAITS2(double, float, SIZE)\ 01044 TINYVECTOR_PROMTRAITS2(float, double, SIZE) 01045 01046 TINYVECTOR_TRAITS(2) 01047 TINYVECTOR_TRAITS(3) 01048 TINYVECTOR_TRAITS(4) 01049 01050 #undef TINYVECTOR_NUMTRAITS 01051 #undef TINYVECTOR_PROMTRAITS1 01052 #undef TINYVECTOR_PROMTRAITS2 01053 #undef TINYVECTOR_TRAITS 01054 01055 #endif // NO_PARTIAL_TEMPLATE_SPECIALIZATION 01056 01057 01058 /********************************************************/ 01059 /* */ 01060 /* TinyVector-Arithmetic */ 01061 /* */ 01062 /********************************************************/ 01063 01064 /** \addtogroup TinyVectorOperators 01065 */ 01066 //@{ 01067 01068 /// component-wise addition 01069 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4> 01070 inline 01071 typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2, SIZE> >::Promote 01072 operator+(TinyVectorBase<V1, SIZE, D1, D2> const & l, 01073 TinyVectorBase<V2, SIZE, D3, D4> const & r) 01074 { 01075 typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2 , SIZE> >::Promote res(l); 01076 res += r; 01077 return res; 01078 } 01079 01080 /// component-wise subtraction 01081 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4> 01082 inline 01083 typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2, SIZE> >::Promote 01084 operator-(TinyVectorBase<V1, SIZE, D1, D2> const & l, 01085 TinyVectorBase<V2, SIZE, D3, D4> const & r) 01086 { 01087 typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2 , SIZE> >::Promote res(l); 01088 res -= r; 01089 return res; 01090 } 01091 01092 /// component-wise multiplication 01093 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4> 01094 inline 01095 typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2, SIZE> >::Promote 01096 operator*(TinyVectorBase<V1, SIZE, D1, D2> const & l, 01097 TinyVectorBase<V2, SIZE, D3, D4> const & r) 01098 { 01099 typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2 , SIZE> >::Promote res(l); 01100 res *= r; 01101 return res; 01102 } 01103 01104 /// component-wise left scalar multiplication 01105 template <class V, int SIZE, class D1, class D2> 01106 inline 01107 typename NumericTraits<TinyVector<V, SIZE> >::RealPromote 01108 operator*(double v, TinyVectorBase<V, SIZE, D1, D2> const & r) 01109 { 01110 return typename NumericTraits<TinyVector<V, SIZE> >::RealPromote(r) *= v; 01111 } 01112 01113 /// component-wise right scalar multiplication 01114 template <class V, int SIZE, class D1, class D2> 01115 inline 01116 typename NumericTraits<TinyVector<V, SIZE> >::RealPromote 01117 operator*(TinyVectorBase<V, SIZE, D1, D2> const & l, double v) 01118 { 01119 return typename NumericTraits<TinyVector<V, SIZE> >::RealPromote(l) *= v; 01120 } 01121 01122 /// component-wise scalar division 01123 template <class V, int SIZE, class D1, class D2> 01124 inline 01125 typename NumericTraits<TinyVector<V, SIZE> >::RealPromote 01126 operator/(TinyVectorBase<V, SIZE, D1, D2> const & l, double v) 01127 { 01128 return typename NumericTraits<TinyVector<V, SIZE> >::RealPromote(l) /= v; 01129 } 01130 01131 01132 /** Unary negation (construct TinyVector with negative values) 01133 */ 01134 template <class V, int SIZE, class D1, class D2> 01135 inline 01136 TinyVector<V, SIZE> 01137 operator-(TinyVectorBase<V, SIZE, D1, D2> const & v) 01138 { 01139 TinyVector<V, SIZE> res(detail::dontInit()); 01140 typedef typename detail::LoopType<SIZE>::type ltype; 01141 ltype::neg(res.begin(), v.begin()); 01142 return res; 01143 } 01144 01145 /// component-wise absolute value 01146 template <class V, int SIZE, class D1, class D2> 01147 inline 01148 TinyVector<V, SIZE> 01149 abs(TinyVectorBase<V, SIZE, D1, D2> const & v) 01150 { 01151 TinyVector<V, SIZE> res(detail::dontInit()); 01152 typedef typename detail::LoopType<SIZE>::type ltype; 01153 ltype::abs(res.begin(), v.begin()); 01154 return res; 01155 } 01156 01157 /** Apply ceil() function to each vector component. 01158 */ 01159 template <class V, int SIZE, class D1, class D2> 01160 inline 01161 TinyVector<V, SIZE> 01162 ceil(TinyVectorBase<V, SIZE, D1, D2> const & v) 01163 { 01164 TinyVector<V, SIZE> res(detail::dontInit()); 01165 typedef typename detail::LoopType<SIZE>::type ltype; 01166 ltype::ceil(res.begin(), v.begin()); 01167 return res; 01168 } 01169 01170 /** Apply floor() function to each vector component. 01171 */ 01172 template <class V, int SIZE, class D1, class D2> 01173 inline 01174 TinyVector<V, SIZE> 01175 floor(TinyVectorBase<V, SIZE, D1, D2> const & v) 01176 { 01177 TinyVector<V, SIZE> res(detail::dontInit()); 01178 typedef typename detail::LoopType<SIZE>::type ltype; 01179 ltype::floor(res.begin(), v.begin()); 01180 return res; 01181 } 01182 01183 /// dot product 01184 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4> 01185 inline 01186 typename PromoteTraits<V1, V2>::Promote 01187 dot(TinyVectorBase<V1, SIZE, D1, D2> const & l, 01188 TinyVectorBase<V2, SIZE, D3, D4> const & r) 01189 { 01190 typedef typename detail::LoopType<SIZE>::type ltype; 01191 return ltype::dot(l.begin(), r.begin()); 01192 } 01193 01194 //@} 01195 01196 01197 } // namespace vigra 01198 01199 #endif // VIGRA_TINYVECTOR_HXX
© Ullrich Köthe (koethe@informatik.uni-hamburg.de) |
html generated using doxygen and Python
|