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

tinyvector.hxx VIGRA

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 namespace lemon {
41 
42 struct Invalid;
43 
44 } // namespace lemon
45 
46 #include <cmath> // abs(double)
47 #include <cstdlib> // abs(int)
48 #include <iosfwd> // ostream
49 #include <algorithm>
50 #include "config.hxx"
51 #include "error.hxx"
52 #include "metaprogramming.hxx"
53 #include "numerictraits.hxx"
54 #include "memory.hxx"
55 #include "mathutil.hxx"
56 #include "diff2d.hxx"
57 #include "static_assert.hxx"
58 
59 #ifdef VIGRA_CHECK_BOUNDS
60 #define VIGRA_ASSERT_INSIDE(diff) \
61  vigra_precondition(diff >= 0, "Index out of bounds");\
62  vigra_precondition(diff < SIZE, "Index out of bounds");
63 #else
64 #define VIGRA_ASSERT_INSIDE(diff)
65 #endif
66 
67 namespace vigra {
68 
69 // mask cl.exe shortcomings [begin]
70 #if defined(_MSC_VER)
71 #pragma warning( push )
72 #pragma warning( disable : 4503 )
73 #endif
74 
75 using VIGRA_CSTD::abs;
76 using VIGRA_CSTD::ceil;
77 using VIGRA_CSTD::floor;
78 using VIGRA_CSTD::sqrt;
79 
80 
81 template <class V1, int SIZE, class D1, class D2>
83 
84 template <class V1, int SIZE, class D1, class D2>
85 inline
88 
89 
90 namespace detail {
91 
92 #define VIGRA_EXEC_LOOP(NAME, OPER) \
93  template <class T1, class T2> \
94  static void NAME(T1 * left, T2 const * right) \
95  { \
96  for(int i=0; i<LEVEL; ++i) \
97  (left[i]) OPER (right[i]); \
98  }
99 
100 #define VIGRA_EXEC_LOOP_MINMAX(NAME, OPER) \
101  template <class T1, class T2> \
102  static void NAME(T1 * left, T2 const * right) \
103  { \
104  for(int i=0; i<LEVEL; ++i) \
105  if(left[i] OPER right[i]) \
106  left[i] = right[i]; \
107  }
108 
109 #define VIGRA_EXEC_LOOP_SCALAR(NAME, OPER) \
110  template <class T1, class T2> \
111  static void NAME(T1 * left, T2 right) \
112  { \
113  for(int i=0; i<LEVEL; ++i) \
114  (left[i]) = detail::RequiresExplicitCast<T1>::cast((left[i]) OPER (right)); \
115  }
116 
117 template <int LEVEL>
118 struct ExecLoop
119 {
120  template <class T1, class T2>
121  static void assignCast(T1 * left, T2 const * right)
122  {
123  for(int i=0; i<LEVEL; ++i)
124  left[i] = detail::RequiresExplicitCast<T1>::cast(right[i]);
125  }
126 
127  template <class T1, class T2>
128  static void reverseAssign(T1 * left, T2 const * right)
129  {
130  for(int i=0; i<LEVEL; ++i)
131  left[i] = right[-i];
132  }
133 
134  template <class T1, class T2>
135  static void assignScalar(T1 * left, T2 right)
136  {
137  for(int i=0; i<LEVEL; ++i)
138  left[i] = detail::RequiresExplicitCast<T1>::cast(right);
139  }
140 
141  template <class T1, class T2>
142  static void power(T1 * left, T2 right)
143  {
144  for(int i=0; i<LEVEL; ++i)
145  left[i] = detail::RequiresExplicitCast<T1>::cast(pow(left, right));
146  }
147 
148  VIGRA_EXEC_LOOP(assign, =)
149  VIGRA_EXEC_LOOP(add, +=)
150  VIGRA_EXEC_LOOP(sub, -=)
151  VIGRA_EXEC_LOOP(mul, *=)
152  VIGRA_EXEC_LOOP(div, /=)
153  VIGRA_EXEC_LOOP(mod, %=)
154  VIGRA_EXEC_LOOP(neg, = -)
155  VIGRA_EXEC_LOOP(abs, = vigra::abs)
156  VIGRA_EXEC_LOOP(floor, = vigra::floor)
157  VIGRA_EXEC_LOOP(ceil, = vigra::ceil)
158  VIGRA_EXEC_LOOP(round, = vigra::round)
159  VIGRA_EXEC_LOOP(sqrt, = vigra::sqrt)
160  VIGRA_EXEC_LOOP(fromPromote, = NumericTraits<T1>::fromPromote)
161  VIGRA_EXEC_LOOP(fromRealPromote, = NumericTraits<T1>::fromRealPromote)
162  VIGRA_EXEC_LOOP_SCALAR(addScalar, +)
163  VIGRA_EXEC_LOOP_SCALAR(subScalar, -)
164  VIGRA_EXEC_LOOP_SCALAR(mulScalar, *)
165  VIGRA_EXEC_LOOP_SCALAR(divScalar, /)
166 
167  VIGRA_EXEC_LOOP_MINMAX(min, >)
168  VIGRA_EXEC_LOOP_MINMAX(max, <)
169 
170  template <class T>
171  static T const & minimum(T const * p)
172  {
173  return *std::min_element(p, p+LEVEL);
174  }
175 
176  template <class T>
177  static T const & maximum(T const * p)
178  {
179  return *std::max_element(p, p+LEVEL);
180  }
181 
182  template <class T>
183  static bool all(T const * p, T const & zero)
184  {
185  for(int i=0; i<LEVEL; ++i)
186  if(p[i] == zero)
187  return false;
188  return true;
189  }
190 
191  template <class T>
192  static bool any(T const * p, T const & zero)
193  {
194  for(int i=0; i<LEVEL; ++i)
195  if(p[i] != zero)
196  return true;
197  return false;
198  }
199 
200  template <class T1, class T2>
201  static bool notEqual(T1 const * left, T2 const * right)
202  {
203  for(int i=0; i<LEVEL; ++i)
204  if(left[i] != right[i])
205  return true;
206  return false;
207  }
208 
209  template <class T1, class T2>
210  static bool lexicographicLessThan(T1 const * left, T2 const * right)
211  {
212  for(int i=0; i<LEVEL; ++i)
213  {
214  if(left[i] < right[i])
215  return true;
216  if(right[i] < left[i])
217  return false;
218  }
219  return false;
220  }
221 
222  template <class T>
223  static bool closeAtTolerance(T const * left, T const * right, T epsilon)
224  {
225  bool res = true;
226  for(int i=0; i<LEVEL; ++i)
227  {
228  res = res && vigra::closeAtTolerance(left[i], right[i], epsilon);
229  }
230  return res;
231  }
232 
233  template <class T>
234  static typename NumericTraits<T>::Promote
235  dot(T const * d)
236  {
237  typename NumericTraits<T>::Promote res(*d * *d);
238  for(int i=1; i<LEVEL; ++i)
239  res += d[i] * d[i];
240  return res;
241  }
242 
243  template <class T1, class T2>
244  static typename PromoteTraits<T1, T2>::Promote
245  dot(T1 const * left, T2 const * right)
246  {
247  typename PromoteTraits<T1, T2>::Promote res(*left * *right);
248  for(int i=1; i<LEVEL; ++i)
249  res += left[i] * right[i];
250  return res;
251  }
252 
253  template <class T>
254  static typename NormTraits<T>::SquaredNormType
255  squaredNorm(T const * d)
256  {
257  typename NormTraits<T>::SquaredNormType res = vigra::squaredNorm(*d);
258  for(int i=1; i<LEVEL; ++i)
259  res += vigra::squaredNorm(d[i]);
260  return res;
261  }
262 };
263 
264 template <int LEVEL>
265 struct UnrollScalarResult
266 {
267  template <class T>
268  static typename NumericTraits<T>::Promote
269  dot(T const * d)
270  {
271  return *d * *d + UnrollScalarResult<LEVEL-1>::dot(d+1);
272  }
273 
274  template <class T1, class T2>
275  static typename PromoteTraits<T1, T2>::Promote
276  dot(T1 const * left, T2 const * right)
277  {
278  return *left * *right + UnrollScalarResult<LEVEL-1>::dot(left+1, right+1);
279  }
280 
281  template <class T>
282  static typename NormTraits<T>::SquaredNormType
283  squaredNorm(T const * d)
284  {
286  }
287 
288  static std::ptrdiff_t
289  squaredNorm(std::ptrdiff_t const * d)
290  {
291  return (*d)*(*d) + UnrollScalarResult<LEVEL-1>::squaredNorm(d+1);
292  }
293 
294  template <class T>
295  static T const & minimum(T const * p)
296  {
297  T const & m = UnrollScalarResult<LEVEL - 1>::minimum(p+1);
298  return *p < m
299  ? *p
300  : m;
301  }
302 
303  template <class T>
304  static T const & maximum(T const * p)
305  {
306  T const & m = UnrollScalarResult<LEVEL - 1>::maximum(p+1);
307  return *p > m
308  ? *p
309  : m;
310  }
311 
312  template <class T>
313  static bool all(T const * p, T const & zero)
314  {
315  return *p != zero && UnrollScalarResult<LEVEL - 1>::all(p+1, zero);
316  }
317 
318  template <class T>
319  static bool any(T const * p, T const & zero)
320  {
321  return *p != zero || UnrollScalarResult<LEVEL - 1>::any(p+1, zero);
322  }
323 };
324 
325 template <>
326 struct UnrollScalarResult<1>
327 {
328  template <class T>
329  static typename NumericTraits<T>::Promote
330  dot(T const * d)
331  {
332  return *d * *d ;
333  }
334 
335  template <class T1, class T2>
336  static typename PromoteTraits<T1, T2>::Promote
337  dot(T1 const * left, T2 const * right)
338  {
339  return *left * *right;
340  }
341 
342  template <class T>
343  static typename NormTraits<T>::SquaredNormType
344  squaredNorm(T const * d)
345  {
346  return vigra::squaredNorm(*d);
347  }
348 
349  static std::ptrdiff_t
350  squaredNorm(std::ptrdiff_t const * d)
351  {
352  return (*d)*(*d);
353  }
354 
355  template <class T>
356  static T const & minimum(T const * p)
357  {
358  return *p;
359  }
360 
361  template <class T>
362  static T const & maximum(T const * p)
363  {
364  return *p;
365  }
366 
367  template <class T>
368  static bool all(T const * p, T const & zero)
369  {
370  return *p != zero;
371  }
372 
373  template <class T>
374  static bool any(T const * p, T const & zero)
375  {
376  return *p != zero;
377  }
378 };
379 
380 #undef VIGRA_EXEC_LOOP
381 #undef VIGRA_EXEC_LOOP_MINMAX
382 #undef VIGRA_EXEC_LOOP_SCALAR
383 
384 #define VIGRA_UNROLL_LOOP(NAME, OPER) \
385  template <class T1, class T2> \
386  static void NAME(T1 * left, T2 const * right) \
387  { \
388  (*left) OPER (*right); \
389  UnrollLoop<LEVEL-1>::NAME(left+1, right+1); \
390  }
391 
392 #define VIGRA_UNROLL_LOOP_MINMAX(NAME, OPER) \
393  template <class T1, class T2> \
394  static void NAME(T1 * left, T2 const * right) \
395  { \
396  if(*left OPER *right) \
397  *left = *right; \
398  UnrollLoop<LEVEL-1>::NAME(left+1, right+1); \
399  }
400 
401 #define VIGRA_UNROLL_LOOP_SCALAR(NAME, OPER) \
402  template <class T1, class T2> \
403  static void NAME(T1 * left, T2 right) \
404  { \
405  (*left) = detail::RequiresExplicitCast<T1>::cast((*left) OPER (right)); \
406  UnrollLoop<LEVEL-1>::NAME(left+1, right); \
407  }
408 
409 
410 template <int LEVEL>
411 struct UnrollLoop
412 {
413  template <class T1, class T2>
414  static void reverseAssign(T1 * left, T2 const * right)
415  {
416  *left = *right;
417  UnrollLoop<LEVEL-1>::reverseAssign(left+1, right-1);
418  }
419 
420  template <class T1, class T2>
421  static void assignCast(T1 * left, T2 const * right)
422  {
423  *left = detail::RequiresExplicitCast<T1>::cast(*right);
424  UnrollLoop<LEVEL-1>::assignCast(left+1, right+1);
425  }
426 
427  template <class T1, class T2>
428  static void assignScalar(T1 * left, T2 right)
429  {
430  *left = detail::RequiresExplicitCast<T1>::cast(right);
431  UnrollLoop<LEVEL-1>::assignScalar(left+1, right);
432  }
433 
434  template <class T1, class T2>
435  static void power(T1 * left, T2 right)
436  {
437  *left = detail::RequiresExplicitCast<T1>::cast(pow(*left, right));
438  UnrollLoop<LEVEL-1>::power(left+1, right);
439  }
440 
441  VIGRA_UNROLL_LOOP(assign, =)
442  VIGRA_UNROLL_LOOP(add, +=)
443  VIGRA_UNROLL_LOOP(sub, -=)
444  VIGRA_UNROLL_LOOP(mul, *=)
445  VIGRA_UNROLL_LOOP(div, /=)
446  VIGRA_UNROLL_LOOP(mod, %=)
447  VIGRA_UNROLL_LOOP(neg, = -)
448  VIGRA_UNROLL_LOOP(abs, = vigra::abs)
449  VIGRA_UNROLL_LOOP(floor, = vigra::floor)
450  VIGRA_UNROLL_LOOP(ceil, = vigra::ceil)
451  VIGRA_UNROLL_LOOP(round, = vigra::round)
452  VIGRA_UNROLL_LOOP(sqrt, = vigra::sqrt)
453  VIGRA_UNROLL_LOOP(fromPromote, = NumericTraits<T1>::fromPromote)
454  VIGRA_UNROLL_LOOP(fromRealPromote, = NumericTraits<T1>::fromRealPromote)
455  VIGRA_UNROLL_LOOP_SCALAR(addScalar, +)
456  VIGRA_UNROLL_LOOP_SCALAR(subScalar, -)
457  VIGRA_UNROLL_LOOP_SCALAR(mulScalar, *)
458  VIGRA_UNROLL_LOOP_SCALAR(divScalar, /)
459 
460  VIGRA_UNROLL_LOOP_MINMAX(min, >)
461  VIGRA_UNROLL_LOOP_MINMAX(max, <)
462 
463  template <class T>
464  static T const & minimum(T const * p)
465  {
466  return UnrollScalarResult<LEVEL>::minimum(p);
467  }
468 
469  template <class T>
470  static T const & maximum(T const * p)
471  {
472  return UnrollScalarResult<LEVEL>::maximum(p);
473  }
474 
475  template <class T>
476  static bool all(T const * p, T const & zero)
477  {
478  return UnrollScalarResult<LEVEL>::all(p, zero);
479  }
480 
481  template <class T>
482  static bool any(T const * p, T const & zero)
483  {
484  return UnrollScalarResult<LEVEL>::any(p, zero);
485  }
486 
487  template <class T1, class T2>
488  static bool notEqual(T1 const * left, T2 const * right)
489  {
490  return (*left != *right) || UnrollLoop<LEVEL - 1>::notEqual(left+1, right+1);
491  }
492 
493  template <class T1, class T2>
494  static bool lexicographicLessThan(T1 const * left, T2 const * right)
495  {
496  if(*left < *right)
497  return true;
498  if(*right < *left)
499  return false;
500  return UnrollLoop<LEVEL - 1>::lexicographicLessThan(left+1, right+1);
501  }
502 
503  template <class T>
504  static bool closeAtTolerance(T const * left, T const * right, T epsilon)
505  {
506  return vigra::closeAtTolerance(*left, *right, epsilon) &&
507  UnrollLoop<LEVEL - 1>::closeAtTolerance(left+1, right+1, epsilon);
508  }
509 
510  template <class T>
511  static typename NumericTraits<T>::Promote
512  dot(T const * d)
513  {
515  }
516 
517  template <class T1, class T2>
518  static typename PromoteTraits<T1, T2>::Promote
519  dot(T1 const * left, T2 const * right)
520  {
521  return UnrollScalarResult<LEVEL>::dot(left, right);
522  }
523 
524  template <class T>
525  static typename NormTraits<T>::SquaredNormType
526  squaredNorm(T const * d)
527  {
529  }
530 };
531 
532 #undef VIGRA_UNROLL_LOOP
533 #undef VIGRA_UNROLL_LOOP_MINMAX
534 #undef VIGRA_UNROLL_LOOP_SCALAR
535 
536 template <>
537 struct UnrollLoop<0>
538 {
539  template <class T1, class T2>
540  static void reverseAssign(T1, T2) {}
541  template <class T1, class T2>
542  static void assignCast(T1, T2) {}
543  template <class T1, class T2>
544  static void assign(T1, T2) {}
545  template <class T1, class T2>
546  static void assignScalar(T1, T2) {}
547  template <class T1, class T2>
548  static void power(T1, T2) {}
549  template <class T1, class T2>
550  static void add(T1, T2) {}
551  template <class T1, class T2>
552  static void addScalar(T1, T2) {}
553  template <class T1, class T2>
554  static void sub(T1, T2) {}
555  template <class T1, class T2>
556  static void subScalar(T1, T2) {}
557  template <class T1, class T2>
558  static void mul(T1, T2) {}
559  template <class T1, class T2>
560  static void mulScalar(T1, T2) {}
561  template <class T1, class T2>
562  static void div(T1, T2) {}
563  template <class T1, class T2>
564  static void mod(T1, T2) {}
565  template <class T1, class T2>
566  static void divScalar(T1, T2) {}
567  template <class T1, class T2>
568  static void fromPromote(T1, T2) {}
569  template <class T1, class T2>
570  static void fromRealPromote(T1, T2) {}
571  template <class T1, class T2>
572  static void neg(T1, T2) {}
573  template <class T1, class T2>
574  static void abs(T1, T2) {}
575  template <class T1, class T2>
576  static void floor(T1, T2) {}
577  template <class T1, class T2>
578  static void ceil(T1, T2) {}
579  template <class T1, class T2>
580  static void round(T1, T2) {}
581  template <class T1, class T2>
582  static void sqrt(T1, T2) {}
583  template <class T1, class T2>
584  static bool notEqual(T1, T2) { return false; }
585  template <class T1, class T2>
586  static bool lexicographicLessThan(T1, T2) { return false; }
587  template <class T1, class T2>
588  static void min(T1, T2) {}
589  template <class T1, class T2>
590  static void max(T1, T2) {}
591  template <class T>
592  static T minimum(T const *) { return NumericTraits<T>::max(); }
593  template <class T>
594  static T maximum(T const *) { return NumericTraits<T>::min(); }
595  template <class T>
596  static bool all(T const *, T const &) { return true; }
597  template <class T>
598  static bool any(T const *, T const &) { return false; }
599  template <class T>
600  static bool closeAtTolerance(T const *, T const *, T) { return true; }
601 };
602 
603 template <int SIZE>
604 struct LoopType
605 {
606  static const int MaxUnrollSize = 5;
607  typedef typename IfBool<(SIZE <= MaxUnrollSize), UnrollLoop<SIZE>, ExecLoop<SIZE> >::type type;
608 
609 };
610 
611 struct DontInit {};
612 
613 inline DontInit dontInit() {return DontInit(); }
614 
615 } // namespace detail
616 
617 template <class T, int SIZE>
618 class TinyVector;
619 
620 template <class T, int SIZE>
622 
623 /********************************************************/
624 /* */
625 /* TinyVectorBase */
626 /* */
627 /********************************************************/
628 
629 /** \brief Base class for fixed size vectors.
630 
631  This class contains functionality shared by
632  \ref TinyVector and \ref TinyVectorView, and enables these classes
633  to be freely mixed within expressions. It is typically not used directly.
634 
635  <b>\#include</b> <vigra/tinyvector.hxx><br>
636  Namespace: vigra
637 **/
638 template <class VALUETYPE, int SIZE, class DATA, class DERIVED>
639 class TinyVectorBase
640 {
641  TinyVectorBase(TinyVectorBase const &); // do not use
642 
643  TinyVectorBase & operator=(TinyVectorBase const & other); // do not use
644 
645  protected:
646 
647  typedef typename detail::LoopType<SIZE>::type Loop;
648 
650  {}
651 
652  public:
653  /** STL-compatible definition of valuetype
654  */
655  typedef VALUETYPE value_type;
656 
657  /** reference (return of operator[]).
658  */
659  typedef VALUETYPE & reference;
660 
661  /** const reference (return of operator[] const).
662  */
663  typedef VALUETYPE const & const_reference;
664 
665  /** pointer (return of operator->).
666  */
667  typedef VALUETYPE * pointer;
668 
669  /** const pointer (return of operator-> const).
670  */
671  typedef VALUETYPE const * const_pointer;
672 
673  /** STL-compatible definition of iterator
674  */
675  typedef value_type * iterator;
676 
677  /** STL-compatible definition of const iterator
678  */
679  typedef value_type const * const_iterator;
680 
681  /** STL-compatible definition of size_type
682  */
683  typedef unsigned int size_type;
684 
685  /** STL-compatible definition of difference_type
686  */
687  typedef std::ptrdiff_t difference_type;
688 
689  /** the scalar type for the outer product
690  */
691  typedef double scalar_multiplier;
692 
693  /** the vector's squared norm type
694  */
695  typedef typename NormTraits<VALUETYPE>::SquaredNormType SquaredNormType;
696 
697  /** the vector's norm type
698  */
699  typedef typename SquareRootTraits<SquaredNormType>::SquareRootResult NormType;
700 
701  /** the vector's size
702  */
703  enum { static_size = SIZE };
704 
705  /** Initialize from another sequence (must have length SIZE!)
706  */
707  template <class Iterator>
708  void init(Iterator i, Iterator end)
709  {
710  vigra_precondition(end-i == SIZE,
711  "TinyVector::init(): Sequence has wrong size.");
712  Loop::assignCast(data_, i);
713  }
714 
715  /** Initialize with constant value
716  */
717  void init(value_type initial)
718  {
719  Loop::assignScalar(data_, initial);
720  }
721 
722  /** Component-wise add-assignment
723  */
724  template <class T1, class D1, class D2>
726  {
727  Loop::add(data_, r.begin());
728  return static_cast<DERIVED &>(*this);
729  }
730 
731  /** Component-wise subtract-assignment
732  */
733  template <class T1, class D1, class D2>
735  {
736  Loop::sub(data_, r.begin());
737  return static_cast<DERIVED &>(*this);
738  }
739 
740  /** Component-wise multiply-assignment
741  */
742  template <class T1, class D1, class D2>
744  {
745  Loop::mul(data_, r.begin());
746  return static_cast<DERIVED &>(*this);
747  }
748 
749  /** Component-wise divide-assignment
750  */
751  template <class T1, class D1, class D2>
753  {
754  Loop::div(data_, r.begin());
755  return static_cast<DERIVED &>(*this);
756  }
757 
758  /** Component-wise modulo-assignment
759  */
760  template <class T1, class D1, class D2>
762  {
763  Loop::mod(data_, r.begin());
764  return static_cast<DERIVED &>(*this);
765  }
766 
767  /** Component-wise scalar multiply-assignment
768  */
769  DERIVED & operator+=(double r)
770  {
771  Loop::addScalar(data_, r);
772  return static_cast<DERIVED &>(*this);
773  }
774 
775  /** Component-wise scalar divide-assignment
776  */
777  DERIVED & operator-=(double r)
778  {
779  Loop::subScalar(data_, r);
780  return static_cast<DERIVED &>(*this);
781  }
782 
783  /** Component-wise scalar multiply-assignment
784  */
785  DERIVED & operator*=(double r)
786  {
787  Loop::mulScalar(data_, r);
788  return static_cast<DERIVED &>(*this);
789  }
790 
791  /** Component-wise scalar divide-assignment
792  */
793  DERIVED & operator/=(double r)
794  {
795  Loop::divScalar(data_, r);
796  return static_cast<DERIVED &>(*this);
797  }
798 
799  /** Calculate magnitude (i.e. 2-norm / Euclidean norm / length).
800  * \see squaredMagnitude()
801  */
803  {
804  return sqrt(static_cast<typename
805  SquareRootTraits<SquaredNormType>::SquareRootArgument>(squaredMagnitude()));
806  }
807 
808  /** Calculate squared magnitude (i.e. sum of squared elements).
809  */
811  {
812  return Loop::squaredNorm(data_);
813  }
814 
815  /** Return the minimal element.
816  */
817  VALUETYPE const & minimum() const
818  {
819  return Loop::minimum(data_);
820  }
821 
822  /** Return the maximal element.
823  */
824  VALUETYPE const & maximum() const
825  {
826  return Loop::maximum(data_);
827  }
828 
829  /** Check that all elements of this vector are non-zero (or 'true' if T is bool).
830  */
831  bool all() const
832  {
833  return Loop::all(data_, VALUETYPE());
834  }
835 
836  /** Check that at least one element of this vector is non-zero (or 'true' if T is bool).
837  */
838  bool any() const
839  {
840  return Loop::any(data_, VALUETYPE());
841  }
842 
843  /** Access component by index.
844  */
846  {
847  VIGRA_ASSERT_INSIDE(i);
848  return data_[i];
849  }
850 
851  /** Get component by index.
852  */
854  {
855  VIGRA_ASSERT_INSIDE(i);
856  return data_[i];
857  }
858 
859  /** Get random access iterator to begin of vector.
860  */
861  iterator begin() { return data_; }
862  /** Get random access iterator past-the-end of vector.
863  */
864  iterator end() { return data_ + SIZE; }
865 
866  /** Get const random access iterator to begin of vector.
867  */
868  const_iterator begin() const { return data_; }
869 
870  /** Get const random access iterator past-the-end of vector.
871  */
872  const_iterator end() const { return data_ + SIZE; }
873 
874  /** Get const random access iterator to begin of vector.
875  */
876  const_iterator cbegin() const { return data_; }
877 
878  /** Get const random access iterator past-the-end of vector.
879  */
880  const_iterator cend() const { return data_ + SIZE; }
881 
882  /** Get a view to the subarray with length <tt>(TO-FROM)</tt> starting at <tt>FROM</tt>.
883  The bounds must fullfill <tt>0 <= FROM < TO <= SIZE</tt>, but this is only
884  checked when <tt>VIGRA_CHECK_BOUNDS</tt> is \#define'd.
885  */
886  template <int FROM, int TO>
887  TinyVectorView<VALUETYPE, TO-FROM> subarray() const
888  {
889 #ifdef VIGRA_CHECK_BOUNDS
890  vigra_precondition(FROM >= 0, "Index out of bounds");
891  vigra_precondition(FROM < TO, "Index out of bounds");
892  vigra_precondition(TO <=SIZE, "Index out of bounds");
893 #endif
894  return TinyVectorView<VALUETYPE, TO-FROM>(data_+FROM);
895  }
896 
897  TinyVector<VALUETYPE, SIZE-1>
898  dropIndex(int m) const
899  {
900 #ifdef VIGRA_CHECK_BOUNDS
901  vigra_precondition(0 <= m && m < SIZE, "Dimension out of bounds");
902 #endif
903  TinyVector<VALUETYPE, SIZE-1> res(SkipInitialization);
904  for(int k=0; k<m; ++k)
905  res[k] = data_[k];
906  for(int k=m; k<SIZE-1; ++k)
907  res[k] = data_[k+1];
908  return res;
909  }
910 
911  /** Size of TinyVector vector always equals the template parameter SIZE.
912  */
913  size_type size() const { return SIZE; }
914 
915  pointer data() { return data_; }
916 
917  const_pointer data() const { return data_; }
918 
919  reference front()
920  {
921  return data_[0];
922  }
923 
924  const_reference front() const
925  {
926  return data_[0];
927  }
928 
929  reference back()
930  {
931  return data_[SIZE-1];
932  }
933 
934  const_reference back() const
935  {
936  return data_[SIZE-1];
937  }
938 
939  /** \brief Factory function for a unit vector for dimension \a k.
940  */
942  {
943  VIGRA_ASSERT_INSIDE(k);
945  ret[k] = 1;
946  return ret;
947  }
948 
949  /** \brief Factory function for a linear sequence.
950 
951  The result will be initialized as <tt>res[k] = start + k*step</tt>.
952  */
953  static TinyVector<VALUETYPE, SIZE> linearSequence(VALUETYPE start=VALUETYPE(), VALUETYPE step=VALUETYPE(1))
954  {
955  TinyVector<VALUETYPE, SIZE> ret(SkipInitialization);
956  for(int k=0; k<SIZE; ++k, start+=step)
957  ret[k] = start;
958  return ret;
959  }
960 
961  protected:
962 
963  DATA data_;
964 };
965 
966 #ifndef DOXYGEN
967 
968 template <int SIZE, int DESIRED_SIZE>
969 struct TinyVector_constructor_has_wrong_number_of_arguments
970 : staticAssert::AssertBool<SIZE == DESIRED_SIZE>
971 {};
972 
973 #endif /* DOXYGEN */
974 
975 enum ReverseCopyTag { ReverseCopy };
976 
977 /** \brief Class for fixed size vectors.
978  \ingroup RangesAndPoints
979 
980  This class contains an array of size SIZE of the specified VALUETYPE.
981  The interface conforms to STL vector, except that there are no functions
982  that change the size of a TinyVector.
983 
984  \ref TinyVectorOperators "Arithmetic operations"
985  on TinyVectors are defined as component-wise applications of these
986  operations. Addition and subtraction of two TinyVectors
987  (+=, -=, +, -, unary -), multiplication and division of an
988  TinyVector with a double, and NumericTraits/PromoteTraits are defined,
989  so that TinyVector fulfills the requirements of \ref LinearAlgebraConcept "Linear Algebra".
990 
991  VIGRA algorithms typically use \ref vigra::VectorAccessor to access
992  TinyVectors as a whole, or specific components of them.
993 
994  See also:<br>
995  <UL style="list-style-image:url(documents/bullet.gif)">
996  <LI> \ref vigra::TinyVectorBase
997  <LI> \ref vigra::TinyVectorView
998  <LI> \ref TinyVectorTraits
999  <LI> \ref TinyVectorOperators
1000  </UL>
1001 
1002  <b>\#include</b> <vigra/tinyvector.hxx><br>
1003  Namespace: vigra
1004 **/
1005 template <class T, int SIZE>
1006 class TinyVector
1007 : public TinyVectorBase<T, SIZE, T[SIZE], TinyVector<T, SIZE> >
1008 {
1009  typedef TinyVectorBase<T, SIZE, T[SIZE], TinyVector<T, SIZE> > BaseType;
1010  typedef typename BaseType::Loop Loop;
1011 
1012  public:
1013 
1014  typedef typename BaseType::value_type value_type;
1015  typedef typename BaseType::reference reference;
1016  typedef typename BaseType::const_reference const_reference;
1017  typedef typename BaseType::pointer pointer;
1018  typedef typename BaseType::const_pointer const_pointer;
1019  typedef typename BaseType::iterator iterator;
1020  typedef typename BaseType::const_iterator const_iterator;
1021  typedef typename BaseType::size_type size_type;
1022  typedef typename BaseType::difference_type difference_type;
1023  typedef typename BaseType::scalar_multiplier scalar_multiplier;
1024  typedef typename BaseType::SquaredNormType SquaredNormType;
1025  typedef typename BaseType::NormType NormType;
1026 
1027  /** Construction with constant value.
1028 
1029  Initializes all vector elements with the given value.
1030  */
1031  explicit TinyVector(value_type const & initial)
1032  : BaseType()
1033  {
1034  Loop::assignScalar(BaseType::begin(), initial);
1035  }
1036 
1037  /** Construction from lemon::Invalid.
1038 
1039  Initializes all vector elements with -1.
1040  */
1041  TinyVector(lemon::Invalid const &)
1042  : BaseType()
1043  {
1044  Loop::assignScalar(BaseType::begin(), -1);
1045  }
1046 
1047  /** Construction with Diff2D.
1048 
1049  Use only when <tt>SIZE == 2</tt>.
1050  */
1051  explicit TinyVector(Diff2D const & initial)
1052  : BaseType()
1053  {
1054  BaseType::data_[0] = detail::RequiresExplicitCast<T>::cast(initial.x);
1055  BaseType::data_[1] = detail::RequiresExplicitCast<T>::cast(initial.y);
1056  }
1057 
1058  /** Construction with explicit values.
1059  Call only if SIZE == 2
1060  */
1061  TinyVector(value_type const & i1, value_type const & i2)
1062  : BaseType()
1063  {
1064  VIGRA_STATIC_ASSERT((TinyVector_constructor_has_wrong_number_of_arguments<SIZE, 2>));
1065  BaseType::data_[0] = i1;
1066  BaseType::data_[1] = i2;
1067  }
1068 
1069  /** Construction with explicit values.
1070  Call only if SIZE == 3
1071  */
1072  TinyVector(value_type const & i1, value_type const & i2, value_type const & i3)
1073  : BaseType()
1074  {
1075  VIGRA_STATIC_ASSERT((TinyVector_constructor_has_wrong_number_of_arguments<SIZE, 3>));
1076  BaseType::data_[0] = i1;
1077  BaseType::data_[1] = i2;
1078  BaseType::data_[2] = i3;
1079  }
1080 
1081  /** Construction with explicit values.
1082  Call only if SIZE == 4
1083  */
1084  TinyVector(value_type const & i1, value_type const & i2,
1085  value_type const & i3, value_type const & i4)
1086  : BaseType()
1087  {
1088  VIGRA_STATIC_ASSERT((TinyVector_constructor_has_wrong_number_of_arguments<SIZE, 4>));
1089  BaseType::data_[0] = i1;
1090  BaseType::data_[1] = i2;
1091  BaseType::data_[2] = i3;
1092  BaseType::data_[3] = i4;
1093  }
1094 
1095  /** Construction with explicit values.
1096  Call only if SIZE == 5
1097  */
1098  TinyVector(value_type const & i1, value_type const & i2,
1099  value_type const & i3, value_type const & i4,
1100  value_type const & i5)
1101  : BaseType()
1102  {
1103  VIGRA_STATIC_ASSERT((TinyVector_constructor_has_wrong_number_of_arguments<SIZE, 5>));
1104  BaseType::data_[0] = i1;
1105  BaseType::data_[1] = i2;
1106  BaseType::data_[2] = i3;
1107  BaseType::data_[3] = i4;
1108  BaseType::data_[4] = i5;
1109  }
1110 
1111  /** Default constructor (initializes all elements with zero).
1112  */
1114  : BaseType()
1115  {
1116  Loop::assignScalar(BaseType::data_, value_type());
1117  }
1118 
1119  /** Construct without initializing the vector elements.
1120  */
1121  explicit TinyVector(SkipInitializationTag)
1122  : BaseType()
1123  {}
1124 
1125  explicit TinyVector(detail::DontInit)
1126  : BaseType()
1127  {}
1128 
1129  /** Copy constructor.
1130  */
1132  : BaseType()
1133  {
1134  Loop::assign(BaseType::data_, r.data_);
1135  }
1136 
1137  /** Constructor from C array.
1138  */
1139  template <class U>
1140  explicit TinyVector(U const * data)
1141  : BaseType()
1142  {
1143  Loop::assign(BaseType::data_, data);
1144  }
1145 
1146  /** Constructor by reverse copy from C array.
1147 
1148  Usage:
1149  \code
1150  TinyVector<int, 3> v(1,2,3);
1151  TinyVector<int, 3> reversed(v.begin(), TinyVector<int, 3>::ReverseCopy);
1152  \endcode
1153  */
1154  explicit TinyVector(const_pointer data, ReverseCopyTag)
1155  : BaseType()
1156  {
1157  Loop::reverseAssign(BaseType::data_, data+SIZE-1);
1158  }
1159 
1160  /** Copy with type conversion.
1161  */
1162  template <class U, class DATA, class DERIVED>
1164  : BaseType()
1165  {
1166  Loop::assignCast(BaseType::data_, r.begin());
1167  }
1168 
1169  /** Copy assignment.
1170  */
1172  {
1173  Loop::assign(BaseType::data_, r.data_);
1174  return *this;
1175  }
1176 
1177  /** Copy assignment with type conversion.
1178  */
1179  template <class U, class DATA, class DERIVED>
1181  {
1182  Loop::assignCast(BaseType::data_, r.begin());
1183  return *this;
1184  }
1185 
1186  /** Assignment from Diff2D.
1187 
1188  Use only when <tt>SIZE == 2</tt>.
1189  */
1191  {
1192  BaseType::data_[0] = detail::RequiresExplicitCast<T>::cast(r.x);
1193  BaseType::data_[1] = detail::RequiresExplicitCast<T>::cast(r.y);
1194  return *this;
1195  }
1196 
1197  /** Assignment from scalar. Will set all entries to the given value.
1198  */
1199  TinyVector & operator=(value_type const & v)
1200  {
1201  Loop::assignScalar(BaseType::begin(), v);
1202  return *this;
1203  }
1204 
1205  /** Copy from a TinyVector with a different number of elements.
1206 
1207  Only the first <tt>min(SIZE, USIZE)</tt> elements are copied.
1208  */
1209  template <class U, int USIZE, class DATA, class DERIVED>
1211  {
1212  static const int minSize = USIZE < SIZE
1213  ? USIZE
1214  : SIZE;
1215 
1216  typedef typename detail::LoopType<minSize>::type MinLoop;
1217  MinLoop::assignCast(BaseType::data_, r.begin());
1218  return *this;
1219  }
1220 };
1221 
1222 /** \brief Wrapper for fixed size vectors.
1223 
1224  This class wraps an array of size SIZE of the specified VALUETYPE.
1225  Thus, the array can be accessed with an interface similar to
1226  that of std::vector (except that there are no functions
1227  that change the size of a TinyVectorView). The TinyVectorView
1228  does <em>not</em> assume ownership of the given memory.
1229 
1230  \ref TinyVectorOperators "Arithmetic operations"
1231  on TinyVectorViews are defined as component-wise applications of these
1232  operations. Addition and subtraction of two TinyVectorViews
1233  (+=, -=, +, -, unary -), multiplication and division of an
1234  TinyVectorViews with a double, and NumericTraits/PromoteTraits are defined,
1235  so that TinyVectorView fulfills the requirements of \ref LinearAlgebraConcept "Linear Algebra".
1236 
1237  VIGRA algorithms typically use \ref vigra::VectorAccessor to access
1238  TinyVectorViews as a whole, or specific components of them.
1239 
1240  <b>See also:</b>
1241  <ul>
1242  <li> \ref vigra::TinyVectorBase
1243  <li> \ref vigra::TinyVector
1244  <li> \ref TinyVectorTraits
1245  <li> \ref TinyVectorOperators
1246  </ul>
1247 
1248  <b>\#include</b> <vigra/tinyvector.hxx><br>
1249  Namespace: vigra
1250 **/
1251 template <class T, int SIZE>
1252 class TinyVectorView
1253 : public TinyVectorBase<T, SIZE, T *, TinyVectorView<T, SIZE> >
1254 {
1255  typedef TinyVectorBase<T, SIZE, T *, TinyVectorView<T, SIZE> > BaseType;
1256  typedef typename BaseType::Loop Loop;
1257 
1258  public:
1259 
1260  typedef typename BaseType::value_type value_type;
1261  typedef typename BaseType::reference reference;
1262  typedef typename BaseType::const_reference const_reference;
1263  typedef typename BaseType::pointer pointer;
1264  typedef typename BaseType::const_pointer const_pointer;
1265  typedef typename BaseType::iterator iterator;
1266  typedef typename BaseType::const_iterator const_iterator;
1267  typedef typename BaseType::size_type size_type;
1268  typedef typename BaseType::difference_type difference_type;
1269  typedef typename BaseType::scalar_multiplier scalar_multiplier;
1270  typedef typename BaseType::SquaredNormType SquaredNormType;
1271  typedef typename BaseType::NormType NormType;
1272 
1273  /** Default constructor
1274  (pointer to wrapped data is NULL).
1275  */
1277  : BaseType()
1278  {
1279  BaseType::data_ = 0;
1280  }
1281 
1282  /** Construct view for given data array
1283  */
1284  TinyVectorView(const_pointer data)
1285  : BaseType()
1286  {
1287  BaseType::data_ = const_cast<pointer>(data);
1288  }
1289 
1290  /** Copy constructor (shallow copy).
1291  */
1293  : BaseType()
1294  {
1295  BaseType::data_ = const_cast<pointer>(other.data_);
1296  }
1297 
1298  /** Construct view from other TinyVector.
1299  */
1300  template <class DATA, class DERIVED>
1302  : BaseType()
1303  {
1304  BaseType::data_ = const_cast<pointer>(other.data());
1305  }
1306 
1307  /** Copy the data (not the pointer) of the rhs.
1308  */
1310  {
1311  Loop::assign(BaseType::data_, r.begin());
1312  return *this;
1313  }
1314 
1315  /** Copy the data of the rhs with cast.
1316  */
1317  template <class U, class DATA, class DERIVED>
1319  {
1320  Loop::assignCast(BaseType::data_, r.begin());
1321  return *this;
1322  }
1323 };
1324 
1325 /********************************************************/
1326 /* */
1327 /* TinyVector Comparison */
1328 /* */
1329 /********************************************************/
1330 
1331 /** \addtogroup TinyVectorOperators Functions for TinyVector
1332 
1333  \brief Implement basic arithmetic and equality for TinyVector.
1334 
1335  These functions fulfill the requirements of a Linear Space (vector space).
1336  Return types are determined according to \ref TinyVectorTraits.
1337 
1338  <b>\#include</b> <vigra/tinyvector.hxx><br>
1339  Namespace: vigra
1340 */
1341 //@{
1342  /// component-wise equal
1343 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
1344 inline bool
1347 {
1348  return !(l != r);
1349 }
1350 
1351  /// component-wise not equal
1352 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
1353 inline bool
1356 {
1357  typedef typename detail::LoopType<SIZE>::type ltype;
1358  return ltype::notEqual(l.begin(), r.begin());
1359 }
1360 
1361  /// lexicographical comparison
1362 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
1363 inline bool
1364 operator<(TinyVectorBase<V1, SIZE, D1, D2> const & l,
1366 {
1367  typedef typename detail::LoopType<SIZE>::type ltype;
1368  return ltype::lexicographicLessThan(l.begin(), r.begin());
1369 }
1370 
1371 
1372  /// pointwise less-than
1373 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
1374 inline bool
1377 {
1378  for(int k=0; k < SIZE; ++k)
1379  if (l[k] >= r[k])
1380  return false;
1381  return true;
1382 }
1383 
1384  /// pointwise greater-than
1385 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
1386 inline bool
1389 {
1390  for(int k=0; k < SIZE; ++k)
1391  if(l[k] <= r[k])
1392  return false;
1393  return true;
1394 }
1395 
1396  /// pointwise less-equal
1397 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
1398 inline bool
1401 {
1402  for(int k=0; k < SIZE; ++k)
1403  if (l[k] > r[k])
1404  return false;
1405  return true;
1406 }
1407 
1408  /// pointwise greater-equal
1409 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
1410 inline bool
1413 {
1414  for(int k=0; k < SIZE; ++k)
1415  if (l[k] < r[k])
1416  return false;
1417  return true;
1418 }
1419 
1420 template <class V, int SIZE, class D1, class D2, class D3, class D4>
1421 bool
1422 closeAtTolerance(TinyVectorBase<V, SIZE, D1, D2> const & l,
1423  TinyVectorBase<V, SIZE, D3, D4> const & r,
1424  V epsilon = NumericTraits<V>::epsilon())
1425 {
1426  typedef typename detail::LoopType<SIZE>::type ltype;
1427  return ltype::closeAtTolerance(l.begin(), r.begin(), epsilon);
1428 }
1429 
1430 template <class V, int SIZE>
1431 bool
1432 closeAtTolerance(TinyVector<V, SIZE> const & l,
1433  TinyVector<V, SIZE> const & r,
1434  V epsilon = NumericTraits<V>::epsilon())
1435 {
1436  typedef typename detail::LoopType<SIZE>::type ltype;
1437  return ltype::closeAtTolerance(l.begin(), r.begin(), epsilon);
1438 }
1439 
1440 /********************************************************/
1441 /* */
1442 /* TinyVector Output */
1443 /* */
1444 /********************************************************/
1445 
1446  /// stream output
1447 template <class V1, int SIZE, class DATA, class DERIVED>
1448 std::ostream &
1449 operator<<(std::ostream & out, TinyVectorBase<V1, SIZE, DATA, DERIVED> const & l)
1450 {
1451  out << "(";
1452  int i;
1453  for(i=0; i<SIZE-1; ++i)
1454  out << l[i] << ", ";
1455  out << l[i] << ")";
1456  return out;
1457 }
1458 //@}
1459 
1460 /********************************************************/
1461 /* */
1462 /* TinyVector-Traits */
1463 /* */
1464 /********************************************************/
1465 
1466 /** \page TinyVectorTraits Numeric and Promote Traits of TinyVector
1467  The numeric and promote traits for TinyVectors follow
1468  the general specifications for \ref NumericPromotionTraits.
1469  They are implemented in terms of the traits of the basic types by
1470  partial template specialization:
1471 
1472  \code
1473 
1474  template <class T, int SIZE>
1475  struct NumericTraits<TinyVector<T, SIZE> >
1476  {
1477  typedef TinyVector<typename NumericTraits<T>::Promote, SIZE> Promote;
1478  typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> RealPromote;
1479 
1480  typedef typename NumericTraits<T>::isIntegral isIntegral;
1481  typedef VigraFalseType isScalar;
1482  typedef typename NumericTraits<T>::isSigned isSigned;
1483 
1484  // etc.
1485  };
1486 
1487  template <class T, int SIZE>
1488  struct NormTraits<TinyVector<T, SIZE> >
1489  {
1490  typedef TinyVector<T, SIZE> Type;
1491  typedef typename Type::SquaredNormType SquaredNormType;
1492  typedef typename Type::NormType NormType;
1493  };
1494 
1495  template <class T1, class T2, SIZE>
1496  struct PromoteTraits<TinyVector<T1, SIZE>, TinyVector<T2, SIZE> >
1497  {
1498  typedef TinyVector<typename PromoteTraits<T1, T2>::Promote, SIZE> Promote;
1499  };
1500  \endcode
1501 
1502  <b>\#include</b> <vigra/tinyvector.hxx><br>
1503  Namespace: vigra
1504 
1505  On compilers that don't support partial template specialization (e.g.
1506  MS VisualC++), the traits classes are explicitly specialized for
1507  <TT>TinyVector<VALUETYPE, SIZE></TT> with
1508  <TT>VALUETYPE = unsigned char | int | float | double</TT> and <TT>SIZE = 2 | 3 | 4</TT>.
1509 
1510 */
1511 
1512 #if !defined(NO_PARTIAL_TEMPLATE_SPECIALIZATION)
1513 
1514 template <class T, int SIZE>
1515 struct NumericTraits<TinyVector<T, SIZE> >
1516 {
1517  typedef TinyVector<T, SIZE> Type;
1518  typedef TinyVector<typename NumericTraits<T>::Promote, SIZE> Promote;
1519  typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> RealPromote;
1520  typedef TinyVector<typename NumericTraits<T>::ComplexPromote, SIZE> ComplexPromote;
1521  typedef T ValueType;
1522 
1523  typedef typename NumericTraits<T>::isIntegral isIntegral;
1524  typedef VigraFalseType isScalar;
1525  typedef typename NumericTraits<T>::isSigned isSigned;
1526  typedef VigraTrueType isOrdered;
1527  typedef VigraFalseType isComplex;
1528 
1529  static TinyVector<T, SIZE> zero()
1530  {
1531  return TinyVector<T, SIZE>(NumericTraits<T>::zero());
1532  }
1533  static TinyVector<T, SIZE> one()
1534  {
1535  return TinyVector<T, SIZE>(NumericTraits<T>::one());
1536  }
1537  static TinyVector<T, SIZE> nonZero()
1538  {
1539  return TinyVector<T, SIZE>(NumericTraits<T>::nonZero());
1540  }
1541 
1542  static TinyVector<T, SIZE> min()
1543  {
1544  return TinyVector<T, SIZE>(NumericTraits<T>::min());
1545  }
1546  static TinyVector<T, SIZE> max()
1547  {
1548  return TinyVector<T, SIZE>(NumericTraits<T>::max());
1549  }
1550 
1551  template <class D1, class D2>
1552  static Promote toPromote(TinyVectorBase<T, SIZE, D1, D2> const & v)
1553  {
1554  return Promote(v);
1555  }
1556 
1557  template <class D1, class D2>
1558  static RealPromote toRealPromote(TinyVectorBase<T, SIZE, D1, D2> const & v)
1559  {
1560  return RealPromote(v);
1561  }
1562 
1563  template <class D1, class D2>
1564  static TinyVector<T, SIZE>
1565  fromPromote(TinyVectorBase<typename NumericTraits<T>::Promote, SIZE, D1, D2> const & v)
1566  {
1567  TinyVector<T, SIZE> res(detail::dontInit());
1568  typedef typename detail::LoopType<SIZE>::type ltype;
1569  ltype::fromPromote(res.begin(), v.begin());
1570  return res;
1571  }
1572 
1573  template <class D1, class D2>
1574  static TinyVector<T, SIZE>
1575  fromRealPromote(TinyVectorBase<typename NumericTraits<T>::RealPromote, SIZE, D1, D2> const & v)
1576  {
1577  TinyVector<T, SIZE> res(detail::dontInit());
1578  typedef typename detail::LoopType<SIZE>::type ltype;
1579  ltype::fromRealPromote(res.begin(), v.begin());
1580  return res;
1581  }
1582 };
1583 
1584 template <class T, int SIZE>
1585 struct NumericTraits<TinyVectorView<T, SIZE> >
1586 : public NumericTraits<TinyVector<T, SIZE> >
1587 {
1588  typedef TinyVector<T, SIZE> Type;
1589  typedef TinyVector<typename NumericTraits<T>::Promote, SIZE> Promote;
1590  typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> RealPromote;
1591  typedef TinyVector<typename NumericTraits<T>::ComplexPromote, SIZE> ComplexPromote;
1592  typedef T ValueType;
1593 
1594  typedef typename NumericTraits<T>::isIntegral isIntegral;
1595  typedef VigraFalseType isScalar;
1596  typedef typename NumericTraits<T>::isSigned isSigned;
1597  typedef VigraFalseType isOrdered;
1598  typedef VigraFalseType isComplex;
1599 };
1600 
1601 template <class T, int SIZE>
1602 struct NormTraits<TinyVector<T, SIZE> >
1603 {
1604  typedef TinyVector<T, SIZE> Type;
1605  typedef typename Type::SquaredNormType SquaredNormType;
1606  typedef typename Type::NormType NormType;
1607 };
1608 
1609 template <class T, int SIZE>
1610 struct NormTraits<TinyVectorView<T, SIZE> >
1611 {
1612  typedef TinyVector<T, SIZE> Type;
1613  typedef typename Type::SquaredNormType SquaredNormType;
1614  typedef typename Type::NormType NormType;
1615 };
1616 
1617 template <class T1, class T2, int SIZE>
1618 struct PromoteTraits<TinyVector<T1, SIZE>, TinyVector<T2, SIZE> >
1619 {
1620  typedef TinyVector<typename PromoteTraits<T1, T2>::Promote, SIZE> Promote;
1621 };
1622 
1623 template <class T1, class T2, int SIZE>
1624 struct PromoteTraits<TinyVectorView<T1, SIZE>, TinyVectorView<T2, SIZE> >
1625 {
1626  typedef TinyVector<typename PromoteTraits<T1, T2>::Promote, SIZE> Promote;
1627 };
1628 
1629 template <class T1, class T2, int SIZE>
1630 struct PromoteTraits<TinyVectorView<T1, SIZE>, TinyVector<T2, SIZE> >
1631 {
1632  typedef TinyVector<typename PromoteTraits<T1, T2>::Promote, SIZE> Promote;
1633 };
1634 
1635 template <class T1, class T2, int SIZE>
1636 struct PromoteTraits<TinyVector<T1, SIZE>, TinyVectorView<T2, SIZE> >
1637 {
1638  typedef TinyVector<typename PromoteTraits<T1, T2>::Promote, SIZE> Promote;
1639 };
1640 
1641 template <class T, int SIZE>
1642 struct PromoteTraits<TinyVector<T, SIZE>, double >
1643 {
1644  typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> Promote;
1645 };
1646 
1647 template <class T, int SIZE>
1648 struct PromoteTraits<double, TinyVector<T, SIZE> >
1649 {
1650  typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> Promote;
1651 };
1652 
1653 template <class T, int SIZE>
1654 struct PromoteTraits<TinyVectorView<T, SIZE>, double >
1655 {
1656  typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> Promote;
1657 };
1658 
1659 template <class T, int SIZE>
1660 struct PromoteTraits<double, TinyVectorView<T, SIZE> >
1661 {
1662  typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> Promote;
1663 };
1664 
1665 template<class T, int SIZE>
1666 struct CanSkipInitialization<TinyVectorView<T, SIZE> >
1667 {
1668  typedef typename CanSkipInitialization<T>::type type;
1669  static const bool value = type::asBool;
1670 };
1671 
1672 template<class T, int SIZE>
1673 struct CanSkipInitialization<TinyVector<T, SIZE> >
1674 {
1675  typedef typename CanSkipInitialization<T>::type type;
1676  static const bool value = type::asBool;
1677 };
1678 
1679 
1680 
1681 #else // NO_PARTIAL_TEMPLATE_SPECIALIZATION
1682 
1683 
1684 #define TINYVECTOR_NUMTRAITS(T, SIZE) \
1685 template<>\
1686 struct NumericTraits<TinyVector<T, SIZE> >\
1687 {\
1688  typedef TinyVector<T, SIZE> Type;\
1689  typedef TinyVector<NumericTraits<T>::Promote, SIZE> Promote;\
1690  typedef TinyVector<NumericTraits<T>::RealPromote, SIZE> RealPromote;\
1691  typedef TinyVector<NumericTraits<T>::ComplexPromote, SIZE> ComplexPromote;\
1692  typedef T ValueType; \
1693  typedef NumericTraits<T>::isIntegral isIntegral;\
1694  typedef VigraFalseType isScalar;\
1695  typedef NumericTraits<T>::isSigned isSigned; \
1696  typedef VigraFalseType isOrdered;\
1697  typedef VigraFalseType isComplex;\
1698  \
1699  static TinyVector<T, SIZE> zero() { \
1700  return TinyVector<T, SIZE>(NumericTraits<T>::zero()); \
1701  }\
1702  static TinyVector<T, SIZE> one() { \
1703  return TinyVector<T, SIZE>(NumericTraits<T>::one()); \
1704  }\
1705  static TinyVector<T, SIZE> nonZero() { \
1706  return TinyVector<T, SIZE>(NumericTraits<T>::nonZero()); \
1707  }\
1708  \
1709  static Promote toPromote(TinyVector<T, SIZE> const & v) { \
1710  return Promote(v); \
1711  }\
1712  static RealPromote toRealPromote(TinyVector<T, SIZE> const & v) { \
1713  return RealPromote(v); \
1714  }\
1715  static TinyVector<T, SIZE> fromPromote(Promote const & v) { \
1716  TinyVector<T, SIZE> res;\
1717  TinyVector<T, SIZE>::iterator d = res.begin(), dend = res.end();\
1718  Promote::const_iterator s = v.begin();\
1719  for(; d != dend; ++d, ++s)\
1720  *d = NumericTraits<T>::fromPromote(*s);\
1721  return res;\
1722  }\
1723  static TinyVector<T, SIZE> fromRealPromote(RealPromote const & v) {\
1724  TinyVector<T, SIZE> res;\
1725  TinyVector<T, SIZE>::iterator d = res.begin(), dend = res.end();\
1726  RealPromote::const_iterator s = v.begin();\
1727  for(; d != dend; ++d, ++s)\
1728  *d = NumericTraits<T>::fromRealPromote(*s);\
1729  return res;\
1730  }\
1731 }; \
1732 template<>\
1733 struct NormTraits<TinyVector<T, SIZE> >\
1734 {\
1735  typedef TinyVector<T, SIZE> Type;\
1736  typedef Type::SquaredNormType SquaredNormType; \
1737  typedef Type::NormType NormType; \
1738 };
1739 
1740 #define TINYVECTOR_PROMTRAITS1(type1, SIZE) \
1741 template<> \
1742 struct PromoteTraits<TinyVector<type1, SIZE>, TinyVector<type1, SIZE> > \
1743 { \
1744  typedef TinyVector<PromoteTraits<type1, type1>::Promote, SIZE> Promote; \
1745  static Promote toPromote(TinyVector<type1, SIZE> const & v) { \
1746  return static_cast<Promote>(v); } \
1747 };
1748 
1749 #define TINYVECTOR_PROMTRAITS2(type1, type2, SIZE) \
1750 template<> \
1751 struct PromoteTraits<TinyVector<type1, SIZE>, TinyVector<type2, SIZE> > \
1752 { \
1753  typedef TinyVector<PromoteTraits<type1, type2>::Promote, SIZE> Promote; \
1754  static Promote toPromote(TinyVector<type1, SIZE> const & v) { \
1755  return static_cast<Promote>(v); } \
1756  static Promote toPromote(TinyVector<type2, SIZE> const & v) { \
1757  return static_cast<Promote>(v); } \
1758 };
1759 
1760 #define TINYVECTOR_TRAITS(SIZE) \
1761 TINYVECTOR_NUMTRAITS(unsigned char, SIZE)\
1762 TINYVECTOR_NUMTRAITS(int, SIZE)\
1763 TINYVECTOR_NUMTRAITS(float, SIZE)\
1764 TINYVECTOR_NUMTRAITS(double, SIZE)\
1765 TINYVECTOR_PROMTRAITS1(unsigned char, SIZE)\
1766 TINYVECTOR_PROMTRAITS1(int, SIZE)\
1767 TINYVECTOR_PROMTRAITS1(float, SIZE)\
1768 TINYVECTOR_PROMTRAITS1(double, SIZE)\
1769 TINYVECTOR_PROMTRAITS2(float, unsigned char, SIZE)\
1770 TINYVECTOR_PROMTRAITS2(unsigned char, float, SIZE)\
1771 TINYVECTOR_PROMTRAITS2(int, unsigned char, SIZE)\
1772 TINYVECTOR_PROMTRAITS2(unsigned char, int, SIZE)\
1773 TINYVECTOR_PROMTRAITS2(int, float, SIZE)\
1774 TINYVECTOR_PROMTRAITS2(float, int, SIZE)\
1775 TINYVECTOR_PROMTRAITS2(double, unsigned char, SIZE)\
1776 TINYVECTOR_PROMTRAITS2(unsigned char, double, SIZE)\
1777 TINYVECTOR_PROMTRAITS2(int, double, SIZE)\
1778 TINYVECTOR_PROMTRAITS2(double, int, SIZE)\
1779 TINYVECTOR_PROMTRAITS2(double, float, SIZE)\
1780 TINYVECTOR_PROMTRAITS2(float, double, SIZE)
1781 
1782 TINYVECTOR_TRAITS(2)
1783 TINYVECTOR_TRAITS(3)
1784 TINYVECTOR_TRAITS(4)
1785 
1786 #undef TINYVECTOR_NUMTRAITS
1787 #undef TINYVECTOR_PROMTRAITS1
1788 #undef TINYVECTOR_PROMTRAITS2
1789 #undef TINYVECTOR_TRAITS
1790 
1791 #endif // NO_PARTIAL_TEMPLATE_SPECIALIZATION
1792 
1793 
1794 /********************************************************/
1795 /* */
1796 /* TinyVector-Arithmetic */
1797 /* */
1798 /********************************************************/
1799 
1800 /** \addtogroup TinyVectorOperators
1801  */
1802 //@{
1803 
1804  /// component-wise addition
1805 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
1806 inline
1807 typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2, SIZE> >::Promote
1810 {
1811  return typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2 , SIZE> >::Promote(l) += r;
1812 }
1813 
1814  /// component-wise subtraction
1815 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
1816 inline
1817 typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2, SIZE> >::Promote
1820 {
1821  return typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2 , SIZE> >::Promote(l) -= r;
1822 }
1823 
1824  /// component-wise multiplication
1825 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
1826 inline
1827 typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2, SIZE> >::Promote
1830 {
1831  return typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2 , SIZE> >::Promote(l) *= r;
1832 }
1833 
1834  /// component-wise division
1835 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
1836 inline
1837 typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2, SIZE> >::Promote
1840 {
1841  return typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2 , SIZE> >::Promote(l) /= r;
1842 }
1843 
1844  /// component-wise modulo
1845 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
1846 inline
1847 typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2, SIZE> >::Promote
1850 {
1851  return typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2 , SIZE> >::Promote(l) %= r;
1852 }
1853 
1854  /// component-wise left scalar addition
1855 template <class V, int SIZE, class D1, class D2>
1856 inline
1857 typename NumericTraits<TinyVector<V, SIZE> >::RealPromote
1859 {
1860  return typename NumericTraits<TinyVector<V, SIZE> >::RealPromote(r) += v;
1861 }
1862 
1863  /// component-wise right scalar addition
1864 template <class V, int SIZE, class D1, class D2>
1865 inline
1866 typename NumericTraits<TinyVector<V, SIZE> >::RealPromote
1868 {
1869  return typename NumericTraits<TinyVector<V, SIZE> >::RealPromote(l) += v;
1870 }
1871 
1872  /// component-wise left scalar subtraction
1873 template <class V, int SIZE, class D1, class D2>
1874 inline
1875 typename NumericTraits<TinyVector<V, SIZE> >::RealPromote
1877 {
1878  return typename NumericTraits<TinyVector<V, SIZE> >::RealPromote(v) -= r;
1879 }
1880 
1881  /// component-wise right scalar subtraction
1882 template <class V, int SIZE, class D1, class D2>
1883 inline
1884 typename NumericTraits<TinyVector<V, SIZE> >::RealPromote
1886 {
1887  return typename NumericTraits<TinyVector<V, SIZE> >::RealPromote(l) -= v;
1888 }
1889 
1890  /// component-wise left scalar multiplication
1891 template <class V, int SIZE, class D1, class D2>
1892 inline
1893 typename NumericTraits<TinyVector<V, SIZE> >::RealPromote
1894 operator*(double v, TinyVectorBase<V, SIZE, D1, D2> const & r)
1895 {
1896  return typename NumericTraits<TinyVector<V, SIZE> >::RealPromote(r) *= v;
1897 }
1898 
1899  /// component-wise right scalar multiplication
1900 template <class V, int SIZE, class D1, class D2>
1901 inline
1902 typename NumericTraits<TinyVector<V, SIZE> >::RealPromote
1903 operator*(TinyVectorBase<V, SIZE, D1, D2> const & l, double v)
1904 {
1905  return typename NumericTraits<TinyVector<V, SIZE> >::RealPromote(l) *= v;
1906 }
1907 
1908  /// component-wise left scalar division
1909 template <class V, int SIZE, class D1, class D2>
1910 inline
1911 typename NumericTraits<TinyVector<V, SIZE> >::RealPromote
1912 operator/(double v, TinyVectorBase<V, SIZE, D1, D2> const & r)
1913 {
1914  return typename NumericTraits<TinyVector<V, SIZE> >::RealPromote(v) /= r;
1915 }
1916 
1917  /// component-wise right scalar division
1918 template <class V, int SIZE, class D1, class D2>
1919 inline
1920 typename NumericTraits<TinyVector<V, SIZE> >::RealPromote
1921 operator/(TinyVectorBase<V, SIZE, D1, D2> const & l, double v)
1922 {
1923  return typename NumericTraits<TinyVector<V, SIZE> >::RealPromote(l) /= v;
1924 }
1925 
1926  /// component-wise scalar division without type promotion
1927 template <class V, int SIZE, class D1, class D2>
1928 inline
1929 TinyVector<V, SIZE>
1931 {
1932  TinyVector<V, SIZE> result(l);
1933  typedef typename detail::LoopType<SIZE>::type Loop;
1934  Loop::divScalar(result.data(), v);
1935  return result;
1936 }
1937 
1938 
1939  /** Unary negation (construct TinyVector with negative values)
1940  */
1941 template <class V, int SIZE, class D1, class D2>
1942 inline
1943 TinyVector<V, SIZE>
1945 {
1946  TinyVector<V, SIZE> res(detail::dontInit());
1947  typedef typename detail::LoopType<SIZE>::type ltype;
1948  ltype::neg(res.begin(), v.begin());
1949  return res;
1950 }
1951 
1952  /// component-wise absolute value
1953 template <class V, int SIZE, class D1, class D2>
1954 inline
1955 TinyVector<V, SIZE>
1957 {
1958  TinyVector<V, SIZE> res(detail::dontInit());
1959  typedef typename detail::LoopType<SIZE>::type ltype;
1960  ltype::abs(res.begin(), v.begin());
1961  return res;
1962 }
1963 
1964  /** Apply ceil() function to each vector component.
1965  */
1966 template <class V, int SIZE, class D1, class D2>
1967 inline
1968 TinyVector<V, SIZE>
1970 {
1971  TinyVector<V, SIZE> res(detail::dontInit());
1972  typedef typename detail::LoopType<SIZE>::type ltype;
1973  ltype::ceil(res.begin(), v.begin());
1974  return res;
1975 }
1976 
1977  /** Apply floor() function to each vector component.
1978  */
1979 template <class V, int SIZE, class D1, class D2>
1980 inline
1981 TinyVector<V, SIZE>
1983 {
1984  TinyVector<V, SIZE> res(detail::dontInit());
1985  typedef typename detail::LoopType<SIZE>::type ltype;
1986  ltype::floor(res.begin(), v.begin());
1987  return res;
1988 }
1989 
1990  /** Apply round() function to each vector component.
1991  */
1992 template <class V, int SIZE, class D1, class D2>
1993 inline
1994 TinyVector<V, SIZE>
1996 {
1997  TinyVector<V, SIZE> res(detail::dontInit());
1998  typedef typename detail::LoopType<SIZE>::type ltype;
1999  ltype::round(res.begin(), v.begin());
2000  return res;
2001 }
2002 
2003  /** Apply roundi() function to each vector component, i.e. return an integer vector.
2004  */
2005 template <class V, int SIZE, class D1, class D2>
2006 inline
2007 TinyVector<std::ptrdiff_t, SIZE>
2009 {
2010  TinyVector<V, SIZE> res(detail::dontInit());
2011  for(int k=0; k<SIZE; ++k)
2012  res[k] = roundi(v[k]);
2013  return res;
2014 }
2015 
2016  /** Apply sqrt() function to each vector component.
2017  */
2018 template <class V, int SIZE, class D1, class D2>
2019 inline
2020 TinyVector<V, SIZE>
2022 {
2023  TinyVector<V, SIZE> res(detail::dontInit());
2024  typedef typename detail::LoopType<SIZE>::type ltype;
2025  ltype::sqrt(res.begin(), v.begin());
2026  return res;
2027 }
2028 
2029 using std::pow;
2030 
2031  /** Apply pow() function to each vector component.
2032  */
2033 template <class V, int SIZE, class D1, class D2, class E>
2034 inline
2035 TinyVector<V, SIZE>
2036 pow(TinyVectorBase<V, SIZE, D1, D2> const & v, E exponent)
2037 {
2038  TinyVector<V, SIZE> res(v);
2039  typedef typename detail::LoopType<SIZE>::type ltype;
2040  ltype::power(res.begin(), exponent);
2041  return res;
2042 }
2043 
2044  /// cross product
2045 template <class V1, class D1, class D2, class V2, class D3, class D4>
2046 inline
2047 TinyVector<typename PromoteTraits<V1, V2>::Promote, 3>
2049  TinyVectorBase<V2, 3, D3, D4> const & r2)
2050 {
2052  Res;
2053  return Res(r1[1]*r2[2] - r1[2]*r2[1],
2054  r1[2]*r2[0] - r1[0]*r2[2],
2055  r1[0]*r2[1] - r1[1]*r2[0]);
2056 }
2057 
2058  /// dot product
2059 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
2060 inline
2061 typename PromoteTraits<V1, V2>::Promote
2064 {
2065  typedef typename detail::LoopType<SIZE>::type ltype;
2066  return ltype::dot(l.begin(), r.begin());
2067 }
2068 
2069  /// sum of the vector's elements
2070 template <class V, int SIZE, class D1, class D2>
2071 inline
2072 typename NumericTraits<V>::Promote
2074 {
2075  typename NumericTraits<V>::Promote res = l[0];
2076  for(int k=1; k<SIZE; ++k)
2077  res += l[k];
2078  return res;
2079 }
2080 
2081  /// cumulative sum of the vector's elements
2082 template <class V, int SIZE, class D1, class D2>
2083 inline
2084 TinyVector<typename NumericTraits<V>::Promote, SIZE>
2086 {
2088  for(int k=1; k<SIZE; ++k)
2089  res[k] += res[k-1];
2090  return res;
2091 }
2092 
2093  /// product of the vector's elements
2094 template <class V, int SIZE, class D1, class D2>
2095 inline
2096 typename NumericTraits<V>::Promote
2098 {
2099  typename NumericTraits<V>::Promote res = l[0];
2100  for(int k=1; k<SIZE; ++k)
2101  res *= l[k];
2102  return res;
2103 }
2104 
2105  /// cumulative product of the vector's elements
2106 template <class V, int SIZE, class D1, class D2>
2107 inline
2108 TinyVector<typename NumericTraits<V>::Promote, SIZE>
2110 {
2112  for(int k=1; k<SIZE; ++k)
2113  res[k] *= res[k-1];
2114  return res;
2115 }
2116 
2117 using std::min;
2118 
2119  /// element-wise minimum
2120 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
2121 inline
2122 TinyVector<typename PromoteTraits<V1, V2>::Promote, SIZE>
2125 {
2126  typedef typename detail::LoopType<SIZE>::type ltype;
2128  ltype::min(res.begin(), r.begin());
2129  return res;
2130 }
2131 
2132 // we also have to overload min for like-typed argument to prevent match of std::min()
2133 template <class V1, int SIZE, class D1, class D2>
2134 inline
2135 TinyVector<V1, SIZE>
2136 min(TinyVectorBase<V1, SIZE, D1, D2> const & l,
2137  TinyVectorBase<V1, SIZE, D1, D2> const & r)
2138 {
2139  typedef typename detail::LoopType<SIZE>::type ltype;
2140  TinyVector<V1, SIZE> res(l);
2141  ltype::min(res.begin(), r.begin());
2142  return res;
2143 }
2144 
2145 template <class V1, int SIZE>
2146 inline
2147 TinyVector<V1, SIZE>
2148 min(TinyVector<V1, SIZE> const & l,
2149  TinyVector<V1, SIZE> const & r)
2150 {
2151  typedef typename detail::LoopType<SIZE>::type ltype;
2152  TinyVector<V1, SIZE> res(l);
2153  ltype::min(res.begin(), r.begin());
2154  return res;
2155 }
2156 
2157  /// minimum element
2158 template <class V, int SIZE, class D1, class D2>
2159 inline
2160 V const &
2162 {
2163  return l.minimum();
2164 }
2165 
2166 using std::max;
2167 
2168  /// element-wise maximum
2169 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
2170 inline
2171 TinyVector<typename PromoteTraits<V1, V2>::Promote, SIZE>
2174 {
2175  typedef typename detail::LoopType<SIZE>::type ltype;
2177  ltype::max(res.begin(), r.begin());
2178  return res;
2179 }
2180 
2181 // we also have to overload max for like-typed argument to prevent match of std::max()
2182 template <class V1, int SIZE, class D1, class D2>
2183 inline
2184 TinyVector<V1, SIZE>
2185 max(TinyVectorBase<V1, SIZE, D1, D2> const & l,
2186  TinyVectorBase<V1, SIZE, D1, D2> const & r)
2187 {
2188  typedef typename detail::LoopType<SIZE>::type ltype;
2189  TinyVector<V1, SIZE> res(l);
2190  ltype::max(res.begin(), r.begin());
2191  return res;
2192 }
2193 
2194 template <class V1, int SIZE>
2195 inline
2196 TinyVector<V1, SIZE>
2197 max(TinyVector<V1, SIZE> const & l,
2198  TinyVector<V1, SIZE> const & r)
2199 {
2200  typedef typename detail::LoopType<SIZE>::type ltype;
2201  TinyVector<V1, SIZE> res(l);
2202  ltype::max(res.begin(), r.begin());
2203  return res;
2204 }
2205 
2206  /// maximum element
2207 template <class V, int SIZE, class D1, class D2>
2208 inline
2209 V const &
2211 {
2212  return l.maximum();
2213 }
2214 
2215  /// squared norm
2216 template <class V1, int SIZE, class D1, class D2>
2217 inline
2218 typename TinyVectorBase<V1, SIZE, D1, D2>::SquaredNormType
2220 {
2221  return t.squaredMagnitude();
2222 }
2223 
2224  /// squared norm
2225 template <class V, int SIZE>
2226 inline
2227 typename TinyVector<V, SIZE>::SquaredNormType
2229 {
2230  return t.squaredMagnitude();
2231 }
2232 
2233 using std::reverse;
2234 
2235  /// reversed copy
2236 template <class V, int SIZE>
2237 inline
2238 TinyVector<V, SIZE>
2239 reverse(TinyVector<V, SIZE> const & t)
2240 {
2241  return TinyVector<V, SIZE>(t.begin(), ReverseCopy);
2242 }
2243 
2244  /** \brief transposed copy
2245 
2246  Elements are arranged such that <tt>res[k] = t[permutation[k]]</tt>.
2247  */
2248 template <class V, int SIZE, class T>
2249 inline
2250 TinyVector<V, SIZE>
2251 transpose(TinyVector<V, SIZE> const & t, TinyVector<T, SIZE> const & permutation)
2252 {
2253  TinyVector<V, SIZE> res(SkipInitialization);
2254  for(int k=0; k<SIZE; ++k)
2255  {
2256  VIGRA_ASSERT_INSIDE(permutation[k]);
2257  res[k] = t[permutation[k]];
2258  }
2259  return res;
2260 }
2261 
2262  /** \brief Clip negative values.
2263 
2264  All elements smaller than 0 are set to zero.
2265  */
2266 template<class V,int SIZE>
2267 inline
2269  return clipLower(t, V(0));
2270 }
2271 
2272  /** \brief Clip values below a threshold.
2273 
2274  All elements smaller than \a val are set to \a val.
2275  */
2276 template<class V,int SIZE>
2277 inline
2279  TinyVector<V, SIZE> res(SkipInitialization);
2280  for(int k=0; k<SIZE; ++k){
2281  res[k]=t[k]< val ? val : t[k];
2282  }
2283  return res;
2284 }
2285 
2286  /** \brief Clip values above a threshold.
2287 
2288  All elements bigger than \a val are set to \a val.
2289  */
2290 template<class V,int SIZE>
2291 inline
2293  TinyVector<V, SIZE> res(SkipInitialization);
2294  for(int k=0; k<SIZE; ++k){
2295  res[k]=t[k]> val ? val : t[k];
2296  }
2297  return res;
2298 }
2299 
2300  /** \brief Clip values to an interval.
2301 
2302  All elements less than \a valLower are set to \a valLower, all elements
2303  bigger than \a valUpper are set to \a valUpper.
2304  */
2305 template<class V,int SIZE>
2306 inline
2307 TinyVector<V, SIZE> clip(TinyVector<V, SIZE> const & t,const V valLower, const V valUpper){
2308  TinyVector<V, SIZE> res(SkipInitialization);
2309  for(int k=0; k<SIZE; ++k){
2310  res[k] = (t[k] < valLower)
2311  ? valLower
2312  : (t[k] > valUpper)
2313  ? valUpper
2314  : t[k];
2315  }
2316  return res;
2317 }
2318 
2319  /** \brief Clip values to a vector of intervals.
2320 
2321  All elements less than \a valLower are set to \a valLower, all elements
2322  bigger than \a valUpper are set to \a valUpper.
2323  */
2324 template<class V,int SIZE>
2325 inline
2327  TinyVector<V, SIZE> const & valLower,
2328  TinyVector<V, SIZE> const & valUpper)
2329 {
2330  TinyVector<V, SIZE> res(SkipInitialization);
2331  for(int k=0; k<SIZE; ++k){
2332  res[k] = (t[k] < valLower[k])
2333  ? valLower[k]
2334  : (t[k] > valUpper[k])
2335  ? valUpper[k]
2336  : t[k];
2337  }
2338  return res;
2339 }
2340 
2341  /** \brief Round up values to the nearest power of 2.
2342  Implemented only for UInt32
2343  */
2344 template<int SIZE>
2346 {
2347  TinyVector<UInt32,SIZE> res(SkipInitialization);
2348  for( size_t k = 0; k < SIZE; k++)
2349  res[k] = ceilPower2(t[k]);
2350  return res;
2351 }
2352 
2353  /** \brief Round down values to the nearest power of 2.
2354  Implemented only for UInt32
2355  */
2356 template<int SIZE>
2358 {
2359  TinyVector<UInt32, SIZE> res(SkipInitialization);
2360  for( size_t k = 0; k < SIZE; k++)
2361  res[k] = floorPower2(t[k]);
2362  return res;
2363 }
2364 
2365 template<class V,int SIZE>
2366 inline
2367 bool isZero(TinyVector<V, SIZE> const & t){
2368  for(int k=0; k<SIZE; ++k){
2369  if(t[k]!=static_cast<V>(0))
2370  return false;
2371  }
2372  return true;
2373 }
2374 
2375 template<class V,int SIZE>
2376 inline typename NumericTraits<V>::RealPromote
2377 mean(TinyVector<V, SIZE> const & t){
2378  const V sumVal = sum(t);
2379  return static_cast< typename NumericTraits<V>::RealPromote>(sumVal)/SIZE;
2380 }
2381 
2382 
2383 template<class V,int SIZE>
2384 inline typename NumericTraits<V>::RealPromote
2385 sizeDividedSquaredNorm(TinyVector<V, SIZE> const & t){
2386  return squaredNorm(t)/SIZE;
2387 }
2388 
2389 template<class V,int SIZE>
2390 inline typename NumericTraits<V>::RealPromote
2391 sizeDividedNorm(TinyVector<V, SIZE> const & t){
2392  return norm(t)/SIZE;
2393 }
2394 
2395 
2396 
2397 //@}
2398 
2399 // mask cl.exe shortcomings [end]
2400 #if defined(_MSC_VER)
2401 #pragma warning( pop )
2402 #endif
2403 
2404 } // namespace vigra
2405 #undef VIGRA_ASSERT_INSIDE
2406 #endif // VIGRA_TINYVECTOR_HXX
static TinyVector< VALUETYPE, SIZE > linearSequence(VALUETYPE start=VALUETYPE(), VALUETYPE step=VALUETYPE(1))
Factory function for a linear sequence.
Definition: tinyvector.hxx:953
NormType magnitude() const
Definition: tinyvector.hxx:802
const_reference operator[](difference_type i) const
Definition: tinyvector.hxx:853
DERIVED & operator/=(double r)
Definition: tinyvector.hxx:793
PromoteTraits< V1, V2 >::Promote dot(RGBValue< V1, RIDX1, GIDX1, BIDX1 > const &r1, RGBValue< V2, RIDX2, GIDX2, BIDX2 > const &r2)
dot product
Definition: rgbvalue.hxx:906
PromoteTraits< RGBValue< V1, R, G, B >, RGBValue< V2, R, G, B > >::Promote cross(RGBValue< V1, R, G, B > const &r1, RGBValue< V2, R, G, B > const &r2)
cross product
Definition: rgbvalue.hxx:889
TinyVectorView & operator=(TinyVectorView const &r)
Definition: tinyvector.hxx:1309
bool all() const
Definition: tinyvector.hxx:831
TinyVector(value_type const &initial)
Definition: tinyvector.hxx:1031
int y
Definition: diff2d.hxx:392
Int32 roundi(FixedPoint16< IntBits, OverflowHandling > v)
rounding to the nearest integer.
Definition: fixedpoint.hxx:1775
VALUETYPE * pointer
Definition: tinyvector.hxx:667
Diff2D operator-(Diff2D const &a, Diff2D const &b)
Definition: diff2d.hxx:711
value_type const * const_iterator
Definition: tinyvector.hxx:679
double scalar_multiplier
Definition: tinyvector.hxx:691
DERIVED & operator-=(double r)
Definition: tinyvector.hxx:777
VALUETYPE const * const_pointer
Definition: tinyvector.hxx:671
TinyVector(TinyVector const &r)
Definition: tinyvector.hxx:1131
TinyVector< V, SIZE > round(TinyVectorBase< V, SIZE, D1, D2 > const &v)
Definition: tinyvector.hxx:1995
DERIVED & operator+=(TinyVectorBase< T1, SIZE, D1, D2 > const &r)
Definition: tinyvector.hxx:725
TinyVector(TinyVectorBase< U, SIZE, DATA, DERIVED > const &r)
Definition: tinyvector.hxx:1163
void sub(FixedPoint< IntBits1, FracBits1 > l, FixedPoint< IntBits2, FracBits2 > r, FixedPoint< IntBits3, FracBits3 > &result)
subtraction with enforced result type.
Definition: fixedpoint.hxx:583
TinyVector< V, SIZE > div(TinyVectorBase< V, SIZE, D1, D2 > const &l, V v)
component-wise scalar division without type promotion
Definition: tinyvector.hxx:1930
TinyVector< V, SIZE > clipUpper(TinyVector< V, SIZE > const &t, const V val)
Clip values above a threshold.
Definition: tinyvector.hxx:2292
TinyVector(value_type const &i1, value_type const &i2, value_type const &i3, value_type const &i4, value_type const &i5)
Definition: tinyvector.hxx:1098
DERIVED & operator+=(double r)
Definition: tinyvector.hxx:769
int x
Definition: diff2d.hxx:385
FFTWComplex< R >::SquaredNormType squaredNorm(const FFTWComplex< R > &a)
squared norm (= squared magnitude)
Definition: fftw3.hxx:1044
V power(const V &x)
Exponentiation to a positive integer power by squaring.
Definition: mathutil.hxx:427
const_iterator begin() const
Definition: tinyvector.hxx:868
const_iterator end() const
Definition: tinyvector.hxx:872
int round(FixedPoint< IntBits, FracBits > v)
rounding to the nearest integer.
Definition: fixedpoint.hxx:683
iterator end()
Definition: tinyvector.hxx:864
Diff2D operator+(Diff2D const &a, Diff2D const &b)
Definition: diff2d.hxx:739
Two dimensional difference vector.
Definition: diff2d.hxx:185
void add(FixedPoint< IntBits1, FracBits1 > l, FixedPoint< IntBits2, FracBits2 > r, FixedPoint< IntBits3, FracBits3 > &result)
addition with enforced result type.
Definition: fixedpoint.hxx:561
const_iterator cbegin() const
Definition: tinyvector.hxx:876
TinyVector< V, SIZE > ceil(TinyVectorBase< V, SIZE, D1, D2 > const &v)
Definition: tinyvector.hxx:1969
SquaredNormType squaredMagnitude() const
Definition: tinyvector.hxx:810
bool allLess(TinyVectorBase< V1, SIZE, D1, D2 > const &l, TinyVectorBase< V2, SIZE, D3, D4 > const &r)
pointwise less-than
Definition: tinyvector.hxx:1375
TinyVector(Diff2D const &initial)
Definition: tinyvector.hxx:1051
TinyVector(const_pointer data, ReverseCopyTag)
Definition: tinyvector.hxx:1154
DERIVED & operator/=(TinyVectorBase< T1, SIZE, D1, D2 > const &r)
Definition: tinyvector.hxx:752
TinyVector< V, SIZE > sqrt(TinyVectorBase< V, SIZE, D1, D2 > const &v)
Definition: tinyvector.hxx:2021
TinyVector & copy(TinyVectorBase< U, USIZE, DATA, DERIVED > const &r)
Definition: tinyvector.hxx:1210
value_type * iterator
Definition: tinyvector.hxx:675
DERIVED & operator*=(double r)
Definition: tinyvector.hxx:785
DERIVED & operator-=(TinyVectorBase< T1, SIZE, D1, D2 > const &r)
Definition: tinyvector.hxx:734
FFTWComplex< R >::NormType norm(const FFTWComplex< R > &a)
norm (= magnitude)
Definition: fftw3.hxx:1037
TinyVector & operator=(TinyVector const &r)
Definition: tinyvector.hxx:1171
TinyVector()
Definition: tinyvector.hxx:1113
VALUETYPE value_type
Definition: tinyvector.hxx:655
TinyVector< V, SIZE > clip(TinyVector< V, SIZE > const &t, const V valLower, const V valUpper)
Clip values to an interval.
Definition: tinyvector.hxx:2307
void mul(FixedPoint< IntBits1, FracBits1 > l, FixedPoint< IntBits2, FracBits2 > r, FixedPoint< IntBits3, FracBits3 > &result)
multiplication with enforced result type.
Definition: fixedpoint.hxx:605
NumericTraits< V >::Promote prod(TinyVectorBase< V, SIZE, D1, D2 > const &l)
product of the vector's elements
Definition: tinyvector.hxx:2097
TinyVectorView(TinyVectorBase< T, SIZE, DATA, DERIVED > const &other)
Definition: tinyvector.hxx:1301
NumericTraits< V >::Promote sum(TinyVectorBase< V, SIZE, D1, D2 > const &l)
sum of the vector's elements
Definition: tinyvector.hxx:2073
TinyVector(value_type const &i1, value_type const &i2, value_type const &i3, value_type const &i4)
Definition: tinyvector.hxx:1084
TinyVectorView()
Definition: tinyvector.hxx:1276
bool operator!=(FFTWComplex< R > const &a, const FFTWComplex< R > &b)
not equal
Definition: fftw3.hxx:841
void init(value_type initial)
Definition: tinyvector.hxx:717
VALUETYPE & reference
Definition: tinyvector.hxx:659
iterator begin()
Definition: tinyvector.hxx:861
bool operator==(FFTWComplex< R > const &a, const FFTWComplex< R > &b)
equal
Definition: fftw3.hxx:825
size_type size() const
Definition: tinyvector.hxx:913
TinyVector< V, SIZE > pow(TinyVectorBase< V, SIZE, D1, D2 > const &v, E exponent)
Definition: tinyvector.hxx:2036
VALUETYPE const & const_reference
Definition: tinyvector.hxx:663
TinyVector & operator=(value_type const &v)
Definition: tinyvector.hxx:1199
TinyVector< V, SIZE >::SquaredNormType squaredNorm(TinyVector< V, SIZE > const &t)
squared norm
Definition: tinyvector.hxx:2228
static TinyVector< VALUETYPE, SIZE > unitVector(int k)
Factory function for a unit vector for dimension k.
Definition: tinyvector.hxx:941
TinyVector(value_type const &i1, value_type const &i2, value_type const &i3)
Definition: tinyvector.hxx:1072
TinyVector(SkipInitializationTag)
Definition: tinyvector.hxx:1121
TinyVectorView & operator=(TinyVectorBase< U, SIZE, DATA, DERIVED > const &r)
Definition: tinyvector.hxx:1318
V const & max(TinyVectorBase< V, SIZE, D1, D2 > const &l)
maximum element
Definition: tinyvector.hxx:2210
TinyVector< typename NumericTraits< V >::Promote, SIZE > cumsum(TinyVectorBase< V, SIZE, D1, D2 > const &l)
cumulative sum of the vector's elements
Definition: tinyvector.hxx:2085
Wrapper for fixed size vectors.
Definition: tinyvector.hxx:621
bool allGreaterEqual(TinyVectorBase< V1, SIZE, D1, D2 > const &l, TinyVectorBase< V2, SIZE, D3, D4 > const &r)
pointwise greater-equal
Definition: tinyvector.hxx:1411
Class for fixed size vectors.This class contains an array of size SIZE of the specified VALUETYPE...
Definition: accessor.hxx:940
bool closeAtTolerance(T1 l, T2 r, typename PromoteTraits< T1, T2 >::Promote epsilon)
Tolerance based floating-point equality.
Definition: mathutil.hxx:1638
FixedPoint16< IntBits3, OverflowHandling > & div(FixedPoint16< IntBits1, OverflowHandling > l, FixedPoint16< IntBits2, OverflowHandling > r, FixedPoint16< IntBits3, OverflowHandling > &result)
division with enforced result type.
Definition: fixedpoint.hxx:1616
unsigned int size_type
Definition: tinyvector.hxx:683
TinyVectorView< VALUETYPE, TO-FROM > subarray() const
Definition: tinyvector.hxx:887
TinyVectorView(TinyVectorView const &other)
Definition: tinyvector.hxx:1292
Base class for fixed size vectors.
Definition: tinyvector.hxx:82
FFTWComplex< R >::NormType abs(const FFTWComplex< R > &a)
absolute value (= magnitude)
Definition: fftw3.hxx:1002
TinyVector< V, SIZE > floor(TinyVectorBase< V, SIZE, D1, D2 > const &v)
Definition: tinyvector.hxx:1982
TinyVector(U const *data)
Definition: tinyvector.hxx:1140
SquareRootTraits< SquaredNormType >::SquareRootResult NormType
Definition: tinyvector.hxx:699
VALUETYPE const & maximum() const
Definition: tinyvector.hxx:824
std::ptrdiff_t difference_type
Definition: tinyvector.hxx:687
TinyVector< V, SIZE > clipLower(TinyVector< V, SIZE > const &t)
Clip negative values.
Definition: tinyvector.hxx:2268
UInt32 floorPower2(UInt32 x)
Round down to the nearest power of 2.
Definition: mathutil.hxx:317
bool any() const
Definition: tinyvector.hxx:838
TinyVector(value_type const &i1, value_type const &i2)
Definition: tinyvector.hxx:1061
bool allLessEqual(TinyVectorBase< V1, SIZE, D1, D2 > const &l, TinyVectorBase< V2, SIZE, D3, D4 > const &r)
pointwise less-equal
Definition: tinyvector.hxx:1399
UInt32 ceilPower2(UInt32 x)
Round up to the nearest power of 2.
Definition: mathutil.hxx:294
bool allGreater(TinyVectorBase< V1, SIZE, D1, D2 > const &l, TinyVectorBase< V2, SIZE, D3, D4 > const &r)
pointwise greater-than
Definition: tinyvector.hxx:1387
int ceil(FixedPoint< IntBits, FracBits > v)
rounding up.
Definition: fixedpoint.hxx:675
const_iterator cend() const
Definition: tinyvector.hxx:880
TinyVector< V, SIZE > reverse(TinyVector< V, SIZE > const &t)
reversed copy
Definition: tinyvector.hxx:2239
TinyVectorView(const_pointer data)
Definition: tinyvector.hxx:1284
TinyVector & operator=(TinyVectorBase< U, SIZE, DATA, DERIVED > const &r)
Definition: tinyvector.hxx:1180
int floor(FixedPoint< IntBits, FracBits > v)
rounding down.
Definition: fixedpoint.hxx:667
TinyVector< typename NumericTraits< V >::Promote, SIZE > cumprod(TinyVectorBase< V, SIZE, D1, D2 > const &l)
cumulative product of the vector's elements
Definition: tinyvector.hxx:2109
VALUETYPE const & minimum() const
Definition: tinyvector.hxx:817
DERIVED & operator%=(TinyVectorBase< T1, SIZE, D1, D2 > const &r)
Definition: tinyvector.hxx:761
void init(Iterator i, Iterator end)
Definition: tinyvector.hxx:708
TinyVector< V, SIZE > abs(TinyVectorBase< V, SIZE, D1, D2 > const &v)
component-wise absolute value
Definition: tinyvector.hxx:1956
NormTraits< VALUETYPE >::SquaredNormType SquaredNormType
Definition: tinyvector.hxx:695
DERIVED & operator*=(TinyVectorBase< T1, SIZE, D1, D2 > const &r)
Definition: tinyvector.hxx:743
TinyVector & operator=(Diff2D const &r)
Definition: tinyvector.hxx:1190
reference operator[](difference_type i)
Definition: tinyvector.hxx:845
SquareRootTraits< FixedPoint< IntBits, FracBits > >::SquareRootResult sqrt(FixedPoint< IntBits, FracBits > v)
square root.
Definition: fixedpoint.hxx:616
PromoteTraits< TinyVector< V1, SIZE >, TinyVector< V2, SIZE > >::Promote operator%(TinyVectorBase< V1, SIZE, D1, D2 > const &l, TinyVectorBase< V2, SIZE, D3, D4 > const &r)
component-wise modulo
Definition: tinyvector.hxx:1848
TinyVector(lemon::Invalid const &)
Definition: tinyvector.hxx:1041
V const & min(TinyVectorBase< V, SIZE, D1, D2 > const &l)
minimum element
Definition: tinyvector.hxx:2161
PromoteTraits< V1, V2 >::Promote dot(TinyVectorBase< V1, SIZE, D1, D2 > const &l, TinyVectorBase< V2, SIZE, D3, D4 > const &r)
dot product
Definition: tinyvector.hxx:2062

© 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.11.1 (Fri May 19 2017)