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

© 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.12.2 (Mon Apr 14 2025)