VectorBase ADFun<Base>::Reverse(size_t q, const VectorBase &w) { // constants const Base zero(0); // temporary indices size_t i, j, k; // number of independent variables size_t n = ind_taddr_.size(); // number of dependent variables size_t m = dep_taddr_.size(); pod_vector<Base> Partial; Partial.extend(num_var_tape_ * q); // update maximum memory requirement // memoryMax = std::max( memoryMax, // Memory() + num_var_tape_ * q * sizeof(Base) // ); // check VectorBase is Simple Vector class with Base type elements CheckSimpleVector<Base, VectorBase>(); CPPAD_ASSERT_KNOWN( size_t(w.size()) == m || size_t(w.size()) == (m * q), "Argument w to Reverse does not have length equal to\n" "the dimension of the range for the corresponding ADFun." ); CPPAD_ASSERT_KNOWN( q > 0, "The first argument to Reverse must be greater than zero." ); CPPAD_ASSERT_KNOWN( num_order_taylor_ >= q, "Less that q taylor_ coefficients are currently stored" " in this ADFun object." ); // special case where multiple forward directions have been computed, // but we are only using the one direction zero order results if( (q == 1) & (num_direction_taylor_ > 1) ) { num_order_taylor_ = 1; // number of orders to copy size_t c = cap_order_taylor_; // keep the same capacity setting size_t r = 1; // only keep one direction capacity_order(c, r); } CPPAD_ASSERT_KNOWN( num_direction_taylor_ == 1, "Reverse mode for Forward(q, r, xq) with more than one direction" "\n(r > 1) is not yet supported for q > 1." ); // initialize entire Partial matrix to zero for(i = 0; i < num_var_tape_; i++) for(j = 0; j < q; j++) Partial[i * q + j] = zero; // set the dependent variable direction // (use += because two dependent variables can point to same location) for(i = 0; i < m; i++) { CPPAD_ASSERT_UNKNOWN( dep_taddr_[i] < num_var_tape_ ); if( size_t(w.size()) == m ) Partial[dep_taddr_[i] * q + q - 1] += w[i]; else { for(k = 0; k < q; k++) // ? should use += here, first make test to demonstrate bug Partial[ dep_taddr_[i] * q + k ] = w[i * q + k ]; } } // evaluate the derivatives CPPAD_ASSERT_UNKNOWN( cskip_op_.size() == play_.num_op_rec() ); CPPAD_ASSERT_UNKNOWN( load_op_.size() == play_.num_load_op_rec() ); ReverseSweep( q - 1, n, num_var_tape_, &play_, cap_order_taylor_, taylor_.data(), q, Partial.data(), cskip_op_.data(), load_op_ ); // return the derivative values VectorBase value(n * q); for(j = 0; j < n; j++) { CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] < num_var_tape_ ); // independent variable taddr equals its operator taddr CPPAD_ASSERT_UNKNOWN( play_.GetOp( ind_taddr_[j] ) == InvOp ); // by the Reverse Identity Theorem // partial of y^{(k)} w.r.t. u^{(0)} is equal to // partial of y^{(q-1)} w.r.t. u^{(q - 1 - k)} if( size_t(w.size()) == m ) { for(k = 0; k < q; k++) value[j * q + k ] = Partial[ind_taddr_[j] * q + q - 1 - k]; } else { for(k = 0; k < q; k++) value[j * q + k ] = Partial[ind_taddr_[j] * q + k]; } } CPPAD_ASSERT_KNOWN( ! ( hasnan(value) && check_for_nan_ ) , "dw = f.Reverse(q, w): has a nan,\n" "but none of its Taylor coefficents are nan." ); return value; }
VectorBase ADFun<Base>::Reverse(size_t p, const VectorBase &w) { // constants const Base zero(0); // temporary indices size_t i, j, k; // number of independent variables size_t n = ind_taddr_.size(); // number of dependent variables size_t m = dep_taddr_.size(); pod_vector<Base> Partial; Partial.extend(total_num_var_ * p); // update maximum memory requirement // memoryMax = std::max( memoryMax, // Memory() + total_num_var_ * p * sizeof(Base) // ); // check VectorBase is Simple Vector class with Base type elements CheckSimpleVector<Base, VectorBase>(); CPPAD_ASSERT_KNOWN( size_t(w.size()) == m || size_t(w.size()) == (m * p), "Argument w to Reverse does not have length equal to\n" "the dimension of the range for the corresponding ADFun." ); CPPAD_ASSERT_KNOWN( p > 0, "The first argument to Reverse must be greater than zero." ); CPPAD_ASSERT_KNOWN( taylor_per_var_ >= p, "Less that p taylor_ coefficients are currently stored" " in this ADFun object." ); // initialize entire Partial matrix to zero for(i = 0; i < total_num_var_; i++) for(j = 0; j < p; j++) Partial[i * p + j] = zero; // set the dependent variable direction // (use += because two dependent variables can point to same location) for(i = 0; i < m; i++) { CPPAD_ASSERT_UNKNOWN( dep_taddr_[i] < total_num_var_ ); if( size_t(w.size()) == m ) Partial[dep_taddr_[i] * p + p - 1] += w[i]; else { for(k = 0; k < p; k++) // ? should use += here, first make test to demonstrate bug Partial[ dep_taddr_[i] * p + k ] = w[i * p + k ]; } } // evaluate the derivatives ReverseSweep( p - 1, n, total_num_var_, &play_, taylor_col_dim_, taylor_.data(), p, Partial.data(), cskip_op_ ); // return the derivative values VectorBase value(n * p); for(j = 0; j < n; j++) { CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] < total_num_var_ ); // independent variable taddr equals its operator taddr CPPAD_ASSERT_UNKNOWN( play_.GetOp( ind_taddr_[j] ) == InvOp ); // by the Reverse Identity Theorem // partial of y^{(k)} w.r.t. u^{(0)} is equal to // partial of y^{(p-1)} w.r.t. u^{(p - 1 - k)} if( size_t(w.size()) == m ) { for(k = 0; k < p; k++) value[j * p + k ] = Partial[ind_taddr_[j] * p + p - 1 - k]; } else { for(k = 0; k < p; k++) value[j * p + k ] = Partial[ind_taddr_[j] * p + k]; } } CPPAD_ASSERT_KNOWN( ! ( hasnan(value) && check_for_nan_ ) , "dw = f.Reverse(p, w): has a nan,\n" "but none of its Taylor coefficents are nan." ); return value; }
VectorBase ADFun<Base>::Reverse(size_t p, const VectorBase &w) const { // temporary indices size_t i, j, k; // number of independent variables size_t n = ind_taddr_.size(); // number of dependent variables size_t m = dep_taddr_.size(); Base *Partial = CPPAD_NULL; Partial = CPPAD_TRACK_NEW_VEC(total_num_var_ * p, Partial); // update maximum memory requirement // memoryMax = std::max( memoryMax, // Memory() + total_num_var_ * p * sizeof(Base) // ); // check VectorBase is Simple Vector class with Base type elements CheckSimpleVector<Base, VectorBase>(); CPPAD_ASSERT_KNOWN( w.size() == m, "Argument w to Reverse does not have length equal to\n" "the dimension of the range for the corresponding ADFun." ); CPPAD_ASSERT_KNOWN( p > 0, "The first argument to Reverse must be greater than zero." ); CPPAD_ASSERT_KNOWN( taylor_per_var_ >= p, "Less that p taylor_ coefficients are currently stored" " in this ADFun object." ); // initialize entire Partial matrix to zero for(i = 0; i < total_num_var_; i++) for(j = 0; j < p; j++) Partial[i * p + j] = Base(0); // set the dependent variable direction // (use += because two dependent variables can point to same location) for(i = 0; i < m; i++) { CPPAD_ASSERT_UNKNOWN( dep_taddr_[i] < total_num_var_ ); Partial[dep_taddr_[i] * p + p - 1] += w[i]; } // evaluate the derivatives ReverseSweep( p - 1, total_num_var_, &play_, taylor_col_dim_, taylor_, p, Partial ); // return the derivative values VectorBase value(n * p); for(j = 0; j < n; j++) { CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] < total_num_var_ ); // independent variable taddr equals its operator taddr CPPAD_ASSERT_UNKNOWN( play_.GetOp( ind_taddr_[j] ) == InvOp ); // by the Reverse Identity Theorem // partial of y^{(k)} w.r.t. u^{(0)} is equal to // partial of y^{(p-1)} w.r.t. u^{(p - 1 - k)} for(k = 0; k < p; k++) value[j * p + k ] = Partial[ind_taddr_[j] * p + p - 1 - k]; } // done with the Partial array CPPAD_TRACK_DEL_VEC(Partial); return value; }