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

accumulator-grammar.hxx
1 /************************************************************************/
2 /* */
3 /* Copyright 2011-2012 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 #ifndef VIGRA_ACCUMULATOR_GRAMMAR_HXX
37 #define VIGRA_ACCUMULATOR_GRAMMAR_HXX
38 
39 #ifdef _MSC_VER
40 #pragma warning (disable: 4503)
41 #endif
42 
43 #include "config.hxx"
44 #include "metaprogramming.hxx"
45 
46 namespace vigra {
47 
48 namespace acc {
49 
50 /**************************************************************************/
51 /* */
52 /* irreducible basic accumulators */
53 /* */
54 /**************************************************************************/
55 
56 
57 class CoordinateSystem; // returns an identity matrix of appropriate size
58 
59 template <unsigned N> class PowerSum; // sum over powers of values
60 template <unsigned N> class AbsPowerSum; // sum over powers of absolute values
61 
62 class Skewness; // skewness
63 class UnbiasedSkewness; // unbiased estimator for skewness
64 class Kurtosis; // excess kurtosis
65 class UnbiasedKurtosis; // unbiased estimator for excess kurtosis
66 class FlatScatterMatrix; // flattened upper-triangular part of the scatter matrix
67 class ScatterMatrixEigensystem; // eigenvalues and eigenvectors of the scatter matrix
68 
69  // in all histogram classes: set bin count at runtime if BinCount == 0
70 template <int BinCount> class IntegerHistogram; // use data values directly as bin indices
71 template <int BinCount> class UserRangeHistogram; // set min/max explicitly at runtime
72 template <int BinCount> class AutoRangeHistogram; // get min/max from accumulators
73 template <int BinCount> class GlobalRangeHistogram; // like AutoRangeHistogram, but use global min/max rather than region min/max
74 
75 class Minimum; // minimum
76 class Maximum; // maximum
77 template <class Hist> class StandardQuantiles; // compute (min, 10%, 25%, 50%, 75%, 90%, max) quantiles from
78  // min/max accumulators and given histogram
79 
80 class ArgMinWeight; // store the value (or coordinate) where weight was minimal
81 class ArgMaxWeight; // store the value (or coordinate) where weight was maximal
82 
83  // FIXME: not yet implemented
84 template <unsigned NDim> class MultiHistogram; // multi-dimensional histogram
85  // (always specify number of bins at runtime)
86 
87 class Centralize; // cache centralized values
88 class PrincipalProjection; // cache values after principal projection
89  // FIXME: not yet implemented
90 class Whiten; // cache values after whitening
91 class RangeMapping; // map value from [min, max] to another range and cache result (e.g. for histogram creation)
92 
93 template <int INDEX> class DataArg; // specifiy the index of the data member in a CoupledHandle
94 template <int INDEX> class WeightArg; // specifiy the index of the weight member in a CoupledHandle
95 template <int INDEX> class LabelArg; // specifiy the index of the label member in a CoupledHandle
96 template <int INDEX> class CoordArg; // specifiy the index of the coord member in a CoupledHandle
97 
98 /*
99 Quantiles other than minimum and maximum require more thought:
100 --------------------------------------------------------------
101  * Exact quantiles can be found in time O(n) using recursive partitioning (quickselect),
102  but this requires the data (or an auxiliary index array) to be re-arranged.
103  * Exact quantiles can be found in time O(k*n) using recursive histogram refinement,
104  were k = O(log(n)/log(BinCount)) is the expected number of required passes over the
105  data, provided that bins are filled approximately evenly. If data can be re-arranged,
106  such that we remember the items corresponding to each bin, running time reduces to O(n)
107  (this is Tibshirani's 'binmedian' algorithm). For the median, Tibshirani proves that
108  the initial histogram only needs to cover the interval [Mean-StdDev, Mean+StdDev].
109  * Both strategies can be combined: perform k passes to reduce bin size to about
110  n/(BinCount)^k, and then perform quickselect on an auxiliary array of size
111  O(n/(BinCount)^k) which has been filled during the final pass.
112  * Good approximate results can be obtained by early stopping of histogram refinement
113  (Tibshirani's 'binapprox' algorithm). A 2-pass algorithm for the median achieves
114  accuracy of StdDev/BinCount: Mean and StdDev are computed during pass 1,
115  and a histogram over [Mean-StdDev, Mean+StdDev] during pass 2.
116  * A 1-pass approximation method is described in Chen et al. However, it assumes that
117  samples arrive in random order which is usually not true in image data.
118 */
119 
120 /**************************************************************************/
121 /* */
122 /* modifiers for composite accumulators */
123 /* */
124 /**************************************************************************/
125 
126  // data normalization w.r.t. number of samples
127 template <class A> class DivideByCount; // A / count
128 template <class A> class RootDivideByCount; // sqrt(A / count)
129 template <class A> class DivideUnbiased; // A / (count - 1)
130 template <class A> class RootDivideUnbiased; // sqrt(A / (count - 1))
131 
132  // data access
133 template <class A> class Coord; // use pixel coordinate instead of pixel value (index 0 of CoupledHandle)
134 template <class A> class Weighted; // use (value, weight) pairs (index 1 and 2 of CoupledHandle)
135 template <class A> class CoordWeighted; // use (coord, weight) pairs(index 0 and end of CoupledHandle)
136 template <class A> class DataFromHandle; // extract data from index 1 of a CoupledHandle
137 
138  // data preparation
139 template <class A> class Central; // subtract mean
140 template <class A> class Principal; // subtract mean and rotate to principal coordinates
141 
142  // FIXME: not implemented yet
143 template <class A> class Whitened; // transform to principal coordinates and scale to unit variance
144 
145 template <class A> class Global; // compute statistic A globally rather than per region
146 
147 /**************************************************************************/
148 /* */
149 /* alias names for important features */
150 /* */
151 /**************************************************************************/
152 
153 /** \brief Alias. Count. */
154 typedef PowerSum<0> Count;
155 /** \brief Alias. Sum. */
156 typedef PowerSum<1> Sum;
157 /** \brief Alias. Sum of squares. */
159 
160 /** \brief Alias. Mean. */
162 /** \brief Alias. Root mean square. */
164 
165 // desired pseudocode (unfortunately not legal in C++)
166 //
167 // template <unsigned N>
168 // typedef DivideByCount<PowerSum<N> > Moment;
169 //
170 // actual definition (desired behavior is realised by rules below)
171 //
172 /** \brief Alias. Moment<N>. */
173 template <unsigned N> class Moment;
174 /** \brief Alias. CentralMoment<N>. */
175 template <unsigned N> class CentralMoment;
176 
177 /** \brief Alias. Sum of squared differences. */
179 /** \brief Alias. Sum of squared differences. */
181 
182 /** \brief Alias. Variance. */
184 /** \brief Alias. Standard deviation. */
186 /** \brief Alias. Unbiased variance. */
188 /** \brief Alias. Unbiased standard deviation. */
190 
191 /** \brief Alias. Covariance. */
193 /** \brief Alias. Unbiased covariance. */
195 /** \brief Alias. Covariance eigensystem. */
197 
198 /** \brief Alias. Absolute sum. */
200 /** \brief Alias. Sum of absolute differences. */
202 /** \brief Alias. Mean absolute deviation. */
204 
205 /** \brief Alias. Region center. */
207 /** \brief Alias. Region radii. */
209 /** \brief Alias. Region axes. */
211 
212 /** \brief Alias. Center of mass. */
214 /** \brief Alias. Moments of inertia. */
216 /** \brief Alias. Axes of inertia. */
218 
219 /**************************************************************************/
220 /* */
221 /* Tag standardization rules */
222 /* */
223 /**************************************************************************/
224 
225 namespace detail {
226 
227 template <class A>
228 struct ModifierRule
229 {
230  typedef A type;
231 };
232 
233 } // namespace detail
234 
235 template <class A>
236 struct Error___Tag_modifiers_of_same_kind_must_not_be_combined;
237 
238  // apply rules as long as the Tag type changes ...
239 template <class A, class S=typename detail::ModifierRule<A>::type>
240 struct StandardizeTag
241 {
242  typedef typename StandardizeTag<S>::type type;
243 };
244 
245  // ... and stop otherwise ...
246 template <class A>
247 struct StandardizeTag<A, A>
248 {
249  typedef A type;
250 };
251 
252  // ... or fail when the tag spec was non-conforming
253 template <class A, class B>
254 struct StandardizeTag<A, Error___Tag_modifiers_of_same_kind_must_not_be_combined<B> >
255  : public Error___Tag_modifiers_of_same_kind_must_not_be_combined<B>
256 {};
257 
258 namespace detail {
259 
260  // Assign priorities to modifiers to determine their standard order (by ascending priority).
261  // SubstitutionMask determines which modifiers must be automatically transferred to dependencies.
262 enum { MinPriority = 1,
263  AccumulatorPriority = 32,
264  PrepareDataPriority = 16,
265  NormalizePriority = 8,
266  AccessDataPriority = 4,
267  WeightingPriority = 2,
268  GlobalPriority = 1,
269  MaxPriority = 32,
270  SubstitutionMask = PrepareDataPriority | AccessDataPriority | WeightingPriority | GlobalPriority };
271 
272 template <class A>
273 struct ModifierPriority
274 {
275  static const int value = AccumulatorPriority;
276 };
277 
278 #define VIGRA_MODIFIER_PRIORITY(MODIFIER, VALUE) \
279 template <class A> \
280 struct ModifierPriority<MODIFIER<A> > \
281 { \
282  static const int value = VALUE; \
283 };
284 
285 VIGRA_MODIFIER_PRIORITY(Global, GlobalPriority)
286 
287 VIGRA_MODIFIER_PRIORITY(Weighted, WeightingPriority)
288 
289 VIGRA_MODIFIER_PRIORITY(Coord, AccessDataPriority)
290 VIGRA_MODIFIER_PRIORITY(DataFromHandle, AccessDataPriority)
291 
292 VIGRA_MODIFIER_PRIORITY(DivideByCount, NormalizePriority)
293 VIGRA_MODIFIER_PRIORITY(RootDivideByCount, NormalizePriority)
294 VIGRA_MODIFIER_PRIORITY(DivideUnbiased, NormalizePriority)
295 VIGRA_MODIFIER_PRIORITY(RootDivideUnbiased, NormalizePriority)
296 
297 VIGRA_MODIFIER_PRIORITY(Central, PrepareDataPriority)
298 VIGRA_MODIFIER_PRIORITY(Principal, PrepareDataPriority)
299 VIGRA_MODIFIER_PRIORITY(Whitened, PrepareDataPriority)
300 
301  // explicitly set priority for base accumulators that look like modifiers
302 VIGRA_MODIFIER_PRIORITY(StandardQuantiles, AccumulatorPriority)
303 
304 #undef VIGRA_MODIFIER_PRIORITY
305 
306  // check if the tag A contains a modifier with TARGET_PRIORITY
307 template <class A, int TARGET_PRIORITY, int PRIORITY=ModifierPriority<A>::value>
308 struct HasModifierPriority
309 {
310  typedef VigraFalseType type;
311  static const bool value = false;
312 };
313 
314 template <class A, int TARGET_PRIORITY>
315 struct HasModifierPriority<A, TARGET_PRIORITY, TARGET_PRIORITY>
316 {
317  typedef VigraTrueType type;
318  static const bool value = true;
319 };
320 
321 template <class A, template <class> class B, int TARGET_PRIORITY, int PRIORITY>
322 struct HasModifierPriority<B<A>, TARGET_PRIORITY, PRIORITY>
323 : public HasModifierPriority<A, TARGET_PRIORITY>
324 {};
325 
326 template <class A, template <class> class B, int TARGET_PRIORITY>
327 struct HasModifierPriority<B<A>, TARGET_PRIORITY, TARGET_PRIORITY>
328 {
329  typedef VigraTrueType type;
330  static const bool value = true;
331 };
332 
333  // three-way compare
334 template <class A, class B>
335 struct ModifierCompare
336 {
337  static const int p1 = ModifierPriority<A>::value;
338  static const int p2 = ModifierPriority<B>::value;
339  static const int value = p1 < p2
340  ? -1
341  : p2 < p1
342  ? 1
343  : 0;
344 };
345 
346 template <class A>
347 struct ModifierCompareToInner;
348 
349 template <class A, template <class> class B>
350 struct ModifierCompareToInner<B<A> >
351 : public ModifierCompare<B<A>, A>
352 {};
353 
354  // sort modifiers by ascending priority
355 template <class A, int compare=ModifierCompareToInner<A>::value>
356 struct ModifierOrder;
357 
358  // do nothing if the order is correct (compare == -1)
359 template <class A>
360 struct ModifierOrder<A, -1>
361 {
362  typedef A type;
363 };
364 
365  // fail if there are two modifiers with the same priority (compare == 0)
366 template <class A, template <class> class B, template <class> class C>
367 struct ModifierOrder<C<B<A> >, 0>
368 {
369  typedef Error___Tag_modifiers_of_same_kind_must_not_be_combined<C<B<A> > > type;
370 };
371 
372  // sort if the order is reversed (compare == 1)
373 template <class A, template <class> class B, template <class> class C>
374 struct ModifierOrder<C<B<A> >, 1>
375 {
376  typedef B<C<A> > type;
377 };
378 
379 #define VIGRA_CLEANUP_DATA_PREPARATION_MODIFIERS(OUTER, INNER, RESULT) \
380 template <class A> \
381 struct ModifierOrder<OUTER<INNER<A > >, 0> \
382 { \
383  typedef RESULT<A > type; \
384 };
385 
386  // drop duplicates
387 VIGRA_CLEANUP_DATA_PREPARATION_MODIFIERS(Central, Central, Central)
388 VIGRA_CLEANUP_DATA_PREPARATION_MODIFIERS(Principal, Principal, Principal)
389 VIGRA_CLEANUP_DATA_PREPARATION_MODIFIERS(Whitened, Whitened, Whitened)
390 
391  // the strongest data preparation modifier takes precendence
392 VIGRA_CLEANUP_DATA_PREPARATION_MODIFIERS(Principal, Central, Principal)
393 VIGRA_CLEANUP_DATA_PREPARATION_MODIFIERS(Whitened, Central, Whitened)
394 VIGRA_CLEANUP_DATA_PREPARATION_MODIFIERS(Whitened, Principal, Whitened)
395 
396  // Coord takes precendence over DataFromHandle
397 VIGRA_CLEANUP_DATA_PREPARATION_MODIFIERS(DataFromHandle, Coord, Coord)
398 
399 #undef VIGRA_CLEANUP_DATA_PREPARATION_MODIFIERS
400 
401  // drop duplicates
402 template <class A, template <class> class B>
403 struct ModifierRule<B<B<A> > >
404 {
405  typedef B<A> type;
406 };
407 
408 template <class A, int PRIORITY=ModifierPriority<A>::value>
409 struct RecurseModifier;
410 
411 template <class A, template <class> class B, int PRIORITY>
412 struct RecurseModifier<B<A>, PRIORITY>
413 {
414  typedef typename ModifierOrder<B<typename StandardizeTag<A>::type> >::type type;
415 };
416 
417 template <class A, template <class> class B>
418 struct RecurseModifier<B<A>, AccumulatorPriority>
419 {
420  typedef B<A> type;
421 };
422 
423  // recurse down the modifier chain, but only of B is actually a modifier,
424  // and not a templated base accumulator (i.e. do not recurse if B's
425  // priority is 'AccumulatorPriority')
426 template <class A, template <class> class B>
427 struct ModifierRule<B<A> >
428 : public RecurseModifier<B<A> >
429 {};
430 
431  // reduce the SOURCE modifier to the TARGET modifier,
432  // using the given TEMPLATE arguments
433  // (this is a work-around for the lack of templated typedef in C++)
434 #define VIGRA_REDUCE_MODFIER(TEMPLATE, SOURCE, TARGET) \
435 template <TEMPLATE > \
436 struct ModifierRule<SOURCE > \
437 { \
438  typedef TARGET type; \
439 };
440 
441 #define VIGRA_VOID
442 
443  // centralizing doesn't change the CoordinateSystem
444 VIGRA_REDUCE_MODFIER(VIGRA_VOID, Central<CoordinateSystem>, CoordinateSystem)
445  // whitened CoordinateSystem are the same as principal CoordinateSystem
446 VIGRA_REDUCE_MODFIER(VIGRA_VOID, Whitened<CoordinateSystem>, Principal<CoordinateSystem>)
447 
448  // counting modified data is the same as counting data, except for weighted data and global counting
449 VIGRA_REDUCE_MODFIER(template <class> class A, A<Count>, Count)
450 VIGRA_REDUCE_MODFIER(VIGRA_VOID, Weighted<Count>, Weighted<Count>)
451 VIGRA_REDUCE_MODFIER(VIGRA_VOID, CoordWeighted<Count>, Weighted<Count>)
452 VIGRA_REDUCE_MODFIER(VIGRA_VOID, Global<Count>, Global<Count>)
453 
454  // reduce aliases that typedef can't handle
455 VIGRA_REDUCE_MODFIER(unsigned N, Moment<N>, DivideByCount<PowerSum<N> >)
456 VIGRA_REDUCE_MODFIER(unsigned N, CentralMoment<N>, DivideByCount<Central<PowerSum<N> > >)
457 VIGRA_REDUCE_MODFIER(class A, CoordWeighted<A>, Weighted<Coord<A> >)
458 
459  // reduce statistics that are inherently centered
460 VIGRA_REDUCE_MODFIER(VIGRA_VOID, Central<Centralize>, Centralize)
461 VIGRA_REDUCE_MODFIER(VIGRA_VOID, Central<Skewness>, Skewness)
462 VIGRA_REDUCE_MODFIER(VIGRA_VOID, Central<Kurtosis>, Kurtosis)
463 VIGRA_REDUCE_MODFIER(VIGRA_VOID, Central<FlatScatterMatrix>, FlatScatterMatrix)
464 VIGRA_REDUCE_MODFIER(VIGRA_VOID, Central<ScatterMatrixEigensystem>, ScatterMatrixEigensystem)
465 
466 VIGRA_REDUCE_MODFIER(VIGRA_VOID, Principal<Centralize>, PrincipalProjection)
467 VIGRA_REDUCE_MODFIER(VIGRA_VOID, Whitened<Centralize>, Whiten)
468 VIGRA_REDUCE_MODFIER(VIGRA_VOID, Principal<PrincipalProjection>, PrincipalProjection)
469 VIGRA_REDUCE_MODFIER(VIGRA_VOID, Whitened<PrincipalProjection>, Whiten)
470 VIGRA_REDUCE_MODFIER(VIGRA_VOID, Whitened<Whiten>, Whiten)
471 
472  // reduce even absolute powers to plain powers
473 template <unsigned N>
474 struct ModifierRule<AbsPowerSum<N> >
475 {
476  typedef typename IfBool<(N % 2 == 0), PowerSum<N>, AbsPowerSum<N> >::type type;
477 };
478 
479 #undef VIGRA_VOID
480 #undef VIGRA_REDUCE_MODFIER
481 
482 template <class A>
483 struct ShouldBeWeighted
484 {
485  typedef VigraFalseType type;
486  static const bool value = false;
487 };
488 
489 template <>
490 struct ShouldBeWeighted<ArgMinWeight>
491 {
492  typedef VigraTrueType type;
493  static const bool value = true;
494 };
495 
496 template <>
497 struct ShouldBeWeighted<ArgMaxWeight>
498 {
499  typedef VigraTrueType type;
500  static const bool value = true;
501 };
502 
503 template <class A, template <class> class B>
504 struct ShouldBeWeighted<B<A> >
505 : public ShouldBeWeighted<A>
506 {};
507 
508 } // namespace detail
509 
510 template <class A>
511 struct IsCoordinateFeature
512 {
513  typedef VigraFalseType type;
514  static const bool value = false;
515 };
516 
517 template <class A, template <class> class B>
518 struct IsCoordinateFeature<B<A> >
519 {
520  typedef typename IsCoordinateFeature<A>::type type;
521  static const bool value = IsCoordinateFeature<A>::value;
522 };
523 
524 template <class A>
525 struct IsCoordinateFeature<Coord<A> >
526 {
527  typedef VigraTrueType type;
528  static const bool value = true;
529 };
530 
531 template <class A>
532 struct IsPrincipalFeature
533 {
534  typedef VigraFalseType type;
535  static const bool value = false;
536 };
537 
538 template <class A, template <class> class B>
539 struct IsPrincipalFeature<B<A> >
540 {
541  typedef typename IsPrincipalFeature<A>::type type;
542  static const bool value = IsPrincipalFeature<A>::value;
543 };
544 
545 template <class A>
546 struct IsPrincipalFeature<Principal<A> >
547 {
548  typedef VigraTrueType type;
549  static const bool value = true;
550 };
551 
552 template <class A>
553 struct IsPrincipalFeature<Whitened<A> >
554 {
555  typedef VigraTrueType type;
556  static const bool value = true;
557 };
558 
559 /**************************************************************************/
560 /* */
561 /* Tag transfer rules */
562 /* */
563 /**************************************************************************/
564 
565 namespace detail {
566 
567 template <class A>
568 struct DefaultModifier;
569 
570 template <class A>
571 struct ModifierPriority<DefaultModifier<A> >
572 {
573  static const int value = ModifierPriority<A>::value << 1;
574 };
575 
576 template <class A, int TargetPriority, int Priority=ModifierPriority<A>::value>
577 struct InsertDefaultModifier
578 {
579  typedef DefaultModifier<typename InsertDefaultModifier<A, (TargetPriority << 1)>::type> type;
580 };
581 
582 template <class A, int TargetPriority>
583 struct InsertDefaultModifier<A, TargetPriority, TargetPriority>
584 {
585  typedef A type;
586 };
587 
588 template <class A, int TargetPriority, int Priority=ModifierPriority<A>::value>
589 struct TagLongForm;
590 
591 template <class A, int TargetPriority>
592 struct TagLongForm<A, TargetPriority, MaxPriority>
593 {
594  typedef typename InsertDefaultModifier<A, TargetPriority>::type type;
595 };
596 
597 template <class A, template <class> class B, int TargetPriority>
598 struct TagLongForm<B<A>, TargetPriority, MaxPriority>
599 {
600  typedef typename InsertDefaultModifier<B<A>, TargetPriority>::type type;
601 };
602 
603 template <class A, template <class> class B, int TargetPriority, int Priority>
604 struct TagLongForm<B<A>, TargetPriority, Priority>
605 {
606  typedef typename TagLongForm<A, (Priority << 1)>::type Inner;
607  typedef typename InsertDefaultModifier<B<Inner>, TargetPriority>::type type;
608 };
609 
610 template <class A, template <class> class B, int TargetPriority>
611 struct TagLongForm<B<A>, TargetPriority, TargetPriority>
612 {
613  typedef typename TagLongForm<A, (TargetPriority << 1)>::type Inner;
614  typedef B<Inner> type;
615 };
616 
617 template <class A>
618 struct LongModifierRule
619 {
620  typedef A type;
621 };
622 
623  // apply rules as long as the Tag type changes ...
624 template <class A, class S=typename LongModifierRule<A>::type>
625 struct StandardizeTagLongForm
626 {
627  typedef typename StandardizeTagLongForm<S>::type type;
628 };
629 
630  // ... and stop otherwise ...
631 template <class A>
632 struct StandardizeTagLongForm<A, A>
633 {
634  typedef A type;
635 };
636 
637 template <class A, template <class> class B>
638 struct LongModifierRule<B<A> >
639 {
640  typedef B<typename LongModifierRule<A>::type> type;
641 };
642 
643 template <class A>
644 struct LongModifierRule<DefaultModifier<A> >
645 {
646  typedef A type;
647 };
648 
649 #define VIGRA_DROP_DATA_PREPARATION_MODIFIERS(SOURCE, TARGET) \
650 template <> \
651 struct LongModifierRule<SOURCE > \
652 { \
653  typedef TARGET type; \
654 };
655 
656 VIGRA_DROP_DATA_PREPARATION_MODIFIERS(Central<Sum>, Sum)
657 VIGRA_DROP_DATA_PREPARATION_MODIFIERS(Principal<Sum>, Sum)
658 VIGRA_DROP_DATA_PREPARATION_MODIFIERS(Whitened<Sum>, Sum)
659 VIGRA_DROP_DATA_PREPARATION_MODIFIERS(Principal<FlatScatterMatrix>, FlatScatterMatrix)
660 VIGRA_DROP_DATA_PREPARATION_MODIFIERS(Whitened<FlatScatterMatrix>, FlatScatterMatrix)
661 VIGRA_DROP_DATA_PREPARATION_MODIFIERS(Principal<ScatterMatrixEigensystem>, ScatterMatrixEigensystem)
662 VIGRA_DROP_DATA_PREPARATION_MODIFIERS(Whitened<ScatterMatrixEigensystem>, ScatterMatrixEigensystem)
663 
664 #undef VIGRA_DROP_DATA_PREPARATION_MODIFIERS
665 
666 template <class A>
667 struct CheckSubstitutionFlag
668 {
669  static const bool value = (ModifierPriority<A>::value & SubstitutionMask) != 0;
670 };
671 
672 template <class A, class B,
673  bool substitute=CheckSubstitutionFlag<A>::value>
674 struct SubstituteModifiers;
675 
676 template <class A, class B>
677 struct SubstituteModifiers<A, B, false>
678 {
679  typedef B type;
680 };
681 
682 template <class A0, template <class> class A1, class B0, template <class> class B1>
683 struct SubstituteModifiers<A1<A0>, B1<B0>, true>
684 {
685  typedef A1<typename SubstituteModifiers<A0, B0>::type> type;
686 };
687 
688 template <class A0, class B0, template <class> class B1>
689 struct SubstituteModifiers<DefaultModifier<A0>, B1<B0>, true>
690 {
691  typedef B1<typename SubstituteModifiers<A0, B0>::type> type;
692 };
693 
694 template <class A0, template <class> class A1, class B0, template <class> class B1>
695 struct SubstituteModifiers<A1<A0>, B1<B0>, false>
696 {
697  typedef B1<typename SubstituteModifiers<A0, B0>::type> type;
698 };
699 
700 } // namespace detail
701 
702 template <class A, class B>
703 struct TransferModifiers
704 {
705  typedef typename StandardizeTag<A>::type StdA;
706  typedef typename StandardizeTag<B>::type StdB;
707  typedef typename detail::TagLongForm<StdA, detail::MinPriority>::type AA;
708  typedef typename detail::TagLongForm<StdB, detail::MinPriority>::type BB;
709  typedef typename detail::SubstituteModifiers<AA, BB>::type AB;
710  typedef typename detail::StandardizeTagLongForm<AB>::type StdAB;
711  typedef typename StandardizeTag<StdAB>::type type;
712 };
713 
714 template <class A, class HEAD, class TAIL>
715 struct TransferModifiers<A, TypeList<HEAD, TAIL> >
716 {
717  typedef TypeList<typename TransferModifiers<A, HEAD>::type,
718  typename TransferModifiers<A, TAIL>::type> type;
719 };
720 
721 template <class A>
722 struct TransferModifiers<A, void>
723 {
724  typedef void type;
725 };
726 
727 template <class TargetTag, class A=typename TargetTag::Dependencies>
728 struct StandardizeDependencies
729 #ifndef DOXYGEN
730 : public StandardizeDependencies<TargetTag, typename A::type>
731 #endif
732 {};
733 
734 template <class TargetTag, class HEAD, class TAIL>
735 struct StandardizeDependencies<TargetTag, TypeList<HEAD, TAIL> >
736 {
737  typedef typename StandardizeTag<TargetTag>::type Target;
738  typedef typename TransferModifiers<Target, TypeList<HEAD, TAIL> >::type type;
739 };
740 
741 template <class TargetTag>
742 struct StandardizeDependencies<TargetTag, void>
743 {
744  typedef void type;
745 };
746 
747 }} // namespace vigra::acc
748 
749 #endif // VIGRA_ACCUMULATOR_GRAMMAR_HXX

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

html generated using doxygen and Python
vigra 1.9.0 (Wed Feb 27 2013)