VectorBase subset(const VectorBase& x, size_t tapeid, int p=1){ VectorBase y; y.resize(vecind(tapeid).size()*p); for(int i=0;i<y.size()/p;i++) for(int j=0;j<p;j++) {y(i*p+j)=x(vecind(tapeid)[i]*p+j);} return y; }
void VectorBase<scalar,index,SizeAtCompileTime>::stCombine(const VectorBase& v1,const VectorBase& v2,VectorBase& v) { v.resize(v1.size()+v2.size()); index n = v1.size(); for ( index i = 0 ; i < n ; ++ i ) v[i] = v1[i]; for ( index i = 0 ; i < v2.size() ; ++ i ) v[i+n] = v2[i]; }
VectorBase ADFun<Base>::Forward( size_t q , const VectorBase& xq , std::ostream& s ) { // 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(); // check Vector is Simple Vector class with Base type elements CheckSimpleVector<Base, VectorBase>(); CPPAD_ASSERT_KNOWN( size_t(xq.size()) == n || size_t(xq.size()) == n*(q+1), "Forward(q, xq): xq.size() is not equal n or n*(q+1)" ); // lowest order we are computing size_t p = q + 1 - size_t(xq.size()) / n; CPPAD_ASSERT_UNKNOWN( p == 0 || p == q ); CPPAD_ASSERT_KNOWN( q <= num_order_taylor_ || p == 0, "Forward(q, xq): Number of Taylor coefficient orders stored in this" " ADFun\nis less than q and xq.size() != n*(q+1)." ); CPPAD_ASSERT_KNOWN( p <= 1 || num_direction_taylor_ == 1, "Forward(q, xq): computing order q >= 2" " and number of directions is not one." "\nMust use Forward(q, r, xq) for this case" ); // does taylor_ need more orders or fewer directions if( (cap_order_taylor_ <= q) | (num_direction_taylor_ != 1) ) { if( p == 0 ) { // no need to copy old values during capacity_order num_order_taylor_ = 0; } else num_order_taylor_ = q; size_t c = std::max(q + 1, cap_order_taylor_); size_t r = 1; capacity_order(c, r); } CPPAD_ASSERT_UNKNOWN( cap_order_taylor_ > q ); CPPAD_ASSERT_UNKNOWN( num_direction_taylor_ == 1 ); // short hand notation for order capacity size_t C = cap_order_taylor_; // set Taylor coefficients for independent variables for(j = 0; j < n; j++) { CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] < num_var_tape_ ); // ind_taddr_[j] is operator taddr for j-th independent variable CPPAD_ASSERT_UNKNOWN( play_.GetOp( ind_taddr_[j] ) == InvOp ); if( p == q ) taylor_[ C * ind_taddr_[j] + q] = xq[j]; else { for(k = 0; k <= q; k++) taylor_[ C * ind_taddr_[j] + k] = xq[ (q+1)*j + 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() ); if( q == 0 ) { forward0sweep(s, true, n, num_var_tape_, &play_, C, taylor_.data(), cskip_op_.data(), load_op_, compare_change_count_, compare_change_number_, compare_change_op_index_ ); } else { forward1sweep(s, true, p, q, n, num_var_tape_, &play_, C, taylor_.data(), cskip_op_.data(), load_op_, compare_change_count_, compare_change_number_, compare_change_op_index_ ); } // return Taylor coefficients for dependent variables VectorBase yq; if( p == q ) { yq.resize(m); for(i = 0; i < m; i++) { CPPAD_ASSERT_UNKNOWN( dep_taddr_[i] < num_var_tape_ ); yq[i] = taylor_[ C * dep_taddr_[i] + q]; } } else { yq.resize(m * (q+1) ); for(i = 0; i < m; i++) { for(k = 0; k <= q; k++) yq[ (q+1) * i + k] = taylor_[ C * dep_taddr_[i] + k ]; } } # ifndef NDEBUG if( check_for_nan_ ) { bool ok = true; if( p == 0 ) { for(i = 0; i < m; i++) { // Visual Studio 2012, CppAD required in front of isnan ? ok &= ! CppAD::isnan( yq[ (q+1) * i + 0 ] ); } } CPPAD_ASSERT_KNOWN(ok, "yq = f.Forward(q, xq): has a zero order Taylor coefficient " "with the value nan." ); if( 0 < q ) { for(i = 0; i < m; i++) { for(k = p; k <= q; k++) { // Studio 2012, CppAD required in front of isnan ? ok &= ! CppAD::isnan( yq[ (q+1-p)*i + k-p ] ); } } } CPPAD_ASSERT_KNOWN(ok, "yq = f.Forward(q, xq): has a non-zero order Taylor coefficient\n" "with the value nan (but zero order coefficients are not nan)." ); } # endif // now we have q + 1 taylor_ coefficient orders per variable num_order_taylor_ = q + 1; return yq; }
VectorBase ADFun<Base>::Forward( size_t q , size_t r , const VectorBase& xq ) { // temporary indices size_t i, j, ell; // number of independent variables size_t n = ind_taddr_.size(); // number of dependent variables size_t m = dep_taddr_.size(); // check Vector is Simple Vector class with Base type elements CheckSimpleVector<Base, VectorBase>(); CPPAD_ASSERT_KNOWN( q > 0, "Forward(q, r, xq): q == 0" ); CPPAD_ASSERT_KNOWN( size_t(xq.size()) == r * n, "Forward(q, r, xq): xq.size() is not equal r * n" ); CPPAD_ASSERT_KNOWN( q <= num_order_taylor_ , "Forward(q, r, xq): Number of Taylor coefficient orders stored in" " this ADFun is less than q" ); CPPAD_ASSERT_KNOWN( q == 1 || num_direction_taylor_ == r , "Forward(q, r, xq): q > 1 and number of Taylor directions r" " is not same as previous Forward(1, r, xq)" ); // does taylor_ need more orders or new number of directions if( cap_order_taylor_ <= q || num_direction_taylor_ != r ) { if( num_direction_taylor_ != r ) num_order_taylor_ = 1; size_t c = std::max(q + 1, cap_order_taylor_); capacity_order(c, r); } CPPAD_ASSERT_UNKNOWN( cap_order_taylor_ > q ); CPPAD_ASSERT_UNKNOWN( num_direction_taylor_ == r ) // short hand notation for order capacity size_t c = cap_order_taylor_; // set Taylor coefficients for independent variables for(j = 0; j < n; j++) { CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] < num_var_tape_ ); // ind_taddr_[j] is operator taddr for j-th independent variable CPPAD_ASSERT_UNKNOWN( play_.GetOp( ind_taddr_[j] ) == InvOp ); for(ell = 0; ell < r; ell++) { size_t index = ((c-1)*r + 1)*ind_taddr_[j] + (q-1)*r + ell + 1; taylor_[ index ] = xq[ r * j + ell ]; } } // evaluate the derivatives CPPAD_ASSERT_UNKNOWN( cskip_op_.size() == play_.num_op_rec() ); CPPAD_ASSERT_UNKNOWN( load_op_.size() == play_.num_load_op_rec() ); forward2sweep( q, r, n, num_var_tape_, &play_, c, taylor_.data(), cskip_op_.data(), load_op_ ); // return Taylor coefficients for dependent variables VectorBase yq; yq.resize(r * m); for(i = 0; i < m; i++) { CPPAD_ASSERT_UNKNOWN( dep_taddr_[i] < num_var_tape_ ); for(ell = 0; ell < r; ell++) { size_t index = ((c-1)*r + 1)*dep_taddr_[i] + (q-1)*r + ell + 1; yq[ r * i + ell ] = taylor_[ index ]; } } # ifndef NDEBUG if( check_for_nan_ ) { bool ok = true; for(i = 0; i < m; i++) { for(ell = 0; ell < r; ell++) { // Studio 2012, CppAD required in front of isnan ? ok &= ! CppAD::isnan( yq[ r * i + ell ] ); } } CPPAD_ASSERT_KNOWN(ok, "yq = f.Forward(q, r, xq): has a non-zero order Taylor coefficient\n" "with the value nan (but zero order coefficients are not nan)." ); } # endif // now we have q + 1 taylor_ coefficient orders per variable num_order_taylor_ = q + 1; return yq; }
VectorBase ADFun<Base>::Forward( size_t q , const VectorBase& xq , std::ostream& s ) { // 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(); // check Vector is Simple Vector class with Base type elements CheckSimpleVector<Base, VectorBase>(); CPPAD_ASSERT_KNOWN( size_t(xq.size()) == n || size_t(xq.size()) == n*(q+1), "Forward(q, xq): xq.size() is not equal n or n*(q+1)" ); // lowest order we are computing size_t p = q + 1 - size_t(xq.size()) / n; CPPAD_ASSERT_UNKNOWN( p == 0 || p == q ); CPPAD_ASSERT_KNOWN( q <= num_order_taylor_ || p == 0, "Forward(q, xq): Number of Taylor coefficient orders stored in this" " ADFun\nis less than q and xq.size() != n*(q+1)." ); CPPAD_ASSERT_KNOWN( p <= 1 || num_direction_taylor_ == 1, "Forward(q, xq): computing order q >= 2" " and number of directions is not one." "\nMust use Forward(q, r, xq) for this case" ); // does taylor_ need more orders or fewer directions if( (cap_order_taylor_ <= q) | (num_direction_taylor_ != 1) ) { if( p == 0 ) { // no need to copy old values during capacity_order num_order_taylor_ = 0; } else num_order_taylor_ = q; size_t c = std::max(q + 1, cap_order_taylor_); size_t r = 1; capacity_order(c, r); } CPPAD_ASSERT_UNKNOWN( cap_order_taylor_ > q ); CPPAD_ASSERT_UNKNOWN( num_direction_taylor_ == 1 ); // short hand notation for order capacity size_t C = cap_order_taylor_; // The optimizer may skip a step that does not affect dependent variables. // Initilaizing zero order coefficients avoids following valgrind warning: // "Conditional jump or move depends on uninitialised value(s)". for(j = 0; j < num_var_tape_; j++) { for(k = p; k <= q; k++) taylor_[C * j + k] = CppAD::numeric_limits<Base>::quiet_NaN(); } // set Taylor coefficients for independent variables for(j = 0; j < n; j++) { CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] < num_var_tape_ ); // ind_taddr_[j] is operator taddr for j-th independent variable CPPAD_ASSERT_UNKNOWN( play_.GetOp( ind_taddr_[j] ) == local::InvOp ); if( p == q ) taylor_[ C * ind_taddr_[j] + q] = xq[j]; else { for(k = 0; k <= q; k++) taylor_[ C * ind_taddr_[j] + k] = xq[ (q+1)*j + 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() ); if( q == 0 ) { local::forward0sweep(s, true, n, num_var_tape_, &play_, C, taylor_.data(), cskip_op_.data(), load_op_, compare_change_count_, compare_change_number_, compare_change_op_index_ ); } else { local::forward1sweep(s, true, p, q, n, num_var_tape_, &play_, C, taylor_.data(), cskip_op_.data(), load_op_, compare_change_count_, compare_change_number_, compare_change_op_index_ ); } // return Taylor coefficients for dependent variables VectorBase yq; if( p == q ) { yq.resize(m); for(i = 0; i < m; i++) { CPPAD_ASSERT_UNKNOWN( dep_taddr_[i] < num_var_tape_ ); yq[i] = taylor_[ C * dep_taddr_[i] + q]; } } else { yq.resize(m * (q+1) ); for(i = 0; i < m; i++) { for(k = 0; k <= q; k++) yq[ (q+1) * i + k] = taylor_[ C * dep_taddr_[i] + k ]; } } # ifndef NDEBUG if( check_for_nan_ ) { bool ok = true; size_t index = m; if( p == 0 ) { for(i = 0; i < m; i++) { // Visual Studio 2012, CppAD required in front of isnan ? if( CppAD::isnan( yq[ (q+1) * i + 0 ] ) ) { ok = false; if( index == m ) index = i; } } } if( ! ok ) { CPPAD_ASSERT_UNKNOWN( index < m ); // CppAD::vector<Base> x0(n); for(j = 0; j < n; j++) x0[j] = taylor_[ C * ind_taddr_[j] + 0 ]; std::string file_name; put_check_for_nan(x0, file_name); std::stringstream ss; ss << "yq = f.Forward(q, xq): a zero order Taylor coefficient is nan.\n" "Corresponding independent variables vector was written " "to binary a file.\n" "vector_size = " << n << "\n" << "file_name = " << file_name << "\n" << "index = " << index << "\n"; // ss.str() returns a string object with a copy of the current // contents in the stream buffer. std::string msg_str = ss.str(); // msg_str.c_str() returns a pointer to the c-string // representation of the string object's value. const char* msg_char_star = msg_str.c_str(); ErrorHandler::Call( true, __LINE__, __FILE__, "if( CppAD::isnan( yq[ (q+1) * index + 0 ] )", msg_char_star ); } CPPAD_ASSERT_KNOWN(ok, "with the value nan." ); if( 0 < q ) { for(i = 0; i < m; i++) { for(k = p; k <= q; k++) { // Studio 2012, CppAD required in front of isnan ? ok &= ! CppAD::isnan( yq[ (q+1-p)*i + k-p ] ); } } } CPPAD_ASSERT_KNOWN(ok, "yq = f.Forward(q, xq): has a non-zero order Taylor coefficient\n" "with the value nan (but zero order coefficients are not nan)." ); } # endif // now we have q + 1 taylor_ coefficient orders per variable num_order_taylor_ = q + 1; return yq; }