CppAD: A C++ Algorithmic Differentiation Package
20130918
|
00001 /* $Id$ */ 00002 # ifndef CPPAD_COND_EXP_INCLUDED 00003 # define CPPAD_COND_EXP_INCLUDED 00004 00005 /* -------------------------------------------------------------------------- 00006 CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell 00007 00008 CppAD is distributed under multiple licenses. This distribution is under 00009 the terms of the 00010 Eclipse Public License Version 1.0. 00011 00012 A copy of this license is included in the COPYING file of this distribution. 00013 Please visit http://www.coin-or.org/CppAD/ for information on other licenses. 00014 -------------------------------------------------------------------------- */ 00015 00016 /* 00017 ------------------------------------------------------------------------------- 00018 $begin CondExp$$ 00019 $spell 00020 Atan2 00021 CondExp 00022 Taylor 00023 std 00024 Cpp 00025 namespace 00026 inline 00027 const 00028 abs 00029 Rel 00030 bool 00031 Lt 00032 Le 00033 Eq 00034 Ge 00035 Gt 00036 $$ 00037 00038 $index conditional, expression$$ 00039 $index expression, conditional$$ 00040 $index assign, conditional$$ 00041 00042 $section AD Conditional Expressions$$ 00043 00044 $head Syntax$$ 00045 $icode%result% = CondExp%Rel%(%left%, %right%, %if_true%, %if_false%)%$$ 00046 00047 00048 $head Purpose$$ 00049 Record, 00050 as part of an AD of $icode Base$$ 00051 $cref/operation sequence/glossary/Operation/Sequence/$$, 00052 the conditional result 00053 $codei% 00054 if( %left% %Cop% %right% ) 00055 %result% = %if_true% 00056 else %result% = %if_false% 00057 %$$ 00058 The relational $icode Rel$$ and comparison operator $icode Cop$$ 00059 above have the following correspondence: 00060 $codei% 00061 %Rel% Lt Le Eq Ge Gt 00062 %Cop% < <= == >= > 00063 %$$ 00064 If $icode f$$ is the $cref ADFun$$ object corresponding to the 00065 AD operation sequence, 00066 the assignment choice for $icode result$$ 00067 in an AD conditional expression is made each time 00068 $cref/f.Forward/Forward/$$ is used to evaluate the zero order Taylor 00069 coefficients with new values for the 00070 $cref/independent variables/glossary/Tape/Independent Variable/$$. 00071 This is in contrast to the $cref/AD comparison operators/Compare/$$ 00072 which are boolean valued and not included in the AD operation sequence. 00073 00074 $head Rel$$ 00075 In the syntax above, the relation $icode Rel$$ represents one of the following 00076 two characters: $code Lt$$, $code Le$$, $code Eq$$, $code Ge$$, $code Gt$$. 00077 As in the table above, 00078 $icode Rel$$ determines which comparison operator $icode Cop$$ is used 00079 when comparing $icode left$$ and $icode right$$. 00080 00081 $head Type$$ 00082 These functions are defined in the CppAD namespace for arguments of 00083 $icode Type$$ is $code float$$ , $code double$$, or any type of the form 00084 $codei%AD<%Base%>%$$. 00085 (Note that all four arguments must have the same type.) 00086 00087 $head left$$ 00088 The argument $icode left$$ has prototype 00089 $codei% 00090 const %Type%& %left% 00091 %$$ 00092 It specifies the value for the left side of the comparison operator. 00093 00094 $head right$$ 00095 The argument $icode right$$ has prototype 00096 $codei% 00097 const %Type%& %right% 00098 %$$ 00099 It specifies the value for the right side of the comparison operator. 00100 00101 $head if_true$$ 00102 The argument $icode if_true$$ has prototype 00103 $codei% 00104 const %Type%& %if_true% 00105 %$$ 00106 It specifies the return value if the result of the comparison is true. 00107 00108 $head if_false$$ 00109 The argument $icode if_false$$ has prototype 00110 $codei% 00111 const %Type%& %if_false% 00112 %$$ 00113 It specifies the return value if the result of the comparison is false. 00114 00115 $head result$$ 00116 The $icode result$$ has prototype 00117 $codei% 00118 %Type%& %if_false% 00119 %$$ 00120 00121 $head Optimize$$ 00122 The $cref optimize$$ method will optimize conditional expressions 00123 in the following way: 00124 During $cref/zero order forward mode/forward_zero/$$, 00125 once the value of the $icode left$$ and $icode right$$ have been determined, 00126 it is known if the true or false case is required. 00127 From this point on, values corresponding to the case that is not required 00128 are not computed. 00129 This optimization is done for the rest of zero order forward mode 00130 as well as forward and reverse derivatives calculations. 00131 There is one exception to this optimization; see 00132 $cref/wish list/WishList/Conditional Expressions/$$. 00133 00134 $head Deprecated$$ 00135 Previous versions of CppAD used 00136 $codei% 00137 CondExp(%flag%, %if_true%, %if_false%) 00138 %$$ 00139 for the same meaning as 00140 $codei% 00141 CondExpGt(%flag%, %Type%(0), %if_true%, %if_false%) 00142 %$$ 00143 Use of $code CondExp$$ is deprecated, but continues to be supported. 00144 00145 $head Operation Sequence$$ 00146 This is an AD of $icode Base$$ 00147 $cref/atomic operation/glossary/Operation/Atomic/$$ 00148 and hence is part of the current 00149 AD of $icode Base$$ 00150 $cref/operation sequence/glossary/Operation/Sequence/$$. 00151 00152 00153 $head Example$$ 00154 00155 $head Test$$ 00156 $children% 00157 example/cond_exp.cpp 00158 %$$ 00159 The file 00160 $cref cond_exp.cpp$$ 00161 contains an example and test of this function. 00162 It returns true if it succeeds and false otherwise. 00163 00164 $head Atan2$$ 00165 The following implementation of the 00166 AD $cref atan2$$ function is a more complex 00167 example of using conditional expressions: 00168 $code 00169 $verbatim%cppad/local/atan2.hpp%0%BEGIN CondExp%// END CondExp%$$ 00170 $$ 00171 00172 00173 $end 00174 ------------------------------------------------------------------------------- 00175 */ 00176 // BEGIN CppAD namespace 00177 namespace CppAD { 00178 00179 template <class Base> 00180 CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION 00181 AD<Base> CondExpOp( 00182 enum CompareOp cop , 00183 const AD<Base> &left , 00184 const AD<Base> &right , 00185 const AD<Base> &if_true , 00186 const AD<Base> &if_false ) 00187 { 00188 AD<Base> returnValue; 00189 CPPAD_ASSERT_UNKNOWN( Parameter(returnValue) ); 00190 00191 // check first case where do not need to tape 00192 if( IdenticalPar(left) & IdenticalPar(right) ) 00193 { switch( cop ) 00194 { 00195 case CompareLt: 00196 if( left.value_ < right.value_ ) 00197 returnValue = if_true; 00198 else returnValue = if_false; 00199 break; 00200 00201 case CompareLe: 00202 if( left.value_ <= right.value_ ) 00203 returnValue = if_true; 00204 else returnValue = if_false; 00205 break; 00206 00207 case CompareEq: 00208 if( left.value_ == right.value_ ) 00209 returnValue = if_true; 00210 else returnValue = if_false; 00211 break; 00212 00213 case CompareGe: 00214 if( left.value_ >= right.value_ ) 00215 returnValue = if_true; 00216 else returnValue = if_false; 00217 break; 00218 00219 case CompareGt: 00220 if( left.value_ > right.value_ ) 00221 returnValue = if_true; 00222 else returnValue = if_false; 00223 break; 00224 00225 default: 00226 CPPAD_ASSERT_UNKNOWN(0); 00227 returnValue = if_true; 00228 } 00229 return returnValue; 00230 } 00231 00232 // must use CondExp incase Base is an AD type and recording 00233 returnValue.value_ = CondExpOp(cop, 00234 left.value_, right.value_, if_true.value_, if_false.value_); 00235 00236 ADTape<Base> *tape = CPPAD_NULL; 00237 if( Variable(left) ) 00238 tape = left.tape_this(); 00239 if( Variable(right) ) 00240 tape = right.tape_this(); 00241 if( Variable(if_true) ) 00242 tape = if_true.tape_this(); 00243 if( Variable(if_false) ) 00244 tape = if_false.tape_this(); 00245 00246 // add this operation to the tape 00247 if( tape != CPPAD_NULL ) 00248 tape->RecordCondExp(cop, 00249 returnValue, left, right, if_true, if_false); 00250 00251 return returnValue; 00252 } 00253 00254 // --- RecordCondExp(cop, returnValue, left, right, if_true, if_false) ----- 00255 00256 /// All these operations are done in \c Rec_, so we should move this 00257 /// routine to <tt>recorder<Base></tt>. 00258 template <class Base> 00259 void ADTape<Base>::RecordCondExp( 00260 enum CompareOp cop , 00261 AD<Base> &returnValue , 00262 const AD<Base> &left , 00263 const AD<Base> &right , 00264 const AD<Base> &if_true , 00265 const AD<Base> &if_false ) 00266 { size_t ind0, ind1, ind2, ind3, ind4, ind5; 00267 size_t returnValue_taddr; 00268 00269 // taddr_ of this variable 00270 CPPAD_ASSERT_UNKNOWN( NumRes(CExpOp) == 1 ); 00271 returnValue_taddr = Rec_.PutOp(CExpOp); 00272 00273 // ind[0] = cop 00274 ind0 = addr_t( cop ); 00275 00276 // ind[1] = base 2 representaion of the value 00277 // [Var(left), Var(right), Var(if_true), Var(if_false)] 00278 ind1 = 0; 00279 00280 // Make sure returnValue is in the list of variables and set its taddr 00281 if( Parameter(returnValue) ) 00282 returnValue.make_variable(id_, returnValue_taddr ); 00283 else returnValue.taddr_ = returnValue_taddr; 00284 00285 // ind[2] = left address 00286 if( Parameter(left) ) 00287 ind2 = Rec_.PutPar(left.value_); 00288 else 00289 { ind1 += 1; 00290 ind2 = left.taddr_; 00291 } 00292 00293 // ind[3] = right address 00294 if( Parameter(right) ) 00295 ind3 = Rec_.PutPar(right.value_); 00296 else 00297 { ind1 += 2; 00298 ind3 = right.taddr_; 00299 } 00300 00301 // ind[4] = if_true address 00302 if( Parameter(if_true) ) 00303 ind4 = Rec_.PutPar(if_true.value_); 00304 else 00305 { ind1 += 4; 00306 ind4 = if_true.taddr_; 00307 } 00308 00309 // ind[5] = if_false address 00310 if( Parameter(if_false) ) 00311 ind5 = Rec_.PutPar(if_false.value_); 00312 else 00313 { ind1 += 8; 00314 ind5 = if_false.taddr_; 00315 } 00316 00317 CPPAD_ASSERT_UNKNOWN( NumArg(CExpOp) == 6 ); 00318 CPPAD_ASSERT_UNKNOWN( ind1 > 0 ); 00319 Rec_.PutArg(ind0, ind1, ind2, ind3, ind4, ind5); 00320 00321 // check that returnValue is a dependent variable 00322 CPPAD_ASSERT_UNKNOWN( Variable(returnValue) ); 00323 } 00324 00325 // ------------ CondExpOp(left, right, if_true, if_false) ---------------- 00326 00327 # define CPPAD_COND_EXP(Name) \ 00328 template <class Base> \ 00329 CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION \ 00330 AD<Base> CondExp##Name( \ 00331 const AD<Base> &left , \ 00332 const AD<Base> &right , \ 00333 const AD<Base> &if_true , \ 00334 const AD<Base> &if_false ) \ 00335 { \ 00336 return CondExpOp(Compare##Name, \ 00337 left, right, if_true, if_false); \ 00338 } 00339 00340 // AD<Base> 00341 CPPAD_COND_EXP(Lt) 00342 CPPAD_COND_EXP(Le) 00343 CPPAD_COND_EXP(Eq) 00344 CPPAD_COND_EXP(Ge) 00345 CPPAD_COND_EXP(Gt) 00346 template <class Base> 00347 CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION 00348 AD<Base> CondExp( 00349 const AD<Base> &flag , 00350 const AD<Base> &if_true , 00351 const AD<Base> &if_false ) 00352 { 00353 return CondExpOp(CompareGt, flag, AD<Base>(0), if_true, if_false); 00354 } 00355 00356 # undef CPPAD_COND_EXP 00357 } // END CppAD namespace 00358 00359 # endif