CppAD: A C++ Algorithmic Differentiation Package  20171217
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
cond_exp.hpp
Go to the documentation of this file.
1 # ifndef CPPAD_CORE_COND_EXP_HPP
2 # define CPPAD_CORE_COND_EXP_HPP
3 
4 /* --------------------------------------------------------------------------
5 CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
6 
7 CppAD is distributed under multiple licenses. This distribution is under
8 the terms of the
9  Eclipse Public License Version 1.0.
10 
11 A copy of this license is included in the COPYING file of this distribution.
12 Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
13 -------------------------------------------------------------------------- */
14 
15 /*
16 -------------------------------------------------------------------------------
17 $begin CondExp$$
18 $spell
19  Atan2
20  CondExp
21  Taylor
22  std
23  Cpp
24  namespace
25  inline
26  const
27  abs
28  Rel
29  bool
30  Lt
31  Le
32  Eq
33  Ge
34  Gt
35 $$
36 
37 
38 $section AD Conditional Expressions$$
39 $mindex assign$$
40 
41 $head Syntax$$
42 $icode%result% = CondExp%Rel%(%left%, %right%, %if_true%, %if_false%)%$$
43 
44 
45 $head Purpose$$
46 Record,
47 as part of an AD of $icode Base$$
48 $cref/operation sequence/glossary/Operation/Sequence/$$,
49 the conditional result
50 $codei%
51  if( %left% %Cop% %right% )
52  %result% = %if_true%
53  else %result% = %if_false%
54 %$$
55 The relational $icode Rel$$ and comparison operator $icode Cop$$
56 above have the following correspondence:
57 $codei%
58  %Rel% Lt Le Eq Ge Gt
59  %Cop% < <= == >= >
60 %$$
61 If $icode f$$ is the $cref ADFun$$ object corresponding to the
62 AD operation sequence,
63 the assignment choice for $icode result$$
64 in an AD conditional expression is made each time
65 $cref/f.Forward/Forward/$$ is used to evaluate the zero order Taylor
66 coefficients with new values for the
67 $cref/independent variables/glossary/Tape/Independent Variable/$$.
68 This is in contrast to the $cref/AD comparison operators/Compare/$$
69 which are boolean valued and not included in the AD operation sequence.
70 
71 $head Rel$$
72 In the syntax above, the relation $icode Rel$$ represents one of the following
73 two characters: $code Lt$$, $code Le$$, $code Eq$$, $code Ge$$, $code Gt$$.
74 As in the table above,
75 $icode Rel$$ determines which comparison operator $icode Cop$$ is used
76 when comparing $icode left$$ and $icode right$$.
77 
78 $head Type$$
79 These functions are defined in the CppAD namespace for arguments of
80 $icode Type$$ is $code float$$ , $code double$$, or any type of the form
81 $codei%AD<%Base%>%$$.
82 (Note that all four arguments must have the same type.)
83 
84 $head left$$
85 The argument $icode left$$ has prototype
86 $codei%
87  const %Type%& %left%
88 %$$
89 It specifies the value for the left side of the comparison operator.
90 
91 $head right$$
92 The argument $icode right$$ has prototype
93 $codei%
94  const %Type%& %right%
95 %$$
96 It specifies the value for the right side of the comparison operator.
97 
98 $head if_true$$
99 The argument $icode if_true$$ has prototype
100 $codei%
101  const %Type%& %if_true%
102 %$$
103 It specifies the return value if the result of the comparison is true.
104 
105 $head if_false$$
106 The argument $icode if_false$$ has prototype
107 $codei%
108  const %Type%& %if_false%
109 %$$
110 It specifies the return value if the result of the comparison is false.
111 
112 $head result$$
113 The $icode result$$ has prototype
114 $codei%
115  %Type%& %if_false%
116 %$$
117 
118 $head Optimize$$
119 The $cref optimize$$ method will optimize conditional expressions
120 in the following way:
121 During $cref/zero order forward mode/forward_zero/$$,
122 once the value of the $icode left$$ and $icode right$$ have been determined,
123 it is known if the true or false case is required.
124 From this point on, values corresponding to the case that is not required
125 are not computed.
126 This optimization is done for the rest of zero order forward mode
127 as well as forward and reverse derivatives calculations.
128 
129 $head Deprecate 2005-08-07$$
130 Previous versions of CppAD used
131 $codei%
132  CondExp(%flag%, %if_true%, %if_false%)
133 %$$
134 for the same meaning as
135 $codei%
136  CondExpGt(%flag%, %Type%(0), %if_true%, %if_false%)
137 %$$
138 Use of $code CondExp$$ is deprecated, but continues to be supported.
139 
140 $head Operation Sequence$$
141 This is an AD of $icode Base$$
142 $cref/atomic operation/glossary/Operation/Atomic/$$
143 and hence is part of the current
144 AD of $icode Base$$
145 $cref/operation sequence/glossary/Operation/Sequence/$$.
146 
147 
148 $head Example$$
149 
150 $head Test$$
151 $children%
152  example/general/cond_exp.cpp
153 %$$
154 The file
155 $cref cond_exp.cpp$$
156 contains an example and test of this function.
157 It returns true if it succeeds and false otherwise.
158 
159 $head Atan2$$
160 The following implementation of the
161 AD $cref atan2$$ function is a more complex
162 example of using conditional expressions:
163 $code
164 $srcfile%cppad/core/atan2.hpp%0%BEGIN CondExp%// END CondExp%$$
165 $$
166 
167 
168 $end
169 -------------------------------------------------------------------------------
170 */
171 // BEGIN CppAD namespace
172 namespace CppAD {
173 
174 template <class Base>
177  enum CompareOp cop ,
178  const AD<Base> &left ,
179  const AD<Base> &right ,
180  const AD<Base> &if_true ,
181  const AD<Base> &if_false )
182 {
183  AD<Base> returnValue;
184  CPPAD_ASSERT_UNKNOWN( Parameter(returnValue) );
185 
186  // check first case where do not need to tape
187  if( IdenticalPar(left) & IdenticalPar(right) )
188  { switch( cop )
189  {
190  case CompareLt:
191  if( left.value_ < right.value_ )
192  returnValue = if_true;
193  else returnValue = if_false;
194  break;
195 
196  case CompareLe:
197  if( left.value_ <= right.value_ )
198  returnValue = if_true;
199  else returnValue = if_false;
200  break;
201 
202  case CompareEq:
203  if( left.value_ == right.value_ )
204  returnValue = if_true;
205  else returnValue = if_false;
206  break;
207 
208  case CompareGe:
209  if( left.value_ >= right.value_ )
210  returnValue = if_true;
211  else returnValue = if_false;
212  break;
213 
214  case CompareGt:
215  if( left.value_ > right.value_ )
216  returnValue = if_true;
217  else returnValue = if_false;
218  break;
219 
220  default:
222  returnValue = if_true;
223  }
224  return returnValue;
225  }
226 
227  // must use CondExp incase Base is an AD type and recording
228  returnValue.value_ = CondExpOp(cop,
229  left.value_, right.value_, if_true.value_, if_false.value_);
230 
231  local::ADTape<Base> *tape = CPPAD_NULL;
232  if( Variable(left) )
233  tape = left.tape_this();
234  if( Variable(right) )
235  tape = right.tape_this();
236  if( Variable(if_true) )
237  tape = if_true.tape_this();
238  if( Variable(if_false) )
239  tape = if_false.tape_this();
240 
241  // add this operation to the tape
242  if( tape != CPPAD_NULL )
243  tape->RecordCondExp(cop,
244  returnValue, left, right, if_true, if_false);
245 
246  return returnValue;
247 }
248 
249 // --- RecordCondExp(cop, returnValue, left, right, if_true, if_false) -----
250 
251 /// All these operations are done in \c Rec_, so we should move this
252 /// routine to <tt>recorder<Base></tt>.
253 template <class Base>
255  enum CompareOp cop ,
256  AD<Base> &returnValue ,
257  const AD<Base> &left ,
258  const AD<Base> &right ,
259  const AD<Base> &if_true ,
260  const AD<Base> &if_false )
261 { addr_t ind0, ind1, ind2, ind3, ind4, ind5;
262  addr_t returnValue_taddr;
263 
264  // taddr_ of this variable
266  returnValue_taddr = Rec_.PutOp(CExpOp);
267 
268  // ind[0] = cop
269  ind0 = addr_t( cop );
270 
271  // ind[1] = base 2 represenation of the value
272  // [Var(left), Var(right), Var(if_true), Var(if_false)]
273  ind1 = 0;
274 
275  // Make sure returnValue is in the list of variables and set its taddr
276  if( Parameter(returnValue) )
277  returnValue.make_variable(id_, returnValue_taddr );
278  else returnValue.taddr_ = returnValue_taddr;
279 
280  // ind[2] = left address
281  if( Parameter(left) )
282  ind2 = Rec_.PutPar(left.value_);
283  else
284  { ind1 += 1;
285  ind2 = left.taddr_;
286  }
287 
288  // ind[3] = right address
289  if( Parameter(right) )
290  ind3 = Rec_.PutPar(right.value_);
291  else
292  { ind1 += 2;
293  ind3 = right.taddr_;
294  }
295 
296  // ind[4] = if_true address
297  if( Parameter(if_true) )
298  ind4 = Rec_.PutPar(if_true.value_);
299  else
300  { ind1 += 4;
301  ind4 = if_true.taddr_;
302  }
303 
304  // ind[5] = if_false address
305  if( Parameter(if_false) )
306  ind5 = Rec_.PutPar(if_false.value_);
307  else
308  { ind1 += 8;
309  ind5 = if_false.taddr_;
310  }
311 
313  CPPAD_ASSERT_UNKNOWN( ind1 > 0 );
314  Rec_.PutArg(ind0, ind1, ind2, ind3, ind4, ind5);
315 
316  // check that returnValue is a dependent variable
317  CPPAD_ASSERT_UNKNOWN( Variable(returnValue) );
318 }
319 
320 // ------------ CondExpOp(left, right, if_true, if_false) ----------------
321 
322 # define CPPAD_COND_EXP(Name) \
323  template <class Base> \
324  CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION \
325  AD<Base> CondExp##Name( \
326  const AD<Base> &left , \
327  const AD<Base> &right , \
328  const AD<Base> &if_true , \
329  const AD<Base> &if_false ) \
330  { \
331  return CondExpOp(Compare##Name, \
332  left, right, if_true, if_false); \
333  }
334 
335 // AD<Base>
341 template <class Base>
343 AD<Base> CondExp(
344  const AD<Base> &flag ,
345  const AD<Base> &if_true ,
346  const AD<Base> &if_false )
347 {
348  return CondExpOp(CompareGt, flag, AD<Base>(0), if_true, if_false);
349 }
350 
351 # undef CPPAD_COND_EXP
352 } // END CppAD namespace
353 
354 # endif
Base value_
Definition: ad.hpp:38
CPPAD_TAPE_ADDR_TYPE addr_t
Definition: declare_ad.hpp:44
Definition: ad.hpp:34
size_t NumArg(OpCode op)
Number of arguments for a specified operator.
Definition: op_code.hpp:175
size_t NumRes(OpCode op)
Number of variables resulting from the specified operation.
Definition: op_code.hpp:281
bool IdenticalPar(const std::complex< double > &x)
#define CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION
A version of the inline command that works with MC compiler.
Definition: define.hpp:43
CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION AD< Base > CondExp(const AD< Base > &flag, const AD< Base > &if_true, const AD< Base > &if_false)
Definition: cond_exp.hpp:343
CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION bool Variable(const AD< Base > &x)
Definition: par_var.hpp:99
void RecordCondExp(enum CompareOp cop, AD< Base > &returnValue, const AD< Base > &left, const AD< Base > &right, const AD< Base > &trueCase, const AD< Base > &falseCase)
All these operations are done in Rec_, so we should move this routine to recorder&lt;Base&gt;.
Definition: cond_exp.hpp:254
#define CPPAD_ASSERT_UNKNOWN(exp)
Check that exp is true, if not terminate execution.
Class used to hold tape that records AD&lt;Base&gt; operations.
Definition: ad_tape.hpp:26
CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION bool Parameter(const AD< Base > &x)
Definition: par_var.hpp:80
addr_t taddr_
Definition: ad.hpp:44
void make_variable(tape_id_t id, addr_t taddr)
Definition: ad.hpp:271
#define CPPAD_COND_EXP(Name)
Definition: cond_exp.hpp:322
std::complex< double > CondExpOp(enum CppAD::CompareOp cop, const std::complex< double > &left, const std::complex< double > &right, const std::complex< double > &trueCase, const std::complex< double > &falseCase)
local::ADTape< Base > * tape_this(void) const
Get a pointer to tape that records AD&lt;Base&gt; operations for the current thread.
Definition: tape_link.hpp:335