CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION bool IdenticalEqualPar (const AD<Base> &x, const AD<Base> &y) { bool parameter; parameter = ( Parameter(x) & Parameter(y) ); return parameter && IdenticalEqualPar(x.value_, y.value_); }
size_t recorder<Base>::PutPar(const Base &par) { static size_t hash_table[CPPAD_HASH_TABLE_SIZE * CPPAD_MAX_NUM_THREADS]; size_t i; size_t code; CPPAD_ASSERT_UNKNOWN( thread_offset_ / CPPAD_HASH_TABLE_SIZE == thread_alloc::thread_num() ); // get hash code for this value code = static_cast<size_t>( hash_code(par) ); CPPAD_ASSERT_UNKNOWN( code < CPPAD_HASH_TABLE_SIZE ); // If we have a match, return the parameter index i = hash_table[code + thread_offset_]; if( i < rec_par_.size() && IdenticalEqualPar(rec_par_[i], par) ) return i; // place a new value in the table i = rec_par_.extend(1); rec_par_[i] = par; CPPAD_ASSERT_UNKNOWN( rec_par_.size() == i + 1 ); // make the hash code point to this new value hash_table[code + thread_offset_] = i; // return the parameter index return i; }
inline size_t optimize_binary_match( const CppAD::vector<struct optimize_old_variable>& tape , size_t current , size_t npar , const Base* par , const CppAD::vector<size_t>& hash_table_var , unsigned short& code ) { OpCode op = tape[current].op; const size_t* arg = tape[current].arg; size_t new_arg[2]; bool parameter[2]; // initialize return value size_t match_var = 0; CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 ); CPPAD_ASSERT_UNKNOWN( NumRes(op) > 0 ); switch(op) { // parameter op variable ---------------------------------- case AddpvOp: case MulpvOp: case DivpvOp: case PowpvOp: case SubpvOp: // arg[0] parameter[0] = true; new_arg[0] = arg[0]; CPPAD_ASSERT_UNKNOWN( arg[0] < npar ); // arg[1] parameter[1] = false; new_arg[1] = tape[arg[1]].new_var; CPPAD_ASSERT_UNKNOWN( arg[1] < current ); break; // variable op parameter ----------------------------------- case DivvpOp: case PowvpOp: case SubvpOp: // arg[0] parameter[0] = false; new_arg[0] = tape[arg[0]].new_var; CPPAD_ASSERT_UNKNOWN( arg[0] < current ); // arg[1] parameter[1] = true; new_arg[1] = arg[1]; CPPAD_ASSERT_UNKNOWN( arg[1] < npar ); break; // variable op variable ----------------------------------- case AddvvOp: case MulvvOp: case DivvvOp: case PowvvOp: case SubvvOp: // arg[0] parameter[0] = false; new_arg[0] = tape[arg[0]].new_var; CPPAD_ASSERT_UNKNOWN( arg[0] < current ); // arg[1] parameter[1] = false; new_arg[1] = tape[arg[1]].new_var; CPPAD_ASSERT_UNKNOWN( arg[1] < current ); break; // must be one of the cases above default: CPPAD_ASSERT_UNKNOWN(false); } code = hash_code( op , new_arg , npar , par ); size_t i = hash_table_var[code]; CPPAD_ASSERT_UNKNOWN( i < current ); if( op == tape[i].op ) { bool match = true; size_t j; for(j = 0; j < 2; j++) { size_t k = tape[i].arg[j]; if( parameter[j] ) { CPPAD_ASSERT_UNKNOWN( k < npar ); match &= IdenticalEqualPar( par[ arg[j] ], par[k] ); } else { CPPAD_ASSERT_UNKNOWN( k < i ); match &= (new_arg[j] == tape[k].new_var); } } if( match ) match_var = tape[i].new_var; } if( (match_var > 0) | ( (op != AddvvOp) & (op != MulvvOp ) ) ) return match_var; // check for match with argument order switched ---------------------- CPPAD_ASSERT_UNKNOWN( op == AddvvOp || op == MulvvOp ); i = new_arg[0]; new_arg[0] = new_arg[1]; new_arg[1] = i; unsigned short code_switch = hash_code( op , new_arg , npar , par ); i = hash_table_var[code_switch]; CPPAD_ASSERT_UNKNOWN( i < current ); if( op == tape[i].op ) { bool match = true; size_t j; for(j = 0; j < 2; j++) { size_t k = tape[i].arg[j]; CPPAD_ASSERT_UNKNOWN( k < i ); match &= (new_arg[j] == tape[k].new_var); } if( match ) match_var = tape[i].new_var; } return match_var; }