[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]

tinyvector.hxx
1 /************************************************************************/
2 /* */
3 /* Copyright 1998-2002 by Ullrich Koethe */
4 /* */
5 /* This file is part of the VIGRA computer vision library. */
6 /* The VIGRA Website is */
7 /* http://hci.iwr.uni-heidelberg.de/vigra/ */
8 /* Please direct questions, bug reports, and contributions to */
9 /* ullrich.koethe@iwr.uni-heidelberg.de or */
10 /* vigra@informatik.uni-hamburg.de */
11 /* */
12 /* Permission is hereby granted, free of charge, to any person */
13 /* obtaining a copy of this software and associated documentation */
14 /* files (the "Software"), to deal in the Software without */
15 /* restriction, including without limitation the rights to use, */
16 /* copy, modify, merge, publish, distribute, sublicense, and/or */
17 /* sell copies of the Software, and to permit persons to whom the */
18 /* Software is furnished to do so, subject to the following */
19 /* conditions: */
20 /* */
21 /* The above copyright notice and this permission notice shall be */
22 /* included in all copies or substantial portions of the */
23 /* Software. */
24 /* */
25 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
26 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
27 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
28 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
29 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
30 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
31 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
32 /* OTHER DEALINGS IN THE SOFTWARE. */
33 /* */
34 /************************************************************************/
35 
36 
37 #ifndef VIGRA_TINYVECTOR_HXX
38 #define VIGRA_TINYVECTOR_HXX
39 
40 #include <cmath> // abs(double)
41 #include <cstdlib> // abs(int)
42 #include <iosfwd> // ostream
43 #include <algorithm>
44 #include "config.hxx"
45 #include "error.hxx"
46 #include "metaprogramming.hxx"
47 #include "numerictraits.hxx"
48 #include "memory.hxx"
49 #include "mathutil.hxx"
50 #include "diff2d.hxx"
51 
52 #ifdef VIGRA_CHECK_BOUNDS
53 #define VIGRA_ASSERT_INSIDE(diff) \
54  vigra_precondition(diff >= 0, "Index out of bounds");\
55  vigra_precondition(diff < SIZE, "Index out of bounds");
56 #else
57 #define VIGRA_ASSERT_INSIDE(diff)
58 #endif
59 
60 namespace vigra {
61 
62 // mask cl.exe shortcomings [begin]
63 #if defined(_MSC_VER)
64 #pragma warning( push )
65 #pragma warning( disable : 4503 )
66 #endif
67 
68 using VIGRA_CSTD::abs;
69 using VIGRA_CSTD::ceil;
70 using VIGRA_CSTD::floor;
71 using VIGRA_CSTD::sqrt;
72 
73 
74 template <class V1, int SIZE, class D1, class D2>
76 
77 template <class V1, int SIZE, class D1, class D2>
78 inline
81 
82 
83 namespace detail {
84 
85 #define VIGRA_EXEC_LOOP(NAME, OPER) \
86  template <class T1, class T2> \
87  static void NAME(T1 * left, T2 const * right) \
88  { \
89  for(int i=0; i<LEVEL; ++i) \
90  (left[i]) OPER (right[i]); \
91  }
92 
93 #define VIGRA_EXEC_LOOP_MINMAX(NAME, OPER) \
94  template <class T1, class T2> \
95  static void NAME(T1 * left, T2 const * right) \
96  { \
97  for(int i=0; i<LEVEL; ++i) \
98  if(left[i] OPER right[i]) \
99  left[i] = right[i]; \
100  }
101 
102 #define VIGRA_EXEC_LOOP_SCALAR(NAME, OPER) \
103  template <class T1, class T2> \
104  static void NAME(T1 * left, T2 right) \
105  { \
106  for(int i=0; i<LEVEL; ++i) \
107  (left[i]) = detail::RequiresExplicitCast<T1>::cast((left[i]) OPER (right)); \
108  }
109 
110 template <int LEVEL>
111 struct ExecLoop
112 {
113  template <class T1, class T2>
114  static void assignCast(T1 * left, T2 const * right)
115  {
116  for(int i=0; i<LEVEL; ++i)
117  left[i] = detail::RequiresExplicitCast<T1>::cast(right[i]);
118  }
119 
120  template <class T1, class T2>
121  static void reverseAssign(T1 * left, T2 const * right)
122  {
123  for(int i=0; i<LEVEL; ++i)
124  left[i] = right[-i];
125  }
126 
127  template <class T1, class T2>
128  static void assignScalar(T1 * left, T2 right)
129  {
130  for(int i=0; i<LEVEL; ++i)
131  left[i] = detail::RequiresExplicitCast<T1>::cast(right);
132  }
133 
134  template <class T1, class T2>
135  static void power(T1 * left, T2 right)
136  {
137  for(int i=0; i<LEVEL; ++i)
138  left[i] = detail::RequiresExplicitCast<T1>::cast(pow(left, right));
139  }
140 
141  VIGRA_EXEC_LOOP(assign, =)
142  VIGRA_EXEC_LOOP(add, +=)
143  VIGRA_EXEC_LOOP(sub, -=)
144  VIGRA_EXEC_LOOP(mul, *=)
145  VIGRA_EXEC_LOOP(div, /=)
146  VIGRA_EXEC_LOOP(neg, = -)
147  VIGRA_EXEC_LOOP(abs, = vigra::abs)
148  VIGRA_EXEC_LOOP(floor, = vigra::floor)
149  VIGRA_EXEC_LOOP(ceil, = vigra::ceil)
150  VIGRA_EXEC_LOOP(sqrt, = vigra::sqrt)
151  VIGRA_EXEC_LOOP(fromPromote, = NumericTraits<T1>::fromPromote)
152  VIGRA_EXEC_LOOP(fromRealPromote, = NumericTraits<T1>::fromRealPromote)
153  VIGRA_EXEC_LOOP_SCALAR(mulScalar, *)
154  VIGRA_EXEC_LOOP_SCALAR(divScalar, /)
155 
156  VIGRA_EXEC_LOOP_MINMAX(min, >)
157  VIGRA_EXEC_LOOP_MINMAX(max, <)
158 
159  template <class T>
160  static T const & minimum(T const * p)
161  {
162  return *std::min_element(p, p+LEVEL);
163  }
164 
165  template <class T>
166  static T const & maximum(T const * p)
167  {
168  return *std::max_element(p, p+LEVEL);
169  }
170 
171  template <class T1, class T2>
172  static bool notEqual(T1 const * left, T2 const * right)
173  {
174  for(int i=0; i<LEVEL; ++i)
175  if(left[i] != right[i])
176  return true;
177  return false;
178  }
179 
180  template <class T1, class T2>
181  static bool less(T1 const * left, T2 const * right)
182  {
183  for(int i=0; i<LEVEL; ++i)
184  {
185  if(left[i] < right[i])
186  return true;
187  if(right[i] < left[i])
188  return false;
189  }
190  return false;
191  }
192  template <class T>
193  static typename NumericTraits<T>::Promote
194  dot(T const * d)
195  {
196  typename NumericTraits<T>::Promote res(*d * *d);
197  for(int i=1; i<LEVEL; ++i)
198  res += d[i] * d[i];
199  return res;
200  }
201 
202  template <class T1, class T2>
203  static typename PromoteTraits<T1, T2>::Promote
204  dot(T1 const * left, T2 const * right)
205  {
206  typename PromoteTraits<T1, T2>::Promote res(*left * *right);
207  for(int i=1; i<LEVEL; ++i)
208  res += left[i] * right[i];
209  return res;
210  }
211 
212  template <class T>
213  static typename NormTraits<T>::SquaredNormType
214  squaredNorm(T const * d)
215  {
216  typename NormTraits<T>::SquaredNormType res = vigra::squaredNorm(*d);
217  for(int i=1; i<LEVEL; ++i)
218  res += vigra::squaredNorm(d[i]);
219  return res;
220  }
221 };
222 
223 template <int LEVEL>
224 struct UnrollScalarResult
225 {
226  template <class T>
227  static typename NumericTraits<T>::Promote
228  dot(T const * d)
229  {
230  return *d * *d + UnrollScalarResult<LEVEL-1>::dot(d+1);
231  }
232 
233  template <class T1, class T2>
234  static typename PromoteTraits<T1, T2>::Promote
235  dot(T1 const * left, T2 const * right)
236  {
237  return *left * *right + UnrollScalarResult<LEVEL-1>::dot(left+1, right+1);
238  }
239 
240  template <class T>
241  static typename NormTraits<T>::SquaredNormType
242  squaredNorm(T const * d)
243  {
245  }
246 
247  static std::ptrdiff_t
248  squaredNorm(std::ptrdiff_t const * d)
249  {
250  return (*d)*(*d) + UnrollScalarResult<LEVEL-1>::squaredNorm(d+1);
251  }
252 
253  template <class T>
254  static T const & minimum(T const * p)
255  {
256  T const & m = UnrollScalarResult<LEVEL - 1>::minimum(p+1);
257  return *p < m
258  ? *p
259  : m;
260  }
261 
262  template <class T>
263  static T const & maximum(T const * p)
264  {
265  T const & m = UnrollScalarResult<LEVEL - 1>::maximum(p+1);
266  return *p > m
267  ? *p
268  : m;
269  }
270 };
271 
272 template <>
273 struct UnrollScalarResult<1>
274 {
275  template <class T>
276  static typename NumericTraits<T>::Promote
277  dot(T const * d)
278  {
279  return *d * *d ;
280  }
281 
282  template <class T1, class T2>
283  static typename PromoteTraits<T1, T2>::Promote
284  dot(T1 const * left, T2 const * right)
285  {
286  return *left * *right;
287  }
288 
289  template <class T>
290  static typename NormTraits<T>::SquaredNormType
291  squaredNorm(T const * d)
292  {
293  return vigra::squaredNorm(*d);
294  }
295 
296  static std::ptrdiff_t
297  squaredNorm(std::ptrdiff_t const * d)
298  {
299  return (*d)*(*d);
300  }
301 
302  template <class T>
303  static T const & minimum(T const * p)
304  {
305  return *p;
306  }
307 
308  template <class T>
309  static T const & maximum(T const * p)
310  {
311  return *p;
312  }
313 };
314 
315 #undef VIGRA_EXEC_LOOP
316 #undef VIGRA_EXEC_LOOP_MINMAX
317 #undef VIGRA_EXEC_LOOP_SCALAR
318 
319 #define VIGRA_UNROLL_LOOP(NAME, OPER) \
320  template <class T1, class T2> \
321  static void NAME(T1 * left, T2 const * right) \
322  { \
323  (*left) OPER (*right); \
324  UnrollLoop<LEVEL-1>::NAME(left+1, right+1); \
325  }
326 
327 #define VIGRA_UNROLL_LOOP_MINMAX(NAME, OPER) \
328  template <class T1, class T2> \
329  static void NAME(T1 * left, T2 const * right) \
330  { \
331  if(*left OPER *right) \
332  *left = *right; \
333  UnrollLoop<LEVEL-1>::NAME(left+1, right+1); \
334  }
335 
336 #define VIGRA_UNROLL_LOOP_SCALAR(NAME, OPER) \
337  template <class T1, class T2> \
338  static void NAME(T1 * left, T2 right) \
339  { \
340  (*left) = detail::RequiresExplicitCast<T1>::cast((*left) OPER (right)); \
341  UnrollLoop<LEVEL-1>::NAME(left+1, right); \
342  }
343 
344 
345 template <int LEVEL>
346 struct UnrollLoop
347 {
348  template <class T1, class T2>
349  static void reverseAssign(T1 * left, T2 const * right)
350  {
351  *left = *right;
352  UnrollLoop<LEVEL-1>::reverseAssign(left+1, right-1);
353  }
354 
355  template <class T1, class T2>
356  static void assignCast(T1 * left, T2 const * right)
357  {
358  *left = detail::RequiresExplicitCast<T1>::cast(*right);
359  UnrollLoop<LEVEL-1>::assignCast(left+1, right+1);
360  }
361 
362  template <class T1, class T2>
363  static void assignScalar(T1 * left, T2 right)
364  {
365  *left = detail::RequiresExplicitCast<T1>::cast(right);
366  UnrollLoop<LEVEL-1>::assignScalar(left+1, right);
367  }
368 
369  template <class T1, class T2>
370  static void power(T1 * left, T2 right)
371  {
372  *left = detail::RequiresExplicitCast<T1>::cast(pow(*left, right));
373  UnrollLoop<LEVEL-1>::power(left+1, right);
374  }
375 
376  VIGRA_UNROLL_LOOP(assign, =)
377  VIGRA_UNROLL_LOOP(add, +=)
378  VIGRA_UNROLL_LOOP(sub, -=)
379  VIGRA_UNROLL_LOOP(mul, *=)
380  VIGRA_UNROLL_LOOP(div, /=)
381  VIGRA_UNROLL_LOOP(neg, = -)
382  VIGRA_UNROLL_LOOP(abs, = vigra::abs)
383  VIGRA_UNROLL_LOOP(floor, = vigra::floor)
384  VIGRA_UNROLL_LOOP(ceil, = vigra::ceil)
385  VIGRA_UNROLL_LOOP(sqrt, = vigra::sqrt)
386  VIGRA_UNROLL_LOOP(fromPromote, = NumericTraits<T1>::fromPromote)
387  VIGRA_UNROLL_LOOP(fromRealPromote, = NumericTraits<T1>::fromRealPromote)
388  VIGRA_UNROLL_LOOP_SCALAR(mulScalar, *)
389  VIGRA_UNROLL_LOOP_SCALAR(divScalar, /)
390 
391  VIGRA_UNROLL_LOOP_MINMAX(min, >)
392  VIGRA_UNROLL_LOOP_MINMAX(max, <)
393 
394  template <class T>
395  static T const & minimum(T const * p)
396  {
397  return UnrollScalarResult<LEVEL>::minimum(p);
398  }
399 
400  template <class T>
401  static T const & maximum(T const * p)
402  {
403  return UnrollScalarResult<LEVEL>::maximum(p);
404  }
405 
406  template <class T1, class T2>
407  static bool notEqual(T1 const * left, T2 const * right)
408  {
409  return (*left != *right) || UnrollLoop<LEVEL - 1>::notEqual(left+1, right+1);
410  }
411 
412  template <class T1, class T2>
413  static bool less(T1 const * left, T2 const * right)
414  {
415  if(*left < *right)
416  return true;
417  if(*right < *left)
418  return false;
419  return UnrollLoop<LEVEL - 1>::less(left+1, right+1);
420  }
421 
422  template <class T>
423  static typename NumericTraits<T>::Promote
424  dot(T const * d)
425  {
427  }
428 
429  template <class T1, class T2>
430  static typename PromoteTraits<T1, T2>::Promote
431  dot(T1 const * left, T2 const * right)
432  {
433  return UnrollScalarResult<LEVEL>::dot(left, right);
434  }
435 
436  template <class T>
437  static typename NormTraits<T>::SquaredNormType
438  squaredNorm(T const * d)
439  {
441  }
442 };
443 
444 #undef VIGRA_UNROLL_LOOP
445 #undef VIGRA_UNROLL_LOOP_MINMAX
446 #undef VIGRA_UNROLL_LOOP_SCALAR
447 
448 template <>
449 struct UnrollLoop<0>
450 {
451  template <class T1, class T2>
452  static void reverseAssign(T1, T2) {}
453  template <class T1, class T2>
454  static void assignCast(T1, T2) {}
455  template <class T1, class T2>
456  static void assign(T1, T2) {}
457  template <class T1, class T2>
458  static void assignScalar(T1, T2) {}
459  template <class T1, class T2>
460  static void power(T1, T2) {}
461  template <class T1, class T2>
462  static void add(T1, T2) {}
463  template <class T1, class T2>
464  static void sub(T1, T2) {}
465  template <class T1, class T2>
466  static void mul(T1, T2) {}
467  template <class T1, class T2>
468  static void mulScalar(T1, T2) {}
469  template <class T1, class T2>
470  static void div(T1, T2) {}
471  template <class T1, class T2>
472  static void divScalar(T1, T2) {}
473  template <class T1, class T2>
474  static void fromPromote(T1, T2) {}
475  template <class T1, class T2>
476  static void fromRealPromote(T1, T2) {}
477  template <class T1, class T2>
478  static void neg(T1, T2) {}
479  template <class T1, class T2>
480  static void abs(T1, T2) {}
481  template <class T1, class T2>
482  static void floor(T1, T2) {}
483  template <class T1, class T2>
484  static void ceil(T1, T2) {}
485  template <class T1, class T2>
486  static void sqrt(T1, T2) {}
487  template <class T1, class T2>
488  static bool notEqual(T1, T2) { return false; }
489  template <class T1, class T2>
490  static bool less(T1, T2) { return false; }
491  template <class T1, class T2>
492  static void min(T1, T2) {}
493  template <class T1, class T2>
494  static void max(T1, T2) {}
495  template <class T>
496  static T minimum(T const * p)
497  {
498  return NumericTraits<T>::max();
499  }
500  template <class T>
501  static T maximum(T const * p)
502  {
503  return NumericTraits<T>::min();
504  }
505 };
506 
507 template <int SIZE>
508 struct LoopType
509 {
510  typedef typename IfBool<(SIZE <= 5), UnrollLoop<SIZE>, ExecLoop<SIZE> >::type type;
511 
512 };
513 
514 struct DontInit {};
515 
516 inline DontInit dontInit() {return DontInit(); }
517 
518 } // namespace detail
519 
520 template <class T, int SIZE>
521 class TinyVector;
522 
523 template <class T, int SIZE>
525 
526 /********************************************************/
527 /* */
528 /* TinyVectorBase */
529 /* */
530 /********************************************************/
531 
532 /** \brief Base class for fixed size vectors.
533 
534  This class contains functionality shared by
535  \ref TinyVector and \ref TinyVectorView, and enables these classes
536  to be freely mixed within expressions. It is typically not used directly.
537 
538  <b>\#include</b> <vigra/tinyvector.hxx><br>
539  Namespace: vigra
540 **/
541 template <class VALUETYPE, int SIZE, class DATA, class DERIVED>
542 class TinyVectorBase
543 {
544  TinyVectorBase(TinyVectorBase const &); // do not use
545 
546  TinyVectorBase & operator=(TinyVectorBase const & other); // do not use
547 
548  protected:
549 
550  typedef typename detail::LoopType<SIZE>::type Loop;
551 
553  {}
554 
555  public:
556  /** STL-compatible definition of valuetype
557  */
558  typedef VALUETYPE value_type;
559 
560  /** reference (return of operator[]).
561  */
562  typedef VALUETYPE & reference;
563 
564  /** const reference (return of operator[] const).
565  */
566  typedef VALUETYPE const & const_reference;
567 
568  /** pointer (return of operator->).
569  */
570  typedef VALUETYPE * pointer;
571 
572  /** const pointer (return of operator-> const).
573  */
574  typedef VALUETYPE const * const_pointer;
575 
576  /** STL-compatible definition of iterator
577  */
578  typedef value_type * iterator;
579 
580  /** STL-compatible definition of const iterator
581  */
582  typedef value_type const * const_iterator;
583 
584  /** STL-compatible definition of size_type
585  */
586  typedef unsigned int size_type;
587 
588  /** STL-compatible definition of difference_type
589  */
590  typedef std::ptrdiff_t difference_type;
591 
592  /** the scalar type for the outer product
593  */
594  typedef double scalar_multiplier;
595 
596  /** the vector's squared norm type
597  */
598  typedef typename NormTraits<VALUETYPE>::SquaredNormType SquaredNormType;
599 
600  /** the vector's norm type
601  */
602  typedef typename SquareRootTraits<SquaredNormType>::SquareRootResult NormType;
603 
604  /** the vector's size
605  */
606  enum { static_size = SIZE };
607 
608  /** Initialize from another sequence (must have length SIZE!)
609  */
610  template <class Iterator>
611  void init(Iterator i, Iterator end)
612  {
613  vigra_precondition(end-i == SIZE,
614  "TinyVector::init(): Sequence has wrong size.");
615  Loop::assignCast(data_, i);
616  }
617 
618  /** Initialize with constant value
619  */
620  void init(value_type initial)
621  {
622  Loop::assignScalar(data_, initial);
623  }
624 
625  /** Component-wise add-assignment
626  */
627  template <class T1, class D1, class D2>
629  {
630  Loop::add(data_, r.begin());
631  return static_cast<DERIVED &>(*this);
632  }
633 
634  /** Component-wise subtract-assignment
635  */
636  template <class T1, class D1, class D2>
638  {
639  Loop::sub(data_, r.begin());
640  return static_cast<DERIVED &>(*this);
641  }
642 
643  /** Component-wise multiply-assignment
644  */
645  template <class T1, class D1, class D2>
647  {
648  Loop::mul(data_, r.begin());
649  return static_cast<DERIVED &>(*this);
650  }
651 
652  /** Component-wise divide-assignment
653  */
654  template <class T1, class D1, class D2>
656  {
657  Loop::div(data_, r.begin());
658  return static_cast<DERIVED &>(*this);
659  }
660 
661  /** Component-wise scalar multiply-assignment
662  */
663  DERIVED & operator*=(double r)
664  {
665  Loop::mulScalar(data_, r);
666  return static_cast<DERIVED &>(*this);
667  }
668 
669  /** Component-wise scalar divide-assignment
670  */
671  DERIVED & operator/=(double r)
672  {
673  Loop::divScalar(data_, r);
674  return static_cast<DERIVED &>(*this);
675  }
676 
677  /** Calculate magnitude.
678  */
680  {
681  return sqrt(static_cast<typename
682  SquareRootTraits<SquaredNormType>::SquareRootArgument>(squaredMagnitude()));
683  }
684 
685  /** Calculate squared magnitude.
686  */
688  {
689  return Loop::squaredNorm(data_);
690  }
691 
692  /** Return the minimal element.
693  */
694  VALUETYPE const & minimum() const
695  {
696  return Loop::minimum(data_);
697  }
698 
699  /** Return the maximal element.
700  */
701  VALUETYPE const & maximum() const
702  {
703  return Loop::maximum(data_);
704  }
705 
706  /** Access component by index.
707  */
709  {
710  VIGRA_ASSERT_INSIDE(i);
711  return data_[i];
712  }
713 
714  /** Get component by index.
715  */
717  {
718  VIGRA_ASSERT_INSIDE(i);
719  return data_[i];
720  }
721 
722  /** Get random access iterator to begin of vector.
723  */
724  iterator begin() { return data_; }
725  /** Get random access iterator past-the-end of vector.
726  */
727  iterator end() { return data_ + SIZE; }
728 
729  /** Get const random access iterator to begin of vector.
730  */
731  const_iterator begin() const { return data_; }
732 
733  /** Get const random access iterator past-the-end of vector.
734  */
735  const_iterator end() const { return data_ + SIZE; }
736 
737  /** Size of TinyVector vector always equals the template parameter SIZE.
738  */
739  size_type size() const { return SIZE; }
740 
741  pointer data() { return data_; }
742 
743  const_pointer data() const { return data_; }
744 
745  protected:
746 
747  DATA data_;
748 };
749 
750 /** \brief Class for fixed size vectors.
751  \ingroup RangesAndPoints
752 
753  This class contains an array of size SIZE of the specified VALUETYPE.
754  The interface conforms to STL vector, except that there are no functions
755  that change the size of a TinyVector.
756 
757  \ref TinyVectorOperators "Arithmetic operations"
758  on TinyVectors are defined as component-wise applications of these
759  operations. Addition and subtraction of two TinyVectors
760  (+=, -=, +, -, unary -), multiplication and division of an
761  TinyVector with a double, and NumericTraits/PromoteTraits are defined,
762  so that TinyVector fulfills the requirements of \ref LinearAlgebraConcept "Linear Algebra".
763 
764  VIGRA algorithms typically use \ref vigra::VectorAccessor to access
765  TinyVectors as a whole, or specific components of them.
766 
767  See also:<br>
768  <UL style="list-style-image:url(documents/bullet.gif)">
769  <LI> \ref vigra::TinyVectorBase
770  <LI> \ref vigra::TinyVectorView
771  <LI> \ref TinyVectorTraits
772  <LI> \ref TinyVectorOperators
773  </UL>
774 
775  <b>\#include</b> <vigra/tinyvector.hxx><br>
776  Namespace: vigra
777 **/
778 template <class T, int SIZE>
779 class TinyVector
780 : public TinyVectorBase<T, SIZE, T[SIZE], TinyVector<T, SIZE> >
781 {
782  typedef TinyVectorBase<T, SIZE, T[SIZE], TinyVector<T, SIZE> > BaseType;
783  typedef typename BaseType::Loop Loop;
784 
785  public:
786 
787  typedef typename BaseType::value_type value_type;
788  typedef typename BaseType::reference reference;
789  typedef typename BaseType::const_reference const_reference;
790  typedef typename BaseType::pointer pointer;
791  typedef typename BaseType::const_pointer const_pointer;
792  typedef typename BaseType::iterator iterator;
793  typedef typename BaseType::const_iterator const_iterator;
794  typedef typename BaseType::size_type size_type;
795  typedef typename BaseType::difference_type difference_type;
796  typedef typename BaseType::scalar_multiplier scalar_multiplier;
797  typedef typename BaseType::SquaredNormType SquaredNormType;
798  typedef typename BaseType::NormType NormType;
799 
800  enum ReverseCopyTag { ReverseCopy };
801 
802  /** Construction with constant value.
803 
804  Initializes all vector elements with the given value.
805  */
806  explicit TinyVector(value_type const & initial)
807  : BaseType()
808  {
809  Loop::assignScalar(BaseType::begin(), initial);
810  }
811 
812  /** Construction with Diff2D.
813 
814  Use only when <tt>SIZE == 2</tt>.
815  */
816  explicit TinyVector(Diff2D const & initial)
817  : BaseType()
818  {
819  BaseType::data_[0] = detail::RequiresExplicitCast<T>::cast(initial.x);
820  BaseType::data_[1] = detail::RequiresExplicitCast<T>::cast(initial.y);
821  }
822 
823  /** Construction with explicit values.
824  Call only if SIZE == 2
825  */
826  TinyVector(value_type const & i1, value_type const & i2)
827  : BaseType()
828  {
829  BaseType::data_[0] = i1;
830  BaseType::data_[1] = i2;
831  }
832 
833  /** Construction with explicit values.
834  Call only if SIZE == 3
835  */
836  TinyVector(value_type const & i1, value_type const & i2, value_type const & i3)
837  : BaseType()
838  {
839  BaseType::data_[0] = i1;
840  BaseType::data_[1] = i2;
841  BaseType::data_[2] = i3;
842  }
843 
844  /** Construction with explicit values.
845  Call only if SIZE == 4
846  */
847  TinyVector(value_type const & i1, value_type const & i2,
848  value_type const & i3, value_type const & i4)
849  : BaseType()
850  {
851  BaseType::data_[0] = i1;
852  BaseType::data_[1] = i2;
853  BaseType::data_[2] = i3;
854  BaseType::data_[3] = i4;
855  }
856 
857  /** Construction with explicit values.
858  Call only if SIZE == 5
859  */
860  TinyVector(value_type const & i1, value_type const & i2,
861  value_type const & i3, value_type const & i4,
862  value_type const & i5)
863  : BaseType()
864  {
865  BaseType::data_[0] = i1;
866  BaseType::data_[1] = i2;
867  BaseType::data_[2] = i3;
868  BaseType::data_[3] = i4;
869  BaseType::data_[4] = i5;
870  }
871 
872  /** Default constructor (initializes all elements with zero).
873  */
875  : BaseType()
876  {
877  Loop::assignScalar(BaseType::data_, NumericTraits<value_type>::zero());
878  }
879 
880  /** Construct without initializing the vector elements.
881  */
882  explicit TinyVector(SkipInitializationTag)
883  : BaseType()
884  {}
885 
886  explicit TinyVector(detail::DontInit)
887  : BaseType()
888  {}
889 
890  /** Copy constructor.
891  */
893  : BaseType()
894  {
895  Loop::assign(BaseType::data_, r.data_);
896  }
897 
898  /** Constructor from C array.
899  */
900  explicit TinyVector(const_pointer data)
901  : BaseType()
902  {
903  Loop::assign(BaseType::data_, data);
904  }
905 
906  /** Constructor by reverse copy from C array.
907 
908  Usage:
909  \code
910  TinyVector<int, 3> v(1,2,3);
911  TinyVector<int, 3> reverse(v.begin(), TinyVector<int, 3>::ReverseCopy);
912  \endcode
913  */
914  explicit TinyVector(const_pointer data, ReverseCopyTag)
915  : BaseType()
916  {
917  Loop::reverseAssign(BaseType::data_, data+SIZE-1);
918  }
919 
920  /** Copy with type conversion.
921  */
922  template <class U, class DATA, class DERIVED>
924  : BaseType()
925  {
926  Loop::assignCast(BaseType::data_, r.begin());
927  }
928 
929  /** Copy assignment.
930  */
932  {
933  Loop::assign(BaseType::data_, r.data_);
934  return *this;
935  }
936 
937  /** Copy assignment with type conversion.
938  */
939  template <class U, class DATA, class DERIVED>
941  {
942  Loop::assignCast(BaseType::data_, r.begin());
943  return *this;
944  }
945 
946  /** Assignment from Diff2D.
947 
948  Use only when <tt>SIZE == 2</tt>.
949  */
951  {
952  BaseType::data_[0] = detail::RequiresExplicitCast<T>::cast(r.x);
953  BaseType::data_[1] = detail::RequiresExplicitCast<T>::cast(r.y);
954  return *this;
955  }
956 
957  /** Assignment from scalar. Will set all entries to the given value.
958  */
959  TinyVector & operator=(value_type const & v)
960  {
961  Loop::assignScalar(BaseType::begin(), v);
962  return *this;
963  }
964 
965  /** Copy from a TinyVector with a different number of elements.
966 
967  Only the first <tt>min(SIZE, USIZE)</tt> elements are copied.
968  */
969  template <class U, int USIZE, class DATA, class DERIVED>
971  {
972  static const int minSize = USIZE < SIZE
973  ? USIZE
974  : SIZE;
975 
976  typedef typename detail::LoopType<minSize>::type MinLoop;
977  MinLoop::assignCast(BaseType::data_, r.begin());
978  return *this;
979  }
980 };
981 
982 /** \brief Wrapper for fixed size vectors.
983 
984  This class wraps an array of size SIZE of the specified VALUETYPE.
985  Thus, the array can be accessed with an interface similar to
986  that of std::vector (except that there are no functions
987  that change the size of a TinyVectorView). The TinyVectorView
988  does <em>not</em> assume ownership of the given memory.
989 
990  \ref TinyVectorOperators "Arithmetic operations"
991  on TinyVectorViews are defined as component-wise applications of these
992  operations. Addition and subtraction of two TinyVectorViews
993  (+=, -=, +, -, unary -), multiplication and division of an
994  TinyVectorViews with a double, and NumericTraits/PromoteTraits are defined,
995  so that TinyVectorView fulfills the requirements of \ref LinearAlgebraConcept "Linear Algebra".
996 
997  VIGRA algorithms typically use \ref vigra::VectorAccessor to access
998  TinyVectorViews as a whole, or specific components of them.
999 
1000  <b>See also:</b>
1001  <ul>
1002  <li> \ref vigra::TinyVectorBase
1003  <li> \ref vigra::TinyVector
1004  <li> \ref TinyVectorTraits
1005  <li> \ref TinyVectorOperators
1006  </ul>
1007 
1008  <b>\#include</b> <vigra/tinyvector.hxx><br>
1009  Namespace: vigra
1010 **/
1011 template <class T, int SIZE>
1012 class TinyVectorView
1013 : public TinyVectorBase<T, SIZE, T *, TinyVectorView<T, SIZE> >
1014 {
1015  typedef TinyVectorBase<T, SIZE, T *, TinyVectorView<T, SIZE> > BaseType;
1016  typedef typename BaseType::Loop Loop;
1017 
1018  public:
1019 
1020  typedef typename BaseType::value_type value_type;
1021  typedef typename BaseType::reference reference;
1022  typedef typename BaseType::const_reference const_reference;
1023  typedef typename BaseType::pointer pointer;
1024  typedef typename BaseType::const_pointer const_pointer;
1025  typedef typename BaseType::iterator iterator;
1026  typedef typename BaseType::const_iterator const_iterator;
1027  typedef typename BaseType::size_type size_type;
1028  typedef typename BaseType::difference_type difference_type;
1029  typedef typename BaseType::scalar_multiplier scalar_multiplier;
1030  typedef typename BaseType::SquaredNormType SquaredNormType;
1031  typedef typename BaseType::NormType NormType;
1032 
1033  /** Default constructor
1034  (pointer to wrapped data is NULL).
1035  */
1037  : BaseType()
1038  {
1039  BaseType::data_ = 0;
1040  }
1041 
1042  /** Construct view for given data array
1043  */
1044  TinyVectorView(const_pointer data)
1045  : BaseType()
1046  {
1047  BaseType::data_ = const_cast<pointer>(data);
1048  }
1049 
1050  /** Copy constructor (shallow copy).
1051  */
1053  : BaseType()
1054  {
1055  BaseType::data_ = const_cast<pointer>(other.data_);
1056  }
1057 
1058  /** Construct view from other TinyVector.
1059  */
1060  template <class DATA, class DERIVED>
1062  : BaseType()
1063  {
1064  BaseType::data_ = const_cast<pointer>(other.data());
1065  }
1066 
1067  /** Copy the data (not the pointer) of the rhs.
1068  */
1070  {
1071  Loop::assign(BaseType::data_, r.begin());
1072  return *this;
1073  }
1074 
1075  /** Copy the data of the rhs with cast.
1076  */
1077  template <class U, class DATA, class DERIVED>
1079  {
1080  Loop::assignCast(BaseType::data_, r.begin());
1081  return *this;
1082  }
1083 };
1084 
1085 /********************************************************/
1086 /* */
1087 /* TinyVector Comparison */
1088 /* */
1089 /********************************************************/
1090 
1091 /** \addtogroup TinyVectorOperators Functions for TinyVector
1092 
1093  \brief Implement basic arithmetic and equality for TinyVector.
1094 
1095  These functions fulfill the requirements of a Linear Space (vector space).
1096  Return types are determined according to \ref TinyVectorTraits.
1097 
1098  <b>\#include</b> <vigra/tinyvector.hxx><br>
1099  Namespace: vigra
1100 */
1101 //@{
1102  /// component-wise equal
1103 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
1104 inline bool
1107 {
1108  return !(l != r);
1109 }
1110 
1111  /// component-wise not equal
1112 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
1113 inline bool
1116 {
1117  typedef typename detail::LoopType<SIZE>::type ltype;
1118  return ltype::notEqual(l.begin(), r.begin());
1119 }
1120 
1121  /// component-wise lexicographical comparison
1122 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
1123 inline bool
1124 operator<(TinyVectorBase<V1, SIZE, D1, D2> const & l,
1126 {
1127  typedef typename detail::LoopType<SIZE>::type ltype;
1128  return ltype::less(l.begin(), r.begin());
1129 }
1130 
1131 /********************************************************/
1132 /* */
1133 /* TinyVector Output */
1134 /* */
1135 /********************************************************/
1136 
1137  /// stream output
1138 template <class V1, int SIZE, class DATA, class DERIVED>
1139 std::ostream &
1140 operator<<(std::ostream & out, TinyVectorBase<V1, SIZE, DATA, DERIVED> const & l)
1141 {
1142  out << "(";
1143  int i;
1144  for(i=0; i<SIZE-1; ++i)
1145  out << l[i] << ", ";
1146  out << l[i] << ")";
1147  return out;
1148 }
1149 //@}
1150 
1151 /********************************************************/
1152 /* */
1153 /* TinyVector-Traits */
1154 /* */
1155 /********************************************************/
1156 
1157 /** \page TinyVectorTraits Numeric and Promote Traits of TinyVector
1158  The numeric and promote traits for TinyVectors follow
1159  the general specifications for \ref NumericPromotionTraits.
1160  They are implemented in terms of the traits of the basic types by
1161  partial template specialization:
1162 
1163  \code
1164 
1165  template <class T, int SIZE>
1166  struct NumericTraits<TinyVector<T, SIZE> >
1167  {
1168  typedef TinyVector<typename NumericTraits<T>::Promote, SIZE> Promote;
1169  typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> RealPromote;
1170 
1171  typedef typename NumericTraits<T>::isIntegral isIntegral;
1172  typedef VigraFalseType isScalar;
1173  typedef typename NumericTraits<T>::isSigned isSigned;
1174 
1175  // etc.
1176  };
1177 
1178  template <class T, int SIZE>
1179  struct NormTraits<TinyVector<T, SIZE> >
1180  {
1181  typedef TinyVector<T, SIZE> Type;
1182  typedef typename Type::SquaredNormType SquaredNormType;
1183  typedef typename Type::NormType NormType;
1184  };
1185 
1186  template <class T1, class T2, SIZE>
1187  struct PromoteTraits<TinyVector<T1, SIZE>, TinyVector<T2, SIZE> >
1188  {
1189  typedef TinyVector<typename PromoteTraits<T1, T2>::Promote, SIZE> Promote;
1190  };
1191  \endcode
1192 
1193  <b>\#include</b> <vigra/tinyvector.hxx><br>
1194  Namespace: vigra
1195 
1196  On compilers that don't support partial template specialization (e.g.
1197  MS VisualC++), the traits classes are explicitly specialized for
1198  <TT>TinyVector<VALUETYPE, SIZE></TT> with
1199  <TT>VALUETYPE = unsigned char | int | float | double</TT> and <TT>SIZE = 2 | 3 | 4</TT>.
1200 
1201 */
1202 
1203 #if !defined(NO_PARTIAL_TEMPLATE_SPECIALIZATION)
1204 
1205 template <class T, int SIZE>
1206 struct NumericTraits<TinyVector<T, SIZE> >
1207 {
1208  typedef TinyVector<T, SIZE> Type;
1209  typedef TinyVector<typename NumericTraits<T>::Promote, SIZE> Promote;
1210  typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> RealPromote;
1211  typedef TinyVector<typename NumericTraits<T>::ComplexPromote, SIZE> ComplexPromote;
1212  typedef T ValueType;
1213 
1214  typedef typename NumericTraits<T>::isIntegral isIntegral;
1215  typedef VigraFalseType isScalar;
1216  typedef typename NumericTraits<T>::isSigned isSigned;
1217  typedef VigraTrueType isOrdered;
1218  typedef VigraFalseType isComplex;
1219 
1220  static TinyVector<T, SIZE> zero()
1221  {
1222  return TinyVector<T, SIZE>(NumericTraits<T>::zero());
1223  }
1224  static TinyVector<T, SIZE> one()
1225  {
1226  return TinyVector<T, SIZE>(NumericTraits<T>::one());
1227  }
1228  static TinyVector<T, SIZE> nonZero()
1229  {
1230  return TinyVector<T, SIZE>(NumericTraits<T>::nonZero());
1231  }
1232 
1233  static TinyVector<T, SIZE> min()
1234  {
1235  return TinyVector<T, SIZE>(NumericTraits<T>::min());
1236  }
1237  static TinyVector<T, SIZE> max()
1238  {
1239  return TinyVector<T, SIZE>(NumericTraits<T>::max());
1240  }
1241 
1242  template <class D1, class D2>
1243  static Promote toPromote(TinyVectorBase<T, SIZE, D1, D2> const & v)
1244  {
1245  return Promote(v);
1246  }
1247 
1248  template <class D1, class D2>
1249  static RealPromote toRealPromote(TinyVectorBase<T, SIZE, D1, D2> const & v)
1250  {
1251  return RealPromote(v);
1252  }
1253 
1254  template <class D1, class D2>
1255  static TinyVector<T, SIZE>
1256  fromPromote(TinyVectorBase<typename NumericTraits<T>::Promote, SIZE, D1, D2> const & v)
1257  {
1258  TinyVector<T, SIZE> res(detail::dontInit());
1259  typedef typename detail::LoopType<SIZE>::type ltype;
1260  ltype::fromPromote(res.begin(), v.begin());
1261  return res;
1262  }
1263 
1264  template <class D1, class D2>
1265  static TinyVector<T, SIZE>
1266  fromRealPromote(TinyVectorBase<typename NumericTraits<T>::RealPromote, SIZE, D1, D2> const & v)
1267  {
1268  TinyVector<T, SIZE> res(detail::dontInit());
1269  typedef typename detail::LoopType<SIZE>::type ltype;
1270  ltype::fromRealPromote(res.begin(), v.begin());
1271  return res;
1272  }
1273 };
1274 
1275 template <class T, int SIZE>
1276 struct NumericTraits<TinyVectorView<T, SIZE> >
1277 : public NumericTraits<TinyVector<T, SIZE> >
1278 {
1279  typedef TinyVector<T, SIZE> Type;
1280  typedef TinyVector<typename NumericTraits<T>::Promote, SIZE> Promote;
1281  typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> RealPromote;
1282  typedef TinyVector<typename NumericTraits<T>::ComplexPromote, SIZE> ComplexPromote;
1283  typedef T ValueType;
1284 
1285  typedef typename NumericTraits<T>::isIntegral isIntegral;
1286  typedef VigraFalseType isScalar;
1287  typedef typename NumericTraits<T>::isSigned isSigned;
1288  typedef VigraFalseType isOrdered;
1289  typedef VigraFalseType isComplex;
1290 };
1291 
1292 template <class T, int SIZE>
1293 struct NormTraits<TinyVector<T, SIZE> >
1294 {
1295  typedef TinyVector<T, SIZE> Type;
1296  typedef typename Type::SquaredNormType SquaredNormType;
1297  typedef typename Type::NormType NormType;
1298 };
1299 
1300 template <class T, int SIZE>
1301 struct NormTraits<TinyVectorView<T, SIZE> >
1302 {
1303  typedef TinyVector<T, SIZE> Type;
1304  typedef typename Type::SquaredNormType SquaredNormType;
1305  typedef typename Type::NormType NormType;
1306 };
1307 
1308 template <class T1, class T2, int SIZE>
1309 struct PromoteTraits<TinyVector<T1, SIZE>, TinyVector<T2, SIZE> >
1310 {
1311  typedef TinyVector<typename PromoteTraits<T1, T2>::Promote, SIZE> Promote;
1312 };
1313 
1314 template <class T1, class T2, int SIZE>
1315 struct PromoteTraits<TinyVectorView<T1, SIZE>, TinyVectorView<T2, SIZE> >
1316 {
1317  typedef TinyVector<typename PromoteTraits<T1, T2>::Promote, SIZE> Promote;
1318 };
1319 
1320 template <class T1, class T2, int SIZE>
1321 struct PromoteTraits<TinyVectorView<T1, SIZE>, TinyVector<T2, SIZE> >
1322 {
1323  typedef TinyVector<typename PromoteTraits<T1, T2>::Promote, SIZE> Promote;
1324 };
1325 
1326 template <class T1, class T2, int SIZE>
1327 struct PromoteTraits<TinyVector<T1, SIZE>, TinyVectorView<T2, SIZE> >
1328 {
1329  typedef TinyVector<typename PromoteTraits<T1, T2>::Promote, SIZE> Promote;
1330 };
1331 
1332 template <class T, int SIZE>
1333 struct PromoteTraits<TinyVector<T, SIZE>, double >
1334 {
1335  typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> Promote;
1336 };
1337 
1338 template <class T, int SIZE>
1339 struct PromoteTraits<double, TinyVector<T, SIZE> >
1340 {
1341  typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> Promote;
1342 };
1343 
1344 template <class T, int SIZE>
1345 struct PromoteTraits<TinyVectorView<T, SIZE>, double >
1346 {
1347  typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> Promote;
1348 };
1349 
1350 template <class T, int SIZE>
1351 struct PromoteTraits<double, TinyVectorView<T, SIZE> >
1352 {
1353  typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> Promote;
1354 };
1355 
1356 template<class T, int SIZE>
1357 struct CanSkipInitialization<TinyVectorView<T, SIZE> >
1358 {
1359  typedef typename CanSkipInitialization<T>::type type;
1360  static const bool value = type::asBool;
1361 };
1362 
1363 template<class T, int SIZE>
1364 struct CanSkipInitialization<TinyVector<T, SIZE> >
1365 {
1366  typedef typename CanSkipInitialization<T>::type type;
1367  static const bool value = type::asBool;
1368 };
1369 
1370 
1371 
1372 #else // NO_PARTIAL_TEMPLATE_SPECIALIZATION
1373 
1374 
1375 #define TINYVECTOR_NUMTRAITS(T, SIZE) \
1376 template<>\
1377 struct NumericTraits<TinyVector<T, SIZE> >\
1378 {\
1379  typedef TinyVector<T, SIZE> Type;\
1380  typedef TinyVector<NumericTraits<T>::Promote, SIZE> Promote;\
1381  typedef TinyVector<NumericTraits<T>::RealPromote, SIZE> RealPromote;\
1382  typedef TinyVector<NumericTraits<T>::ComplexPromote, SIZE> ComplexPromote;\
1383  typedef T ValueType; \
1384  typedef NumericTraits<T>::isIntegral isIntegral;\
1385  typedef VigraFalseType isScalar;\
1386  typedef NumericTraits<T>::isSigned isSigned; \
1387  typedef VigraFalseType isOrdered;\
1388  typedef VigraFalseType isComplex;\
1389  \
1390  static TinyVector<T, SIZE> zero() { \
1391  return TinyVector<T, SIZE>(NumericTraits<T>::zero()); \
1392  }\
1393  static TinyVector<T, SIZE> one() { \
1394  return TinyVector<T, SIZE>(NumericTraits<T>::one()); \
1395  }\
1396  static TinyVector<T, SIZE> nonZero() { \
1397  return TinyVector<T, SIZE>(NumericTraits<T>::nonZero()); \
1398  }\
1399  \
1400  static Promote toPromote(TinyVector<T, SIZE> const & v) { \
1401  return Promote(v); \
1402  }\
1403  static RealPromote toRealPromote(TinyVector<T, SIZE> const & v) { \
1404  return RealPromote(v); \
1405  }\
1406  static TinyVector<T, SIZE> fromPromote(Promote const & v) { \
1407  TinyVector<T, SIZE> res;\
1408  TinyVector<T, SIZE>::iterator d = res.begin(), dend = res.end();\
1409  Promote::const_iterator s = v.begin();\
1410  for(; d != dend; ++d, ++s)\
1411  *d = NumericTraits<T>::fromPromote(*s);\
1412  return res;\
1413  }\
1414  static TinyVector<T, SIZE> fromRealPromote(RealPromote const & v) {\
1415  TinyVector<T, SIZE> res;\
1416  TinyVector<T, SIZE>::iterator d = res.begin(), dend = res.end();\
1417  RealPromote::const_iterator s = v.begin();\
1418  for(; d != dend; ++d, ++s)\
1419  *d = NumericTraits<T>::fromRealPromote(*s);\
1420  return res;\
1421  }\
1422 }; \
1423 template<>\
1424 struct NormTraits<TinyVector<T, SIZE> >\
1425 {\
1426  typedef TinyVector<T, SIZE> Type;\
1427  typedef Type::SquaredNormType SquaredNormType; \
1428  typedef Type::NormType NormType; \
1429 };
1430 
1431 #define TINYVECTOR_PROMTRAITS1(type1, SIZE) \
1432 template<> \
1433 struct PromoteTraits<TinyVector<type1, SIZE>, TinyVector<type1, SIZE> > \
1434 { \
1435  typedef TinyVector<PromoteTraits<type1, type1>::Promote, SIZE> Promote; \
1436  static Promote toPromote(TinyVector<type1, SIZE> const & v) { \
1437  return static_cast<Promote>(v); } \
1438 };
1439 
1440 #define TINYVECTOR_PROMTRAITS2(type1, type2, SIZE) \
1441 template<> \
1442 struct PromoteTraits<TinyVector<type1, SIZE>, TinyVector<type2, SIZE> > \
1443 { \
1444  typedef TinyVector<PromoteTraits<type1, type2>::Promote, SIZE> Promote; \
1445  static Promote toPromote(TinyVector<type1, SIZE> const & v) { \
1446  return static_cast<Promote>(v); } \
1447  static Promote toPromote(TinyVector<type2, SIZE> const & v) { \
1448  return static_cast<Promote>(v); } \
1449 };
1450 
1451 #define TINYVECTOR_TRAITS(SIZE) \
1452 TINYVECTOR_NUMTRAITS(unsigned char, SIZE)\
1453 TINYVECTOR_NUMTRAITS(int, SIZE)\
1454 TINYVECTOR_NUMTRAITS(float, SIZE)\
1455 TINYVECTOR_NUMTRAITS(double, SIZE)\
1456 TINYVECTOR_PROMTRAITS1(unsigned char, SIZE)\
1457 TINYVECTOR_PROMTRAITS1(int, SIZE)\
1458 TINYVECTOR_PROMTRAITS1(float, SIZE)\
1459 TINYVECTOR_PROMTRAITS1(double, SIZE)\
1460 TINYVECTOR_PROMTRAITS2(float, unsigned char, SIZE)\
1461 TINYVECTOR_PROMTRAITS2(unsigned char, float, SIZE)\
1462 TINYVECTOR_PROMTRAITS2(int, unsigned char, SIZE)\
1463 TINYVECTOR_PROMTRAITS2(unsigned char, int, SIZE)\
1464 TINYVECTOR_PROMTRAITS2(int, float, SIZE)\
1465 TINYVECTOR_PROMTRAITS2(float, int, SIZE)\
1466 TINYVECTOR_PROMTRAITS2(double, unsigned char, SIZE)\
1467 TINYVECTOR_PROMTRAITS2(unsigned char, double, SIZE)\
1468 TINYVECTOR_PROMTRAITS2(int, double, SIZE)\
1469 TINYVECTOR_PROMTRAITS2(double, int, SIZE)\
1470 TINYVECTOR_PROMTRAITS2(double, float, SIZE)\
1471 TINYVECTOR_PROMTRAITS2(float, double, SIZE)
1472 
1473 TINYVECTOR_TRAITS(2)
1474 TINYVECTOR_TRAITS(3)
1475 TINYVECTOR_TRAITS(4)
1476 
1477 #undef TINYVECTOR_NUMTRAITS
1478 #undef TINYVECTOR_PROMTRAITS1
1479 #undef TINYVECTOR_PROMTRAITS2
1480 #undef TINYVECTOR_TRAITS
1481 
1482 #endif // NO_PARTIAL_TEMPLATE_SPECIALIZATION
1483 
1484 
1485 /********************************************************/
1486 /* */
1487 /* TinyVector-Arithmetic */
1488 /* */
1489 /********************************************************/
1490 
1491 /** \addtogroup TinyVectorOperators
1492  */
1493 //@{
1494 
1495  /// component-wise addition
1496 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
1497 inline
1498 typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2, SIZE> >::Promote
1501 {
1502  return typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2 , SIZE> >::Promote(l) += r;
1503 }
1504 
1505  /// component-wise subtraction
1506 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
1507 inline
1508 typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2, SIZE> >::Promote
1511 {
1512  return typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2 , SIZE> >::Promote(l) -= r;
1513 }
1514 
1515  /// component-wise multiplication
1516 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
1517 inline
1518 typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2, SIZE> >::Promote
1521 {
1522  return typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2 , SIZE> >::Promote(l) *= r;
1523 }
1524 
1525  /// component-wise division
1526 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
1527 inline
1528 typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2, SIZE> >::Promote
1531 {
1532  return typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2 , SIZE> >::Promote(l) /= r;
1533 }
1534 
1535  /// component-wise left scalar multiplication
1536 template <class V, int SIZE, class D1, class D2>
1537 inline
1538 typename NumericTraits<TinyVector<V, SIZE> >::RealPromote
1539 operator*(double v, TinyVectorBase<V, SIZE, D1, D2> const & r)
1540 {
1541  return typename NumericTraits<TinyVector<V, SIZE> >::RealPromote(r) *= v;
1542 }
1543 
1544  /// component-wise right scalar multiplication
1545 template <class V, int SIZE, class D1, class D2>
1546 inline
1547 typename NumericTraits<TinyVector<V, SIZE> >::RealPromote
1548 operator*(TinyVectorBase<V, SIZE, D1, D2> const & l, double v)
1549 {
1550  return typename NumericTraits<TinyVector<V, SIZE> >::RealPromote(l) *= v;
1551 }
1552 
1553  /// component-wise scalar division
1554 template <class V, int SIZE, class D1, class D2>
1555 inline
1556 typename NumericTraits<TinyVector<V, SIZE> >::RealPromote
1557 operator/(TinyVectorBase<V, SIZE, D1, D2> const & l, double v)
1558 {
1559  return typename NumericTraits<TinyVector<V, SIZE> >::RealPromote(l) /= v;
1560 }
1561 
1562  /// component-wise scalar division without type promotion
1563 template <class V, int SIZE, class D1, class D2>
1564 inline
1565 TinyVector<V, SIZE>
1567 {
1568  TinyVector<V, SIZE> result(l);
1569  typedef typename detail::LoopType<SIZE>::type Loop;
1570  Loop::divScalar(result.data(), v);
1571  return result;
1572 }
1573 
1574 
1575  /** Unary negation (construct TinyVector with negative values)
1576  */
1577 template <class V, int SIZE, class D1, class D2>
1578 inline
1579 TinyVector<V, SIZE>
1581 {
1582  TinyVector<V, SIZE> res(detail::dontInit());
1583  typedef typename detail::LoopType<SIZE>::type ltype;
1584  ltype::neg(res.begin(), v.begin());
1585  return res;
1586 }
1587 
1588  /// component-wise absolute value
1589 template <class V, int SIZE, class D1, class D2>
1590 inline
1591 TinyVector<V, SIZE>
1593 {
1594  TinyVector<V, SIZE> res(detail::dontInit());
1595  typedef typename detail::LoopType<SIZE>::type ltype;
1596  ltype::abs(res.begin(), v.begin());
1597  return res;
1598 }
1599 
1600  /** Apply ceil() function to each vector component.
1601  */
1602 template <class V, int SIZE, class D1, class D2>
1603 inline
1604 TinyVector<V, SIZE>
1606 {
1607  TinyVector<V, SIZE> res(detail::dontInit());
1608  typedef typename detail::LoopType<SIZE>::type ltype;
1609  ltype::ceil(res.begin(), v.begin());
1610  return res;
1611 }
1612 
1613  /** Apply floor() function to each vector component.
1614  */
1615 template <class V, int SIZE, class D1, class D2>
1616 inline
1617 TinyVector<V, SIZE>
1619 {
1620  TinyVector<V, SIZE> res(detail::dontInit());
1621  typedef typename detail::LoopType<SIZE>::type ltype;
1622  ltype::floor(res.begin(), v.begin());
1623  return res;
1624 }
1625 
1626  /** Apply sqrt() function to each vector component.
1627  */
1628 template <class V, int SIZE, class D1, class D2>
1629 inline
1630 TinyVector<V, SIZE>
1632 {
1633  TinyVector<V, SIZE> res(detail::dontInit());
1634  typedef typename detail::LoopType<SIZE>::type ltype;
1635  ltype::sqrt(res.begin(), v.begin());
1636  return res;
1637 }
1638 
1639 using std::pow;
1640 
1641  /** Apply pow() function to each vector component.
1642  */
1643 template <class V, int SIZE, class D1, class D2, class E>
1644 inline
1645 TinyVector<V, SIZE>
1646 pow(TinyVectorBase<V, SIZE, D1, D2> const & v, E exponent)
1647 {
1648  TinyVector<V, SIZE> res(v);
1649  typedef typename detail::LoopType<SIZE>::type ltype;
1650  ltype::power(res.begin(), exponent);
1651  return res;
1652 }
1653 
1654  /// cross product
1655 template <class V1, class D1, class D2, class V2, class D3, class D4>
1656 inline
1657 TinyVector<typename PromoteTraits<V1, V2>::Promote, 3>
1659  TinyVectorBase<V2, 3, D3, D4> const & r2)
1660 {
1662  Res;
1663  return Res(r1[1]*r2[2] - r1[2]*r2[1],
1664  r1[2]*r2[0] - r1[0]*r2[2],
1665  r1[0]*r2[1] - r1[1]*r2[0]);
1666 }
1667 
1668  /// dot product
1669 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
1670 inline
1671 typename PromoteTraits<V1, V2>::Promote
1674 {
1675  typedef typename detail::LoopType<SIZE>::type ltype;
1676  return ltype::dot(l.begin(), r.begin());
1677 }
1678 
1679  /// sum of the vector's elements
1680 template <class V, int SIZE, class D1, class D2>
1681 inline
1682 typename NumericTraits<V>::Promote
1684 {
1685  typename NumericTraits<V>::Promote res = l[0];
1686  for(int k=1; k<SIZE; ++k)
1687  res += l[k];
1688  return res;
1689 }
1690 
1691  /// cumulative sum of the vector's elements
1692 template <class V, int SIZE, class D1, class D2>
1693 inline
1694 TinyVector<typename NumericTraits<V>::Promote, SIZE>
1696 {
1698  for(int k=1; k<SIZE; ++k)
1699  res[k] += res[k-1];
1700  return res;
1701 }
1702 
1703  /// product of the vector's elements
1704 template <class V, int SIZE, class D1, class D2>
1705 inline
1706 typename NumericTraits<V>::Promote
1708 {
1709  typename NumericTraits<V>::Promote res = l[0];
1710  for(int k=1; k<SIZE; ++k)
1711  res *= l[k];
1712  return res;
1713 }
1714 
1715  /// cumulative product of the vector's elements
1716 template <class V, int SIZE, class D1, class D2>
1717 inline
1718 TinyVector<typename NumericTraits<V>::Promote, SIZE>
1720 {
1722  for(int k=1; k<SIZE; ++k)
1723  res[k] *= res[k-1];
1724  return res;
1725 }
1726 
1727 using std::min;
1728 
1729  /// element-wise minimum
1730 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
1731 inline
1732 TinyVector<typename PromoteTraits<V1, V2>::Promote, SIZE>
1735 {
1736  typedef typename detail::LoopType<SIZE>::type ltype;
1738  ltype::min(res.begin(), r.begin());
1739  return res;
1740 }
1741 
1742 // we also have to overload min for like-typed argument to prevent match of std::min()
1743 template <class V1, int SIZE, class D1, class D2>
1744 inline
1745 TinyVector<V1, SIZE>
1746 min(TinyVectorBase<V1, SIZE, D1, D2> const & l,
1747  TinyVectorBase<V1, SIZE, D1, D2> const & r)
1748 {
1749  typedef typename detail::LoopType<SIZE>::type ltype;
1750  TinyVector<V1, SIZE> res(l);
1751  ltype::min(res.begin(), r.begin());
1752  return res;
1753 }
1754 
1755 template <class V1, int SIZE>
1756 inline
1757 TinyVector<V1, SIZE>
1758 min(TinyVector<V1, SIZE> const & l,
1759  TinyVector<V1, SIZE> const & r)
1760 {
1761  typedef typename detail::LoopType<SIZE>::type ltype;
1762  TinyVector<V1, SIZE> res(l);
1763  ltype::min(res.begin(), r.begin());
1764  return res;
1765 }
1766 
1767  /// minimum element
1768 template <class V, int SIZE, class D1, class D2>
1769 inline
1770 V const &
1772 {
1773  return l.minimum();
1774 }
1775 
1776 using std::max;
1777 
1778  /// element-wise maximum
1779 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
1780 inline
1781 TinyVector<typename PromoteTraits<V1, V2>::Promote, SIZE>
1784 {
1785  typedef typename detail::LoopType<SIZE>::type ltype;
1787  ltype::max(res.begin(), r.begin());
1788  return res;
1789 }
1790 
1791 // we also have to overload max for like-typed argument to prevent match of std::max()
1792 template <class V1, int SIZE, class D1, class D2>
1793 inline
1794 TinyVector<V1, SIZE>
1795 max(TinyVectorBase<V1, SIZE, D1, D2> const & l,
1796  TinyVectorBase<V1, SIZE, D1, D2> const & r)
1797 {
1798  typedef typename detail::LoopType<SIZE>::type ltype;
1799  TinyVector<V1, SIZE> res(l);
1800  ltype::max(res.begin(), r.begin());
1801  return res;
1802 }
1803 
1804 template <class V1, int SIZE>
1805 inline
1806 TinyVector<V1, SIZE>
1807 max(TinyVector<V1, SIZE> const & l,
1808  TinyVector<V1, SIZE> const & r)
1809 {
1810  typedef typename detail::LoopType<SIZE>::type ltype;
1811  TinyVector<V1, SIZE> res(l);
1812  ltype::max(res.begin(), r.begin());
1813  return res;
1814 }
1815 
1816  /// maximum element
1817 template <class V, int SIZE, class D1, class D2>
1818 inline
1819 V const &
1821 {
1822  return l.maximum();
1823 }
1824 
1825  /// squared norm
1826 template <class V1, int SIZE, class D1, class D2>
1827 inline
1828 typename TinyVectorBase<V1, SIZE, D1, D2>::SquaredNormType
1830 {
1831  return t.squaredMagnitude();
1832 }
1833 
1834  /// squared norm
1835 template <class V, int SIZE>
1836 inline
1837 typename TinyVector<V, SIZE>::SquaredNormType
1839 {
1840  return t.squaredMagnitude();
1841 }
1842 //@}
1843 
1844 // mask cl.exe shortcomings [end]
1845 #if defined(_MSC_VER)
1846 #pragma warning( pop )
1847 #endif
1848 
1849 } // namespace vigra
1850 #undef VIGRA_ASSERT_INSIDE
1851 #endif // VIGRA_TINYVECTOR_HXX

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de)
Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany

html generated using doxygen and Python
vigra 1.9.0 (Tue Oct 22 2013)