Sacado Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Sacado_trad2.hpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // Sacado Package
4 //
5 // Copyright 2006 NTESS and the Sacado contributors.
6 // SPDX-License-Identifier: LGPL-2.1-or-later
7 // *****************************************************************************
8 // @HEADER
9 
10 // Extension of the RAD package (Reverse Automatic Differentiation) --
11 // a package specialized for function and gradient evaluations -- to
12 // Hessian-vector products.
13 // Written in 2007 by David M. Gay at Sandia National Labs, Albuquerque, NM.
14 
15 #ifndef SACADO_TRAD2_H
16 #define SACADO_TRAD2_H
17 
18 #include "Sacado_ConfigDefs.h"
19 #include "Sacado_trad2_Traits.hpp"
20 
21 #include <stddef.h>
22 #include <Sacado_cmath.hpp>
23 
24 #if defined(RAD_DEBUG_BLOCKKEEP) && !defined(HAVE_SACADO_UNINIT)
25 #undef RAD_DEBUG_BLOCKKEEP
26 #endif
27 
28 #ifdef RAD_Const_WARN // ==> RAD_AUTO_AD_Const and RAD_DEBUG
29 #ifndef RAD_AUTO_AD_Const
30 #define RAD_AUTO_AD_Const
31 #endif
32 #ifndef RAD_DEBUG
33 #define RAD_DEBUG
34 #endif
35 extern "C" int RAD_Const_Warn(const void*);// outside any namespace for
36  // ease in setting breakpoints
37 #endif // RAD_Const_WARN
38 
39 #ifdef RAD_DEBUG
40 #include <cstdio>
41 #include <stdlib.h>
42 #endif
43 
44 #ifndef RAD_AUTO_AD_Const
45 #ifdef RAD_DEBUG_BLOCKKEEP
46 #include <complex> // must be here when SACADO_NAMESPACE is #defined
47 #endif
48 #endif
49 
50 namespace Sacado {
51 namespace Rad2 {
52 
53 // -DRAD_NO_USING_STDCC is needed, e.g., with Sun CC 5.7
54 #ifndef RAD_NO_USING_STDCC
55  // Bring math functions into scope
56  using std::exp;
57  using std::log;
58  using std::log10;
59  using std::sqrt;
60  using std::cos;
61  using std::sin;
62  using std::tan;
63  using std::acos;
64  using std::asin;
65  using std::atan;
66  using std::cosh;
67  using std::sinh;
68  using std::tanh;
69  using std::abs;
70  using std::fabs;
71  using std::atan2;
72  using std::pow;
73 #endif
74 
75 #ifdef RAD_AUTO_AD_Const
76 #undef RAD_DEBUG_BLOCKKEEP
77 #else
78 #ifdef RAD_DEBUG_BLOCKKEEP
79 #if !(RAD_DEBUG_BLOCKKEEP > 0)
80 #undef RAD_DEBUG_BLOCKKEEP
81 #else
82 extern "C" void _uninit_f2c(void *x, int type, long len);
83 
84 template <typename T>
85 struct UninitType {};
86 
87 template <>
88 struct UninitType<float> {
89  static const int utype = 4;
90 };
91 
92 template <>
93 struct UninitType<double> {
94  static const int utype = 5;
95 };
96 
97 template <typename T>
98 struct UninitType< std::complex<T> > {
99  static const int utype = UninitType<T>::utype + 2;
100 };
101 
102 #endif /*RAD_DEBUG_BLOCKKEEP > 0*/
103 #endif /*RAD_DEBUG_BLOCKKEEP*/
104 #endif /*RAD_AUTO_AD_Const*/
105 
107 
108  template<typename T> class
109 DoubleAvoid {
110  public:
111  typedef double dtype;
112  typedef T ttype;
113  };
114  template<> class
116  public:
119  };
120 
121 #define Dtype typename DoubleAvoid<Double>::dtype
122 #define Ttype typename DoubleAvoid<Double>::ttype
123 
124  template<typename Double> class IndepADvar;
125  template<typename Double> class ConstADvar;
126  template<typename Double> class ConstADvari;
127  template<typename Double> class ADvar;
128  template<typename Double> class ADvar1;
129  template<typename Double> class ADvar1g;
130  template<typename Double> class ADvar1s;
131  template<typename Double> class ADvar2;
132  template<typename Double> class ADvar2g;
133  template<typename Double> class ADvar2q;
134  template<typename Double> class ADvari;
135  template<typename Double> class ADvari_block;
136  template<typename Double> class ADvarn;
137  template<typename Double> class Derp;
138 
139  template<typename Double> struct
140 ADmemblock { // We get memory in ADmemblock chunks and never give it back,
141  // but reuse it once computations start anew after call(s) on
142  // ADcontext::Gradcomp() or ADcontext::Weighted_Gradcomp().
144  Double memblk[2000];
145  };
146 
147  template<typename Double> class
148 ADvari_block {
149  public:
151  enum { Gulp = 1021 };
153  ADVari **limit;
154  ADVari *pADvari[Gulp];
155  };
156 
157  template<typename Double> class
158 ADcontext { // A singleton class: one instance in radops.c
169  ADMemblock *Busy, *Free;
170  char *Mbase;
171  size_t Mleft;
172  ADVari **Ailimit, **Ainext;
173  ADVari_block *Aibusy, *Aifree;
174  ADMemblock *First;
175  ADVari_block *AiFirst;
176  double First0[(sizeof(ADMemblock) + sizeof(double) - 1) / sizeof(double)];
177  double First1[(sizeof(ADVari_block) + sizeof(double) - 1) / sizeof(double)];
178  void *new_ADmemblock(size_t);
179  void new_ADvari_block();
184 #ifdef RAD_DEBUG_BLOCKKEEP
185  int rad_busy_blocks;
186  ADMemblock *rad_Oldcurmb;
187 #endif
188  public:
189  static const Double One, negOne;
190  ADcontext();
191  void *Memalloc(size_t len);
192  static void Gradcomp(int wantgrad);
193  static void Hvprod(int, ADVar**, Double*, Double*);
194  static void aval_reset(void);
195  static void Weighted_Gradcomp(int, ADVar**, Double*);
196  static inline void Gradcomp() { Gradcomp(1); }
197  inline void ADvari_record(ADVari *x) {
198  if (Ainext >= Ailimit)
199  new_ADvari_block();
200  *Ainext++ = x;
201  }
202  };
203 
204  template<typename Double> class
205 CADcontext: public ADcontext<Double> { // for possibly constant ADvar values
206  protected:
208  public:
209  friend class ADvar<Double>;
210  CADcontext(): ADcontext<Double>() { fpval_implies_const = false; }
211  };
212 
213  template<typename Double> class
214 Derp { // one derivative-propagation operation
215  public:
216  friend class ADvarn<Double>;
218  static Derp *LastDerp;
220  const Double *a;
221  const ADVari *b;
222  mutable ADVari *c;
223  Derp(){};
224  Derp(const ADVari *);
225  Derp(const Double *, const ADVari *);
226  Derp(const Double *, const ADVari *, const ADVari *);
227  /* c->aval += a * b->aval; */
228  };
229 
230 
231 // Now we use #define to overcome bad design in the C++ templating system
232 
233 #define Ai const ADvari<Double>&
234 #define AI const IndepADvar<Double>&
235 #define T template<typename Double>
236 #define D Double
237 #define T1(f) \
238 T F f (AI); \
239 T F f (Ai);
240 #define T2(r,f) \
241  T r f(Ai,Ai); \
242  T r f(Ai,D); \
243  T r f(Ai,Dtype); \
244  T r f(Ai,long); \
245  T r f(Ai,int); \
246  T r f(D,Ai); \
247  T r f(Dtype,Ai); \
248  T r f(long,Ai); \
249  T r f(int,Ai); \
250  T r f(AI,D); \
251  T r f(AI,Dtype); \
252  T r f(AI,long); \
253  T r f(AI,int); \
254  T r f(D,AI); \
255  T r f(Dtype,AI); \
256  T r f(long,AI); \
257  T r f(int,AI); \
258  T r f(Ai,AI);\
259  T r f(AI,Ai);\
260  T r f(AI,AI);
261 
262 #define F ADvari<Double>&
263 T2(F, operator+)
264 T2(F, operator-)
265 T2(F, operator*)
266 T2(F, operator/)
267 T2(F, atan2)
268 T2(F, pow)
269 T2(F, max)
270 T2(F, min)
271 T2(int, operator<)
272 T2(int, operator<=)
273 T2(int, operator==)
274 T2(int, operator!=)
275 T2(int, operator>=)
276 T2(int, operator>)
277 T1(operator+)
278 T1(operator-)
279 T1(abs)
280 T1(acos)
281 T1(acosh)
282 T1(asin)
283 T1(asinh)
284 T1(atan)
285 T1(atanh)
286 T1(cos)
287 T1(cosh)
288 T1(exp)
289 T1(log)
290 T1(log10)
291 T1(sin)
292 T1(sinh)
293 T1(sqrt)
294 T1(tan)
295 T1(tanh)
296 T1(fabs)
297 
298 T F copy(AI);
299 T F copy(Ai);
300 
301 #undef F
302 #undef T2
303 #undef T1
304 #undef D
305 #undef T
306 #undef AI
307 #undef Ai
308 
309 } /* namespace Rad2 */
310 } /* namespace Sacado */
311 #define SNS Sacado::Rad2
312 namespace std { // Moved here from bottom for use in testing nesting of Rad with itself.
313  using SNS::exp;
314  using SNS::log;
315  using SNS::log10;
316  using SNS::sqrt;
317  using SNS::cos;
318  using SNS::sin;
319  using SNS::tan;
320  using SNS::acos;
321  using SNS::asin;
322  using SNS::atan;
323  using SNS::cosh;
324  using SNS::sinh;
325  using SNS::tanh;
326  using SNS::abs;
327  using SNS::fabs;
328  using SNS::atan2;
329  using SNS::pow;
330 }
331 #undef SNS
332 namespace Sacado {
333 namespace Rad2 {
334 
335  template<typename Double>ADvari<Double>& ADf1(Double f, Double g, const IndepADvar<Double> &x);
336  template<typename Double>ADvari<Double>& ADf2(Double f, Double gx, Double gy,
337  const IndepADvar<Double> &x, const IndepADvar<Double> &y);
338  template<typename Double>ADvari<Double>& ADfn(Double f, int n,
339  const IndepADvar<Double> *x, const Double *g);
340 
341  template<typename Double> IndepADvar<Double>& ADvar_operatoreq(IndepADvar<Double>*,
342  const ADvari<Double>&);
343  template<typename Double> ADvar<Double>& ADvar_operatoreq(ADvar<Double>*, const ADvari<Double>&);
344  template<typename Double> void AD_Const(const IndepADvar<Double>&);
345  template<typename Double> void AD_Const1(Double*, const IndepADvar<Double>&);
346  template<typename Double> ADvari<Double>& ADf1(Double, Double, const ADvari<Double>&);
347  template<typename Double> ADvari<Double>& ADf2(Double, Double, Double,
348  const ADvari<Double>&, const ADvari<Double>&);
349  template<typename Double> ADvari<Double>& ADf2(Double, Double, Double,
350  const IndepADvar<Double>&, const ADvari<Double>&);
351  template<typename Double> ADvari<Double>& ADf2(Double, Double, Double,
352  const ADvari<Double>&, const IndepADvar<Double>&);
353  template<typename Double> Double val(const ADvari<Double>&);
354 
367  };
368 
369  template<typename Double> ADvari<Double>&
370 ADf1(Double f, Double g, Double h, const ADvari<Double> &x);
371 
372  template<typename Double> ADvari<Double>&
373 ADf2(Double f, Double gx, Double gy, Double hxx,
374  Double hxy, Double hyy, const ADvari<Double> &x, const ADvari<Double> &y);
375 
376  template<typename Double> ADvari<Double>&
377 ADfn(Double f, int n, const IndepADvar<Double> *x, const Double *g, const Double *h);
378 
379  template<typename Double> class
380 ADvari { // implementation of an ADvar
381  public:
385 #ifdef RAD_AUTO_AD_Const
386  friend class IndepADvar<Double>;
387 #ifdef RAD_Const_WARN
388  mutable const IndepADVar *padv;
389 #else
390  protected:
391  mutable const IndepADVar *padv;
392 #endif //RAD_Const_WARN
393  private:
394  ADvari *Next;
395  static ADvari *First_ADvari, **Last_ADvari;
396  public:
397  inline void ADvari_padv(const IndepADVar *v) {
398  *Last_ADvari = this;
399  Last_ADvari = &this->Next;
400  this->padv = v;
401  }
402 #endif //RAD_AUTO_AD_Const
403 #ifdef RAD_DEBUG
404  int gcgen;
405  int opno;
406  static int gcgen_cur, last_opno, zap_gcgen, zap_gcgen1, zap_opno;
407  static FILE *debug_file;
408 #endif
411  Double Val; // result of this operation
412  mutable Double aval; // adjoint -- partial of final result w.r.t. this Val
413  mutable Double dO; // deriv of op w.r.t. t in x + t*p
414  mutable Double aO; // adjoint (in Hv computation) of op
415  mutable Double adO; // adjoint (in Hv computation) of dO
416  void *operator new(size_t len) {
417 #ifdef RAD_DEBUG
418  ADvari *rv = (ADvari*)ADvari::adc.Memalloc(len);
419  rv->gcgen = gcgen_cur;
420  rv->opno = ++last_opno;
421  if (last_opno == zap_opno && gcgen_cur == zap_gcgen)
422  printf("");
423  return rv;
424 #else
425  return ADvari::adc.Memalloc(len);
426 #endif
427  }
428  void operator delete(void*) {} /*Should never be called.*/
429  inline ADvari(Advari_Opclass oc, Double t):
430  opclass(oc), Val(t), aval(0.), dO(0.)
431  { if (oc != Hv_const) ADvari::adc.ADvari_record(this); }
432  inline ADvari(Advari_Opclass oc, Double t, Double ta):
433  opclass(oc), Val(t), aval(ta), dO(0.)
434  { if (oc != Hv_const) ADvari::adc.ADvari_record(this); }
435  private:
436  inline ADvari(): Val(0.), aval(0.), dO(0.) {} // prevent construction without value (?)
437  public:
438  friend class ConstADvari<Double>;
439 #ifdef RAD_AUTO_AD_Const
440  friend class ADcontext<Double>;
441  friend class ADvar<Double>;
442  friend class ADvar1<Double>;
443  friend class ADvar1s<Double>;
444  friend class ADvar2<Double>;
445  friend class ADvar2q<Double>;
446  friend class ConstADvar<Double>;
447  ADvari(const IndepADVar *, Double);
448  ADvari(const IndepADVar *, Double, Double);
449  ADvari(const IndepADVar *, Double, Double, int);
450 #endif
451 #define F friend
452 #define R ADvari&
453 #define Ai const ADvari&
454 #define T1(r,f) F r f <>(Ai);
455 #define T2(r,f) \
456 F r f <>(Ai,Ai); \
457 F r f <>(Ttype,Ai); \
458 F r f <>(Ai,Ttype); \
459 F r f <>(double,Ai); \
460 F r f <>(Ai,double); \
461 F r f <>(long,Ai); \
462 F r f <>(Ai,long); \
463 F r f <>(int,Ai); \
464 F r f <>(Ai,int);
465  T1(R,operator+)
466  T2(R,operator+)
467  T1(R,operator-)
468  T2(R,operator-)
469  T2(R,operator*)
470  T2(R,operator/)
471  T1(R,abs)
472  T1(R,acos)
473  T1(R,acosh)
474  T1(R,asin)
475  T1(R,asinh)
476  T1(R,atan)
477  T1(R,atanh)
478  T2(R,atan2)
479  T2(R,max)
480  T2(R,min)
481  T1(R,cos)
482  T1(R,cosh)
483  T1(R,exp)
484  T1(R,log)
485  T1(R,log10)
486  T2(R,pow)
487  T1(R,sin)
488  T1(R,sinh)
489  T1(R,sqrt)
490  T1(R,tan)
491  T1(R,tanh)
492  T1(R,fabs)
493  T1(R,copy)
494  T2(int,operator<)
495  T2(int,operator<=)
496  T2(int,operator==)
497  T2(int,operator!=)
498  T2(int,operator>=)
499  T2(int,operator>)
500 #undef T2
501 #undef T1
502 #undef Ai
503 #undef R
504 #undef F
505 
506  friend ADvari& ADf1<>(Double f, Double g, Double h, const ADvari &x);
507  friend ADvari& ADf2<>(Double f, Double gx, Double gy, Double hxx,
508  Double hxy, Double hyy, const ADvari &x, const ADvari &y);
509  friend ADvari& ADfn<>(Double f, int n, const IndepADVar *x,
510  const Double *g, const Double *h);
511 
512  inline operator Double() { return this->Val; }
513  inline operator Double() const { return this->Val; }
514  };
515 
516  template<typename Double> class
517 ADvar1: public ADvari<Double> { // simplest unary ops
518  public:
521  ADvar1(Advari_Opclass oc, Double val1, const Double *a1, const ADVari *c1):
522  ADVari(oc,val1), d(a1,this,c1) {}
523 #ifdef RAD_AUTO_AD_Const
524  typedef typename ADVari::IndepADVar IndepADVar;
525  typedef ADvar<Double> ADVar;
526  ADvar1(const IndepADVar*, const IndepADVar&);
527  ADvar1(const IndepADVar*, const ADVari&);
528  ADvar1(Advari_Opclass oc, const Double val1, const Double *a1,
529  const ADVari *c1, const ADVar *v):
530  ADVari(oc,val1), d(a1,this,c1) {
531  c1->padv = 0;
532  this->ADvari_padv(v);
533  }
534 #endif
535  };
536 
537 
538  template<typename Double> class
539 ConstADvari: public ADvari<Double> {
540  private:
542  ConstADvari() {}; // prevent construction without value (?)
543  static ConstADvari *lastcad;
544  public:
548  inline void *operator new(size_t len) { return ConstADvari::cadc.Memalloc(len); }
549  inline ConstADvari(Double t): ADVari(Hv_copy, t) { prevcad = lastcad; lastcad = this; }
550  static void aval_reset(void);
551  };
552 
553 
554  template<typename Double> class
555 IndepADvar { // an independent ADvar
556  private:
558  /* private to prevent assignment */
559 #ifdef RAD_AUTO_AD_Const
560  if (cv)
561  cv->padv = 0;
562  return new ADvar1<Double>(this,x);
563 #elif defined(RAD_EQ_ALIAS)
564  this->cv = x.cv;
565  return *this;
566 #else
567  return ADvar_operatoreq(this,*x.cv);
568 #endif //RAD_AUTO_AD_Const
569  }
570  protected:
571  static void AD_Const(const IndepADvar&);
572  mutable ADvari<Double> *cv;
573  public:
575  friend class ADvar<Double>;
576  friend class ADcontext<Double>;
577  friend class ADvar1<Double>;
578  friend class ADvarn<Double>;
581  IndepADvar(Ttype);
582  IndepADvar(double);
583  IndepADvar(int);
584  IndepADvar(long);
585  IndepADvar& operator= (Double);
586 #ifdef RAD_AUTO_AD_Const
587  friend IndepADvar& ADvar_operatoreq<>(IndepADvar*, const ADVari&);
588  inline IndepADvar(const IndepADvar &x) { cv = x.cv ? new ADvar1<Double>(this, x) : 0; };
589  inline IndepADvar(ADVari *ncv) { cv = ncv; }
590  inline IndepADvar() { cv = 0; }
591  inline ~IndepADvar() {
592  if (cv)
593  cv->padv = 0;
594  }
595 #else
596  inline IndepADvar() {
597 #ifndef RAD_EQ_ALIAS
598  cv = 0;
599 #endif
600  }
601  inline ~IndepADvar() {}
602  friend IndepADvar& ADvar_operatoreq<>(IndepADvar*, const ADVari&);
603 #endif
604 
605 #ifdef RAD_Const_WARN
606  inline operator ADVari&() const {
607  ADVari *tcv = this->cv;
608  if (tcv->opno < 0)
609  RAD_Const_Warn(tcv);
610  return *tcv;
611  }
612  inline operator ADVari*() const {
613  ADVari *tcv = this->cv;
614  if (tcv->opno < 0)
615  RAD_Const_Warn(tcv);
616  return tcv;
617  }
618 #else //RAD_Const_WARN
619  inline operator ADVari&() const { return *this->cv; }
620  inline operator ADVari*() const { return this->cv; }
621 #endif //RAD_Const_WARN
622 
623  Double val() const { return cv->Val; }
624  Double adj() const { return cv->aval; }
625 
626  friend void AD_Const1<>(Double*, const IndepADvar&);
627 
628  friend ADVari& ADf1<>(Double, Double, const IndepADvar&);
629  friend ADVari& ADf2<>(Double, Double, Double, const IndepADvar&, const IndepADvar&);
630  friend ADVari& ADf2<>(Double, Double, Double, const ADVari&, const IndepADvar&);
631  friend ADVari& ADf2<>(Double, Double, Double, const IndepADvar&, const ADVari&);
632 
633  static inline void Gradcomp(int wantgrad)
634  { ADcontext<Double>::Gradcomp(wantgrad); }
635  static inline void Gradcomp()
637  static inline void Hvprod(int n, ADVar **vp, Double *v, Double *hv)
638  { ADcontext<Double>::Hvprod(n, vp, v, hv); }
639  static inline void aval_reset() { ConstADvari<Double>::aval_reset(); }
640  static inline void Weighted_Gradcomp(int n, ADVar **v, Double *w)
642 
643  /* We use #define to deal with bizarre templating rules that apparently */
644  /* require us to spell the some conversion explicitly */
645 
646 
647 #define Ai const ADVari&
648 #define AI const IndepADvar&
649 #define D Double
650 #define T2(r,f) \
651  r f <>(AI,AI);\
652  r f <>(Ai,AI);\
653  r f <>(AI,Ai);\
654  r f <>(Ttype,AI);\
655  r f <>(double,AI);\
656  r f <>(long,AI);\
657  r f <>(int,AI);\
658  r f <>(AI,Ttype);\
659  r f <>(AI,double);\
660  r f <>(AI,long);\
661  r f <>(AI,int);
662 #define T1(f) friend ADVari& f<> (AI);
663 
664 #define F friend ADVari&
665 T2(F, operator+)
666 T2(F, operator-)
667 T2(F, operator*)
668 T2(F, operator/)
669 T2(F, atan2)
670 T2(F, max)
671 T2(F, min)
672 T2(F, pow)
673 #undef F
674 #define F friend int
675 T2(F, operator<)
676 T2(F, operator<=)
677 T2(F, operator==)
678 T2(F, operator!=)
679 T2(F, operator>=)
680 T2(F, operator>)
681 
682 T1(operator+)
683 T1(operator-)
684 T1(abs)
685 T1(acos)
686 T1(acosh)
687 T1(asin)
688 T1(asinh)
689 T1(atan)
690 T1(atanh)
691 T1(cos)
692 T1(cosh)
693 T1(exp)
694 T1(log)
695 T1(log10)
696 T1(sin)
697 T1(sinh)
698 T1(sqrt)
699 T1(tan)
700 T1(tanh)
701 T1(fabs)
702 T1(copy)
703 
704 #undef F
705 #undef T1
706 #undef T2
707 #undef D
708 #undef AI
709 #undef Ai
710 
711  };
712 
713  template<typename Double> class
714 ADvar: public IndepADvar<Double> { // an "active" variable
715  public:
717  template <typename U> struct apply { typedef ADvar<U> type; };
718 
722  private:
723  void ADvar_ctr(Double d) {
724  ADVari *x;
725  if (ConstADVari::cadc.fpval_implies_const)
726  x = new ConstADVari(d);
727  else {
728 #ifdef RAD_AUTO_AD_Const
729  x = new ADVari((IndepADVar*)this, d);
730  x->ADvari_padv(this);
731 #else
732  x = new ADVari(Hv_const, d);
733 #endif
734  }
735  this->cv = x;
736  }
737  public:
738  friend class ADvar1<Double>;
740  ADvar() { /* cv = 0; */ }
741  ADvar(Ttype d) { ADvar_ctr(d); }
742  ADvar(double i) { ADvar_ctr(Double(i)); }
743  ADvar(int i) { ADvar_ctr(Double(i)); }
744  ADvar(long i) { ADvar_ctr(Double(i)); }
745  inline ~ADvar() {}
746 #ifdef RAD_AUTO_AD_Const
747  ADvar(IndepADVar &x) {
748  this->cv = x.cv ? new ADVar1(this, x) : 0;
749  }
750  ADvar(ADVari &x) :IndepADVar(&x) { x.ADvari_padv((IndepADVar*)this);}
751  inline ADvar& operator=(IndepADVar &x) {
752  if (this->cv)
753  this->cv->padv = 0;
754  this->cv = new ADVar1(this,x);
755  return *this;
756  }
757  inline ADvar& operator=(ADVari &x) {
758  if (this->cv)
759  this->cv->padv = 0;
760  this->cv = new ADVar1(this, x);
761  return *this;
762  }
763 #else
764  friend ADvar& ADvar_operatoreq<>(ADvar*, const ADVari&);
765 #ifdef RAD_EQ_ALIAS
766  /* allow aliasing v and w after "v = w;" */
767  inline ADvar(const IndepADVar &x) { this->cv = (ADVari*)x.cv; }
768  inline ADvar(const ADVari &x) { this->cv = (ADVari*)&x; }
769  inline ADvar& operator=(IndepADVar &x) { this->cv = (ADVari*)x.cv; return *this; }
770  inline ADvar& operator=(const ADVari &x) { this->cv = (ADVari*)&x; return *this; }
771 #else
772  friend ADvar& ADvar_operatoreq<>(ADvar*, const ADVari&);
773  ADvar(const IndepADVar &x) { this->cv = x.cv ? new ADVar1(x.cv->Val, &this->cv->adc.One, x.cv) : 0; }
774  ADvar(const ADvar&x) { this->cv = x.cv ?
775  new ADVar1(Hv_copy, x.cv->Val, &this->cv->adc.One, (ADVari*)x.cv) : 0; }
776  ADvar(const ADVari &x) { this->cv = new ADVar1(Hv_copy, x.Val, &this->cv->adc.One, &x); }
777  inline ADvar& operator=(IndepADVar &x) { return ADvar_operatoreq(this,*x.cv); };
778  inline ADvar& operator=(const ADVari &x) { return ADvar_operatoreq(this,x); };
779 #endif /* RAD_EQ_ALIAS */
780 #endif /* RAD_AUTO_AD_Const */
781  ADvar& operator=(Double);
782  ADvar& operator+=(const ADVari&);
783  ADvar& operator+=(Double);
784  ADvar& operator-=(const ADVari&);
785  ADvar& operator-=(Double);
786  ADvar& operator*=(const ADVari&);
787  ADvar& operator*=(Double);
788  ADvar& operator/=(const ADVari&);
789  ADvar& operator/=(Double);
790  inline static bool get_fpval_implies_const(void)
791  { return ConstADVari::cadc.fpval_implies_const; }
792  inline static void set_fpval_implies_const(bool newval)
793  { ConstADVari::cadc.fpval_implies_const = newval; }
794  inline static bool setget_fpval_implies_const(bool newval) {
795  bool oldval = ConstADVari::cadc.fpval_implies_const;
796  ConstADVari::cadc.fpval_implies_const = newval;
797  return oldval;
798  }
799  static inline void Gradcomp(int wantgrad)
800  { ADcontext<Double>::Gradcomp(wantgrad); }
801  static inline void Gradcomp()
803  static inline void aval_reset() { ConstADVari::aval_reset(); }
804  static inline void Weighted_Gradcomp(int n, ADvar **v, Double *w)
806  };
807 
808 template<typename Double>
809  inline void AD_Const1(Double *notused, const IndepADvar<Double>&v)
811 
812 template<typename Double>
813  inline void AD_Const(const IndepADvar<Double>&v) { AD_Const1((Double*)0, v); }
814 
815  template<typename Double> class
816 ConstADvar: public ADvar<Double> {
817  public:
819  typedef typename ADVar::ADVari ADVari;
820  typedef typename ADVar::ConstADVari ConstADVari;
822  typedef typename ADVar::IndepADVar IndepADVar;
823  private: // disable op=
824  ConstADvar& operator+=(ADVari&);
825  ConstADvar& operator+=(Double);
826  ConstADvar& operator-=(ADVari&);
827  ConstADvar& operator-=(Double);
828  ConstADvar& operator*=(ADVari&);
829  ConstADvar& operator*=(Double);
830  ConstADvar& operator/=(ADVari&);
831  ConstADvar& operator/=(Double);
832  void ConstADvar_ctr(Double);
833  public:
834  ConstADvar(Ttype d) { ConstADvar_ctr(d); }
835  ConstADvar(double i) { ConstADvar_ctr(Double(i)); }
836  ConstADvar(int i) { ConstADvar_ctr(Double(i)); }
837  ConstADvar(long i) { ConstADvar_ctr(Double(i)); }
838  ConstADvar(const IndepADVar&);
839  ConstADvar(const ConstADvar&);
840  ConstADvar(const ADVari&);
841  inline ~ConstADvar() {}
842 #ifdef RAD_NO_CONST_UPDATE
843  private:
844 #endif
845  ConstADvar();
846  inline ConstADvar& operator=(Double d) { this->cv->Val = d; return *this; }
847  inline ConstADvar& operator=(ADVari& d) { this->cv->Val = d.Val; return *this; }
848  };
849 
850  template<typename Double> class
851 ADvar1s: public ADvar1<Double> { // unary ops with partials
852  public:
854  typedef typename ADVar1::ADVari ADVari;
855  Double pL; // deriv of op w.r.t. left operand L
856  ADvar1s(Double val1, Double a1, const ADVari *c1):
857  ADVar1(Hv_timesL,val1,&pL,c1), pL(a1) {}
858 #ifdef RAD_AUTO_AD_Const
859  Double a;
860  typedef typename ADVar1::ADVar ADVar;
861  ADvar1s(Double val1, Double a1, const ADVari *c1, const ADVar *v):
862  ADVar1(Hv_timesL,val1,&a,c1,v), a(a1) {}
863 #endif
864  };
865 
866  template<typename Double> class
867 ADvar1g: public ADvar1<Double> { // unary ops with partials
868  public:
870  typedef typename ADVar1::ADVari ADVari;
871  Double pL; // deriv of op w.r.t. left operand L
872  Double pL2; // partial of op w.r.t. L,L
873  ADvar1g(Double val1, Double d1, Double d2, const ADVari *c1):
874  ADVar1(Hv_unary,val1,&pL,c1), pL(d1), pL2(d2) {}
875  };
876 
877  template<typename Double> class
878 ADvar2: public ADvari<Double> { // basic binary ops
879  public:
882  DErp dL, dR;
883  ADvar2(Advari_Opclass oc, Double val1, const ADVari *Lcv, const Double *Lc,
884  const ADVari *Rcv, const Double *Rc):
885  ADVari(oc,val1) {
886  dR.next = DErp::LastDerp;
887  dL.next = &dR;
888  DErp::LastDerp = &dL;
889  dL.a = Lc;
890  dL.c = (ADVari*)Lcv;
891  dR.a = Rc;
892  dR.c = (ADVari*)Rcv;
893  dL.b = dR.b = this;
894  }
895 #ifdef RAD_AUTO_AD_Const
896  typedef ADvar<Double> ADVar;
897  ADvar2(Advari_Opclass oc, Double val1, const ADVari *Lcv, const Double *Lc,
898  const ADVari *Rcv, const Double *Rc, ADVar *v):
899  ADVari(oc,val1) {
900  dR.next = DErp::LastDerp;
901  dL.next = &dR;
902  DErp::LastDerp = &dL;
903  dL.a = Lc;
904  dL.c = Lcv;
905  dR.a = Rc;
906  dR.c = Rcv;
907  dL.b = dR.b = this;
908  Lcv->padv = 0;
909  this->ADvari_padv(v);
910  }
911 #endif
912  };
913 
914  template<typename Double> class
915 ADvar2q: public ADvar2<Double> { // binary ops with partials
916  public:
918  typedef typename ADVar2::ADVari ADVari;
919  typedef typename ADVar2::DErp DErp;
920  Double pL; // deriv of op w.r.t. left operand L
921  Double pR; // deriv of op w.r.t. right operand R
922  Double pLR; // second partial w.r.t. L,R
923  Double pR2; // second partial w.r.t. R,R
924  ADvar2q(Double val1, Double Lp, Double Rp, Double LR, Double R2,
925  const ADVari *Lcv, const ADVari *Rcv):
926  ADVar2(Hv_quotLR,val1,Lcv,&pL,Rcv,&pR),
927  pL(Lp), pR(Rp), pLR(LR), pR2(R2) {}
928 #ifdef RAD_AUTO_AD_Const
929  typedef typename ADVar2::ADVar ADVar;
930  ADvar2q(Double val1, Double Lp, Double Rp, Double LR, Double R2,
931  const ADVari *Lcv, const ADVari *Rcv, const ADVar *v):
932  ADVar2(Hv_quotLR,val1,Lcv,&pL,Rcv,&pR,v),
933  pL(Lp), pR(Rp), pLR(LR), pR2(R2) {}
934 #endif
935  };
936 
937  template<typename Double> class
938 ADvar2g: public ADvar2<Double> { // general binary ops with partials
939  public:
941  typedef typename ADVar2::ADVari ADVari;
942  Double pL; // deriv of op w.r.t. left operand L
943  Double pR; // deriv of op w.r.t. right operand R
944  Double pL2; // second partial w.r.t. L,L
945  Double pLR; // second partial w.r.t. L,R
946  Double pR2; // second partial w.r.t. R,R
947  ADvar2g(Double val1, Double Lp, Double Rp, Double L2, Double LR, Double R2,
948  const ADVari *Lcv, const ADVari *Rcv):
949  ADVar2(Hv_binary,val1,Lcv,&pL,Rcv,&pR),
950  pL(Lp), pR(Rp), pL2(L2), pLR(LR), pR2(R2) { }
951  };
952 
953  template<typename Double> class
954 ADvarn: public ADvari<Double> { // n-ary ops with partials g and
955  // 2nd partials h (lower triangle, rowwise)
956  public:
959  typedef typename ADVari::IndepADVar IndepADVar;
961  int n;
962  Double *G, *H;
963  DErp *D;
964  ADvarn(Double val1, int n1, const IndepADVar *x, const Double *g, const Double *h):
965  ADVari(Hv_nary,val1), n(n1) {
966  DErp *d1, *dlast;
967  Double *a1;
968  int i, nh;
969 
970  a1 = G = (Double*)ADVari::adc.Memalloc(n1*sizeof(*g));
971  d1 = D = (DErp*)ADVari::adc.Memalloc(n1*sizeof(DErp));
972  dlast = DErp::LastDerp;
973  for(i = 0; i < n1; i++, d1++) {
974  d1->next = dlast;
975  dlast = d1;
976  a1[i] = g[i];
977  d1->a = &a1[i];
978  d1->b = this;
979  d1->c = x[i].cv;
980  }
981  DErp::LastDerp = dlast;
982  nh = (n1*(n1+1)) >> 1;
983  a1 = H = (double*)ADVari::adc.Memalloc(nh * sizeof(*h));
984  for(i = 0; i < nh; i++)
985  a1[i] = h[i];
986  }
987  };
988 
989 template<typename Double>
990  inline ADvari<Double>& operator+(const ADvari<Double> &T) { return *(ADvari<Double>*)&T; }
991 
992 template<typename Double>
993  inline int operator<(const ADvari<Double> &L, const ADvari<Double> &R) { return L.Val < R.Val; }
994 template<typename Double>
995  inline int operator<(const ADvari<Double> &L, Double R) { return L.Val < R; }
996 template<typename Double>
997  inline int operator<(Double L, const ADvari<Double> &R) { return L < R.Val; }
998 
999 template<typename Double>
1000  inline int operator<=(const ADvari<Double> &L, const ADvari<Double> &R) { return L.Val <= R.Val; }
1001 template<typename Double>
1002  inline int operator<=(const ADvari<Double> &L, Double R) { return L.Val <= R; }
1003 template<typename Double>
1004  inline int operator<=(Double L, const ADvari<Double> &R) { return L <= R.Val; }
1005 
1006 template<typename Double>
1007  inline int operator==(const ADvari<Double> &L, const ADvari<Double> &R) { return L.Val == R.Val; }
1008 template<typename Double>
1009  inline int operator==(const ADvari<Double> &L, Double R) { return L.Val == R; }
1010 template<typename Double>
1011  inline int operator==(Double L, const ADvari<Double> &R) { return L == R.Val; }
1012 
1013 template<typename Double>
1014  inline int operator!=(const ADvari<Double> &L, const ADvari<Double> &R) { return L.Val != R.Val; }
1015 template<typename Double>
1016  inline int operator!=(const ADvari<Double> &L, Double R) { return L.Val != R; }
1017 template<typename Double>
1018  inline int operator!=(Double L, const ADvari<Double> &R) { return L != R.Val; }
1019 
1020 template<typename Double>
1021  inline int operator>=(const ADvari<Double> &L, const ADvari<Double> &R) { return L.Val >= R.Val; }
1022 template<typename Double>
1023  inline int operator>=(const ADvari<Double> &L, Double R) { return L.Val >= R; }
1024 template<typename Double>
1025  inline int operator>=(Double L, const ADvari<Double> &R) { return L >= R.Val; }
1026 
1027 template<typename Double>
1028  inline int operator>(const ADvari<Double> &L, const ADvari<Double> &R) { return L.Val > R.Val; }
1029 template<typename Double>
1030  inline int operator>(const ADvari<Double> &L, Double R) { return L.Val > R; }
1031 template<typename Double>
1032  inline int operator>(Double L, const ADvari<Double> &R) { return L > R.Val; }
1033 
1034 template<typename Double>
1035  inline void *ADcontext<Double>::Memalloc(size_t len) {
1036  if (Mleft >= len)
1037  return Mbase + (Mleft -= len);
1038  return new_ADmemblock(len);
1039  }
1040 
1041 template<typename Double>
1042  inline Derp<Double>::Derp(const ADVari *c1): c((ADVari*)c1) {
1043  next = LastDerp;
1044  LastDerp = this;
1045  }
1046 
1047 template<typename Double>
1048  inline Derp<Double>::Derp(const Double *a1, const ADVari *c1): a(a1), c((ADVari*)c1) {
1049  next = LastDerp;
1050  LastDerp = this;
1051  }
1052 
1053 template<typename Double>
1054  inline Derp<Double>::Derp(const Double *a1, const ADVari *b1, const ADVari *c1):
1055  a(a1), b(b1), c((ADVari*)c1) {
1056  next = LastDerp;
1057  LastDerp = this;
1058  }
1059 
1060 /**** radops ****/
1061 
1062 template<typename Double> Derp<Double> *Derp<Double>::LastDerp = 0;
1063 template<typename Double> ADcontext<Double> ADvari<Double>::adc;
1064 template<typename Double> const Double ADcontext<Double>::One = 1.;
1065 template<typename Double> const Double ADcontext<Double>::negOne = -1.;
1066 template<typename Double> CADcontext<Double> ConstADvari<Double>::cadc;
1067 template<typename Double> ConstADvari<Double> *ConstADvari<Double>::lastcad;
1068 
1069 #ifdef RAD_AUTO_AD_Const
1070 template<typename Double> ADvari<Double>* ADvari<Double>::First_ADvari;
1072 #endif
1073 
1074 #ifdef RAD_DEBUG
1075 #ifndef RAD_DEBUG_gcgen1
1076 #define RAD_DEBUG_gcgen1 -1
1077 #endif
1078 template<typename Double> int ADvari<Double>::gcgen_cur;
1079 template<typename Double> int ADvari<Double>::last_opno;
1080 template<typename Double> int ADvari<Double>::zap_gcgen;
1081 template<typename Double> int ADvari<Double>::zap_gcgen1 = RAD_DEBUG_gcgen1;
1082 template<typename Double> int ADvari<Double>::zap_opno;
1083 template<typename Double> FILE *ADvari<Double>::debug_file;
1084 #endif
1085 
1086 
1087  template<typename Double>
1089 {
1090  ADVari_block *fb;
1091 
1092  First = (ADMemblock*)First0;
1093  First->next = 0;
1094  Busy = First;
1095  Free = 0;
1096  Mbase = (char*)First->memblk;
1097  Mleft = sizeof(First->memblk);
1098  AiFirst = Aibusy = fb = (ADVari_block*)First1;
1099  Aifree = 0;
1100  Ainext = fb->pADvari;
1101  fb->next = fb->prev = 0;
1102  fb->limit = Ailimit = fb->pADvari + ADVari_block::Gulp;
1103  rad_need_reinit = 0;
1104 #ifdef RAD_DEBUG_BLOCKKEEP
1105  rad_busy_blocks = 0;
1106  rad_mleft_save = 0;
1107  rad_Oldcurmb = 0;
1108 #endif
1109  }
1110 
1111 template<typename Double> void*
1113 {
1114  ADMemblock *mb, *mb0, *mb1, *mbf, *x;
1115  ADVari_block *b;
1116 #ifdef RAD_AUTO_AD_Const
1117  ADVari *a, *anext;
1118  IndepADvar<Double> *v;
1119 #ifdef RAD_Const_WARN
1120  ADVari *cv;
1121  int i, j;
1122 #endif
1123 #endif /*RAD_AUTO_AD_Const*/
1124 
1125  if ((rad_need_reinit & 1) && this == &ADVari::adc) {
1126  rad_need_reinit &= ~1;
1127  DErp::LastDerp = 0;
1128  Aibusy = b = AiFirst;
1129  Aifree = b->next;
1130  b->next = b->prev = 0;
1131  Ailimit = b->limit = (Ainext = b->pADvari) + ADVari_block::Gulp;
1132 #ifdef RAD_DEBUG_BLOCKKEEP
1133  Mleft = rad_mleft_save;
1134  if (Mleft < sizeof(First->memblk))
1135  _uninit_f2c(Mbase + Mleft,
1136  UninitType<Double>::utype,
1137  (sizeof(First->memblk) - Mleft)
1138  /sizeof(typename Sacado::ValueType<Double>::type));
1139  if ((mb = Busy->next)) {
1140  if (!(mb0 = rad_Oldcurmb))
1141  mb0 = (ADMemblock*)First0;
1142  for(;; mb = mb->next) {
1143  _uninit_f2c(mb->memblk,
1144  UninitType<Double>::utype,
1145  sizeof(First->memblk)
1146  /sizeof(typename Sacado::ValueType<Double>::type));
1147  if (mb == mb0)
1148  break;
1149  }
1150  }
1151  rad_Oldcurmb = Busy;
1152  if (rad_busy_blocks >= RAD_DEBUG_BLOCKKEEP) {
1153  rad_busy_blocks = 0;
1154  rad_Oldcurmb = 0;
1155  mb0 = (ADMemblock*)First0;
1156  mbf = Free;
1157  for(mb = Busy; mb != mb0; mb = mb1) {
1158  mb1 = mb->next;
1159  mb->next = mbf;
1160  mbf = mb;
1161  }
1162  Free = mbf;
1163  Busy = mb;
1164  Mbase = (char*)First->memblk;
1165  Mleft = sizeof(First->memblk);
1166  }
1167 
1168 #else /* !RAD_DEBUG_BLOCKKEEP */
1169 
1170  mb0 = First;
1171  mbf = Free;
1172  for(mb = Busy; mb != mb0; mb = mb1) {
1173  mb1 = mb->next;
1174  mb->next = mbf;
1175  mbf = mb;
1176  }
1177  Free = mbf;
1178  Busy = mb;
1179  Mbase = (char*)First->memblk;
1180  Mleft = sizeof(First->memblk);
1181 #ifdef RAD_AUTO_AD_Const
1182  if (ADVari::adc.rad_need_reinit & 2) {
1183  ADVari::adc.rad_need_reinit &= ~2;
1184  *ADVari::Last_ADvari = 0;
1185  ADVari::Last_ADvari = &ADVari::First_ADvari;
1186  anext = ADVari::First_ADvari;
1187  if (anext) {
1188  while((a = anext)) {
1189  anext = a->Next;
1190  if ((v = (IndepADvar<Double> *)a->padv)) {
1191 #ifdef RAD_Const_WARN
1192  if ((i = a->opno) > 0)
1193  i = -i;
1194  j = a->gcgen;
1195  v->cv = cv = new ADVari(v, a->Val, a->aval);
1196  cv->opno = i;
1197  cv->gcgen = j;
1198 #else
1199  v->cv = new ADVari(v, a->Val, a->aval);
1200 #endif
1201  }
1202  }
1203  }
1204  }
1205 #endif /*RAD_AUTO_AD_Const*/
1206 #endif /*RAD_DEBUG_BLOCKKEEP*/
1207  if (Mleft >= len)
1208  return Mbase + (Mleft -= len);
1209  }
1210 
1211  if ((x = Free))
1212  Free = x->next;
1213  else
1214  x = new ADMemblock;
1215 #ifdef RAD_DEBUG_BLOCKKEEP
1216  rad_busy_blocks++;
1217 #endif
1218  x->next = Busy;
1219  Busy = x;
1220  return (Mbase = (char*)x->memblk) +
1221  (Mleft = sizeof(First->memblk) - len);
1222  }
1223 
1224 template<typename Double> void
1226 {
1227  ADVari_block *ob, *nb;
1228  ob = Aibusy;
1229  ob->limit = Ailimit; // should be unnecessary, but harmless
1230  if ((nb = Aifree))
1231  Aifree = nb->next;
1232  else
1233  nb = new ADVari_block;
1234  Aibusy = Aibusy->next = nb;
1235  nb->limit = Ailimit = (Ainext = nb->pADvari) + ADVari_block::Gulp;
1236  ob->next = nb;
1237  nb->prev = ob;
1238  nb->next = 0;
1239  }
1240 
1241 template<typename Double> void
1243 {
1244  DErp *d;
1245 
1246  if (ADVari::adc.rad_need_reinit) {
1247  for(d = DErp::LastDerp; d; d = d->next)
1248  d->c->aval = 0;
1249  }
1250  if (!(ADVari::adc.rad_need_reinit & 1)) {
1251  ADVari::adc.rad_need_reinit = 1;
1252  ADVari::adc.rad_mleft_save = ADVari::adc.Mleft;
1253  ADVari::adc.Mleft = 0;
1254  }
1255 #ifdef RAD_DEBUG
1256  if (ADVari::gcgen_cur == ADVari::zap_gcgen1) {
1257  const char *fname;
1258  if (!(fname = getenv("RAD_DEBUG_FILE")))
1259  fname = "rad_debug.out";
1260  else if (!*fname)
1261  fname = 0;
1262  if (fname)
1263  ADVari::debug_file = fopen(fname, "w");
1264  ADVari::zap_gcgen1 = -1;
1265  }
1266 #endif
1267  if ((d = DErp::LastDerp) != 0) {
1268 #ifdef RAD_AUTO_AD_Const
1269  ADVari::adc.rad_need_reinit |= 2;
1270 #endif /*RAD_AUTO_AD_Const*/
1271  if (wantgrad) {
1272  d->b->aval = 1;
1273 #ifdef RAD_DEBUG
1274  if (ADVari::debug_file)
1275  do {
1276  fprintf(ADVari::debug_file, "%d\t%d\t%g + %g * %g",
1277  d->c->opno, d->b->opno, d->c->aval,
1278  *d->a, d->b->aval);
1279  d->c->aval += *d->a * d->b->aval;
1280  fprintf(ADVari::debug_file, " = %g\n", d->c->aval);
1281  fflush(ADVari::debug_file);
1282  } while((d = d->next));
1283  else
1284 #endif
1285  do d->c->aval += *d->a * d->b->aval;
1286  while((d = d->next));
1287  DErp::LastDerp = 0;
1288  }
1289  }
1290 #ifdef RAD_DEBUG
1291  if (ADVari::debug_file) {
1292  fclose(ADVari::debug_file);
1293  ADVari::debug_file = 0;
1294  }
1295 #endif //RAD_DEBUG
1296 #ifdef RAD_DEBUG
1297  ADVari::gcgen_cur++;
1298  ADVari::last_opno = 0;
1299 #endif
1300  }
1301 
1302 template<typename Double> void
1303 ADcontext<Double>::Weighted_Gradcomp(int n, ADVar **V, Double *w)
1304 {
1305  DErp *d;
1306  int i;
1307 #ifdef RAD_Const_WARN
1308  ADVari *cv;
1309  int j;
1310 #endif
1311 #ifdef RAD_AUTO_AD_Const
1312  ADVari *a, *anext;
1313  IndepADvar<Double> *v;
1314 #endif /*RAD_AUTO_AD_Const*/
1315 
1316  if (ADVari::adc.rad_need_reinit) {
1317  for(d = DErp::LastDerp; d; d = d->next)
1318  d->c->aval = 0;
1319  }
1320  if (!(ADVari::adc.rad_need_reinit & 1)) {
1321  ADVari::adc.rad_need_reinit = 1;
1322  ADVari::adc.rad_mleft_save = ADVari::adc.Mleft;
1323  ADVari::adc.Mleft = 0;
1324  }
1325 #ifdef RAD_DEBUG
1326  if (ADVari::gcgen_cur == ADVari::zap_gcgen1) {
1327  const char *fname;
1328  if (!(fname = getenv("RAD_DEBUG_FILE")))
1329  fname = "rad_debug.out";
1330  else if (!*fname)
1331  fname = 0;
1332  if (fname)
1333  ADVari::debug_file = fopen(fname, "w");
1334  ADVari::zap_gcgen1 = -1;
1335  }
1336 #endif
1337  if ((d = DErp::LastDerp) != 0) {
1338  for(i = 0; i < n; i++)
1339  V[i]->cv->aval = w[i];
1340 #ifdef RAD_DEBUG
1341  if (ADVari::debug_file)
1342  do {
1343  fprintf(ADVari::debug_file, "%d\t%d\t%g + %g * %g",
1344  d->c->opno, d->b->opno, d->c->aval, *d->a, d->b->aval);
1345  d->c->aval += *d->a * d->b->aval;
1346  fprintf(ADVari::debug_file, " = %g\n", d->c->aval);
1347  fflush(ADVari::debug_file);
1348  } while((d = d->next));
1349  else
1350 #endif
1351  do d->c->aval += *d->a * d->b->aval;
1352  while((d = d->next));
1353  }
1354 #ifdef RAD_DEBUG
1355  if (ADVari::debug_file) {
1356  fclose(ADVari::debug_file);
1357  ADVari::debug_file = 0;
1358  }
1359 #endif //RAD_DEBUG
1360 #ifdef RAD_AUTO_AD_Const
1361  *ADVari::Last_ADvari = 0;
1362  ADVari::Last_ADvari = &ADVari::First_ADvari;
1363  if ((anext = ADVari::First_ADvari) && !(ADVari::adc.rad_need_reinit & 2)) {
1364  ADVari::adc.rad_need_reinit = 3;
1365  while((a = anext)) {
1366  anext = a->Next;
1367  if ((v = (IndepADvar<Double> *)a->padv)) {
1368 #ifdef RAD_Const_WARN
1369  if ((i = a->opno) > 0)
1370  i = -i;
1371  j = a->gcgen;
1372  v->cv = cv = new ADVari(v, a->Val, a->aval);
1373  cv->opno = i;
1374  cv->gcgen = j;
1375 #else
1376  v->cv = new ADVari(v, a->Val, a->aval);
1377 #endif
1378  }
1379  }
1380  DErp::LastDerp = 0;
1381  }
1382 #endif /*RAD_AUTO_AD_Const*/
1383 #ifdef RAD_DEBUG
1384  ADVari::gcgen_cur++;
1385  ADVari::last_opno = 0;
1386 #endif
1387  }
1388 
1389  template<typename Double>
1391 {
1392 
1393  ADVari *x = new ADVari(Hv_const, d);
1394  cv = x;
1395  }
1396 
1397  template<typename Double>
1399 {
1400 
1401  ADVari *x = new ADVari(Hv_const, Double(i));
1402  cv = x;
1403  }
1404 
1405  template<typename Double>
1407 {
1408 
1409  ADVari *x = new ADVari(Hv_const, Double(i));
1410  cv = x;
1411  }
1412 
1413  template<typename Double>
1415 {
1416 
1417  ADVari *x = new ADVari(Hv_const, Double(i));
1418  cv = x;
1419  }
1420 
1421  template<typename Double>
1423 {
1424  ConstADVari *x = new ConstADVari(0.);
1425  this->cv = x;
1426  }
1427 
1428  template<typename Double> void
1430 {
1431  ConstADVari *x = new ConstADVari(d);
1432  this->cv = x;
1433  }
1434 
1435  template<typename Double>
1437 {
1438  ConstADVari *y = new ConstADVari(x.cv->Val);
1439  DErp *d = new DErp(&x.adc.One, y, x.cv);
1440  this->cv = y;
1441  }
1442 
1443  template<typename Double>
1445 {
1446  ConstADVari *y = new ConstADVari(x.cv->Val);
1447  DErp *d = new DErp(&x.cv->adc.One, y, (ADVari*)x.cv);
1448  this->cv = y;
1449  }
1450 
1451  template<typename Double>
1453 {
1454  ConstADVari *y = new ConstADVari(x.Val);
1455  DErp *d = new DErp(&x.adc.One, y, &x);
1456  this->cv = y;
1457  }
1458 
1459  template<typename Double>
1460  void
1461 IndepADvar<Double>::AD_Const(const IndepADvar &v)
1462 {
1463  typedef ConstADvari<Double> ConstADVari;
1464 
1465  ConstADVari *ncv = new ConstADVari(v.val());
1466 #ifdef RAD_AUTO_AD_Const
1467  if (v.cv)
1468  v.cv->padv = 0;
1469 #endif
1470  v.cv = ncv;
1471  }
1472 
1473  template<typename Double>
1474  void
1476 {
1478  while(x) {
1479  x->aval = 0;
1480  x = x->prevcad;
1481  }
1482  }
1483 
1484 #ifdef RAD_AUTO_AD_Const
1485 
1486  template<typename Double>
1487 ADvari<Double>::ADvari(const IndepADVar *x, Double d): Val(d), aval(0.)
1488 {
1489  opclass = Hv_const;
1490  this->ADvari_padv(x);
1491  }
1492 
1493  template<typename Double>
1494 ADvari<Double>::ADvari(const IndepADVar *x, Double d, Double g): Val(d), aval(g)
1495 {
1496  opclass = Hv_const;
1497  this->ADvari_padv(x);
1498  }
1499 
1500  template<typename Double>
1501 ADvar1<Double>::ADvar1(const IndepADVar *x, const IndepADVar &y):
1502  ADVari(Hv_copy, y.cv->Val), d((const Double*)&ADcontext<Double>::One, (ADVari*)this, y.cv)
1503 {
1504  this->ADvari_padv(x);
1505  }
1506 
1507  template<typename Double>
1508 ADvar1<Double>::ADvar1(const IndepADVar *x, const ADVari &y):
1509  ADVari(Hv_copy, y.Val), d((const Double*)&ADcontext<Double>::One, this, &y)
1510 {
1511  this->ADvari_padv(x);
1512  }
1513 
1514 #endif /* RAD_AUTO_AD_Const */
1515 
1516  template<typename Double>
1517  IndepADvar<Double>&
1519 { This->cv = new ADvar1<Double>(Hv_copy, x.Val, &x.adc.One, &x);
1520  return *(IndepADvar<Double>*) This; }
1521 
1522  template<typename Double>
1523  ADvar<Double>&
1525 { This->cv = new ADvar1<Double>(Hv_copy, x.Val, &x.adc.One, &x); return *(ADvar<Double>*) This; }
1526 
1527  template<typename Double>
1528  IndepADvar<Double>&
1530 {
1531 #ifdef RAD_AUTO_AD_Const
1532  ADVari *ncv = new ADVari(this, d);
1533  if (this->cv)
1534  this->cv->padv = 0;
1535  this->cv = ncv;
1536 #else
1537  this->cv = new ADVari(Hv_const, d);
1538 #endif
1539  return *this;
1540  }
1541 
1542  template<typename Double>
1543  ADvar<Double>&
1545 {
1546 #ifdef RAD_AUTO_AD_Const
1547  ADVari *nv = new ADVari(this, d);
1548  if (this->cv)
1549  this->cv->padv = 0;
1550  this->cv = nv;
1551 #else
1552  this->cv = ConstADVari::cadc.fpval_implies_const
1553  ? new ConstADVari(d)
1554  : new ADVari(Hv_const, d);
1555 #endif
1556  return *this;
1557  }
1558 
1559  template<typename Double>
1562  return *(new ADvar1<Double>(Hv_negate, -T.Val, &T.adc.negOne, &T));
1563  }
1564 
1565  template<typename Double>
1566  ADvari<Double>&
1568  return *(new ADvar2<Double>(Hv_plusLR, L.Val + R.Val, &L, &L.adc.One, &R, &L.adc.One));
1569  }
1570 
1571 #ifdef RAD_AUTO_AD_Const
1572 #define RAD_ACA ,this
1573 #else
1574 #define RAD_ACA /*nothing*/
1575 #endif
1576 
1577  template<typename Double>
1578  ADvar<Double>&
1580  ADVari *Lcv = this->cv;
1581  this->cv = new ADvar2<Double>(Hv_plusLR, Lcv->Val + R.Val, Lcv,
1582  &R.adc.One, &R, &R.adc.One RAD_ACA);
1583  return *this;
1584  }
1585 
1586  template<typename Double>
1588 operator+(const ADvari<Double> &L, Double R) {
1589  return *(new ADvar1<Double>(Hv_copy, L.Val + R, &L.adc.One, &L));
1590  }
1591 
1592  template<typename Double>
1593  ADvar<Double>&
1595  ADVari *tcv = this->cv;
1596  this->cv = new ADVar1(Hv_copy, tcv->Val + R, &tcv->adc.One, tcv RAD_ACA);
1597  return *this;
1598  }
1599 
1600  template<typename Double>
1602 operator+(Double L, const ADvari<Double> &R) {
1603  return *(new ADvar1<Double>(Hv_copy, L + R.Val, &R.adc.One, &R));
1604  }
1605 
1606  template<typename Double>
1607  ADvari<Double>&
1609  return *(new ADvar2<Double>(Hv_minusLR, L.Val - R.Val, &L, &L.adc.One, &R, &L.adc.negOne));
1610  }
1611 
1612  template<typename Double>
1613  ADvar<Double>&
1615  ADVari *Lcv = this->cv;
1616  this->cv = new ADvar2<Double>(Hv_minusLR,Lcv->Val - R.Val, Lcv,
1617  &R.adc.One, &R, &R.adc.negOne RAD_ACA);
1618  return *this;
1619  }
1620 
1621  template<typename Double>
1623 operator-(const ADvari<Double> &L, Double R) {
1624  return *(new ADvar1<Double>(Hv_copy, L.Val - R, &L.adc.One, &L));
1625  }
1626 
1627  template<typename Double>
1628  ADvar<Double>&
1630  ADVari *tcv = this->cv;
1631  this->cv = new ADVar1(Hv_copy, tcv->Val - R, &tcv->adc.One, tcv RAD_ACA);
1632  return *this;
1633  }
1634 
1635  template<typename Double>
1637 operator-(Double L, const ADvari<Double> &R) {
1638  return *(new ADvar1<Double>(Hv_negate, L - R.Val, &R.adc.negOne, &R));
1639  }
1640 
1641  template<typename Double>
1642  ADvari<Double>&
1644  return *(new ADvar2<Double>(Hv_timesLR, L.Val * R.Val, &L, &R.Val, &R, &L.Val));
1645  }
1646 
1647  template<typename Double>
1648  ADvar<Double>&
1650  ADVari *Lcv = this->cv;
1651  this->cv = new ADvar2<Double>(Hv_timesLR, Lcv->Val * R.Val, Lcv,
1652  &R.Val, &R, &Lcv->Val RAD_ACA);
1653  return *this;
1654  }
1655 
1656  template<typename Double>
1658 operator*(const ADvari<Double> &L, Double R) {
1659  return *(new ADvar1s<Double>(L.Val * R, R, &L));
1660  }
1661 
1662  template<typename Double>
1663  ADvar<Double>&
1665  ADVari *Lcv = this->cv;
1666  this->cv = new ADvar1s<Double>(Lcv->Val * R, R, Lcv RAD_ACA);
1667  return *this;
1668  }
1669 
1670  template<typename Double>
1672 operator*(Double L, const ADvari<Double> &R) {
1673  return *(new ADvar1s<Double>(L * R.Val, L, &R));
1674  }
1675 
1676  template<typename Double>
1677  ADvari<Double>&
1679  Double Lv = L.Val, Rv = R.Val, pL = 1. / Rv, q = Lv/Rv, qpL = q*pL;
1680  return *(new ADvar2q<Double>(q, pL, -qpL, -pL*pL, 2.*pL*qpL, &L, &R));
1681  }
1682 
1683  template<typename Double>
1684  ADvar<Double>&
1686  ADVari *Lcv = this->cv;
1687  Double Lv = Lcv->Val, Rv = R.Val, pL = 1. / Rv, q = Lv/Rv, qpL = q*pL;
1688  this->cv = new ADvar2q<Double>(q, pL, -qpL, -pL*pL, 2.*pL*qpL, Lcv, &R RAD_ACA);
1689  return *this;
1690  }
1691 
1692  template<typename Double>
1694 operator/(const ADvari<Double> &L, Double R) {
1695  return *(new ADvar1s<Double>(L.Val / R, 1./R, &L));
1696  }
1697 
1698  template<typename Double>
1699  ADvari<Double>&
1700 operator/(Double L, const ADvari<Double> &R) {
1701  Double recip = 1. / R.Val;
1702  Double q = L * recip;
1703  Double d1 = -q*recip;
1704  return *(new ADvar1g<Double>(q, d1, -q*d1, &R));
1705  }
1706 
1707  template<typename Double>
1708  ADvar<Double>&
1710  ADVari *Lcv = this->cv;
1711  this->cv = new ADvar1s<Double>(Lcv->Val / R, 1./R, Lcv RAD_ACA);
1712  return *this;
1713  }
1714 
1715  template<typename Double>
1718  Double t = v.Val, t1 = 1. - t*t, d1 = -1./std::sqrt(t1);
1719  return *(new ADvar1g<Double>(std::acos(t), d1, t*d1/t1, &v));
1720  }
1721 
1722  template<typename Double>
1723  ADvari<Double>&
1725  Double d1, t, t1, t2;
1726  t = v.Val;
1727  t1 = std::sqrt(t2 = t*t - 1.);
1728  d1 = 1. / t1;
1729  return *(new ADvar1g<Double>(std::log(t + t1), d1, -t*d1/t2, &v));
1730  }
1731 
1732  template<typename Double>
1733  ADvari<Double>&
1735  Double d1, t, t1;
1736  t = v.Val;
1737  d1 = 1. / std::sqrt(t1 = 1. - t*t);
1738  return *(new ADvar1g<Double>(std::asin(t), d1, t*d1/t1, &v));
1739  }
1740 
1741  template<typename Double>
1742  ADvari<Double>&
1744  Double d1, t, t1, t2, td;
1745  t = v.Val;
1746  t1 = std::sqrt(t2 = t*t + 1.);
1747  d1 = 1. / t1;
1748  td = 1.;
1749  if (t < 0.)
1750  td = -1.;
1751  return *(new ADvar1g<Double>(td*std::log(t*td + t1), d1, -(t/t2)*d1, &v));
1752  }
1753 
1754  template<typename Double>
1755  ADvari<Double>&
1757  Double t = v.Val, d1 = 1./(1. + t*t);
1758  return *(new ADvar1g<Double>(std::atan(t), d1, -(t+t)*d1*d1, &v));
1759  }
1760 
1761  template<typename Double>
1762  ADvari<Double>&
1764  Double t = v.Val, d1 = 1./(1. - t*t);
1765  return *(new ADvar1g<Double>(0.5*std::log((1.+t)/(1.-t)), d1, (t+t)*d1*d1, &v));
1766  }
1767 
1768  template<typename Double>
1769  ADvari<Double>&
1771  Double R2, t, t2, x, x2, y, y2;
1772  x = L.Val;
1773  y = R.Val;
1774  x2 = x*x;
1775  y2 = y*y;
1776  t = 1./(x2 + y2);
1777  t2 = t*t;
1778  R2 = 2.*t2*x*y;
1779  return *(new ADvar2g<Double>(std::atan2(x,y), y*t, -x*t, -R2, t2*(x2 - y2), R2, &L, &R));
1780  }
1781 
1782  template<typename Double>
1783  ADvari<Double>&
1784 atan2(Double x, const ADvari<Double> &R) {
1785  Double t, x2, y, y2;
1786  y = R.Val;
1787  x2 = x*x;
1788  y2 = y*y;
1789  t = 1./(x2 + y2);
1790  return *(new ADvar1g<Double>(std::atan2(x,y), -x*t, 2.*t*t*x*y, &R));
1791  }
1792 
1793  template<typename Double>
1794  ADvari<Double>&
1795 atan2(const ADvari<Double> &L, Double y) {
1796  Double t, x, x2, y2;
1797  x = L.Val;
1798  x2 = x*x;
1799  y2 = y*y;
1800  t = 1./(x2 + y2);
1801  return *(new ADvar1g<Double>(std::atan2(x,y), y*t, -2.*t*t*x*y, &L));
1802  }
1803 
1804  template<typename Double>
1805  ADvari<Double>&
1806 max(const ADvari<Double> &L, const ADvari<Double> &R) {
1807  const ADvari<Double> &x = L.Val >= R.Val ? L : R;
1808  return *(new ADvar1<Double>(Hv_copy, x.Val, &x.adc.One, &x));
1809  }
1810 
1811  template<typename Double>
1812  ADvari<Double>&
1813 max(Double L, const ADvari<Double> &R) {
1814  if (L >= R.Val)
1815  return *(new ADvari<Double>(Hv_const, L));
1816  return *(new ADvar1<Double>(Hv_copy, R.Val, &R.adc.One, &R));
1817  }
1818 
1819  template<typename Double>
1820  ADvari<Double>&
1821 max(const ADvari<Double> &L, Double R) {
1822  if (L.Val >= R)
1823  return *(new ADvar1<Double>(Hv_copy, L.Val, &L.adc.One, &L));
1824  return *(new ADvari<Double>(Hv_const, R));
1825  }
1826 
1827  template<typename Double>
1828  ADvari<Double>&
1829 min(const ADvari<Double> &L, const ADvari<Double> &R) {
1830  const ADvari<Double> &x = L.Val <= R.Val ? L : R;
1831  return *(new ADvar1<Double>(Hv_copy, x.Val, &x.adc.One, &x));
1832  }
1833 
1834  template<typename Double>
1835  ADvari<Double>&
1836 min(Double L, const ADvari<Double> &R) {
1837  if (L <= R.Val)
1838  return *(new ADvari<Double>(Hv_const, L));
1839  return *(new ADvar1<Double>(Hv_copy, R.Val, &R.adc.One, &R));
1840  }
1841 
1842  template<typename Double>
1843  ADvari<Double>&
1844 min(const ADvari<Double> &L, Double R) {
1845  if (L.Val <= R)
1846  return *(new ADvar1<Double>(Hv_copy, L.Val, &L.adc.One, &L));
1847  return *(new ADvari<Double>(Hv_const, R));
1848  }
1849 
1850  template<typename Double>
1851  ADvari<Double>&
1852 cos(const ADvari<Double> &v) {
1853  Double t = std::cos(v.Val);
1854  return *(new ADvar1g<Double>(t, -std::sin(v.Val), -t, &v));
1855  }
1856 
1857  template<typename Double>
1858  ADvari<Double>&
1860  Double t = std::cosh(v.Val);
1861  return *(new ADvar1g<Double>(t, std::sinh(v.Val), t, &v));
1862  }
1863 
1864  template<typename Double>
1865  ADvari<Double>&
1866 exp(const ADvari<Double> &v) {
1867  Double t = std::exp(v.Val);
1868  return *(new ADvar1g<Double>(t, t, t, &v));
1869  }
1870 
1871  template<typename Double>
1872  ADvari<Double>&
1873 log(const ADvari<Double> &v) {
1874  Double x = v.Val, d1 = 1. / x;
1875  return *(new ADvar1g<Double>(std::log(x), d1, -d1*d1, &v));
1876  }
1877 
1878  template<typename Double>
1879  ADvari<Double>&
1881  static double num = 1. / std::log(10.);
1882  Double d1, t, x;
1883  x = v.Val;
1884  t = 1. / x;
1885  d1 = num * t;
1886  return *(new ADvar1g<Double>(std::log10(x), d1, -d1*t, &v));
1887  }
1888 
1889  template<typename Double>
1890  ADvari<Double>&
1891 pow(const ADvari<Double> &L, const ADvari<Double> &R) {
1892  Double dx, dy, t, x, xlog, xym1, y;
1893  x = L.Val;
1894  y = R.Val;
1895  t = std::pow(x,y);
1896  xym1 = t / x;
1897  xlog = std::log(x);
1898  dx = y*xym1;
1899  dy = t * xlog;
1900  return *(new ADvar2g<Double>(t, dx, dy, (y-1.)*dx/x, xym1*(1. + y*xlog), dy*xlog, &L, &R));
1901  }
1902 
1903  template<typename Double>
1904  ADvari<Double>&
1905 pow(Double x, const ADvari<Double> &R) {
1906  Double dy, t, xlog, y;
1907  y = R.Val;
1908  t = std::pow(x,y);
1909  xlog = std::log(x);
1910  dy = t * xlog;
1911  return *(new ADvar1g<Double>(t, dy, dy*xlog, &R));
1912  }
1913 
1914  template<typename Double>
1915  ADvari<Double>&
1916 pow(const ADvari<Double> &L, Double y) {
1917  Double dx, t, x;
1918  x = L.Val;
1919  t = std::pow(x,y);
1920  dx = y*t/x;
1921  return *(new ADvar1g<Double>(t, dx, (y-1.)*dx/x, &L));
1922  }
1923 
1924  template<typename Double>
1925  ADvari<Double>&
1926 sin(const ADvari<Double> &v) {
1927  Double t = std::sin(v.Val);
1928  return *(new ADvar1g<Double>(t, std::cos(v.Val), -t, &v));
1929  }
1930 
1931  template<typename Double>
1932  ADvari<Double>&
1934  Double t = std::sinh(v.Val);
1935  return *(new ADvar1g<Double>(t, std::cosh(v.Val), t, &v));
1936  }
1937 
1938  template<typename Double>
1939  ADvari<Double>&
1941  Double t = std::sqrt(v.Val);
1942  Double d1 = 0.5 / t;
1943  return *(new ADvar1g<Double>(t, d1, -0.5*d1/v.Val, &v));
1944  }
1945 
1946  template<typename Double>
1947  ADvari<Double>&
1948 tan(const ADvari<Double> &v) {
1949  Double d1, rv, t;
1950  rv = std::tan(v.Val);
1951  t = 1. / std::cos(v.Val);
1952  d1 = t*t;
1953  return *(new ADvar1g<Double>(rv, d1, (rv+rv)*d1, &v));
1954  }
1955 
1956  template<typename Double>
1957  ADvari<Double>&
1959  Double d1, rv, t;
1960  rv = std::tanh(v.Val);
1961  t = 1. / std::cosh(v.Val);
1962  d1 = t*t;
1963  return *(new ADvar1g<Double>(rv, d1, -(rv+rv)*d1, &v));
1964  }
1965 
1966  template<typename Double>
1967  ADvari<Double>&
1968 abs(const ADvari<Double> &v) {
1969  Double t, p;
1970  p = 1.;
1971  if ((t = v.Val) < 0) {
1972  t = -t;
1973  p = -p;
1974  }
1975  return *(new ADvar1g<Double>(t, p, 0., &v));
1976  }
1977 
1978  template<typename Double>
1979  ADvari<Double>&
1980 fabs(const ADvari<Double> &v) { // Synonym for "abs"
1981  // "fabs" is not the best choice of name,
1982  // but this name is used at Sandia.
1983  Double t, p;
1984  p = 1.;
1985  if ((t = v.Val) < 0) {
1986  t = -t;
1987  p = -p;
1988  }
1989  return *(new ADvar1g<Double>(t, p, 0., &v));
1990  }
1991 
1992  template<typename Double>
1993  ADvari<Double>&
1994 ADf1(Double f, Double g, Double h, const ADvari<Double> &x) {
1995  return *(new ADvar1g<Double>(f, g, h, &x));
1996  }
1997 
1998  template<typename Double>
1999  inline ADvari<Double>&
2000 ADf1(Double f, Double g, Double h, const IndepADvar<Double> &x) {
2001  return *(new ADvar1g<Double>(f, g, h, x.cv));
2002  }
2003 
2004  template<typename Double>
2005  ADvari<Double>&
2006 ADf2(Double f, Double gx, Double gy, Double hxx, Double hxy, Double hyy,
2007  const ADvari<Double> &x, const ADvari<Double> &y) {
2008  return *(new ADvar2g<Double>(f, gx, gy, hxx, hxy, hyy, &x, &y));
2009  }
2010 
2011  template<typename Double>
2012  ADvari<Double>&
2013 ADf2(Double f, Double gx, Double gy, Double hxx, Double hxy, Double hyy,
2014  const ADvari<Double> &x, const IndepADvar<Double> &y) {
2015  return *(new ADvar2g<Double>(f, gx, gy, hxx, hxy, hyy, &x, y.cv));
2016  }
2017 
2018  template<typename Double>
2019  ADvari<Double>&
2020 ADf2(Double f, Double gx, Double gy, Double hxx, Double hxy, Double hyy,
2021  const IndepADvar<Double> &x, const ADvari<Double> &y) {
2022  return *(new ADvar2g<Double>(f, gx, gy, hxx, hxy, hyy, x.cv, &y));
2023  }
2024 
2025  template<typename Double>
2026  ADvari<Double>&
2027 ADf2(Double f, Double gx, Double gy, Double hxx, Double hxy, Double hyy,
2028  const IndepADvar<Double> &x, const IndepADvar<Double> &y) {
2029  return *(new ADvar2g<Double>(f, gx, gy, hxx, hxy, hyy, x.cv, y.cv));
2030  }
2031 
2032  template<typename Double>
2033  ADvari<Double>&
2034 ADfn(Double f, int n, const IndepADvar<Double> *x, const Double *g, const Double *h) {
2035  return *(new ADvarn<Double>(f, n, x, g, h));
2036  }
2037 
2038  template<typename Double>
2039  inline ADvari<Double>&
2040 ADfn(Double f, int n, const ADvar<Double> *x, const Double *g, const Double *h) {
2041  return ADfn<Double>(f, n, (IndepADvar<Double>*)x, g, h);
2042  }
2043 
2044  template<typename Double>
2045  void
2046 ADcontext<Double>::Hvprod(int n, ADvar<Double> **x, Double *v, Double *hv)
2047 {
2048  ADVari *a, *aL, *aR, **ap, **ape;
2049  ADVari_block *b, *b0;
2050  DErp *d;
2051  Double aO, adO, *g, *h, *h0, t, tL, tR;
2052  int i, j, k, m;
2053  for(i = 0; i < n; i++) {
2054  a = x[i]->cv;
2055  a->dO = v[i];
2056  a->aO = a->adO = 0.;
2057  }
2058  ADVari::adc.Aibusy->limit = ADVari::adc.Ainext;
2059  a = 0;
2060  for(b0 = 0, b = ADVari::adc.AiFirst; b; b0 = b, b = b->next) {
2061  ap = b->pADvari;
2062  ape = b->limit;
2063  while(ap < ape) {
2064  a = *ap++;
2065  a->aO = a->adO = 0.;
2066  switch(a->opclass) {
2067  case Hv_copy:
2068  a->dO = ((ADVar1*)a)->d.c->dO;
2069  break;
2070  case Hv_binary:
2071  a->dO = ((ADVar2g*)a)->pL * ((ADVar2g*)a)->dL.c->dO
2072  + ((ADVar2g*)a)->pR * ((ADVar2g*)a)->dR.c->dO;
2073  break;
2074  case Hv_unary:
2075  a->dO = ((ADVar1g*)a)->pL * ((ADVar1g*)a)->d.c->dO;
2076  break;
2077  case Hv_negate:
2078  a->dO = -((ADVar1*)a)->d.c->dO;
2079  break;
2080  case Hv_plusLR:
2081  a->dO = ((ADVar2*)a)->dL.c->dO + ((ADVar2*)a)->dR.c->dO;
2082  break;
2083  case Hv_minusLR:
2084  a->dO = ((ADVar2*)a)->dL.c->dO - ((ADVar2*)a)->dR.c->dO;
2085  break;
2086  case Hv_timesL:
2087  a->dO = ((ADVar1s*)a)->pL * ((ADVar1s*)a)->d.c->dO;
2088  break;
2089  case Hv_timesLR:
2090  a->dO = ((ADVar2*)a)->dR.c->Val * ((ADVar2*)a)->dL.c->dO
2091  + ((ADVar2*)a)->dL.c->Val * ((ADVar2*)a)->dR.c->dO;
2092  break;
2093  case Hv_quotLR:
2094  a->dO = ((ADVar2q*)a)->pL * ((ADVar2q*)a)->dL.c->dO
2095  + ((ADVar2q*)a)->pR * ((ADVar2q*)a)->dR.c->dO;
2096  break;
2097  case Hv_nary:
2098  d = ((ADVarn*)a)->D;
2099  m = ((ADVarn*)a)->n;
2100  g = ((ADVarn*)a)->G;
2101  t = 0.;
2102  for(i = 0; i < m; i++)
2103  t += g[i] * d[i].c->dO;
2104  a->dO = t;
2105  break;
2106  case Hv_const:
2107  ;
2108  }
2109  }
2110  }
2111  if (a)
2112  a->adO = 1.;
2113  for(b = b0; b; b = b->prev) {
2114  ape = b->pADvari;
2115  ap = b->limit;
2116  while(ap > ape) {
2117  a = *--ap;
2118  aO = a->aO;
2119  adO = a->adO;
2120  switch(a->opclass) {
2121  case Hv_copy:
2122  aL = ((ADVar1*)a)->d.c;
2123  aL->aO += aO;
2124  aL->adO += adO;
2125  break;
2126  case Hv_binary:
2127  aL = ((ADVar2g*)a)->dL.c;
2128  aR = ((ADVar2g*)a)->dR.c;
2129  tL = adO*aL->dO;
2130  tR = adO*aR->dO;
2131  aL->aO += aO*((ADVar2g*)a)->pL
2132  + tL*((ADVar2g*)a)->pL2
2133  + tR*((ADVar2g*)a)->pLR;
2134  aR->aO += aO*((ADVar2g*)a)->pR
2135  + tL*((ADVar2g*)a)->pLR
2136  + tR*((ADVar2g*)a)->pR2;
2137  aL->adO += adO * ((ADVar2g*)a)->pL;
2138  aR->adO += adO * ((ADVar2g*)a)->pR;
2139  break;
2140  case Hv_unary:
2141  aL = ((ADVar1g*)a)->d.c;
2142  aL->aO += aO * ((ADVar1g*)a)->pL
2143  + adO * aL->dO * ((ADVar1g*)a)->pL2;
2144  aL->adO += adO * ((ADVar1g*)a)->pL;
2145  break;
2146  case Hv_negate:
2147  aL = ((ADVar1*)a)->d.c;
2148  aL->aO -= aO;
2149  aL->adO -= adO;
2150  break;
2151  case Hv_plusLR:
2152  aL = ((ADVar2*)a)->dL.c;
2153  aR = ((ADVar2*)a)->dR.c;
2154  aL->aO += aO;
2155  aL->adO += adO;
2156  aR->aO += aO;
2157  aR->adO += adO;
2158  break;
2159  case Hv_minusLR:
2160  aL = ((ADVar2*)a)->dL.c;
2161  aR = ((ADVar2*)a)->dR.c;
2162  aL->aO += aO;
2163  aL->adO += adO;
2164  aR->aO -= aO;
2165  aR->adO -= adO;
2166  break;
2167  case Hv_timesL:
2168  aL = ((ADVar1s*)a)->d.c;
2169  aL->aO += aO * (tL = ((ADVar1s*)a)->pL);
2170  aL->adO += adO * tL;
2171  break;
2172  case Hv_timesLR:
2173  aL = ((ADVar2*)a)->dL.c;
2174  aR = ((ADVar2*)a)->dR.c;
2175  aL->aO += aO * (tL = aR->Val) + adO*aR->dO;
2176  aR->aO += aO * (tR = aL->Val) + adO*aL->dO;
2177  aL->adO += adO * tL;
2178  aR->adO += adO * tR;
2179  break;
2180  case Hv_quotLR:
2181  aL = ((ADVar2q*)a)->dL.c;
2182  aR = ((ADVar2q*)a)->dR.c;
2183  tL = adO*aL->dO;
2184  tR = adO*aR->dO;
2185  aL->aO += aO*((ADVar2q*)a)->pL
2186  + tR*((ADVar2q*)a)->pLR;
2187  aR->aO += aO*((ADVar2q*)a)->pR
2188  + tL*((ADVar2q*)a)->pLR
2189  + tR*((ADVar2q*)a)->pR2;
2190  aL->adO += adO * ((ADVar2q*)a)->pL;
2191  aR->adO += adO * ((ADVar2q*)a)->pR;
2192  break;
2193  case Hv_nary:
2194  d = ((ADVarn*)a)->D;
2195  m = ((ADVarn*)a)->n;
2196  g = ((ADVarn*)a)->G;
2197  h0 = ((ADVarn*)a)->H;
2198  for(i = 0; i < m; i++) {
2199  aL = d[i].c;
2200  aL->adO += adO * (t = g[i]);
2201  aL->aO += t*aO;
2202  t = adO * aL->dO;
2203  for(h = h0, j = 0; j <= i; j++)
2204  d[j].c->aO += t * *h++;
2205  h0 = h--;
2206  for(k = j; j < m; j++)
2207  d[j].c->aO += t * *(h += k++);
2208  }
2209  case Hv_const:
2210  ;
2211  }
2212  }
2213  }
2214  for(i = 0; i < n; i++) {
2215  a = x[i]->cv;
2216  a->dO = 0.;
2217  hv[i] = a->aO;
2218  }
2219  }
2220 
2221  template<typename Double>
2222  inline Double
2223 val(const ADvari<Double> &x) {
2224  return x.Val;
2225  }
2226 
2227 #undef RAD_ACA
2228 #define A (ADvari<Double>*)
2229 #ifdef RAD_Const_WARN
2230 #define C(x) (((x)->opno < 0) ? RAD_Const_Warn(x) : 0, *A x)
2231 #else
2232 #define C(x) *A x
2233 #endif
2234 #define T template<typename Double> inline
2235 #define F ADvari<Double>&
2236 #define Ai const ADvari<Double>&
2237 #define AI const IndepADvar<Double>&
2238 #define D Double
2239 #define T2(r,f) \
2240  T r f(Ai L, AI R) { return f(L, C(R.cv)); }\
2241  T r f(AI L, Ai R) { return f(C(L.cv), R); }\
2242  T r f(AI L, AI R) { return f(C(L.cv), C(R.cv)); }\
2243  T r f(AI L, D R) { return f(C(L.cv), R); }\
2244  T r f(Ai L, Dtype R) { return f(L, (D)R); }\
2245  T r f(AI L, Dtype R) { return f(C(L.cv), (D)R); }\
2246  T r f(Ai L, long R) { return f(L, (D)R); }\
2247  T r f(AI L, long R) { return f(C(L.cv), (D)R); }\
2248  T r f(Ai L, int R) { return f(L, (D)R); }\
2249  T r f(AI L, int R) { return f(C(L.cv), (D)R); }\
2250  T r f(D L, AI R) { return f(L, C(R.cv)); }\
2251  T r f(Dtype L, Ai R) { return f((D)L, R); }\
2252  T r f(Dtype L, AI R) { return f((D)L, C(R.cv)); }\
2253  T r f(long L, Ai R) { return f((D)L, R); }\
2254  T r f(long L, AI R) { return f((D)L, C(R.cv)); }\
2255  T r f(int L, Ai R) { return f((D)L, R); }\
2256  T r f(int L, AI R) { return f((D)L, C(R.cv)); }
2257 
2258 T2(F, operator+)
2259 T2(F, operator-)
2260 T2(F, operator*)
2261 T2(F, operator/)
2262 T2(F, atan2)
2263 T2(F, pow)
2264 T2(F, max)
2265 T2(F, min)
2266 T2(int, operator<)
2267 T2(int, operator<=)
2268 T2(int, operator==)
2269 T2(int, operator!=)
2270 T2(int, operator>=)
2271 T2(int, operator>)
2272 
2273 #undef T2
2274 #undef D
2275 
2276 #define T1(f)\
2277  T F f(AI x) { return f(C(x.cv)); }
2278 
2279 T1(operator+)
2280 T1(operator-)
2281 T1(abs)
2282 T1(acos)
2283 T1(acosh)
2284 T1(asin)
2285 T1(asinh)
2286 T1(atan)
2287 T1(atanh)
2288 T1(cos)
2289 T1(cosh)
2290 T1(exp)
2291 T1(log)
2292 T1(log10)
2293 T1(sin)
2294 T1(sinh)
2295 T1(sqrt)
2296 T1(tan)
2297 T1(tanh)
2298 T1(fabs)
2299 
2300 T F copy(AI x)
2301 { return *(new ADvar1<Double>(Hv_copy, x.cv->Val, &ADcontext<Double>::One, (ADvari<Double>*)x.cv)); }
2302 
2303 T F copy(Ai x)
2304 { return *(new ADvar1<Double>(Hv_copy, x.Val, &ADcontext<Double>::One, (ADvari<Double>*)&x)); }
2305 
2306 #undef T1
2307 #undef AI
2308 #undef Ai
2309 #undef F
2310 #undef T
2311 #undef A
2312 #undef C
2313 #undef Ttype
2314 #undef Dtype
2315 
2316 } /* namespace Rad2 */
2317 } /* namespace Sacado */
2318 
2319 #endif /* SACADO_TRAD2_H */
const char * p
#define Ttype
ADT_RAD ADvari< double > Ai
ADvari< Double > & abs(const ADvari< Double > &v)
ADvar(const IndepADVar &x)
static ADcontext< Double > adc
ADvari< Double > ADVari
ADvari< Double > & acos(const ADvari< Double > &v)
static bool get_fpval_implies_const(void)
void f()
ADvar2q< Double > ADVar2q
static void Gradcomp()
asin(expr.val())
void ADvari_record(ADVari *x)
cosh(expr.val())
const Double * a
ADvari< Double > & asinh(const ADvari< Double > &v)
static void aval_reset()
expr expr dx(i)
abs(expr.val())
ADT_RAD IndepADvar< double > AI
ADvari< Double > & atan(const ADvari< Double > &v)
ADvari< Double > & sqrt(const ADvari< Double > &v)
ADVar2::ADVari ADVari
ADvar1< Double > ADVar1
static void Weighted_Gradcomp(int n, ADvar **v, Double *w)
ADvari< Double > & fabs(const ADvari< Double > &v)
Sacado::RadVec::ADvar< double > ADVar
void ADvar_ctr(Double d)
ADvar1s< Double > ADVar1s
ADvar2g< Double > ADVar2g
ADvar1< Double > ADVar1
Double val(const ADvari< Double > &)
#define RAD_ACA
static ConstADvari * lastcad
ADvar(const ADvar &x)
ADvari(Advari_Opclass oc, Double t, Double ta)
ConstADvari< Double > ConstADVari
ADvari< Double > & operator-(const ADvari< Double > &T)
ADvari< Double > ADVari
void AD_Const(const IndepADvar< Double > &)
ADvar1< Double > ADVar1
ADVar1::ADVari ADVari
ADvar2q(Double val1, Double Lp, Double Rp, Double LR, Double R2, const ADVari *Lcv, const ADVari *Rcv)
ADvari< Double > & cos(const ADvari< Double > &v)
atan(expr.val())
static void Weighted_Gradcomp(int, ADVar **, Double *)
ADVar::IndepADVar IndepADVar
ADvari< Double > ADVari
ADvari< Double > & asin(const ADvari< Double > &v)
ADvari< Double > & sin(const ADvari< Double > &v)
#define R
Definition: Sacado_rad.hpp:161
ADvar1< Double > ADVar1
static void Gradcomp(int wantgrad)
ADvarn(Double val1, int n1, const IndepADVar *x, const Double *g, const Double *h)
ADvari< Double > & max(const ADvari< Double > &L, const ADvari< Double > &R)
ADvar & operator+=(const ADVari &)
IndepADvar< Double > & ADvar_operatoreq(IndepADvar< Double > *, const ADvari< Double > &)
#define T
Definition: Sacado_rad.hpp:553
static void Hvprod(int n, ADVar **vp, Double *v, Double *hv)
Advari_Opclass opclass
tanh(expr.val())
ADvari< Double > ADVari
ADvari< Double > & log(const ADvari< Double > &v)
static const Double One
expr expr1 expr1 expr1 c expr2 expr1 expr2 expr1 expr2 expr1 expr1 expr1 expr1 c expr2 expr1 expr2 expr1 expr2 expr1 expr1 expr1 expr1 c *expr2 expr1 expr2 expr1 expr2 expr1 expr1 expr1 expr1 c expr2 expr1 expr2 expr1 expr2 expr1 expr1 expr1 expr2 expr1 expr2 expr1 expr1 expr1 expr2 expr1 expr2 expr1 expr1 expr1 c
ADVar2::ADVari ADVari
FloatingPoint< double > Double
ADvar2(Advari_Opclass oc, Double val1, const ADVari *Lcv, const Double *Lc, const ADVari *Rcv, const Double *Rc)
ADVar::ConstADVari ConstADVari
int operator>=(const ADvari< Double > &L, const ADvari< Double > &R)
#define T2(r, f)
Definition: Sacado_rad.hpp:558
static int rad_need_reinit
void AD_Const1(Double *, const IndepADvar< Double > &)
ADVari::IndepADVar IndepADVar
static Derp * LastDerp
int RAD_Const_Warn(void *v)
static void AD_Const(const IndepADvar &)
ConstADvar & operator=(Double d)
sqrt(expr.val())
sinh(expr.val())
ADmemblock< Double > ADMemblock
tan(expr.val())
ADvari< Double > & sinh(const ADvari< Double > &v)
ADvari< Double > & atanh(const ADvari< Double > &v)
ADvar1g< Double > ADVar1g
void * new_ADmemblock(size_t)
#define T1(r, f)
Definition: Sacado_rad.hpp:583
Derp< Double > DErp
void g()
ADvari< Double > & operator+(const ADvari< Double > &T)
int operator==(const ADvari< Double > &L, const ADvari< Double > &R)
static void Hvprod(int, ADVar **, Double *, Double *)
ADvari< Double > & pow(const ADvari< Double > &L, const ADvari< Double > &R)
int operator>(const ADvari< Double > &L, const ADvari< Double > &R)
ADvar2< Double > ADVar2
atan2(expr1.val(), expr2.val())
ADvar & operator*=(const ADVari &)
IndepADvar< Double > IndepADVar
static CADcontext< Double > cadc
ADvar2< Double > ADVar2
ADvari< Double > ADVari
IndepADvar & operator=(IndepADvar &x)
ADvari< Double > * cv
IndepADvar< Double > IndepADVar
ADvari< Double > & ADf2(Double f, Double gx, Double gy, const IndepADvar< Double > &x, const IndepADvar< Double > &y)
sin(expr.val())
ADvar1(Advari_Opclass oc, Double val1, const Double *a1, const ADVari *c1)
ADvari< Double > & atan2(const ADvari< Double > &L, const ADvari< Double > &R)
static void Gradcomp(int wantgrad)
log(expr.val())
static void Weighted_Gradcomp(int n, ADVar **v, Double *w)
ADvari< Double > ADVari
static void set_fpval_implies_const(bool newval)
ADvar & operator=(const ADVari &x)
ADvari< Double > ADVari
static void aval_reset(void)
ADvari_block< Double > ADVari_block
acos(expr.val())
ADvari< Double > & tan(const ADvari< Double > &v)
ADvari< Double > & operator*(const ADvari< Double > &L, const ADvari< Double > &R)
SACADO_INLINE_FUNCTION mpl::enable_if_c< ExprLevel< Expr< T1 > >::value==ExprLevel< Expr< T2 > >::value, Expr< PowerOp< Expr< T1 >, Expr< T2 > > > >::type pow(const Expr< T1 > &expr1, const Expr< T2 > &expr2)
ADvari< Double > & log10(const ADvari< Double > &v)
ADvari< Double > & operator/(const ADvari< Double > &L, const ADvari< Double > &R)
const ADVari * b
ADvari< Double > & cosh(const ADvari< Double > &v)
Derp< Double > DErp
ADvari< Double > & acosh(const ADvari< Double > &v)
ADvar2< Double > ADVar2
ADvar< Double > ADVar
ConstADvar & operator=(ADVari &d)
ADvari< Double > & min(const ADvari< Double > &L, const ADvari< Double > &R)
ADvarn< Double > ADVarn
exp(expr.val())
ScalarType< value_type >::type scalar_type
static bool setget_fpval_implies_const(bool newval)
ADvari(Advari_Opclass oc, Double t)
ADvar1s(Double val1, Double a1, const ADVari *c1)
ADvar(const ADVari &x)
ADvari< Double > & exp(const ADvari< Double > &v)
fabs(expr.val())
ADvari< Double > & ADf1(Double f, Double g, const IndepADvar< Double > &x)
Turn ADvar into a meta-function class usable with mpl::apply.
int n
ADvar2g(Double val1, Double Lp, Double Rp, Double L2, Double LR, Double R2, const ADVari *Lcv, const ADVari *Rcv)
log10(expr.val())
ADvari< Double > & tanh(const ADvari< Double > &v)
void * Memalloc(size_t len)
cos(expr.val())
ADVar1::ADVari ADVari
int operator!=(const ADvari< Double > &L, const ADvari< Double > &R)
ADvar & operator=(IndepADVar &x)
if(first)
Definition: uninit.c:110
const double y
ADvar & operator-=(const ADVari &)
ADvar & operator/=(const ADVari &)
ADvari< Double > & ADfn(Double f, int n, const IndepADvar< Double > *x, const Double *g)
ADvar1g(Double val1, Double d1, Double d2, const ADVari *c1)