CppAD: A C++ Algorithmic Differentiation Package 20110419
|
00001 /* $Id$ */ 00002 # ifndef CPPAD_COND_EXP_INCLUDED 00003 # define CPPAD_COND_EXP_INCLUDED 00004 00005 /* -------------------------------------------------------------------------- 00006 CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-11 Bradley M. Bell 00007 00008 CppAD is distributed under multiple licenses. This distribution is under 00009 the terms of the 00010 Common 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 $codei%%result% = CondExp%Rel%(%left%, %right%, %exp_if_true%, %exp_if_false%)%$$ 00046 00047 00048 $head Purpose$$ 00049 Record, 00050 as part of an AD of $icode Base$$ 00051 $xref/glossary/Operation/Sequence/operation sequence/1/$$, 00052 the conditional result 00053 $codei% 00054 if( %left% %Cop% %right% ) 00055 %result% = %exp_if_true% 00056 else %result% = %exp_if_false% 00057 %$$ 00058 The relational $icode Rel$$ and comparison operator $icode Cop$$ 00059 above have the following correspondence: 00060 $table 00061 $icode Rel$$ 00062 $pre $$ $cnext $code Lt$$ 00063 $pre $$ $cnext $code Le$$ 00064 $pre $$ $cnext $code Eq$$ 00065 $pre $$ $cnext $code Ge$$ 00066 $pre $$ $cnext $code Gt$$ 00067 $rnext 00068 $icode Cop$$ 00069 $cnext $code <$$ 00070 $cnext $code <=$$ 00071 $cnext $code ==$$ 00072 $cnext $code >=$$ 00073 $cnext $code >$$ 00074 $tend 00075 If $icode f$$ is the $xref/ADFun/$$ object corresponding to the 00076 AD operation sequence, 00077 the assignment choice for $icode result$$ 00078 in an AD conditional expression is made each time 00079 $xref/Forward//f.Forward/$$ is used to evaluate the zero order Taylor 00080 coefficients with new values for the 00081 $cref/independent variables/glossary/Tape/Independent Variable/$$. 00082 This is in contrast to the $xref/Compare//AD comparison operators/$$ 00083 which are boolean valued and not included in the AD operation sequence. 00084 00085 $head Rel$$ 00086 In the syntax above, the relation $icode Rel$$ represents one of the following 00087 two characters: $code Lt$$, $code Le$$, $code Eq$$, $code Ge$$, $code Gt$$. 00088 As in the table above, 00089 $icode Rel$$ determines which comparison operator $icode Cop$$ is used 00090 when comparing $icode left$$ and $icode right$$. 00091 00092 $head Type$$ 00093 These functions are defined in the CppAD namespace for arguments of 00094 $icode Type$$ is $code float$$ , $code double$$, or any type of the form 00095 $codei%AD<%Base%>%$$. 00096 (Note that all four arguments must have the same type.) 00097 00098 $head left$$ 00099 The argument $icode left$$ has prototype 00100 $codei% 00101 const %Type% &%left% 00102 %$$ 00103 It specifies the value for the left side of the comparison operator. 00104 00105 $head right$$ 00106 The argument $icode right$$ has prototype 00107 $codei% 00108 const %Type% &%right% 00109 %$$ 00110 It specifies the value for the right side of the comparison operator. 00111 00112 $head exp_if_true$$ 00113 The argument $icode exp_if_true$$ has prototype 00114 $codei% 00115 const %Type% &%exp_if_true% 00116 %$$ 00117 It specifies the return value if the result of the comparison is true. 00118 00119 $head exp_if_false$$ 00120 The argument $icode exp_if_false$$ has prototype 00121 $codei% 00122 const %Type% &%exp_if_false% 00123 %$$ 00124 It specifies the return value if the result of the comparison is false. 00125 00126 $head result$$ 00127 The $icode result$$ has prototype 00128 $codei% 00129 %Type% &%exp_if_false% 00130 %$$ 00131 00132 00133 $head CondExp$$ 00134 Previous versions of CppAD used 00135 $codei% 00136 CondExp(%flag%, %exp_if_true%, %exp_if_false%) 00137 %$$ 00138 for the same meaning as 00139 $codei% 00140 CondExpGt(%flag%, %Type%(0), %exp_if_true%, %exp_if_false%) 00141 %$$ 00142 Use of $code CondExp$$ is deprecated, but continues to be supported. 00143 00144 $head Operation Sequence$$ 00145 This is an AD of $icode Base$$ 00146 $xref/glossary/Operation/Atomic/atomic operation/1/$$ 00147 and hence is part of the current 00148 AD of $icode Base$$ 00149 $xref/glossary/Operation/Sequence/operation sequence/1/$$. 00150 00151 00152 $head Example$$ 00153 00154 $head Test$$ 00155 $children% 00156 example/cond_exp.cpp 00157 %$$ 00158 The file 00159 $xref/CondExp.cpp/$$ 00160 contains an example and test of this function. 00161 It returns true if it succeeds and false otherwise. 00162 00163 $head Atan2$$ 00164 The following implementation of the 00165 AD $xref/atan2/$$ function is a more complex 00166 example of using conditional expressions: 00167 $code 00168 $verbatim%cppad/local/atan2.hpp%0%BEGIN CondExp%// END CondExp%$$ 00169 $$ 00170 00171 00172 $end 00173 ------------------------------------------------------------------------------- 00174 */ 00175 // BEGIN CppAD namespace 00176 namespace CppAD { 00177 00178 // ------------ CondExpOp(cop, left, right, exp_if_true, exp_if_false) -------------- 00179 // CompareType and ResultType are different for the forward and reverse 00180 // sparese calculations. 00181 template <class CompareType, class ResultType> 00182 CPPAD_INLINE ResultType CondExpTemplate( 00183 enum CompareOp cop , 00184 const CompareType &left , 00185 const CompareType &right , 00186 const ResultType &exp_if_true , 00187 const ResultType &exp_if_false ) 00188 { ResultType returnValue; 00189 switch( cop ) 00190 { 00191 case CompareLt: 00192 if( left < right ) 00193 returnValue = exp_if_true; 00194 else returnValue = exp_if_false; 00195 break; 00196 00197 case CompareLe: 00198 if( left <= right ) 00199 returnValue = exp_if_true; 00200 else returnValue = exp_if_false; 00201 break; 00202 00203 case CompareEq: 00204 if( left == right ) 00205 returnValue = exp_if_true; 00206 else returnValue = exp_if_false; 00207 break; 00208 00209 case CompareGe: 00210 if( left >= right ) 00211 returnValue = exp_if_true; 00212 else returnValue = exp_if_false; 00213 break; 00214 00215 case CompareGt: 00216 if( left > right ) 00217 returnValue = exp_if_true; 00218 else returnValue = exp_if_false; 00219 break; 00220 00221 default: 00222 CPPAD_ASSERT_UNKNOWN(0); 00223 returnValue = exp_if_true; 00224 } 00225 return returnValue; 00226 } 00227 00228 inline float CondExpOp( 00229 enum CompareOp cop , 00230 const float &left , 00231 const float &right , 00232 const float &exp_if_true , 00233 const float &exp_if_false ) 00234 { return CondExpTemplate(cop, left, right, exp_if_true, exp_if_false); 00235 } 00236 00237 inline double CondExpOp( 00238 enum CompareOp cop , 00239 const double &left , 00240 const double &right , 00241 const double &exp_if_true , 00242 const double &exp_if_false ) 00243 { return CondExpTemplate(cop, left, right, exp_if_true, exp_if_false); 00244 } 00245 00246 template <class Base> 00247 CPPAD_INLINE AD<Base> CondExpOp( 00248 enum CompareOp cop , 00249 const AD<Base> &left , 00250 const AD<Base> &right , 00251 const AD<Base> &exp_if_true , 00252 const AD<Base> &exp_if_false ) 00253 { 00254 AD<Base> returnValue; 00255 CPPAD_ASSERT_UNKNOWN( Parameter(returnValue) ); 00256 00257 // check first case where do not need to tape 00258 if( IdenticalPar(left) & IdenticalPar(right) ) 00259 { switch( cop ) 00260 { 00261 case CompareLt: 00262 if( left.value_ < right.value_ ) 00263 returnValue = exp_if_true; 00264 else returnValue = exp_if_false; 00265 break; 00266 00267 case CompareLe: 00268 if( left.value_ <= right.value_ ) 00269 returnValue = exp_if_true; 00270 else returnValue = exp_if_false; 00271 break; 00272 00273 case CompareEq: 00274 if( left.value_ == right.value_ ) 00275 returnValue = exp_if_true; 00276 else returnValue = exp_if_false; 00277 break; 00278 00279 case CompareGe: 00280 if( left.value_ >= right.value_ ) 00281 returnValue = exp_if_true; 00282 else returnValue = exp_if_false; 00283 break; 00284 00285 case CompareGt: 00286 if( left.value_ > right.value_ ) 00287 returnValue = exp_if_true; 00288 else returnValue = exp_if_false; 00289 break; 00290 00291 default: 00292 CPPAD_ASSERT_UNKNOWN(0); 00293 returnValue = exp_if_true; 00294 } 00295 return returnValue; 00296 } 00297 00298 // must use CondExp incase Base is an AD type and recording 00299 returnValue.value_ = CondExpOp(cop, 00300 left.value_, right.value_, exp_if_true.value_, exp_if_false.value_); 00301 00302 ADTape<Base> *tape = CPPAD_NULL; 00303 if( Variable(left) ) 00304 tape = left.tape_this(); 00305 if( Variable(right) ) 00306 tape = right.tape_this(); 00307 if( Variable(exp_if_true) ) 00308 tape = exp_if_true.tape_this(); 00309 if( Variable(exp_if_false) ) 00310 tape = exp_if_false.tape_this(); 00311 00312 // add this operation to the tape 00313 if( tape != CPPAD_NULL ) 00314 tape->RecordCondExp(cop, 00315 returnValue, left, right, exp_if_true, exp_if_false); 00316 00317 return returnValue; 00318 } 00319 00320 // --- RecordCondExp(cop, returnValue, left, right, exp_if_true, exp_if_false) ----- 00321 00322 /// All these operations are done in \c Rec_, so we should move this 00323 /// routine to <tt>recorder<Base></tt>. 00324 template <class Base> 00325 void ADTape<Base>::RecordCondExp( 00326 enum CompareOp cop , 00327 AD<Base> &returnValue , 00328 const AD<Base> &left , 00329 const AD<Base> &right , 00330 const AD<Base> &exp_if_true , 00331 const AD<Base> &exp_if_false ) 00332 { size_t ind0, ind1, ind2, ind3, ind4, ind5; 00333 size_t returnValue_taddr; 00334 00335 // taddr_ of this variable 00336 CPPAD_ASSERT_UNKNOWN( NumRes(CExpOp) == 1 ); 00337 returnValue_taddr = Rec_.PutOp(CExpOp); 00338 00339 // ind[0] = cop 00340 ind0 = size_t( cop ); 00341 00342 // ind[1] = base 2 representaion of the value 00343 // [Var(left), Var(right), Var(exp_if_true), Var(exp_if_false)] 00344 ind1 = 0; 00345 00346 // Make sure returnValue is in the list of variables and set its taddr 00347 if( Parameter(returnValue) ) 00348 returnValue.make_variable(id_, returnValue_taddr ); 00349 else returnValue.taddr_ = returnValue_taddr; 00350 00351 // ind[2] = left address 00352 if( Parameter(left) ) 00353 ind2 = Rec_.PutPar(left.value_); 00354 else 00355 { ind1 += 1; 00356 ind2 = left.taddr_; 00357 } 00358 00359 // ind[3] = right address 00360 if( Parameter(right) ) 00361 ind3 = Rec_.PutPar(right.value_); 00362 else 00363 { ind1 += 2; 00364 ind3 = right.taddr_; 00365 } 00366 00367 // ind[4] = exp_if_true address 00368 if( Parameter(exp_if_true) ) 00369 ind4 = Rec_.PutPar(exp_if_true.value_); 00370 else 00371 { ind1 += 4; 00372 ind4 = exp_if_true.taddr_; 00373 } 00374 00375 // ind[5] = exp_if_false address 00376 if( Parameter(exp_if_false) ) 00377 ind5 = Rec_.PutPar(exp_if_false.value_); 00378 else 00379 { ind1 += 8; 00380 ind5 = exp_if_false.taddr_; 00381 } 00382 00383 CPPAD_ASSERT_UNKNOWN( NumArg(CExpOp) == 6 ); 00384 CPPAD_ASSERT_UNKNOWN( ind1 > 0 ); 00385 Rec_.PutArg(ind0, ind1, ind2, ind3, ind4, ind5); 00386 00387 // check that returnValue is a dependent variable 00388 CPPAD_ASSERT_UNKNOWN( Variable(returnValue) ); 00389 } 00390 00391 // ------------ CondExpOp(left, right, exp_if_true, exp_if_false) ---------------- 00392 00393 # define CPPAD_COND_EXP(Name) \ 00394 template <class Base> \ 00395 CPPAD_INLINE AD<Base> CondExp##Name( \ 00396 const AD<Base> &left , \ 00397 const AD<Base> &right , \ 00398 const AD<Base> &exp_if_true , \ 00399 const AD<Base> &exp_if_false ) \ 00400 { \ 00401 return CondExpOp(Compare##Name, \ 00402 left, right, exp_if_true, exp_if_false); \ 00403 } 00404 00405 // AD<Base> 00406 CPPAD_COND_EXP(Lt) 00407 CPPAD_COND_EXP(Le) 00408 CPPAD_COND_EXP(Eq) 00409 CPPAD_COND_EXP(Ge) 00410 CPPAD_COND_EXP(Gt) 00411 template <class Base> 00412 CPPAD_INLINE AD<Base> CondExp( 00413 const AD<Base> &flag , 00414 const AD<Base> &exp_if_true , 00415 const AD<Base> &exp_if_false ) 00416 { 00417 return CondExpOp(CompareGt, flag, AD<Base>(0), exp_if_true, exp_if_false); 00418 } 00419 00420 # undef CPPAD_COND_EXP 00421 # define CPPAD_COND_EXP(Name, Op, Type) \ 00422 inline Type CondExp##Name( \ 00423 const Type &left , \ 00424 const Type &right , \ 00425 const Type &exp_if_true , \ 00426 const Type &exp_if_false ) \ 00427 { Type returnValue; \ 00428 if( left Op right ) \ 00429 returnValue = exp_if_true; \ 00430 else returnValue = exp_if_false; \ 00431 return returnValue; \ 00432 } 00433 00434 // float 00435 CPPAD_COND_EXP(Lt, <, float) 00436 CPPAD_COND_EXP(Le, <=, float) 00437 CPPAD_COND_EXP(Eq, ==, float) 00438 CPPAD_COND_EXP(Ge, >=, float) 00439 CPPAD_COND_EXP(Gt, >, float) 00440 inline float CondExp( 00441 const float &flag , 00442 const float &exp_if_true , 00443 const float &exp_if_false ) 00444 { 00445 return CondExpGt(flag, float(0), exp_if_true, exp_if_false); 00446 } 00447 00448 // double 00449 CPPAD_COND_EXP(Lt, <, double) 00450 CPPAD_COND_EXP(Le, <=, double) 00451 CPPAD_COND_EXP(Eq, ==, double) 00452 CPPAD_COND_EXP(Ge, >=, double) 00453 CPPAD_COND_EXP(Gt, >, double) 00454 inline double CondExp( 00455 const double &flag , 00456 const double &exp_if_true , 00457 const double &exp_if_false ) 00458 { 00459 return CondExpGt(flag, 0., exp_if_true, exp_if_false); 00460 } 00461 00462 # undef CPPAD_COND_EXP 00463 00464 } // END CppAD namespace 00465 00466 # endif