28 #ifdef CPPAD_FRAMEWORK 61 template <
class Base,
class Func>
63 std::cout <<
"Generating tape\n";
66 for(
int i=0;i<n;i++)x[i]=AD<Base>(x_[i]);
67 CppAD::Independent(x);
70 for(
int i=0;i<y.size();i++)y2[i]=y[i];
71 CppAD::ADFun<Base>* padf=
new CppAD::ADFun<Base>(x,y2);
79 CppAD::ADFun<Base>* forrev(CppAD::ADFun<AD<Base> >* padf,
vector<double> x_){
80 size_t n=padf->Domain();
81 size_t m=padf->Range();
84 for(
int i=0;i<x_.size();i++)x[i]=AD<Base>(x_[i]);
85 for(
int i=x_.size();i<x.size();i++)x[i]=AD<Base>(0);
88 CppAD::Independent(x);
89 for(
size_t i=0;i<n;i++)tmp1[i]=x[i];
90 for(
size_t i=0;i<m;i++)tmp2[i]=x[i+n];
91 padf->Forward(0,tmp1);
92 y = padf->Reverse(1,tmp2);
93 CppAD::ADFun<Base>* padf2=
new CppAD::ADFun<Base>(x,y);
98 template <
class ADBase>
99 CppAD::ADFun<double>* multi_forrev(CppAD::ADFun<ADBase>* padf,
vector<double> x_){
100 return multi_forrev(forrev(padf, x_), x_);
103 CppAD::ADFun<double>* multi_forrev<double>(CppAD::ADFun<double>* padf,
vector<double> x_) CSKIP({
109 typedef typename Func::ScalarType::value_type Base;
110 CppAD::ADFun<Base>* f0=generate_tape<Base>(f,x);
111 CppAD::ADFun<double>* fn=multi_forrev(f0,x);
115 #define NTHREADS config.nthreads 116 #define THREAD omp_get_thread_num() 123 template<
template<
class>
class UserFunctor>
124 struct forrev_derivatives{
127 forrev_derivatives(){
132 CppAD::vector<CppAD::vector<CppAD::ADFun<double>* > > vpf;
133 void cpyADfunPointer(CppAD::ADFun<double>* padf,
int i){
137 for(
int thread=1;thread<NTHREADS;thread++){
138 vpf[thread][i]=
new CppAD::ADFun<double>();
139 vpf[thread][i]->operator=(*padf);
143 UserFunctor<double> f;
146 UserFunctor<AD<double> > f0;
147 UserFunctor<AD<AD<double> > > f1;
148 UserFunctor<AD<AD<AD<double> > > > f2;
149 UserFunctor<AD<AD<AD<AD<double> > > > > f3;
150 vpf.resize(NTHREADS);
151 for(
int thread=0;thread<NTHREADS;thread++){
152 vpf[thread].resize(4);
154 cpyADfunPointer(tape_symbol(f0,x), 0);
155 cpyADfunPointer(tape_symbol(f1,x), 1);
156 cpyADfunPointer(tape_symbol(f2,x), 2);
157 cpyADfunPointer(tape_symbol(f3,x), 3);
165 int get_output_dim(
int input_dim){
168 if (input_dim == n) output_dim = m;
169 else if (input_dim == n+m) output_dim = n;
170 else if (input_dim == n+m+n) output_dim = n+m;
171 else if (input_dim == n+m+n+n+m) output_dim = n+m+n;
172 else Rf_error(
"get_output_dim failed");
176 int get_level(
int input_dim){
178 if (input_dim == n) level = 0;
179 else if (input_dim == n+m) level = 1;
180 else if (input_dim == n+m+n) level = 2;
181 else if (input_dim == n+m+n+n+m) level = 3;
182 else Rf_error(
"get_level failed");
186 CppAD::vector<double> operator()(CppAD::vector<double> tx){
187 int level = get_level(tx.size());
188 return vpf[THREAD][level]->Forward(0,tx);
196 #define REGISTER_ATOMIC(USERFUNCTION) \ 197 namespace USERFUNCTION##NAMESPACE{ \ 198 template<class Type> \ 199 struct UserFunctor{ \ 200 typedef Type ScalarType; \ 201 vector<Type> operator()(vector<Type> x){ \ 202 return USERFUNCTION(x); \ 205 atomic::forrev_derivatives<UserFunctor> double_version; \ 206 TMB_ATOMIC_VECTOR_FUNCTION( \ 209 double_version.get_output_dim(tx.size()) \ 211 ty = double_version(tx); \ 213 CppAD::vector<Type> concat(tx.size() + py.size()); \ 214 for(size_t i=0; i < tx.size(); i++) concat[i] = tx[i]; \ 215 for(size_t i=0; i < py.size(); i++) concat[tx.size()+i] = py[i]; \ 216 px = generalized_symbol(concat); \ 218 template<class Base> \ 219 vector<Base> generalized_symbol(vector<Base> x){ \ 220 CppAD::vector<Base> xx(x.size()); \ 221 for(int i=0;i<x.size();i++)xx[i]=x[i]; \ 222 CppAD::vector<Base> yy=generalized_symbol(xx); \ 223 vector<Base> y(yy.size()); \ 224 for(int i=0;i<y.size();i++)y[i]=yy[i]; \ 228 vector<double> USERFUNCTION(vector<double> x){ \ 229 USERFUNCTION##NAMESPACE::double_version.init(x); \ 230 return USERFUNCTION##NAMESPACE::generalized_symbol(x); \ 232 vector<AD<double> > USERFUNCTION(vector<AD<double> > x){ \ 233 return USERFUNCTION##NAMESPACE::generalized_symbol(x); \ 235 vector<AD<AD<double> > > USERFUNCTION(vector<AD<AD<double> > > x){ \ 236 return USERFUNCTION##NAMESPACE::generalized_symbol(x); \ 238 vector<AD<AD<AD<double> > > > USERFUNCTION(vector<AD<AD<AD<double> > > > x){ \ 239 return USERFUNCTION##NAMESPACE::generalized_symbol(x); \ 246 #endif // CPPAD_FRAMEWORK 248 #ifdef TMBAD_FRAMEWORK 266 template<
class Functor>
274 if ( (
size_t) x.size() != Tape.Domain() ) {
277 std::vector<Type> x_(x.data(), x.data() + x.size());
278 std::vector<Type> y_ = Tape(x_);
294 template<
class Functor>
297 #define NTHREADS config.nthreads 298 #define THREAD omp_get_thread_num() 303 std::vector< AtomicLocal<Functor> >* p_;
305 static std::vector< AtomicLocal<Functor> >* p =
306 new std::vector< AtomicLocal<Functor> > (NTHREADS, Functor() );
311 return ((*p_)[THREAD])(x);
317 #define REGISTER_ATOMIC(USERFUNCTION) \ 318 namespace USERFUNCTION##NAMESPACE { \ 319 template<class Type> \ 320 struct UserFunctor { \ 321 typedef Type ScalarType; \ 322 vector<Type> operator()(const vector<Type> &x) { \ 323 return USERFUNCTION(x); \ 327 vector<double> USERFUNCTION(const vector<double> &x) { \ 328 typedef USERFUNCTION##NAMESPACE::UserFunctor<double> Functor; \ 329 return atomic::AtomicGlobal<Functor>()(x); \ 331 vector<TMBad::ad_aug> USERFUNCTION(const vector<TMBad::ad_aug> &x) { \ 332 typedef USERFUNCTION##NAMESPACE::UserFunctor<TMBad::ad_aug> Functor; \ 333 return atomic::AtomicGlobal<Functor>()(x); \ 338 #endif // TMBAD_FRAMEWORK Vector class used by TMB.
For backwards compatibility with CppAD.
Namespace with special functions and derivatives.
Interoperability with other vector classes.
User interface to checkpointing using TMBad.