[ 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. */
158 typedef PowerSum<2> SumOfSquares;
159
160 /** \brief Alias. Mean. */
161 typedef DivideByCount<Sum> Mean;
162 /** \brief Alias. Root mean square. */
163 typedef RootDivideByCount<SumOfSquares> RootMeanSquares;
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. */
178 typedef Central<PowerSum<2> > SumOfSquaredDifferences;
179 /** \brief Alias. Sum of squared differences. */
180 typedef SumOfSquaredDifferences SSD;
181
182 /** \brief Alias. Variance. */
183 typedef DivideByCount<Central<PowerSum<2> > > Variance;
184 /** \brief Alias. Standard deviation. */
185 typedef RootDivideByCount<Central<PowerSum<2> > > StdDev;
186 /** \brief Alias. Unbiased variance. */
187 typedef DivideUnbiased<Central<PowerSum<2> > > UnbiasedVariance;
188 /** \brief Alias. Unbiased standard deviation. */
189 typedef RootDivideUnbiased<Central<PowerSum<2> > > UnbiasedStdDev;
190
191 /** \brief Alias. Covariance. */
192 typedef DivideByCount<FlatScatterMatrix> Covariance;
193 /** \brief Alias. Unbiased covariance. */
194 typedef DivideUnbiased<FlatScatterMatrix> UnbiasedCovariance;
195 /** \brief Alias. Covariance eigensystem. */
196 typedef DivideByCount<ScatterMatrixEigensystem> CovarianceEigensystem;
197
198 /** \brief Alias. Absolute sum. */
199 typedef AbsPowerSum<1> AbsSum;
200 /** \brief Alias. Sum of absolute differences. */
201 typedef Central<AbsSum> SumOfAbsDifferences;
202 /** \brief Alias. Mean absolute deviation. */
203 typedef DivideByCount<SumOfAbsDifferences> MeanAbsoluteDeviation;
204
205 /** \brief Alias. Region center. */
206 typedef Coord<Mean> RegionCenter;
207 /** \brief Alias. Region radii. */
208 typedef Coord<Principal<StdDev> > RegionRadii;
209 /** \brief Alias. Region axes. */
210 typedef Coord<Principal<CoordinateSystem> > RegionAxes;
211
212 /** \brief Alias. Center of mass. */
213 typedef Weighted<RegionCenter> CenterOfMass;
214 /** \brief Alias. Moments of inertia. */
215 typedef Weighted<Coord<Principal<Variance> > > MomentsOfInertia;
216 /** \brief Alias. Axes of inertia. */
217 typedef Weighted<RegionAxes> AxesOfInertia;
218
219 /**************************************************************************/
220 /* */
221 /* Tag standardization rules */
222 /* */
223 /**************************************************************************/
224
225 namespace acc_detail {
226
227 template <class A>
228 struct ModifierRule
229 {
230 typedef A type;
231 };
232
233 } // namespace acc_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 acc_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 acc_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 acc_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 acc_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 A, template <class> class AA, class B, template <class> class BB>
683 struct SubstituteModifiers<AA<A>, BB<B>, true>
684 {
685 typedef AA<typename SubstituteModifiers<A, B>::type> type;
686 };
687
688 template <class A, class B, template <class> class BB>
689 struct SubstituteModifiers<DefaultModifier<A>, BB<B>, true>
690 {
691 typedef BB<typename SubstituteModifiers<A, B>::type> type;
692 };
693
694 template <class A, template <class> class AA, class B, template <class> class BB>
695 struct SubstituteModifiers<AA<A>, BB<B>, false>
696 {
697 typedef BB<typename SubstituteModifiers<A, B>::type> type;
698 };
699
700 } // namespace acc_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 acc_detail::TagLongForm<StdA, acc_detail::MinPriority>::type AA;
708 typedef typename acc_detail::TagLongForm<StdB, acc_detail::MinPriority>::type BB;
709 typedef typename acc_detail::SubstituteModifiers<AA, BB>::type AB;
710 typedef typename acc_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.10.0 (Mon Nov 18 2013)