[ 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 <algorithm> 00044 #include "config.hxx" 00045 #include "error.hxx" 00046 #include "metaprogramming.hxx" 00047 #include "numerictraits.hxx" 00048 #include "memory.hxx" 00049 #include "mathutil.hxx" 00050 #include "diff2d.hxx" 00051 00052 #ifdef VIGRA_CHECK_BOUNDS 00053 #define VIGRA_ASSERT_INSIDE(diff) \ 00054 vigra_precondition(diff >= 0, "Index out of bounds");\ 00055 vigra_precondition(diff < SIZE, "Index out of bounds"); 00056 #else 00057 #define VIGRA_ASSERT_INSIDE(diff) 00058 #endif 00059 00060 namespace vigra { 00061 00062 // mask cl.exe shortcomings [begin] 00063 #if defined(_MSC_VER) 00064 #pragma warning( push ) 00065 #pragma warning( disable : 4503 ) 00066 #endif 00067 00068 using VIGRA_CSTD::abs; 00069 using VIGRA_CSTD::ceil; 00070 using VIGRA_CSTD::floor; 00071 using VIGRA_CSTD::sqrt; 00072 00073 00074 template <class V1, int SIZE, class D1, class D2> 00075 class TinyVectorBase; 00076 00077 template <class V1, int SIZE, class D1, class D2> 00078 inline 00079 typename TinyVectorBase<V1, SIZE, D1, D2>::SquaredNormType 00080 squaredNorm(TinyVectorBase<V1, SIZE, D1, D2> const & t); 00081 00082 00083 namespace detail { 00084 00085 #define VIGRA_EXEC_LOOP(NAME, OPER) \ 00086 template <class T1, class T2> \ 00087 static void NAME(T1 * left, T2 const * right) \ 00088 { \ 00089 for(int i=0; i<LEVEL; ++i) \ 00090 (left[i]) OPER (right[i]); \ 00091 } 00092 00093 #define VIGRA_EXEC_LOOP_MINMAX(NAME, OPER) \ 00094 template <class T1, class T2> \ 00095 static void NAME(T1 * left, T2 const * right) \ 00096 { \ 00097 for(int i=0; i<LEVEL; ++i) \ 00098 if(left[i] OPER right[i]) \ 00099 left[i] = right[i]; \ 00100 } 00101 00102 #define VIGRA_EXEC_LOOP_SCALAR(NAME, OPER) \ 00103 template <class T1, class T2> \ 00104 static void NAME(T1 * left, T2 right) \ 00105 { \ 00106 for(int i=0; i<LEVEL; ++i) \ 00107 (left[i]) = detail::RequiresExplicitCast<T1>::cast((left[i]) OPER (right)); \ 00108 } 00109 00110 template <int LEVEL> 00111 struct ExecLoop 00112 { 00113 template <class T1, class T2> 00114 static void assignCast(T1 * left, T2 const * right) 00115 { 00116 for(int i=0; i<LEVEL; ++i) 00117 left[i] = detail::RequiresExplicitCast<T1>::cast(right[i]); 00118 } 00119 00120 template <class T1, class T2> 00121 static void reverseAssign(T1 * left, T2 const * right) 00122 { 00123 for(int i=0; i<LEVEL; ++i) 00124 left[i] = right[-i]; 00125 } 00126 00127 template <class T1, class T2> 00128 static void assignScalar(T1 * left, T2 right) 00129 { 00130 for(int i=0; i<LEVEL; ++i) 00131 left[i] = detail::RequiresExplicitCast<T1>::cast(right); 00132 } 00133 00134 template <class T1, class T2> 00135 static void power(T1 * left, T2 right) 00136 { 00137 for(int i=0; i<LEVEL; ++i) 00138 left[i] = detail::RequiresExplicitCast<T1>::cast(pow(left, right)); 00139 } 00140 00141 VIGRA_EXEC_LOOP(assign, =) 00142 VIGRA_EXEC_LOOP(add, +=) 00143 VIGRA_EXEC_LOOP(sub, -=) 00144 VIGRA_EXEC_LOOP(mul, *=) 00145 VIGRA_EXEC_LOOP(div, /=) 00146 VIGRA_EXEC_LOOP(neg, = -) 00147 VIGRA_EXEC_LOOP(abs, = vigra::abs) 00148 VIGRA_EXEC_LOOP(floor, = vigra::floor) 00149 VIGRA_EXEC_LOOP(ceil, = vigra::ceil) 00150 VIGRA_EXEC_LOOP(sqrt, = vigra::sqrt) 00151 VIGRA_EXEC_LOOP(fromPromote, = NumericTraits<T1>::fromPromote) 00152 VIGRA_EXEC_LOOP(fromRealPromote, = NumericTraits<T1>::fromRealPromote) 00153 VIGRA_EXEC_LOOP_SCALAR(mulScalar, *) 00154 VIGRA_EXEC_LOOP_SCALAR(divScalar, /) 00155 00156 VIGRA_EXEC_LOOP_MINMAX(min, >) 00157 VIGRA_EXEC_LOOP_MINMAX(max, <) 00158 00159 template <class T> 00160 static T const & minimum(T const * p) 00161 { 00162 return *std::min_element(p, p+LEVEL); 00163 } 00164 00165 template <class T> 00166 static T const & maximum(T const * p) 00167 { 00168 return *std::max_element(p, p+LEVEL); 00169 } 00170 00171 template <class T1, class T2> 00172 static bool notEqual(T1 const * left, T2 const * right) 00173 { 00174 for(int i=0; i<LEVEL; ++i) 00175 if(left[i] != right[i]) 00176 return true; 00177 return false; 00178 } 00179 00180 template <class T1, class T2> 00181 static bool less(T1 const * left, T2 const * right) 00182 { 00183 for(int i=0; i<LEVEL; ++i) 00184 { 00185 if(left[i] < right[i]) 00186 return true; 00187 if(right[i] < left[i]) 00188 return false; 00189 } 00190 return false; 00191 } 00192 template <class T> 00193 static typename NumericTraits<T>::Promote 00194 dot(T const * d) 00195 { 00196 typename NumericTraits<T>::Promote res(*d * *d); 00197 for(int i=1; i<LEVEL; ++i) 00198 res += d[i] * d[i]; 00199 return res; 00200 } 00201 00202 template <class T1, class T2> 00203 static typename PromoteTraits<T1, T2>::Promote 00204 dot(T1 const * left, T2 const * right) 00205 { 00206 typename PromoteTraits<T1, T2>::Promote res(*left * *right); 00207 for(int i=1; i<LEVEL; ++i) 00208 res += left[i] * right[i]; 00209 return res; 00210 } 00211 00212 template <class T> 00213 static typename NormTraits<T>::SquaredNormType 00214 squaredNorm(T const * d) 00215 { 00216 typename NormTraits<T>::SquaredNormType res = vigra::squaredNorm(*d); 00217 for(int i=1; i<LEVEL; ++i) 00218 res += vigra::squaredNorm(d[i]); 00219 return res; 00220 } 00221 }; 00222 00223 template <int LEVEL> 00224 struct UnrollScalarResult 00225 { 00226 template <class T> 00227 static typename NumericTraits<T>::Promote 00228 dot(T const * d) 00229 { 00230 return *d * *d + UnrollScalarResult<LEVEL-1>::dot(d+1); 00231 } 00232 00233 template <class T1, class T2> 00234 static typename PromoteTraits<T1, T2>::Promote 00235 dot(T1 const * left, T2 const * right) 00236 { 00237 return *left * *right + UnrollScalarResult<LEVEL-1>::dot(left+1, right+1); 00238 } 00239 00240 template <class T> 00241 static typename NormTraits<T>::SquaredNormType 00242 squaredNorm(T const * d) 00243 { 00244 return vigra::squaredNorm(*d) + UnrollScalarResult<LEVEL-1>::squaredNorm(d+1); 00245 } 00246 00247 static std::ptrdiff_t 00248 squaredNorm(std::ptrdiff_t const * d) 00249 { 00250 return (*d)*(*d) + UnrollScalarResult<LEVEL-1>::squaredNorm(d+1); 00251 } 00252 00253 template <class T> 00254 static T const & minimum(T const * p) 00255 { 00256 T const & m = UnrollScalarResult<LEVEL - 1>::minimum(p+1); 00257 return *p < m 00258 ? *p 00259 : m; 00260 } 00261 00262 template <class T> 00263 static T const & maximum(T const * p) 00264 { 00265 T const & m = UnrollScalarResult<LEVEL - 1>::maximum(p+1); 00266 return *p > m 00267 ? *p 00268 : m; 00269 } 00270 }; 00271 00272 template <> 00273 struct UnrollScalarResult<1> 00274 { 00275 template <class T> 00276 static typename NumericTraits<T>::Promote 00277 dot(T const * d) 00278 { 00279 return *d * *d ; 00280 } 00281 00282 template <class T1, class T2> 00283 static typename PromoteTraits<T1, T2>::Promote 00284 dot(T1 const * left, T2 const * right) 00285 { 00286 return *left * *right; 00287 } 00288 00289 template <class T> 00290 static typename NormTraits<T>::SquaredNormType 00291 squaredNorm(T const * d) 00292 { 00293 return vigra::squaredNorm(*d); 00294 } 00295 00296 static std::ptrdiff_t 00297 squaredNorm(std::ptrdiff_t const * d) 00298 { 00299 return (*d)*(*d); 00300 } 00301 00302 template <class T> 00303 static T const & minimum(T const * p) 00304 { 00305 return *p; 00306 } 00307 00308 template <class T> 00309 static T const & maximum(T const * p) 00310 { 00311 return *p; 00312 } 00313 }; 00314 00315 #undef VIGRA_EXEC_LOOP 00316 #undef VIGRA_EXEC_LOOP_MINMAX 00317 #undef VIGRA_EXEC_LOOP_SCALAR 00318 00319 #define VIGRA_UNROLL_LOOP(NAME, OPER) \ 00320 template <class T1, class T2> \ 00321 static void NAME(T1 * left, T2 const * right) \ 00322 { \ 00323 (*left) OPER (*right); \ 00324 UnrollLoop<LEVEL-1>::NAME(left+1, right+1); \ 00325 } 00326 00327 #define VIGRA_UNROLL_LOOP_MINMAX(NAME, OPER) \ 00328 template <class T1, class T2> \ 00329 static void NAME(T1 * left, T2 const * right) \ 00330 { \ 00331 if(*left OPER *right) \ 00332 *left = *right; \ 00333 UnrollLoop<LEVEL-1>::NAME(left+1, right+1); \ 00334 } 00335 00336 #define VIGRA_UNROLL_LOOP_SCALAR(NAME, OPER) \ 00337 template <class T1, class T2> \ 00338 static void NAME(T1 * left, T2 right) \ 00339 { \ 00340 (*left) = detail::RequiresExplicitCast<T1>::cast((*left) OPER (right)); \ 00341 UnrollLoop<LEVEL-1>::NAME(left+1, right); \ 00342 } 00343 00344 00345 template <int LEVEL> 00346 struct UnrollLoop 00347 { 00348 template <class T1, class T2> 00349 static void reverseAssign(T1 * left, T2 const * right) 00350 { 00351 *left = *right; 00352 UnrollLoop<LEVEL-1>::reverseAssign(left+1, right-1); 00353 } 00354 00355 template <class T1, class T2> 00356 static void assignCast(T1 * left, T2 const * right) 00357 { 00358 *left = detail::RequiresExplicitCast<T1>::cast(*right); 00359 UnrollLoop<LEVEL-1>::assignCast(left+1, right+1); 00360 } 00361 00362 template <class T1, class T2> 00363 static void assignScalar(T1 * left, T2 right) 00364 { 00365 *left = detail::RequiresExplicitCast<T1>::cast(right); 00366 UnrollLoop<LEVEL-1>::assignScalar(left+1, right); 00367 } 00368 00369 template <class T1, class T2> 00370 static void power(T1 * left, T2 right) 00371 { 00372 *left = detail::RequiresExplicitCast<T1>::cast(pow(*left, right)); 00373 UnrollLoop<LEVEL-1>::power(left+1, right); 00374 } 00375 00376 VIGRA_UNROLL_LOOP(assign, =) 00377 VIGRA_UNROLL_LOOP(add, +=) 00378 VIGRA_UNROLL_LOOP(sub, -=) 00379 VIGRA_UNROLL_LOOP(mul, *=) 00380 VIGRA_UNROLL_LOOP(div, /=) 00381 VIGRA_UNROLL_LOOP(neg, = -) 00382 VIGRA_UNROLL_LOOP(abs, = vigra::abs) 00383 VIGRA_UNROLL_LOOP(floor, = vigra::floor) 00384 VIGRA_UNROLL_LOOP(ceil, = vigra::ceil) 00385 VIGRA_UNROLL_LOOP(sqrt, = vigra::sqrt) 00386 VIGRA_UNROLL_LOOP(fromPromote, = NumericTraits<T1>::fromPromote) 00387 VIGRA_UNROLL_LOOP(fromRealPromote, = NumericTraits<T1>::fromRealPromote) 00388 VIGRA_UNROLL_LOOP_SCALAR(mulScalar, *) 00389 VIGRA_UNROLL_LOOP_SCALAR(divScalar, /) 00390 00391 VIGRA_UNROLL_LOOP_MINMAX(min, >) 00392 VIGRA_UNROLL_LOOP_MINMAX(max, <) 00393 00394 template <class T> 00395 static T const & minimum(T const * p) 00396 { 00397 return UnrollScalarResult<LEVEL>::minimum(p); 00398 } 00399 00400 template <class T> 00401 static T const & maximum(T const * p) 00402 { 00403 return UnrollScalarResult<LEVEL>::maximum(p); 00404 } 00405 00406 template <class T1, class T2> 00407 static bool notEqual(T1 const * left, T2 const * right) 00408 { 00409 return (*left != *right) || UnrollLoop<LEVEL - 1>::notEqual(left+1, right+1); 00410 } 00411 00412 template <class T1, class T2> 00413 static bool less(T1 const * left, T2 const * right) 00414 { 00415 if(*left < *right) 00416 return true; 00417 if(*right < *left) 00418 return false; 00419 return UnrollLoop<LEVEL - 1>::less(left+1, right+1); 00420 } 00421 00422 template <class T> 00423 static typename NumericTraits<T>::Promote 00424 dot(T const * d) 00425 { 00426 return UnrollScalarResult<LEVEL>::dot(d); 00427 } 00428 00429 template <class T1, class T2> 00430 static typename PromoteTraits<T1, T2>::Promote 00431 dot(T1 const * left, T2 const * right) 00432 { 00433 return UnrollScalarResult<LEVEL>::dot(left, right); 00434 } 00435 00436 template <class T> 00437 static typename NormTraits<T>::SquaredNormType 00438 squaredNorm(T const * d) 00439 { 00440 return UnrollScalarResult<LEVEL>::squaredNorm(d); 00441 } 00442 }; 00443 00444 #undef VIGRA_UNROLL_LOOP 00445 #undef VIGRA_UNROLL_LOOP_MINMAX 00446 #undef VIGRA_UNROLL_LOOP_SCALAR 00447 00448 template <> 00449 struct UnrollLoop<0> 00450 { 00451 template <class T1, class T2> 00452 static void reverseAssign(T1, T2) {} 00453 template <class T1, class T2> 00454 static void assignCast(T1, T2) {} 00455 template <class T1, class T2> 00456 static void assign(T1, T2) {} 00457 template <class T1, class T2> 00458 static void assignScalar(T1, T2) {} 00459 template <class T1, class T2> 00460 static void power(T1, T2) {} 00461 template <class T1, class T2> 00462 static void add(T1, T2) {} 00463 template <class T1, class T2> 00464 static void sub(T1, T2) {} 00465 template <class T1, class T2> 00466 static void mul(T1, T2) {} 00467 template <class T1, class T2> 00468 static void mulScalar(T1, T2) {} 00469 template <class T1, class T2> 00470 static void div(T1, T2) {} 00471 template <class T1, class T2> 00472 static void divScalar(T1, T2) {} 00473 template <class T1, class T2> 00474 static void fromPromote(T1, T2) {} 00475 template <class T1, class T2> 00476 static void fromRealPromote(T1, T2) {} 00477 template <class T1, class T2> 00478 static void neg(T1, T2) {} 00479 template <class T1, class T2> 00480 static void abs(T1, T2) {} 00481 template <class T1, class T2> 00482 static void floor(T1, T2) {} 00483 template <class T1, class T2> 00484 static void ceil(T1, T2) {} 00485 template <class T1, class T2> 00486 static void sqrt(T1, T2) {} 00487 template <class T1, class T2> 00488 static bool notEqual(T1, T2) { return false; } 00489 template <class T1, class T2> 00490 static bool less(T1, T2) { return false; } 00491 template <class T1, class T2> 00492 static void min(T1, T2) {} 00493 template <class T1, class T2> 00494 static void max(T1, T2) {} 00495 template <class T> 00496 static T minimum(T const * p) 00497 { 00498 return NumericTraits<T>::max(); 00499 } 00500 template <class T> 00501 static T maximum(T const * p) 00502 { 00503 return NumericTraits<T>::min(); 00504 } 00505 }; 00506 00507 template <int SIZE> 00508 struct LoopType 00509 { 00510 typedef typename IfBool<(SIZE <= 5), UnrollLoop<SIZE>, ExecLoop<SIZE> >::type type; 00511 00512 }; 00513 00514 struct DontInit {}; 00515 00516 inline DontInit dontInit() {return DontInit(); } 00517 00518 } // namespace detail 00519 00520 template <class T, int SIZE> 00521 class TinyVector; 00522 00523 template <class T, int SIZE> 00524 class TinyVectorView; 00525 00526 /********************************************************/ 00527 /* */ 00528 /* TinyVectorBase */ 00529 /* */ 00530 /********************************************************/ 00531 00532 /** \brief Base class for fixed size vectors. 00533 00534 This class contains functionality shared by 00535 \ref TinyVector and \ref TinyVectorView, and enables these classes 00536 to be freely mixed within expressions. It is typically not used directly. 00537 00538 <b>\#include</b> <vigra/tinyvector.hxx><br> 00539 Namespace: vigra 00540 **/ 00541 template <class VALUETYPE, int SIZE, class DATA, class DERIVED> 00542 class TinyVectorBase 00543 { 00544 TinyVectorBase(TinyVectorBase const &); // do not use 00545 00546 TinyVectorBase & operator=(TinyVectorBase const & other); // do not use 00547 00548 protected: 00549 00550 typedef typename detail::LoopType<SIZE>::type Loop; 00551 00552 TinyVectorBase() 00553 {} 00554 00555 public: 00556 /** STL-compatible definition of valuetype 00557 */ 00558 typedef VALUETYPE value_type; 00559 00560 /** reference (return of operator[]). 00561 */ 00562 typedef VALUETYPE & reference; 00563 00564 /** const reference (return of operator[] const). 00565 */ 00566 typedef VALUETYPE const & const_reference; 00567 00568 /** pointer (return of operator->). 00569 */ 00570 typedef VALUETYPE * pointer; 00571 00572 /** const pointer (return of operator-> const). 00573 */ 00574 typedef VALUETYPE const * const_pointer; 00575 00576 /** STL-compatible definition of iterator 00577 */ 00578 typedef value_type * iterator; 00579 00580 /** STL-compatible definition of const iterator 00581 */ 00582 typedef value_type const * const_iterator; 00583 00584 /** STL-compatible definition of size_type 00585 */ 00586 typedef unsigned int size_type; 00587 00588 /** STL-compatible definition of difference_type 00589 */ 00590 typedef std::ptrdiff_t difference_type; 00591 00592 /** the scalar type for the outer product 00593 */ 00594 typedef double scalar_multiplier; 00595 00596 /** the vector's squared norm type 00597 */ 00598 typedef typename NormTraits<VALUETYPE>::SquaredNormType SquaredNormType; 00599 00600 /** the vector's norm type 00601 */ 00602 typedef typename SquareRootTraits<SquaredNormType>::SquareRootResult NormType; 00603 00604 /** the vector's size 00605 */ 00606 enum { static_size = SIZE }; 00607 00608 /** Initialize from another sequence (must have length SIZE!) 00609 */ 00610 template <class Iterator> 00611 void init(Iterator i, Iterator end) 00612 { 00613 vigra_precondition(end-i == SIZE, 00614 "TinyVector::init(): Sequence has wrong size."); 00615 Loop::assignCast(data_, i); 00616 } 00617 00618 /** Initialize with constant value 00619 */ 00620 void init(value_type initial) 00621 { 00622 Loop::assignScalar(data_, initial); 00623 } 00624 00625 /** Component-wise add-assignment 00626 */ 00627 template <class T1, class D1, class D2> 00628 DERIVED & operator+=(TinyVectorBase<T1, SIZE, D1, D2> const & r) 00629 { 00630 Loop::add(data_, r.begin()); 00631 return static_cast<DERIVED &>(*this); 00632 } 00633 00634 /** Component-wise subtract-assignment 00635 */ 00636 template <class T1, class D1, class D2> 00637 DERIVED & operator-=(TinyVectorBase<T1, SIZE, D1, D2> const & r) 00638 { 00639 Loop::sub(data_, r.begin()); 00640 return static_cast<DERIVED &>(*this); 00641 } 00642 00643 /** Component-wise multiply-assignment 00644 */ 00645 template <class T1, class D1, class D2> 00646 DERIVED & operator*=(TinyVectorBase<T1, SIZE, D1, D2> const & r) 00647 { 00648 Loop::mul(data_, r.begin()); 00649 return static_cast<DERIVED &>(*this); 00650 } 00651 00652 /** Component-wise divide-assignment 00653 */ 00654 template <class T1, class D1, class D2> 00655 DERIVED & operator/=(TinyVectorBase<T1, SIZE, D1, D2> const & r) 00656 { 00657 Loop::div(data_, r.begin()); 00658 return static_cast<DERIVED &>(*this); 00659 } 00660 00661 /** Component-wise scalar multiply-assignment 00662 */ 00663 DERIVED & operator*=(double r) 00664 { 00665 Loop::mulScalar(data_, r); 00666 return static_cast<DERIVED &>(*this); 00667 } 00668 00669 /** Component-wise scalar divide-assignment 00670 */ 00671 DERIVED & operator/=(double r) 00672 { 00673 Loop::divScalar(data_, r); 00674 return static_cast<DERIVED &>(*this); 00675 } 00676 00677 /** Calculate magnitude. 00678 */ 00679 NormType magnitude() const 00680 { 00681 return sqrt(static_cast<typename 00682 SquareRootTraits<SquaredNormType>::SquareRootArgument>(squaredMagnitude())); 00683 } 00684 00685 /** Calculate squared magnitude. 00686 */ 00687 SquaredNormType squaredMagnitude() const 00688 { 00689 return Loop::squaredNorm(data_); 00690 } 00691 00692 /** Return the minimal element. 00693 */ 00694 VALUETYPE const & minimum() const 00695 { 00696 return Loop::minimum(data_); 00697 } 00698 00699 /** Return the maximal element. 00700 */ 00701 VALUETYPE const & maximum() const 00702 { 00703 return Loop::maximum(data_); 00704 } 00705 00706 /** Access component by index. 00707 */ 00708 reference operator[](difference_type i) 00709 { 00710 VIGRA_ASSERT_INSIDE(i); 00711 return data_[i]; 00712 } 00713 00714 /** Get component by index. 00715 */ 00716 const_reference operator[](difference_type i) const 00717 { 00718 VIGRA_ASSERT_INSIDE(i); 00719 return data_[i]; 00720 } 00721 00722 /** Get random access iterator to begin of vector. 00723 */ 00724 iterator begin() { return data_; } 00725 /** Get random access iterator past-the-end of vector. 00726 */ 00727 iterator end() { return data_ + SIZE; } 00728 00729 /** Get const random access iterator to begin of vector. 00730 */ 00731 const_iterator begin() const { return data_; } 00732 00733 /** Get const random access iterator past-the-end of vector. 00734 */ 00735 const_iterator end() const { return data_ + SIZE; } 00736 00737 /** Size of TinyVector vector always equals the template parameter SIZE. 00738 */ 00739 size_type size() const { return SIZE; } 00740 00741 pointer data() { return data_; } 00742 00743 const_pointer data() const { return data_; } 00744 00745 protected: 00746 00747 DATA data_; 00748 }; 00749 00750 /** \brief Class for fixed size vectors. 00751 \ingroup RangesAndPoints 00752 00753 This class contains an array of size SIZE of the specified VALUETYPE. 00754 The interface conforms to STL vector, except that there are no functions 00755 that change the size of a TinyVector. 00756 00757 \ref TinyVectorOperators "Arithmetic operations" 00758 on TinyVectors are defined as component-wise applications of these 00759 operations. Addition and subtraction of two TinyVectors 00760 (+=, -=, +, -, unary -), multiplication and division of an 00761 TinyVector with a double, and NumericTraits/PromoteTraits are defined, 00762 so that TinyVector fulfills the requirements of \ref LinearAlgebraConcept "Linear Algebra". 00763 00764 VIGRA algorithms typically use \ref vigra::VectorAccessor to access 00765 TinyVectors as a whole, or specific components of them. 00766 00767 See also:<br> 00768 <UL style="list-style-image:url(documents/bullet.gif)"> 00769 <LI> \ref vigra::TinyVectorBase 00770 <LI> \ref vigra::TinyVectorView 00771 <LI> \ref TinyVectorTraits 00772 <LI> \ref TinyVectorOperators 00773 </UL> 00774 00775 <b>\#include</b> <vigra/tinyvector.hxx><br> 00776 Namespace: vigra 00777 **/ 00778 template <class T, int SIZE> 00779 class TinyVector 00780 : public TinyVectorBase<T, SIZE, T[SIZE], TinyVector<T, SIZE> > 00781 { 00782 typedef TinyVectorBase<T, SIZE, T[SIZE], TinyVector<T, SIZE> > BaseType; 00783 typedef typename BaseType::Loop Loop; 00784 00785 public: 00786 00787 typedef typename BaseType::value_type value_type; 00788 typedef typename BaseType::reference reference; 00789 typedef typename BaseType::const_reference const_reference; 00790 typedef typename BaseType::pointer pointer; 00791 typedef typename BaseType::const_pointer const_pointer; 00792 typedef typename BaseType::iterator iterator; 00793 typedef typename BaseType::const_iterator const_iterator; 00794 typedef typename BaseType::size_type size_type; 00795 typedef typename BaseType::difference_type difference_type; 00796 typedef typename BaseType::scalar_multiplier scalar_multiplier; 00797 typedef typename BaseType::SquaredNormType SquaredNormType; 00798 typedef typename BaseType::NormType NormType; 00799 00800 enum ReverseCopyTag { ReverseCopy }; 00801 00802 /** Construction with constant value. 00803 00804 Initializes all vector elements with the given value. 00805 */ 00806 explicit TinyVector(value_type const & initial) 00807 : BaseType() 00808 { 00809 Loop::assignScalar(BaseType::begin(), initial); 00810 } 00811 00812 /** Construction with Diff2D. 00813 00814 Use only when <tt>SIZE == 2</tt>. 00815 */ 00816 explicit TinyVector(Diff2D const & initial) 00817 : BaseType() 00818 { 00819 BaseType::data_[0] = detail::RequiresExplicitCast<T>::cast(initial.x); 00820 BaseType::data_[1] = detail::RequiresExplicitCast<T>::cast(initial.y); 00821 } 00822 00823 /** Construction with explicit values. 00824 Call only if SIZE == 2 00825 */ 00826 TinyVector(value_type const & i1, value_type const & i2) 00827 : BaseType() 00828 { 00829 BaseType::data_[0] = i1; 00830 BaseType::data_[1] = i2; 00831 } 00832 00833 /** Construction with explicit values. 00834 Call only if SIZE == 3 00835 */ 00836 TinyVector(value_type const & i1, value_type const & i2, value_type const & i3) 00837 : BaseType() 00838 { 00839 BaseType::data_[0] = i1; 00840 BaseType::data_[1] = i2; 00841 BaseType::data_[2] = i3; 00842 } 00843 00844 /** Construction with explicit values. 00845 Call only if SIZE == 4 00846 */ 00847 TinyVector(value_type const & i1, value_type const & i2, 00848 value_type const & i3, value_type const & i4) 00849 : BaseType() 00850 { 00851 BaseType::data_[0] = i1; 00852 BaseType::data_[1] = i2; 00853 BaseType::data_[2] = i3; 00854 BaseType::data_[3] = i4; 00855 } 00856 00857 /** Construction with explicit values. 00858 Call only if SIZE == 5 00859 */ 00860 TinyVector(value_type const & i1, value_type const & i2, 00861 value_type const & i3, value_type const & i4, 00862 value_type const & i5) 00863 : BaseType() 00864 { 00865 BaseType::data_[0] = i1; 00866 BaseType::data_[1] = i2; 00867 BaseType::data_[2] = i3; 00868 BaseType::data_[3] = i4; 00869 BaseType::data_[4] = i5; 00870 } 00871 00872 /** Default constructor (initializes all elements with zero). 00873 */ 00874 TinyVector() 00875 : BaseType() 00876 { 00877 Loop::assignScalar(BaseType::data_, NumericTraits<value_type>::zero()); 00878 } 00879 00880 /** Construct without initializing the vector elements. 00881 */ 00882 explicit TinyVector(SkipInitializationTag) 00883 : BaseType() 00884 {} 00885 00886 explicit TinyVector(detail::DontInit) 00887 : BaseType() 00888 {} 00889 00890 /** Copy constructor. 00891 */ 00892 TinyVector(TinyVector const & r) 00893 : BaseType() 00894 { 00895 Loop::assign(BaseType::data_, r.data_); 00896 } 00897 00898 /** Constructor from C array. 00899 */ 00900 explicit TinyVector(const_pointer data) 00901 : BaseType() 00902 { 00903 Loop::assign(BaseType::data_, data); 00904 } 00905 00906 /** Constructor by reverse copy from C array. 00907 00908 Usage: 00909 \code 00910 TinyVector<int, 3> v(1,2,3); 00911 TinyVector<int, 3> reverse(v.begin(), TinyVector<int, 3>::ReverseCopy); 00912 \endcode 00913 */ 00914 explicit TinyVector(const_pointer data, ReverseCopyTag) 00915 : BaseType() 00916 { 00917 Loop::reverseAssign(BaseType::data_, data+SIZE-1); 00918 } 00919 00920 /** Copy with type conversion. 00921 */ 00922 template <class U, class DATA, class DERIVED> 00923 TinyVector(TinyVectorBase<U, SIZE, DATA, DERIVED> const & r) 00924 : BaseType() 00925 { 00926 Loop::assignCast(BaseType::data_, r.begin()); 00927 } 00928 00929 /** Copy assignment. 00930 */ 00931 TinyVector & operator=(TinyVector const & r) 00932 { 00933 Loop::assign(BaseType::data_, r.data_); 00934 return *this; 00935 } 00936 00937 /** Copy assignment with type conversion. 00938 */ 00939 template <class U, class DATA, class DERIVED> 00940 TinyVector & operator=(TinyVectorBase<U, SIZE, DATA, DERIVED> const & r) 00941 { 00942 Loop::assignCast(BaseType::data_, r.begin()); 00943 return *this; 00944 } 00945 00946 /** Assignment from Diff2D. 00947 00948 Use only when <tt>SIZE == 2</tt>. 00949 */ 00950 TinyVector & operator=(Diff2D const & r) 00951 { 00952 BaseType::data_[0] = detail::RequiresExplicitCast<T>::cast(r.x); 00953 BaseType::data_[1] = detail::RequiresExplicitCast<T>::cast(r.y); 00954 return *this; 00955 } 00956 00957 /** Assignment from scalar. Will set all entries to the given value. 00958 */ 00959 TinyVector & operator=(value_type const & v) 00960 { 00961 Loop::assignScalar(BaseType::begin(), v); 00962 return *this; 00963 } 00964 00965 /** Copy from a TinyVector with a different number of elements. 00966 00967 Only the first <tt>min(SIZE, USIZE)</tt> elements are copied. 00968 */ 00969 template <class U, int USIZE, class DATA, class DERIVED> 00970 TinyVector & copy(TinyVectorBase<U, USIZE, DATA, DERIVED> const & r) 00971 { 00972 static const int minSize = USIZE < SIZE 00973 ? USIZE 00974 : SIZE; 00975 00976 typedef typename detail::LoopType<minSize>::type MinLoop; 00977 MinLoop::assignCast(BaseType::data_, r.begin()); 00978 return *this; 00979 } 00980 }; 00981 00982 /** \brief Wrapper for fixed size vectors. 00983 00984 This class wraps an array of size SIZE of the specified VALUETYPE. 00985 Thus, the array can be accessed with an interface similar to 00986 that of std::vector (except that there are no functions 00987 that change the size of a TinyVectorView). The TinyVectorView 00988 does <em>not</em> assume ownership of the given memory. 00989 00990 \ref TinyVectorOperators "Arithmetic operations" 00991 on TinyVectorViews are defined as component-wise applications of these 00992 operations. Addition and subtraction of two TinyVectorViews 00993 (+=, -=, +, -, unary -), multiplication and division of an 00994 TinyVectorViews with a double, and NumericTraits/PromoteTraits are defined, 00995 so that TinyVectorView fulfills the requirements of \ref LinearAlgebraConcept "Linear Algebra". 00996 00997 VIGRA algorithms typically use \ref vigra::VectorAccessor to access 00998 TinyVectorViews as a whole, or specific components of them. 00999 01000 <b>See also:</b> 01001 <ul> 01002 <li> \ref vigra::TinyVectorBase 01003 <li> \ref vigra::TinyVector 01004 <li> \ref TinyVectorTraits 01005 <li> \ref TinyVectorOperators 01006 </ul> 01007 01008 <b>\#include</b> <vigra/tinyvector.hxx><br> 01009 Namespace: vigra 01010 **/ 01011 template <class T, int SIZE> 01012 class TinyVectorView 01013 : public TinyVectorBase<T, SIZE, T *, TinyVectorView<T, SIZE> > 01014 { 01015 typedef TinyVectorBase<T, SIZE, T *, TinyVectorView<T, SIZE> > BaseType; 01016 typedef typename BaseType::Loop Loop; 01017 01018 public: 01019 01020 typedef typename BaseType::value_type value_type; 01021 typedef typename BaseType::reference reference; 01022 typedef typename BaseType::const_reference const_reference; 01023 typedef typename BaseType::pointer pointer; 01024 typedef typename BaseType::const_pointer const_pointer; 01025 typedef typename BaseType::iterator iterator; 01026 typedef typename BaseType::const_iterator const_iterator; 01027 typedef typename BaseType::size_type size_type; 01028 typedef typename BaseType::difference_type difference_type; 01029 typedef typename BaseType::scalar_multiplier scalar_multiplier; 01030 typedef typename BaseType::SquaredNormType SquaredNormType; 01031 typedef typename BaseType::NormType NormType; 01032 01033 /** Default constructor 01034 (pointer to wrapped data is NULL). 01035 */ 01036 TinyVectorView() 01037 : BaseType() 01038 { 01039 BaseType::data_ = 0; 01040 } 01041 01042 /** Construct view for given data array 01043 */ 01044 TinyVectorView(const_pointer data) 01045 : BaseType() 01046 { 01047 BaseType::data_ = const_cast<pointer>(data); 01048 } 01049 01050 /** Copy constructor (shallow copy). 01051 */ 01052 TinyVectorView(TinyVectorView const & other) 01053 : BaseType() 01054 { 01055 BaseType::data_ = const_cast<pointer>(other.data_); 01056 } 01057 01058 /** Construct view from other TinyVector. 01059 */ 01060 template <class DATA, class DERIVED> 01061 TinyVectorView(TinyVectorBase<T, SIZE, DATA, DERIVED> const & other) 01062 : BaseType() 01063 { 01064 BaseType::data_ = const_cast<pointer>(other.data()); 01065 } 01066 01067 /** Copy the data (not the pointer) of the rhs. 01068 */ 01069 TinyVectorView & operator=(TinyVectorView const & r) 01070 { 01071 Loop::assign(BaseType::data_, r.begin()); 01072 return *this; 01073 } 01074 01075 /** Copy the data of the rhs with cast. 01076 */ 01077 template <class U, class DATA, class DERIVED> 01078 TinyVectorView & operator=(TinyVectorBase<U, SIZE, DATA, DERIVED> const & r) 01079 { 01080 Loop::assignCast(BaseType::data_, r.begin()); 01081 return *this; 01082 } 01083 }; 01084 01085 /********************************************************/ 01086 /* */ 01087 /* TinyVector Comparison */ 01088 /* */ 01089 /********************************************************/ 01090 01091 /** \addtogroup TinyVectorOperators Functions for TinyVector 01092 01093 \brief Implement basic arithmetic and equality for TinyVector. 01094 01095 These functions fulfill the requirements of a Linear Space (vector space). 01096 Return types are determined according to \ref TinyVectorTraits. 01097 01098 <b>\#include</b> <vigra/tinyvector.hxx><br> 01099 Namespace: vigra 01100 */ 01101 //@{ 01102 /// component-wise equal 01103 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4> 01104 inline bool 01105 operator==(TinyVectorBase<V1, SIZE, D1, D2> const & l, 01106 TinyVectorBase<V2, SIZE, D3, D4> const & r) 01107 { 01108 return !(l != r); 01109 } 01110 01111 /// component-wise not equal 01112 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4> 01113 inline bool 01114 operator!=(TinyVectorBase<V1, SIZE, D1, D2> const & l, 01115 TinyVectorBase<V2, SIZE, D3, D4> const & r) 01116 { 01117 typedef typename detail::LoopType<SIZE>::type ltype; 01118 return ltype::notEqual(l.begin(), r.begin()); 01119 } 01120 01121 /// component-wise lexicographical comparison 01122 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4> 01123 inline bool 01124 operator<(TinyVectorBase<V1, SIZE, D1, D2> const & l, 01125 TinyVectorBase<V2, SIZE, D3, D4> const & r) 01126 { 01127 typedef typename detail::LoopType<SIZE>::type ltype; 01128 return ltype::less(l.begin(), r.begin()); 01129 } 01130 01131 /********************************************************/ 01132 /* */ 01133 /* TinyVector Output */ 01134 /* */ 01135 /********************************************************/ 01136 01137 /// stream output 01138 template <class V1, int SIZE, class DATA, class DERIVED> 01139 std::ostream & 01140 operator<<(std::ostream & out, TinyVectorBase<V1, SIZE, DATA, DERIVED> const & l) 01141 { 01142 out << "("; 01143 int i; 01144 for(i=0; i<SIZE-1; ++i) 01145 out << l[i] << ", "; 01146 out << l[i] << ")"; 01147 return out; 01148 } 01149 //@} 01150 01151 /********************************************************/ 01152 /* */ 01153 /* TinyVector-Traits */ 01154 /* */ 01155 /********************************************************/ 01156 01157 /** \page TinyVectorTraits Numeric and Promote Traits of TinyVector 01158 The numeric and promote traits for TinyVectors follow 01159 the general specifications for \ref NumericPromotionTraits. 01160 They are implemented in terms of the traits of the basic types by 01161 partial template specialization: 01162 01163 \code 01164 01165 template <class T, int SIZE> 01166 struct NumericTraits<TinyVector<T, SIZE> > 01167 { 01168 typedef TinyVector<typename NumericTraits<T>::Promote, SIZE> Promote; 01169 typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> RealPromote; 01170 01171 typedef typename NumericTraits<T>::isIntegral isIntegral; 01172 typedef VigraFalseType isScalar; 01173 typedef typename NumericTraits<T>::isSigned isSigned; 01174 01175 // etc. 01176 }; 01177 01178 template <class T, int SIZE> 01179 struct NormTraits<TinyVector<T, SIZE> > 01180 { 01181 typedef TinyVector<T, SIZE> Type; 01182 typedef typename Type::SquaredNormType SquaredNormType; 01183 typedef typename Type::NormType NormType; 01184 }; 01185 01186 template <class T1, class T2, SIZE> 01187 struct PromoteTraits<TinyVector<T1, SIZE>, TinyVector<T2, SIZE> > 01188 { 01189 typedef TinyVector<typename PromoteTraits<T1, T2>::Promote, SIZE> Promote; 01190 }; 01191 \endcode 01192 01193 <b>\#include</b> <vigra/tinyvector.hxx><br> 01194 Namespace: vigra 01195 01196 On compilers that don't support partial template specialization (e.g. 01197 MS VisualC++), the traits classes are explicitly specialized for 01198 <TT>TinyVector<VALUETYPE, SIZE></TT> with 01199 <TT>VALUETYPE = unsigned char | int | float | double</TT> and <TT>SIZE = 2 | 3 | 4</TT>. 01200 01201 */ 01202 01203 #if !defined(NO_PARTIAL_TEMPLATE_SPECIALIZATION) 01204 01205 template <class T, int SIZE> 01206 struct NumericTraits<TinyVector<T, SIZE> > 01207 { 01208 typedef TinyVector<T, SIZE> Type; 01209 typedef TinyVector<typename NumericTraits<T>::Promote, SIZE> Promote; 01210 typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> RealPromote; 01211 typedef TinyVector<typename NumericTraits<T>::ComplexPromote, SIZE> ComplexPromote; 01212 typedef T ValueType; 01213 01214 typedef typename NumericTraits<T>::isIntegral isIntegral; 01215 typedef VigraFalseType isScalar; 01216 typedef typename NumericTraits<T>::isSigned isSigned; 01217 typedef VigraTrueType isOrdered; 01218 typedef VigraFalseType isComplex; 01219 01220 static TinyVector<T, SIZE> zero() 01221 { 01222 return TinyVector<T, SIZE>(NumericTraits<T>::zero()); 01223 } 01224 static TinyVector<T, SIZE> one() 01225 { 01226 return TinyVector<T, SIZE>(NumericTraits<T>::one()); 01227 } 01228 static TinyVector<T, SIZE> nonZero() 01229 { 01230 return TinyVector<T, SIZE>(NumericTraits<T>::nonZero()); 01231 } 01232 01233 static TinyVector<T, SIZE> min() 01234 { 01235 return TinyVector<T, SIZE>(NumericTraits<T>::min()); 01236 } 01237 static TinyVector<T, SIZE> max() 01238 { 01239 return TinyVector<T, SIZE>(NumericTraits<T>::max()); 01240 } 01241 01242 template <class D1, class D2> 01243 static Promote toPromote(TinyVectorBase<T, SIZE, D1, D2> const & v) 01244 { 01245 return Promote(v); 01246 } 01247 01248 template <class D1, class D2> 01249 static RealPromote toRealPromote(TinyVectorBase<T, SIZE, D1, D2> const & v) 01250 { 01251 return RealPromote(v); 01252 } 01253 01254 template <class D1, class D2> 01255 static TinyVector<T, SIZE> 01256 fromPromote(TinyVectorBase<typename NumericTraits<T>::Promote, SIZE, D1, D2> const & v) 01257 { 01258 TinyVector<T, SIZE> res(detail::dontInit()); 01259 typedef typename detail::LoopType<SIZE>::type ltype; 01260 ltype::fromPromote(res.begin(), v.begin()); 01261 return res; 01262 } 01263 01264 template <class D1, class D2> 01265 static TinyVector<T, SIZE> 01266 fromRealPromote(TinyVectorBase<typename NumericTraits<T>::RealPromote, SIZE, D1, D2> const & v) 01267 { 01268 TinyVector<T, SIZE> res(detail::dontInit()); 01269 typedef typename detail::LoopType<SIZE>::type ltype; 01270 ltype::fromRealPromote(res.begin(), v.begin()); 01271 return res; 01272 } 01273 }; 01274 01275 template <class T, int SIZE> 01276 struct NumericTraits<TinyVectorView<T, SIZE> > 01277 : public NumericTraits<TinyVector<T, SIZE> > 01278 { 01279 typedef TinyVector<T, SIZE> Type; 01280 typedef TinyVector<typename NumericTraits<T>::Promote, SIZE> Promote; 01281 typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> RealPromote; 01282 typedef TinyVector<typename NumericTraits<T>::ComplexPromote, SIZE> ComplexPromote; 01283 typedef T ValueType; 01284 01285 typedef typename NumericTraits<T>::isIntegral isIntegral; 01286 typedef VigraFalseType isScalar; 01287 typedef typename NumericTraits<T>::isSigned isSigned; 01288 typedef VigraFalseType isOrdered; 01289 typedef VigraFalseType isComplex; 01290 }; 01291 01292 template <class T, int SIZE> 01293 struct NormTraits<TinyVector<T, SIZE> > 01294 { 01295 typedef TinyVector<T, SIZE> Type; 01296 typedef typename Type::SquaredNormType SquaredNormType; 01297 typedef typename Type::NormType NormType; 01298 }; 01299 01300 template <class T, int SIZE> 01301 struct NormTraits<TinyVectorView<T, SIZE> > 01302 { 01303 typedef TinyVector<T, SIZE> Type; 01304 typedef typename Type::SquaredNormType SquaredNormType; 01305 typedef typename Type::NormType NormType; 01306 }; 01307 01308 template <class T1, class T2, int SIZE> 01309 struct PromoteTraits<TinyVector<T1, SIZE>, TinyVector<T2, SIZE> > 01310 { 01311 typedef TinyVector<typename PromoteTraits<T1, T2>::Promote, SIZE> Promote; 01312 }; 01313 01314 template <class T1, class T2, int SIZE> 01315 struct PromoteTraits<TinyVectorView<T1, SIZE>, TinyVectorView<T2, SIZE> > 01316 { 01317 typedef TinyVector<typename PromoteTraits<T1, T2>::Promote, SIZE> Promote; 01318 }; 01319 01320 template <class T1, class T2, int SIZE> 01321 struct PromoteTraits<TinyVectorView<T1, SIZE>, TinyVector<T2, SIZE> > 01322 { 01323 typedef TinyVector<typename PromoteTraits<T1, T2>::Promote, SIZE> Promote; 01324 }; 01325 01326 template <class T1, class T2, int SIZE> 01327 struct PromoteTraits<TinyVector<T1, SIZE>, TinyVectorView<T2, SIZE> > 01328 { 01329 typedef TinyVector<typename PromoteTraits<T1, T2>::Promote, SIZE> Promote; 01330 }; 01331 01332 template <class T, int SIZE> 01333 struct PromoteTraits<TinyVector<T, SIZE>, double > 01334 { 01335 typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> Promote; 01336 }; 01337 01338 template <class T, int SIZE> 01339 struct PromoteTraits<double, TinyVector<T, SIZE> > 01340 { 01341 typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> Promote; 01342 }; 01343 01344 template <class T, int SIZE> 01345 struct PromoteTraits<TinyVectorView<T, SIZE>, double > 01346 { 01347 typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> Promote; 01348 }; 01349 01350 template <class T, int SIZE> 01351 struct PromoteTraits<double, TinyVectorView<T, SIZE> > 01352 { 01353 typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> Promote; 01354 }; 01355 01356 template<class T, int SIZE> 01357 struct CanSkipInitialization<TinyVectorView<T, SIZE> > 01358 { 01359 typedef typename CanSkipInitialization<T>::type type; 01360 static const bool value = type::asBool; 01361 }; 01362 01363 template<class T, int SIZE> 01364 struct CanSkipInitialization<TinyVector<T, SIZE> > 01365 { 01366 typedef typename CanSkipInitialization<T>::type type; 01367 static const bool value = type::asBool; 01368 }; 01369 01370 01371 01372 #else // NO_PARTIAL_TEMPLATE_SPECIALIZATION 01373 01374 01375 #define TINYVECTOR_NUMTRAITS(T, SIZE) \ 01376 template<>\ 01377 struct NumericTraits<TinyVector<T, SIZE> >\ 01378 {\ 01379 typedef TinyVector<T, SIZE> Type;\ 01380 typedef TinyVector<NumericTraits<T>::Promote, SIZE> Promote;\ 01381 typedef TinyVector<NumericTraits<T>::RealPromote, SIZE> RealPromote;\ 01382 typedef TinyVector<NumericTraits<T>::ComplexPromote, SIZE> ComplexPromote;\ 01383 typedef T ValueType; \ 01384 typedef NumericTraits<T>::isIntegral isIntegral;\ 01385 typedef VigraFalseType isScalar;\ 01386 typedef NumericTraits<T>::isSigned isSigned; \ 01387 typedef VigraFalseType isOrdered;\ 01388 typedef VigraFalseType isComplex;\ 01389 \ 01390 static TinyVector<T, SIZE> zero() { \ 01391 return TinyVector<T, SIZE>(NumericTraits<T>::zero()); \ 01392 }\ 01393 static TinyVector<T, SIZE> one() { \ 01394 return TinyVector<T, SIZE>(NumericTraits<T>::one()); \ 01395 }\ 01396 static TinyVector<T, SIZE> nonZero() { \ 01397 return TinyVector<T, SIZE>(NumericTraits<T>::nonZero()); \ 01398 }\ 01399 \ 01400 static Promote toPromote(TinyVector<T, SIZE> const & v) { \ 01401 return Promote(v); \ 01402 }\ 01403 static RealPromote toRealPromote(TinyVector<T, SIZE> const & v) { \ 01404 return RealPromote(v); \ 01405 }\ 01406 static TinyVector<T, SIZE> fromPromote(Promote const & v) { \ 01407 TinyVector<T, SIZE> res;\ 01408 TinyVector<T, SIZE>::iterator d = res.begin(), dend = res.end();\ 01409 Promote::const_iterator s = v.begin();\ 01410 for(; d != dend; ++d, ++s)\ 01411 *d = NumericTraits<T>::fromPromote(*s);\ 01412 return res;\ 01413 }\ 01414 static TinyVector<T, SIZE> fromRealPromote(RealPromote const & v) {\ 01415 TinyVector<T, SIZE> res;\ 01416 TinyVector<T, SIZE>::iterator d = res.begin(), dend = res.end();\ 01417 RealPromote::const_iterator s = v.begin();\ 01418 for(; d != dend; ++d, ++s)\ 01419 *d = NumericTraits<T>::fromRealPromote(*s);\ 01420 return res;\ 01421 }\ 01422 }; \ 01423 template<>\ 01424 struct NormTraits<TinyVector<T, SIZE> >\ 01425 {\ 01426 typedef TinyVector<T, SIZE> Type;\ 01427 typedef Type::SquaredNormType SquaredNormType; \ 01428 typedef Type::NormType NormType; \ 01429 }; 01430 01431 #define TINYVECTOR_PROMTRAITS1(type1, SIZE) \ 01432 template<> \ 01433 struct PromoteTraits<TinyVector<type1, SIZE>, TinyVector<type1, SIZE> > \ 01434 { \ 01435 typedef TinyVector<PromoteTraits<type1, type1>::Promote, SIZE> Promote; \ 01436 static Promote toPromote(TinyVector<type1, SIZE> const & v) { \ 01437 return static_cast<Promote>(v); } \ 01438 }; 01439 01440 #define TINYVECTOR_PROMTRAITS2(type1, type2, SIZE) \ 01441 template<> \ 01442 struct PromoteTraits<TinyVector<type1, SIZE>, TinyVector<type2, SIZE> > \ 01443 { \ 01444 typedef TinyVector<PromoteTraits<type1, type2>::Promote, SIZE> Promote; \ 01445 static Promote toPromote(TinyVector<type1, SIZE> const & v) { \ 01446 return static_cast<Promote>(v); } \ 01447 static Promote toPromote(TinyVector<type2, SIZE> const & v) { \ 01448 return static_cast<Promote>(v); } \ 01449 }; 01450 01451 #define TINYVECTOR_TRAITS(SIZE) \ 01452 TINYVECTOR_NUMTRAITS(unsigned char, SIZE)\ 01453 TINYVECTOR_NUMTRAITS(int, SIZE)\ 01454 TINYVECTOR_NUMTRAITS(float, SIZE)\ 01455 TINYVECTOR_NUMTRAITS(double, SIZE)\ 01456 TINYVECTOR_PROMTRAITS1(unsigned char, SIZE)\ 01457 TINYVECTOR_PROMTRAITS1(int, SIZE)\ 01458 TINYVECTOR_PROMTRAITS1(float, SIZE)\ 01459 TINYVECTOR_PROMTRAITS1(double, SIZE)\ 01460 TINYVECTOR_PROMTRAITS2(float, unsigned char, SIZE)\ 01461 TINYVECTOR_PROMTRAITS2(unsigned char, float, SIZE)\ 01462 TINYVECTOR_PROMTRAITS2(int, unsigned char, SIZE)\ 01463 TINYVECTOR_PROMTRAITS2(unsigned char, int, SIZE)\ 01464 TINYVECTOR_PROMTRAITS2(int, float, SIZE)\ 01465 TINYVECTOR_PROMTRAITS2(float, int, SIZE)\ 01466 TINYVECTOR_PROMTRAITS2(double, unsigned char, SIZE)\ 01467 TINYVECTOR_PROMTRAITS2(unsigned char, double, SIZE)\ 01468 TINYVECTOR_PROMTRAITS2(int, double, SIZE)\ 01469 TINYVECTOR_PROMTRAITS2(double, int, SIZE)\ 01470 TINYVECTOR_PROMTRAITS2(double, float, SIZE)\ 01471 TINYVECTOR_PROMTRAITS2(float, double, SIZE) 01472 01473 TINYVECTOR_TRAITS(2) 01474 TINYVECTOR_TRAITS(3) 01475 TINYVECTOR_TRAITS(4) 01476 01477 #undef TINYVECTOR_NUMTRAITS 01478 #undef TINYVECTOR_PROMTRAITS1 01479 #undef TINYVECTOR_PROMTRAITS2 01480 #undef TINYVECTOR_TRAITS 01481 01482 #endif // NO_PARTIAL_TEMPLATE_SPECIALIZATION 01483 01484 01485 /********************************************************/ 01486 /* */ 01487 /* TinyVector-Arithmetic */ 01488 /* */ 01489 /********************************************************/ 01490 01491 /** \addtogroup TinyVectorOperators 01492 */ 01493 //@{ 01494 01495 /// component-wise addition 01496 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4> 01497 inline 01498 typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2, SIZE> >::Promote 01499 operator+(TinyVectorBase<V1, SIZE, D1, D2> const & l, 01500 TinyVectorBase<V2, SIZE, D3, D4> const & r) 01501 { 01502 return typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2 , SIZE> >::Promote(l) += r; 01503 } 01504 01505 /// component-wise subtraction 01506 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4> 01507 inline 01508 typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2, SIZE> >::Promote 01509 operator-(TinyVectorBase<V1, SIZE, D1, D2> const & l, 01510 TinyVectorBase<V2, SIZE, D3, D4> const & r) 01511 { 01512 return typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2 , SIZE> >::Promote(l) -= r; 01513 } 01514 01515 /// component-wise multiplication 01516 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4> 01517 inline 01518 typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2, SIZE> >::Promote 01519 operator*(TinyVectorBase<V1, SIZE, D1, D2> const & l, 01520 TinyVectorBase<V2, SIZE, D3, D4> const & r) 01521 { 01522 return typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2 , SIZE> >::Promote(l) *= r; 01523 } 01524 01525 /// component-wise division 01526 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4> 01527 inline 01528 typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2, SIZE> >::Promote 01529 operator/(TinyVectorBase<V1, SIZE, D1, D2> const & l, 01530 TinyVectorBase<V2, SIZE, D3, D4> const & r) 01531 { 01532 return typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2 , SIZE> >::Promote(l) /= r; 01533 } 01534 01535 /// component-wise left scalar multiplication 01536 template <class V, int SIZE, class D1, class D2> 01537 inline 01538 typename NumericTraits<TinyVector<V, SIZE> >::RealPromote 01539 operator*(double v, TinyVectorBase<V, SIZE, D1, D2> const & r) 01540 { 01541 return typename NumericTraits<TinyVector<V, SIZE> >::RealPromote(r) *= v; 01542 } 01543 01544 /// component-wise right scalar multiplication 01545 template <class V, int SIZE, class D1, class D2> 01546 inline 01547 typename NumericTraits<TinyVector<V, SIZE> >::RealPromote 01548 operator*(TinyVectorBase<V, SIZE, D1, D2> const & l, double v) 01549 { 01550 return typename NumericTraits<TinyVector<V, SIZE> >::RealPromote(l) *= v; 01551 } 01552 01553 /// component-wise scalar division 01554 template <class V, int SIZE, class D1, class D2> 01555 inline 01556 typename NumericTraits<TinyVector<V, SIZE> >::RealPromote 01557 operator/(TinyVectorBase<V, SIZE, D1, D2> const & l, double v) 01558 { 01559 return typename NumericTraits<TinyVector<V, SIZE> >::RealPromote(l) /= v; 01560 } 01561 01562 /// component-wise scalar division without type promotion 01563 template <class V, int SIZE, class D1, class D2> 01564 inline 01565 TinyVector<V, SIZE> 01566 div(TinyVectorBase<V, SIZE, D1, D2> const & l, V v) 01567 { 01568 TinyVector<V, SIZE> result(l); 01569 typedef typename detail::LoopType<SIZE>::type Loop; 01570 Loop::divScalar(result.data(), v); 01571 return result; 01572 } 01573 01574 01575 /** Unary negation (construct TinyVector with negative values) 01576 */ 01577 template <class V, int SIZE, class D1, class D2> 01578 inline 01579 TinyVector<V, SIZE> 01580 operator-(TinyVectorBase<V, SIZE, D1, D2> const & v) 01581 { 01582 TinyVector<V, SIZE> res(detail::dontInit()); 01583 typedef typename detail::LoopType<SIZE>::type ltype; 01584 ltype::neg(res.begin(), v.begin()); 01585 return res; 01586 } 01587 01588 /// component-wise absolute value 01589 template <class V, int SIZE, class D1, class D2> 01590 inline 01591 TinyVector<V, SIZE> 01592 abs(TinyVectorBase<V, SIZE, D1, D2> const & v) 01593 { 01594 TinyVector<V, SIZE> res(detail::dontInit()); 01595 typedef typename detail::LoopType<SIZE>::type ltype; 01596 ltype::abs(res.begin(), v.begin()); 01597 return res; 01598 } 01599 01600 /** Apply ceil() function to each vector component. 01601 */ 01602 template <class V, int SIZE, class D1, class D2> 01603 inline 01604 TinyVector<V, SIZE> 01605 ceil(TinyVectorBase<V, SIZE, D1, D2> const & v) 01606 { 01607 TinyVector<V, SIZE> res(detail::dontInit()); 01608 typedef typename detail::LoopType<SIZE>::type ltype; 01609 ltype::ceil(res.begin(), v.begin()); 01610 return res; 01611 } 01612 01613 /** Apply floor() function to each vector component. 01614 */ 01615 template <class V, int SIZE, class D1, class D2> 01616 inline 01617 TinyVector<V, SIZE> 01618 floor(TinyVectorBase<V, SIZE, D1, D2> const & v) 01619 { 01620 TinyVector<V, SIZE> res(detail::dontInit()); 01621 typedef typename detail::LoopType<SIZE>::type ltype; 01622 ltype::floor(res.begin(), v.begin()); 01623 return res; 01624 } 01625 01626 /** Apply sqrt() function to each vector component. 01627 */ 01628 template <class V, int SIZE, class D1, class D2> 01629 inline 01630 TinyVector<V, SIZE> 01631 sqrt(TinyVectorBase<V, SIZE, D1, D2> const & v) 01632 { 01633 TinyVector<V, SIZE> res(detail::dontInit()); 01634 typedef typename detail::LoopType<SIZE>::type ltype; 01635 ltype::sqrt(res.begin(), v.begin()); 01636 return res; 01637 } 01638 01639 using std::pow; 01640 01641 /** Apply pow() function to each vector component. 01642 */ 01643 template <class V, int SIZE, class D1, class D2, class E> 01644 inline 01645 TinyVector<V, SIZE> 01646 pow(TinyVectorBase<V, SIZE, D1, D2> const & v, E exponent) 01647 { 01648 TinyVector<V, SIZE> res(v); 01649 typedef typename detail::LoopType<SIZE>::type ltype; 01650 ltype::power(res.begin(), exponent); 01651 return res; 01652 } 01653 01654 /// cross product 01655 template <class V1, class D1, class D2, class V2, class D3, class D4> 01656 inline 01657 TinyVector<typename PromoteTraits<V1, V2>::Promote, 3> 01658 cross(TinyVectorBase<V1, 3, D1, D2> const & r1, 01659 TinyVectorBase<V2, 3, D3, D4> const & r2) 01660 { 01661 typedef TinyVector<typename PromoteTraits<V1, V2>::Promote, 3> 01662 Res; 01663 return Res(r1[1]*r2[2] - r1[2]*r2[1], 01664 r1[2]*r2[0] - r1[0]*r2[2], 01665 r1[0]*r2[1] - r1[1]*r2[0]); 01666 } 01667 01668 /// dot product 01669 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4> 01670 inline 01671 typename PromoteTraits<V1, V2>::Promote 01672 dot(TinyVectorBase<V1, SIZE, D1, D2> const & l, 01673 TinyVectorBase<V2, SIZE, D3, D4> const & r) 01674 { 01675 typedef typename detail::LoopType<SIZE>::type ltype; 01676 return ltype::dot(l.begin(), r.begin()); 01677 } 01678 01679 /// sum of the vector's elements 01680 template <class V, int SIZE, class D1, class D2> 01681 inline 01682 typename NumericTraits<V>::Promote 01683 sum(TinyVectorBase<V, SIZE, D1, D2> const & l) 01684 { 01685 typename NumericTraits<V>::Promote res = l[0]; 01686 for(int k=1; k<SIZE; ++k) 01687 res += l[k]; 01688 return res; 01689 } 01690 01691 /// cumulative sum of the vector's elements 01692 template <class V, int SIZE, class D1, class D2> 01693 inline 01694 TinyVector<typename NumericTraits<V>::Promote, SIZE> 01695 cumsum(TinyVectorBase<V, SIZE, D1, D2> const & l) 01696 { 01697 TinyVector<typename NumericTraits<V>::Promote, SIZE> res(l); 01698 for(int k=1; k<SIZE; ++k) 01699 res[k] += res[k-1]; 01700 return res; 01701 } 01702 01703 /// product of the vector's elements 01704 template <class V, int SIZE, class D1, class D2> 01705 inline 01706 typename NumericTraits<V>::Promote 01707 prod(TinyVectorBase<V, SIZE, D1, D2> const & l) 01708 { 01709 typename NumericTraits<V>::Promote res = l[0]; 01710 for(int k=1; k<SIZE; ++k) 01711 res *= l[k]; 01712 return res; 01713 } 01714 01715 /// cumulative product of the vector's elements 01716 template <class V, int SIZE, class D1, class D2> 01717 inline 01718 TinyVector<typename NumericTraits<V>::Promote, SIZE> 01719 cumprod(TinyVectorBase<V, SIZE, D1, D2> const & l) 01720 { 01721 TinyVector<typename NumericTraits<V>::Promote, SIZE> res(l); 01722 for(int k=1; k<SIZE; ++k) 01723 res[k] *= res[k-1]; 01724 return res; 01725 } 01726 01727 using std::min; 01728 01729 /// element-wise minimum 01730 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4> 01731 inline 01732 TinyVector<typename PromoteTraits<V1, V2>::Promote, SIZE> 01733 min(TinyVectorBase<V1, SIZE, D1, D2> const & l, 01734 TinyVectorBase<V2, SIZE, D3, D4> const & r) 01735 { 01736 typedef typename detail::LoopType<SIZE>::type ltype; 01737 TinyVector<typename PromoteTraits<V1, V2>::Promote, SIZE> res(l); 01738 ltype::min(res.begin(), r.begin()); 01739 return res; 01740 } 01741 01742 // we also have to overload min for like-typed argument to prevent match of std::min() 01743 template <class V1, int SIZE, class D1, class D2> 01744 inline 01745 TinyVector<V1, SIZE> 01746 min(TinyVectorBase<V1, SIZE, D1, D2> const & l, 01747 TinyVectorBase<V1, SIZE, D1, D2> const & r) 01748 { 01749 typedef typename detail::LoopType<SIZE>::type ltype; 01750 TinyVector<V1, SIZE> res(l); 01751 ltype::min(res.begin(), r.begin()); 01752 return res; 01753 } 01754 01755 template <class V1, int SIZE> 01756 inline 01757 TinyVector<V1, SIZE> 01758 min(TinyVector<V1, SIZE> const & l, 01759 TinyVector<V1, SIZE> const & r) 01760 { 01761 typedef typename detail::LoopType<SIZE>::type ltype; 01762 TinyVector<V1, SIZE> res(l); 01763 ltype::min(res.begin(), r.begin()); 01764 return res; 01765 } 01766 01767 /// minimum element 01768 template <class V, int SIZE, class D1, class D2> 01769 inline 01770 V const & 01771 min(TinyVectorBase<V, SIZE, D1, D2> const & l) 01772 { 01773 return l.minimum(); 01774 } 01775 01776 using std::max; 01777 01778 /// element-wise maximum 01779 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4> 01780 inline 01781 TinyVector<typename PromoteTraits<V1, V2>::Promote, SIZE> 01782 max(TinyVectorBase<V1, SIZE, D1, D2> const & l, 01783 TinyVectorBase<V2, SIZE, D3, D4> const & r) 01784 { 01785 typedef typename detail::LoopType<SIZE>::type ltype; 01786 TinyVector<typename PromoteTraits<V1, V2>::Promote, SIZE> res(l); 01787 ltype::max(res.begin(), r.begin()); 01788 return res; 01789 } 01790 01791 // we also have to overload max for like-typed argument to prevent match of std::max() 01792 template <class V1, int SIZE, class D1, class D2> 01793 inline 01794 TinyVector<V1, SIZE> 01795 max(TinyVectorBase<V1, SIZE, D1, D2> const & l, 01796 TinyVectorBase<V1, SIZE, D1, D2> const & r) 01797 { 01798 typedef typename detail::LoopType<SIZE>::type ltype; 01799 TinyVector<V1, SIZE> res(l); 01800 ltype::max(res.begin(), r.begin()); 01801 return res; 01802 } 01803 01804 template <class V1, int SIZE> 01805 inline 01806 TinyVector<V1, SIZE> 01807 max(TinyVector<V1, SIZE> const & l, 01808 TinyVector<V1, SIZE> const & r) 01809 { 01810 typedef typename detail::LoopType<SIZE>::type ltype; 01811 TinyVector<V1, SIZE> res(l); 01812 ltype::max(res.begin(), r.begin()); 01813 return res; 01814 } 01815 01816 /// maximum element 01817 template <class V, int SIZE, class D1, class D2> 01818 inline 01819 V const & 01820 max(TinyVectorBase<V, SIZE, D1, D2> const & l) 01821 { 01822 return l.maximum(); 01823 } 01824 01825 /// squared norm 01826 template <class V1, int SIZE, class D1, class D2> 01827 inline 01828 typename TinyVectorBase<V1, SIZE, D1, D2>::SquaredNormType 01829 squaredNorm(TinyVectorBase<V1, SIZE, D1, D2> const & t) 01830 { 01831 return t.squaredMagnitude(); 01832 } 01833 01834 /// squared norm 01835 template <class V, int SIZE> 01836 inline 01837 typename TinyVector<V, SIZE>::SquaredNormType 01838 squaredNorm(TinyVector<V, SIZE> const & t) 01839 { 01840 return t.squaredMagnitude(); 01841 } 01842 //@} 01843 01844 // mask cl.exe shortcomings [end] 01845 #if defined(_MSC_VER) 01846 #pragma warning( pop ) 01847 #endif 01848 01849 } // namespace vigra 01850 #undef VIGRA_ASSERT_INSIDE 01851 #endif // VIGRA_TINYVECTOR_HXX
© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de) |
html generated using doxygen and Python
|