inline void forward_powvv_op_dir( size_t q , size_t r , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // convert from final result to first result i_z -= 2; // 2 = NumRes(PowvvOp) - 1 // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(PowvvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(PowvvOp) == 3 ); CPPAD_ASSERT_UNKNOWN( 0 < q ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); CPPAD_ASSERT_UNKNOWN( std::numeric_limits<addr_t>::max() >= i_z ); // z_0 = log(x) forward_log_op_dir(q, r, i_z, arg[0], cap_order, taylor); // z_1 = y * z_0 addr_t adr[2]; adr[0] = addr_t( i_z ); adr[1] = arg[1]; forward_mulvv_op_dir(q, r, i_z+1, adr, parameter, cap_order, taylor); // z_2 = exp(z_1) forward_exp_op_dir(q, r, i_z+2, i_z+1, cap_order, taylor); }
inline void forward_powpv_op( size_t p , size_t q , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // convert from final result to first result i_z -= 2; // 2 = NumRes(PowpvOp) - 1; // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(PowpvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(PowpvOp) == 3 ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); CPPAD_ASSERT_UNKNOWN( p <= q ); // Taylor coefficients corresponding to arguments and result Base* z_0 = taylor + i_z * cap_order; // z_0 = log(x) Base x = parameter[ arg[0] ]; size_t d; for(d = p; d <= q; d++) { if( d == 0 ) z_0[d] = log(x); else z_0[d] = Base(0.0); } // 2DO: remove requirement that i_z * cap_order <= max addr_t value CPPAD_ASSERT_KNOWN( std::numeric_limits<addr_t>::max() >= i_z * cap_order, "cppad_tape_addr_type maximum value has been exceeded\n" "This is due to a kludge in the pow operation and should be fixed." ); // z_1 = z_0 * y addr_t adr[2]; // offset of z_i in taylor (as if it were a parameter); i.e., log(x) adr[0] = addr_t( i_z * cap_order ); // offset of y in taylor (as a variable) adr[1] = arg[1]; // Trick: use taylor both for the parameter vector and variable values forward_mulpv_op(p, q, i_z+1, adr, taylor, cap_order, taylor); // z_2 = exp(z_1) // zero order case exactly same as Base type operation if( p == 0 ) { Base* y = taylor + arg[1] * cap_order; Base* z_2 = taylor + (i_z+2) * cap_order; z_2[0] = pow(x, y[0]); p++; } if( p <= q ) forward_exp_op(p, q, i_z+2, i_z+1, cap_order, taylor); }
/* Helper function for markArgs */ void markOpField( //std::ostream &os , void* os, const char *leader, //const Type &value, const addr_t* op_arg, size_t width ){ addr_t index=addr_t(op_arg-play_.op_arg_rec_.data()); arg_mark_[index]=true; }
inline void forward_powpv_op_dir( size_t q , size_t r , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // convert from final result to first result i_z -= 2; // 2 = NumRes(PowpvOp) - 1; // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(PowpvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(PowpvOp) == 3 ); CPPAD_ASSERT_UNKNOWN( 0 < q ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); // Taylor coefficients corresponding to arguments and result size_t num_taylor_per_var = (cap_order-1) * r + 1; Base* z_0 = taylor + i_z * num_taylor_per_var; // z_0 = log(x) size_t m = (q-1) * r + 1; for(size_t ell = 0; ell < r; ell++) z_0[m+ell] = Base(0.0); // 2DO: remove requirement i_z * num_taylor_per_var <= max addr_t value CPPAD_ASSERT_KNOWN( std::numeric_limits<addr_t>::max() >= i_z * num_taylor_per_var, "cppad_tape_addr_type maximum value has been exceeded\n" "This is due to a kludge in the pow operation and should be fixed." ); // z_1 = z_0 * y addr_t adr[2]; // offset of z_0 in taylor (as if it were a parameter); i.e., log(x) adr[0] = addr_t( i_z * num_taylor_per_var ); // ofset of y in taylor (as a variable) adr[1] = arg[1]; // Trick: use taylor both for the parameter vector and variable values forward_mulpv_op_dir(q, r, i_z+1, adr, taylor, cap_order, taylor); // z_2 = exp(z_1) forward_exp_op_dir(q, r, i_z+2, i_z+1, cap_order, taylor); }
inline void reverse_powpv_op( size_t d , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , const Base* taylor , size_t nc_partial , Base* partial ) { // convert from final result to first result i_z -= 2; // NumRes(PowpvOp) - 1; // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(PowvvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(PowvvOp) == 3 ); CPPAD_ASSERT_UNKNOWN( d < cap_order ); CPPAD_ASSERT_UNKNOWN( d < nc_partial ); // z_2 = exp(z_1) reverse_exp_op( d, i_z+2, i_z+1, cap_order, taylor, nc_partial, partial ); // 2DO: remove requirement that i_z * cap_order <= max addr_t value CPPAD_ASSERT_KNOWN( std::numeric_limits<addr_t>::max() >= i_z * cap_order, "cppad_tape_addr_type maximum value has been exceeded\n" "This is due to a kludge in the pow operation and should be fixed." ); // z_1 = z_0 * y addr_t adr[2]; adr[0] = addr_t( i_z * cap_order ); // offset of z_0[0] in taylor adr[1] = arg[1]; // index of y in taylor and partial // use taylor both for parameter and variable values reverse_mulpv_op( d, i_z+1, adr, taylor, cap_order, taylor, nc_partial, partial ); // z_0 = log(x) // x is a parameter }
inline void forward_powvv_op( size_t p , size_t q , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // convert from final result to first result i_z -= 2; // 2 = NumRes(PowvvOp) - 1; // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(PowvvOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(PowvvOp) == 3 ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); CPPAD_ASSERT_UNKNOWN( p <= q ); CPPAD_ASSERT_UNKNOWN( std::numeric_limits<addr_t>::max() >= i_z ); // z_0 = log(x) forward_log_op(p, q, i_z, arg[0], cap_order, taylor); // z_1 = z_0 * y addr_t adr[2]; adr[0] = addr_t( i_z ); adr[1] = arg[1]; forward_mulvv_op(p, q, i_z+1, adr, parameter, cap_order, taylor); // z_2 = exp(z_1) // final result for zero order case is exactly the same as for Base if( p == 0 ) { // Taylor coefficients corresponding to arguments and result Base* x = taylor + arg[0] * cap_order; Base* y = taylor + arg[1] * cap_order; Base* z_2 = taylor + (i_z+2) * cap_order; z_2[0] = pow(x[0], y[0]); p++; } if( p <= q ) forward_exp_op(p, q, i_z+2, i_z+1, cap_order, taylor); }
inline void forward_powvp_op( size_t p , size_t q , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , Base* taylor ) { // convert from final result to first result i_z -= 2; // 2 = NumRes(PowvpOp) - 1 // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(PowvpOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(PowvpOp) == 3 ); CPPAD_ASSERT_UNKNOWN( q < cap_order ); CPPAD_ASSERT_UNKNOWN( p <= q ); CPPAD_ASSERT_UNKNOWN( std::numeric_limits<addr_t>::max() >= i_z ); // z_0 = log(x) forward_log_op(p, q, i_z, arg[0], cap_order, taylor); // z_1 = y * z_0 addr_t adr[2]; adr[0] = arg[1]; adr[1] = addr_t( i_z ); forward_mulpv_op(p, q, i_z+1, adr, parameter, cap_order, taylor); // z_2 = exp(z_1) // zero order case exactly same as Base type operation if( p == 0 ) { Base* z_2 = taylor + (i_z+2) * cap_order; Base* x = taylor + arg[0] * cap_order; Base y = parameter[ arg[1] ]; z_2[0] = pow(x[0], y); p++; } if( p <= q ) forward_exp_op(p, q, i_z+2, i_z+1, cap_order, taylor); }
inline void reverse_powvp_op( size_t d , size_t i_z , const addr_t* arg , const Base* parameter , size_t cap_order , const Base* taylor , size_t nc_partial , Base* partial ) { // convert from final result to first result i_z -= 2; // NumRes(PowvpOp) - 1; // check assumptions CPPAD_ASSERT_UNKNOWN( NumArg(PowvpOp) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(PowvpOp) == 3 ); CPPAD_ASSERT_UNKNOWN( d < cap_order ); CPPAD_ASSERT_UNKNOWN( d < nc_partial ); CPPAD_ASSERT_UNKNOWN( std::numeric_limits<addr_t>::max() >= i_z ); // z_2 = exp(z_1) reverse_exp_op( d, i_z+2, i_z+1, cap_order, taylor, nc_partial, partial ); // z_1 = y * z_0 addr_t adr[2]; adr[0] = arg[1]; adr[1] = addr_t( i_z ); reverse_mulpv_op( d, i_z+1, adr, parameter, cap_order, taylor, nc_partial, partial ); // z_0 = log(x) reverse_log_op( d, i_z, arg[0], cap_order, taylor, nc_partial, partial ); }
void ADTape<Base>::RecordCondExp( enum CompareOp cop , AD<Base> &returnValue , const AD<Base> &left , const AD<Base> &right , const AD<Base> &if_true , const AD<Base> &if_false ) { size_t ind0, ind1, ind2, ind3, ind4, ind5; size_t returnValue_taddr; // taddr_ of this variable CPPAD_ASSERT_UNKNOWN( NumRes(CExpOp) == 1 ); returnValue_taddr = Rec_.PutOp(CExpOp); // ind[0] = cop ind0 = addr_t( cop ); // ind[1] = base 2 representaion of the value // [Var(left), Var(right), Var(if_true), Var(if_false)] ind1 = 0; // Make sure returnValue is in the list of variables and set its taddr if( Parameter(returnValue) ) returnValue.make_variable(id_, returnValue_taddr ); else returnValue.taddr_ = returnValue_taddr; // ind[2] = left address if( Parameter(left) ) ind2 = Rec_.PutPar(left.value_); else { ind1 += 1; ind2 = left.taddr_; } // ind[3] = right address if( Parameter(right) ) ind3 = Rec_.PutPar(right.value_); else { ind1 += 2; ind3 = right.taddr_; } // ind[4] = if_true address if( Parameter(if_true) ) ind4 = Rec_.PutPar(if_true.value_); else { ind1 += 4; ind4 = if_true.taddr_; } // ind[5] = if_false address if( Parameter(if_false) ) ind5 = Rec_.PutPar(if_false.value_); else { ind1 += 8; ind5 = if_false.taddr_; } CPPAD_ASSERT_UNKNOWN( NumArg(CExpOp) == 6 ); CPPAD_ASSERT_UNKNOWN( ind1 > 0 ); Rec_.PutArg(ind0, ind1, ind2, ind3, ind4, ind5); // check that returnValue is a dependent variable CPPAD_ASSERT_UNKNOWN( Variable(returnValue) ); }
void subgraph_info::get_rev( const play::const_random_iterator<Addr>& random_itr , const pod_vector<size_t>& dep_taddr , addr_t i_dep , pod_vector<addr_t>& subgraph ) { // check sizes CPPAD_ASSERT_UNKNOWN( map_user_op_.size() == n_op_ ); // process_range_ CPPAD_ASSERT_UNKNOWN( process_range_[i_dep] == false ); process_range_[i_dep] = true; // special value; see init_rev_in_subgraph addr_t depend_yes = addr_t( n_dep_ ); // assumption on i_dep CPPAD_ASSERT_UNKNOWN( i_dep < depend_yes ); // start with an empty subgraph for this dependent variable subgraph.resize(0); // tape index corresponding to this dependent variable size_t i_var = dep_taddr[i_dep]; // operator corresponding to this dependent variable size_t i_op = random_itr.var2op(i_var); i_op = size_t( map_user_op_[i_op] ); // if this variable depends on the selected indepent variables // process its subgraph CPPAD_ASSERT_UNKNOWN( in_subgraph_[i_op] != i_dep ) if( in_subgraph_[i_op] <= depend_yes ) { subgraph.push_back( addr_t(i_op) ); in_subgraph_[i_op] = i_dep; } // space used to return set of arguments that are variables pod_vector<size_t> argument_variable; // temporary space used by get_argument_variable pod_vector<bool> work; // scan all the operators in this subgraph size_t sub_index = 0; while(sub_index < subgraph.size() ) { // this operator connected to this dependent and selected independent i_op = size_t( subgraph[sub_index] ); CPPAD_ASSERT_UNKNOWN( in_subgraph_[i_op] == i_dep ); // // There must be a result for this operator # ifndef NDEBUG OpCode op = random_itr.get_op(i_op); CPPAD_ASSERT_UNKNOWN(op == AFunOp || NumRes(op) > 0 ); # endif // // which variables are connected to this operator get_argument_variable(random_itr, i_op, argument_variable, work); for(size_t j = 0; j < argument_variable.size(); ++j) { // add the corresponding operators to the subgraph size_t j_var = argument_variable[j]; size_t j_op = random_itr.var2op(j_var); j_op = size_t( map_user_op_[j_op] ); bool add = in_subgraph_[j_op] <= depend_yes; add &= in_subgraph_[j_op] != i_dep; if( random_itr.get_op(j_op) == InvOp ) { CPPAD_ASSERT_UNKNOWN( j_op == j_var ); add &= select_domain_[j_var - 1]; } if( add ) { subgraph.push_back( addr_t(j_op) ); in_subgraph_[j_op] = i_dep; } } // we are done scaning this subgraph operator ++sub_index; } }
bool isDepArg(const addr_t* op_arg){ addr_t index=addr_t(op_arg-play_.op_arg_rec_.data()); return arg_mark_[index]; }