VectorBase ADFun<Base>::ForTwo( const VectorBase &x, const VectorSize_t &j, const VectorSize_t &k) { size_t i; size_t j1; size_t k1; size_t l; size_t n = Domain(); size_t m = Range(); size_t p = j.size(); // check VectorBase is Simple Vector class with Base type elements CheckSimpleVector<Base, VectorBase>(); // check VectorSize_t is Simple Vector class with size_t elements CheckSimpleVector<size_t, VectorSize_t>(); CPPAD_ASSERT_KNOWN( x.size() == n, "ForTwo: Length of x not equal domain dimension for f." ); CPPAD_ASSERT_KNOWN( j.size() == k.size(), "ForTwo: Lenght of the j and k vectors are not equal." ); // point at which we are evaluating the second partials Forward(0, x); // dimension the return value VectorBase ddy(m * p); // allocate memory to hold all possible diagonal Taylor coefficients // (for large sparse cases, this is not efficient) VectorBase D(m * n); // boolean flag for which diagonal coefficients are computed CppAD::vector<bool> c(n); for(j1 = 0; j1 < n; j1++) c[j1] = false; // direction vector in argument space VectorBase dx(n); for(j1 = 0; j1 < n; j1++) dx[j1] = Base(0); // result vector in range space VectorBase dy(m); // compute the diagonal coefficients that are needed for(l = 0; l < p; l++) { j1 = j[l]; k1 = k[l]; CPPAD_ASSERT_KNOWN( j1 < n, "ForTwo: an element of j not less than domain dimension for f." ); CPPAD_ASSERT_KNOWN( k1 < n, "ForTwo: an element of k not less than domain dimension for f." ); size_t count = 2; while(count) { count--; if( ! c[j1] ) { // diagonal term in j1 direction c[j1] = true; dx[j1] = Base(1); Forward(1, dx); dx[j1] = Base(0); dy = Forward(2, dx); for(i = 0; i < m; i++) D[i * n + j1 ] = dy[i]; } j1 = k1; } } // compute all the requested cross partials for(l = 0; l < p; l++) { j1 = j[l]; k1 = k[l]; if( j1 == k1 ) { for(i = 0; i < m; i++) ddy[i * p + l] = Base(2) * D[i * n + j1]; } else { // cross term in j1 and k1 directions dx[j1] = Base(1); dx[k1] = Base(1); Forward(1, dx); dx[j1] = Base(0); dx[k1] = Base(0); dy = Forward(2, dx); // place result in return value for(i = 0; i < m; i++) ddy[i * p + l] = dy[i] - D[i*n+j1] - D[i*n+k1]; } } return ddy; }
VectorBase ADFun<Base>::RevTwo( const VectorBase &x, const VectorSize_t &i, const VectorSize_t &j) { size_t i1; size_t j1; size_t k; size_t l; size_t n = Domain(); size_t m = Range(); size_t p = i.size(); // check VectorBase is Simple Vector class with Base elements CheckSimpleVector<Base, VectorBase>(); // check VectorSize_t is Simple Vector class with size_t elements CheckSimpleVector<size_t, VectorSize_t>(); CPPAD_ASSERT_KNOWN( x.size() == n, "RevTwo: Length of x not equal domain dimension for f." ); CPPAD_ASSERT_KNOWN( i.size() == j.size(), "RevTwo: Lenght of the i and j vectors are not equal." ); // point at which we are evaluating the second partials Forward(0, x); // dimension the return value VectorBase ddw(n * p); // direction vector in argument space VectorBase dx(n); for(j1 = 0; j1 < n; j1++) dx[j1] = Base(0); // direction vector in range space VectorBase w(m); for(i1 = 0; i1 < m; i1++) w[i1] = Base(0); // place to hold the results of a reverse calculation VectorBase r(n * 2); // check the indices in i and j for(l = 0; l < p; l++) { i1 = i[l]; j1 = j[l]; CPPAD_ASSERT_KNOWN( i1 < m, "RevTwo: an eleemnt of i not less than range dimension for f." ); CPPAD_ASSERT_KNOWN( j1 < n, "RevTwo: an element of j not less than domain dimension for f." ); } // loop over all forward directions for(j1 = 0; j1 < n; j1++) { // first order forward mode calculation done bool first_done = false; for(l = 0; l < p; l++) if( j[l] == j1 ) { if( ! first_done ) { first_done = true; // first order forward mode in j1 direction dx[j1] = Base(1); Forward(1, dx); dx[j1] = Base(0); } // execute a reverse in this component direction i1 = i[l]; w[i1] = Base(1); r = Reverse(2, w); w[i1] = Base(0); // place the reverse result in return value for(k = 0; k < n; k++) ddw[k * p + l] = r[k * 2 + 1]; } } return ddw; }