void operator()( const ADVector& ax , ADVector& ay , size_t id = 0 ) { size_t i, j; size_t n = ax.size(); size_t m = ay.size(); # ifndef NDEBUG bool ok; std::string msg = "atomic_base: " + afun_name() + ".eval: "; if( (n == 0) | (m == 0) ) { msg += "ax.size() or ay.size() is zero"; CPPAD_ASSERT_KNOWN(false, msg.c_str() ); } # endif size_t thread = thread_alloc::thread_num(); vector <Base>& tx = afun_tx_[thread]; vector <Base>& ty = afun_ty_[thread]; vector <bool>& vx = afun_vx_[thread]; vector <bool>& vy = afun_vy_[thread]; // if( vx.size() != n ) { vx.resize(n); tx.resize(n); } if( vy.size() != m ) { vy.resize(m); ty.resize(m); } // // Determine tape corresponding to variables in ax tape_id_t tape_id = 0; ADTape<Base>* tape = CPPAD_NULL; for(j = 0; j < n; j++) { tx[j] = ax[j].value_; vx[j] = Variable( ax[j] ); if( vx[j] ) { if( tape_id == 0 ) { tape = ax[j].tape_this(); tape_id = ax[j].tape_id_; CPPAD_ASSERT_UNKNOWN( tape != CPPAD_NULL ); } # ifndef NDEBUG if( tape_id != ax[j].tape_id_ ) { msg += afun_name() + ": ax contains variables from different threads."; CPPAD_ASSERT_KNOWN(false, msg.c_str()); } # endif } } // Use zero order forward mode to compute values size_t q = 0, p = 0; set_id(id); # ifdef NDEBUG forward(q, p, vx, vy, tx, ty); # else ok = forward(q, p, vx, vy, tx, ty); if( ! ok ) { msg += afun_name() + ": ok is false for " "zero order forward mode calculation."; CPPAD_ASSERT_KNOWN(false, msg.c_str()); } # endif bool record_operation = false; for(i = 0; i < m; i++) { // pass back values ay[i].value_ = ty[i]; // initialize entire vector parameters (not in tape) ay[i].tape_id_ = 0; ay[i].taddr_ = 0; // we need to record this operation if // any of the eleemnts of ay are variables, record_operation |= vy[i]; } # ifndef NDEBUG if( record_operation & (tape == CPPAD_NULL) ) { msg += "all elements of vx are false but vy contains a true element"; CPPAD_ASSERT_KNOWN(false, msg.c_str() ); } # endif // if tape is not null, ay is on the tape if( record_operation ) { // Operator that marks beginning of this atomic operation CPPAD_ASSERT_UNKNOWN( NumRes(UserOp) == 0 ); CPPAD_ASSERT_UNKNOWN( NumArg(UserOp) == 4 ); tape->Rec_.PutArg(index_, id, n, m); tape->Rec_.PutOp(UserOp); // Now put n operators, one for each element of arugment vector CPPAD_ASSERT_UNKNOWN( NumRes(UsravOp) == 0 ); CPPAD_ASSERT_UNKNOWN( NumRes(UsrapOp) == 0 ); CPPAD_ASSERT_UNKNOWN( NumArg(UsravOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumArg(UsrapOp) == 1 ); for(j = 0; j < n; j++) { if( vx[j] ) { // information for an argument that is a variable tape->Rec_.PutArg(ax[j].taddr_); tape->Rec_.PutOp(UsravOp); } else { // information for an arugment that is parameter addr_t par = tape->Rec_.PutPar(ax[j].value_); tape->Rec_.PutArg(par); tape->Rec_.PutOp(UsrapOp); } } // Now put m operators, one for each element of result vector CPPAD_ASSERT_UNKNOWN( NumArg(UsrrpOp) == 1 ); CPPAD_ASSERT_UNKNOWN( NumRes(UsrrpOp) == 0 ); CPPAD_ASSERT_UNKNOWN( NumArg(UsrrvOp) == 0 ); CPPAD_ASSERT_UNKNOWN( NumRes(UsrrvOp) == 1 ); for(i = 0; i < m; i++) { if( vy[i] ) { ay[i].taddr_ = tape->Rec_.PutOp(UsrrvOp); ay[i].tape_id_ = tape_id; } else { addr_t par = tape->Rec_.PutPar(ay[i].value_); tape->Rec_.PutArg(par); tape->Rec_.PutOp(UsrrpOp); } } // Put a duplicate UserOp at end of UserOp sequence tape->Rec_.PutArg(index_, id, n, m); tape->Rec_.PutOp(UserOp); } return; }
bool atomic_base<Base>::rev_sparse_hes( const vector<Base>& x , const local::pod_vector<size_t>& x_index , const local::pod_vector<size_t>& y_index , const InternalSparsity& for_jac_sparsity , bool* rev_jac_flag , InternalSparsity& rev_hes_sparsity ) { CPPAD_ASSERT_UNKNOWN( for_jac_sparsity.end() == rev_hes_sparsity.end() ); size_t q = rev_hes_sparsity.end(); size_t n = x_index.size(); size_t m = y_index.size(); bool ok = false; size_t thread = thread_alloc::thread_num(); allocate_work(thread); bool zero_empty = true; bool input_empty = false; bool transpose = false; // // vx vector<bool> vx(n); for(size_t j = 0; j < n; j++) vx[j] = x_index[j] != 0; // // note that s and t are vectors so transpose does not matter for bool case vector<bool> bool_s( work_[thread]->bool_s ); vector<bool> bool_t( work_[thread]->bool_t ); // bool_s.resize(m); bool_t.resize(n); // for(size_t i = 0; i < m; i++) { if( y_index[i] > 0 ) bool_s[i] = rev_jac_flag[ y_index[i] ]; } // std::string msg = ": atomic_base.rev_sparse_hes: returned false"; if( sparsity_ == pack_sparsity_enum ) { vectorBool& pack_r( work_[thread]->pack_r ); vectorBool& pack_u( work_[thread]->pack_u ); vectorBool& pack_v( work_[thread]->pack_h ); // pack_v.resize(n * q); // local::get_internal_sparsity( transpose, x_index, for_jac_sparsity, pack_r ); local::get_internal_sparsity( transpose, y_index, rev_hes_sparsity, pack_u ); // ok = rev_sparse_hes(vx, bool_s, bool_t, q, pack_r, pack_u, pack_v, x); if( ! ok ) ok = rev_sparse_hes(vx, bool_s, bool_t, q, pack_r, pack_u, pack_v); if( ! ok ) { msg = afun_name() + msg + " sparsity = pack_sparsity_enum"; CPPAD_ASSERT_KNOWN(false, msg.c_str()); } local::set_internal_sparsity(zero_empty, input_empty, transpose, x_index, rev_hes_sparsity, pack_v ); } else if( sparsity_ == bool_sparsity_enum ) { vector<bool>& bool_r( work_[thread]->bool_r ); vector<bool>& bool_u( work_[thread]->bool_u ); vector<bool>& bool_v( work_[thread]->bool_h ); // bool_v.resize(n * q); // local::get_internal_sparsity( transpose, x_index, for_jac_sparsity, bool_r ); local::get_internal_sparsity( transpose, y_index, rev_hes_sparsity, bool_u ); // ok = rev_sparse_hes(vx, bool_s, bool_t, q, bool_r, bool_u, bool_v, x); if( ! ok ) ok = rev_sparse_hes(vx, bool_s, bool_t, q, bool_r, bool_u, bool_v); if( ! ok ) { msg = afun_name() + msg + " sparsity = bool_sparsity_enum"; CPPAD_ASSERT_KNOWN(false, msg.c_str()); } local::set_internal_sparsity(zero_empty, input_empty, transpose, x_index, rev_hes_sparsity, bool_v ); } else { CPPAD_ASSERT_UNKNOWN( sparsity_ == set_sparsity_enum ); vector< std::set<size_t> >& set_r( work_[thread]->set_r ); vector< std::set<size_t> >& set_u( work_[thread]->set_u ); vector< std::set<size_t> >& set_v( work_[thread]->set_h ); // set_v.resize(n); // local::get_internal_sparsity( transpose, x_index, for_jac_sparsity, set_r ); local::get_internal_sparsity( transpose, y_index, rev_hes_sparsity, set_u ); // ok = rev_sparse_hes(vx, bool_s, bool_t, q, set_r, set_u, set_v, x); if( ! ok ) ok = rev_sparse_hes(vx, bool_s, bool_t, q, set_r, set_u, set_v); if( ! ok ) { msg = afun_name() + msg + " sparsity = set_sparsity_enum"; CPPAD_ASSERT_KNOWN(false, msg.c_str()); } local::set_internal_sparsity(zero_empty, input_empty, transpose, x_index, rev_hes_sparsity, set_v ); } for(size_t j = 0; j < n; j++) { if( x_index[j] > 0 ) rev_jac_flag[ x_index[j] ] |= bool_t[j]; } return ok; }