CppAD: A C++ Algorithmic Differentiation Package 20110419
cond_exp.hpp
Go to the documentation of this file.
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