CppAD: A C++ Algorithmic Differentiation Package  20130918
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-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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines