00001 #pragma once
00002 #ifndef OPENGM_FUNCTION_LEVEL_OPERATOR_HXX
00003 #define OPENGM_FUNCTION_LEVEL_OPERATOR_HXX
00004
00005 #include <vector>
00006 #include <set>
00007
00008 #include "opengm/opengm.hxx"
00009 #include "opengm/utilities/accessor_iterator.hxx"
00010 #include "opengm/utilities/shape_accessor.hxx"
00011 #include "opengm/utilities/indexing.hxx"
00012
00013 namespace opengm {
00014
00016
00019 class ComputeViAndAShape {
00020 public:
00021 typedef std::vector<size_t> ViSequenceType;
00022
00023 template<class A, class B ,class VI_A,class VI_B,class VI_C,class SHAPE_C>
00024 static inline void computeViandShape
00025 (
00026 const VI_A & via,
00027 const VI_B & vib,
00028 VI_C & vic,
00029 const A& a,
00030 const B& b ,
00031 SHAPE_C & shapeC
00032 ) {
00033 OPENGM_ASSERT(a.dimension() == via.size());
00034 OPENGM_ASSERT(a.dimension() != 0 || (a.dimension() == 0 && a.size() == 1));
00035 OPENGM_ASSERT(b.dimension() == vib.size());
00036 OPENGM_ASSERT(b.dimension() != 0 || (b.dimension() == 0 && b.size() == 1));
00037 shapeC.clear();
00038 vic.clear();
00039 const size_t dimA = via.size();
00040 const size_t dimB = vib.size();
00041 vic.reserve(dimA+dimB);
00042 shapeC.reserve(dimA+dimB);
00043 if(via.size() == 0 && vib.size() == 0) {
00044 }
00045 else if(via.size() == 0) {
00046 vic.assign(vib.begin(),vib.end());
00047 for(size_t i=0;i<dimB;++i) {
00048 shapeC.push_back(b.shape(i));
00049 }
00050 }
00051 else if(vib.size() == 0) {
00052 vic.assign(via.begin(),via.end());
00053 for(size_t i=0;i<dimA;++i) {
00054 shapeC.push_back(a.shape(i));
00055 }
00056 }
00057 else {
00058 size_t ia = 0;
00059 size_t ib = 0;
00060 bool first = true;
00061 while(ia<dimA || ib<dimB) {
00062 if(first==true) {
00063 first=false;
00064 if(via[ia]<=vib[ib]) {
00065 vic.push_back(via[ia]);
00066 shapeC.push_back(a.shape(ia));
00067 ++ia;
00068 }
00069 else{
00070 vic.push_back(vib[ib]);
00071 shapeC.push_back(b.shape(ib));
00072 ++ib;
00073 }
00074 }
00075 else if(ia>=dimA) {
00076 if(vic.back()!=vib[ib]) {
00077 vic.push_back(vib[ib]);
00078 shapeC.push_back(b.shape(ib));
00079 }
00080 ++ib;
00081 }
00082 else if(ib>=dimB) {
00083 if(vic.back()!=via[ia]) {
00084 vic.push_back(via[ia]);
00085 shapeC.push_back(a.shape(ia));
00086 }
00087 ++ia;
00088 }
00089 else if(via[ia]<=vib[ib]) {
00090 if(vic.back()!=via[ia] ) {
00091 vic.push_back(via[ia]);
00092 shapeC.push_back(a.shape(ia));
00093 }
00094 ++ia;
00095 }
00096 else{
00097 if(vic.back()!=vib[ib] ) {
00098 vic.push_back(vib[ib]);
00099 shapeC.push_back(b.shape(ib));
00100 }
00101 ++ib;
00102 }
00103 }
00104 OPENGM_ASSERT(ia == dimA);
00105 OPENGM_ASSERT(ib == dimB);
00106 }
00107 }
00108 };
00109
00111 template<class A, class B, class C, class OP>
00112 class BinaryOperationImpl
00113 {
00114 public:
00115 template<class VI_A,class VI_B,class VI_C>
00116 static void op(const A& , const B& , C& , const VI_A& , const VI_B & , VI_C & , OP);
00117 };
00118
00120 template<class A, class B, class OP>
00121 class BinaryOperationInplaceImpl
00122 {
00123 public:
00124 template<class VI_A,class VI_B>
00125 static void op(A& , const B& , VI_A& , const VI_B& , OP);
00126 };
00127
00129 template<class A, class B, class OP>
00130 class UnaryOperationImpl {
00131 public:
00132 static void op(const A& a, B& b, OP);
00133 };
00134
00136 template<class A, class OP>
00137 class UnaryOperationInplaceImpl {
00138 public:
00139 static void op(A& a, OP);
00140 };
00141
00143 template<class A, class B, class C, class OP>
00144 template<class VI_A,class VI_B,class VI_C>
00145 void BinaryOperationImpl<A, B, C, OP>::op
00146 (
00147 const A& a,
00148 const B& b,
00149 C& c,
00150 const VI_A & via,
00151 const VI_B & vib,
00152 VI_C & vic,
00153 OP op
00154 ) {
00155 OPENGM_ASSERT(a.dimension() == via.size());
00156 OPENGM_ASSERT(a.dimension() != 0 || (a.dimension() == 0 && a.size() == 1));
00157 OPENGM_ASSERT(b.dimension() == vib.size());
00158 OPENGM_ASSERT(b.dimension() != 0 || (b.dimension() == 0 && b.size() == 1));
00159
00160 c.assign();
00161
00162 opengm::FastSequence<typename C::LabelType> shapeC;
00163 ComputeViAndAShape::computeViandShape(via, vib, vic, a, b, shapeC);
00164 OPENGM_ASSERT(shapeC.size() == vic.size());
00165
00166 c.resize(shapeC.begin(), shapeC.end());
00167
00168 const size_t dimA = a.dimension();
00169 const size_t dimB = b.dimension();
00170
00171 const size_t numElemmentC = c.size();
00172 typedef typename opengm::FastSequence<typename C::LabelType>::ConstIteratorType FIterType;
00173 if(dimA != 0 && dimB != 0) {
00174 opengm::TripleShapeWalker<FIterType > shapeWalker(shapeC.begin(),shapeC.size(), vic, via, vib);
00175 for(size_t i=0; i<numElemmentC; ++i) {
00176 OPENGM_ASSERT(a.dimension() == shapeWalker.coordinateTupleA().size());
00177 OPENGM_ASSERT(b.dimension() == shapeWalker.coordinateTupleB().size());
00178 OPENGM_ASSERT(c.dimension() == shapeWalker.coordinateTupleAB().size());
00179 c(shapeWalker.coordinateTupleAB().begin()) = op(a(shapeWalker.coordinateTupleA().begin()), b(shapeWalker.coordinateTupleB().begin()));
00180 ++shapeWalker;
00181 }
00182 }
00183 else if(dimA == 0 && dimB == 0) {
00184 const size_t scalarIndex=0;
00185 c.resize(&scalarIndex, &scalarIndex+1);
00186 c(&scalarIndex) = op(a(&scalarIndex), b(&scalarIndex));
00187 }
00188 else if(dimA == 0) {
00189 opengm::ShapeWalker<FIterType > shapeWalker(shapeC.begin(),shapeC.size());
00190 const size_t scalarIndex=0;
00191 for(size_t i=0; i<numElemmentC; ++i) {
00192 c(shapeWalker.coordinateTuple().begin()) = op(a(&scalarIndex), b(shapeWalker.coordinateTuple().begin()));
00193 ++shapeWalker;
00194 }
00195 }
00196 else {
00197 opengm::ShapeWalker<FIterType > shapeWalker(shapeC.begin(),shapeC.size());
00198 const size_t scalarIndex=0;
00199 for(size_t i=0; i<numElemmentC; ++i) {
00200 c(shapeWalker.coordinateTuple().begin()) = op(a(shapeWalker.coordinateTuple().begin()), b(&scalarIndex));
00201 ++shapeWalker;
00202 }
00203 }
00204 OPENGM_ASSERT(a.dimension() == via.size());
00205 OPENGM_ASSERT(a.dimension() != 0 || (a.dimension() == 0 && a.size() == 1));
00206 OPENGM_ASSERT(b.dimension() == vib.size());
00207 OPENGM_ASSERT(b.dimension() != 0 || (b.dimension() == 0 && b.size() == 1));
00208 OPENGM_ASSERT(c.dimension() == vic.size());
00209 OPENGM_ASSERT(c.dimension() != 0 || (c.dimension() == 0 && c.size() == 1));
00210 }
00211
00213 template<class A, class B, class OP>
00214 template<class VI_A,class VI_B>
00215 void BinaryOperationInplaceImpl<A, B, OP>::op
00216 (
00217 A& a,
00218 const B& b,
00219 VI_A & via,
00220 const VI_B & vib,
00221 OP op
00222 )
00223 {
00224 OPENGM_ASSERT(a.dimension() == via.size());
00225 OPENGM_ASSERT(a.dimension() != 0 || (a.dimension() == 0 && a.size() == 1));
00226 OPENGM_ASSERT(b.dimension() == vib.size());
00227 OPENGM_ASSERT(b.dimension() != 0 || (b.dimension() == 0 && b.size() == 1));
00228
00229 opengm::FastSequence<size_t> shapeANew;
00230 opengm::FastSequence<size_t> viaNew;
00231 ComputeViAndAShape::computeViandShape(via, vib, viaNew, a, b, shapeANew);
00232 OPENGM_ASSERT(shapeANew.size() == viaNew.size());
00233
00234 if(viaNew.size() == via.size()) {
00235 if(viaNew.size() != 0) {
00236 if(vib.size() != 0) {
00237 const size_t numElementInA = a.size();
00238 opengm::DoubleShapeWalker<opengm::FastSequence<size_t>::const_iterator > shapeWalker(shapeANew.begin(),shapeANew.size(), viaNew, vib);
00239 for(size_t i=0; i<numElementInA; ++i) {
00240 a(shapeWalker.coordinateTupleAB().begin()) = op(a(shapeWalker.coordinateTupleAB().begin()), b(shapeWalker.coordinateTupleA().begin()));
00241 ++shapeWalker;
00242 }
00243 }
00244 else {
00245 const size_t numElementInA = a.size();
00246 opengm::DoubleShapeWalker<opengm::FastSequence<size_t>::const_iterator > shapeWalker(shapeANew.begin(),shapeANew.size(), viaNew, vib); const size_t scalarIndex = 0;
00247 for(size_t i=0; i<numElementInA; ++i) {
00248 a(shapeWalker.coordinateTupleAB().begin()) = op(a(shapeWalker.coordinateTupleAB().begin()), b(&scalarIndex));
00249 ++shapeWalker;
00250 }
00251 }
00252 }
00253 else {
00254 const size_t scalarIndex=0;
00255 a.resize(&scalarIndex, &scalarIndex+1);
00256 a(&scalarIndex) = op(a(&scalarIndex), b(&scalarIndex));
00257 via.assign(viaNew.begin(),viaNew.end());
00258 }
00259 }
00260
00261 else {
00262 A aNew;
00263 BinaryOperationImpl<A, B, A, OP>::op(a, b, aNew, via, vib, viaNew, op);
00264 a = aNew;
00265 via.assign(viaNew.begin(),viaNew.end());
00266 }
00267 OPENGM_ASSERT(a.dimension() == via.size());
00268 OPENGM_ASSERT(a.dimension() != 0 || (a.dimension() == 0 && a.size() == 1));
00269 OPENGM_ASSERT(b.dimension() == vib.size());
00270 OPENGM_ASSERT(b.dimension() != 0 || (b.dimension() == 0 && b.size() == 1));
00271 }
00272
00274 template<class A, class B, class OP>
00275 void UnaryOperationImpl<A, B, OP>::op
00276 (
00277 const A& a,
00278 B& b,
00279 OP op
00280 )
00281 {
00282 OPENGM_ASSERT(a.dimension() != 0 || (a.dimension() == 0 && a.size() == 1));
00283
00284 b.assign();
00285
00286 const size_t dimA = a.dimension();
00287 if(dimA != 0) {
00288
00289 typedef opengm::AccessorIterator<opengm::FunctionShapeAccessor<A>, true> ShapeIterType;
00290 ShapeIterType shapeABegin(a, 0);
00291 ShapeIterType shapeAEnd(a, dimA);
00292 b.resize(shapeABegin, shapeAEnd);
00293 opengm::ShapeWalker< ShapeIterType> shapeWalker(shapeABegin, dimA);
00294 const size_t numElemmentA = a.size();
00295 for(size_t i=0; i<numElemmentA; ++i) {
00296 b(shapeWalker.coordinateTuple().begin()) = op(a(shapeWalker.coordinateTuple().begin()));
00297 ++shapeWalker;
00298 }
00299 }
00300 else {
00301 const size_t scalarIndex=0;
00302 b.resize(&scalarIndex, &scalarIndex+1);
00303 b(&scalarIndex) = op(a(&scalarIndex));
00304 }
00305 }
00306
00308 template<class A, class OP>
00309 void UnaryOperationInplaceImpl<A, OP>::op
00310 (
00311 A& a,
00312 OP op
00313 )
00314 {
00315 OPENGM_ASSERT(a.dimension() != 0 || (a.dimension() == 0 && a.size() == 1));
00316 const size_t dimA = a.dimension();
00317 if(dimA != 0) {
00318 typedef opengm::AccessorIterator<opengm::FunctionShapeAccessor<A>, true> ShapeIterType;
00319 ShapeIterType shapeABegin(a, 0);
00320 opengm::ShapeWalker< ShapeIterType> shapeWalker(shapeABegin, dimA);
00321 const size_t numElemmentA = a.size();
00322 for(size_t i=0; i<numElemmentA; ++i) {
00323 a(shapeWalker.coordinateTuple().begin()) = op(a(shapeWalker.coordinateTuple().begin()));
00324 ++shapeWalker;
00325 }
00326 }
00327 else {
00328 const size_t scalarIndex=0;
00329 a(&scalarIndex) = op(a(&scalarIndex));
00330 }
00331 }
00332
00334
00335 }
00336
00337 #endif // #ifndef OPENGM_FUNCTION_LEVEL_OPERATOR_HXX