CppADCodeGen  HEAD
A C++ Algorithmic Differentiation Package with Source Code Generation
cond_exp_op.hpp
1 #ifndef CPPAD_CG_COND_EXP_OP_INCLUDED
2 #define CPPAD_CG_COND_EXP_OP_INCLUDED
3 /* --------------------------------------------------------------------------
4  * CppADCodeGen: C++ Algorithmic Differentiation with Source Code Generation:
5  * Copyright (C) 2012 Ciengis
6  *
7  * CppADCodeGen is distributed under multiple licenses:
8  *
9  * - Eclipse Public License Version 1.0 (EPL1), and
10  * - GNU General Public License Version 3 (GPL3).
11  *
12  * EPL1 terms and conditions can be found in the file "epl-v10.txt", while
13  * terms and conditions for the GPL3 can be found in the file "gpl3.txt".
14  * ----------------------------------------------------------------------------
15  * Author: Joao Leal
16  */
17 
18 namespace CppAD {
19 
20 namespace {
21 
25 template<class Base>
26 inline bool isSameExpression(const cg::CG<Base>& trueCase,
27  const cg::CG<Base>& falseCase) {
28  return (trueCase.isParameter() && falseCase.isParameter() &&
29  trueCase.getValue() == falseCase.getValue()) ||
30  (trueCase.isVariable() && falseCase.isVariable() &&
31  trueCase.getOperationNode() == falseCase.getOperationNode());
32 }
33 
39 template<class Base>
40 inline cg::CodeHandler<Base>* findCodeHandler(const cg::CG<Base>& left,
41  const cg::CG<Base>& right,
42  const cg::CG<Base>& trueCase,
43  const cg::CG<Base>& falseCase) {
44  cg::CodeHandler<Base>* handler;
45 
46  cg::CodeHandler<Base>* lh = left.getCodeHandler();
47  cg::CodeHandler<Base>* rh = right.getCodeHandler();
48  cg::CodeHandler<Base>* th = trueCase.getCodeHandler();
49  cg::CodeHandler<Base>* fh = falseCase.getCodeHandler();
50 
51  if (!left.isParameter()) {
52  handler = lh;
53  } else if (!right.isParameter()) {
54  handler = rh;
55  } else if (!trueCase.isParameter()) {
56  handler = th;
57  } else if (!falseCase.isParameter()) {
58  handler = fh;
59  } else {
60  CPPAD_ASSERT_UNKNOWN(0)
61  throw cg::CGException("Unexpected error!");
62  }
63 
64  if ((!right.isParameter() && rh != handler)
65  || (!trueCase.isParameter() && th != handler)
66  || (!falseCase.isParameter() && fh != handler)) {
67  throw cg::CGException("Attempting to use different source code generation handlers in the same source code generation");
68  }
69 
70  return handler;
71 }
72 
73 } // END namespace
74 
79 template<class Base>
80 inline cg::CG<Base> CondExp(cg::CGOpCode op,
81  const cg::CG<Base>& left,
82  const cg::CG<Base>& right,
83  const cg::CG<Base>& trueCase,
84  const cg::CG<Base>& falseCase,
85  bool (*compare)(const Base&, const Base&)) {
86  using namespace CppAD::cg;
87 
88  if (left.isParameter() && right.isParameter()) {
89  if (compare(left.getValue(), right.getValue()))
90  return trueCase;
91  else
92  return falseCase;
93 
94 
95  } else if (isSameExpression(trueCase, falseCase)) {
96  return trueCase;
97  } else {
98 
99  CodeHandler<Base>* handler = findCodeHandler(left, right, trueCase, falseCase);
100 
101  CG<Base> result(*handler->makeNode(op,{left.argument(), right.argument(), trueCase.argument(), falseCase.argument()}));
102 
103  if (left.isValueDefined() && right.isValueDefined()) {
104  if (compare(left.getValue(), right.getValue())) {
105  if (trueCase.isValueDefined()) {
106  result.setValue(trueCase.getValue());
107  }
108  } else
109  if (falseCase.isValueDefined()) {
110  result.setValue(falseCase.getValue());
111  }
112  }
113 
114  return result;
115  }
116 
117 }
118 
122 template<class Base>
124  const cg::CG<Base>& right,
125  const cg::CG<Base>& trueCase,
126  const cg::CG<Base>& falseCase) {
127 
128  bool (*compare)(const Base&, const Base&) = [](const Base& l, const Base & r) {
129  return l < r;
130  };
131 
132  return CondExp(cg::CGOpCode::ComLt,
133  left, right,
134  trueCase, falseCase,
135  compare);
136 }
137 
141 template<class Base>
143  const cg::CG<Base>& right,
144  const cg::CG<Base>& trueCase,
145  const cg::CG<Base>& falseCase) {
146  bool (*comp)(const Base&, const Base&) = [](const Base& l, const Base & r) {
147  return l <= r;
148  };
149 
150  return CondExp(cg::CGOpCode::ComLe,
151  left, right,
152  trueCase, falseCase,
153  comp);
154 }
155 
159 template<class Base>
161  const cg::CG<Base>& right,
162  const cg::CG<Base>& trueCase,
163  const cg::CG<Base>& falseCase) {
164  bool (*comp)(const Base&, const Base&) = [](const Base& l, const Base & r) {
165  return l == r;
166  };
167 
168  return CondExp(cg::CGOpCode::ComEq,
169  left, right,
170  trueCase, falseCase,
171  comp);
172 }
173 
177 template<class Base>
179  const cg::CG<Base>& right,
180  const cg::CG<Base>& trueCase,
181  const cg::CG<Base>& falseCase) {
182  bool (*comp)(const Base&, const Base&) = [](const Base& l, const Base & r) {
183  return l >= r;
184  };
185 
186  return CondExp(cg::CGOpCode::ComGe,
187  left, right,
188  trueCase, falseCase,
189  comp);
190 }
191 
195 template<class Base>
197  const cg::CG<Base>& right,
198  const cg::CG<Base>& trueCase,
199  const cg::CG<Base>& falseCase) {
200  bool (*comp)(const Base&, const Base&) = [](const Base& l, const Base & r) {
201  return l > r;
202  };
203 
204  return CondExp(cg::CGOpCode::ComGt,
205  left, right,
206  trueCase, falseCase,
207  comp);
208 }
209 
210 template<class Base>
211 inline cg::CG<Base> CondExpOp(enum CompareOp cop,
212  const cg::CG<Base>& left,
213  const cg::CG<Base>& right,
214  const cg::CG<Base>& trueCase,
215  const cg::CG<Base>& falseCase) {
216  switch (cop) {
217  case CompareLt:
218  return CondExpLt(left, right, trueCase, falseCase);
219 
220  case CompareLe:
221  return CondExpLe(left, right, trueCase, falseCase);
222 
223  case CompareEq:
224  return CondExpEq(left, right, trueCase, falseCase);
225 
226  case CompareGe:
227  return CondExpGe(left, right, trueCase, falseCase);
228 
229  case CompareGt:
230  return CondExpGt(left, right, trueCase, falseCase);
231 
232  default:
233  CPPAD_ASSERT_UNKNOWN(0)
234  return trueCase;
235  }
236 }
237 
238 } // END CppAD namespace
239 
240 #endif
cg::CG< Base > CondExpGt(const cg::CG< Base > &left, const cg::CG< Base > &right, const cg::CG< Base > &trueCase, const cg::CG< Base > &falseCase)
const Base & getValue() const
Definition: variable.hpp:45
cg::CG< Base > CondExp(cg::CGOpCode op, const cg::CG< Base > &left, const cg::CG< Base > &right, const cg::CG< Base > &trueCase, const cg::CG< Base > &falseCase, bool(*compare)(const Base &, const Base &))
Definition: cond_exp_op.hpp:80
void setValue(const Base &val)
Definition: variable.hpp:54
cg::CG< Base > CondExpGe(const cg::CG< Base > &left, const cg::CG< Base > &right, const cg::CG< Base > &trueCase, const cg::CG< Base > &falseCase)
cg::CG< Base > CondExpLe(const cg::CG< Base > &left, const cg::CG< Base > &right, const cg::CG< Base > &trueCase, const cg::CG< Base > &falseCase)
cg::CG< Base > CondExpEq(const cg::CG< Base > &left, const cg::CG< Base > &right, const cg::CG< Base > &trueCase, const cg::CG< Base > &falseCase)
cg::CG< Base > CondExpLt(const cg::CG< Base > &left, const cg::CG< Base > &right, const cg::CG< Base > &trueCase, const cg::CG< Base > &falseCase)
bool isValueDefined() const
Definition: variable.hpp:40
bool isParameter() const
Definition: variable.hpp:35