vigra - vigra/tinyvector.hxx Source File

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