OpenGM  2.3.x
Discrete Graphical Model Library
graphicalmodel_factor_operator.hxx
Go to the documentation of this file.
1 #pragma once
2 #ifndef OPENGM_OPERATIONWRAPPER_HXX
3 #define OPENGM_OPERATIONWRAPPER_HXX
4 
8 
9 namespace opengm {
10 
12 
13 namespace functionwrapper {
14  struct FactorFlag;
15  struct IndependentFactorFlag;
16  struct IndependentFactorOrFactorFlag;
17  struct ScalarFlag;
18  struct ErrorFlag;
19 
20  namespace executor {
21 
22  namespace unary {
23 
24  template<class A, class B, class OP, size_t IX, size_t DX, bool END>
25  class OperationExecutor;
26 
27  template<class A, class B, class OP, size_t IX, size_t DX>
28  class OperationExecutor<A, B, OP, IX, DX, false>
29  {
30  public:
31  typedef std::vector<typename A::IndexType> ViType;
32 
33  static void op
34  (
35  const A& a,
36  B& b,
37  OP op,
38  const size_t rtia
39  ) {
40  if(rtia==IX) {
41  typedef typename meta::GetFunction<A, IX>::FunctionType FunctionTypeA;
42  typedef typename meta::GetFunction<B, 0>::FunctionType FunctionTypeB;
43  const FunctionTypeA& fa=meta::GetFunction<A, IX>::get(a);
44  FunctionTypeB& fb=meta::GetFunction<B, 0>::get(b);
45  b.variableIndexSequence().assign(a.variableIndexSequence().begin(),a.variableIndexSequence().end());
46  typedef opengm::UnaryOperationImpl<FunctionTypeA, FunctionTypeB, OP> UnaryOperationType;
47  UnaryOperationType::op(fa, fb, op);
48  }
49  else {
50  typedef OperationExecutor
51  <
52  A, B, OP,
53  IX+1,
54  DX,
55  meta::Bool<IX+1==DX>::value
56  > NewExecutorType;
57  NewExecutorType::op(a, b, op, rtia);
58  }
59  }
60  };
61 
62  template<class A, class B, class OP, size_t IX, size_t DX>
63  class OperationExecutor<A, B, OP, IX, DX, true>
64  {
65  public:
66  static void op
67  (
68  const A& a,
69  B& b,
70  OP op,
71  const size_t rtia
72  ) {
73  throw RuntimeError("Incorrect function type id.");
74  }
75  };
76 
77  } // namespace unary
78 
79  namespace binary {
80 
81  template<class A, class B, class C, class OP, size_t IX, size_t IY, size_t DX, size_t DY, bool END>
82  class OperationExecutor;
83 
84  template<class A, class B, class C, class OP, size_t IX, size_t IY, size_t DX, size_t DY>
85  class OperationExecutor<A, B, C, OP, IX, IY, DX, DY, false>
86  {
87  public:
88  typedef typename A::VisContainerType ViTypeA;
89  typedef typename B::VisContainerType ViTypeB;
90  typedef typename C::VisContainerType ViTypeC;
91  static void op
92  (
93  const A& a,
94  const B& b,
95  C& c,
96  OP op,
97  const ViTypeA& via,
98  const ViTypeB& vib,
99  ViTypeC& vic,
100  const size_t rtia,
101  const size_t rtib
102  ) {
103  if(rtia==IX && rtib==IY) {
104  typedef typename meta::GetFunction<A, IX>::FunctionType FunctionTypeA;
105  typedef typename meta::GetFunction<B, IY>::FunctionType FunctionTypeB;
106  typedef typename meta::GetFunction<C, 0>::FunctionType FunctionTypeC;
107  const FunctionTypeA& fa = meta::GetFunction<A, IX>::get(a);
108  const FunctionTypeB& fb = meta::GetFunction<B, IY>::get(b);
109  FunctionTypeC& fc = meta::GetFunction<C, 0>::get(c);
110  typedef opengm::BinaryOperationImpl<FunctionTypeA, FunctionTypeB, FunctionTypeC, OP> BinaryOperationType;
111  BinaryOperationType::op(fa, fb, fc, via, vib, vic, op);
112  }
113  else {
114  typedef typename meta::If
115  <
116  IX==DX-1,
117  meta::SizeT<0>,
118  meta::SizeT<IX+1>
119  >::type IXNewType;
120  typedef typename meta::If
121  <
122  IX==DX-1,
123  meta::SizeT<IY+1>,
124  meta::SizeT<IY>
125  >::type IYNewType;
126  typedef OperationExecutor
127  <
128  A, B, C, OP,
129  IXNewType::value,
130  IYNewType::value,
131  DX, DY,
132  meta::Bool< meta::And<(IX==DX-1) , (IY==DY-1)>::value >::value
133  > NewExecutorType;
134  NewExecutorType::op(a, b, c, op, via, vib, vic, rtia, rtib);
135  }
136  }
137  };
138 
139  template<class A, class B, class C, class OP, size_t IX, size_t IY, size_t DX, size_t DY>
140  class OperationExecutor<A, B, C, OP, IX, IY, DX, DY, true>
141  {
142  public:
143  typedef typename A::VisContainerType ViTypeA;
144  typedef typename B::VisContainerType ViTypeB;
145  typedef typename C::VisContainerType ViTypeC;
146  static void op
147  (
148  const A& a,
149  const B& b,
150  C& c,
151  OP op,
152  const ViTypeA& via,
153  const ViTypeB& vib,
154  ViTypeC& vic,
155  const size_t rtia,
156  const size_t rtib
157  ) {
158  throw RuntimeError("Incorrect function type id.");
159  }
160  };
161 
162  template<class A, class B, class OP, size_t IY, size_t DY, bool END>
163  class InplaceOperationExecutor;
164 
165  template<class A, class B, class OP, size_t IY, size_t DY>
166  class InplaceOperationExecutor<A, B, OP, IY, DY, false>
167  {
168  public:
169  typedef typename A::VisContainerType ViTypeA;
170  typedef typename B::VisContainerType ViTypeB;
171  static void op
172  (
173  A& a,
174  const B& b,
175  OP op,
176  const size_t rtib
177  ) {
178  if(rtib==IY) {
179  typedef typename meta::GetFunction<A, 0>::FunctionType FunctionTypeA;
180  typedef typename meta::GetFunction<B, IY>::FunctionType FunctionTypeB;
181  typedef typename FunctionTypeA::IndexType IndexType;
182  FunctionTypeA& fa=meta::GetFunction<A, 0>::get(a);
183  const FunctionTypeB& fb=meta::GetFunction<B, IY>::get(b);
184  ViTypeA & via=a.variableIndexSequence();
185  const ViTypeB & vib=b.variableIndexSequence();
186  typedef opengm::BinaryOperationInplaceImpl<FunctionTypeA, FunctionTypeB, OP> BinaryOperationType;
187  BinaryOperationType::op(fa, fb, via, vib, op);
188  }
189  else {
190  typedef InplaceOperationExecutor
191  <
192  A, B, OP,
193  IY+1,
194  DY,
195  meta::Bool<IY+1==DY>::value
196  > NewExecutorType;
197  NewExecutorType::op(a, b, op, rtib);
198  }
199  }
200  };
201 
202  template<class A, class B, class OP, size_t IY, size_t DY>
203  class InplaceOperationExecutor<A, B, OP, IY, DY, true>
204  {
205  public:
206  typedef std::vector<typename A::IndexType> ViType;
207  static void op
208  (
209  A& a,
210  const B& b,
211  OP op,
212  const size_t rtib
213  ) {
214  throw RuntimeError("Incorrect function type id.");
215  }
216  };
217 
218  } // namespace binary
219 
220  } // namespace executor
221 
222  namespace unary {
223 
224  template<class A, class B, class OP, class FlagA, class FlagB>
225  class OperationWrapper;
226 
227  // A is Independent factor
228  template<class A, class OP, class FlagA>
229  class InplaceOperationWrapper;
230 
231  // A factor or independet facotr
232  // B is independent factor
233  template<class A, class B, class OP>
234  class OperationWrapper<A, B, OP, IndependentFactorOrFactorFlag, IndependentFactorFlag>
235  {
236  public:
237  static void op
238  (
239  const A& a,
240  B& b,
241  OP op
242  ) {
243  typedef typename meta::EvalIf
244  <
245  meta::IsIndependentFactor<A>::value,
246  meta::Self<meta::SizeT<1> >,
247  meta::Self< meta::SizeT<A::NrOfFunctionTypes> >
248  >::type NFA;
249  typedef executor::unary::OperationExecutor<A, B, OP, 0, NFA::value, NFA::value==0> ExecutorType;
250  ExecutorType::op(a, b, op, opengm::meta::GetFunctionTypeIndex<A>::get(a));
251  }
252  };
253 
254  // A is scalar
255  // B is scalar
256  template<class A, class B, class OP>
257  class OperationWrapper<A, B, OP, ScalarFlag, ScalarFlag>
258  {
259  public:
260  static void op
261  (
262  const A& a,
263  B& b,
264  OP op
265  ) {
266  b = op(a);
267  }
268  };
269 
270  template<class A, class B, class OP>
271  class OperationWrapperSelector
272  {
273  typedef meta::Bool <opengm::meta::IsFundamental<A>::value> IsAScalarType;
274  typedef meta::Bool <opengm::meta::IsFundamental<B>::value> IsBScalarType;
275  typedef meta::Bool <opengm::meta::IsIndependentFactor<A>::value> IsAIndependentFactorType;
276  typedef meta::Bool <opengm::meta::IsIndependentFactor<B>::value> IsBIndependentFactorType;
277  typedef meta::Bool <opengm::meta::IsFactor<A>::value> IsAFactorType;
278  typedef meta::Bool <opengm::meta::IsFactor<B>::value> IsBFactorType;
279  // meta switch
280  typedef typename meta::TypeListGenerator
281  <
282  meta::SwitchCase<IsAScalarType::value, ScalarFlag>,
283  meta::SwitchCase< meta::Or<IsAIndependentFactorType::value , IsAFactorType::value>::value , IndependentFactorOrFactorFlag>
284  >::type CaseListA;
285  typedef typename meta::Switch<CaseListA, ErrorFlag>::type FlagA;
286  typedef typename meta::TypeListGenerator
287  <
288  meta::SwitchCase<IsBScalarType::value, ScalarFlag>,
289  meta::SwitchCase<IsBIndependentFactorType::value, IndependentFactorFlag>
290  >::type CaseListB;
291  typedef typename meta::Switch<CaseListB, ErrorFlag>::type FlagB;
292 
293  public:
294  static void op
295  (
296  const A& a,
297  B& b,
298  OP op
299  ) {
300  unary::OperationWrapper<A, B, OP, FlagA, FlagB>::op(a, b, op);
301  }
302  };
303 
304  // A is Independent factor
305  template<class A, class OP>
306  class InplaceOperationWrapper<A, OP, IndependentFactorFlag>
307  {
308  public:
309  static void op
310  (
311  A& a,
312  OP op
313  ) {
314  typedef typename meta::GetFunction<A, 0>::FunctionType FunctionTypeA;
315  FunctionTypeA& fa = meta::GetFunction<A, 0>::get(a);
316  typedef typename opengm::UnaryOperationInplaceImpl<FunctionTypeA, OP> UnaryOperationType;
317  UnaryOperationType::op(fa, op);
318  }
319  };
320 
321  //A is scalar
322  template<class A, class OP>
323  class InplaceOperationWrapper<A, OP, ScalarFlag>
324  {
325  public:
326  static void op
327  (
328  A& a,
329  OP op
330  ) {
331  a = op(a);
332  }
333  };
334 
335  template<class A, class OP>
336  class InplaceOperationWrapperSelector
337  {
338  typedef meta::Bool <opengm::meta::IsFundamental<A>::value> IsAScalarType;
339  typedef meta::Bool <opengm::meta::IsIndependentFactor<A>::value> IsAIndependentFactorType;
340  //meta switch
341  typedef typename meta::TypeListGenerator
342  <
343  meta::SwitchCase<IsAScalarType::value, ScalarFlag>,
344  meta::SwitchCase<IsAIndependentFactorType::value, IndependentFactorFlag>
345  >::type CaseListA;
346  typedef typename meta::Switch<CaseListA, ErrorFlag>::type FlagA;
347  typedef unary::InplaceOperationWrapper<A, OP, FlagA> OperationWrapperType;
348 
349  public:
350  static void op
351  (
352  A& a,
353  OP op
354  ) {
355  OperationWrapperType::op(a, op);
356  }
357  };
358 
359  } // namespace unary
360 
361  namespace binary {
362 
363  template<class A, class B, class C, class OP, class FlagA, class FlagB, class FlagC>
364  class OperationWrapper;
365  template<class A, class B, class OP, class FlagA, class FlagB>
366  class InplaceOperationWrapper;
367 
368  template<class A, class B, class C, class OP>
369  class OperationWrapper<A, B, C, OP, IndependentFactorOrFactorFlag, ScalarFlag, IndependentFactorFlag>
370  {
371  public:
372  static void op
373  (
374  const A& a,
375  const B& b,
376  C& c,
377  OP op
378  ) {
379  typedef typename opengm::BinaryToUnaryFunctor<B, OP, false> BTUFunctor;
380  BTUFunctor btufunctor(b, op);
381  opengm::functionwrapper::unary::OperationWrapperSelector<A, C, BTUFunctor>::op(a, c, btufunctor);
382  }
383  };
384 
385  template<class A, class B, class C, class OP>
386  class OperationWrapper<A, B, C, OP, ScalarFlag, IndependentFactorOrFactorFlag, IndependentFactorFlag>
387  {
388  public:
389  static void op
390  (
391  const A& a,
392  const B& b,
393  C& c, OP op
394  ) {
395  typedef opengm::SwapArgumemtFunctor<A, OP> SwapFunctorType;
396  OperationWrapper<B, A, C, SwapFunctorType, IndependentFactorOrFactorFlag, ScalarFlag, IndependentFactorFlag >::op(b, a, c, SwapFunctorType(op));
397  }
398  };
399 
400  template<class A, class B, class C, class OP>
401  class OperationWrapper<A, B, C, OP, ScalarFlag, ScalarFlag, ScalarFlag>
402  {
403  public:
404  static void op
405  (
406  const A& a,
407  const B& b,
408  C& c,
409  OP op
410  ) {
411  c = op(a, b);
412  }
413  };
414 
415  template<class A, class B, class C, class OP>
416  class OperationWrapper<A, B, C, OP, IndependentFactorOrFactorFlag, IndependentFactorOrFactorFlag, IndependentFactorFlag>
417  {
418  public:
419  typedef typename A::VisContainerType ViTypeA;
420  typedef typename B::VisContainerType ViTypeB;
421  typedef typename C::VisContainerType ViTypeC;
422  static void op
423  (
424  const A& a,
425  const B& b,
426  C& c,
427  OP op
428  ) {
429  const ViTypeA& viA = a.variableIndexSequence();
430  const ViTypeB& viB = b.variableIndexSequence();
431  ViTypeC & viC = c.variableIndexSequence();
432  typedef typename meta::EvalIf
433  <
434  meta::IsIndependentFactor<A>::value,
435  meta::Self<meta::SizeT<1> >,
436  meta::Self< meta::SizeT<A::NrOfFunctionTypes> >
437  >::type NFA;
438  typedef typename meta::EvalIf
439  <
440  meta::IsIndependentFactor<B>::value,
441  meta::Self<meta::SizeT<1> >,
442  meta::Self< meta::SizeT<B::NrOfFunctionTypes> >
443  >::type NFB;
444  typedef executor::binary::OperationExecutor<A, B, C, OP, 0, 0, NFA::value, NFB::value, meta::And<NFA::value==0 , NFB::value==0 >::value > ExecutorType;
445  ExecutorType::op
446  (
447  a, b, c,
448  op,
449  viA, viB, viC,
450  opengm::meta::GetFunctionTypeIndex<A>::get(a),
451  opengm::meta::GetFunctionTypeIndex<B>::get(b)
452  );
453  }
454  };
455 
456  template<class A, class B, class C, class OP>
457  class OperationWrapperSelector
458  {
459  typedef meta::Bool <opengm::meta::IsFundamental<A>::value> IsAScalarType;
460  typedef meta::Bool <opengm::meta::IsFundamental<B>::value> IsBScalarType;
461  typedef meta::Bool <opengm::meta::IsFundamental<C>::value> IsCScalarType;
462  typedef meta::Bool <opengm::meta::IsIndependentFactor<A>::value> IsAIndependentFactorType;
463  typedef meta::Bool <opengm::meta::IsIndependentFactor<B>::value> IsBIndependentFactorType;
464  typedef meta::Bool <opengm::meta::IsIndependentFactor<C>::value> IsCIndependentFactorType;
465  typedef meta::Bool <opengm::meta::IsFactor<A>::value> IsAFactorType;
466  typedef meta::Bool <opengm::meta::IsFactor<B>::value> IsBFactorType;
467  typedef meta::Bool <opengm::meta::IsFactor<C>::value> IsCFactorType;
468  typedef typename meta::TypeListGenerator
469  <
470  meta::SwitchCase<IsAScalarType::value, ScalarFlag>,
471  meta::SwitchCase<IsAIndependentFactorType::value ||IsAFactorType::value, IndependentFactorOrFactorFlag>
472  >::type CaseListA;
473  typedef typename meta::Switch<CaseListA, ErrorFlag>::type FlagA;
474  typedef typename meta::TypeListGenerator
475  <
476  meta::SwitchCase<IsBScalarType::value, ScalarFlag>,
477  meta::SwitchCase<IsBIndependentFactorType::value ||IsBFactorType::value, IndependentFactorOrFactorFlag>
478  >::type CaseListB;
479  typedef typename meta::Switch<CaseListB, ErrorFlag>::type FlagB;
480  typedef typename meta::TypeListGenerator
481  <
482  meta::SwitchCase<IsCScalarType::value, ScalarFlag>,
483  meta::SwitchCase<IsCIndependentFactorType::value, IndependentFactorFlag>
484  >::type CaseListC;
485  typedef typename meta::Switch<CaseListC, ErrorFlag>::type FlagC;
486  typedef binary::OperationWrapper<A, B, C, OP, FlagA, FlagB, FlagC> OperationWrapperType;
487 
488  public:
489  static void op
490  (
491  const A& a,
492  const B& b,
493  C& c,
494  OP op
495  ) {
496  OperationWrapperType::op(a, b, c, op);
497  }
498  };
499 
500  template<class A, class B, class OP>
501  class InplaceOperationWrapper<A, B, OP, ScalarFlag, ScalarFlag>
502  {
503  public:
504  static void op
505  (
506  A& a,
507  const B& b,
508  OP op
509  ) {
510  a = op(a, b);
511  }
512  };
513 
514  template<class A, class B, class OP>
515  class InplaceOperationWrapper<A, B, OP, IndependentFactorFlag, ScalarFlag>
516  {
517  public:
518  static void op
519  (
520  A& a,
521  const B& b,
522  OP op
523  ) {
524  typedef typename opengm::BinaryToUnaryFunctor<B, OP, false> BTUFunctor;
525  BTUFunctor btufunctor(b, op);
526  opengm::UnaryOperationInplaceImpl<A, BTUFunctor>::op(a, btufunctor);
527  }
528  };
529 
530  template<class A, class B, class OP>
531  class InplaceOperationWrapper<A, B, OP, IndependentFactorFlag, IndependentFactorOrFactorFlag>
532  {
533  public:
534  static void op
535  (
536  A& a,
537  const B& b,
538  OP op
539  ) {
540  typedef typename meta::EvalIf
541  <
542  meta::IsIndependentFactor<B>::value,
543  meta::Self<meta::SizeT<1> >,
544  meta::Self< meta::SizeT<B::NrOfFunctionTypes> >
545  >::type NFB;
546  typedef executor::binary::InplaceOperationExecutor<A, B, OP, 0, NFB::value, meta::Bool<NFB::value==0>::value> ExecutorType;
547  ExecutorType::op(a, b, op, opengm::meta::GetFunctionTypeIndex<B>::get(b));
548  }
549  };
550 
551  template<class A, class B, class OP>
552  class InplaceOperationWrapperSelector
553  {
554  typedef meta::Bool <opengm::meta::IsFundamental<A>::value> IsAScalarType;
555  typedef meta::Bool <opengm::meta::IsFundamental<B>::value> IsBScalarType;
556  typedef meta::Bool <opengm::meta::IsIndependentFactor<A>::value> IsAIndependentFactorType;
557  typedef meta::Bool <opengm::meta::IsIndependentFactor<B>::value> IsBIndependentFactorType;
558  typedef meta::Bool <opengm::meta::IsFactor<A>::value> IsAFactorType;
559  typedef meta::Bool <opengm::meta::IsFactor<B>::value> IsBFactorType;
560  typedef typename meta::TypeListGenerator
561  <
562  meta::SwitchCase<IsAScalarType::value, ScalarFlag>,
563  meta::SwitchCase<IsAIndependentFactorType::value , IndependentFactorFlag>
564  >::type CaseListA;
565  typedef typename meta::Switch<CaseListA, ErrorFlag>::type FlagA;
566  typedef typename meta::TypeListGenerator
567  <
568  meta::SwitchCase<IsBScalarType::value, ScalarFlag>,
569  meta::SwitchCase< meta::Or<IsBIndependentFactorType::value, IsBFactorType::value>::value, IndependentFactorOrFactorFlag>
570  >::type CaseListB;
571  typedef typename meta::Switch<CaseListB, ErrorFlag>::type FlagB;
572  typedef binary::InplaceOperationWrapper<A, B, OP, FlagA, FlagB> OperationWrapperType;
573 
574  public:
575  static void op
576  (
577  A& a,
578  const B& b,
579  OP op
580  ) {
581  OperationWrapperType::op(a, b, op);
582  }
583  };
584 
585  } // namespace binary
586 
587 } // namespace functionwrapper
588 
589 template<class A , class B , class C, class OP>
590 inline void operateBinary
591 (
592  const A& a,
593  const B& b ,
594  C& c,
595  OP op
596 ) {
597  functionwrapper::binary::OperationWrapperSelector<A, B, C, OP>::op(a, b, c, op);
598 }
599 
600 template<class A , class B, class OP>
601 inline void operateBinary
602 (
603  A& a,
604  const B& b ,
605  OP op
606 ) {
607  functionwrapper::binary::InplaceOperationWrapperSelector<A, B, OP>::op(a, b, op);
608 }
609 
610 template<class A , class B , class OP>
611 inline void operateUnary
612 (
613  const A& a,
614  B& b,
615  OP op
616 ) {
617  functionwrapper::unary::OperationWrapperSelector<A, B, OP>::op(a, b, op);
618 }
619 
620 template<class A, class OP>
621 inline void operateUnary
622 (
623  A& a ,
624  OP op
625 ) {
626  functionwrapper::unary::InplaceOperationWrapperSelector<A, OP>::op(a, op);
627 }
628 
630 
631 } // namespace opengm
632 
633 #endif // OPENGM_OPERATIONWRAPPER_HXX
The OpenGM namespace.
Definition: config.hxx:43