[ 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 "config.hxx"
44 #include "error.hxx"
45 #include "metaprogramming.hxx"
46 #include "numerictraits.hxx"
47 #include "memory.hxx"
48 #include "mathutil.hxx"
49 #include "diff2d.hxx"
50 
51 #ifdef VIGRA_CHECK_BOUNDS
52 #define VIGRA_ASSERT_INSIDE(diff) \
53  vigra_precondition(diff >= 0, "Index out of bounds");\
54  vigra_precondition(diff < SIZE, "Index out of bounds");
55 #else
56 #define VIGRA_ASSERT_INSIDE(diff)
57 #endif
58 
59 namespace vigra {
60 
61 using VIGRA_CSTD::abs;
62 using VIGRA_CSTD::ceil;
63 using VIGRA_CSTD::floor;
64 
65 
66 template <class V1, int SIZE, class D1, class D2>
67 class TinyVectorBase;
68 
69 template <class V1, int SIZE, class D1, class D2>
70 inline
71 typename TinyVectorBase<V1, SIZE, D1, D2>::SquaredNormType
72 squaredNorm(TinyVectorBase<V1, SIZE, D1, D2> const & t);
73 
74 
75 namespace detail {
76 
77 #define VIGRA_EXEC_LOOP(NAME, OPER) \
78  template <class T1, class T2> \
79  static void NAME(T1 * left, T2 const * right) \
80  { \
81  for(int i=0; i<LEVEL; ++i) \
82  (left[i]) OPER (right[i]); \
83  }
84 
85 #define VIGRA_EXEC_LOOP_SCALAR(NAME, OPER) \
86  template <class T1, class T2> \
87  static void NAME(T1 * left, T2 right) \
88  { \
89  for(int i=0; i<LEVEL; ++i) \
90  (left[i]) = detail::RequiresExplicitCast<T1>::cast((left[i]) OPER (right)); \
91  }
92 
93 template <int LEVEL>
94 struct ExecLoop
95 {
96  template <class T1, class T2>
97  static void assignCast(T1 * left, T2 const * right)
98  {
99  for(int i=0; i<LEVEL; ++i)
100  left[i] = detail::RequiresExplicitCast<T1>::cast(right[i]);
101  }
102 
103  template <class T1, class T2>
104  static void reverseAssign(T1 * left, T2 const * right)
105  {
106  for(int i=0; i<LEVEL; ++i)
107  left[i] = right[-i];
108  }
109 
110  template <class T1, class T2>
111  static void assignScalar(T1 * left, T2 right)
112  {
113  for(int i=0; i<LEVEL; ++i)
114  left[i] = detail::RequiresExplicitCast<T1>::cast(right);
115  }
116 
117  VIGRA_EXEC_LOOP(assign, =)
118  VIGRA_EXEC_LOOP(add, +=)
119  VIGRA_EXEC_LOOP(sub, -=)
120  VIGRA_EXEC_LOOP(mul, *=)
121  VIGRA_EXEC_LOOP(div, /=)
122  VIGRA_EXEC_LOOP(neg, = -)
123  VIGRA_EXEC_LOOP(abs, = vigra::abs)
124  VIGRA_EXEC_LOOP(floor, = vigra::floor)
125  VIGRA_EXEC_LOOP(ceil, = vigra::ceil)
126  VIGRA_EXEC_LOOP(fromPromote, = NumericTraits<T1>::fromPromote)
127  VIGRA_EXEC_LOOP(fromRealPromote, = NumericTraits<T1>::fromRealPromote)
128  VIGRA_EXEC_LOOP_SCALAR(mulScalar, *)
129  VIGRA_EXEC_LOOP_SCALAR(divScalar, /)
130 
131  template <class T1, class T2>
132  static bool notEqual(T1 const * left, T2 const * right)
133  {
134  for(int i=0; i<LEVEL; ++i)
135  if(left[i] != right[i])
136  return true;
137  return false;
138  }
139 
140  template <class T>
141  static typename NumericTraits<T>::Promote
142  dot(T const * d)
143  {
144  typename NumericTraits<T>::Promote res(*d * *d);
145  for(int i=1; i<LEVEL; ++i)
146  res += d[i] * d[i];
147  return res;
148  }
149 
150  template <class T1, class T2>
151  static typename PromoteTraits<T1, T2>::Promote
152  dot(T1 const * left, T2 const * right)
153  {
154  typename PromoteTraits<T1, T2>::Promote res(*left * *right);
155  for(int i=1; i<LEVEL; ++i)
156  res += left[i] * right[i];
157  return res;
158  }
159 
160  template <class T>
161  static typename NormTraits<T>::SquaredNormType
162  squaredNorm(T const * d)
163  {
164  typename NormTraits<T>::SquaredNormType res = vigra::squaredNorm(*d);
165  for(int i=1; i<LEVEL; ++i)
166  res += vigra::squaredNorm(d[i]);
167  return res;
168  }
169 };
170 
171 template <int LEVEL>
172 struct UnrollDot
173 {
174  template <class T>
175  static typename NumericTraits<T>::Promote
176  dot(T const * d)
177  {
178  return *d * *d + UnrollDot<LEVEL-1>::dot(d+1);
179  }
180 
181  template <class T1, class T2>
182  static typename PromoteTraits<T1, T2>::Promote
183  dot(T1 const * left, T2 const * right)
184  {
185  return *left * *right + UnrollDot<LEVEL-1>::dot(left+1, right+1);
186  }
187 };
188 
189 template <>
190 struct UnrollDot<1>
191 {
192  template <class T>
193  static typename NumericTraits<T>::Promote
194  dot(T const * d)
195  {
196  return *d * *d ;
197  }
198 
199  template <class T1, class T2>
200  static typename PromoteTraits<T1, T2>::Promote
201  dot(T1 const * left, T2 const * right)
202  {
203  return *left * *right;
204  }
205 };
206 
207 template <int LEVEL>
208 struct UnrollSquaredNorm
209 {
210  template <class T>
211  static typename NormTraits<T>::SquaredNormType
212  squaredNorm(T const * d)
213  {
215  }
216 
217  static std::ptrdiff_t
218  squaredNorm(std::ptrdiff_t const * d)
219  {
220  return (*d)*(*d) + UnrollSquaredNorm<LEVEL-1>::squaredNorm(d+1);
221  }
222 };
223 
224 template <>
225 struct UnrollSquaredNorm<1>
226 {
227  template <class T>
228  static typename NormTraits<T>::SquaredNormType
229  squaredNorm(T const * d)
230  {
231  return vigra::squaredNorm(*d);
232  }
233 
234  static std::ptrdiff_t
235  squaredNorm(std::ptrdiff_t const * d)
236  {
237  return (*d)*(*d);
238  }
239 };
240 
241 #undef VIGRA_EXEC_LOOP
242 #undef VIGRA_EXEC_LOOP_SCALAR
243 
244 #define VIGRA_UNROLL_LOOP(NAME, OPER) \
245  template <class T1, class T2> \
246  static void NAME(T1 * left, T2 const * right) \
247  { \
248  (*left) OPER (*right); \
249  UnrollLoop<LEVEL-1>::NAME(left+1, right+1); \
250  }
251 
252 #define VIGRA_UNROLL_LOOP_SCALAR(NAME, OPER) \
253  template <class T1, class T2> \
254  static void NAME(T1 * left, T2 right) \
255  { \
256  (*left) = detail::RequiresExplicitCast<T1>::cast((*left) OPER (right)); \
257  UnrollLoop<LEVEL-1>::NAME(left+1, right); \
258  }
259 
260 
261 template <int LEVEL>
262 struct UnrollLoop
263 {
264  template <class T1, class T2>
265  static void reverseAssign(T1 * left, T2 const * right)
266  {
267  *left = *right;
268  UnrollLoop<LEVEL-1>::reverseAssign(left+1, right-1);
269  }
270 
271  template <class T1, class T2>
272  static void assignCast(T1 * left, T2 const * right)
273  {
274  *left = detail::RequiresExplicitCast<T1>::cast(*right);
275  UnrollLoop<LEVEL-1>::assignCast(left+1, right+1);
276  }
277 
278  template <class T1, class T2>
279  static void assignScalar(T1 * left, T2 right)
280  {
281  *left = detail::RequiresExplicitCast<T1>::cast(right);
282  UnrollLoop<LEVEL-1>::assignScalar(left+1, right);
283  }
284 
285  VIGRA_UNROLL_LOOP(assign, =)
286  VIGRA_UNROLL_LOOP(add, +=)
287  VIGRA_UNROLL_LOOP(sub, -=)
288  VIGRA_UNROLL_LOOP(mul, *=)
289  VIGRA_UNROLL_LOOP(div, /=)
290  VIGRA_UNROLL_LOOP(neg, = -)
291  VIGRA_UNROLL_LOOP(abs, = vigra::abs)
292  VIGRA_UNROLL_LOOP(floor, = vigra::floor)
293  VIGRA_UNROLL_LOOP(ceil, = vigra::ceil)
294  VIGRA_UNROLL_LOOP(fromPromote, = NumericTraits<T1>::fromPromote)
295  VIGRA_UNROLL_LOOP(fromRealPromote, = NumericTraits<T1>::fromRealPromote)
296  VIGRA_UNROLL_LOOP_SCALAR(mulScalar, *)
297  VIGRA_UNROLL_LOOP_SCALAR(divScalar, /)
298 
299  template <class T1, class T2>
300  static bool notEqual(T1 const * left, T2 const * right)
301  {
302  return (*left != *right) || UnrollLoop<LEVEL - 1>::notEqual(left+1, right+1);
303  }
304 
305  template <class T>
306  static typename NumericTraits<T>::Promote
307  dot(T const * d)
308  {
309  return UnrollDot<LEVEL>::dot(d);
310  }
311 
312  template <class T1, class T2>
313  static typename PromoteTraits<T1, T2>::Promote
314  dot(T1 const * left, T2 const * right)
315  {
316  return UnrollDot<LEVEL>::dot(left, right);
317  }
318 
319  template <class T>
320  static typename NormTraits<T>::SquaredNormType
321  squaredNorm(T const * d)
322  {
324  }
325 };
326 
327 #undef VIGRA_UNROLL_LOOP
328 #undef VIGRA_UNROLL_LOOP_SCALAR
329 
330 template <>
331 struct UnrollLoop<0>
332 {
333  template <class T1, class T2>
334  static void reverseAssign(T1, T2) {}
335  template <class T1, class T2>
336  static void assignCast(T1, T2) {}
337  template <class T1, class T2>
338  static void assign(T1, T2) {}
339  template <class T1, class T2>
340  static void assignScalar(T1, T2) {}
341  template <class T1, class T2>
342  static void add(T1, T2) {}
343  template <class T1, class T2>
344  static void sub(T1, T2) {}
345  template <class T1, class T2>
346  static void mul(T1, T2) {}
347  template <class T1, class T2>
348  static void mulScalar(T1, T2) {}
349  template <class T1, class T2>
350  static void div(T1, T2) {}
351  template <class T1, class T2>
352  static void divScalar(T1, T2) {}
353  template <class T1, class T2>
354  static void fromPromote(T1, T2) {}
355  template <class T1, class T2>
356  static void fromRealPromote(T1, T2) {}
357  template <class T1, class T2>
358  static void neg(T1, T2) {}
359  template <class T1, class T2>
360  static void abs(T1, T2) {}
361  template <class T1, class T2>
362  static void floor(T1, T2) {}
363  template <class T1, class T2>
364  static void ceil(T1, T2) {}
365  template <class T1, class T2>
366  static bool notEqual(T1, T2) { return false; }
367 };
368 
369 template <int SIZE>
370 struct LoopType
371 {
372  typedef typename IfBool<(SIZE < 5), UnrollLoop<SIZE>, ExecLoop<SIZE> >::type type;
373 
374 };
375 
376 struct DontInit {};
377 
378 inline DontInit dontInit() {return DontInit(); }
379 
380 } // namespace detail
381 
382 template <class T, int SIZE>
383 class TinyVector;
384 
385 template <class T, int SIZE>
386 class TinyVectorView;
387 
388 /********************************************************/
389 /* */
390 /* TinyVectorBase */
391 /* */
392 /********************************************************/
393 
394 /** \brief Base class for fixed size vectors.
395 
396  This class contains functionality shared by
397  \ref TinyVector and \ref TinyVectorView, and enables these classes
398  to be freely mixed within expressions. It is typically not used directly.
399 
400  <b>\#include</b> <<a href="tinyvector_8hxx-source.html">vigra/tinyvector.hxx</a>><br>
401  Namespace: vigra
402 **/
403 template <class VALUETYPE, int SIZE, class DATA, class DERIVED>
405 {
406  TinyVectorBase(TinyVectorBase const &); // do not use
407 
408  TinyVectorBase & operator=(TinyVectorBase const & other); // do not use
409 
410  protected:
411 
412  typedef typename detail::LoopType<SIZE>::type Loop;
413 
415  {}
416 
417  public:
418  /** STL-compatible definition of valuetype
419  */
420  typedef VALUETYPE value_type;
421 
422  /** reference (return of operator[]).
423  */
424  typedef VALUETYPE & reference;
425 
426  /** const reference (return of operator[] const).
427  */
428  typedef VALUETYPE const & const_reference;
429 
430  /** pointer (return of operator->).
431  */
432  typedef VALUETYPE * pointer;
433 
434  /** const pointer (return of operator-> const).
435  */
436  typedef VALUETYPE const * const_pointer;
437 
438  /** STL-compatible definition of iterator
439  */
440  typedef value_type * iterator;
441 
442  /** STL-compatible definition of const iterator
443  */
444  typedef value_type const * const_iterator;
445 
446  /** STL-compatible definition of size_type
447  */
448  typedef unsigned int size_type;
449 
450  /** STL-compatible definition of difference_type
451  */
452  typedef int difference_type;
453 
454  /** the scalar type for the outer product
455  */
456  typedef double scalar_multiplier;
457 
458  /** the vector's squared norm type
459  */
460  typedef typename NormTraits<VALUETYPE>::SquaredNormType SquaredNormType;
461 
462  /** the vector's norm type
463  */
464  typedef typename SquareRootTraits<SquaredNormType>::SquareRootResult NormType;
465 
466  /** the vector's size
467  */
468  enum { static_size = SIZE };
469 
470  /** Initialize from another sequence (must have length SIZE!)
471  */
472  template <class Iterator>
473  void init(Iterator i, Iterator end)
474  {
475  vigra_precondition(end-i == SIZE,
476  "TinyVector::init(): Sequence has wrong size.");
477  Loop::assignCast(data_, i);
478  }
479 
480  /** Initialize with constant value
481  */
482  void init(value_type initial)
483  {
484  Loop::assignScalar(data_, initial);
485  }
486 
487  /** Component-wise add-assignment
488  */
489  template <class T1, class D1, class D2>
491  {
492  Loop::add(data_, r.begin());
493  return static_cast<DERIVED &>(*this);
494  }
495 
496  /** Component-wise subtract-assignment
497  */
498  template <class T1, class D1, class D2>
500  {
501  Loop::sub(data_, r.begin());
502  return static_cast<DERIVED &>(*this);
503  }
504 
505  /** Component-wise multiply-assignment
506  */
507  template <class T1, class D1, class D2>
509  {
510  Loop::mul(data_, r.begin());
511  return static_cast<DERIVED &>(*this);
512  }
513 
514  /** Component-wise divide-assignment
515  */
516  template <class T1, class D1, class D2>
518  {
519  Loop::div(data_, r.begin());
520  return static_cast<DERIVED &>(*this);
521  }
522 
523  /** Component-wise scalar multiply-assignment
524  */
525  DERIVED & operator*=(double r)
526  {
527  Loop::mulScalar(data_, r);
528  return static_cast<DERIVED &>(*this);
529  }
530 
531  /** Component-wise scalar divide-assignment
532  */
533  DERIVED & operator/=(double r)
534  {
535  Loop::divScalar(data_, r);
536  return static_cast<DERIVED &>(*this);
537  }
538 
539  /** Calculate magnitude.
540  */
542  {
543  return sqrt(static_cast<typename
544  SquareRootTraits<SquaredNormType>::SquareRootArgument>(squaredMagnitude()));
545  }
546 
547  /** Calculate squared magnitude.
548  */
550  {
551  return Loop::squaredNorm(data_);
552  }
553 
554  /** Access component by index.
555  */
557  {
558  VIGRA_ASSERT_INSIDE(i);
559  return data_[i];
560  }
561 
562  /** Get component by index.
563  */
565  {
566  VIGRA_ASSERT_INSIDE(i);
567  return data_[i];
568  }
569 
570  /** Get random access iterator to begin of vector.
571  */
572  iterator begin() { return data_; }
573  /** Get random access iterator past-the-end of vector.
574  */
575  iterator end() { return data_ + SIZE; }
576 
577  /** Get const random access iterator to begin of vector.
578  */
579  const_iterator begin() const { return data_; }
580 
581  /** Get const random access iterator past-the-end of vector.
582  */
583  const_iterator end() const { return data_ + SIZE; }
584 
585  /** Size of TinyVector vector always equals the template parameter SIZE.
586  */
587  size_type size() const { return SIZE; }
588 
589  pointer data() { return data_; }
590 
591  const_pointer data() const { return data_; }
592 
593  protected:
594 
595  DATA data_;
596 };
597 
598 /** \brief Class for fixed size vectors.
599  \ingroup RangesAndPoints
600 
601  This class contains an array of size SIZE of the specified VALUETYPE.
602  The interface conforms to STL vector, except that there are no functions
603  that change the size of a TinyVector.
604 
605  \ref TinyVectorOperators "Arithmetic operations"
606  on TinyVectors are defined as component-wise applications of these
607  operations. Addition and subtraction of two TinyVectors
608  (+=, -=, +, -, unary -), multiplication and division of an
609  TinyVector with a double, and NumericTraits/PromoteTraits are defined,
610  so that TinyVector fulfills the requirements of \ref LinearAlgebraConcept "Linear Algebra".
611 
612  VIGRA algorithms typically use \ref vigra::VectorAccessor to access
613  TinyVectors as a whole, or specific components of them.
614 
615  See also:<br>
616  <UL style="list-style-image:url(documents/bullet.gif)">
617  <LI> \ref vigra::TinyVectorBase
618  <LI> \ref vigra::TinyVectorView
619  <LI> \ref TinyVectorTraits
620  <LI> \ref TinyVectorOperators
621  </UL>
622 
623  <b>\#include</b> <<a href="tinyvector_8hxx-source.html">vigra/tinyvector.hxx</a>><br>
624  Namespace: vigra
625 **/
626 template <class T, int SIZE>
628 : public TinyVectorBase<T, SIZE, T[SIZE], TinyVector<T, SIZE> >
629 {
631  typedef typename BaseType::Loop Loop;
632 
633  public:
634 
636  typedef typename BaseType::reference reference;
638  typedef typename BaseType::pointer pointer;
640  typedef typename BaseType::iterator iterator;
642  typedef typename BaseType::size_type size_type;
646  typedef typename BaseType::NormType NormType;
647 
648  enum ReverseCopyTag { ReverseCopy };
649 
650  /** Construction with constant value
651  */
652  explicit TinyVector(value_type const & initial)
653  : BaseType()
654  {
655  Loop::assignScalar(BaseType::begin(), initial);
656  }
657 
658  /** Construction with Diff2D (only implemented for 2D TinyVector)
659  */
660  explicit TinyVector(Diff2D const & initial)
661  : BaseType()
662  {
663  BaseType::data_[0] = detail::RequiresExplicitCast<T>::cast(initial.x);
664  BaseType::data_[1] = detail::RequiresExplicitCast<T>::cast(initial.y);
665  }
666 
667  /** Construction with explicit values.
668  Call only if SIZE == 2
669  */
670  TinyVector(value_type const & i1, value_type const & i2)
671  : BaseType()
672  {
673  BaseType::data_[0] = i1;
674  BaseType::data_[1] = i2;
675  }
676 
677  /** Construction with explicit values.
678  Call only if SIZE == 3
679  */
680  TinyVector(value_type const & i1, value_type const & i2, value_type const & i3)
681  : BaseType()
682  {
683  BaseType::data_[0] = i1;
684  BaseType::data_[1] = i2;
685  BaseType::data_[2] = i3;
686  }
687 
688  /** Construction with explicit values.
689  Call only if SIZE == 4
690  */
691  TinyVector(value_type const & i1, value_type const & i2,
692  value_type const & i3, value_type const & i4)
693  : BaseType()
694  {
695  BaseType::data_[0] = i1;
696  BaseType::data_[1] = i2;
697  BaseType::data_[2] = i3;
698  BaseType::data_[3] = i4;
699  }
700 
701  /** Construction with explicit values.
702  Call only if SIZE == 5
703  */
704  TinyVector(value_type const & i1, value_type const & i2,
705  value_type const & i3, value_type const & i4,
706  value_type const & i5)
707  : BaseType()
708  {
709  BaseType::data_[0] = i1;
710  BaseType::data_[1] = i2;
711  BaseType::data_[2] = i3;
712  BaseType::data_[3] = i4;
713  BaseType::data_[4] = i5;
714  }
715  /** Default constructor (initializes all components with zero)
716  */
718  : BaseType()
719  {
720  Loop::assignScalar(BaseType::data_, NumericTraits<value_type>::zero());
721  }
722 
723  /** Copy constructor.
724  */
726  : BaseType()
727  {
728  Loop::assign(BaseType::data_, r.data_);
729  }
730 
731  /** Constructor from C array.
732  */
733  explicit TinyVector(const_pointer data)
734  : BaseType()
735  {
736  Loop::assign(BaseType::data_, data);
737  }
738 
739  /** Constructor by reverse copy from C array.
740 
741  Usage:
742  \code
743  TinyVector<int, 3> v(1,2,3);
744  TinyVector<int, 3> reverse(v.begin(), TinyVector<int, 3>::ReverseCopy);
745  \endcode
746  */
747  explicit TinyVector(const_pointer data, ReverseCopyTag)
748  : BaseType()
749  {
750  Loop::reverseAssign(BaseType::data_, data+SIZE-1);
751  }
752 
753  /** Copy assignment.
754  */
756  {
757  Loop::assign(BaseType::data_, r.data_);
758  return *this;
759  }
760 
761  /** Assignment from Diff2D.
762  */
764  {
765  BaseType::data_[0] = detail::RequiresExplicitCast<T>::cast(r.x);
766  BaseType::data_[1] = detail::RequiresExplicitCast<T>::cast(r.y);
767  return *this;
768  }
769 
770  /** Copy with type conversion.
771  */
772  template <class U>
774  : BaseType()
775  {
776  Loop::assignCast(BaseType::data_, r.begin());
777  }
778 
779  /** Copy with type conversion.
780  */
781  template <class U, class DATA, class DERIVED>
783  : BaseType()
784  {
785  Loop::assignCast(BaseType::data_, r.begin());
786  }
787 
788  /** Copy assignment with type conversion.
789  */
790  template <class U, class DATA, class DERIVED>
792  {
793  Loop::assignCast(BaseType::data_, r.begin());
794  return *this;
795  }
796 
797  explicit TinyVector(SkipInitializationTag)
798  : BaseType()
799  {}
800 
801  explicit TinyVector(detail::DontInit)
802  : BaseType()
803  {}
804 };
805 
806 /** \brief Wrapper for fixed size vectors.
807 
808  This class wraps an array of size SIZE of the specified VALUETYPE.
809  Thus, the array can be accessed with an interface similar to
810  that of std::vector (except that there are no functions
811  that change the size of a TinyVectorView). The TinyVectorView
812  does <em>not</em> assume ownership of the given memory.
813 
814  \ref TinyVectorOperators "Arithmetic operations"
815  on TinyVectorViews are defined as component-wise applications of these
816  operations. Addition and subtraction of two TinyVectorViews
817  (+=, -=, +, -, unary -), multiplication and division of an
818  TinyVectorViews with a double, and NumericTraits/PromoteTraits are defined,
819  so that TinyVectorView fulfills the requirements of \ref LinearAlgebraConcept "Linear Algebra".
820 
821  VIGRA algorithms typically use \ref vigra::VectorAccessor to access
822  TinyVectorViews as a whole, or specific components of them.
823 
824  <b>See also:</b>
825  <ul>
826  <li> \ref vigra::TinyVectorBase
827  <li> \ref vigra::TinyVector
828  <li> \ref TinyVectorTraits
829  <li> \ref TinyVectorOperators
830  </ul>
831 
832  <b>\#include</b> <<a href="tinyvector_8hxx-source.html">vigra/tinyvector.hxx</a>><br>
833  Namespace: vigra
834 **/
835 template <class T, int SIZE>
837 : public TinyVectorBase<T, SIZE, T *, TinyVectorView<T, SIZE> >
838 {
840  typedef typename BaseType::Loop Loop;
841 
842  public:
843 
845  typedef typename BaseType::reference reference;
847  typedef typename BaseType::pointer pointer;
849  typedef typename BaseType::iterator iterator;
851  typedef typename BaseType::size_type size_type;
855  typedef typename BaseType::NormType NormType;
856 
857  /** Default constructor
858  (pointer to wrapped data is NULL).
859  */
861  : BaseType()
862  {
863  BaseType::data_ = 0;
864  }
865 
866  /** Construct view for given data array
867  */
869  : BaseType()
870  {
871  BaseType::data_ = const_cast<pointer>(data);
872  }
873 
874  /** Copy constructor (shallow copy).
875  */
877  : BaseType()
878  {
879  BaseType::data_ = const_cast<pointer>(other.data_);
880  }
881 
882  /** Construct view from other TinyVector.
883  */
884  template <class DATA, class DERIVED>
886  : BaseType()
887  {
888  BaseType::data_ = const_cast<pointer>(other.data());
889  }
890 
891  /** Copy the data (not the pointer) of the rhs.
892  */
894  {
895  Loop::assign(BaseType::data_, r.begin());
896  return *this;
897  }
898 
899  /** Copy the data of the rhs with cast.
900  */
901  template <class U, class DATA, class DERIVED>
903  {
904  Loop::assignCast(BaseType::data_, r.begin());
905  return *this;
906  }
907 };
908 
909 /********************************************************/
910 /* */
911 /* TinyVector Comparison */
912 /* */
913 /********************************************************/
914 
915 /** \addtogroup TinyVectorOperators Functions for TinyVector
916 
917  \brief Implement basic arithmetic and equality for TinyVector.
918 
919  These functions fulfill the requirements of a Linear Space (vector space).
920  Return types are determined according to \ref TinyVectorTraits.
921 
922  <b>\#include</b> <<a href="tinyvector_8hxx-source.html">vigra/tinyvector.hxx</a>><br>
923  Namespace: vigra
924 */
925 //@{
926  /// component-wise equal
927 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
928 inline bool
931 {
932  return !(l != r);
933 }
934 
935  /// component-wise not equal
936 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
937 inline bool
940 {
941  typedef typename detail::LoopType<SIZE>::type ltype;
942  return ltype::notEqual(l.begin(), r.begin());
943 }
944 
945 /********************************************************/
946 /* */
947 /* TinyVector Output */
948 /* */
949 /********************************************************/
950 
951  /// stream output
952 template <class V1, int SIZE, class DATA, class DERIVED>
953 std::ostream &
954 operator<<(std::ostream & out, TinyVectorBase<V1, SIZE, DATA, DERIVED> const & l)
955 {
956  out << "(";
957  int i;
958  for(i=0; i<SIZE-1; ++i)
959  out << l[i] << ", ";
960  out << l[i] << ")";
961  return out;
962 }
963 //@}
964 
965 /********************************************************/
966 /* */
967 /* TinyVector-Traits */
968 /* */
969 /********************************************************/
970 
971 /** \page TinyVectorTraits Numeric and Promote Traits of TinyVector
972  The numeric and promote traits for TinyVectors follow
973  the general specifications for \ref NumericPromotionTraits.
974  They are implemented in terms of the traits of the basic types by
975  partial template specialization:
976 
977  \code
978 
979  template <class T, int SIZE>
980  struct NumericTraits<TinyVector<T, SIZE> >
981  {
982  typedef TinyVector<typename NumericTraits<T>::Promote, SIZE> Promote;
983  typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> RealPromote;
984 
985  typedef typename NumericTraits<T>::isIntegral isIntegral;
986  typedef VigraFalseType isScalar;
987  typedef typename NumericTraits<T>::isSigned isSigned;
988 
989  // etc.
990  };
991 
992  template <class T, int SIZE>
993  struct NormTraits<TinyVector<T, SIZE> >
994  {
995  typedef TinyVector<T, SIZE> Type;
996  typedef typename Type::SquaredNormType SquaredNormType;
997  typedef typename Type::NormType NormType;
998  };
999 
1000  template <class T1, class T2, SIZE>
1001  struct PromoteTraits<TinyVector<T1, SIZE>, TinyVector<T2, SIZE> >
1002  {
1003  typedef TinyVector<typename PromoteTraits<T1, T2>::Promote, SIZE> Promote;
1004  };
1005  \endcode
1006 
1007  <b>\#include</b> <<a href="tinyvector_8hxx-source.html">vigra/tinyvector.hxx</a>><br>
1008  Namespace: vigra
1009 
1010  On compilers that don't support pertial template specialization (e.g.
1011  MS VisualC++), the traits classes are explicitly specialized for
1012  <TT>TinyVector<VALUETYPE, SIZE></TT> with
1013  <TT>VALUETYPE = unsigned char | int | float | double</TT> and <TT>SIZE = 2 | 3 | 4</TT>.
1014 
1015 */
1016 
1017 #if !defined(NO_PARTIAL_TEMPLATE_SPECIALIZATION)
1018 
1019 template <class T, int SIZE>
1020 struct NumericTraits<TinyVector<T, SIZE> >
1021 {
1022  typedef TinyVector<T, SIZE> Type;
1023  typedef TinyVector<typename NumericTraits<T>::Promote, SIZE> Promote;
1024  typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> RealPromote;
1025  typedef TinyVector<typename NumericTraits<T>::ComplexPromote, SIZE> ComplexPromote;
1026  typedef T ValueType;
1027 
1028  typedef typename NumericTraits<T>::isIntegral isIntegral;
1029  typedef VigraFalseType isScalar;
1030  typedef typename NumericTraits<T>::isSigned isSigned;
1031  typedef VigraFalseType isOrdered;
1032  typedef VigraFalseType isComplex;
1033 
1034  static TinyVector<T, SIZE> zero() {
1035  return TinyVector<T, SIZE>(NumericTraits<T>::zero());
1036  }
1037  static TinyVector<T, SIZE> one() {
1038  return TinyVector<T, SIZE>(NumericTraits<T>::one());
1039  }
1040  static TinyVector<T, SIZE> nonZero() {
1041  return TinyVector<T, SIZE>(NumericTraits<T>::nonZero());
1042  }
1043 
1044  template <class D1, class D2>
1045  static Promote toPromote(TinyVectorBase<T, SIZE, D1, D2> const & v)
1046  {
1047  return Promote(v);
1048  }
1049 
1050  template <class D1, class D2>
1051  static RealPromote toRealPromote(TinyVectorBase<T, SIZE, D1, D2> const & v)
1052  {
1053  return RealPromote(v);
1054  }
1055 
1056  template <class D1, class D2>
1057  static TinyVector<T, SIZE>
1058  fromPromote(TinyVectorBase<typename NumericTraits<T>::Promote, SIZE, D1, D2> const & v)
1059  {
1060  TinyVector<T, SIZE> res(detail::dontInit());
1061  typedef typename detail::LoopType<SIZE>::type ltype;
1062  ltype::fromPromote(res.begin(), v.begin());
1063  return res;
1064  }
1065 
1066  template <class D1, class D2>
1067  static TinyVector<T, SIZE>
1068  fromRealPromote(TinyVectorBase<typename NumericTraits<T>::RealPromote, SIZE, D1, D2> const & v)
1069  {
1070  TinyVector<T, SIZE> res(detail::dontInit());
1071  typedef typename detail::LoopType<SIZE>::type ltype;
1072  ltype::fromRealPromote(res.begin(), v.begin());
1073  return res;
1074  }
1075 };
1076 
1077 template <class T, int SIZE>
1078 struct NumericTraits<TinyVectorView<T, SIZE> >
1079 : public NumericTraits<TinyVector<T, SIZE> >
1080 {
1081  typedef TinyVector<T, SIZE> Type;
1082  typedef TinyVector<typename NumericTraits<T>::Promote, SIZE> Promote;
1083  typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> RealPromote;
1084  typedef TinyVector<typename NumericTraits<T>::ComplexPromote, SIZE> ComplexPromote;
1085  typedef T ValueType;
1086 
1087  typedef typename NumericTraits<T>::isIntegral isIntegral;
1088  typedef VigraFalseType isScalar;
1089  typedef typename NumericTraits<T>::isSigned isSigned;
1090  typedef VigraFalseType isOrdered;
1091  typedef VigraFalseType isComplex;
1092 };
1093 
1094 template <class T, int SIZE>
1095 struct NormTraits<TinyVector<T, SIZE> >
1096 {
1097  typedef TinyVector<T, SIZE> Type;
1098  typedef typename Type::SquaredNormType SquaredNormType;
1099  typedef typename Type::NormType NormType;
1100 };
1101 
1102 template <class T, int SIZE>
1103 struct NormTraits<TinyVectorView<T, SIZE> >
1104 {
1105  typedef TinyVector<T, SIZE> Type;
1106  typedef typename Type::SquaredNormType SquaredNormType;
1107  typedef typename Type::NormType NormType;
1108 };
1109 
1110 template <class T1, class T2, int SIZE>
1111 struct PromoteTraits<TinyVector<T1, SIZE>, TinyVector<T2, SIZE> >
1112 {
1113  typedef TinyVector<typename PromoteTraits<T1, T2>::Promote, SIZE> Promote;
1114 };
1115 
1116 template <class T1, class T2, int SIZE>
1117 struct PromoteTraits<TinyVectorView<T1, SIZE>, TinyVectorView<T2, SIZE> >
1118 {
1119  typedef TinyVector<typename PromoteTraits<T1, T2>::Promote, SIZE> Promote;
1120 };
1121 
1122 template <class T1, class T2, int SIZE>
1123 struct PromoteTraits<TinyVectorView<T1, SIZE>, TinyVector<T2, SIZE> >
1124 {
1125  typedef TinyVector<typename PromoteTraits<T1, T2>::Promote, SIZE> Promote;
1126 };
1127 
1128 template <class T1, class T2, int SIZE>
1129 struct PromoteTraits<TinyVector<T1, SIZE>, TinyVectorView<T2, SIZE> >
1130 {
1131  typedef TinyVector<typename PromoteTraits<T1, T2>::Promote, SIZE> Promote;
1132 };
1133 
1134 template <class T, int SIZE>
1135 struct PromoteTraits<TinyVector<T, SIZE>, double >
1136 {
1137  typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> Promote;
1138 };
1139 
1140 template <class T, int SIZE>
1141 struct PromoteTraits<double, TinyVector<T, SIZE> >
1142 {
1143  typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> Promote;
1144 };
1145 
1146 template <class T, int SIZE>
1147 struct PromoteTraits<TinyVectorView<T, SIZE>, double >
1148 {
1149  typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> Promote;
1150 };
1151 
1152 template <class T, int SIZE>
1153 struct PromoteTraits<double, TinyVectorView<T, SIZE> >
1154 {
1155  typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> Promote;
1156 };
1157 
1158 template<class T, int SIZE>
1159 struct CanSkipInitialization<TinyVectorView<T, SIZE> >
1160 {
1161  typedef typename CanSkipInitialization<T>::type type;
1162  static const bool value = type::asBool;
1163 };
1164 
1165 template<class T, int SIZE>
1166 struct CanSkipInitialization<TinyVector<T, SIZE> >
1167 {
1168  typedef typename CanSkipInitialization<T>::type type;
1169  static const bool value = type::asBool;
1170 };
1171 
1172 
1173 
1174 #else // NO_PARTIAL_TEMPLATE_SPECIALIZATION
1175 
1176 
1177 #define TINYVECTOR_NUMTRAITS(T, SIZE) \
1178 template<>\
1179 struct NumericTraits<TinyVector<T, SIZE> >\
1180 {\
1181  typedef TinyVector<T, SIZE> Type;\
1182  typedef TinyVector<NumericTraits<T>::Promote, SIZE> Promote;\
1183  typedef TinyVector<NumericTraits<T>::RealPromote, SIZE> RealPromote;\
1184  typedef TinyVector<NumericTraits<T>::ComplexPromote, SIZE> ComplexPromote;\
1185  typedef T ValueType; \
1186  typedef NumericTraits<T>::isIntegral isIntegral;\
1187  typedef VigraFalseType isScalar;\
1188  typedef NumericTraits<T>::isSigned isSigned; \
1189  typedef VigraFalseType isOrdered;\
1190  typedef VigraFalseType isComplex;\
1191  \
1192  static TinyVector<T, SIZE> zero() { \
1193  return TinyVector<T, SIZE>(NumericTraits<T>::zero()); \
1194  }\
1195  static TinyVector<T, SIZE> one() { \
1196  return TinyVector<T, SIZE>(NumericTraits<T>::one()); \
1197  }\
1198  static TinyVector<T, SIZE> nonZero() { \
1199  return TinyVector<T, SIZE>(NumericTraits<T>::nonZero()); \
1200  }\
1201  \
1202  static Promote toPromote(TinyVector<T, SIZE> const & v) { \
1203  return Promote(v); \
1204  }\
1205  static RealPromote toRealPromote(TinyVector<T, SIZE> const & v) { \
1206  return RealPromote(v); \
1207  }\
1208  static TinyVector<T, SIZE> fromPromote(Promote const & v) { \
1209  TinyVector<T, SIZE> res;\
1210  TinyVector<T, SIZE>::iterator d = res.begin(), dend = res.end();\
1211  Promote::const_iterator s = v.begin();\
1212  for(; d != dend; ++d, ++s)\
1213  *d = NumericTraits<T>::fromPromote(*s);\
1214  return res;\
1215  }\
1216  static TinyVector<T, SIZE> fromRealPromote(RealPromote const & v) {\
1217  TinyVector<T, SIZE> res;\
1218  TinyVector<T, SIZE>::iterator d = res.begin(), dend = res.end();\
1219  RealPromote::const_iterator s = v.begin();\
1220  for(; d != dend; ++d, ++s)\
1221  *d = NumericTraits<T>::fromRealPromote(*s);\
1222  return res;\
1223  }\
1224 }; \
1225 template<>\
1226 struct NormTraits<TinyVector<T, SIZE> >\
1227 {\
1228  typedef TinyVector<T, SIZE> Type;\
1229  typedef Type::SquaredNormType SquaredNormType; \
1230  typedef Type::NormType NormType; \
1231 };
1232 
1233 #define TINYVECTOR_PROMTRAITS1(type1, SIZE) \
1234 template<> \
1235 struct PromoteTraits<TinyVector<type1, SIZE>, TinyVector<type1, SIZE> > \
1236 { \
1237  typedef TinyVector<PromoteTraits<type1, type1>::Promote, SIZE> Promote; \
1238  static Promote toPromote(TinyVector<type1, SIZE> const & v) { \
1239  return static_cast<Promote>(v); } \
1240 };
1241 
1242 #define TINYVECTOR_PROMTRAITS2(type1, type2, SIZE) \
1243 template<> \
1244 struct PromoteTraits<TinyVector<type1, SIZE>, TinyVector<type2, SIZE> > \
1245 { \
1246  typedef TinyVector<PromoteTraits<type1, type2>::Promote, SIZE> Promote; \
1247  static Promote toPromote(TinyVector<type1, SIZE> const & v) { \
1248  return static_cast<Promote>(v); } \
1249  static Promote toPromote(TinyVector<type2, SIZE> const & v) { \
1250  return static_cast<Promote>(v); } \
1251 };
1252 
1253 #define TINYVECTOR_TRAITS(SIZE) \
1254 TINYVECTOR_NUMTRAITS(unsigned char, SIZE)\
1255 TINYVECTOR_NUMTRAITS(int, SIZE)\
1256 TINYVECTOR_NUMTRAITS(float, SIZE)\
1257 TINYVECTOR_NUMTRAITS(double, SIZE)\
1258 TINYVECTOR_PROMTRAITS1(unsigned char, SIZE)\
1259 TINYVECTOR_PROMTRAITS1(int, SIZE)\
1260 TINYVECTOR_PROMTRAITS1(float, SIZE)\
1261 TINYVECTOR_PROMTRAITS1(double, SIZE)\
1262 TINYVECTOR_PROMTRAITS2(float, unsigned char, SIZE)\
1263 TINYVECTOR_PROMTRAITS2(unsigned char, float, SIZE)\
1264 TINYVECTOR_PROMTRAITS2(int, unsigned char, SIZE)\
1265 TINYVECTOR_PROMTRAITS2(unsigned char, int, SIZE)\
1266 TINYVECTOR_PROMTRAITS2(int, float, SIZE)\
1267 TINYVECTOR_PROMTRAITS2(float, int, SIZE)\
1268 TINYVECTOR_PROMTRAITS2(double, unsigned char, SIZE)\
1269 TINYVECTOR_PROMTRAITS2(unsigned char, double, SIZE)\
1270 TINYVECTOR_PROMTRAITS2(int, double, SIZE)\
1271 TINYVECTOR_PROMTRAITS2(double, int, SIZE)\
1272 TINYVECTOR_PROMTRAITS2(double, float, SIZE)\
1273 TINYVECTOR_PROMTRAITS2(float, double, SIZE)
1274 
1275 TINYVECTOR_TRAITS(2)
1276 TINYVECTOR_TRAITS(3)
1277 TINYVECTOR_TRAITS(4)
1278 
1279 #undef TINYVECTOR_NUMTRAITS
1280 #undef TINYVECTOR_PROMTRAITS1
1281 #undef TINYVECTOR_PROMTRAITS2
1282 #undef TINYVECTOR_TRAITS
1283 
1284 #endif // NO_PARTIAL_TEMPLATE_SPECIALIZATION
1285 
1286 
1287 /********************************************************/
1288 /* */
1289 /* TinyVector-Arithmetic */
1290 /* */
1291 /********************************************************/
1292 
1293 /** \addtogroup TinyVectorOperators
1294  */
1295 //@{
1296 
1297  /// component-wise addition
1298 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
1299 inline
1300 typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2, SIZE> >::Promote
1303 {
1304  return typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2 , SIZE> >::Promote(l) += r;
1305 }
1306 
1307  /// component-wise subtraction
1308 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
1309 inline
1310 typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2, SIZE> >::Promote
1313 {
1314  return typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2 , SIZE> >::Promote(l) -= r;
1315 }
1316 
1317  /// component-wise multiplication
1318 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
1319 inline
1320 typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2, SIZE> >::Promote
1323 {
1324  return typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2 , SIZE> >::Promote(l) *= r;
1325 }
1326 
1327  /// component-wise division
1328 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
1329 inline
1330 typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2, SIZE> >::Promote
1333 {
1334  return typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2 , SIZE> >::Promote(l) /= r;
1335 }
1336 
1337  /// component-wise left scalar multiplication
1338 template <class V, int SIZE, class D1, class D2>
1339 inline
1340 typename NumericTraits<TinyVector<V, SIZE> >::RealPromote
1341 operator*(double v, TinyVectorBase<V, SIZE, D1, D2> const & r)
1342 {
1343  return typename NumericTraits<TinyVector<V, SIZE> >::RealPromote(r) *= v;
1344 }
1345 
1346  /// component-wise right scalar multiplication
1347 template <class V, int SIZE, class D1, class D2>
1348 inline
1349 typename NumericTraits<TinyVector<V, SIZE> >::RealPromote
1350 operator*(TinyVectorBase<V, SIZE, D1, D2> const & l, double v)
1351 {
1352  return typename NumericTraits<TinyVector<V, SIZE> >::RealPromote(l) *= v;
1353 }
1354 
1355  /// component-wise scalar division
1356 template <class V, int SIZE, class D1, class D2>
1357 inline
1358 typename NumericTraits<TinyVector<V, SIZE> >::RealPromote
1359 operator/(TinyVectorBase<V, SIZE, D1, D2> const & l, double v)
1360 {
1361  return typename NumericTraits<TinyVector<V, SIZE> >::RealPromote(l) /= v;
1362 }
1363 
1364 
1365  /** Unary negation (construct TinyVector with negative values)
1366  */
1367 template <class V, int SIZE, class D1, class D2>
1368 inline
1369 TinyVector<V, SIZE>
1371 {
1372  TinyVector<V, SIZE> res(detail::dontInit());
1373  typedef typename detail::LoopType<SIZE>::type ltype;
1374  ltype::neg(res.begin(), v.begin());
1375  return res;
1376 }
1377 
1378  /// component-wise absolute value
1379 template <class V, int SIZE, class D1, class D2>
1380 inline
1381 TinyVector<V, SIZE>
1383 {
1384  TinyVector<V, SIZE> res(detail::dontInit());
1385  typedef typename detail::LoopType<SIZE>::type ltype;
1386  ltype::abs(res.begin(), v.begin());
1387  return res;
1388 }
1389 
1390  /** Apply ceil() function to each vector component.
1391  */
1392 template <class V, int SIZE, class D1, class D2>
1393 inline
1394 TinyVector<V, SIZE>
1396 {
1397  TinyVector<V, SIZE> res(detail::dontInit());
1398  typedef typename detail::LoopType<SIZE>::type ltype;
1399  ltype::ceil(res.begin(), v.begin());
1400  return res;
1401 }
1402 
1403  /** Apply floor() function to each vector component.
1404  */
1405 template <class V, int SIZE, class D1, class D2>
1406 inline
1407 TinyVector<V, SIZE>
1409 {
1410  TinyVector<V, SIZE> res(detail::dontInit());
1411  typedef typename detail::LoopType<SIZE>::type ltype;
1412  ltype::floor(res.begin(), v.begin());
1413  return res;
1414 }
1415 
1416  /// cross product
1417 template <class V1, class D1, class D2, class V2, class D3, class D4>
1418 inline
1419 TinyVector<typename PromoteTraits<V1, V2>::Promote, 3>
1421  TinyVectorBase<V2, 3, D3, D4> const & r2)
1422 {
1424  Res;
1425  return Res(r1[1]*r2[2] - r1[2]*r2[1],
1426  r1[2]*r2[0] - r1[0]*r2[2],
1427  r1[0]*r2[1] - r1[1]*r2[0]);
1428 }
1429 
1430  /// dot product
1431 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
1432 inline
1433 typename PromoteTraits<V1, V2>::Promote
1436 {
1437  typedef typename detail::LoopType<SIZE>::type ltype;
1438  return ltype::dot(l.begin(), r.begin());
1439 }
1440 
1441 
1442  /// squared norm
1443 template <class V1, int SIZE, class D1, class D2>
1444 inline
1445 typename TinyVectorBase<V1, SIZE, D1, D2>::SquaredNormType
1447 {
1448  return t.squaredMagnitude();
1449 }
1450 
1451  /// squared norm
1452 template <class V, int SIZE>
1453 inline
1454 typename TinyVector<V, SIZE>::SquaredNormType
1456 {
1457  return t.squaredMagnitude();
1458 }
1459 //@}
1460 
1461 
1462 } // namespace vigra
1463 #undef VIGRA_ASSERT_INSIDE
1464 #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.7.1 (Thu Jun 14 2012)