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