00001 # ifndef CPPAD_COND_EXP_INCLUDED
00002 # define CPPAD_COND_EXP_INCLUDED
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 
00053 
00054 
00055 
00056 
00057 
00058 
00059 
00060 
00061 
00062 
00063 
00064 
00065 
00066 
00067 
00068 
00069 
00070 
00071 
00072 
00073 
00074 
00075 
00076 
00077 
00078 
00079 
00080 
00081 
00082 
00083 
00084 
00085 
00086 
00087 
00088 
00089 
00090 
00091 
00092 
00093 
00094 
00095 
00096 
00097 
00098 
00099 
00100 
00101 
00102 
00103 
00104 
00105 
00106 
00107 
00108 
00109 
00110 
00111 
00112 
00113 
00114 
00115 
00116 
00117 
00118 
00119 
00120 
00121 
00122 
00123 
00124 
00125 
00126 
00127 
00128 
00129 
00130 
00131 
00132 
00133 
00134 
00135 
00136 
00137 
00138 
00139 
00140 
00141 
00142 
00143 
00144 
00145 
00146 
00147 
00148 
00149 
00150 
00151 
00152 
00153 
00154 
00155 
00156 
00157 
00158 
00159 
00160 
00161 
00162 
00163 
00164 
00165 
00166 
00167 
00168 
00169 
00170 
00171 
00172 
00173 
00174 
00175 
00176 namespace CppAD {
00177 
00178 
00179 
00180 
00181 template <class CompareType, class ResultType>
00182 inline ResultType CondExpTemplate( 
00183         enum  CompareOp            cop ,
00184         const CompareType        &left ,
00185         const CompareType       &right , 
00186         const ResultType     &trueCase , 
00187         const ResultType    &falseCase )
00188 {       ResultType returnValue;
00189         switch( cop )
00190         {
00191                 case CompareLt:
00192                 if( left < right )
00193                         returnValue = trueCase;
00194                 else    returnValue = falseCase;
00195                 break;
00196 
00197                 case CompareLe:
00198                 if( left <= right )
00199                         returnValue = trueCase;
00200                 else    returnValue = falseCase;
00201                 break;
00202 
00203                 case CompareEq:
00204                 if( left == right )
00205                         returnValue = trueCase;
00206                 else    returnValue = falseCase;
00207                 break;
00208 
00209                 case CompareGe:
00210                 if( left >= right )
00211                         returnValue = trueCase;
00212                 else    returnValue = falseCase;
00213                 break;
00214 
00215                 case CompareGt:
00216                 if( left > right )
00217                         returnValue = trueCase;
00218                 else    returnValue = falseCase;
00219                 break;
00220 
00221                 default:
00222                 CPPAD_ASSERT_UNKNOWN(0);
00223                 returnValue = trueCase;
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  &trueCase , 
00233         const float &falseCase )
00234 {       return CondExpTemplate(cop, left, right, trueCase, falseCase);
00235 }
00236 
00237 inline double CondExpOp( 
00238         enum CompareOp     cop ,
00239         const double      &left ,
00240         const double     &right , 
00241         const double  &trueCase , 
00242         const double &falseCase )
00243 {       return CondExpTemplate(cop, left, right, trueCase, falseCase);
00244 }
00245 
00246 template <class Base>
00247 inline AD<Base> CondExpOp(
00248         enum  CompareOp cop       ,
00249         const AD<Base> &left      , 
00250         const AD<Base> &right     , 
00251         const AD<Base> &trueCase  , 
00252         const AD<Base> &falseCase )
00253 {
00254         AD<Base> returnValue;
00255         CPPAD_ASSERT_UNKNOWN( Parameter(returnValue) );
00256 
00257         
00258         if( IdenticalPar(left) & IdenticalPar(right) )
00259         {       switch( cop )
00260                 {
00261                         case CompareLt:
00262                         if( left.value_ < right.value_ )
00263                                 returnValue = trueCase;
00264                         else    returnValue = falseCase;
00265                         break;
00266 
00267                         case CompareLe:
00268                         if( left.value_ <= right.value_ )
00269                                 returnValue = trueCase;
00270                         else    returnValue = falseCase;
00271                         break;
00272 
00273                         case CompareEq:
00274                         if( left.value_ == right.value_ )
00275                                 returnValue = trueCase;
00276                         else    returnValue = falseCase;
00277                         break;
00278 
00279                         case CompareGe:
00280                         if( left.value_ >= right.value_ )
00281                                 returnValue = trueCase;
00282                         else    returnValue = falseCase;
00283                         break;
00284 
00285                         case CompareGt:
00286                         if( left.value_ > right.value_ )
00287                                 returnValue = trueCase;
00288                         else    returnValue = falseCase;
00289                         break;
00290 
00291                         default:
00292                         CPPAD_ASSERT_UNKNOWN(0);
00293                         returnValue = trueCase;
00294                 }
00295                 return returnValue;
00296         }
00297 
00298         
00299         returnValue.value_ = CondExpOp(cop, 
00300                 left.value_, right.value_, trueCase.value_, falseCase.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(trueCase) )
00308                 tape = trueCase.tape_this();
00309         if( Variable(falseCase) )
00310                 tape = falseCase.tape_this();
00311 
00312         
00313         if( tape != CPPAD_NULL ) 
00314                 tape->RecordCondExp(cop, 
00315                         returnValue, left, right, trueCase, falseCase);
00316 
00317         return returnValue;
00318 }
00319 
00320 
00321 
00322 template <class Base>
00323 void ADTape<Base>::RecordCondExp(
00324         enum CompareOp  cop         ,
00325         AD<Base>       &returnValue ,
00326         const AD<Base> &left        ,
00327         const AD<Base> &right       ,
00328         const AD<Base> &trueCase    ,
00329         const AD<Base> &falseCase   )
00330 {       size_t   ind0, ind1, ind2, ind3, ind4, ind5;
00331         size_t   returnValue_taddr;
00332 
00333         
00334         returnValue_taddr = Rec.PutOp(CExpOp);
00335 
00336         
00337         ind0 = size_t( cop );
00338 
00339         
00340         
00341         ind1 = 0;
00342 
00343         
00344         if( Parameter(returnValue) )
00345                 returnValue.make_variable(id_, returnValue_taddr );
00346         else    returnValue.taddr_ = returnValue_taddr;
00347 
00348         
00349         if( Parameter(left) )
00350                 ind2 = Rec.PutPar(left.value_);
00351         else
00352         {       ind1 += 1;
00353                 ind2 = left.taddr_;     
00354         }
00355 
00356         
00357         if( Parameter(right) )
00358                 ind3 = Rec.PutPar(right.value_);
00359         else
00360         {       ind1 += 2;
00361                 ind3 = right.taddr_;    
00362         }
00363 
00364         
00365         if( Parameter(trueCase) )
00366                 ind4 = Rec.PutPar(trueCase.value_);
00367         else
00368         {       ind1 += 4;
00369                 ind4 = trueCase.taddr_; 
00370         }
00371 
00372         
00373         if( Parameter(falseCase) )
00374                 ind5 = Rec.PutPar(falseCase.value_);
00375         else
00376         {       ind1 += 8;
00377                 ind5 = falseCase.taddr_;        
00378         }
00379 
00380         CPPAD_ASSERT_UNKNOWN( NumInd(CExpOp) == 6 );
00381         CPPAD_ASSERT_UNKNOWN( ind1 > 0 );
00382         Rec.PutInd(ind0, ind1, ind2, ind3, ind4, ind5);
00383 
00384         
00385         CPPAD_ASSERT_UNKNOWN( Variable(returnValue) );
00386 }
00387 
00388 
00389 
00390 # define CPPAD_COND_EXP(Name)                                              \
00391         template <class Base>                                              \
00392         inline AD<Base> CondExp##Name(                                     \
00393                 const AD<Base> &left      ,                                \
00394                 const AD<Base> &right     ,                                \
00395                 const AD<Base> &trueCase  ,                                \
00396                 const AD<Base> &falseCase )                                \
00397         {                                                                  \
00398                 return CondExpOp(Compare##Name,                            \
00399                         left, right, trueCase, falseCase);                 \
00400         }
00401 
00402 
00403 CPPAD_COND_EXP(Lt)
00404 CPPAD_COND_EXP(Le)
00405 CPPAD_COND_EXP(Eq)
00406 CPPAD_COND_EXP(Ge)
00407 CPPAD_COND_EXP(Gt)
00408 template <class Base>
00409 inline AD<Base> CondExp(
00410         const AD<Base> &flag      , 
00411         const AD<Base> &trueCase  ,
00412         const AD<Base> &falseCase )
00413 {       
00414         return CondExpOp(CompareGt, flag, AD<Base>(0), trueCase, falseCase);
00415 }
00416 
00417 # undef CPPAD_COND_EXP
00418 # define CPPAD_COND_EXP(Name, Op, Type)                             \
00419         inline Type CondExp##Name(                                  \
00420                 const Type &left      ,                             \
00421                 const Type &right     ,                             \
00422                 const Type &trueCase  ,                             \
00423                 const Type &falseCase )                             \
00424         {       Type returnValue;                                   \
00425                 if( left Op right )                                 \
00426                         returnValue = trueCase;                     \
00427                 else    returnValue = falseCase;                    \
00428                 return returnValue;                                 \
00429         }
00430 
00431 
00432 CPPAD_COND_EXP(Lt,  <, float)
00433 CPPAD_COND_EXP(Le, <=, float)
00434 CPPAD_COND_EXP(Eq, ==, float)
00435 CPPAD_COND_EXP(Ge, >=, float)
00436 CPPAD_COND_EXP(Gt,  >, float)
00437 inline float CondExp(
00438         const float &flag      , 
00439         const float &trueCase  ,
00440         const float &falseCase )
00441 {       
00442         return CondExpGt(flag, float(0), trueCase, falseCase);
00443 }
00444 
00445 
00446 CPPAD_COND_EXP(Lt,  <, double)
00447 CPPAD_COND_EXP(Le, <=, double)
00448 CPPAD_COND_EXP(Eq, ==, double)
00449 CPPAD_COND_EXP(Ge, >=, double)
00450 CPPAD_COND_EXP(Gt,  >, double)
00451 inline double CondExp(
00452         const double &flag      , 
00453         const double &trueCase  ,
00454         const double &falseCase )
00455 {       
00456         return CondExpGt(flag, 0., trueCase, falseCase);
00457 }
00458 
00459 # undef CPPAD_COND_EXP
00460 
00461 } 
00462 
00463 # endif