[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]
vigra/accumulator-grammar.hxx | ![]() |
00001 /************************************************************************/ 00002 /* */ 00003 /* Copyright 2011-2012 by Ullrich Koethe */ 00004 /* */ 00005 /* This file is part of the VIGRA computer vision library. */ 00006 /* The VIGRA Website is */ 00007 /* http://hci.iwr.uni-heidelberg.de/vigra/ */ 00008 /* Please direct questions, bug reports, and contributions to */ 00009 /* ullrich.koethe@iwr.uni-heidelberg.de or */ 00010 /* vigra@informatik.uni-hamburg.de */ 00011 /* */ 00012 /* Permission is hereby granted, free of charge, to any person */ 00013 /* obtaining a copy of this software and associated documentation */ 00014 /* files (the "Software"), to deal in the Software without */ 00015 /* restriction, including without limitation the rights to use, */ 00016 /* copy, modify, merge, publish, distribute, sublicense, and/or */ 00017 /* sell copies of the Software, and to permit persons to whom the */ 00018 /* Software is furnished to do so, subject to the following */ 00019 /* conditions: */ 00020 /* */ 00021 /* The above copyright notice and this permission notice shall be */ 00022 /* included in all copies or substantial portions of the */ 00023 /* Software. */ 00024 /* */ 00025 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */ 00026 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */ 00027 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */ 00028 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */ 00029 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */ 00030 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */ 00031 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */ 00032 /* OTHER DEALINGS IN THE SOFTWARE. */ 00033 /* */ 00034 /************************************************************************/ 00035 00036 #ifndef VIGRA_ACCUMULATOR_GRAMMAR_HXX 00037 #define VIGRA_ACCUMULATOR_GRAMMAR_HXX 00038 00039 #ifdef _MSC_VER 00040 #pragma warning (disable: 4503) 00041 #endif 00042 00043 #include "config.hxx" 00044 #include "metaprogramming.hxx" 00045 00046 namespace vigra { 00047 00048 namespace acc { 00049 00050 /**************************************************************************/ 00051 /* */ 00052 /* irreducible basic accumulators */ 00053 /* */ 00054 /**************************************************************************/ 00055 00056 00057 class CoordinateSystem; // returns an identity matrix of appropriate size 00058 00059 template <unsigned N> class PowerSum; // sum over powers of values 00060 template <unsigned N> class AbsPowerSum; // sum over powers of absolute values 00061 00062 class Skewness; // skewness 00063 class UnbiasedSkewness; // unbiased estimator for skewness 00064 class Kurtosis; // excess kurtosis 00065 class UnbiasedKurtosis; // unbiased estimator for excess kurtosis 00066 class FlatScatterMatrix; // flattened upper-triangular part of the scatter matrix 00067 class ScatterMatrixEigensystem; // eigenvalues and eigenvectors of the scatter matrix 00068 00069 // in all histogram classes: set bin count at runtime if BinCount == 0 00070 template <int BinCount> class IntegerHistogram; // use data values directly as bin indices 00071 template <int BinCount> class UserRangeHistogram; // set min/max explicitly at runtime 00072 template <int BinCount> class AutoRangeHistogram; // get min/max from accumulators 00073 template <int BinCount> class GlobalRangeHistogram; // like AutoRangeHistogram, but use global min/max rather than region min/max 00074 00075 class Minimum; // minimum 00076 class Maximum; // maximum 00077 template <class Hist> class StandardQuantiles; // compute (min, 10%, 25%, 50%, 75%, 90%, max) quantiles from 00078 // min/max accumulators and given histogram 00079 00080 class ArgMinWeight; // store the value (or coordinate) where weight was minimal 00081 class ArgMaxWeight; // store the value (or coordinate) where weight was maximal 00082 00083 // FIXME: not yet implemented 00084 template <unsigned NDim> class MultiHistogram; // multi-dimensional histogram 00085 // (always specify number of bins at runtime) 00086 00087 class Centralize; // cache centralized values 00088 class PrincipalProjection; // cache values after principal projection 00089 // FIXME: not yet implemented 00090 class Whiten; // cache values after whitening 00091 class RangeMapping; // map value from [min, max] to another range and cache result (e.g. for histogram creation) 00092 00093 template <int INDEX> class DataArg; // specifiy the index of the data member in a CoupledHandle 00094 template <int INDEX> class WeightArg; // specifiy the index of the weight member in a CoupledHandle 00095 template <int INDEX> class LabelArg; // specifiy the index of the label member in a CoupledHandle 00096 template <int INDEX> class CoordArg; // specifiy the index of the coord member in a CoupledHandle 00097 00098 /* 00099 Quantiles other than minimum and maximum require more thought: 00100 -------------------------------------------------------------- 00101 * Exact quantiles can be found in time O(n) using recursive partitioning (quickselect), 00102 but this requires the data (or an auxiliary index array) to be re-arranged. 00103 * Exact quantiles can be found in time O(k*n) using recursive histogram refinement, 00104 were k = O(log(n)/log(BinCount)) is the expected number of required passes over the 00105 data, provided that bins are filled approximately evenly. If data can be re-arranged, 00106 such that we remember the items corresponding to each bin, running time reduces to O(n) 00107 (this is Tibshirani's 'binmedian' algorithm). For the median, Tibshirani proves that 00108 the initial histogram only needs to cover the interval [Mean-StdDev, Mean+StdDev]. 00109 * Both strategies can be combined: perform k passes to reduce bin size to about 00110 n/(BinCount)^k, and then perform quickselect on an auxiliary array of size 00111 O(n/(BinCount)^k) which has been filled during the final pass. 00112 * Good approximate results can be obtained by early stopping of histogram refinement 00113 (Tibshirani's 'binapprox' algorithm). A 2-pass algorithm for the median achieves 00114 accuracy of StdDev/BinCount: Mean and StdDev are computed during pass 1, 00115 and a histogram over [Mean-StdDev, Mean+StdDev] during pass 2. 00116 * A 1-pass approximation method is described in Chen et al. However, it assumes that 00117 samples arrive in random order which is usually not true in image data. 00118 */ 00119 00120 /**************************************************************************/ 00121 /* */ 00122 /* modifiers for composite accumulators */ 00123 /* */ 00124 /**************************************************************************/ 00125 00126 // data normalization w.r.t. number of samples 00127 template <class A> class DivideByCount; // A / count 00128 template <class A> class RootDivideByCount; // sqrt(A / count) 00129 template <class A> class DivideUnbiased; // A / (count - 1) 00130 template <class A> class RootDivideUnbiased; // sqrt(A / (count - 1)) 00131 00132 // data access 00133 template <class A> class Coord; // use pixel coordinate instead of pixel value (index 0 of CoupledHandle) 00134 template <class A> class Weighted; // use (value, weight) pairs (index 1 and 2 of CoupledHandle) 00135 template <class A> class CoordWeighted; // use (coord, weight) pairs(index 0 and end of CoupledHandle) 00136 template <class A> class DataFromHandle; // extract data from index 1 of a CoupledHandle 00137 00138 // data preparation 00139 template <class A> class Central; // subtract mean 00140 template <class A> class Principal; // subtract mean and rotate to principal coordinates 00141 00142 // FIXME: not implemented yet 00143 template <class A> class Whitened; // transform to principal coordinates and scale to unit variance 00144 00145 template <class A> class Global; // compute statistic A globally rather than per region 00146 00147 /**************************************************************************/ 00148 /* */ 00149 /* alias names for important features */ 00150 /* */ 00151 /**************************************************************************/ 00152 00153 /** \brief Alias. Count. */ 00154 typedef PowerSum<0> Count; 00155 /** \brief Alias. Sum. */ 00156 typedef PowerSum<1> Sum; 00157 /** \brief Alias. Sum of squares. */ 00158 typedef PowerSum<2> SumOfSquares; 00159 00160 /** \brief Alias. Mean. */ 00161 typedef DivideByCount<Sum> Mean; 00162 /** \brief Alias. Root mean square. */ 00163 typedef RootDivideByCount<SumOfSquares> RootMeanSquares; 00164 00165 // desired pseudocode (unfortunately not legal in C++) 00166 // 00167 // template <unsigned N> 00168 // typedef DivideByCount<PowerSum<N> > Moment; 00169 // 00170 // actual definition (desired behavior is realised by rules below) 00171 // 00172 /** \brief Alias. Moment<N>. */ 00173 template <unsigned N> class Moment; 00174 /** \brief Alias. CentralMoment<N>. */ 00175 template <unsigned N> class CentralMoment; 00176 00177 /** \brief Alias. Sum of squared differences. */ 00178 typedef Central<PowerSum<2> > SumOfSquaredDifferences; 00179 /** \brief Alias. Sum of squared differences. */ 00180 typedef SumOfSquaredDifferences SSD; 00181 00182 /** \brief Alias. Variance. */ 00183 typedef DivideByCount<Central<PowerSum<2> > > Variance; 00184 /** \brief Alias. Standard deviation. */ 00185 typedef RootDivideByCount<Central<PowerSum<2> > > StdDev; 00186 /** \brief Alias. Unbiased variance. */ 00187 typedef DivideUnbiased<Central<PowerSum<2> > > UnbiasedVariance; 00188 /** \brief Alias. Unbiased standard deviation. */ 00189 typedef RootDivideUnbiased<Central<PowerSum<2> > > UnbiasedStdDev; 00190 00191 /** \brief Alias. Covariance. */ 00192 typedef DivideByCount<FlatScatterMatrix> Covariance; 00193 /** \brief Alias. Unbiased covariance. */ 00194 typedef DivideUnbiased<FlatScatterMatrix> UnbiasedCovariance; 00195 /** \brief Alias. Covariance eigensystem. */ 00196 typedef DivideByCount<ScatterMatrixEigensystem> CovarianceEigensystem; 00197 00198 /** \brief Alias. Absolute sum. */ 00199 typedef AbsPowerSum<1> AbsSum; 00200 /** \brief Alias. Sum of absolute differences. */ 00201 typedef Central<AbsSum> SumOfAbsDifferences; 00202 /** \brief Alias. Mean absolute deviation. */ 00203 typedef DivideByCount<SumOfAbsDifferences> MeanAbsoluteDeviation; 00204 00205 /** \brief Alias. Region center. */ 00206 typedef Coord<Mean> RegionCenter; 00207 /** \brief Alias. Region radii. */ 00208 typedef Coord<Principal<StdDev> > RegionRadii; 00209 /** \brief Alias. Region axes. */ 00210 typedef Coord<Principal<CoordinateSystem> > RegionAxes; 00211 00212 /** \brief Alias. Center of mass. */ 00213 typedef Weighted<RegionCenter> CenterOfMass; 00214 /** \brief Alias. Moments of inertia. */ 00215 typedef Weighted<Coord<Principal<Variance> > > MomentsOfInertia; 00216 /** \brief Alias. Axes of inertia. */ 00217 typedef Weighted<RegionAxes> AxesOfInertia; 00218 00219 /**************************************************************************/ 00220 /* */ 00221 /* Tag standardization rules */ 00222 /* */ 00223 /**************************************************************************/ 00224 00225 namespace detail { 00226 00227 template <class A> 00228 struct ModifierRule 00229 { 00230 typedef A type; 00231 }; 00232 00233 } // namespace detail 00234 00235 template <class A> 00236 struct Error___Tag_modifiers_of_same_kind_must_not_be_combined; 00237 00238 // apply rules as long as the Tag type changes ... 00239 template <class A, class S=typename detail::ModifierRule<A>::type> 00240 struct StandardizeTag 00241 { 00242 typedef typename StandardizeTag<S>::type type; 00243 }; 00244 00245 // ... and stop otherwise ... 00246 template <class A> 00247 struct StandardizeTag<A, A> 00248 { 00249 typedef A type; 00250 }; 00251 00252 // ... or fail when the tag spec was non-conforming 00253 template <class A, class B> 00254 struct StandardizeTag<A, Error___Tag_modifiers_of_same_kind_must_not_be_combined<B> > 00255 : public Error___Tag_modifiers_of_same_kind_must_not_be_combined<B> 00256 {}; 00257 00258 namespace detail { 00259 00260 // Assign priorities to modifiers to determine their standard order (by ascending priority). 00261 // SubstitutionMask determines which modifiers must be automatically transferred to dependencies. 00262 enum { MinPriority = 1, 00263 AccumulatorPriority = 32, 00264 PrepareDataPriority = 16, 00265 NormalizePriority = 8, 00266 AccessDataPriority = 4, 00267 WeightingPriority = 2, 00268 GlobalPriority = 1, 00269 MaxPriority = 32, 00270 SubstitutionMask = PrepareDataPriority | AccessDataPriority | WeightingPriority | GlobalPriority }; 00271 00272 template <class A> 00273 struct ModifierPriority 00274 { 00275 static const int value = AccumulatorPriority; 00276 }; 00277 00278 #define VIGRA_MODIFIER_PRIORITY(MODIFIER, VALUE) \ 00279 template <class A> \ 00280 struct ModifierPriority<MODIFIER<A> > \ 00281 { \ 00282 static const int value = VALUE; \ 00283 }; 00284 00285 VIGRA_MODIFIER_PRIORITY(Global, GlobalPriority) 00286 00287 VIGRA_MODIFIER_PRIORITY(Weighted, WeightingPriority) 00288 00289 VIGRA_MODIFIER_PRIORITY(Coord, AccessDataPriority) 00290 VIGRA_MODIFIER_PRIORITY(DataFromHandle, AccessDataPriority) 00291 00292 VIGRA_MODIFIER_PRIORITY(DivideByCount, NormalizePriority) 00293 VIGRA_MODIFIER_PRIORITY(RootDivideByCount, NormalizePriority) 00294 VIGRA_MODIFIER_PRIORITY(DivideUnbiased, NormalizePriority) 00295 VIGRA_MODIFIER_PRIORITY(RootDivideUnbiased, NormalizePriority) 00296 00297 VIGRA_MODIFIER_PRIORITY(Central, PrepareDataPriority) 00298 VIGRA_MODIFIER_PRIORITY(Principal, PrepareDataPriority) 00299 VIGRA_MODIFIER_PRIORITY(Whitened, PrepareDataPriority) 00300 00301 // explicitly set priority for base accumulators that look like modifiers 00302 VIGRA_MODIFIER_PRIORITY(StandardQuantiles, AccumulatorPriority) 00303 00304 #undef VIGRA_MODIFIER_PRIORITY 00305 00306 // check if the tag A contains a modifier with TARGET_PRIORITY 00307 template <class A, int TARGET_PRIORITY, int PRIORITY=ModifierPriority<A>::value> 00308 struct HasModifierPriority 00309 { 00310 typedef VigraFalseType type; 00311 static const bool value = false; 00312 }; 00313 00314 template <class A, int TARGET_PRIORITY> 00315 struct HasModifierPriority<A, TARGET_PRIORITY, TARGET_PRIORITY> 00316 { 00317 typedef VigraTrueType type; 00318 static const bool value = true; 00319 }; 00320 00321 template <class A, template <class> class B, int TARGET_PRIORITY, int PRIORITY> 00322 struct HasModifierPriority<B<A>, TARGET_PRIORITY, PRIORITY> 00323 : public HasModifierPriority<A, TARGET_PRIORITY> 00324 {}; 00325 00326 template <class A, template <class> class B, int TARGET_PRIORITY> 00327 struct HasModifierPriority<B<A>, TARGET_PRIORITY, TARGET_PRIORITY> 00328 { 00329 typedef VigraTrueType type; 00330 static const bool value = true; 00331 }; 00332 00333 // three-way compare 00334 template <class A, class B> 00335 struct ModifierCompare 00336 { 00337 static const int p1 = ModifierPriority<A>::value; 00338 static const int p2 = ModifierPriority<B>::value; 00339 static const int value = p1 < p2 00340 ? -1 00341 : p2 < p1 00342 ? 1 00343 : 0; 00344 }; 00345 00346 template <class A> 00347 struct ModifierCompareToInner; 00348 00349 template <class A, template <class> class B> 00350 struct ModifierCompareToInner<B<A> > 00351 : public ModifierCompare<B<A>, A> 00352 {}; 00353 00354 // sort modifiers by ascending priority 00355 template <class A, int compare=ModifierCompareToInner<A>::value> 00356 struct ModifierOrder; 00357 00358 // do nothing if the order is correct (compare == -1) 00359 template <class A> 00360 struct ModifierOrder<A, -1> 00361 { 00362 typedef A type; 00363 }; 00364 00365 // fail if there are two modifiers with the same priority (compare == 0) 00366 template <class A, template <class> class B, template <class> class C> 00367 struct ModifierOrder<C<B<A> >, 0> 00368 { 00369 typedef Error___Tag_modifiers_of_same_kind_must_not_be_combined<C<B<A> > > type; 00370 }; 00371 00372 // sort if the order is reversed (compare == 1) 00373 template <class A, template <class> class B, template <class> class C> 00374 struct ModifierOrder<C<B<A> >, 1> 00375 { 00376 typedef B<C<A> > type; 00377 }; 00378 00379 #define VIGRA_CLEANUP_DATA_PREPARATION_MODIFIERS(OUTER, INNER, RESULT) \ 00380 template <class A> \ 00381 struct ModifierOrder<OUTER<INNER<A > >, 0> \ 00382 { \ 00383 typedef RESULT<A > type; \ 00384 }; 00385 00386 // drop duplicates 00387 VIGRA_CLEANUP_DATA_PREPARATION_MODIFIERS(Central, Central, Central) 00388 VIGRA_CLEANUP_DATA_PREPARATION_MODIFIERS(Principal, Principal, Principal) 00389 VIGRA_CLEANUP_DATA_PREPARATION_MODIFIERS(Whitened, Whitened, Whitened) 00390 00391 // the strongest data preparation modifier takes precendence 00392 VIGRA_CLEANUP_DATA_PREPARATION_MODIFIERS(Principal, Central, Principal) 00393 VIGRA_CLEANUP_DATA_PREPARATION_MODIFIERS(Whitened, Central, Whitened) 00394 VIGRA_CLEANUP_DATA_PREPARATION_MODIFIERS(Whitened, Principal, Whitened) 00395 00396 // Coord takes precendence over DataFromHandle 00397 VIGRA_CLEANUP_DATA_PREPARATION_MODIFIERS(DataFromHandle, Coord, Coord) 00398 00399 #undef VIGRA_CLEANUP_DATA_PREPARATION_MODIFIERS 00400 00401 // drop duplicates 00402 template <class A, template <class> class B> 00403 struct ModifierRule<B<B<A> > > 00404 { 00405 typedef B<A> type; 00406 }; 00407 00408 template <class A, int PRIORITY=ModifierPriority<A>::value> 00409 struct RecurseModifier; 00410 00411 template <class A, template <class> class B, int PRIORITY> 00412 struct RecurseModifier<B<A>, PRIORITY> 00413 { 00414 typedef typename ModifierOrder<B<typename StandardizeTag<A>::type> >::type type; 00415 }; 00416 00417 template <class A, template <class> class B> 00418 struct RecurseModifier<B<A>, AccumulatorPriority> 00419 { 00420 typedef B<A> type; 00421 }; 00422 00423 // recurse down the modifier chain, but only of B is actually a modifier, 00424 // and not a templated base accumulator (i.e. do not recurse if B's 00425 // priority is 'AccumulatorPriority') 00426 template <class A, template <class> class B> 00427 struct ModifierRule<B<A> > 00428 : public RecurseModifier<B<A> > 00429 {}; 00430 00431 // reduce the SOURCE modifier to the TARGET modifier, 00432 // using the given TEMPLATE arguments 00433 // (this is a work-around for the lack of templated typedef in C++) 00434 #define VIGRA_REDUCE_MODFIER(TEMPLATE, SOURCE, TARGET) \ 00435 template <TEMPLATE > \ 00436 struct ModifierRule<SOURCE > \ 00437 { \ 00438 typedef TARGET type; \ 00439 }; 00440 00441 #define VIGRA_VOID 00442 00443 // centralizing doesn't change the CoordinateSystem 00444 VIGRA_REDUCE_MODFIER(VIGRA_VOID, Central<CoordinateSystem>, CoordinateSystem) 00445 // whitened CoordinateSystem are the same as principal CoordinateSystem 00446 VIGRA_REDUCE_MODFIER(VIGRA_VOID, Whitened<CoordinateSystem>, Principal<CoordinateSystem>) 00447 00448 // counting modified data is the same as counting data, except for weighted data and global counting 00449 VIGRA_REDUCE_MODFIER(template <class> class A, A<Count>, Count) 00450 VIGRA_REDUCE_MODFIER(VIGRA_VOID, Weighted<Count>, Weighted<Count>) 00451 VIGRA_REDUCE_MODFIER(VIGRA_VOID, CoordWeighted<Count>, Weighted<Count>) 00452 VIGRA_REDUCE_MODFIER(VIGRA_VOID, Global<Count>, Global<Count>) 00453 00454 // reduce aliases that typedef can't handle 00455 VIGRA_REDUCE_MODFIER(unsigned N, Moment<N>, DivideByCount<PowerSum<N> >) 00456 VIGRA_REDUCE_MODFIER(unsigned N, CentralMoment<N>, DivideByCount<Central<PowerSum<N> > >) 00457 VIGRA_REDUCE_MODFIER(class A, CoordWeighted<A>, Weighted<Coord<A> >) 00458 00459 // reduce statistics that are inherently centered 00460 VIGRA_REDUCE_MODFIER(VIGRA_VOID, Central<Centralize>, Centralize) 00461 VIGRA_REDUCE_MODFIER(VIGRA_VOID, Central<Skewness>, Skewness) 00462 VIGRA_REDUCE_MODFIER(VIGRA_VOID, Central<Kurtosis>, Kurtosis) 00463 VIGRA_REDUCE_MODFIER(VIGRA_VOID, Central<FlatScatterMatrix>, FlatScatterMatrix) 00464 VIGRA_REDUCE_MODFIER(VIGRA_VOID, Central<ScatterMatrixEigensystem>, ScatterMatrixEigensystem) 00465 00466 VIGRA_REDUCE_MODFIER(VIGRA_VOID, Principal<Centralize>, PrincipalProjection) 00467 VIGRA_REDUCE_MODFIER(VIGRA_VOID, Whitened<Centralize>, Whiten) 00468 VIGRA_REDUCE_MODFIER(VIGRA_VOID, Principal<PrincipalProjection>, PrincipalProjection) 00469 VIGRA_REDUCE_MODFIER(VIGRA_VOID, Whitened<PrincipalProjection>, Whiten) 00470 VIGRA_REDUCE_MODFIER(VIGRA_VOID, Whitened<Whiten>, Whiten) 00471 00472 // reduce even absolute powers to plain powers 00473 template <unsigned N> 00474 struct ModifierRule<AbsPowerSum<N> > 00475 { 00476 typedef typename IfBool<(N % 2 == 0), PowerSum<N>, AbsPowerSum<N> >::type type; 00477 }; 00478 00479 #undef VIGRA_VOID 00480 #undef VIGRA_REDUCE_MODFIER 00481 00482 template <class A> 00483 struct ShouldBeWeighted 00484 { 00485 typedef VigraFalseType type; 00486 static const bool value = false; 00487 }; 00488 00489 template <> 00490 struct ShouldBeWeighted<ArgMinWeight> 00491 { 00492 typedef VigraTrueType type; 00493 static const bool value = true; 00494 }; 00495 00496 template <> 00497 struct ShouldBeWeighted<ArgMaxWeight> 00498 { 00499 typedef VigraTrueType type; 00500 static const bool value = true; 00501 }; 00502 00503 template <class A, template <class> class B> 00504 struct ShouldBeWeighted<B<A> > 00505 : public ShouldBeWeighted<A> 00506 {}; 00507 00508 } // namespace detail 00509 00510 template <class A> 00511 struct IsCoordinateFeature 00512 { 00513 typedef VigraFalseType type; 00514 static const bool value = false; 00515 }; 00516 00517 template <class A, template <class> class B> 00518 struct IsCoordinateFeature<B<A> > 00519 { 00520 typedef typename IsCoordinateFeature<A>::type type; 00521 static const bool value = IsCoordinateFeature<A>::value; 00522 }; 00523 00524 template <class A> 00525 struct IsCoordinateFeature<Coord<A> > 00526 { 00527 typedef VigraTrueType type; 00528 static const bool value = true; 00529 }; 00530 00531 template <class A> 00532 struct IsPrincipalFeature 00533 { 00534 typedef VigraFalseType type; 00535 static const bool value = false; 00536 }; 00537 00538 template <class A, template <class> class B> 00539 struct IsPrincipalFeature<B<A> > 00540 { 00541 typedef typename IsPrincipalFeature<A>::type type; 00542 static const bool value = IsPrincipalFeature<A>::value; 00543 }; 00544 00545 template <class A> 00546 struct IsPrincipalFeature<Principal<A> > 00547 { 00548 typedef VigraTrueType type; 00549 static const bool value = true; 00550 }; 00551 00552 template <class A> 00553 struct IsPrincipalFeature<Whitened<A> > 00554 { 00555 typedef VigraTrueType type; 00556 static const bool value = true; 00557 }; 00558 00559 /**************************************************************************/ 00560 /* */ 00561 /* Tag transfer rules */ 00562 /* */ 00563 /**************************************************************************/ 00564 00565 namespace detail { 00566 00567 template <class A> 00568 struct DefaultModifier; 00569 00570 template <class A> 00571 struct ModifierPriority<DefaultModifier<A> > 00572 { 00573 static const int value = ModifierPriority<A>::value << 1; 00574 }; 00575 00576 template <class A, int TargetPriority, int Priority=ModifierPriority<A>::value> 00577 struct InsertDefaultModifier 00578 { 00579 typedef DefaultModifier<typename InsertDefaultModifier<A, (TargetPriority << 1)>::type> type; 00580 }; 00581 00582 template <class A, int TargetPriority> 00583 struct InsertDefaultModifier<A, TargetPriority, TargetPriority> 00584 { 00585 typedef A type; 00586 }; 00587 00588 template <class A, int TargetPriority, int Priority=ModifierPriority<A>::value> 00589 struct TagLongForm; 00590 00591 template <class A, int TargetPriority> 00592 struct TagLongForm<A, TargetPriority, MaxPriority> 00593 { 00594 typedef typename InsertDefaultModifier<A, TargetPriority>::type type; 00595 }; 00596 00597 template <class A, template <class> class B, int TargetPriority> 00598 struct TagLongForm<B<A>, TargetPriority, MaxPriority> 00599 { 00600 typedef typename InsertDefaultModifier<B<A>, TargetPriority>::type type; 00601 }; 00602 00603 template <class A, template <class> class B, int TargetPriority, int Priority> 00604 struct TagLongForm<B<A>, TargetPriority, Priority> 00605 { 00606 typedef typename TagLongForm<A, (Priority << 1)>::type Inner; 00607 typedef typename InsertDefaultModifier<B<Inner>, TargetPriority>::type type; 00608 }; 00609 00610 template <class A, template <class> class B, int TargetPriority> 00611 struct TagLongForm<B<A>, TargetPriority, TargetPriority> 00612 { 00613 typedef typename TagLongForm<A, (TargetPriority << 1)>::type Inner; 00614 typedef B<Inner> type; 00615 }; 00616 00617 template <class A> 00618 struct LongModifierRule 00619 { 00620 typedef A type; 00621 }; 00622 00623 // apply rules as long as the Tag type changes ... 00624 template <class A, class S=typename LongModifierRule<A>::type> 00625 struct StandardizeTagLongForm 00626 { 00627 typedef typename StandardizeTagLongForm<S>::type type; 00628 }; 00629 00630 // ... and stop otherwise ... 00631 template <class A> 00632 struct StandardizeTagLongForm<A, A> 00633 { 00634 typedef A type; 00635 }; 00636 00637 template <class A, template <class> class B> 00638 struct LongModifierRule<B<A> > 00639 { 00640 typedef B<typename LongModifierRule<A>::type> type; 00641 }; 00642 00643 template <class A> 00644 struct LongModifierRule<DefaultModifier<A> > 00645 { 00646 typedef A type; 00647 }; 00648 00649 #define VIGRA_DROP_DATA_PREPARATION_MODIFIERS(SOURCE, TARGET) \ 00650 template <> \ 00651 struct LongModifierRule<SOURCE > \ 00652 { \ 00653 typedef TARGET type; \ 00654 }; 00655 00656 VIGRA_DROP_DATA_PREPARATION_MODIFIERS(Central<Sum>, Sum) 00657 VIGRA_DROP_DATA_PREPARATION_MODIFIERS(Principal<Sum>, Sum) 00658 VIGRA_DROP_DATA_PREPARATION_MODIFIERS(Whitened<Sum>, Sum) 00659 VIGRA_DROP_DATA_PREPARATION_MODIFIERS(Principal<FlatScatterMatrix>, FlatScatterMatrix) 00660 VIGRA_DROP_DATA_PREPARATION_MODIFIERS(Whitened<FlatScatterMatrix>, FlatScatterMatrix) 00661 VIGRA_DROP_DATA_PREPARATION_MODIFIERS(Principal<ScatterMatrixEigensystem>, ScatterMatrixEigensystem) 00662 VIGRA_DROP_DATA_PREPARATION_MODIFIERS(Whitened<ScatterMatrixEigensystem>, ScatterMatrixEigensystem) 00663 00664 #undef VIGRA_DROP_DATA_PREPARATION_MODIFIERS 00665 00666 template <class A> 00667 struct CheckSubstitutionFlag 00668 { 00669 static const bool value = (ModifierPriority<A>::value & SubstitutionMask) != 0; 00670 }; 00671 00672 template <class A, class B, 00673 bool substitute=CheckSubstitutionFlag<A>::value> 00674 struct SubstituteModifiers; 00675 00676 template <class A, class B> 00677 struct SubstituteModifiers<A, B, false> 00678 { 00679 typedef B type; 00680 }; 00681 00682 template <class A0, template <class> class A1, class B0, template <class> class B1> 00683 struct SubstituteModifiers<A1<A0>, B1<B0>, true> 00684 { 00685 typedef A1<typename SubstituteModifiers<A0, B0>::type> type; 00686 }; 00687 00688 template <class A0, class B0, template <class> class B1> 00689 struct SubstituteModifiers<DefaultModifier<A0>, B1<B0>, true> 00690 { 00691 typedef B1<typename SubstituteModifiers<A0, B0>::type> type; 00692 }; 00693 00694 template <class A0, template <class> class A1, class B0, template <class> class B1> 00695 struct SubstituteModifiers<A1<A0>, B1<B0>, false> 00696 { 00697 typedef B1<typename SubstituteModifiers<A0, B0>::type> type; 00698 }; 00699 00700 } // namespace detail 00701 00702 template <class A, class B> 00703 struct TransferModifiers 00704 { 00705 typedef typename StandardizeTag<A>::type StdA; 00706 typedef typename StandardizeTag<B>::type StdB; 00707 typedef typename detail::TagLongForm<StdA, detail::MinPriority>::type AA; 00708 typedef typename detail::TagLongForm<StdB, detail::MinPriority>::type BB; 00709 typedef typename detail::SubstituteModifiers<AA, BB>::type AB; 00710 typedef typename detail::StandardizeTagLongForm<AB>::type StdAB; 00711 typedef typename StandardizeTag<StdAB>::type type; 00712 }; 00713 00714 template <class A, class HEAD, class TAIL> 00715 struct TransferModifiers<A, TypeList<HEAD, TAIL> > 00716 { 00717 typedef TypeList<typename TransferModifiers<A, HEAD>::type, 00718 typename TransferModifiers<A, TAIL>::type> type; 00719 }; 00720 00721 template <class A> 00722 struct TransferModifiers<A, void> 00723 { 00724 typedef void type; 00725 }; 00726 00727 template <class TargetTag, class A=typename TargetTag::Dependencies> 00728 struct StandardizeDependencies 00729 #ifndef DOXYGEN 00730 : public StandardizeDependencies<TargetTag, typename A::type> 00731 #endif 00732 {}; 00733 00734 template <class TargetTag, class HEAD, class TAIL> 00735 struct StandardizeDependencies<TargetTag, TypeList<HEAD, TAIL> > 00736 { 00737 typedef typename StandardizeTag<TargetTag>::type Target; 00738 typedef typename TransferModifiers<Target, TypeList<HEAD, TAIL> >::type type; 00739 }; 00740 00741 template <class TargetTag> 00742 struct StandardizeDependencies<TargetTag, void> 00743 { 00744 typedef void type; 00745 }; 00746 00747 }} // namespace vigra::acc 00748 00749 #endif // VIGRA_ACCUMULATOR_GRAMMAR_HXX
© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de) |
html generated using doxygen and Python
|