CppAD: A C++ Algorithmic Differentiation Package
20130102
|
00001 /* $Id$ */ 00002 # ifndef CPPAD_COND_EXP_INCLUDED 00003 # define CPPAD_COND_EXP_INCLUDED 00004 00005 /* -------------------------------------------------------------------------- 00006 CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 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 00122 $head CondExp$$ 00123 Previous versions of CppAD used 00124 $codei% 00125 CondExp(%flag%, %if_true%, %if_false%) 00126 %$$ 00127 for the same meaning as 00128 $codei% 00129 CondExpGt(%flag%, %Type%(0), %if_true%, %if_false%) 00130 %$$ 00131 Use of $code CondExp$$ is deprecated, but continues to be supported. 00132 00133 $head Operation Sequence$$ 00134 This is an AD of $icode Base$$ 00135 $cref/atomic operation/glossary/Operation/Atomic/$$ 00136 and hence is part of the current 00137 AD of $icode Base$$ 00138 $cref/operation sequence/glossary/Operation/Sequence/$$. 00139 00140 00141 $head Example$$ 00142 00143 $head Test$$ 00144 $children% 00145 example/cond_exp.cpp 00146 %$$ 00147 The file 00148 $cref cond_exp.cpp$$ 00149 contains an example and test of this function. 00150 It returns true if it succeeds and false otherwise. 00151 00152 $head Atan2$$ 00153 The following implementation of the 00154 AD $cref atan2$$ function is a more complex 00155 example of using conditional expressions: 00156 $code 00157 $verbatim%cppad/local/atan2.hpp%0%BEGIN CondExp%// END CondExp%$$ 00158 $$ 00159 00160 00161 $end 00162 ------------------------------------------------------------------------------- 00163 */ 00164 // BEGIN CppAD namespace 00165 namespace CppAD { 00166 00167 template <class Base> 00168 CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION 00169 AD<Base> CondExpOp( 00170 enum CompareOp cop , 00171 const AD<Base> &left , 00172 const AD<Base> &right , 00173 const AD<Base> &if_true , 00174 const AD<Base> &if_false ) 00175 { 00176 AD<Base> returnValue; 00177 CPPAD_ASSERT_UNKNOWN( Parameter(returnValue) ); 00178 00179 // check first case where do not need to tape 00180 if( IdenticalPar(left) & IdenticalPar(right) ) 00181 { switch( cop ) 00182 { 00183 case CompareLt: 00184 if( left.value_ < right.value_ ) 00185 returnValue = if_true; 00186 else returnValue = if_false; 00187 break; 00188 00189 case CompareLe: 00190 if( left.value_ <= right.value_ ) 00191 returnValue = if_true; 00192 else returnValue = if_false; 00193 break; 00194 00195 case CompareEq: 00196 if( left.value_ == right.value_ ) 00197 returnValue = if_true; 00198 else returnValue = if_false; 00199 break; 00200 00201 case CompareGe: 00202 if( left.value_ >= right.value_ ) 00203 returnValue = if_true; 00204 else returnValue = if_false; 00205 break; 00206 00207 case CompareGt: 00208 if( left.value_ > right.value_ ) 00209 returnValue = if_true; 00210 else returnValue = if_false; 00211 break; 00212 00213 default: 00214 CPPAD_ASSERT_UNKNOWN(0); 00215 returnValue = if_true; 00216 } 00217 return returnValue; 00218 } 00219 00220 // must use CondExp incase Base is an AD type and recording 00221 returnValue.value_ = CondExpOp(cop, 00222 left.value_, right.value_, if_true.value_, if_false.value_); 00223 00224 ADTape<Base> *tape = CPPAD_NULL; 00225 if( Variable(left) ) 00226 tape = left.tape_this(); 00227 if( Variable(right) ) 00228 tape = right.tape_this(); 00229 if( Variable(if_true) ) 00230 tape = if_true.tape_this(); 00231 if( Variable(if_false) ) 00232 tape = if_false.tape_this(); 00233 00234 // add this operation to the tape 00235 if( tape != CPPAD_NULL ) 00236 tape->RecordCondExp(cop, 00237 returnValue, left, right, if_true, if_false); 00238 00239 return returnValue; 00240 } 00241 00242 // --- RecordCondExp(cop, returnValue, left, right, if_true, if_false) ----- 00243 00244 /// All these operations are done in \c Rec_, so we should move this 00245 /// routine to <tt>recorder<Base></tt>. 00246 template <class Base> 00247 void ADTape<Base>::RecordCondExp( 00248 enum CompareOp cop , 00249 AD<Base> &returnValue , 00250 const AD<Base> &left , 00251 const AD<Base> &right , 00252 const AD<Base> &if_true , 00253 const AD<Base> &if_false ) 00254 { size_t ind0, ind1, ind2, ind3, ind4, ind5; 00255 size_t returnValue_taddr; 00256 00257 // taddr_ of this variable 00258 CPPAD_ASSERT_UNKNOWN( NumRes(CExpOp) == 1 ); 00259 returnValue_taddr = Rec_.PutOp(CExpOp); 00260 00261 // ind[0] = cop 00262 ind0 = addr_t( cop ); 00263 00264 // ind[1] = base 2 representaion of the value 00265 // [Var(left), Var(right), Var(if_true), Var(if_false)] 00266 ind1 = 0; 00267 00268 // Make sure returnValue is in the list of variables and set its taddr 00269 if( Parameter(returnValue) ) 00270 returnValue.make_variable(id_, returnValue_taddr ); 00271 else returnValue.taddr_ = returnValue_taddr; 00272 00273 // ind[2] = left address 00274 if( Parameter(left) ) 00275 ind2 = Rec_.PutPar(left.value_); 00276 else 00277 { ind1 += 1; 00278 ind2 = left.taddr_; 00279 } 00280 00281 // ind[3] = right address 00282 if( Parameter(right) ) 00283 ind3 = Rec_.PutPar(right.value_); 00284 else 00285 { ind1 += 2; 00286 ind3 = right.taddr_; 00287 } 00288 00289 // ind[4] = if_true address 00290 if( Parameter(if_true) ) 00291 ind4 = Rec_.PutPar(if_true.value_); 00292 else 00293 { ind1 += 4; 00294 ind4 = if_true.taddr_; 00295 } 00296 00297 // ind[5] = if_false address 00298 if( Parameter(if_false) ) 00299 ind5 = Rec_.PutPar(if_false.value_); 00300 else 00301 { ind1 += 8; 00302 ind5 = if_false.taddr_; 00303 } 00304 00305 CPPAD_ASSERT_UNKNOWN( NumArg(CExpOp) == 6 ); 00306 CPPAD_ASSERT_UNKNOWN( ind1 > 0 ); 00307 Rec_.PutArg(ind0, ind1, ind2, ind3, ind4, ind5); 00308 00309 // check that returnValue is a dependent variable 00310 CPPAD_ASSERT_UNKNOWN( Variable(returnValue) ); 00311 } 00312 00313 // ------------ CondExpOp(left, right, if_true, if_false) ---------------- 00314 00315 # define CPPAD_COND_EXP(Name) \ 00316 template <class Base> \ 00317 CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION \ 00318 AD<Base> CondExp##Name( \ 00319 const AD<Base> &left , \ 00320 const AD<Base> &right , \ 00321 const AD<Base> &if_true , \ 00322 const AD<Base> &if_false ) \ 00323 { \ 00324 return CondExpOp(Compare##Name, \ 00325 left, right, if_true, if_false); \ 00326 } 00327 00328 // AD<Base> 00329 CPPAD_COND_EXP(Lt) 00330 CPPAD_COND_EXP(Le) 00331 CPPAD_COND_EXP(Eq) 00332 CPPAD_COND_EXP(Ge) 00333 CPPAD_COND_EXP(Gt) 00334 template <class Base> 00335 CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION 00336 AD<Base> CondExp( 00337 const AD<Base> &flag , 00338 const AD<Base> &if_true , 00339 const AD<Base> &if_false ) 00340 { 00341 return CondExpOp(CompareGt, flag, AD<Base>(0), if_true, if_false); 00342 } 00343 00344 # undef CPPAD_COND_EXP 00345 } // END CppAD namespace 00346 00347 # endif