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