graphicalmodel_factor_operator.hxx

Go to the documentation of this file.
00001 #pragma once
00002 #ifndef OPENGM_OPERATIONWRAPPER_HXX
00003 #define OPENGM_OPERATIONWRAPPER_HXX
00004 
00005 #include "opengm/utilities/functors.hxx"
00006 #include "opengm/functions/operations/operator.hxx"
00007 #include "opengm/utilities/metaprogramming.hxx"
00008 
00009 namespace opengm {
00010 
00012 
00013 namespace functionwrapper {
00014    struct FactorFlag;
00015    struct IndependentFactorFlag;
00016    struct IndependentFactorOrFactorFlag;
00017    struct ScalarFlag;
00018    struct ErrorFlag;
00019 
00020    namespace executor {
00021 
00022       namespace unary {
00023 
00024          template<class A, class B, class OP, size_t IX, size_t DX, bool END>
00025          class OperationExecutor;
00026 
00027          template<class A, class B, class OP, size_t IX, size_t DX>
00028          class OperationExecutor<A, B, OP, IX, DX, false>
00029          {
00030          public:
00031             typedef std::vector<typename A::IndexType> ViType;
00032 
00033             static void op
00034             (
00035                const A& a,
00036                B& b,
00037                OP op,
00038                const size_t rtia
00039             ) {
00040                if(rtia==IX) {
00041                   typedef typename meta::GetFunction<A, IX>::FunctionType FunctionTypeA;
00042                   typedef typename meta::GetFunction<B, 0>::FunctionType FunctionTypeB;
00043                   const FunctionTypeA& fa=meta::GetFunction<A, IX>::get(a);
00044                   FunctionTypeB& fb=meta::GetFunction<B, 0>::get(b);
00045                   b.variableIndexSequence()=a.variableIndexSequence();
00046                   typedef opengm::UnaryOperationImpl<FunctionTypeA, FunctionTypeB, OP> UnaryOperationType;
00047                   UnaryOperationType::op(fa, fb, op);
00048                }
00049                else {
00050                   typedef OperationExecutor
00051                   <
00052                      A, B, OP,
00053                      IX+1,
00054                      DX,
00055                      meta::Bool<IX+1==DX>::value
00056                   > NewExecutorType;
00057                   NewExecutorType::op(a, b, op, rtia);
00058                }
00059             }
00060          };
00061 
00062          template<class A, class B, class OP, size_t IX, size_t DX>
00063          class OperationExecutor<A, B, OP, IX, DX, true>
00064          {
00065          public:
00066             static void op
00067             (
00068                const A& a,
00069                B& b,
00070                OP op,
00071                const size_t rtia
00072             ) {
00073                throw RuntimeError("Incorrect function type id.");
00074             }
00075          };
00076 
00077       } // namespace unary
00078 
00079       namespace binary {
00080 
00081          template<class A, class B, class C, class OP, size_t IX, size_t IY, size_t DX, size_t DY, bool  END>
00082          class OperationExecutor;
00083 
00084          template<class A, class B, class C, class OP, size_t IX, size_t IY, size_t DX, size_t DY>
00085          class OperationExecutor<A, B, C, OP, IX, IY, DX, DY, false>
00086          {
00087          public:
00088             typedef std::vector<typename A::IndexType> ViType;
00089             static void op
00090             (
00091                const A& a,
00092                const B& b,
00093                C& c,
00094                OP op,
00095                const ViType& via,
00096                const ViType& vib,
00097                ViType& vic,
00098                const size_t rtia,
00099                const size_t rtib
00100             ) {
00101                if(rtia==IX && rtib==IY) {
00102                   typedef typename meta::GetFunction<A, IX>::FunctionType FunctionTypeA;
00103                   typedef typename meta::GetFunction<B, IY>::FunctionType FunctionTypeB;
00104                   typedef typename meta::GetFunction<C, 0>::FunctionType FunctionTypeC;
00105                   const FunctionTypeA& fa = meta::GetFunction<A, IX>::get(a);
00106                   const FunctionTypeB& fb = meta::GetFunction<B, IY>::get(b);
00107                   FunctionTypeC& fc = meta::GetFunction<C, 0>::get(c);
00108                   typedef opengm::BinaryOperationImpl<FunctionTypeA, FunctionTypeB, FunctionTypeC, OP> BinaryOperationType;
00109                   BinaryOperationType::op(fa, fb, fc, via, vib, vic, op);
00110                }
00111                else {
00112                   typedef typename meta::If
00113                   <
00114                      IX==DX-1,
00115                      meta::SizeT<0>,
00116                      meta::SizeT<IX+1>
00117                   >::type IXNewType;
00118                   typedef typename meta::If
00119                   <
00120                      IX==DX-1,
00121                      meta::SizeT<IY+1>,
00122                      meta::SizeT<IY>
00123                   >::type IYNewType;
00124                   typedef OperationExecutor
00125                   <
00126                      A, B, C, OP,
00127                      IXNewType::value,
00128                      IYNewType::value,
00129                      DX, DY,
00130                      meta::Bool<    meta::And<(IX==DX-1) , (IY==DY-1)>::value >::value
00131                   > NewExecutorType;
00132                   NewExecutorType::op(a, b, c, op, via, vib, vic, rtia, rtib);
00133                }
00134             }
00135          };
00136 
00137          template<class A, class B, class C, class OP, size_t IX, size_t IY, size_t DX, size_t DY>
00138          class OperationExecutor<A, B, C, OP, IX, IY, DX, DY, true>
00139          {
00140          public:
00141             typedef std::vector<typename A::IndexType> ViType;
00142             static void op
00143             (
00144                const A& a,
00145                const B& b,
00146                C& c,
00147                OP op,
00148                const ViType& via,
00149                const ViType& vib,
00150                ViType& vic,
00151                const size_t rtia,
00152                const size_t rtib
00153             ) {
00154                throw RuntimeError("Incorrect function type id.");
00155             }
00156          };
00157 
00158          template<class A, class B, class OP, size_t IY, size_t DY, bool END>
00159          class InplaceOperationExecutor;
00160 
00161          template<class A, class B, class OP, size_t IY, size_t DY>
00162          class InplaceOperationExecutor<A, B, OP, IY, DY, false>
00163          {
00164          public:
00165             typedef std::vector<typename A::IndexType> ViType;
00166             static void op
00167             (
00168                A& a,
00169                const B& b,
00170                OP op,
00171                const size_t rtib
00172             ) {
00173                if(rtib==IY) {
00174                   typedef typename meta::GetFunction<A, 0>::FunctionType FunctionTypeA;
00175                   typedef typename meta::GetFunction<B, IY>::FunctionType FunctionTypeB;
00176                   typedef typename FunctionTypeA::IndexType IndexType;
00177                   FunctionTypeA& fa=meta::GetFunction<A, 0>::get(a);
00178                   const FunctionTypeB& fb=meta::GetFunction<B, IY>::get(b);
00179                   std::vector<IndexType>& via=a.variableIndexSequence();
00180                   const std::vector<IndexType>& vib=b.variableIndexSequence();
00181                   typedef opengm::BinaryOperationInplaceImpl<FunctionTypeA, FunctionTypeB, OP> BinaryOperationType;
00182                   BinaryOperationType::op(fa, fb, via, vib, op);
00183                }
00184                else {
00185                   typedef InplaceOperationExecutor
00186                   <
00187                      A, B, OP,
00188                      IY+1,
00189                      DY,
00190                      meta::Bool<IY+1==DY>::value
00191                   > NewExecutorType;
00192                   NewExecutorType::op(a, b, op, rtib);
00193                }
00194             }
00195          };
00196 
00197          template<class A, class B, class OP, size_t IY, size_t DY>
00198          class InplaceOperationExecutor<A, B, OP, IY, DY, true>
00199          {
00200          public:
00201             typedef std::vector<typename A::IndexType> ViType;
00202             static void op
00203             (
00204                A& a,
00205                const B& b,
00206                OP op,
00207                const size_t rtib
00208             ) {
00209                throw RuntimeError("Incorrect function type id.");
00210             }
00211          };
00212 
00213       } // namespace binary
00214 
00215    } // namespace executor
00216 
00217    namespace unary {
00218 
00219       template<class A, class B, class OP, class FlagA, class FlagB>
00220       class OperationWrapper;
00221 
00222       // A is Independent factor
00223       template<class A, class OP, class FlagA>
00224       class InplaceOperationWrapper;
00225 
00226       // A factor or independet facotr
00227       // B is independent factor
00228       template<class A, class B, class OP>
00229       class OperationWrapper<A, B, OP, IndependentFactorOrFactorFlag, IndependentFactorFlag>
00230       {
00231       public:
00232          static void op
00233          (
00234             const A& a,
00235             B& b,
00236             OP op
00237          ) {
00238             typedef typename meta::EvalIf
00239             <
00240                meta::IsIndependentFactor<A>::value,
00241                meta::Self<meta::SizeT<1> >,
00242                meta::Self< meta::SizeT<A::NrOfFunctionTypes> >
00243             >::type NFA;
00244             typedef executor::unary::OperationExecutor<A, B, OP, 0, NFA::value, NFA::value==0> ExecutorType;
00245             ExecutorType::op(a, b, op, opengm::meta::GetFunctionTypeIndex<A>::get(a));
00246          }
00247       };
00248 
00249       // A is scalar
00250       // B is scalar
00251       template<class A, class B, class OP>
00252       class OperationWrapper<A, B, OP, ScalarFlag, ScalarFlag>
00253       {
00254       public:
00255          static void op
00256          (
00257             const A& a,
00258             B& b,
00259             OP op
00260          ) {
00261             b = op(a);
00262          }
00263       };
00264 
00265       template<class A, class B, class OP>
00266       class OperationWrapperSelector
00267       {
00268          typedef meta::Bool <opengm::meta::IsFundamental<A>::value> IsAScalarType;
00269          typedef meta::Bool <opengm::meta::IsFundamental<B>::value> IsBScalarType;
00270          typedef meta::Bool <opengm::meta::IsIndependentFactor<A>::value> IsAIndependentFactorType;
00271          typedef meta::Bool <opengm::meta::IsIndependentFactor<B>::value> IsBIndependentFactorType;
00272          typedef meta::Bool <opengm::meta::IsFactor<A>::value> IsAFactorType;
00273          typedef meta::Bool <opengm::meta::IsFactor<B>::value> IsBFactorType;
00274          // meta switch
00275          typedef typename meta::TypeListGenerator
00276          <
00277             meta::SwitchCase<IsAScalarType::value, ScalarFlag>,
00278             meta::SwitchCase< meta::Or<IsAIndependentFactorType::value , IsAFactorType::value>::value , IndependentFactorOrFactorFlag>
00279          >::type CaseListA;
00280          typedef typename meta::Switch<CaseListA, ErrorFlag>::type FlagA;
00281          typedef typename meta::TypeListGenerator
00282          <
00283             meta::SwitchCase<IsBScalarType::value, ScalarFlag>,
00284             meta::SwitchCase<IsBIndependentFactorType::value, IndependentFactorFlag>
00285          >::type CaseListB;
00286          typedef typename meta::Switch<CaseListB, ErrorFlag>::type FlagB;
00287 
00288       public:
00289          static void op
00290          (
00291             const A& a,
00292             B& b,
00293             OP op
00294          ) {
00295             unary::OperationWrapper<A, B, OP, FlagA, FlagB>::op(a, b, op);
00296          }
00297       };
00298 
00299       // A is Independent factor
00300       template<class A, class OP>
00301       class InplaceOperationWrapper<A, OP, IndependentFactorFlag>
00302       {
00303       public:
00304          static void op
00305          (
00306             A& a,
00307             OP op
00308          ) {
00309             typedef typename meta::GetFunction<A, 0>::FunctionType FunctionTypeA;
00310             FunctionTypeA& fa = meta::GetFunction<A, 0>::get(a);
00311             typedef typename opengm::UnaryOperationInplaceImpl<FunctionTypeA, OP> UnaryOperationType;
00312             UnaryOperationType::op(fa, op);
00313          }
00314       };
00315 
00316       //A is scalar
00317       template<class A, class OP>
00318       class InplaceOperationWrapper<A, OP, ScalarFlag>
00319       {
00320       public:
00321          static void op
00322          (
00323             A& a,
00324             OP op
00325          ) {
00326             a = op(a);
00327          }
00328       };
00329 
00330       template<class A, class OP>
00331       class InplaceOperationWrapperSelector
00332       {
00333          typedef meta::Bool <opengm::meta::IsFundamental<A>::value> IsAScalarType;
00334          typedef meta::Bool <opengm::meta::IsIndependentFactor<A>::value> IsAIndependentFactorType;
00335          //meta switch
00336          typedef typename meta::TypeListGenerator
00337          <
00338             meta::SwitchCase<IsAScalarType::value, ScalarFlag>,
00339             meta::SwitchCase<IsAIndependentFactorType::value, IndependentFactorFlag>
00340          >::type CaseListA;
00341          typedef typename meta::Switch<CaseListA, ErrorFlag>::type FlagA;
00342          typedef unary::InplaceOperationWrapper<A, OP, FlagA> OperationWrapperType;
00343 
00344       public:
00345          static void op
00346          (
00347             A& a,
00348             OP op
00349          ) {
00350             OperationWrapperType::op(a, op);
00351          }
00352       };
00353 
00354    } // namespace unary
00355 
00356    namespace binary {
00357 
00358       template<class A, class B, class C, class OP, class FlagA, class FlagB, class FlagC>
00359       class OperationWrapper;
00360       template<class A, class B, class OP, class FlagA, class FlagB>
00361       class InplaceOperationWrapper;
00362 
00363       template<class A, class B, class C, class OP>
00364       class OperationWrapper<A, B, C, OP, IndependentFactorOrFactorFlag, ScalarFlag, IndependentFactorFlag>
00365       {
00366       public:
00367          static void op
00368          (
00369             const A& a,
00370             const B& b,
00371             C& c,
00372             OP op
00373          ) {
00374             typedef typename opengm::BinaryToUnaryFunctor<B, OP, false> BTUFunctor;
00375             BTUFunctor btufunctor(b, op);
00376             opengm::functionwrapper::unary::OperationWrapperSelector<A, C, BTUFunctor>::op(a, c, btufunctor);
00377          }
00378       };
00379 
00380       template<class A, class B, class C, class OP>
00381       class OperationWrapper<A, B, C, OP, ScalarFlag, IndependentFactorOrFactorFlag, IndependentFactorFlag>
00382       {
00383       public:
00384          static void op
00385          (
00386             const A& a,
00387             const B& b,
00388             C& c, OP op
00389          ) {
00390             typedef opengm::SwapArgumemtFunctor<A, OP> SwapFunctorType;
00391             OperationWrapper<B, A, C, SwapFunctorType, IndependentFactorOrFactorFlag, ScalarFlag, IndependentFactorFlag >::op(b, a, c, SwapFunctorType(op));
00392          }
00393       };
00394 
00395       template<class A, class B, class C, class OP>
00396       class OperationWrapper<A, B, C, OP, ScalarFlag, ScalarFlag, ScalarFlag>
00397       {
00398       public:
00399          static void op
00400          (
00401             const A& a,
00402             const B& b,
00403             C& c,
00404             OP op
00405          ) {
00406             c = op(a, b);
00407          }
00408       };
00409 
00410       template<class A, class B, class C, class OP>
00411       class OperationWrapper<A, B, C, OP, IndependentFactorOrFactorFlag, IndependentFactorOrFactorFlag, IndependentFactorFlag>
00412       {
00413       public:
00414          typedef std::vector<typename A::IndexType> ViType;
00415 
00416          static void op
00417          (
00418             const A& a,
00419             const B& b,
00420             C& c,
00421             OP op
00422          ) {
00423             const ViType& viA = a.variableIndexSequence();
00424             const ViType& viB = b.variableIndexSequence();
00425             ViType& viC = c.variableIndexSequence();
00426             typedef typename meta::EvalIf
00427             <
00428                meta::IsIndependentFactor<A>::value,
00429                meta::Self<meta::SizeT<1> >,
00430                meta::Self< meta::SizeT<A::NrOfFunctionTypes> >
00431             >::type NFA;
00432             typedef typename meta::EvalIf
00433             <
00434                meta::IsIndependentFactor<B>::value,
00435                meta::Self<meta::SizeT<1> >,
00436                meta::Self< meta::SizeT<B::NrOfFunctionTypes> >
00437             >::type NFB;
00438             typedef executor::binary::OperationExecutor<A, B, C, OP, 0, 0, NFA::value, NFB::value, meta::And<NFA::value==0 , NFB::value==0 >::value > ExecutorType;
00439             ExecutorType::op
00440             (
00441                a, b, c,
00442                op,
00443                viA, viB, viC,
00444                opengm::meta::GetFunctionTypeIndex<A>::get(a),
00445                opengm::meta::GetFunctionTypeIndex<B>::get(b)
00446             );
00447          }
00448       };
00449 
00450       template<class A, class B, class C, class OP>
00451       class OperationWrapperSelector
00452       {
00453          typedef meta::Bool <opengm::meta::IsFundamental<A>::value> IsAScalarType;
00454          typedef meta::Bool <opengm::meta::IsFundamental<B>::value> IsBScalarType;
00455          typedef meta::Bool <opengm::meta::IsFundamental<C>::value> IsCScalarType;
00456          typedef meta::Bool <opengm::meta::IsIndependentFactor<A>::value> IsAIndependentFactorType;
00457          typedef meta::Bool <opengm::meta::IsIndependentFactor<B>::value> IsBIndependentFactorType;
00458          typedef meta::Bool <opengm::meta::IsIndependentFactor<C>::value> IsCIndependentFactorType;
00459          typedef meta::Bool <opengm::meta::IsFactor<A>::value> IsAFactorType;
00460          typedef meta::Bool <opengm::meta::IsFactor<B>::value> IsBFactorType;
00461          typedef meta::Bool <opengm::meta::IsFactor<C>::value> IsCFactorType;
00462          typedef typename meta::TypeListGenerator
00463          <
00464             meta::SwitchCase<IsAScalarType::value, ScalarFlag>,
00465             meta::SwitchCase<IsAIndependentFactorType::value ||IsAFactorType::value, IndependentFactorOrFactorFlag>
00466          >::type CaseListA;
00467          typedef typename meta::Switch<CaseListA, ErrorFlag>::type FlagA;
00468          typedef typename meta::TypeListGenerator
00469          <
00470             meta::SwitchCase<IsBScalarType::value, ScalarFlag>,
00471             meta::SwitchCase<IsBIndependentFactorType::value ||IsBFactorType::value, IndependentFactorOrFactorFlag>
00472          >::type CaseListB;
00473          typedef typename meta::Switch<CaseListB, ErrorFlag>::type FlagB;
00474          typedef typename meta::TypeListGenerator
00475          <
00476             meta::SwitchCase<IsCScalarType::value, ScalarFlag>,
00477             meta::SwitchCase<IsCIndependentFactorType::value, IndependentFactorFlag>
00478          >::type CaseListC;
00479          typedef typename meta::Switch<CaseListC, ErrorFlag>::type FlagC;
00480          typedef binary::OperationWrapper<A, B, C, OP, FlagA, FlagB, FlagC> OperationWrapperType;
00481 
00482       public:
00483          static void op
00484          (
00485             const A& a,
00486             const B& b,
00487             C& c,
00488             OP op
00489          ) {
00490             OperationWrapperType::op(a, b, c, op);
00491          }
00492       };
00493 
00494       template<class A, class B, class OP>
00495       class InplaceOperationWrapper<A, B, OP, ScalarFlag, ScalarFlag>
00496       {
00497       public:
00498          static void op
00499          (
00500             A& a,
00501             const B& b,
00502             OP op
00503          ) {
00504             a = op(a, b);
00505          }
00506       };
00507 
00508       template<class A, class B, class OP>
00509       class InplaceOperationWrapper<A, B, OP, IndependentFactorFlag, ScalarFlag>
00510       {
00511       public:
00512          static void op
00513          (
00514             A& a,
00515             const B& b,
00516             OP op
00517          ) {
00518             typedef typename opengm::BinaryToUnaryFunctor<B, OP, false> BTUFunctor;
00519             BTUFunctor btufunctor(b, op);
00520             opengm::UnaryOperationInplaceImpl<A, BTUFunctor>::op(a, btufunctor);
00521          }
00522       };
00523 
00524       template<class A, class B, class OP>
00525       class InplaceOperationWrapper<A, B, OP, IndependentFactorFlag, IndependentFactorOrFactorFlag>
00526       {
00527       public:
00528          static void op
00529          (
00530             A& a,
00531             const B& b,
00532             OP op
00533          ) {
00534             typedef typename meta::EvalIf
00535             <
00536                meta::IsIndependentFactor<B>::value,
00537                meta::Self<meta::SizeT<1> >,
00538                meta::Self< meta::SizeT<B::NrOfFunctionTypes> >
00539             >::type NFB;
00540             typedef executor::binary::InplaceOperationExecutor<A, B, OP, 0, NFB::value, meta::Bool<NFB::value==0>::value> ExecutorType;
00541             ExecutorType::op(a, b, op, opengm::meta::GetFunctionTypeIndex<B>::get(b));
00542          }
00543       };
00544 
00545       template<class A, class B, class OP>
00546       class InplaceOperationWrapperSelector
00547       {
00548          typedef meta::Bool <opengm::meta::IsFundamental<A>::value> IsAScalarType;
00549          typedef meta::Bool <opengm::meta::IsFundamental<B>::value> IsBScalarType;
00550          typedef meta::Bool <opengm::meta::IsIndependentFactor<A>::value> IsAIndependentFactorType;
00551          typedef meta::Bool <opengm::meta::IsIndependentFactor<B>::value> IsBIndependentFactorType;
00552          typedef meta::Bool <opengm::meta::IsFactor<A>::value> IsAFactorType;
00553          typedef meta::Bool <opengm::meta::IsFactor<B>::value> IsBFactorType;
00554          typedef typename meta::TypeListGenerator
00555          <
00556             meta::SwitchCase<IsAScalarType::value, ScalarFlag>,
00557             meta::SwitchCase<IsAIndependentFactorType::value , IndependentFactorFlag>
00558          >::type CaseListA;
00559          typedef typename meta::Switch<CaseListA, ErrorFlag>::type FlagA;
00560          typedef typename meta::TypeListGenerator
00561          <
00562             meta::SwitchCase<IsBScalarType::value, ScalarFlag>,
00563             meta::SwitchCase< meta::Or<IsBIndependentFactorType::value, IsBFactorType::value>::value, IndependentFactorOrFactorFlag>
00564          >::type CaseListB;
00565          typedef typename meta::Switch<CaseListB, ErrorFlag>::type FlagB;
00566          typedef binary::InplaceOperationWrapper<A, B, OP, FlagA, FlagB> OperationWrapperType;
00567 
00568       public:
00569          static void op
00570          (
00571             A& a,
00572             const B& b,
00573             OP op
00574          ) {
00575            OperationWrapperType::op(a, b, op);
00576          }
00577       };
00578 
00579    } // namespace binary
00580 
00581 } // namespace functionwrapper
00582 
00583 template<class A , class B , class C, class OP>
00584 inline void operateBinary
00585 (
00586    const A& a,
00587    const B& b ,
00588    C& c,
00589    OP op
00590 ) {
00591    functionwrapper::binary::OperationWrapperSelector<A, B, C, OP>::op(a, b, c, op);
00592 }
00593 
00594 template<class A , class B, class OP>
00595 inline void operateBinary
00596 (
00597    A& a,
00598    const B& b ,
00599    OP op
00600 ) {
00601    functionwrapper::binary::InplaceOperationWrapperSelector<A, B, OP>::op(a, b, op);
00602 }
00603 
00604 template<class A , class B , class OP>
00605 inline void operateUnary
00606 (
00607    const A& a,
00608    B& b,
00609    OP op
00610 ) {
00611    functionwrapper::unary::OperationWrapperSelector<A, B, OP>::op(a, b, op);
00612 }
00613 
00614 template<class A, class OP>
00615 inline void operateUnary
00616 (
00617    A& a ,
00618    OP op
00619 ) {
00620    functionwrapper::unary::InplaceOperationWrapperSelector<A, OP>::op(a, op);
00621 }
00622 
00624 
00625 } // namespace opengm
00626 
00627 #endif // OPENGM_OPERATIONWRAPPER_HXX
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
Generated on Mon Jun 17 16:31:03 2013 for OpenGM by  doxygen 1.6.3