00001 #pragma once
00002 #ifndef OPENGM_FUNCTION_LEVEL_ACCUMULATOR_HXX
00003 #define OPENGM_FUNCTION_LEVEL_ACCUMULATOR_HXX
00004
00005 #include "opengm/utilities/accumulation.hxx"
00006 #include "opengm/utilities/accessor_iterator.hxx"
00007 #include "opengm/utilities/shape_accessor.hxx"
00008 #include "opengm/utilities/indexing.hxx"
00009
00010 namespace opengm {
00011
00013
00015 template<class A, class B, class ACC>
00016 class AccumulateAllImpl {
00017 typedef typename A::LabelType LabelType;
00018 typedef typename A::ValueType ValueType;
00019
00020 public:
00021 static void op(const A&, B&);
00022 static void op(const A&, B&, std::vector<LabelType>& state);
00023 };
00024
00026 template<class A, class B, class ACC>
00027 class AccumulateSomeImpl {
00028 typedef typename A::LabelType LabelType;
00029 typedef typename A::IndexType IndexType;
00030 typedef typename A::ValueType ValueType;
00031 typedef std::vector<IndexType> ViSequenceType;
00032
00033 public:
00034 template<class Iterator>
00035 static void op(const A&, const ViSequenceType&, Iterator, Iterator, B&, ViSequenceType&);
00036 };
00037
00039 template<class A, class ACC>
00040 class AccumulateSomeInplaceImpl {
00041 typedef typename A::LabelType LabelType;
00042 typedef typename A::IndexType IndexType;
00043 typedef typename A::ValueType ValueType;
00044 typedef std::vector<IndexType> ViSequenceType;
00045
00046 public:
00047 template<class Iterator>
00048 static void op(A&, ViSequenceType&, Iterator, Iterator);
00049 };
00050
00052 template<class A, class B, class ACC>
00053 void AccumulateAllImpl<A, B, ACC>::op
00054 (
00055 const A& a,
00056 B& b
00057 ) {
00058 OPENGM_ASSERT(a.dimension() != 0 || (a.dimension() == 0 && a.size() == 1));
00059 opengm::Accumulation<ValueType, LabelType, ACC> acc;
00060 const size_t dimA = a.dimension();
00061 const size_t numElement = a.size();
00062 if(dimA != 0) {
00063 typedef opengm::AccessorIterator<opengm::FunctionShapeAccessor<A>, true> ShapeIterType;
00064 ShapeIterType shapeABegin(a, 0);
00065 opengm::ShapeWalker< ShapeIterType> shapeWalker(shapeABegin, dimA);
00066 const opengm::FastSequence<size_t> & coordinate = shapeWalker.coordinateTuple();
00067 for(size_t i=0; i<numElement ; ++i) {
00068 acc(a(coordinate.begin()));
00069 ++shapeWalker;
00070 }
00071 }
00072 else {
00073 size_t indexSequenceToScalar[] = {0};
00074 acc(a(indexSequenceToScalar));
00075 }
00076 b = static_cast<B>(acc.value());
00077 }
00078
00080 template<class A, class B, class ACC>
00081 void AccumulateAllImpl<A, B, ACC>::op
00082 (
00083 const A& a,
00084 B& b,
00085 std::vector<typename AccumulateAllImpl<A, B, ACC>::LabelType>& state
00086 ) {
00087 OPENGM_ASSERT(a.dimension() != 0 || (a.dimension() == 0 && a.size() == 1));
00088 opengm::Accumulation<ValueType, LabelType, ACC> acc;
00089 const size_t dimA = a.dimension();
00090 const size_t numElement = a.size();
00091 if(dimA != 0) {
00092 state.resize(dimA);
00093 typedef opengm::AccessorIterator<opengm::FunctionShapeAccessor<A>, true> ShapeIterType;
00094 ShapeIterType shapeABegin(a, 0);
00095 opengm::ShapeWalker< ShapeIterType> shapeWalker(shapeABegin, dimA);
00096 const opengm::FastSequence<size_t> & coordinate = shapeWalker.coordinateTuple();
00097 for(size_t i=0; i<numElement; ++i) {
00098 acc(a(coordinate.begin()), coordinate);
00099 ++shapeWalker;
00100 }
00101 acc.state(state);
00102 }
00103 else {
00104 size_t indexSequenceToScalar[] = {0};
00105 acc(a(indexSequenceToScalar));
00106 state.clear();
00107 }
00108 b = static_cast<B>(acc.value());
00109 }
00110
00112 template<class A, class B, class ACC>
00113 template<class Iterator>
00114 void AccumulateSomeImpl<A, B, ACC>::op
00115 (
00116 const A& a,
00117 const ViSequenceType& viA,
00118 Iterator viAccBegin,
00119 Iterator viAccEnd,
00120 B& b,
00121 ViSequenceType& viB
00122 ) {
00123 OPENGM_ASSERT(a.dimension() == viA.size());
00124 OPENGM_ASSERT(a.dimension() != 0 || (a.dimension() == 0 && a.size() == 1));
00125 const size_t dimA = a.dimension();
00126 viB.clear();
00127 b.assign();
00128 if(dimA != 0) {
00129 size_t rawViSize = std::distance(viAccBegin, viAccEnd);
00130 opengm::FastSequence<size_t> viAcc;
00131 opengm::FastSequence<size_t> shapeAcc;
00132 opengm::FastSequence<size_t> shapeNotAcc;
00133 opengm::FastSequence<size_t> notAccPosition;
00134 for(size_t i=0; i <dimA; ++i) {
00135 bool found = false;
00136 for(size_t j=0; j < rawViSize; ++j) {
00137 if(static_cast<opengm::UInt64Type>(viA[i]) == static_cast<opengm::UInt64Type>(viAccBegin[j])) {
00138 viAcc.push_back(viAccBegin[j]);
00139 shapeAcc.push_back(a.shape(i));
00140 found = true;
00141 break;
00142 }
00143 }
00144 if(!found) {
00145 viB.push_back(viA[i]);
00146 shapeNotAcc.push_back(a.shape(i));
00147 notAccPosition.push_back(i);
00148 }
00149 }
00150 if(shapeAcc.size() == dimA) {
00151
00152 ValueType scalarAccResult;
00153 AccumulateAllImpl<A, ValueType, ACC>::op(a, scalarAccResult);
00154 size_t indexSequenceToScalar[] = {0};
00155 size_t shapeToScalarArray[] = {0};
00156 b.resize(shapeToScalarArray, shapeToScalarArray);
00157 b(indexSequenceToScalar) = scalarAccResult;
00158 }
00159 else if(shapeAcc.size() == 0) {
00160
00161
00162 b.resize(shapeNotAcc.begin(), shapeNotAcc.end());
00163 opengm::ShapeWalker< opengm::FastSequence<size_t>::const_iterator> shapeWalker(shapeNotAcc.begin(), dimA);
00164 const opengm::FastSequence<size_t> & coordinate = shapeWalker.coordinateTuple();
00165 for(size_t i=0; i <a.size() ; ++i) {
00166 b(coordinate.begin()) = a(coordinate.begin());
00167 ++shapeWalker;
00168 }
00169 viB.assign(viA.begin(),viA.end());
00170 }
00171 else {
00172
00173 b.resize(shapeNotAcc.begin(), shapeNotAcc.end());
00174
00175 opengm::ShapeWalker< opengm::FastSequence<size_t>::const_iterator> walker(shapeNotAcc.begin(), shapeNotAcc.size());
00176 const opengm::FastSequence<size_t> & coordinateNotAcc = walker.coordinateTuple();
00177
00178 typedef opengm::AccessorIterator<opengm::FunctionShapeAccessor<A>, true> ShapeIterType;
00179 ShapeIterType shapeABegin(a, 0);
00180 SubShapeWalker< ShapeIterType ,opengm::FastSequence<size_t>,opengm::FastSequence<size_t> >
00181 subWalker(shapeABegin, dimA, notAccPosition, coordinateNotAcc);
00182 const size_t subSizeAcc = subWalker.subSize();
00183
00184 for(size_t i=0; i<b.size(); ++i) {
00185
00186
00187 Accumulation<ValueType, LabelType, ACC> acc;
00188 subWalker.resetCoordinate();
00189 for(size_t j=0; j < subSizeAcc; ++j) {
00190 acc(a( subWalker.coordinateTuple().begin()));
00191 ++subWalker;
00192 }
00193 b(coordinateNotAcc.begin()) = acc.value();
00194 ++walker;
00195 }
00196 }
00197 }
00198 else {
00199 Accumulation<ValueType, LabelType, ACC> acc;
00200 size_t indexSequenceToScalar[] = {0};
00201 ValueType accRes=static_cast<ValueType>(0.0);
00202 acc(accRes);
00203 size_t shapeToScalarArray[] = {0};
00204 b.resize(shapeToScalarArray, shapeToScalarArray);
00205 b(indexSequenceToScalar) = acc.value();
00206 }
00207 OPENGM_ASSERT(b.dimension() == viB.size());
00208 OPENGM_ASSERT(b.dimension() != 0 || (b.dimension() == 0 && b.size() == 1));
00209 }
00210
00212 template<class A, class ACC>
00213 template<class Iterator>
00214 void AccumulateSomeInplaceImpl<A, ACC>::op
00215 (
00216 A& a,
00217 ViSequenceType& viA,
00218 Iterator viAccBegin,
00219 Iterator viAccEnd
00220 ) {
00221 OPENGM_ASSERT(a.dimension() == viA.size());
00222 OPENGM_ASSERT(a.dimension() != 0 || (a.dimension() == 0 && a.size() == 1));
00223 const size_t dimA = a.dimension();
00224 opengm::FastSequence<size_t> viB;
00225 if(dimA != 0) {
00226 const size_t rawViSize = std::distance(viAccBegin, viAccEnd);
00227 opengm::FastSequence<size_t> viAcc;
00228 opengm::FastSequence<size_t> shapeAcc;
00229 opengm::FastSequence<size_t> shapeNotAcc;
00230 opengm::FastSequence<size_t> notAccPosition;
00231 for(size_t i = 0; i <dimA; ++i) {
00232 bool found = false;
00233 for(size_t j=0; j < rawViSize; ++j) {
00234 if( static_cast<UInt64Type>(viA[i]) == static_cast<UInt64Type>(viAccBegin[j])) {
00235 viAcc.push_back(viAccBegin[j]);
00236 shapeAcc.push_back(a.shape(i));
00237 found = true;
00238 break;
00239 }
00240 }
00241 if(!found) {
00242 viB.push_back(viA[i]);
00243 shapeNotAcc.push_back(a.shape(i));
00244 notAccPosition.push_back(i);
00245 }
00246 }
00247 if(shapeAcc.size() == dimA) {
00248
00249 ValueType scalarAccResult;
00250 AccumulateAllImpl<A, ValueType, ACC>::op(a, scalarAccResult);
00251 a.assign();
00252 size_t shapeToScalarArray[] = {0};
00253 a.resize(shapeToScalarArray, shapeToScalarArray);
00254 a(shapeToScalarArray) = scalarAccResult;
00255 viA.clear();
00256 }
00257 else if(shapeAcc.size() == 0) {
00258
00259
00260 }
00261 else {
00262
00263 A b;
00264 b.resize(shapeNotAcc.begin(), shapeNotAcc.end());
00265
00266 opengm::ShapeWalker< typename opengm::FastSequence<size_t>::const_iterator> walker(shapeNotAcc.begin(), shapeNotAcc.size());
00267 const opengm::FastSequence<size_t> & coordinateNotAcc = walker.coordinateTuple();
00268
00269 typedef opengm::AccessorIterator<opengm::FunctionShapeAccessor<A>, true> ShapeIterType;
00270 ShapeIterType shapeABegin(a, 0);
00271 SubShapeWalker< ShapeIterType,opengm::FastSequence<size_t> ,opengm::FastSequence<size_t> >
00272 subWalker(shapeABegin, dimA, notAccPosition, coordinateNotAcc);
00273 const size_t subSizeAcc = subWalker.subSize();
00274
00275 for(size_t i=0; i < b.size(); ++i) {
00276
00277
00278 Accumulation<ValueType, LabelType, ACC> acc;
00279 subWalker.resetCoordinate();
00280 for(size_t j=0; j<subSizeAcc; ++j) {
00281 acc(a(subWalker.coordinateTuple().begin()));
00282 ++subWalker;
00283 }
00284 b(coordinateNotAcc.begin()) = acc.value();
00285 ++walker;
00286 }
00287 a = b;
00288 viA.assign(viB.begin(),viB.end());
00289 }
00290 }
00291 else {
00292 Accumulation<ValueType, LabelType, ACC> acc;
00293 ValueType accRes=static_cast<ValueType>(0.0);
00294 acc(accRes);
00295 a.assign();
00296 a(0) = acc.value();
00297 }
00298 OPENGM_ASSERT(a.dimension() == viA.size());
00299 OPENGM_ASSERT(a.dimension() != 0 || (a.dimension() == 0 && a.size() == 1));
00300 }
00301
00302 }
00303
00305
00306 #endif // OPENGM_FUNCTION_LEVEL_ACCUMULATOR_HXX