[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]
vigra/tinyvector.hxx | ![]() |
00001 /************************************************************************/ 00002 /* */ 00003 /* Copyright 1998-2002 by Ullrich Koethe */ 00004 /* */ 00005 /* This file is part of the VIGRA computer vision library. */ 00006 /* The VIGRA Website is */ 00007 /* http://hci.iwr.uni-heidelberg.de/vigra/ */ 00008 /* Please direct questions, bug reports, and contributions to */ 00009 /* ullrich.koethe@iwr.uni-heidelberg.de or */ 00010 /* vigra@informatik.uni-hamburg.de */ 00011 /* */ 00012 /* Permission is hereby granted, free of charge, to any person */ 00013 /* obtaining a copy of this software and associated documentation */ 00014 /* files (the "Software"), to deal in the Software without */ 00015 /* restriction, including without limitation the rights to use, */ 00016 /* copy, modify, merge, publish, distribute, sublicense, and/or */ 00017 /* sell copies of the Software, and to permit persons to whom the */ 00018 /* Software is furnished to do so, subject to the following */ 00019 /* conditions: */ 00020 /* */ 00021 /* The above copyright notice and this permission notice shall be */ 00022 /* included in all copies or substantial portions of the */ 00023 /* Software. */ 00024 /* */ 00025 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */ 00026 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */ 00027 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */ 00028 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */ 00029 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */ 00030 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */ 00031 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */ 00032 /* OTHER DEALINGS IN THE SOFTWARE. */ 00033 /* */ 00034 /************************************************************************/ 00035 00036 00037 #ifndef VIGRA_TINYVECTOR_HXX 00038 #define VIGRA_TINYVECTOR_HXX 00039 00040 #include <cmath> // abs(double) 00041 #include <cstdlib> // abs(int) 00042 #include <iosfwd> // ostream 00043 #include "config.hxx" 00044 #include "error.hxx" 00045 #include "metaprogramming.hxx" 00046 #include "numerictraits.hxx" 00047 #include "memory.hxx" 00048 #include "mathutil.hxx" 00049 #include "diff2d.hxx" 00050 00051 #ifdef VIGRA_CHECK_BOUNDS 00052 #define VIGRA_ASSERT_INSIDE(diff) \ 00053 vigra_precondition(diff >= 0, "Index out of bounds");\ 00054 vigra_precondition(diff < SIZE, "Index out of bounds"); 00055 #else 00056 #define VIGRA_ASSERT_INSIDE(diff) 00057 #endif 00058 00059 namespace vigra { 00060 00061 using VIGRA_CSTD::abs; 00062 using VIGRA_CSTD::ceil; 00063 using VIGRA_CSTD::floor; 00064 00065 00066 template <class V1, int SIZE, class D1, class D2> 00067 class TinyVectorBase; 00068 00069 template <class V1, int SIZE, class D1, class D2> 00070 inline 00071 typename TinyVectorBase<V1, SIZE, D1, D2>::SquaredNormType 00072 squaredNorm(TinyVectorBase<V1, SIZE, D1, D2> const & t); 00073 00074 00075 namespace detail { 00076 00077 #define VIGRA_EXEC_LOOP(NAME, OPER) \ 00078 template <class T1, class T2> \ 00079 static void NAME(T1 * left, T2 const * right) \ 00080 { \ 00081 for(int i=0; i<LEVEL; ++i) \ 00082 (left[i]) OPER (right[i]); \ 00083 } 00084 00085 #define VIGRA_EXEC_LOOP_SCALAR(NAME, OPER) \ 00086 template <class T1, class T2> \ 00087 static void NAME(T1 * left, T2 right) \ 00088 { \ 00089 for(int i=0; i<LEVEL; ++i) \ 00090 (left[i]) = detail::RequiresExplicitCast<T1>::cast((left[i]) OPER (right)); \ 00091 } 00092 00093 template <int LEVEL> 00094 struct ExecLoop 00095 { 00096 template <class T1, class T2> 00097 static void assignCast(T1 * left, T2 const * right) 00098 { 00099 for(int i=0; i<LEVEL; ++i) 00100 left[i] = detail::RequiresExplicitCast<T1>::cast(right[i]); 00101 } 00102 00103 template <class T1, class T2> 00104 static void reverseAssign(T1 * left, T2 const * right) 00105 { 00106 for(int i=0; i<LEVEL; ++i) 00107 left[i] = right[-i]; 00108 } 00109 00110 template <class T1, class T2> 00111 static void assignScalar(T1 * left, T2 right) 00112 { 00113 for(int i=0; i<LEVEL; ++i) 00114 left[i] = detail::RequiresExplicitCast<T1>::cast(right); 00115 } 00116 00117 VIGRA_EXEC_LOOP(assign, =) 00118 VIGRA_EXEC_LOOP(add, +=) 00119 VIGRA_EXEC_LOOP(sub, -=) 00120 VIGRA_EXEC_LOOP(mul, *=) 00121 VIGRA_EXEC_LOOP(div, /=) 00122 VIGRA_EXEC_LOOP(neg, = -) 00123 VIGRA_EXEC_LOOP(abs, = vigra::abs) 00124 VIGRA_EXEC_LOOP(floor, = vigra::floor) 00125 VIGRA_EXEC_LOOP(ceil, = vigra::ceil) 00126 VIGRA_EXEC_LOOP(fromPromote, = NumericTraits<T1>::fromPromote) 00127 VIGRA_EXEC_LOOP(fromRealPromote, = NumericTraits<T1>::fromRealPromote) 00128 VIGRA_EXEC_LOOP_SCALAR(mulScalar, *) 00129 VIGRA_EXEC_LOOP_SCALAR(divScalar, /) 00130 00131 template <class T1, class T2> 00132 static bool notEqual(T1 const * left, T2 const * right) 00133 { 00134 for(int i=0; i<LEVEL; ++i) 00135 if(left[i] != right[i]) 00136 return true; 00137 return false; 00138 } 00139 00140 template <class T> 00141 static typename NumericTraits<T>::Promote 00142 dot(T const * d) 00143 { 00144 typename NumericTraits<T>::Promote res(*d * *d); 00145 for(int i=1; i<LEVEL; ++i) 00146 res += d[i] * d[i]; 00147 return res; 00148 } 00149 00150 template <class T1, class T2> 00151 static typename PromoteTraits<T1, T2>::Promote 00152 dot(T1 const * left, T2 const * right) 00153 { 00154 typename PromoteTraits<T1, T2>::Promote res(*left * *right); 00155 for(int i=1; i<LEVEL; ++i) 00156 res += left[i] * right[i]; 00157 return res; 00158 } 00159 00160 template <class T> 00161 static typename NormTraits<T>::SquaredNormType 00162 squaredNorm(T const * d) 00163 { 00164 typename NormTraits<T>::SquaredNormType res = vigra::squaredNorm(*d); 00165 for(int i=1; i<LEVEL; ++i) 00166 res += vigra::squaredNorm(d[i]); 00167 return res; 00168 } 00169 }; 00170 00171 template <int LEVEL> 00172 struct UnrollDot 00173 { 00174 template <class T> 00175 static typename NumericTraits<T>::Promote 00176 dot(T const * d) 00177 { 00178 return *d * *d + UnrollDot<LEVEL-1>::dot(d+1); 00179 } 00180 00181 template <class T1, class T2> 00182 static typename PromoteTraits<T1, T2>::Promote 00183 dot(T1 const * left, T2 const * right) 00184 { 00185 return *left * *right + UnrollDot<LEVEL-1>::dot(left+1, right+1); 00186 } 00187 }; 00188 00189 template <> 00190 struct UnrollDot<1> 00191 { 00192 template <class T> 00193 static typename NumericTraits<T>::Promote 00194 dot(T const * d) 00195 { 00196 return *d * *d ; 00197 } 00198 00199 template <class T1, class T2> 00200 static typename PromoteTraits<T1, T2>::Promote 00201 dot(T1 const * left, T2 const * right) 00202 { 00203 return *left * *right; 00204 } 00205 }; 00206 00207 template <int LEVEL> 00208 struct UnrollSquaredNorm 00209 { 00210 template <class T> 00211 static typename NormTraits<T>::SquaredNormType 00212 squaredNorm(T const * d) 00213 { 00214 return vigra::squaredNorm(*d) + UnrollSquaredNorm<LEVEL-1>::squaredNorm(d+1); 00215 } 00216 00217 static std::ptrdiff_t 00218 squaredNorm(std::ptrdiff_t const * d) 00219 { 00220 return (*d)*(*d) + UnrollSquaredNorm<LEVEL-1>::squaredNorm(d+1); 00221 } 00222 }; 00223 00224 template <> 00225 struct UnrollSquaredNorm<1> 00226 { 00227 template <class T> 00228 static typename NormTraits<T>::SquaredNormType 00229 squaredNorm(T const * d) 00230 { 00231 return vigra::squaredNorm(*d); 00232 } 00233 00234 static std::ptrdiff_t 00235 squaredNorm(std::ptrdiff_t const * d) 00236 { 00237 return (*d)*(*d); 00238 } 00239 }; 00240 00241 #undef VIGRA_EXEC_LOOP 00242 #undef VIGRA_EXEC_LOOP_SCALAR 00243 00244 #define VIGRA_UNROLL_LOOP(NAME, OPER) \ 00245 template <class T1, class T2> \ 00246 static void NAME(T1 * left, T2 const * right) \ 00247 { \ 00248 (*left) OPER (*right); \ 00249 UnrollLoop<LEVEL-1>::NAME(left+1, right+1); \ 00250 } 00251 00252 #define VIGRA_UNROLL_LOOP_SCALAR(NAME, OPER) \ 00253 template <class T1, class T2> \ 00254 static void NAME(T1 * left, T2 right) \ 00255 { \ 00256 (*left) = detail::RequiresExplicitCast<T1>::cast((*left) OPER (right)); \ 00257 UnrollLoop<LEVEL-1>::NAME(left+1, right); \ 00258 } 00259 00260 00261 template <int LEVEL> 00262 struct UnrollLoop 00263 { 00264 template <class T1, class T2> 00265 static void reverseAssign(T1 * left, T2 const * right) 00266 { 00267 *left = *right; 00268 UnrollLoop<LEVEL-1>::reverseAssign(left+1, right-1); 00269 } 00270 00271 template <class T1, class T2> 00272 static void assignCast(T1 * left, T2 const * right) 00273 { 00274 *left = detail::RequiresExplicitCast<T1>::cast(*right); 00275 UnrollLoop<LEVEL-1>::assignCast(left+1, right+1); 00276 } 00277 00278 template <class T1, class T2> 00279 static void assignScalar(T1 * left, T2 right) 00280 { 00281 *left = detail::RequiresExplicitCast<T1>::cast(right); 00282 UnrollLoop<LEVEL-1>::assignScalar(left+1, right); 00283 } 00284 00285 VIGRA_UNROLL_LOOP(assign, =) 00286 VIGRA_UNROLL_LOOP(add, +=) 00287 VIGRA_UNROLL_LOOP(sub, -=) 00288 VIGRA_UNROLL_LOOP(mul, *=) 00289 VIGRA_UNROLL_LOOP(div, /=) 00290 VIGRA_UNROLL_LOOP(neg, = -) 00291 VIGRA_UNROLL_LOOP(abs, = vigra::abs) 00292 VIGRA_UNROLL_LOOP(floor, = vigra::floor) 00293 VIGRA_UNROLL_LOOP(ceil, = vigra::ceil) 00294 VIGRA_UNROLL_LOOP(fromPromote, = NumericTraits<T1>::fromPromote) 00295 VIGRA_UNROLL_LOOP(fromRealPromote, = NumericTraits<T1>::fromRealPromote) 00296 VIGRA_UNROLL_LOOP_SCALAR(mulScalar, *) 00297 VIGRA_UNROLL_LOOP_SCALAR(divScalar, /) 00298 00299 template <class T1, class T2> 00300 static bool notEqual(T1 const * left, T2 const * right) 00301 { 00302 return (*left != *right) || UnrollLoop<LEVEL - 1>::notEqual(left+1, right+1); 00303 } 00304 00305 template <class T> 00306 static typename NumericTraits<T>::Promote 00307 dot(T const * d) 00308 { 00309 return UnrollDot<LEVEL>::dot(d); 00310 } 00311 00312 template <class T1, class T2> 00313 static typename PromoteTraits<T1, T2>::Promote 00314 dot(T1 const * left, T2 const * right) 00315 { 00316 return UnrollDot<LEVEL>::dot(left, right); 00317 } 00318 00319 template <class T> 00320 static typename NormTraits<T>::SquaredNormType 00321 squaredNorm(T const * d) 00322 { 00323 return UnrollSquaredNorm<LEVEL>::squaredNorm(d); 00324 } 00325 }; 00326 00327 #undef VIGRA_UNROLL_LOOP 00328 #undef VIGRA_UNROLL_LOOP_SCALAR 00329 00330 template <> 00331 struct UnrollLoop<0> 00332 { 00333 template <class T1, class T2> 00334 static void reverseAssign(T1, T2) {} 00335 template <class T1, class T2> 00336 static void assignCast(T1, T2) {} 00337 template <class T1, class T2> 00338 static void assign(T1, T2) {} 00339 template <class T1, class T2> 00340 static void assignScalar(T1, T2) {} 00341 template <class T1, class T2> 00342 static void add(T1, T2) {} 00343 template <class T1, class T2> 00344 static void sub(T1, T2) {} 00345 template <class T1, class T2> 00346 static void mul(T1, T2) {} 00347 template <class T1, class T2> 00348 static void mulScalar(T1, T2) {} 00349 template <class T1, class T2> 00350 static void div(T1, T2) {} 00351 template <class T1, class T2> 00352 static void divScalar(T1, T2) {} 00353 template <class T1, class T2> 00354 static void fromPromote(T1, T2) {} 00355 template <class T1, class T2> 00356 static void fromRealPromote(T1, T2) {} 00357 template <class T1, class T2> 00358 static void neg(T1, T2) {} 00359 template <class T1, class T2> 00360 static void abs(T1, T2) {} 00361 template <class T1, class T2> 00362 static void floor(T1, T2) {} 00363 template <class T1, class T2> 00364 static void ceil(T1, T2) {} 00365 template <class T1, class T2> 00366 static bool notEqual(T1, T2) { return false; } 00367 }; 00368 00369 template <int SIZE> 00370 struct LoopType 00371 { 00372 typedef typename IfBool<(SIZE < 5), UnrollLoop<SIZE>, ExecLoop<SIZE> >::type type; 00373 00374 }; 00375 00376 struct DontInit {}; 00377 00378 inline DontInit dontInit() {return DontInit(); } 00379 00380 } // namespace detail 00381 00382 template <class T, int SIZE> 00383 class TinyVector; 00384 00385 template <class T, int SIZE> 00386 class TinyVectorView; 00387 00388 /********************************************************/ 00389 /* */ 00390 /* TinyVectorBase */ 00391 /* */ 00392 /********************************************************/ 00393 00394 /** \brief Base class for fixed size vectors. 00395 00396 This class contains functionality shared by 00397 \ref TinyVector and \ref TinyVectorView, and enables these classes 00398 to be freely mixed within expressions. It is typically not used directly. 00399 00400 <b>\#include</b> <vigra/tinyvector.hxx><br> 00401 Namespace: vigra 00402 **/ 00403 template <class VALUETYPE, int SIZE, class DATA, class DERIVED> 00404 class TinyVectorBase 00405 { 00406 TinyVectorBase(TinyVectorBase const &); // do not use 00407 00408 TinyVectorBase & operator=(TinyVectorBase const & other); // do not use 00409 00410 protected: 00411 00412 typedef typename detail::LoopType<SIZE>::type Loop; 00413 00414 TinyVectorBase() 00415 {} 00416 00417 public: 00418 /** STL-compatible definition of valuetype 00419 */ 00420 typedef VALUETYPE value_type; 00421 00422 /** reference (return of operator[]). 00423 */ 00424 typedef VALUETYPE & reference; 00425 00426 /** const reference (return of operator[] const). 00427 */ 00428 typedef VALUETYPE const & const_reference; 00429 00430 /** pointer (return of operator->). 00431 */ 00432 typedef VALUETYPE * pointer; 00433 00434 /** const pointer (return of operator-> const). 00435 */ 00436 typedef VALUETYPE const * const_pointer; 00437 00438 /** STL-compatible definition of iterator 00439 */ 00440 typedef value_type * iterator; 00441 00442 /** STL-compatible definition of const iterator 00443 */ 00444 typedef value_type const * const_iterator; 00445 00446 /** STL-compatible definition of size_type 00447 */ 00448 typedef unsigned int size_type; 00449 00450 /** STL-compatible definition of difference_type 00451 */ 00452 typedef int difference_type; 00453 00454 /** the scalar type for the outer product 00455 */ 00456 typedef double scalar_multiplier; 00457 00458 /** the vector's squared norm type 00459 */ 00460 typedef typename NormTraits<VALUETYPE>::SquaredNormType SquaredNormType; 00461 00462 /** the vector's norm type 00463 */ 00464 typedef typename SquareRootTraits<SquaredNormType>::SquareRootResult NormType; 00465 00466 /** the vector's size 00467 */ 00468 enum { static_size = SIZE }; 00469 00470 /** Initialize from another sequence (must have length SIZE!) 00471 */ 00472 template <class Iterator> 00473 void init(Iterator i, Iterator end) 00474 { 00475 vigra_precondition(end-i == SIZE, 00476 "TinyVector::init(): Sequence has wrong size."); 00477 Loop::assignCast(data_, i); 00478 } 00479 00480 /** Initialize with constant value 00481 */ 00482 void init(value_type initial) 00483 { 00484 Loop::assignScalar(data_, initial); 00485 } 00486 00487 /** Component-wise add-assignment 00488 */ 00489 template <class T1, class D1, class D2> 00490 DERIVED & operator+=(TinyVectorBase<T1, SIZE, D1, D2> const & r) 00491 { 00492 Loop::add(data_, r.begin()); 00493 return static_cast<DERIVED &>(*this); 00494 } 00495 00496 /** Component-wise subtract-assignment 00497 */ 00498 template <class T1, class D1, class D2> 00499 DERIVED & operator-=(TinyVectorBase<T1, SIZE, D1, D2> const & r) 00500 { 00501 Loop::sub(data_, r.begin()); 00502 return static_cast<DERIVED &>(*this); 00503 } 00504 00505 /** Component-wise multiply-assignment 00506 */ 00507 template <class T1, class D1, class D2> 00508 DERIVED & operator*=(TinyVectorBase<T1, SIZE, D1, D2> const & r) 00509 { 00510 Loop::mul(data_, r.begin()); 00511 return static_cast<DERIVED &>(*this); 00512 } 00513 00514 /** Component-wise divide-assignment 00515 */ 00516 template <class T1, class D1, class D2> 00517 DERIVED & operator/=(TinyVectorBase<T1, SIZE, D1, D2> const & r) 00518 { 00519 Loop::div(data_, r.begin()); 00520 return static_cast<DERIVED &>(*this); 00521 } 00522 00523 /** Component-wise scalar multiply-assignment 00524 */ 00525 DERIVED & operator*=(double r) 00526 { 00527 Loop::mulScalar(data_, r); 00528 return static_cast<DERIVED &>(*this); 00529 } 00530 00531 /** Component-wise scalar divide-assignment 00532 */ 00533 DERIVED & operator/=(double r) 00534 { 00535 Loop::divScalar(data_, r); 00536 return static_cast<DERIVED &>(*this); 00537 } 00538 00539 /** Calculate magnitude. 00540 */ 00541 NormType magnitude() const 00542 { 00543 return sqrt(static_cast<typename 00544 SquareRootTraits<SquaredNormType>::SquareRootArgument>(squaredMagnitude())); 00545 } 00546 00547 /** Calculate squared magnitude. 00548 */ 00549 SquaredNormType squaredMagnitude() const 00550 { 00551 return Loop::squaredNorm(data_); 00552 } 00553 00554 /** Access component by index. 00555 */ 00556 reference operator[](difference_type i) 00557 { 00558 VIGRA_ASSERT_INSIDE(i); 00559 return data_[i]; 00560 } 00561 00562 /** Get component by index. 00563 */ 00564 const_reference operator[](difference_type i) const 00565 { 00566 VIGRA_ASSERT_INSIDE(i); 00567 return data_[i]; 00568 } 00569 00570 /** Get random access iterator to begin of vector. 00571 */ 00572 iterator begin() { return data_; } 00573 /** Get random access iterator past-the-end of vector. 00574 */ 00575 iterator end() { return data_ + SIZE; } 00576 00577 /** Get const random access iterator to begin of vector. 00578 */ 00579 const_iterator begin() const { return data_; } 00580 00581 /** Get const random access iterator past-the-end of vector. 00582 */ 00583 const_iterator end() const { return data_ + SIZE; } 00584 00585 /** Size of TinyVector vector always equals the template parameter SIZE. 00586 */ 00587 size_type size() const { return SIZE; } 00588 00589 pointer data() { return data_; } 00590 00591 const_pointer data() const { return data_; } 00592 00593 protected: 00594 00595 DATA data_; 00596 }; 00597 00598 /** \brief Class for fixed size vectors. 00599 \ingroup RangesAndPoints 00600 00601 This class contains an array of size SIZE of the specified VALUETYPE. 00602 The interface conforms to STL vector, except that there are no functions 00603 that change the size of a TinyVector. 00604 00605 \ref TinyVectorOperators "Arithmetic operations" 00606 on TinyVectors are defined as component-wise applications of these 00607 operations. Addition and subtraction of two TinyVectors 00608 (+=, -=, +, -, unary -), multiplication and division of an 00609 TinyVector with a double, and NumericTraits/PromoteTraits are defined, 00610 so that TinyVector fulfills the requirements of \ref LinearAlgebraConcept "Linear Algebra". 00611 00612 VIGRA algorithms typically use \ref vigra::VectorAccessor to access 00613 TinyVectors as a whole, or specific components of them. 00614 00615 See also:<br> 00616 <UL style="list-style-image:url(documents/bullet.gif)"> 00617 <LI> \ref vigra::TinyVectorBase 00618 <LI> \ref vigra::TinyVectorView 00619 <LI> \ref TinyVectorTraits 00620 <LI> \ref TinyVectorOperators 00621 </UL> 00622 00623 <b>\#include</b> <vigra/tinyvector.hxx><br> 00624 Namespace: vigra 00625 **/ 00626 template <class T, int SIZE> 00627 class TinyVector 00628 : public TinyVectorBase<T, SIZE, T[SIZE], TinyVector<T, SIZE> > 00629 { 00630 typedef TinyVectorBase<T, SIZE, T[SIZE], TinyVector<T, SIZE> > BaseType; 00631 typedef typename BaseType::Loop Loop; 00632 00633 public: 00634 00635 typedef typename BaseType::value_type value_type; 00636 typedef typename BaseType::reference reference; 00637 typedef typename BaseType::const_reference const_reference; 00638 typedef typename BaseType::pointer pointer; 00639 typedef typename BaseType::const_pointer const_pointer; 00640 typedef typename BaseType::iterator iterator; 00641 typedef typename BaseType::const_iterator const_iterator; 00642 typedef typename BaseType::size_type size_type; 00643 typedef typename BaseType::difference_type difference_type; 00644 typedef typename BaseType::scalar_multiplier scalar_multiplier; 00645 typedef typename BaseType::SquaredNormType SquaredNormType; 00646 typedef typename BaseType::NormType NormType; 00647 00648 enum ReverseCopyTag { ReverseCopy }; 00649 00650 /** Construction with constant value 00651 */ 00652 explicit TinyVector(value_type const & initial) 00653 : BaseType() 00654 { 00655 Loop::assignScalar(BaseType::begin(), initial); 00656 } 00657 00658 /** Construction with Diff2D (only implemented for 2D TinyVector) 00659 */ 00660 explicit TinyVector(Diff2D const & initial) 00661 : BaseType() 00662 { 00663 BaseType::data_[0] = detail::RequiresExplicitCast<T>::cast(initial.x); 00664 BaseType::data_[1] = detail::RequiresExplicitCast<T>::cast(initial.y); 00665 } 00666 00667 /** Construction with explicit values. 00668 Call only if SIZE == 2 00669 */ 00670 TinyVector(value_type const & i1, value_type const & i2) 00671 : BaseType() 00672 { 00673 BaseType::data_[0] = i1; 00674 BaseType::data_[1] = i2; 00675 } 00676 00677 /** Construction with explicit values. 00678 Call only if SIZE == 3 00679 */ 00680 TinyVector(value_type const & i1, value_type const & i2, value_type const & i3) 00681 : BaseType() 00682 { 00683 BaseType::data_[0] = i1; 00684 BaseType::data_[1] = i2; 00685 BaseType::data_[2] = i3; 00686 } 00687 00688 /** Construction with explicit values. 00689 Call only if SIZE == 4 00690 */ 00691 TinyVector(value_type const & i1, value_type const & i2, 00692 value_type const & i3, value_type const & i4) 00693 : BaseType() 00694 { 00695 BaseType::data_[0] = i1; 00696 BaseType::data_[1] = i2; 00697 BaseType::data_[2] = i3; 00698 BaseType::data_[3] = i4; 00699 } 00700 00701 /** Construction with explicit values. 00702 Call only if SIZE == 5 00703 */ 00704 TinyVector(value_type const & i1, value_type const & i2, 00705 value_type const & i3, value_type const & i4, 00706 value_type const & i5) 00707 : BaseType() 00708 { 00709 BaseType::data_[0] = i1; 00710 BaseType::data_[1] = i2; 00711 BaseType::data_[2] = i3; 00712 BaseType::data_[3] = i4; 00713 BaseType::data_[4] = i5; 00714 } 00715 /** Default constructor (initializes all components with zero) 00716 */ 00717 TinyVector() 00718 : BaseType() 00719 { 00720 Loop::assignScalar(BaseType::data_, NumericTraits<value_type>::zero()); 00721 } 00722 00723 /** Copy constructor. 00724 */ 00725 TinyVector(TinyVector const & r) 00726 : BaseType() 00727 { 00728 Loop::assign(BaseType::data_, r.data_); 00729 } 00730 00731 /** Constructor from C array. 00732 */ 00733 explicit TinyVector(const_pointer data) 00734 : BaseType() 00735 { 00736 Loop::assign(BaseType::data_, data); 00737 } 00738 00739 /** Constructor by reverse copy from C array. 00740 00741 Usage: 00742 \code 00743 TinyVector<int, 3> v(1,2,3); 00744 TinyVector<int, 3> reverse(v.begin(), TinyVector<int, 3>::ReverseCopy); 00745 \endcode 00746 */ 00747 explicit TinyVector(const_pointer data, ReverseCopyTag) 00748 : BaseType() 00749 { 00750 Loop::reverseAssign(BaseType::data_, data+SIZE-1); 00751 } 00752 00753 /** Copy assignment. 00754 */ 00755 TinyVector & operator=(TinyVector const & r) 00756 { 00757 Loop::assign(BaseType::data_, r.data_); 00758 return *this; 00759 } 00760 00761 /** Assignment from Diff2D. 00762 */ 00763 TinyVector & operator=(Diff2D const & r) 00764 { 00765 BaseType::data_[0] = detail::RequiresExplicitCast<T>::cast(r.x); 00766 BaseType::data_[1] = detail::RequiresExplicitCast<T>::cast(r.y); 00767 return *this; 00768 } 00769 00770 /** Copy with type conversion. 00771 */ 00772 template <class U> 00773 TinyVector(TinyVector<U, SIZE> const & r) 00774 : BaseType() 00775 { 00776 Loop::assignCast(BaseType::data_, r.begin()); 00777 } 00778 00779 /** Copy with type conversion. 00780 */ 00781 template <class U, class DATA, class DERIVED> 00782 TinyVector(TinyVectorBase<U, SIZE, DATA, DERIVED> const & r) 00783 : BaseType() 00784 { 00785 Loop::assignCast(BaseType::data_, r.begin()); 00786 } 00787 00788 /** Copy assignment with type conversion. 00789 */ 00790 template <class U, class DATA, class DERIVED> 00791 TinyVector & operator=(TinyVectorBase<U, SIZE, DATA, DERIVED> const & r) 00792 { 00793 Loop::assignCast(BaseType::data_, r.begin()); 00794 return *this; 00795 } 00796 00797 explicit TinyVector(SkipInitializationTag) 00798 : BaseType() 00799 {} 00800 00801 explicit TinyVector(detail::DontInit) 00802 : BaseType() 00803 {} 00804 }; 00805 00806 /** \brief Wrapper for fixed size vectors. 00807 00808 This class wraps an array of size SIZE of the specified VALUETYPE. 00809 Thus, the array can be accessed with an interface similar to 00810 that of std::vector (except that there are no functions 00811 that change the size of a TinyVectorView). The TinyVectorView 00812 does <em>not</em> assume ownership of the given memory. 00813 00814 \ref TinyVectorOperators "Arithmetic operations" 00815 on TinyVectorViews are defined as component-wise applications of these 00816 operations. Addition and subtraction of two TinyVectorViews 00817 (+=, -=, +, -, unary -), multiplication and division of an 00818 TinyVectorViews with a double, and NumericTraits/PromoteTraits are defined, 00819 so that TinyVectorView fulfills the requirements of \ref LinearAlgebraConcept "Linear Algebra". 00820 00821 VIGRA algorithms typically use \ref vigra::VectorAccessor to access 00822 TinyVectorViews as a whole, or specific components of them. 00823 00824 <b>See also:</b> 00825 <ul> 00826 <li> \ref vigra::TinyVectorBase 00827 <li> \ref vigra::TinyVector 00828 <li> \ref TinyVectorTraits 00829 <li> \ref TinyVectorOperators 00830 </ul> 00831 00832 <b>\#include</b> <vigra/tinyvector.hxx><br> 00833 Namespace: vigra 00834 **/ 00835 template <class T, int SIZE> 00836 class TinyVectorView 00837 : public TinyVectorBase<T, SIZE, T *, TinyVectorView<T, SIZE> > 00838 { 00839 typedef TinyVectorBase<T, SIZE, T *, TinyVectorView<T, SIZE> > BaseType; 00840 typedef typename BaseType::Loop Loop; 00841 00842 public: 00843 00844 typedef typename BaseType::value_type value_type; 00845 typedef typename BaseType::reference reference; 00846 typedef typename BaseType::const_reference const_reference; 00847 typedef typename BaseType::pointer pointer; 00848 typedef typename BaseType::const_pointer const_pointer; 00849 typedef typename BaseType::iterator iterator; 00850 typedef typename BaseType::const_iterator const_iterator; 00851 typedef typename BaseType::size_type size_type; 00852 typedef typename BaseType::difference_type difference_type; 00853 typedef typename BaseType::scalar_multiplier scalar_multiplier; 00854 typedef typename BaseType::SquaredNormType SquaredNormType; 00855 typedef typename BaseType::NormType NormType; 00856 00857 /** Default constructor 00858 (pointer to wrapped data is NULL). 00859 */ 00860 TinyVectorView() 00861 : BaseType() 00862 { 00863 BaseType::data_ = 0; 00864 } 00865 00866 /** Construct view for given data array 00867 */ 00868 TinyVectorView(const_pointer data) 00869 : BaseType() 00870 { 00871 BaseType::data_ = const_cast<pointer>(data); 00872 } 00873 00874 /** Copy constructor (shallow copy). 00875 */ 00876 TinyVectorView(TinyVectorView const & other) 00877 : BaseType() 00878 { 00879 BaseType::data_ = const_cast<pointer>(other.data_); 00880 } 00881 00882 /** Construct view from other TinyVector. 00883 */ 00884 template <class DATA, class DERIVED> 00885 TinyVectorView(TinyVectorBase<T, SIZE, DATA, DERIVED> const & other) 00886 : BaseType() 00887 { 00888 BaseType::data_ = const_cast<pointer>(other.data()); 00889 } 00890 00891 /** Copy the data (not the pointer) of the rhs. 00892 */ 00893 TinyVectorView & operator=(TinyVectorView const & r) 00894 { 00895 Loop::assign(BaseType::data_, r.begin()); 00896 return *this; 00897 } 00898 00899 /** Copy the data of the rhs with cast. 00900 */ 00901 template <class U, class DATA, class DERIVED> 00902 TinyVectorView & operator=(TinyVectorBase<U, SIZE, DATA, DERIVED> const & r) 00903 { 00904 Loop::assignCast(BaseType::data_, r.begin()); 00905 return *this; 00906 } 00907 }; 00908 00909 /********************************************************/ 00910 /* */ 00911 /* TinyVector Comparison */ 00912 /* */ 00913 /********************************************************/ 00914 00915 /** \addtogroup TinyVectorOperators Functions for TinyVector 00916 00917 \brief Implement basic arithmetic and equality for TinyVector. 00918 00919 These functions fulfill the requirements of a Linear Space (vector space). 00920 Return types are determined according to \ref TinyVectorTraits. 00921 00922 <b>\#include</b> <vigra/tinyvector.hxx><br> 00923 Namespace: vigra 00924 */ 00925 //@{ 00926 /// component-wise equal 00927 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4> 00928 inline bool 00929 operator==(TinyVectorBase<V1, SIZE, D1, D2> const & l, 00930 TinyVectorBase<V2, SIZE, D3, D4> const & r) 00931 { 00932 return !(l != r); 00933 } 00934 00935 /// component-wise not equal 00936 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4> 00937 inline bool 00938 operator!=(TinyVectorBase<V1, SIZE, D1, D2> const & l, 00939 TinyVectorBase<V2, SIZE, D3, D4> const & r) 00940 { 00941 typedef typename detail::LoopType<SIZE>::type ltype; 00942 return ltype::notEqual(l.begin(), r.begin()); 00943 } 00944 00945 /********************************************************/ 00946 /* */ 00947 /* TinyVector Output */ 00948 /* */ 00949 /********************************************************/ 00950 00951 /// stream output 00952 template <class V1, int SIZE, class DATA, class DERIVED> 00953 std::ostream & 00954 operator<<(std::ostream & out, TinyVectorBase<V1, SIZE, DATA, DERIVED> const & l) 00955 { 00956 out << "("; 00957 int i; 00958 for(i=0; i<SIZE-1; ++i) 00959 out << l[i] << ", "; 00960 out << l[i] << ")"; 00961 return out; 00962 } 00963 //@} 00964 00965 /********************************************************/ 00966 /* */ 00967 /* TinyVector-Traits */ 00968 /* */ 00969 /********************************************************/ 00970 00971 /** \page TinyVectorTraits Numeric and Promote Traits of TinyVector 00972 The numeric and promote traits for TinyVectors follow 00973 the general specifications for \ref NumericPromotionTraits. 00974 They are implemented in terms of the traits of the basic types by 00975 partial template specialization: 00976 00977 \code 00978 00979 template <class T, int SIZE> 00980 struct NumericTraits<TinyVector<T, SIZE> > 00981 { 00982 typedef TinyVector<typename NumericTraits<T>::Promote, SIZE> Promote; 00983 typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> RealPromote; 00984 00985 typedef typename NumericTraits<T>::isIntegral isIntegral; 00986 typedef VigraFalseType isScalar; 00987 typedef typename NumericTraits<T>::isSigned isSigned; 00988 00989 // etc. 00990 }; 00991 00992 template <class T, int SIZE> 00993 struct NormTraits<TinyVector<T, SIZE> > 00994 { 00995 typedef TinyVector<T, SIZE> Type; 00996 typedef typename Type::SquaredNormType SquaredNormType; 00997 typedef typename Type::NormType NormType; 00998 }; 00999 01000 template <class T1, class T2, SIZE> 01001 struct PromoteTraits<TinyVector<T1, SIZE>, TinyVector<T2, SIZE> > 01002 { 01003 typedef TinyVector<typename PromoteTraits<T1, T2>::Promote, SIZE> Promote; 01004 }; 01005 \endcode 01006 01007 <b>\#include</b> <vigra/tinyvector.hxx><br> 01008 Namespace: vigra 01009 01010 On compilers that don't support partial template specialization (e.g. 01011 MS VisualC++), the traits classes are explicitly specialized for 01012 <TT>TinyVector<VALUETYPE, SIZE></TT> with 01013 <TT>VALUETYPE = unsigned char | int | float | double</TT> and <TT>SIZE = 2 | 3 | 4</TT>. 01014 01015 */ 01016 01017 #if !defined(NO_PARTIAL_TEMPLATE_SPECIALIZATION) 01018 01019 template <class T, int SIZE> 01020 struct NumericTraits<TinyVector<T, SIZE> > 01021 { 01022 typedef TinyVector<T, SIZE> Type; 01023 typedef TinyVector<typename NumericTraits<T>::Promote, SIZE> Promote; 01024 typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> RealPromote; 01025 typedef TinyVector<typename NumericTraits<T>::ComplexPromote, SIZE> ComplexPromote; 01026 typedef T ValueType; 01027 01028 typedef typename NumericTraits<T>::isIntegral isIntegral; 01029 typedef VigraFalseType isScalar; 01030 typedef typename NumericTraits<T>::isSigned isSigned; 01031 typedef VigraFalseType isOrdered; 01032 typedef VigraFalseType isComplex; 01033 01034 static TinyVector<T, SIZE> zero() { 01035 return TinyVector<T, SIZE>(NumericTraits<T>::zero()); 01036 } 01037 static TinyVector<T, SIZE> one() { 01038 return TinyVector<T, SIZE>(NumericTraits<T>::one()); 01039 } 01040 static TinyVector<T, SIZE> nonZero() { 01041 return TinyVector<T, SIZE>(NumericTraits<T>::nonZero()); 01042 } 01043 01044 template <class D1, class D2> 01045 static Promote toPromote(TinyVectorBase<T, SIZE, D1, D2> const & v) 01046 { 01047 return Promote(v); 01048 } 01049 01050 template <class D1, class D2> 01051 static RealPromote toRealPromote(TinyVectorBase<T, SIZE, D1, D2> const & v) 01052 { 01053 return RealPromote(v); 01054 } 01055 01056 template <class D1, class D2> 01057 static TinyVector<T, SIZE> 01058 fromPromote(TinyVectorBase<typename NumericTraits<T>::Promote, SIZE, D1, D2> const & v) 01059 { 01060 TinyVector<T, SIZE> res(detail::dontInit()); 01061 typedef typename detail::LoopType<SIZE>::type ltype; 01062 ltype::fromPromote(res.begin(), v.begin()); 01063 return res; 01064 } 01065 01066 template <class D1, class D2> 01067 static TinyVector<T, SIZE> 01068 fromRealPromote(TinyVectorBase<typename NumericTraits<T>::RealPromote, SIZE, D1, D2> const & v) 01069 { 01070 TinyVector<T, SIZE> res(detail::dontInit()); 01071 typedef typename detail::LoopType<SIZE>::type ltype; 01072 ltype::fromRealPromote(res.begin(), v.begin()); 01073 return res; 01074 } 01075 }; 01076 01077 template <class T, int SIZE> 01078 struct NumericTraits<TinyVectorView<T, SIZE> > 01079 : public NumericTraits<TinyVector<T, SIZE> > 01080 { 01081 typedef TinyVector<T, SIZE> Type; 01082 typedef TinyVector<typename NumericTraits<T>::Promote, SIZE> Promote; 01083 typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> RealPromote; 01084 typedef TinyVector<typename NumericTraits<T>::ComplexPromote, SIZE> ComplexPromote; 01085 typedef T ValueType; 01086 01087 typedef typename NumericTraits<T>::isIntegral isIntegral; 01088 typedef VigraFalseType isScalar; 01089 typedef typename NumericTraits<T>::isSigned isSigned; 01090 typedef VigraFalseType isOrdered; 01091 typedef VigraFalseType isComplex; 01092 }; 01093 01094 template <class T, int SIZE> 01095 struct NormTraits<TinyVector<T, SIZE> > 01096 { 01097 typedef TinyVector<T, SIZE> Type; 01098 typedef typename Type::SquaredNormType SquaredNormType; 01099 typedef typename Type::NormType NormType; 01100 }; 01101 01102 template <class T, int SIZE> 01103 struct NormTraits<TinyVectorView<T, SIZE> > 01104 { 01105 typedef TinyVector<T, SIZE> Type; 01106 typedef typename Type::SquaredNormType SquaredNormType; 01107 typedef typename Type::NormType NormType; 01108 }; 01109 01110 template <class T1, class T2, int SIZE> 01111 struct PromoteTraits<TinyVector<T1, SIZE>, TinyVector<T2, SIZE> > 01112 { 01113 typedef TinyVector<typename PromoteTraits<T1, T2>::Promote, SIZE> Promote; 01114 }; 01115 01116 template <class T1, class T2, int SIZE> 01117 struct PromoteTraits<TinyVectorView<T1, SIZE>, TinyVectorView<T2, SIZE> > 01118 { 01119 typedef TinyVector<typename PromoteTraits<T1, T2>::Promote, SIZE> Promote; 01120 }; 01121 01122 template <class T1, class T2, int SIZE> 01123 struct PromoteTraits<TinyVectorView<T1, SIZE>, TinyVector<T2, SIZE> > 01124 { 01125 typedef TinyVector<typename PromoteTraits<T1, T2>::Promote, SIZE> Promote; 01126 }; 01127 01128 template <class T1, class T2, int SIZE> 01129 struct PromoteTraits<TinyVector<T1, SIZE>, TinyVectorView<T2, SIZE> > 01130 { 01131 typedef TinyVector<typename PromoteTraits<T1, T2>::Promote, SIZE> Promote; 01132 }; 01133 01134 template <class T, int SIZE> 01135 struct PromoteTraits<TinyVector<T, SIZE>, double > 01136 { 01137 typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> Promote; 01138 }; 01139 01140 template <class T, int SIZE> 01141 struct PromoteTraits<double, TinyVector<T, SIZE> > 01142 { 01143 typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> Promote; 01144 }; 01145 01146 template <class T, int SIZE> 01147 struct PromoteTraits<TinyVectorView<T, SIZE>, double > 01148 { 01149 typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> Promote; 01150 }; 01151 01152 template <class T, int SIZE> 01153 struct PromoteTraits<double, TinyVectorView<T, SIZE> > 01154 { 01155 typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> Promote; 01156 }; 01157 01158 template<class T, int SIZE> 01159 struct CanSkipInitialization<TinyVectorView<T, SIZE> > 01160 { 01161 typedef typename CanSkipInitialization<T>::type type; 01162 static const bool value = type::asBool; 01163 }; 01164 01165 template<class T, int SIZE> 01166 struct CanSkipInitialization<TinyVector<T, SIZE> > 01167 { 01168 typedef typename CanSkipInitialization<T>::type type; 01169 static const bool value = type::asBool; 01170 }; 01171 01172 01173 01174 #else // NO_PARTIAL_TEMPLATE_SPECIALIZATION 01175 01176 01177 #define TINYVECTOR_NUMTRAITS(T, SIZE) \ 01178 template<>\ 01179 struct NumericTraits<TinyVector<T, SIZE> >\ 01180 {\ 01181 typedef TinyVector<T, SIZE> Type;\ 01182 typedef TinyVector<NumericTraits<T>::Promote, SIZE> Promote;\ 01183 typedef TinyVector<NumericTraits<T>::RealPromote, SIZE> RealPromote;\ 01184 typedef TinyVector<NumericTraits<T>::ComplexPromote, SIZE> ComplexPromote;\ 01185 typedef T ValueType; \ 01186 typedef NumericTraits<T>::isIntegral isIntegral;\ 01187 typedef VigraFalseType isScalar;\ 01188 typedef NumericTraits<T>::isSigned isSigned; \ 01189 typedef VigraFalseType isOrdered;\ 01190 typedef VigraFalseType isComplex;\ 01191 \ 01192 static TinyVector<T, SIZE> zero() { \ 01193 return TinyVector<T, SIZE>(NumericTraits<T>::zero()); \ 01194 }\ 01195 static TinyVector<T, SIZE> one() { \ 01196 return TinyVector<T, SIZE>(NumericTraits<T>::one()); \ 01197 }\ 01198 static TinyVector<T, SIZE> nonZero() { \ 01199 return TinyVector<T, SIZE>(NumericTraits<T>::nonZero()); \ 01200 }\ 01201 \ 01202 static Promote toPromote(TinyVector<T, SIZE> const & v) { \ 01203 return Promote(v); \ 01204 }\ 01205 static RealPromote toRealPromote(TinyVector<T, SIZE> const & v) { \ 01206 return RealPromote(v); \ 01207 }\ 01208 static TinyVector<T, SIZE> fromPromote(Promote const & v) { \ 01209 TinyVector<T, SIZE> res;\ 01210 TinyVector<T, SIZE>::iterator d = res.begin(), dend = res.end();\ 01211 Promote::const_iterator s = v.begin();\ 01212 for(; d != dend; ++d, ++s)\ 01213 *d = NumericTraits<T>::fromPromote(*s);\ 01214 return res;\ 01215 }\ 01216 static TinyVector<T, SIZE> fromRealPromote(RealPromote const & v) {\ 01217 TinyVector<T, SIZE> res;\ 01218 TinyVector<T, SIZE>::iterator d = res.begin(), dend = res.end();\ 01219 RealPromote::const_iterator s = v.begin();\ 01220 for(; d != dend; ++d, ++s)\ 01221 *d = NumericTraits<T>::fromRealPromote(*s);\ 01222 return res;\ 01223 }\ 01224 }; \ 01225 template<>\ 01226 struct NormTraits<TinyVector<T, SIZE> >\ 01227 {\ 01228 typedef TinyVector<T, SIZE> Type;\ 01229 typedef Type::SquaredNormType SquaredNormType; \ 01230 typedef Type::NormType NormType; \ 01231 }; 01232 01233 #define TINYVECTOR_PROMTRAITS1(type1, SIZE) \ 01234 template<> \ 01235 struct PromoteTraits<TinyVector<type1, SIZE>, TinyVector<type1, SIZE> > \ 01236 { \ 01237 typedef TinyVector<PromoteTraits<type1, type1>::Promote, SIZE> Promote; \ 01238 static Promote toPromote(TinyVector<type1, SIZE> const & v) { \ 01239 return static_cast<Promote>(v); } \ 01240 }; 01241 01242 #define TINYVECTOR_PROMTRAITS2(type1, type2, SIZE) \ 01243 template<> \ 01244 struct PromoteTraits<TinyVector<type1, SIZE>, TinyVector<type2, SIZE> > \ 01245 { \ 01246 typedef TinyVector<PromoteTraits<type1, type2>::Promote, SIZE> Promote; \ 01247 static Promote toPromote(TinyVector<type1, SIZE> const & v) { \ 01248 return static_cast<Promote>(v); } \ 01249 static Promote toPromote(TinyVector<type2, SIZE> const & v) { \ 01250 return static_cast<Promote>(v); } \ 01251 }; 01252 01253 #define TINYVECTOR_TRAITS(SIZE) \ 01254 TINYVECTOR_NUMTRAITS(unsigned char, SIZE)\ 01255 TINYVECTOR_NUMTRAITS(int, SIZE)\ 01256 TINYVECTOR_NUMTRAITS(float, SIZE)\ 01257 TINYVECTOR_NUMTRAITS(double, SIZE)\ 01258 TINYVECTOR_PROMTRAITS1(unsigned char, SIZE)\ 01259 TINYVECTOR_PROMTRAITS1(int, SIZE)\ 01260 TINYVECTOR_PROMTRAITS1(float, SIZE)\ 01261 TINYVECTOR_PROMTRAITS1(double, SIZE)\ 01262 TINYVECTOR_PROMTRAITS2(float, unsigned char, SIZE)\ 01263 TINYVECTOR_PROMTRAITS2(unsigned char, float, SIZE)\ 01264 TINYVECTOR_PROMTRAITS2(int, unsigned char, SIZE)\ 01265 TINYVECTOR_PROMTRAITS2(unsigned char, int, SIZE)\ 01266 TINYVECTOR_PROMTRAITS2(int, float, SIZE)\ 01267 TINYVECTOR_PROMTRAITS2(float, int, SIZE)\ 01268 TINYVECTOR_PROMTRAITS2(double, unsigned char, SIZE)\ 01269 TINYVECTOR_PROMTRAITS2(unsigned char, double, SIZE)\ 01270 TINYVECTOR_PROMTRAITS2(int, double, SIZE)\ 01271 TINYVECTOR_PROMTRAITS2(double, int, SIZE)\ 01272 TINYVECTOR_PROMTRAITS2(double, float, SIZE)\ 01273 TINYVECTOR_PROMTRAITS2(float, double, SIZE) 01274 01275 TINYVECTOR_TRAITS(2) 01276 TINYVECTOR_TRAITS(3) 01277 TINYVECTOR_TRAITS(4) 01278 01279 #undef TINYVECTOR_NUMTRAITS 01280 #undef TINYVECTOR_PROMTRAITS1 01281 #undef TINYVECTOR_PROMTRAITS2 01282 #undef TINYVECTOR_TRAITS 01283 01284 #endif // NO_PARTIAL_TEMPLATE_SPECIALIZATION 01285 01286 01287 /********************************************************/ 01288 /* */ 01289 /* TinyVector-Arithmetic */ 01290 /* */ 01291 /********************************************************/ 01292 01293 /** \addtogroup TinyVectorOperators 01294 */ 01295 //@{ 01296 01297 /// component-wise addition 01298 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4> 01299 inline 01300 typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2, SIZE> >::Promote 01301 operator+(TinyVectorBase<V1, SIZE, D1, D2> const & l, 01302 TinyVectorBase<V2, SIZE, D3, D4> const & r) 01303 { 01304 return typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2 , SIZE> >::Promote(l) += r; 01305 } 01306 01307 /// component-wise subtraction 01308 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4> 01309 inline 01310 typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2, SIZE> >::Promote 01311 operator-(TinyVectorBase<V1, SIZE, D1, D2> const & l, 01312 TinyVectorBase<V2, SIZE, D3, D4> const & r) 01313 { 01314 return typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2 , SIZE> >::Promote(l) -= r; 01315 } 01316 01317 /// component-wise multiplication 01318 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4> 01319 inline 01320 typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2, SIZE> >::Promote 01321 operator*(TinyVectorBase<V1, SIZE, D1, D2> const & l, 01322 TinyVectorBase<V2, SIZE, D3, D4> const & r) 01323 { 01324 return typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2 , SIZE> >::Promote(l) *= r; 01325 } 01326 01327 /// component-wise division 01328 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4> 01329 inline 01330 typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2, SIZE> >::Promote 01331 operator/(TinyVectorBase<V1, SIZE, D1, D2> const & l, 01332 TinyVectorBase<V2, SIZE, D3, D4> const & r) 01333 { 01334 return typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2 , SIZE> >::Promote(l) /= r; 01335 } 01336 01337 /// component-wise left scalar multiplication 01338 template <class V, int SIZE, class D1, class D2> 01339 inline 01340 typename NumericTraits<TinyVector<V, SIZE> >::RealPromote 01341 operator*(double v, TinyVectorBase<V, SIZE, D1, D2> const & r) 01342 { 01343 return typename NumericTraits<TinyVector<V, SIZE> >::RealPromote(r) *= v; 01344 } 01345 01346 /// component-wise right scalar multiplication 01347 template <class V, int SIZE, class D1, class D2> 01348 inline 01349 typename NumericTraits<TinyVector<V, SIZE> >::RealPromote 01350 operator*(TinyVectorBase<V, SIZE, D1, D2> const & l, double v) 01351 { 01352 return typename NumericTraits<TinyVector<V, SIZE> >::RealPromote(l) *= v; 01353 } 01354 01355 /// component-wise scalar division 01356 template <class V, int SIZE, class D1, class D2> 01357 inline 01358 typename NumericTraits<TinyVector<V, SIZE> >::RealPromote 01359 operator/(TinyVectorBase<V, SIZE, D1, D2> const & l, double v) 01360 { 01361 return typename NumericTraits<TinyVector<V, SIZE> >::RealPromote(l) /= v; 01362 } 01363 01364 /// component-wise scalar division without type promotion 01365 template <class V, int SIZE, class D1, class D2> 01366 inline 01367 TinyVector<V, SIZE> 01368 div(TinyVectorBase<V, SIZE, D1, D2> const & l, V v) 01369 { 01370 TinyVector<V, SIZE> result(l); 01371 typedef typename detail::LoopType<SIZE>::type Loop; 01372 Loop::divScalar(result.data(), v); 01373 return result; 01374 } 01375 01376 01377 /** Unary negation (construct TinyVector with negative values) 01378 */ 01379 template <class V, int SIZE, class D1, class D2> 01380 inline 01381 TinyVector<V, SIZE> 01382 operator-(TinyVectorBase<V, SIZE, D1, D2> const & v) 01383 { 01384 TinyVector<V, SIZE> res(detail::dontInit()); 01385 typedef typename detail::LoopType<SIZE>::type ltype; 01386 ltype::neg(res.begin(), v.begin()); 01387 return res; 01388 } 01389 01390 /// component-wise absolute value 01391 template <class V, int SIZE, class D1, class D2> 01392 inline 01393 TinyVector<V, SIZE> 01394 abs(TinyVectorBase<V, SIZE, D1, D2> const & v) 01395 { 01396 TinyVector<V, SIZE> res(detail::dontInit()); 01397 typedef typename detail::LoopType<SIZE>::type ltype; 01398 ltype::abs(res.begin(), v.begin()); 01399 return res; 01400 } 01401 01402 /** Apply ceil() function to each vector component. 01403 */ 01404 template <class V, int SIZE, class D1, class D2> 01405 inline 01406 TinyVector<V, SIZE> 01407 ceil(TinyVectorBase<V, SIZE, D1, D2> const & v) 01408 { 01409 TinyVector<V, SIZE> res(detail::dontInit()); 01410 typedef typename detail::LoopType<SIZE>::type ltype; 01411 ltype::ceil(res.begin(), v.begin()); 01412 return res; 01413 } 01414 01415 /** Apply floor() function to each vector component. 01416 */ 01417 template <class V, int SIZE, class D1, class D2> 01418 inline 01419 TinyVector<V, SIZE> 01420 floor(TinyVectorBase<V, SIZE, D1, D2> const & v) 01421 { 01422 TinyVector<V, SIZE> res(detail::dontInit()); 01423 typedef typename detail::LoopType<SIZE>::type ltype; 01424 ltype::floor(res.begin(), v.begin()); 01425 return res; 01426 } 01427 01428 /// cross product 01429 template <class V1, class D1, class D2, class V2, class D3, class D4> 01430 inline 01431 TinyVector<typename PromoteTraits<V1, V2>::Promote, 3> 01432 cross(TinyVectorBase<V1, 3, D1, D2> const & r1, 01433 TinyVectorBase<V2, 3, D3, D4> const & r2) 01434 { 01435 typedef TinyVector<typename PromoteTraits<V1, V2>::Promote, 3> 01436 Res; 01437 return Res(r1[1]*r2[2] - r1[2]*r2[1], 01438 r1[2]*r2[0] - r1[0]*r2[2], 01439 r1[0]*r2[1] - r1[1]*r2[0]); 01440 } 01441 01442 /// dot product 01443 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4> 01444 inline 01445 typename PromoteTraits<V1, V2>::Promote 01446 dot(TinyVectorBase<V1, SIZE, D1, D2> const & l, 01447 TinyVectorBase<V2, SIZE, D3, D4> const & r) 01448 { 01449 typedef typename detail::LoopType<SIZE>::type ltype; 01450 return ltype::dot(l.begin(), r.begin()); 01451 } 01452 01453 /// sum of the vector's elements 01454 template <class V, int SIZE, class D1, class D2> 01455 inline 01456 typename NumericTraits<V>::Promote 01457 sum(TinyVectorBase<V, SIZE, D1, D2> const & l) 01458 { 01459 typename NumericTraits<V>::Promote res = l[0]; 01460 for(int k=1; k<SIZE; ++k) 01461 res += l[k]; 01462 return res; 01463 } 01464 01465 /// cumulative sum of the vector's elements 01466 template <class V, int SIZE, class D1, class D2> 01467 inline 01468 TinyVector<typename NumericTraits<V>::Promote, SIZE> 01469 cumsum(TinyVectorBase<V, SIZE, D1, D2> const & l) 01470 { 01471 TinyVector<typename NumericTraits<V>::Promote, SIZE> res(l); 01472 for(int k=1; k<SIZE; ++k) 01473 res[k] += res[k-1]; 01474 return res; 01475 } 01476 01477 /// product of the vector's elements 01478 template <class V, int SIZE, class D1, class D2> 01479 inline 01480 typename NumericTraits<V>::Promote 01481 prod(TinyVectorBase<V, SIZE, D1, D2> const & l) 01482 { 01483 typename NumericTraits<V>::Promote res = l[0]; 01484 for(int k=1; k<SIZE; ++k) 01485 res *= l[k]; 01486 return res; 01487 } 01488 01489 /// cumulative sum of the vector's elements 01490 template <class V, int SIZE, class D1, class D2> 01491 inline 01492 TinyVector<typename NumericTraits<V>::Promote, SIZE> 01493 cumprod(TinyVectorBase<V, SIZE, D1, D2> const & l) 01494 { 01495 TinyVector<typename NumericTraits<V>::Promote, SIZE> res(l); 01496 for(int k=1; k<SIZE; ++k) 01497 res[k] *= res[k-1]; 01498 return res; 01499 } 01500 01501 /// element-wise minimum 01502 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4> 01503 inline 01504 TinyVector<typename PromoteTraits<V1, V2>::Promote, SIZE> 01505 min(TinyVectorBase<V1, SIZE, D1, D2> const & l, 01506 TinyVectorBase<V2, SIZE, D3, D4> const & r) 01507 { 01508 TinyVector<typename PromoteTraits<V1, V2>::Promote, SIZE> res(l); 01509 for(int k=0; k<SIZE; ++k) 01510 if(r[k] < res[k]) 01511 res[k] = r[k]; 01512 return res; 01513 } 01514 01515 /// element-wise maximum 01516 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4> 01517 inline 01518 TinyVector<typename PromoteTraits<V1, V2>::Promote, SIZE> 01519 max(TinyVectorBase<V1, SIZE, D1, D2> const & l, 01520 TinyVectorBase<V2, SIZE, D3, D4> const & r) 01521 { 01522 TinyVector<typename PromoteTraits<V1, V2>::Promote, SIZE> res(l); 01523 for(int k=0; k<SIZE; ++k) 01524 if(res[k] < r[k]) 01525 res[k] = r[k]; 01526 return res; 01527 } 01528 01529 /// squared norm 01530 template <class V1, int SIZE, class D1, class D2> 01531 inline 01532 typename TinyVectorBase<V1, SIZE, D1, D2>::SquaredNormType 01533 squaredNorm(TinyVectorBase<V1, SIZE, D1, D2> const & t) 01534 { 01535 return t.squaredMagnitude(); 01536 } 01537 01538 /// squared norm 01539 template <class V, int SIZE> 01540 inline 01541 typename TinyVector<V, SIZE>::SquaredNormType 01542 squaredNorm(TinyVector<V, SIZE> const & t) 01543 { 01544 return t.squaredMagnitude(); 01545 } 01546 //@} 01547 01548 01549 } // namespace vigra 01550 #undef VIGRA_ASSERT_INSIDE 01551 #endif // VIGRA_TINYVECTOR_HXX
© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de) |
html generated using doxygen and Python
|