CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION AD<Base> CondExpOp( enum CompareOp cop , const AD<Base> &left , const AD<Base> &right , const AD<Base> &if_true , const AD<Base> &if_false ) { AD<Base> returnValue; CPPAD_ASSERT_UNKNOWN( Parameter(returnValue) ); // check first case where do not need to tape if( IdenticalPar(left) & IdenticalPar(right) ) { switch( cop ) { case CompareLt: if( left.value_ < right.value_ ) returnValue = if_true; else returnValue = if_false; break; case CompareLe: if( left.value_ <= right.value_ ) returnValue = if_true; else returnValue = if_false; break; case CompareEq: if( left.value_ == right.value_ ) returnValue = if_true; else returnValue = if_false; break; case CompareGe: if( left.value_ >= right.value_ ) returnValue = if_true; else returnValue = if_false; break; case CompareGt: if( left.value_ > right.value_ ) returnValue = if_true; else returnValue = if_false; break; default: CPPAD_ASSERT_UNKNOWN(0); returnValue = if_true; } return returnValue; } // must use CondExp incase Base is an AD type and recording returnValue.value_ = CondExpOp(cop, left.value_, right.value_, if_true.value_, if_false.value_); ADTape<Base> *tape = CPPAD_NULL; if( Variable(left) ) tape = left.tape_this(); if( Variable(right) ) tape = right.tape_this(); if( Variable(if_true) ) tape = if_true.tape_this(); if( Variable(if_false) ) tape = if_false.tape_this(); // add this operation to the tape if( tape != CPPAD_NULL ) tape->RecordCondExp(cop, returnValue, left, right, if_true, if_false); return returnValue; }
CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION bool IdenticalPar(const AD<Base> &x) { return Parameter(x) && IdenticalPar(x.value_); }
inline void forward_cskip_op_0( size_t i_z , const addr_t* arg , size_t num_par , const Base* parameter , size_t cap_order , Base* taylor , bool* cskip_op ) { CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < size_t(CompareNe) ); CPPAD_ASSERT_UNKNOWN( arg[1] != 0 ); Base left, right; if( arg[1] & 1 ) { // If varialbe arg[2] <= i_z, it has already been computed, // but it will be skipped for higher orders. left = taylor[ arg[2] * cap_order + 0 ]; } else { CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < num_par ); left = parameter[ arg[2] ]; } if( arg[1] & 2 ) { // If varialbe arg[3] <= i_z, it has already been computed, // but it will be skipped for higher orders. right = taylor[ arg[3] * cap_order + 0 ]; } else { CPPAD_ASSERT_UNKNOWN( size_t(arg[3]) < num_par ); right = parameter[ arg[3] ]; } bool ok_to_skip = IdenticalPar(left) & IdenticalPar(right); if( ! ok_to_skip ) return; // initialize to avoid compiler warning bool true_case = false; Base diff = left - right; switch( CompareOp( arg[0] ) ) { case CompareLt: true_case = LessThanZero(diff); break; case CompareLe: true_case = LessThanOrZero(diff); break; case CompareEq: true_case = IdenticalZero(diff); break; case CompareGe: true_case = GreaterThanOrZero(diff); break; case CompareGt: true_case = GreaterThanZero(diff); break; case CompareNe: true_case = ! IdenticalZero(diff); break; default: CPPAD_ASSERT_UNKNOWN(false); } if( true_case ) { for(size_t i = 0; i < size_t(arg[4]); i++) cskip_op[ arg[6+i] ] = true; } else { for(size_t i = 0; i < size_t(arg[5]); i++) cskip_op[ arg[6+arg[4]+i] ] = true; } return; }