/*! Fetch the next operator during a reverse sweep. Use reverse_start to initialize to reverse play back. The first call to reverse_next (after reverse_start) will give the last operator in the recording. We use the notation reverse_routine to denote the set reverse_start, reverse_next, reverse_csum, reverse_cskip. \param op [in,out] The input value of \c op must be its output value from the previous call to a reverse_routine. Its output value is the next operator in the recording (in reverse order). The last operator sets op equal to EndOp. \param op_arg [in,out] The input value of \c op_arg must be its output value from the previous call to a reverse_routine. Its output value is the beginning of the vector of argument indices for this operation. The last operator sets op_arg equal to the beginning of the argument indices for the entire recording. For speed, \c reverse_next does not check for the special cases <tt>op == CSumOp</tt> or <tt>op == CSkipOp</tt>. In these cases, the other return values from \c reverse_next must be corrected by a call to \c reverse_csum or \c reverse_cskip respectively. \param op_index [in,out] The input value of \c op_index must be its output value from the previous call to a reverse_routine. Its output value is the index of this operator in the recording. Thus the output value following the previous call to reverse_start is equal to the number of variables in the recording minus one. In addition, the output value decreases by one with each call to reverse_next. The last operator sets op_index equal to 0. \param var_index [in,out] The input value of \c var_index must be its output value from the previous call to a reverse_routine. Its output value is the index of the primary (last) result corresponding to the operator op. The last operator sets var_index equal to 0 (corresponding to BeginOp at beginning of operation sequence). */ void reverse_next( OpCode& op, const addr_t*& op_arg, size_t& op_index, size_t& var_index) { using CppAD::NumRes; using CppAD::NumArg; CPPAD_ASSERT_UNKNOWN( op_ == op ); CPPAD_ASSERT_UNKNOWN( op_arg == op_arg_ ); CPPAD_ASSERT_UNKNOWN( op_index == op_index_ ); CPPAD_ASSERT_UNKNOWN( var_index == var_index_ ); // index of the last result for the next operator CPPAD_ASSERT_UNKNOWN( var_index_ >= NumRes(op_) ); var_index = var_index_ -= NumRes(op_); // next operator CPPAD_ASSERT_UNKNOWN( op_index_ > 0 ); op_index = --op_index_; // index op = op_ = OpCode( op_rec_[ op_index_ ] ); // value // first argument for next operator op_arg = op_arg_ -= NumArg(op); CPPAD_ASSERT_UNKNOWN( op_arg_rec_.data() <= op_arg_ ); CPPAD_ASSERT_UNKNOWN( op_arg_ + NumArg(op) <= op_arg_rec_.data() + op_arg_rec_.size() ); }
/*! Correct \c forward_next return values when <tt>op == CSkipOp</tt>. \param op [in] The input value of op must be the return value from the previous call to \c forward_next and must be \c CSkipOp. It is not modified. \param op_arg [in,out] The input value of \c op_arg must be the return value from the previous call to \c forward_next. Its output value is the beginning of the vector of argument indices for the next operation. \param op_index [in] The input value of \c op_index does must be the return value from the previous call to \c forward_next. Its is not modified. \param var_index [in,out] The input value of \c var_index must be the return value from the previous call to \c forward_next. It is not modified. */ void forward_cskip( OpCode& op, const addr_t*& op_arg, size_t& op_index, size_t& var_index) { using CppAD::NumRes; using CppAD::NumArg; CPPAD_ASSERT_UNKNOWN( op_ == op ); CPPAD_ASSERT_UNKNOWN( op_arg == op_arg_ ); CPPAD_ASSERT_UNKNOWN( op_index == op_index_ ); CPPAD_ASSERT_UNKNOWN( var_index == var_index_ ); CPPAD_ASSERT_UNKNOWN( op == CSkipOp ); CPPAD_ASSERT_UNKNOWN( NumArg(CSkipOp) == 0 ); CPPAD_ASSERT_UNKNOWN( op_arg[4] + op_arg[5] == op_arg[ 6 + op_arg[4] + op_arg[5] ] ); /* The only thing that really needs fixing is op_arg_. Actual number of arugments for this operator is 7 + op_arg[4] + op_arg[5] We must change op_arg_ so that when you add NumArg(CSkipOp) you get first argument for next operator in sequence. */ op_arg = op_arg_ += 7 + op_arg[4] + op_arg[5]; CPPAD_ASSERT_UNKNOWN( op_arg_rec_.data() <= op_arg_ ); CPPAD_ASSERT_UNKNOWN( op_arg_ + NumArg(op) <= op_arg_rec_.data() + op_arg_rec_.size() ); CPPAD_ASSERT_UNKNOWN( var_index_ < num_var_rec_ ); }
/*! Fetch the next operator during a forward sweep. Use forward_start to initialize to the first operator; i.e., the BeginOp at the beginning of the recording. We use the notation forward_routine to denote the set forward_start, forward_next, forward_csum, forward_cskip. \param op [in,out] The input value of \c op must be its output value from the previous call to a forward_routine. Its output value is the next operator in the recording. For speed, \c forward_next does not check for the special cases where <tt>op == CSumOp</tt> or <tt>op == CSkipOp</tt>. In these cases, the other return values from \c forward_next must be corrected by a call to \c forward_csum or \c forward_cskip respectively. \param op_arg [in,out] The input value of \c op_arg must be its output value form the previous call to a forward routine. Its output value is the beginning of the vector of argument indices for this operation. \param op_index [in,out] The input value of \c op_index must be its output value form the previous call to a forward routine. Its output value is the index of the next operator in the recording. Thus the ouput value following the previous call to forward_start is one. In addition, the output value increases by one with each call to forward_next. \param var_index [in,out] The input value of \c var_index must be its output value form the previous call to a forward routine. Its output value is the index of the primary (last) result corresponding to the operator op. */ void forward_next( OpCode& op, const addr_t*& op_arg, size_t& op_index, size_t& var_index) { using CppAD::NumRes; using CppAD::NumArg; CPPAD_ASSERT_UNKNOWN( op_ == op ); CPPAD_ASSERT_UNKNOWN( op_arg == op_arg_ ); CPPAD_ASSERT_UNKNOWN( op_index == op_index_ ); CPPAD_ASSERT_UNKNOWN( var_index == var_index_ ); // index for the next operator op_index = ++op_index_; // first argument for next operator op_arg = op_arg_ += NumArg(op_); // next operator op = op_ = OpCode( op_rec_[ op_index_ ] ); // index for last result for next operator var_index = var_index_ += NumRes(op); CPPAD_ASSERT_UNKNOWN( op_arg_rec_.data() <= op_arg_ ); CPPAD_ASSERT_UNKNOWN( op_arg_ + NumArg(op) <= op_arg_rec_.data() + op_arg_rec_.size() ); CPPAD_ASSERT_UNKNOWN( var_index_ < num_var_rec_ ); }
void reverse_cskip( OpCode& op, const addr_t*& op_arg, size_t& op_index, size_t& var_index) { using CppAD::NumRes; using CppAD::NumArg; CPPAD_ASSERT_UNKNOWN( op_ == op ); CPPAD_ASSERT_UNKNOWN( op_arg == op_arg_ ); CPPAD_ASSERT_UNKNOWN( op_index == op_index_ ); CPPAD_ASSERT_UNKNOWN( var_index == var_index_ ); CPPAD_ASSERT_UNKNOWN( op == CSkipOp ); CPPAD_ASSERT_UNKNOWN( NumArg(CSkipOp) == 0 ); /* The variables that need fixing are op_arg_ and op_arg. Currently, op_arg points first arugment for the previous operator. */ --op_arg; op_arg = op_arg_ -= (op_arg[0] + 4); CPPAD_ASSERT_UNKNOWN( op_arg[1] + op_arg[2] == op_arg[ 3 + op_arg[1] + op_arg[2] ] ); CPPAD_ASSERT_UNKNOWN( op_index_ < op_rec_.size() ); CPPAD_ASSERT_UNKNOWN( op_arg_rec_.data() <= op_arg_ ); CPPAD_ASSERT_UNKNOWN( var_index_ < num_var_rec_ ); }
void reverse_csum( OpCode& op, const addr_t*& op_arg, size_t& op_index, size_t& var_index) { using CppAD::NumRes; using CppAD::NumArg; CPPAD_ASSERT_UNKNOWN( op_ == op ); CPPAD_ASSERT_UNKNOWN( op_arg == op_arg_ ); CPPAD_ASSERT_UNKNOWN( op_index == op_index_ ); CPPAD_ASSERT_UNKNOWN( var_index == var_index_ ); CPPAD_ASSERT_UNKNOWN( op == CSumOp ); CPPAD_ASSERT_UNKNOWN( NumArg(CSumOp) == 0 ); /* The variables that need fixing are op_arg_ and op_arg. Currently, op_arg points to the last argument for the previous operator. */ // last argument for this csum operation --op_arg; // first argument for this csum operation op_arg = op_arg_ -= (op_arg[0] + 4); // now op_arg points to the first argument for this csum operator CPPAD_ASSERT_UNKNOWN( op_arg[0] + op_arg[1] == op_arg[ 3 + op_arg[0] + op_arg[1] ] ); CPPAD_ASSERT_UNKNOWN( op_index_ < op_rec_.size() ); CPPAD_ASSERT_UNKNOWN( op_arg_rec_.data() <= op_arg_ ); CPPAD_ASSERT_UNKNOWN( var_index_ < num_var_rec_ ); }
void next_reverse( OpCode& op, const addr_t*& op_arg, size_t& op_index, size_t& var_index) { using CppAD::NumRes; using CppAD::NumArg; // index of the last result for the next operator CPPAD_ASSERT_UNKNOWN( var_index_ >= NumRes(op_) ); var_index = var_index_ -= NumRes(op_); // next operator CPPAD_ASSERT_UNKNOWN( op_index_ > 0 ); op_index = --op_index_; // index op = op_ = OpCode( rec_op_[ op_index_ ] ); // value // first argument for next operator CPPAD_ASSERT_UNKNOWN( op_arg_ >= NumArg(op) ); op_arg_ -= NumArg(op); // index op_arg = op_arg_ + rec_op_arg_.data(); // pointer }
void reverse_csum( OpCode& op, const addr_t*& op_arg, size_t& op_index, size_t& var_index) { using CppAD::NumRes; using CppAD::NumArg; CPPAD_ASSERT_UNKNOWN( op == CSumOp ); CPPAD_ASSERT_UNKNOWN( NumArg(CSumOp) == 0 ); /* The things needs fixing are op_arg_ and op_arg. Currently, op_arg points first arugment for the previous operator. */ --op_arg; op_arg_ -= (op_arg[0] + 4); op_arg = op_arg_ + rec_op_arg_.data(); CPPAD_ASSERT_UNKNOWN( op_arg[0] + op_arg[1] == op_arg[ 3 + op_arg[0] + op_arg[1] ] ); CPPAD_ASSERT_UNKNOWN( op_index_ < rec_op_.size() ); CPPAD_ASSERT_UNKNOWN( op_arg_ + NumArg(op) <= rec_op_arg_.size() ); CPPAD_ASSERT_UNKNOWN( var_index_ < num_rec_var_ ); }
/*! Correct \c next_forward return values when <tt>op == CSumOp</tt>. \param op The input value of op must be the return value from the previous call to \c next_forward and must be \c CSumOp. \param op_arg The input value of *op_arg must be the return value from the previous call to \c next_forward. Its output value is the beginning of the vector of argument indices for this operation. \param op_index The input value of op_index does must be the return value from the previous call to \c next_forward. Its output value is the index of this operator in the recording. \param var_index The input value of var_index must be the return value from the previous call to \c next_forward. Its output value is the index of the primary (last) result corresponding to this. */ void forward_csum( OpCode& op, const addr_t*& op_arg, size_t& op_index, size_t& var_index) { using CppAD::NumRes; using CppAD::NumArg; CPPAD_ASSERT_UNKNOWN( op == CSumOp ); CPPAD_ASSERT_UNKNOWN( NumArg(CSumOp) == 0 ); CPPAD_ASSERT_UNKNOWN( op_arg[0] + op_arg[1] == op_arg[ 3 + op_arg[0] + op_arg[1] ] ); /* The only thing that really needs fixing is op_arg_. Actual number of arugments for this operator is op_arg[0] + op_arg[1] + 4. We must change op_arg_ so that when you add NumArg(CSumOp) you get first argument for next operator in sequence. */ op_arg_ += op_arg[0] + op_arg[1] + 4; CPPAD_ASSERT_UNKNOWN( op_arg_ + NumArg(op) <= rec_op_arg_.size() ); CPPAD_ASSERT_UNKNOWN( var_index_ < num_rec_var_ ); }
void next_forward( OpCode& op, const addr_t*& op_arg, size_t& op_index, size_t& var_index) { using CppAD::NumRes; using CppAD::NumArg; // index for the next operator op_index = ++op_index_; // first argument for next operator op_arg_ += NumArg(op_); // index op_arg = op_arg_ + rec_op_arg_.data(); // pointer // next operator op = op_ = OpCode( rec_op_[ op_index_ ] ); // index for last result for next operator var_index = var_index_ += NumRes(op); CPPAD_ASSERT_UNKNOWN( op_arg_ + NumArg(op) <= rec_op_arg_.size() ); CPPAD_ASSERT_UNKNOWN( var_index_ < num_rec_var_ ); }