operator.hxx

Go to the documentation of this file.
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    // clear c
00160    c.assign();
00161    // compute output vi's and shape of c
00162    opengm::FastSequence<typename C::LabelType> shapeC;
00163    ComputeViAndAShape::computeViandShape(via, vib, vic, a, b, shapeC);
00164    OPENGM_ASSERT(shapeC.size() == vic.size());
00165    // reshape c
00166    c.resize(shapeC.begin(), shapeC.end());
00167    // get dimensions and number of Elements in c
00168    const size_t dimA = a.dimension();
00169    const size_t dimB = b.dimension();
00170    //const size_t dimC = c.dimension();
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 { // DimB == 0
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    // compute output vi's and shape of a(new)
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    // in-place
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    // not inplace
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    // clear b
00284    b.assign();
00285    // get dimensions and number of Elements in b
00286    const size_t dimA = a.dimension();
00287    if(dimA !=  0) {
00288       // reshape b
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 } // namespace opengm
00336 
00337 #endif // #ifndef OPENGM_FUNCTION_LEVEL_OPERATOR_HXX
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
Generated on Mon Jun 17 16:31:05 2013 for OpenGM by  doxygen 1.6.3