Sacado_trad2.hpp

Go to the documentation of this file.
00001 // @HEADER
00002 // ***********************************************************************
00003 //
00004 //                           Sacado Package
00005 //                 Copyright (2007) Sandia Corporation
00006 //
00007 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00008 // the U.S. Government retains certain rights in this software.
00009 //
00010 // This library is free software; you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as
00012 // published by the Free Software Foundation; either version 2.1 of the
00013 // License, or (at your option) any later version.
00014 //
00015 // This library is distributed in the hope that it will be useful, but
00016 // WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 // Lesser General Public License for more details.
00019 //
00020 // You should have received a copy of the GNU Lesser General Public
00021 // License along with this library; if not, write to the Free Software
00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00023 // USA
00024 // Questions? Contact David M. Gay (dmgay@sandia.gov) or Eric T. Phipps
00025 // (etphipp@sandia.gov).
00026 //
00027 // ***********************************************************************
00028 // @HEADER
00029 
00030 // Extension of the RAD package (Reverse Automatic Differentiation) --
00031 // a package specialized for function and gradient evaluations -- to
00032 // Hessian-vector products.
00033 // Written in 2007 by David M. Gay at Sandia National Labs, Albuquerque, NM.
00034 
00035 #ifndef SACADO_TRAD2_H
00036 #define SACADO_TRAD2_H
00037 
00038 #include "Sacado_ConfigDefs.h"
00039 #include "Sacado_trad_Traits.hpp"
00040 
00041 #include <stddef.h>
00042 #include <cmath>
00043 #include <math.h>
00044 
00045 #ifdef RAD_Const_WARN // ==> RAD_AUTO_AD_Const and RAD_DEBUG
00046 #ifndef RAD_AUTO_AD_Const
00047 #define RAD_AUTO_AD_Const
00048 #endif
00049 #ifndef RAD_DEBUG
00050 #define RAD_DEBUG
00051 #endif
00052 extern "C" int RAD_Const_Warn(const void*);// outside any namespace for
00053           // ease in setting breakpoints
00054 #endif // RAD_Const_WARN
00055 
00056 #ifdef RAD_DEBUG
00057 #include <cstdio>
00058 #include <stdlib.h>
00059 #endif
00060 
00061 #ifndef RAD_AUTO_AD_Const
00062 #ifdef RAD_DEBUG_BLOCKKEEP
00063 #include <complex>  // must be here when SACADO_NAMESPACE is #defined
00064 #endif
00065 #endif
00066 
00067 namespace Sacado {
00068 namespace Rad2 {
00069 
00070 // -DRAD_NO_USING_STDCC is needed, e.g., with Sun CC 5.7
00071 #ifndef RAD_NO_USING_STDCC
00072   // Bring math functions into scope
00073   using std::exp;
00074   using std::log;
00075   using std::log10;
00076   using std::sqrt;
00077   using std::cos;
00078   using std::sin;
00079   using std::tan;
00080   using std::acos;
00081   using std::asin;
00082   using std::atan;
00083   using std::cosh;
00084   using std::sinh;
00085   using std::tanh;
00086   using std::abs;
00087   using std::fabs;
00088   using std::atan2;
00089   using std::pow;
00090 #endif 
00091 
00092 #ifdef RAD_AUTO_AD_Const
00093 #undef RAD_DEBUG_BLOCKKEEP
00094 #else 
00095 #ifdef RAD_DEBUG_BLOCKKEEP
00096 #if !(RAD_DEBUG_BLOCKKEEP > 0)
00097 #undef RAD_DEBUG_BLOCKKEEP
00098 #else
00099 extern "C" void _uninit_f2c(void *x, int type, long len);
00100 
00101 template <typename T>
00102 struct UninitType {};
00103 
00104 template <>
00105 struct UninitType<float> {
00106   static const int utype = 4;
00107 };
00108 
00109 template <>
00110 struct UninitType<double> {
00111   static const int utype = 5;
00112 };
00113 
00114 template <typename T>
00115 struct UninitType< std::complex<T> > {
00116   static const int utype = UninitType<T>::utype + 2;
00117 };
00118 
00119 #endif /*RAD_DEBUG_BLOCKKEEP > 0*/
00120 #endif /*RAD_DEBUG_BLOCKKEEP*/
00121 #endif /*RAD_AUTO_AD_Const*/
00122 
00123  class RAD_DoubleIgnore {};
00124 
00125  template<typename T> class
00126 DoubleAvoid {
00127  public:
00128   typedef double  dtype;
00129   typedef T ttype;
00130   };
00131  template<> class
00132 DoubleAvoid<double> {
00133  public:
00134   typedef RAD_DoubleIgnore &dtype;
00135   typedef RAD_DoubleIgnore &ttype;
00136   };
00137 
00138 #define Dtype typename DoubleAvoid<Double>::dtype
00139 #define Ttype typename DoubleAvoid<Double>::ttype
00140 
00141  template<typename Double> class IndepADvar;
00142  template<typename Double> class ConstADvar;
00143  template<typename Double> class ConstADvari;
00144  template<typename Double> class ADvar;
00145  template<typename Double> class ADvar1;
00146  template<typename Double> class ADvar1g;
00147  template<typename Double> class ADvar1s;
00148  template<typename Double> class ADvar2;
00149  template<typename Double> class ADvar2g;
00150  template<typename Double> class ADvar2q;
00151  template<typename Double> class ADvari;
00152  template<typename Double> class ADvari_block;
00153  template<typename Double> class ADvarn;
00154  template<typename Double> class Derp;
00155 
00156  template<typename Double> struct
00157 ADmemblock {  // We get memory in ADmemblock chunks and never give it back,
00158     // but reuse it once computations start anew after call(s) on
00159     // ADcontext::Gradcomp() or ADcontext::Weighted_Gradcomp().
00160   ADmemblock *next;
00161   Double memblk[2000];
00162   };
00163 
00164  template<typename Double> class
00165 ADvari_block {
00166  public:
00167   typedef ADvari<Double> ADVari;
00168   enum { Gulp = 1021 };
00169   ADvari_block *next, *prev;
00170   ADVari **limit;
00171   ADVari *pADvari[Gulp];
00172   };
00173 
00174  template<typename Double> class
00175 ADcontext { // A singleton class: one instance in radops.c
00176   typedef ADmemblock<Double> ADMemblock;
00177   typedef ADvari <Double> ADVari;
00178   typedef ADvar1 <Double> ADVar1;
00179   typedef ADvar2 <Double> ADVar2;
00180   typedef ADvarn <Double> ADVarn;
00181   typedef ADvar1g<Double> ADVar1g;
00182   typedef ADvar1s<Double> ADVar1s;
00183   typedef ADvar2g<Double> ADVar2g;
00184   typedef ADvar2q<Double> ADVar2q;
00185   typedef ADvari_block<Double> ADVari_block;
00186   ADMemblock *Busy, *Free;
00187   char *Mbase;
00188   size_t Mleft;
00189   ADVari **Ailimit, **Ainext;
00190   ADVari_block *Aibusy, *Aifree;
00191   ADMemblock *First;
00192   ADVari_block *AiFirst;
00193   double First0[(sizeof(ADMemblock) + sizeof(double) - 1) / sizeof(double)];
00194   double First1[(sizeof(ADVari_block) + sizeof(double) - 1) / sizeof(double)];
00195   void *new_ADmemblock(size_t);
00196   void new_ADvari_block();
00197   typedef ADvar<Double> ADVar;
00198   typedef Derp<Double> DErp;
00199   int rad_need_reinit;
00200   size_t rad_mleft_save;
00201 #ifdef RAD_DEBUG_BLOCKKEEP
00202   int rad_busy_blocks;
00203   ADMemblock *rad_Oldcurmb;
00204 #endif
00205  public:
00206   static const Double One, negOne;
00207   ADcontext();
00208   void *Memalloc(size_t len);
00209   static void Gradcomp();
00210   static void Hvprod(int, ADVar**, Double*, Double*);
00211   static void aval_reset(void);
00212   static void Weighted_Gradcomp(int, ADVar**, Double*);
00213   inline void ADvari_record(ADVari *x) {
00214     if (Ainext >= Ailimit)
00215       new_ADvari_block();
00216     *Ainext++ = x;
00217     }
00218   };
00219 
00220  template<typename Double> class
00221 CADcontext: public ADcontext<Double> {  // for possibly constant ADvar values
00222  protected:
00223   bool fpval_implies_const;
00224  public:
00225   friend class ADvar<Double>;
00226   CADcontext(): ADcontext<Double>() { fpval_implies_const = false; }
00227   };
00228 
00229  template<typename Double> class
00230 Derp {    // one derivative-propagation operation
00231  public:
00232   friend class ADvarn<Double>;
00233   typedef ADvari<Double> ADVari;
00234   static Derp *LastDerp;
00235   Derp *next;
00236   const Double *a;
00237   const ADVari *b;
00238   mutable ADVari *c;
00239   Derp(){};
00240   Derp(const ADVari *);
00241   Derp(const Double *, const ADVari *);
00242   Derp(const Double *, const ADVari *, const ADVari *);
00243   /* c->aval += a * b->aval; */
00244   };
00245 
00246 
00247 // Now we use #define to overcome bad design in the C++ templating system
00248 
00249 #define Ai const ADvari<Double>&
00250 #define AI const IndepADvar<Double>&
00251 #define T template<typename Double>
00252 #define D Double
00253 #define T1(f) \
00254 T F f (AI); \
00255 T F f (Ai);
00256 #define T2(r,f) \
00257  T r f(Ai,Ai); \
00258  T r f(Ai,D); \
00259  T r f(Ai,Dtype); \
00260  T r f(Ai,long); \
00261  T r f(Ai,int); \
00262  T r f(D,Ai); \
00263  T r f(Dtype,Ai); \
00264  T r f(long,Ai); \
00265  T r f(int,Ai); \
00266  T r f(AI,D); \
00267  T r f(AI,Dtype); \
00268  T r f(AI,long); \
00269  T r f(AI,int); \
00270  T r f(D,AI); \
00271  T r f(Dtype,AI); \
00272  T r f(long,AI); \
00273  T r f(int,AI); \
00274  T r f(Ai,AI);\
00275  T r f(AI,Ai);\
00276  T r f(AI,AI);
00277 
00278 #define F ADvari<Double>&
00279 T2(F, operator+)
00280 T2(F, operator-)
00281 T2(F, operator*)
00282 T2(F, operator/)
00283 T2(F, atan2)
00284 T2(F, pow)
00285 T2(F, max)
00286 T2(F, min)
00287 T2(int, operator<)
00288 T2(int, operator<=)
00289 T2(int, operator==)
00290 T2(int, operator!=)
00291 T2(int, operator>=)
00292 T2(int, operator>)
00293 T1(operator+)
00294 T1(operator-)
00295 T1(abs)
00296 T1(acos)
00297 T1(acosh)
00298 T1(asin)
00299 T1(asinh)
00300 T1(atan)
00301 T1(atanh)
00302 T1(cos)
00303 T1(cosh)
00304 T1(exp)
00305 T1(log)
00306 T1(log10)
00307 T1(sin)
00308 T1(sinh)
00309 T1(sqrt)
00310 T1(tan)
00311 T1(tanh)
00312 T1(fabs)
00313 
00314 T F copy(AI);
00315 T F copy(Ai);
00316 
00317 #undef F
00318 #undef T2
00319 #undef T1
00320 #undef D
00321 #undef T
00322 #undef AI
00323 #undef Ai
00324 
00325 } /* namespace Rad2 */
00326 } /* namespace Sacado */
00327 #define SNS Sacado::Rad2
00328 namespace std { // Moved here from bottom for use in testing nesting of Rad with itself.
00329   using SNS::exp;
00330   using SNS::log;
00331   using SNS::log10;
00332   using SNS::sqrt;
00333   using SNS::cos;
00334   using SNS::sin;
00335   using SNS::tan;
00336   using SNS::acos;
00337   using SNS::asin;
00338   using SNS::atan;
00339   using SNS::cosh;
00340   using SNS::sinh;
00341   using SNS::tanh;
00342   using SNS::abs;
00343   using SNS::fabs;
00344   using SNS::atan2;
00345   using SNS::pow;
00346 }
00347 #undef SNS
00348 namespace Sacado {
00349 namespace Rad2 {
00350 
00351  template<typename Double>ADvari<Double>& ADf1(Double f, Double g, const IndepADvar<Double> &x);
00352  template<typename Double>ADvari<Double>& ADf2(Double f, Double gx, Double gy,
00353   const IndepADvar<Double> &x, const IndepADvar<Double> &y);
00354  template<typename Double>ADvari<Double>& ADfn(Double f, int n,
00355   const IndepADvar<Double> *x, const Double *g);
00356 
00357  template<typename Double> IndepADvar<Double>& ADvar_operatoreq(IndepADvar<Double>*,
00358   const ADvari<Double>&);
00359  template<typename Double> ADvar<Double>& ADvar_operatoreq(ADvar<Double>*, const ADvari<Double>&);
00360  template<typename Double> void AD_Const(const IndepADvar<Double>&);
00361  template<typename Double> void AD_Const1(Double*, const IndepADvar<Double>&);
00362  template<typename Double> ADvari<Double>& ADf1(Double, Double, const ADvari<Double>&);
00363  template<typename Double> ADvari<Double>& ADf2(Double, Double, Double,
00364   const ADvari<Double>&, const ADvari<Double>&);
00365  template<typename Double> ADvari<Double>& ADf2(Double, Double, Double,
00366   const IndepADvar<Double>&, const ADvari<Double>&);
00367  template<typename Double> ADvari<Double>& ADf2(Double, Double, Double,
00368   const ADvari<Double>&, const IndepADvar<Double>&);
00369  template<typename Double> Double val(const ADvari<Double>&);
00370 
00371  enum Advari_Opclass {
00372   Hv_const,
00373   Hv_copy,
00374   Hv_binary,
00375   Hv_unary,
00376   Hv_negate,
00377   Hv_plusLR,
00378   Hv_minusLR,
00379   Hv_timesL,
00380   Hv_timesLR,
00381   Hv_quotLR,
00382   Hv_nary
00383   };
00384 
00385  template<typename Double> ADvari<Double>&
00386 ADf1(Double f, Double g, Double h, const ADvari<Double> &x);
00387 
00388  template<typename Double> ADvari<Double>&
00389 ADf2(Double f, Double gx, Double gy, Double hxx,
00390       Double hxy, Double hyy, const ADvari<Double> &x, const ADvari<Double> &y);
00391 
00392  template<typename Double> ADvari<Double>&
00393 ADfn(Double f, int n, const IndepADvar<Double> *x, const Double *g, const Double *h);
00394 
00395  template<typename Double> class
00396 ADvari {  // implementation of an ADvar
00397  public:
00398   typedef Double value_type;
00399   typedef IndepADvar<Double> IndepADVar;
00400 #ifdef RAD_AUTO_AD_Const
00401   friend class IndepADvar<Double>;
00402 #ifdef RAD_Const_WARN
00403   mutable const IndepADVar *padv;
00404 #else
00405  protected:
00406   mutable const IndepADVar *padv;
00407 #endif //RAD_Const_WARN
00408  private:
00409   ADvari *Next;
00410   static ADvari *First_ADvari, **Last_ADvari;
00411  public:
00412 #endif //RAD_AUTO_AD_Const
00413 #ifdef RAD_DEBUG
00414   int gcgen;
00415   int opno;
00416   static int gcgen_cur, last_opno, zap_gcgen, zap_gcgen1, zap_opno;
00417   static FILE *debug_file;
00418 #endif
00419   static ADcontext<Double> adc;
00420   Advari_Opclass opclass;
00421   Double Val;   // result of this operation
00422   mutable Double aval;  // adjoint -- partial of final result w.r.t. this Val
00423   mutable Double dO;  // deriv of op w.r.t. t in x + t*p
00424   mutable Double aO;  // adjoint (in Hv computation) of op
00425   mutable Double adO; // adjoint (in Hv computation) of dO
00426   void *operator new(size_t len) {
00427 #ifdef RAD_DEBUG
00428     ADvari *rv = (ADvari*)ADvari::adc.Memalloc(len);
00429     rv->gcgen = gcgen_cur;
00430     rv->opno = ++last_opno;
00431     if (last_opno == zap_opno && gcgen_cur == zap_gcgen)
00432       printf("");
00433     return rv;
00434 #else
00435     return ADvari::adc.Memalloc(len);
00436 #endif
00437     }
00438   void operator delete(void*) {} /*Should never be called.*/
00439   inline ADvari(Advari_Opclass oc, Double t):
00440     opclass(oc), Val(t), aval(0.), dO(0.)
00441     { if (oc != Hv_const) ADvari::adc.ADvari_record(this); }
00442   inline ADvari(Advari_Opclass oc, Double t, Double ta):
00443     opclass(oc), Val(t), aval(ta), dO(0.)
00444     { if (oc != Hv_const) ADvari::adc.ADvari_record(this); }
00445  private:
00446   inline ADvari(): Val(0.), aval(0.), dO(0.) {} // prevent construction without value (?)
00447  public:
00448   friend class ConstADvari<Double>;
00449 #ifdef RAD_AUTO_AD_Const
00450   friend class ADcontext<Double>;
00451   friend class ADvar<Double>;
00452   friend class ADvar1<Double>;
00453   friend class ADvar1s<Double>;
00454   friend class ADvar2<Double>;
00455   friend class ADvar2q<Double>;
00456   friend class ConstADvar<Double>;
00457   ADvari(const IndepADVar *, Double);
00458   ADvari(const IndepADVar *, Double, Double);
00459   ADvari(const IndepADVar *, Double, Double, int);
00460 #endif
00461 #define F friend
00462 #define R ADvari&
00463 #define Ai const ADvari&
00464 #define T1(r,f) F r f <>(Ai);
00465 #define T2(r,f) \
00466 F r f <>(Ai,Ai); \
00467 F r f <>(Ttype,Ai); \
00468 F r f <>(Ai,Ttype); \
00469 F r f <>(double,Ai); \
00470 F r f <>(Ai,double); \
00471 F r f <>(long,Ai); \
00472 F r f <>(Ai,long); \
00473 F r f <>(int,Ai); \
00474 F r f <>(Ai,int);
00475   T1(R,operator+)
00476   T2(R,operator+)
00477   T1(R,operator-)
00478   T2(R,operator-)
00479   T2(R,operator*)
00480   T2(R,operator/)
00481   T1(R,abs)
00482   T1(R,acos)
00483   T1(R,acosh)
00484   T1(R,asin)
00485   T1(R,asinh)
00486   T1(R,atan)
00487   T1(R,atanh)
00488   T2(R,atan2)
00489   T2(R,max)
00490   T2(R,min)
00491   T1(R,cos)
00492   T1(R,cosh)
00493   T1(R,exp)
00494   T1(R,log)
00495   T1(R,log10)
00496   T2(R,pow)
00497   T1(R,sin)
00498   T1(R,sinh)
00499   T1(R,sqrt)
00500   T1(R,tan)
00501   T1(R,tanh)
00502   T1(R,fabs)
00503   T1(R,copy)
00504   T2(int,operator<)
00505   T2(int,operator<=)
00506   T2(int,operator==)
00507   T2(int,operator!=)
00508   T2(int,operator>=)
00509   T2(int,operator>)
00510 #undef T2
00511 #undef T1
00512 #undef Ai
00513 #undef R
00514 #undef F
00515 
00516   friend ADvari& ADf1<>(Double f, Double g, Double h, const ADvari &x);
00517   friend ADvari& ADf2<>(Double f, Double gx, Double gy, Double hxx,
00518       Double hxy, Double hyy, const ADvari &x, const ADvari &y);
00519   friend ADvari& ADfn<>(Double f, int n, const IndepADVar *x,
00520       const Double *g, const Double *h);
00521 
00522   inline operator Double() { return this->Val; }
00523   inline operator Double() const { return this->Val; }
00524   };
00525 
00526  template<typename Double> class
00527 ADvar1: public ADvari<Double> { // simplest unary ops
00528  public:
00529   typedef ADvari<Double> ADVari;
00530   Derp<Double> d;
00531   ADvar1(Advari_Opclass oc, Double val1, const Double *a1, const ADVari *c1):
00532     ADVari(oc,val1), d(a1,this,c1) {}
00533 #ifdef RAD_AUTO_AD_Const
00534   typedef typename ADVari::IndepADVar IndepADVar;
00535   typedef ADvar<Double> ADVar;
00536   ADvar1(const IndepADVar*, const IndepADVar&);
00537   ADvar1(const IndepADVar*, const ADVari&);
00538   ADvar1(const Double val1, const Double *a1, const ADVari *c1, const ADVar *v):
00539       ADVari(val1), d(a1,this,c1) {
00540     c1->padv = 0;
00541     *ADVari::Last_ADvari = this;
00542     ADVari::Last_ADvari = &this->Next;
00543     this->padv = v;
00544     }
00545 #endif
00546   };
00547 
00548 
00549  template<typename Double> class
00550 ConstADvari: public ADvari<Double> {
00551  private:
00552   ConstADvari *prevcad;
00553   ConstADvari() {}; // prevent construction without value (?)
00554   static ConstADvari *lastcad;
00555  public:
00556   typedef ADvari<Double> ADVari;
00557   typedef Derp<Double> DErp;
00558   static CADcontext<Double> cadc;
00559   inline void *operator new(size_t len) { return ConstADvari::cadc.Memalloc(len); }
00560   inline ConstADvari(Double t): ADVari(Hv_copy, t) { prevcad = lastcad; lastcad = this; }
00561   static void aval_reset(void);
00562   };
00563 
00564 
00565  template<typename Double> class
00566 IndepADvar {    // an independent ADvar
00567  private:
00568   IndepADvar& operator=(IndepADvar&x) {
00569     /* private to prevent assignment */
00570 #ifdef RAD_AUTO_AD_Const
00571     if (cv)
00572       cv->padv = 0;
00573     cv = new ADvar1<Double>(this,x);
00574     return *this;
00575 #else
00576 #ifdef RAD_EQ_ALIAS
00577     this->cv = x.cv;
00578     return *this;
00579 #else
00580     return ADvar_operatoreq(this,*x.cv);
00581 #endif
00582 #endif
00583     }
00584  protected:
00585   static void AD_Const(const IndepADvar&);
00586   mutable ADvari<Double> *cv;
00587  public:
00588   typedef Double value_type;
00589   friend class ADvar<Double>;
00590   friend class ADcontext<Double>;
00591   friend class ADvar1<Double>;
00592   friend class ADvarn<Double>;
00593   typedef ADvari<Double> ADVari;
00594   typedef ADvar<Double> ADVar;
00595   IndepADvar(Ttype);
00596   IndepADvar(double);
00597   IndepADvar(int);
00598   IndepADvar(long);
00599   IndepADvar& operator= (Double);
00600 #ifdef RAD_AUTO_AD_Const
00601   inline IndepADvar(const IndepADvar &x) { cv = x.cv ? new ADvar1<Double>(this, x) : 0; };
00602   inline IndepADvar() { cv = 0; }
00603   inline ~IndepADvar() {
00604           if (cv)
00605             cv->padv = 0;
00606           }
00607 #else
00608   inline IndepADvar() {
00609 #ifndef RAD_EQ_ALIAS
00610     cv = 0;
00611 #endif
00612     }
00613   inline ~IndepADvar() {}
00614   friend IndepADvar& ADvar_operatoreq<>(IndepADvar*, const ADVari&);
00615 #endif
00616 
00617 #ifdef RAD_Const_WARN
00618   inline operator ADVari&() const {
00619     ADVari *tcv = this->cv;
00620     if (tcv->opno < 0)
00621       RAD_Const_Warn(tcv);
00622     return *tcv;
00623     }
00624   inline operator ADVari*() const {
00625     ADVari *tcv = this->cv;
00626     if (tcv->opno < 0)
00627       RAD_Const_Warn(tcv);
00628     return tcv;
00629     }
00630 #else //RAD_Const_WARN
00631   inline operator ADVari&() const { return *this->cv; }
00632   inline operator ADVari*() const { return this->cv; }
00633 #endif //RAD_Const_WARN
00634 
00635   Double val() const { return cv->Val; }
00636   Double adj() const { return cv->aval; }
00637 
00638   friend void AD_Const1<>(Double*, const IndepADvar&);
00639 
00640   friend ADVari& ADf1<>(Double, Double, const IndepADvar&);
00641   friend ADVari& ADf2<>(Double, Double, Double, const IndepADvar&, const IndepADvar&);
00642   friend ADVari& ADf2<>(Double, Double, Double, const ADVari&, const IndepADvar&);
00643   friend ADVari& ADf2<>(Double, Double, Double, const IndepADvar&, const ADVari&);
00644 
00645   static inline void Gradcomp() { ADcontext<Double>::Gradcomp(); }
00646   static inline void Hvprod(int n, ADVar **vp, Double *v, Double *hv)
00647         { ADcontext<Double>::Hvprod(n, vp, v, hv); }
00648   static inline void aval_reset() { ConstADvari<Double>::aval_reset(); }
00649   static inline void Weighted_Gradcomp(int n, ADVar **v, Double *w)
00650         { ADcontext<Double>::Weighted_Gradcomp(n, v, w); }
00651 
00652   /* We use #define to deal with bizarre templating rules that apparently */
00653   /* require us to spell the some conversion explicitly */
00654 
00655 
00656 #define Ai const ADVari&
00657 #define AI const IndepADvar&
00658 #define D Double
00659 #define T2(r,f) \
00660  r f <>(AI,AI);\
00661  r f <>(Ai,AI);\
00662  r f <>(AI,Ai);\
00663  r f <>(Ttype,AI);\
00664  r f <>(double,AI);\
00665  r f <>(long,AI);\
00666  r f <>(int,AI);\
00667  r f <>(AI,Ttype);\
00668  r f <>(AI,double);\
00669  r f <>(AI,long);\
00670  r f <>(AI,int);
00671 #define T1(f) friend ADVari& f<> (AI);
00672 
00673 #define F friend ADVari&
00674 T2(F, operator+)
00675 T2(F, operator-)
00676 T2(F, operator*)
00677 T2(F, operator/)
00678 T2(F, atan2)
00679 T2(F, max)
00680 T2(F, min)
00681 T2(F, pow)
00682 #undef F
00683 #define F friend int
00684 T2(F, operator<)
00685 T2(F, operator<=)
00686 T2(F, operator==)
00687 T2(F, operator!=)
00688 T2(F, operator>=)
00689 T2(F, operator>)
00690 
00691 T1(operator+)
00692 T1(operator-)
00693 T1(abs)
00694 T1(acos)
00695 T1(acosh)
00696 T1(asin)
00697 T1(asinh)
00698 T1(atan)
00699 T1(atanh)
00700 T1(cos)
00701 T1(cosh)
00702 T1(exp)
00703 T1(log)
00704 T1(log10)
00705 T1(sin)
00706 T1(sinh)
00707 T1(sqrt)
00708 T1(tan)
00709 T1(tanh)
00710 T1(fabs)
00711 T1(copy)
00712 
00713 #undef F
00714 #undef T1
00715 #undef T2
00716 #undef D
00717 #undef AI
00718 #undef Ai
00719 
00720   };
00721 
00722  template<typename Double> class
00723 ADvar: public IndepADvar<Double> {  // an "active" variable
00724  public:
00725   typedef IndepADvar<Double> IndepADVar;
00726   typedef typename IndepADVar::ADVari ADVari;
00727   typedef ConstADvari<Double> ConstADVari;
00728  private:
00729   void ADvar_ctr(Double d) {
00730     ADVari *x = ConstADVari::cadc.fpval_implies_const
00731       ? new ConstADVari(d)
00732 #ifdef RAD_AUTO_AD_Const
00733       : new ADVari((IndepADVar*)this, d);
00734 #else
00735       : new ADVari(Hv_const, d);
00736 #endif
00737     this->cv = x;
00738     }
00739  public:
00740   friend class ADvar1<Double>;
00741   typedef ADvar1<Double> ADVar1;
00742   ADvar() { /* cv = 0; */ }
00743   ADvar(Ttype d)  { ADvar_ctr(d); }
00744   ADvar(double i) { ADvar_ctr(Double(i)); }
00745   ADvar(int i)  { ADvar_ctr(Double(i)); }
00746   ADvar(long i) { ADvar_ctr(Double(i)); }
00747   inline ~ADvar() {}
00748 #ifdef RAD_AUTO_AD_Const
00749   inline ADvar(IndepADVar &x) {
00750     this->cv = x.cv ? new ADVar1(this, x) : 0;
00751     }
00752   inline ADvar(ADVari &x) { this->cv = &x; x.padv = this; }
00753   inline ADvar& operator=(IndepADVar &x) {
00754     if (this->cv)
00755       this->cv->padv = 0;
00756     this->cv = new ADVar1(this,x);
00757     return *this;
00758     }
00759   inline ADvar& operator=(ADVari &x) {
00760     if (this->cv)
00761       this->cv->padv = 0;
00762     this->cv = new ADVar1(this, x);
00763     return *this;
00764     }
00765 #else 
00766   friend ADvar& ADvar_operatoreq<>(ADvar*, const ADVari&);
00767 #ifdef RAD_EQ_ALIAS
00768   /* allow aliasing v and w after "v = w;" */
00769   inline ADvar(const IndepADVar &x) { this->cv = (ADVari*)x.cv; }
00770   inline ADvar(const ADVari &x) { this->cv = (ADVari*)&x; }
00771   inline ADvar& operator=(IndepADVar &x) { this->cv = (ADVari*)x.cv; return *this; }
00772   inline ADvar& operator=(const ADVari &x) { this->cv = (ADVari*)&x; return *this; }
00773 #else 
00774   ADvar(const IndepADVar &x) { this->cv = x.cv ? new ADVar1(x.cv->Val, &this->cv->adc.One, x.cv) : 0; }
00775   ADvar(const ADvar&x) { this->cv = x.cv ?
00776     new ADVar1(Hv_copy, x.cv->Val, &this->cv->adc.One, (ADVari*)x.cv) : 0; }
00777   ADvar(const ADVari &x) { this->cv = new ADVar1(Hv_copy, x.Val, &this->cv->adc.One, &x); }
00778   inline ADvar& operator=(IndepADVar &x) { return ADvar_operatoreq(this,*x.cv); };
00779   inline ADvar& operator=(const ADVari &x) { return ADvar_operatoreq(this,x); };
00780 #endif /* RAD_EQ_ALIAS */
00781 #endif /* RAD_AUTO_AD_Const */
00782   ADvar& operator=(Double);
00783   ADvar& operator+=(const ADVari&);
00784   ADvar& operator+=(Double);
00785   ADvar& operator-=(const ADVari&);
00786   ADvar& operator-=(Double);
00787   ADvar& operator*=(const ADVari&);
00788   ADvar& operator*=(Double);
00789   ADvar& operator/=(const ADVari&);
00790   ADvar& operator/=(Double);
00791   inline static bool get_fpval_implies_const(void)
00792     { return ConstADVari::cadc.fpval_implies_const; }
00793   inline static void set_fpval_implies_const(bool newval)
00794     { ConstADVari::cadc.fpval_implies_const = newval; }
00795   inline static bool setget_fpval_implies_const(bool newval) {
00796     bool oldval = ConstADVari::cadc.fpval_implies_const;
00797     ConstADVari::cadc.fpval_implies_const = newval;
00798     return oldval;
00799     }
00800   static inline void Gradcomp() { ADcontext<Double>::Gradcomp(); }
00801   static inline void aval_reset() { ConstADVari::aval_reset(); }
00802   static inline void Weighted_Gradcomp(int n, ADvar **v, Double *w)
00803         { ADcontext<Double>::Weighted_Gradcomp(n, v, w); }
00804   };
00805 
00806 template<typename Double>
00807  inline void AD_Const1(Double *notused, const IndepADvar<Double>&v)
00808 { IndepADvar<Double>::AD_Const(v); }
00809 
00810 template<typename Double>
00811  inline void AD_Const(const IndepADvar<Double>&v) { AD_Const1((Double*)0, v); }
00812 
00813  template<typename Double> class
00814 ConstADvar: public ADvar<Double> {
00815  public:
00816   typedef ADvar<Double> ADVar;
00817   typedef typename ADVar::ADVari ADVari;
00818   typedef typename ADVar::ConstADVari ConstADVari;
00819   typedef Derp<Double> DErp;
00820   typedef typename ADVar::IndepADVar IndepADVar;
00821  private: // disable op=
00822   ConstADvar& operator+=(ADVari&);
00823   ConstADvar& operator+=(Double);
00824   ConstADvar& operator-=(ADVari&);
00825   ConstADvar& operator-=(Double);
00826   ConstADvar& operator*=(ADVari&);
00827   ConstADvar& operator*=(Double);
00828   ConstADvar& operator/=(ADVari&);
00829   ConstADvar& operator/=(Double);
00830   void ConstADvar_ctr(Double);
00831  public:
00832   ConstADvar(Ttype d) { ConstADvar_ctr(d); }
00833   ConstADvar(double i)  { ConstADvar_ctr(Double(i)); }
00834   ConstADvar(int i) { ConstADvar_ctr(Double(i)); }
00835   ConstADvar(long i)  { ConstADvar_ctr(Double(i)); }
00836   ConstADvar(const IndepADVar&);
00837   ConstADvar(const ConstADvar&);
00838   ConstADvar(const ADVari&);
00839   inline ~ConstADvar() {}
00840 #ifdef RAD_NO_CONST_UPDATE
00841  private:
00842 #endif
00843   ConstADvar();
00844   inline ConstADvar& operator=(Double d) { this->cv->Val = d; return *this; }
00845   inline ConstADvar& operator=(ADVari& d) { this->cv->Val = d.Val; return *this; }
00846  };
00847 
00848  template<typename Double> class
00849 ADvar1s: public ADvar1<Double> { // unary ops with partials
00850  public:
00851   typedef ADvar1<Double> ADVar1;
00852   typedef typename ADVar1::ADVari ADVari;
00853   Double pL;  // deriv of op w.r.t. left operand L
00854   ADvar1s(Double val1, Double a1, const ADVari *c1):
00855     ADVar1(Hv_timesL,val1,&pL,c1), pL(a1) {}
00856 #ifdef RAD_AUTO_AD_Const
00857   typedef typename ADVar1::ADVar ADVar;
00858   ADvar1s(Double val1, Double a1, const ADVari *c1, const ADVar *v):
00859     ADVar1(val1,&a,c1,v), a(a1) {}
00860 #endif
00861   };
00862 
00863  template<typename Double> class
00864 ADvar1g: public ADvar1<Double> { // unary ops with partials
00865  public:
00866   typedef ADvar1<Double> ADVar1;
00867   typedef typename ADVar1::ADVari ADVari;
00868   Double pL;  // deriv of op w.r.t. left operand L
00869   Double pL2; // partial of op w.r.t. L,L
00870   ADvar1g(Double val1, Double d1, Double d2, const ADVari *c1):
00871     ADVar1(Hv_unary,val1,&pL,c1), pL(d1), pL2(d2) {}
00872   };
00873 
00874  template<typename Double> class
00875 ADvar2: public ADvari<Double> { // basic binary ops
00876  public:
00877   typedef ADvari<Double> ADVari;
00878   typedef Derp<Double> DErp;
00879   DErp dL, dR;
00880   ADvar2(Advari_Opclass oc, Double val1, const ADVari *Lcv, const Double *Lc,
00881     const ADVari *Rcv, const Double *Rc):
00882       ADVari(oc,val1) {
00883     dR.next = DErp::LastDerp;
00884     dL.next = &dR;
00885     DErp::LastDerp = &dL;
00886     dL.a = Lc;
00887     dL.c = (ADVari*)Lcv;
00888     dR.a = Rc;
00889     dR.c = (ADVari*)Rcv;
00890     dL.b = dR.b = this;
00891     }
00892 #ifdef RAD_AUTO_AD_Const
00893   typedef ADvar<Double> ADVar;
00894   ADvar2(Double val1, const ADVari *Lcv, const Double *Lc,
00895     const ADVari *Rcv, const Double *Rc, ADVar *v):
00896       ADVari(val1) {
00897     dR.next = DErp::LastDerp;
00898     dL.next = &dR;
00899     DErp::LastDerp = &dL;
00900     dL.a = Lc;
00901     dL.c = Lcv;
00902     dR.a = Rc;
00903     dR.c = Rcv;
00904     dL.b = dR.b = this;
00905     Lcv->padv = 0;
00906     *ADVari::Last_ADvari = this;
00907     ADVari::Last_ADvari = &this->Next;
00908     this->padv = v;
00909     }
00910 #endif
00911   };
00912 
00913  template<typename Double> class
00914 ADvar2q: public ADvar2<Double> { // binary ops with partials
00915  public:
00916   typedef ADvar2<Double> ADVar2;
00917   typedef typename ADVar2::ADVari ADVari;
00918   typedef typename ADVar2::DErp DErp;
00919   Double pL;  // deriv of op w.r.t. left operand L
00920   Double pR;  // deriv of op w.r.t. right operand R
00921   Double pLR; // second partial w.r.t. L,R
00922   Double pR2; // second partial w.r.t. R,R
00923   ADvar2q(Double val1, Double Lp, Double Rp, Double LR, Double R2,
00924     const ADVari *Lcv, const ADVari *Rcv):
00925       ADVar2(Hv_quotLR,val1,Lcv,&pL,Rcv,&pR),
00926       pL(Lp), pR(Rp), pLR(LR), pR2(R2) {}
00927 #ifdef RAD_AUTO_AD_Const
00928   typedef typename ADVar2::ADVar ADVar;
00929   ADvar2q(Double val1, Double Lp, Double Rp, Double LR, Double R2,
00930     const ADVari *Lcv, const ADVari *Rcv, const ADVar *v):
00931       ADVar2(Hv_quotLR,val1,Lcv,&pL,Rcv,&pR,v),
00932       pL(Lp), pR(Rp), pLR(LR), pR2(R2) {}
00933 #endif
00934   };
00935 
00936  template<typename Double> class
00937 ADvar2g: public ADvar2<Double> { // general binary ops with partials
00938  public:
00939   typedef ADvar2<Double> ADVar2;
00940   typedef typename ADVar2::ADVari ADVari;
00941   Double pL;  // deriv of op w.r.t. left operand L
00942   Double pR;  // deriv of op w.r.t. right operand R
00943   Double pL2; // second partial w.r.t. L,L
00944   Double pLR; // second partial w.r.t. L,R
00945   Double pR2; // second partial w.r.t. R,R
00946   ADvar2g(Double val1, Double Lp, Double Rp, Double L2, Double LR, Double R2,
00947     const ADVari *Lcv, const ADVari *Rcv):
00948       ADVar2(Hv_binary,val1,Lcv,&pL,Rcv,&pR),
00949       pL(Lp), pR(Rp), pL2(L2), pLR(LR), pR2(R2) { }
00950   };
00951 
00952  template<typename Double> class
00953 ADvarn: public ADvari<Double> { // n-ary ops with partials g and
00954         // 2nd partials h (lower triangle, rowwise)
00955  public:
00956   typedef ADvari<Double> ADVari;
00957   typedef ADvar<Double> ADVar;
00958   typedef typename ADVari::IndepADVar IndepADVar;
00959   typedef Derp<Double> DErp;
00960   int n;
00961   Double *G, *H;
00962   DErp *D;
00963   ADvarn(Double val1, int n1, const IndepADVar *x, const Double *g, const Double *h):
00964       ADVari(Hv_nary,val1), n(n1) {
00965     DErp *d1, *dlast;
00966     Double *a1;
00967     int i, nh;
00968 
00969     a1 = G = (Double*)ADVari::adc.Memalloc(n*sizeof(*g));
00970     d1 = D = (DErp*)ADVari::adc.Memalloc(n*sizeof(DErp));
00971     dlast = DErp::LastDerp;
00972     for(i = 0; i < n1; i++, d1++) {
00973       d1->next = dlast;
00974       dlast = d1;
00975       a1[i] = g[i];
00976       d1->a = &a1[i];
00977       d1->b = this;
00978       d1->c = x[i].cv;
00979       }
00980     DErp::LastDerp = dlast;
00981     nh = (n*(n+1)) >> 1;
00982     a1 = H = (double*)ADVari::adc.Memalloc(nh * sizeof(*h));
00983     for(i = 0; i < nh; i++)
00984       a1[i] = h[i];
00985     }
00986   };
00987 
00988 template<typename Double>
00989  inline ADvari<Double>& operator+(const ADvari<Double> &T) { return *(ADvari<Double>*)&T; }
00990 
00991 template<typename Double>
00992  inline int operator<(const ADvari<Double> &L, const ADvari<Double> &R) { return L.Val < R.Val; }
00993 template<typename Double>
00994  inline int operator<(const ADvari<Double> &L, Double R) { return L.Val < R; }
00995 template<typename Double>
00996  inline int operator<(Double L, const ADvari<Double> &R) { return L < R.Val; }
00997 
00998 template<typename Double>
00999  inline int operator<=(const ADvari<Double> &L, const ADvari<Double> &R) { return L.Val <= R.Val; }
01000 template<typename Double>
01001  inline int operator<=(const ADvari<Double> &L, Double R) { return L.Val <= R; }
01002 template<typename Double>
01003  inline int operator<=(Double L, const ADvari<Double> &R) { return L <= R.Val; }
01004 
01005 template<typename Double>
01006  inline int operator==(const ADvari<Double> &L, const ADvari<Double> &R) { return L.Val == R.Val; }
01007 template<typename Double>
01008  inline int operator==(const ADvari<Double> &L, Double R) { return L.Val == R; }
01009 template<typename Double>
01010  inline int operator==(Double L, const ADvari<Double> &R) { return L == R.Val; }
01011 
01012 template<typename Double>
01013  inline int operator!=(const ADvari<Double> &L, const ADvari<Double> &R) { return L.Val != R.Val; }
01014 template<typename Double>
01015  inline int operator!=(const ADvari<Double> &L, Double R) { return L.Val != R; }
01016 template<typename Double>
01017  inline int operator!=(Double L, const ADvari<Double> &R) { return L != R.Val; }
01018 
01019 template<typename Double>
01020  inline int operator>=(const ADvari<Double> &L, const ADvari<Double> &R) { return L.Val >= R.Val; }
01021 template<typename Double>
01022  inline int operator>=(const ADvari<Double> &L, Double R) { return L.Val >= R; }
01023 template<typename Double>
01024  inline int operator>=(Double L, const ADvari<Double> &R) { return L >= R.Val; }
01025 
01026 template<typename Double>
01027  inline int operator>(const ADvari<Double> &L, const ADvari<Double> &R) { return L.Val > R.Val; }
01028 template<typename Double>
01029  inline int operator>(const ADvari<Double> &L, Double R) { return L.Val > R; }
01030 template<typename Double>
01031  inline int operator>(Double L, const ADvari<Double> &R) { return L > R.Val; }
01032 
01033 template<typename Double>
01034  inline void *ADcontext<Double>::Memalloc(size_t len) {
01035     if (Mleft >= len)
01036       return Mbase + (Mleft -= len);
01037     return new_ADmemblock(len);
01038     }
01039 
01040 template<typename Double>
01041  inline Derp<Double>::Derp(const ADVari *c1): c((ADVari*)c1) {
01042     next = LastDerp;
01043     LastDerp = this;
01044     }
01045 
01046 template<typename Double>
01047  inline Derp<Double>::Derp(const Double *a1, const ADVari *c1): a(a1), c((ADVari*)c1) {
01048     next = LastDerp;
01049     LastDerp = this;
01050     }
01051 
01052 template<typename Double>
01053  inline Derp<Double>::Derp(const Double *a1, const ADVari *b1, const ADVari *c1):
01054   a(a1), b(b1), c((ADVari*)c1) {
01055     next = LastDerp;
01056     LastDerp = this;
01057     }
01058 
01059 /**** radops ****/
01060 
01061 template<typename Double> Derp<Double> *Derp<Double>::LastDerp = 0;
01062 template<typename Double> ADcontext<Double> ADvari<Double>::adc;
01063 template<typename Double> const Double ADcontext<Double>::One = 1.;
01064 template<typename Double> const Double ADcontext<Double>::negOne = -1.;
01065 template<typename Double> CADcontext<Double> ConstADvari<Double>::cadc;
01066 template<typename Double> ConstADvari<Double> *ConstADvari<Double>::lastcad;
01067 
01068 #ifdef RAD_AUTO_AD_Const
01069 template<typename Double> ADvari<Double>*   ADvari<Double>::First_ADvari;
01070 template<typename Double> ADvari<Double>**  ADvari<Double>::Last_ADvari = &ADvari<Double>::First_ADvari;
01071 #endif
01072 
01073 #ifdef RAD_DEBUG
01074 #ifndef RAD_DEBUG_gcgen1
01075 #define RAD_DEBUG_gcgen1 -1
01076 #endif
01077 template<typename Double> int ADvari<Double>::gcgen_cur;
01078 template<typename Double> int ADvari<Double>::last_opno;
01079 template<typename Double> int ADvari<Double>::zap_gcgen;
01080 template<typename Double> int ADvari<Double>::zap_gcgen1 = RAD_DEBUG_gcgen1;
01081 template<typename Double> int ADvari<Double>::zap_opno;
01082 template<typename Double> FILE *ADvari<Double>::debug_file;
01083 #endif
01084 
01085 
01086  template<typename Double>
01087 ADcontext<Double>::ADcontext()
01088 {
01089   ADVari_block *fb;
01090 
01091   First = (ADMemblock*)First0;
01092   First->next = 0;
01093   Busy = First;
01094   Free = 0;
01095   Mbase = (char*)First->memblk;
01096   Mleft = sizeof(First->memblk);
01097   AiFirst = Aibusy = fb = (ADVari_block*)First1;
01098   Aifree = 0;
01099   Ainext = fb->pADvari;
01100   fb->next = fb->prev = 0;
01101   fb->limit = Ailimit = fb->pADvari + ADVari_block::Gulp;
01102   rad_need_reinit = 0;
01103 #ifdef RAD_DEBUG_BLOCKKEEP
01104   rad_busy_blocks = 0;
01105   rad_mleft_save = 0;
01106   rad_Oldcurmb = 0;
01107 #endif
01108   }
01109 
01110 template<typename Double> void*
01111 ADcontext<Double>::new_ADmemblock(size_t len)
01112 {
01113   ADMemblock *mb, *mb0, *mb1, *mbf, *x;
01114   ADVari_block *b;
01115 
01116   if ((rad_need_reinit & 1) && this == &ADVari::adc) {
01117     rad_need_reinit &= ~1;
01118     DErp::LastDerp = 0;
01119     Aibusy = b = AiFirst;
01120     Aifree = b->next;
01121     b->next = b->prev = 0;
01122     Ailimit = b->limit = (Ainext = b->pADvari) + ADVari_block::Gulp;
01123 #ifdef RAD_DEBUG_BLOCKKEEP
01124     Mleft = rad_mleft_save;
01125     if (Mleft < sizeof(First->memblk))
01126       _uninit_f2c(Mbase + Mleft,
01127         UninitType<Double>::utype,
01128         (sizeof(First->memblk) - Mleft)
01129         /sizeof(typename Sacado::ValueType<Double>::type));
01130     if (mb = Busy->next) {
01131       if (!(mb0 = rad_Oldcurmb))
01132         mb0 = (ADMemblock*)First0;
01133       for(;; mb = mb->next) {
01134         _uninit_f2c(mb->memblk,
01135           UninitType<Double>::utype,
01136           sizeof(First->memblk)
01137           /sizeof(typename Sacado::ValueType<Double>::type));
01138         if (mb == mb0)
01139           break;
01140         }
01141       }
01142     rad_Oldcurmb = Busy;
01143     if (rad_busy_blocks >= RAD_DEBUG_BLOCKKEEP) {
01144       rad_busy_blocks = 0;
01145       rad_Oldcurmb = 0;
01146       mb0 = (ADMemblock*)First0;
01147       mbf =  Free;
01148       for(mb = Busy; mb != mb0; mb = mb1) {
01149         mb1 = mb->next;
01150         mb->next = mbf;
01151         mbf = mb;
01152         }
01153       Free = mbf;
01154       Busy = mb;
01155       Mbase = (char*)First->memblk;
01156       Mleft = sizeof(First->memblk);
01157       }
01158 
01159 #else /* !RAD_DEBUG_BLOCKKEEP */
01160 
01161     mb0 = First;
01162     mbf =  Free;
01163     for(mb = Busy; mb != mb0; mb = mb1) {
01164       mb1 = mb->next;
01165       mb->next = mbf;
01166       mbf = mb;
01167       }
01168     Free = mbf;
01169     Busy = mb;
01170     Mbase = (char*)First->memblk;
01171     Mleft = sizeof(First->memblk);
01172 #endif /*RAD_DEBUG_BLOCKKEEP*/
01173     if (Mleft >= len)
01174       return Mbase + (Mleft -= len);
01175     }
01176 
01177   if ((x = Free))
01178     Free = x->next;
01179   else
01180     x = new ADMemblock;
01181 #ifdef RAD_DEBUG_BLOCKKEEP
01182   rad_busy_blocks++;
01183 #endif
01184   x->next = Busy;
01185   Busy = x;
01186   return (Mbase = (char*)x->memblk) +
01187     (Mleft = sizeof(First->memblk) - len);
01188   }
01189 
01190 template<typename Double> void
01191 ADcontext<Double>::new_ADvari_block()
01192 {
01193   ADVari_block *ob, *nb;
01194   ob = Aibusy;
01195   ob->limit = Ailimit;  // should be unnecessary, but harmless
01196   if (nb = Aifree)
01197     Aifree = nb->next;
01198   else
01199     nb = new ADVari_block;
01200   Aibusy = Aibusy->next = nb;
01201   nb->limit = Ailimit = (Ainext = nb->pADvari) + ADVari_block::Gulp;
01202   ob->next = nb;
01203   nb->prev = ob;
01204   nb->next = 0;
01205   }
01206 
01207 template<typename Double> void
01208 ADcontext<Double>::Gradcomp()
01209 {
01210   DErp *d;
01211 #ifdef RAD_AUTO_AD_Const
01212   ADVari *a, *anext;
01213   IndepADvar<Double> *v;
01214 #ifdef RAD_Const_WARN
01215   ADVari *cv;
01216   int i, j;
01217 #endif
01218 #endif /*RAD_AUTO_AD_Const*/
01219 
01220   if (ADVari::adc.rad_need_reinit) {
01221     for(d = DErp::LastDerp; d; d = d->next)
01222       d->c->aval = 0;
01223     }
01224   if (!(ADVari::adc.rad_need_reinit & 1)) {
01225     ADVari::adc.rad_need_reinit = 1;
01226     ADVari::adc.rad_mleft_save = ADVari::adc.Mleft;
01227     ADVari::adc.Mleft = 0;
01228     }
01229 #ifdef RAD_DEBUG
01230   if (ADVari::gcgen_cur == ADVari::zap_gcgen1) {
01231     const char *fname;
01232     if (!(fname = getenv("RAD_DEBUG_FILE")))
01233       fname = "rad_debug.out";
01234     else if (!*fname)
01235       fname = 0;
01236     if (fname)
01237       ADVari::debug_file = fopen(fname, "w");
01238     ADVari::zap_gcgen1 = -1;
01239     }
01240 #endif
01241   if ((d = DErp::LastDerp)) {
01242     d->b->aval = 1;
01243 #ifdef RAD_DEBUG
01244     if (ADVari::debug_file)
01245       do {
01246         fprintf(ADVari::debug_file, "%d\t%d\t%g + %g * %g",
01247           d->c->opno, d->b->opno, d->c->aval, *d->a, d->b->aval);
01248         d->c->aval += *d->a * d->b->aval;
01249         fprintf(ADVari::debug_file, " = %g\n", d->c->aval);
01250         fflush(ADVari::debug_file);
01251         } while(d = d->next);
01252     else
01253 #endif
01254     do d->c->aval += *d->a * d->b->aval;
01255     while((d = d->next));
01256     }
01257 #ifdef RAD_DEBUG
01258   if (ADVari::debug_file) {
01259     fclose(ADVari::debug_file);
01260     ADVari::debug_file = 0;
01261     }
01262 #endif //RAD_DEBUG
01263 #ifdef RAD_AUTO_AD_Const
01264   *ADVari::Last_ADvari = 0;
01265   ADVari::Last_ADvari = &ADVari::First_ADvari;
01266   if ((anext = ADVari::First_ADvari) && !(ADVari::adc.rad_need_reinit & 2)) {
01267     ADVari::adc.rad_need_reinit = 3;
01268     while((a = anext)) {
01269       anext = a->Next;
01270       if ((v = (IndepADvar<Double> *)a->padv)) {
01271 #ifdef RAD_Const_WARN
01272         if ((i = a->opno) > 0)
01273           i = -i;
01274         j = a->gcgen;
01275         v->cv = cv = new ADVari(v, a->Val, a->aval);
01276         cv->opno = i;
01277         cv->gcgen = j;
01278 #else
01279         v->cv = new ADVari(v, a->Val, a->aval);
01280 #endif
01281         }
01282       }
01283     DErp::LastDerp = 0;
01284     }
01285 #endif /*RAD_AUTO_AD_Const*/
01286 #ifdef RAD_DEBUG
01287   ADVari::gcgen_cur++;
01288   ADVari::last_opno = 0;
01289 #endif
01290   }
01291 
01292 template<typename Double> void
01293 ADcontext<Double>::Weighted_Gradcomp(int n, ADVar **V, Double *w)
01294 {
01295   DErp *d;
01296   int i;
01297 #ifdef RAD_Const_WARN
01298   ADVari *cv;
01299   int j;
01300 #endif
01301 #ifdef RAD_AUTO_AD_Const
01302   ADVari *a, *anext;
01303   IndepADvar<Double> *v;
01304 #endif /*RAD_AUTO_AD_Const*/
01305 
01306   if (ADVari::adc.rad_need_reinit) {
01307     for(d = DErp::LastDerp; d; d = d->next)
01308       d->c->aval = 0;
01309     }
01310   if (!(ADVari::adc.rad_need_reinit & 1)) {
01311     ADVari::adc.rad_need_reinit = 1;
01312     ADVari::adc.rad_mleft_save = ADVari::adc.Mleft;
01313     ADVari::adc.Mleft = 0;
01314     }
01315 #ifdef RAD_DEBUG
01316   if (ADVari::gcgen_cur == ADVari::zap_gcgen1) {
01317     const char *fname;
01318     if (!(fname = getenv("RAD_DEBUG_FILE")))
01319       fname = "rad_debug.out";
01320     else if (!*fname)
01321       fname = 0;
01322     if (fname)
01323       ADVari::debug_file = fopen(fname, "w");
01324     ADVari::zap_gcgen1 = -1;
01325     }
01326 #endif
01327   if (d = DErp::LastDerp) {
01328     for(i = 0; i < n; i++)
01329       V[i]->cv->aval = w[i];
01330 #ifdef RAD_DEBUG
01331     if (ADVari::debug_file)
01332       do {
01333         fprintf(ADVari::debug_file, "%d\t%d\t%g + %g * %g",
01334           d->c->opno, d->b->opno, d->c->aval, *d->a, d->b->aval);
01335         d->c->aval += *d->a * d->b->aval;
01336         fprintf(ADVari::debug_file, " = %g\n", d->c->aval);
01337         fflush(ADVari::debug_file);
01338         } while(d = d->next);
01339     else
01340 #endif
01341     do d->c->aval += *d->a * d->b->aval;
01342     while(d = d->next);
01343     }
01344 #ifdef RAD_DEBUG
01345   if (ADVari::debug_file) {
01346     fclose(ADVari::debug_file);
01347     ADVari::debug_file = 0;
01348     }
01349 #endif //RAD_DEBUG
01350 #ifdef RAD_AUTO_AD_Const
01351   *ADVari::Last_ADvari = 0;
01352   ADVari::Last_ADvari = &ADVari::First_ADvari;
01353   if ((anext = ADVari::First_ADvari) && !(ADVari::adc.rad_need_reinit & 2)) {
01354     ADVari::adc.rad_need_reinit = 3;
01355     while(a = anext) {
01356       anext = a->Next;
01357       if (v = (IndepADvar<Double> *)a->padv) {
01358 #ifdef RAD_Const_WARN
01359         if ((i = a->opno) > 0)
01360           i = -i;
01361         j = a->gcgen;
01362         v->cv = cv = new ADVari(v, a->Val, a->aval);
01363         cv->opno = i;
01364         cv->gcgen = j;
01365 #else
01366         v->cv = new ADVari(v, a->Val, a->aval);
01367 #endif
01368         }
01369       }
01370     DErp::LastDerp = 0;
01371     }
01372 #endif /*RAD_AUTO_AD_Const*/
01373 #ifdef RAD_DEBUG
01374   ADVari::gcgen_cur++;
01375   ADVari::last_opno = 0;
01376 #endif
01377     }
01378 
01379  template<typename Double>
01380 IndepADvar<Double>::IndepADvar(Ttype d)
01381 {
01382 
01383   ADVari *x = new ADVari(Hv_const, d);
01384   cv = x;
01385   }
01386 
01387  template<typename Double>
01388 IndepADvar<Double>::IndepADvar(double i)
01389 {
01390 
01391   ADVari *x = new ADVari(Hv_const, Double(i));
01392   cv = x;
01393   }
01394 
01395  template<typename Double>
01396 IndepADvar<Double>::IndepADvar(int i)
01397 {
01398 
01399   ADVari *x = new ADVari(Hv_const, Double(i));
01400   cv = x;
01401   }
01402 
01403  template<typename Double>
01404 IndepADvar<Double>::IndepADvar(long i)
01405 {
01406 
01407   ADVari *x = new ADVari(Hv_const, Double(i));
01408   cv = x;
01409   }
01410 
01411  template<typename Double>
01412 ConstADvar<Double>::ConstADvar()
01413 {
01414   ConstADVari *x = new ConstADVari(0.);
01415   this->cv = x;
01416   }
01417 
01418  template<typename Double> void
01419 ConstADvar<Double>::ConstADvar_ctr(Double d)
01420 {
01421   ConstADVari *x = new ConstADVari(d);
01422   this->cv = x;
01423   }
01424 
01425  template<typename Double>
01426 ConstADvar<Double>::ConstADvar(const IndepADVar &x)
01427 {
01428   ConstADVari *y = new ConstADVari(x.cv->Val);
01429   DErp *d = new DErp(&x.adc.One, y, x.cv);
01430   this->cv = y;
01431   }
01432 
01433  template<typename Double>
01434 ConstADvar<Double>::ConstADvar(const ConstADvar &x)
01435 {
01436   ConstADVari *y = new ConstADVari(x.cv->Val);
01437   DErp *d = new DErp(&x.cv->adc.One, y, (ADVari*)x.cv);
01438   this->cv = y;
01439   }
01440 
01441  template<typename Double>
01442 ConstADvar<Double>::ConstADvar(const ADVari &x)
01443 {
01444   ConstADVari *y = new ConstADVari(x.Val);
01445   DErp *d = new DErp(&x.adc.One, y, &x);
01446   this->cv = y;
01447   }
01448 
01449  template<typename Double>
01450  void
01451 IndepADvar<Double>::AD_Const(const IndepADvar &v)
01452 {
01453   typedef ConstADvari<Double> ConstADVari;
01454 
01455   ConstADVari *ncv = new ConstADVari(v.val());
01456 #ifdef RAD_AUTO_AD_Const
01457   v.cv->padv = 0;
01458 #endif
01459   v.cv = ncv;
01460   }
01461 
01462  template<typename Double>
01463  void
01464 ConstADvari<Double>::aval_reset()
01465 {
01466   ConstADvari *x = ConstADvari::lastcad;
01467   while(x) {
01468     x->aval = 0;
01469     x = x->prevcad;
01470     }
01471   }
01472 
01473 #ifdef RAD_AUTO_AD_Const
01474 
01475  template<typename Double>
01476 ADvari<Double>::ADvari(const IndepADVar *x, Double d): Val(d), aval(0.)
01477 {
01478   opclass = Hv_const;
01479   *Last_ADvari = this;
01480   Last_ADvari = &Next;
01481   this->padv = (IndepADVar*)x;
01482   }
01483 
01484  template<typename Double>
01485 ADvari<Double>::ADvari(const IndepADVar *x, Double d, Double g): Val(d), aval(g)
01486 {
01487   *Last_ADvari = this;
01488   Last_ADvari = &Next;
01489   this->padv = (IndepADVar*)x;
01490   }
01491 
01492  template<typename Double>
01493 ADvar1<Double>::ADvar1(const IndepADVar *x, const IndepADVar &y):
01494   ADVari(Hv_copy, y.cv->Val), d((const Double*)&ADcontext<Double>::One, (ADVari*)this, y.cv)
01495 {
01496   *ADVari::Last_ADvari = this;
01497   ADVari::Last_ADvari = &this->Next;
01498   this->padv = x;
01499   }
01500 
01501  template<typename Double>
01502 ADvar1<Double>::ADvar1(const IndepADVar *x, const ADVari &y):
01503   ADVari(Hv_copy, y.Val), d((const Double*)&ADcontext<Double>::One, this, &y)
01504 {
01505   *ADVari::Last_ADvari = this;
01506   ADVari::Last_ADvari = &this->Next;
01507   this->padv = x;
01508   }
01509 
01510 #else /* !RAD_AUTO_AD_Const */
01511 
01512  template<typename Double>
01513  IndepADvar<Double>&
01514 ADvar_operatoreq(IndepADvar<Double> *This, const ADvari<Double> &x)
01515 { This->cv = new ADvar1<Double>(Hv_copy, x.Val, &x.adc.One, &x);
01516   return *(IndepADvar<Double>*) This; }
01517 
01518  template<typename Double>
01519  ADvar<Double>&
01520 ADvar_operatoreq(ADvar<Double> *This, const ADvari<Double> &x)
01521 { This->cv = new ADvar1<Double>(Hv_copy, x.Val, &x.adc.One, &x); return *(ADvar<Double>*) This; }
01522 
01523 #endif /* RAD_AUTO_AD_Const */
01524 
01525 
01526  template<typename Double>
01527  IndepADvar<Double>&
01528 IndepADvar<Double>::operator=(Double d)
01529 {
01530 #ifdef RAD_AUTO_AD_Const
01531   if (this->cv)
01532     this->cv->padv = 0;
01533   this->cv = new ADVari(Hv_const, this,d);
01534 #else
01535   this->cv = new ADVari(Hv_const, d);
01536 #endif
01537   return *this;
01538   }
01539 
01540  template<typename Double>
01541  ADvar<Double>&
01542 ADvar<Double>::operator=(Double d)
01543 {
01544 #ifdef RAD_AUTO_AD_Const
01545   if (this->cv)
01546     this->cv->padv = 0;
01547   this->cv = new ADVari(Hv_const, this,d);
01548 #else
01549   this->cv = ConstADVari::cadc.fpval_implies_const
01550     ? new ConstADVari(d)
01551     : new ADVari(Hv_const, d);
01552 #endif
01553   return *this;
01554   }
01555 
01556  template<typename Double>
01557  ADvari<Double>&
01558 operator-(const ADvari<Double> &T) {
01559   return *(new ADvar1<Double>(Hv_negate, -T.Val, &T.adc.negOne, &T));
01560   }
01561 
01562  template<typename Double>
01563  ADvari<Double>&
01564 operator+(const ADvari<Double> &L, const ADvari<Double> &R) {
01565   return *(new ADvar2<Double>(Hv_plusLR, L.Val + R.Val, &L, &L.adc.One, &R, &L.adc.One));
01566   }
01567 
01568 #ifdef RAD_AUTO_AD_Const
01569 #define RAD_ACA ,this
01570 #else
01571 #define RAD_ACA /*nothing*/
01572 #endif
01573 
01574  template<typename Double>
01575  ADvar<Double>&
01576 ADvar<Double>::operator+=(const ADVari &R) {
01577   ADVari *Lcv = this->cv;
01578   this->cv = new ADvar2<Double>(Hv_plusLR, Lcv->Val + R.Val, Lcv,
01579           &R.adc.One, &R, &R.adc.One RAD_ACA);
01580   return *this;
01581   }
01582 
01583  template<typename Double>
01584  ADvari<Double>&
01585 operator+(const ADvari<Double> &L, Double R) {
01586   return *(new ADvar1<Double>(Hv_copy, L.Val + R, &L.adc.One, &L));
01587   }
01588 
01589  template<typename Double>
01590  ADvar<Double>&
01591 ADvar<Double>::operator+=(Double R) {
01592   ADVari *tcv = this->cv;
01593   this->cv = new ADVar1(Hv_copy, tcv->Val + R, &tcv->adc.One, tcv RAD_ACA);
01594   return *this;
01595   }
01596 
01597  template<typename Double>
01598  ADvari<Double>&
01599 operator+(Double L, const ADvari<Double> &R) {
01600   return *(new ADvar1<Double>(Hv_copy, L + R.Val, &R.adc.One, &R));
01601   }
01602 
01603  template<typename Double>
01604  ADvari<Double>&
01605 operator-(const ADvari<Double> &L, const ADvari<Double> &R) {
01606   return *(new ADvar2<Double>(Hv_minusLR, L.Val - R.Val, &L, &L.adc.One, &R, &L.adc.negOne));
01607   }
01608 
01609  template<typename Double>
01610  ADvar<Double>&
01611 ADvar<Double>::operator-=(const ADVari &R) {
01612   ADVari *Lcv = this->cv;
01613   this->cv = new ADvar2<Double>(Hv_minusLR,Lcv->Val - R.Val, Lcv,
01614           &R.adc.One, &R, &R.adc.negOne RAD_ACA);
01615   return *this;
01616   }
01617 
01618  template<typename Double>
01619  ADvari<Double>&
01620 operator-(const ADvari<Double> &L, Double R) {
01621   return *(new ADvar1<Double>(Hv_copy, L.Val - R, &L.adc.One, &L));
01622   }
01623 
01624  template<typename Double>
01625  ADvar<Double>&
01626 ADvar<Double>::operator-=(Double R) {
01627   ADVari *tcv = this->cv;
01628   this->cv = new ADVar1(Hv_copy, tcv->Val - R, &tcv->adc.One, tcv RAD_ACA);
01629   return *this;
01630   }
01631 
01632  template<typename Double>
01633  ADvari<Double>&
01634 operator-(Double L, const ADvari<Double> &R) {
01635   return *(new ADvar1<Double>(Hv_negate, L - R.Val, &R.adc.negOne, &R));
01636   }
01637 
01638  template<typename Double>
01639  ADvari<Double>&
01640 operator*(const ADvari<Double> &L, const ADvari<Double> &R) {
01641   return *(new ADvar2<Double>(Hv_timesLR, L.Val * R.Val, &L, &R.Val, &R, &L.Val));
01642   }
01643 
01644  template<typename Double>
01645  ADvar<Double>&
01646 ADvar<Double>::operator*=(const ADVari &R) {
01647   ADVari *Lcv = this->cv;
01648   this->cv = new ADvar2<Double>(Hv_timesLR, Lcv->Val * R.Val, Lcv,
01649           &R.Val, &R, &Lcv->Val RAD_ACA);
01650   return *this;
01651   }
01652 
01653  template<typename Double>
01654  ADvari<Double>&
01655 operator*(const ADvari<Double> &L, Double R) {
01656   return *(new ADvar1s<Double>(L.Val * R, R, &L));
01657   }
01658 
01659  template<typename Double>
01660  ADvar<Double>&
01661 ADvar<Double>::operator*=(Double R) {
01662   ADVari *Lcv = this->cv;
01663   this->cv = new ADvar1s<Double>(Lcv->Val * R, R, Lcv RAD_ACA);
01664   return *this;
01665   }
01666 
01667  template<typename Double>
01668  ADvari<Double>&
01669 operator*(Double L, const ADvari<Double> &R) {
01670   return *(new ADvar1s<Double>(L * R.Val, L, &R));
01671   }
01672 
01673  template<typename Double>
01674  ADvari<Double>&
01675 operator/(const ADvari<Double> &L, const ADvari<Double> &R) {
01676   Double Lv = L.Val, Rv = R.Val, pL = 1. / Rv, q = Lv/Rv, qpL = q*pL;
01677   return *(new ADvar2q<Double>(q, pL, -qpL, -pL*pL, 2.*pL*qpL, &L, &R));
01678   }
01679 
01680  template<typename Double>
01681  ADvar<Double>&
01682 ADvar<Double>::operator/=(const ADVari &R) {
01683   ADVari *Lcv = this->cv;
01684   Double Lv = Lcv->Val, Rv = R.Val, pL = 1. / Rv, q = Lv/Rv, qpL = q*pL;
01685   this->cv = new ADvar2q<Double>(q, pL, -qpL, -pL*pL, 2.*pL*qpL, Lcv, &R RAD_ACA);
01686   return *this;
01687   }
01688 
01689  template<typename Double>
01690  ADvari<Double>&
01691 operator/(const ADvari<Double> &L, Double R) {
01692   return *(new ADvar1s<Double>(L.Val / R, 1./R, &L));
01693   }
01694 
01695  template<typename Double>
01696  ADvari<Double>&
01697 operator/(Double L, const ADvari<Double> &R) {
01698   Double recip = 1. / R.Val;
01699   Double q = L * recip;
01700   Double d1 = -q*recip;
01701   return *(new ADvar1g<Double>(q, d1, -q*d1, &R));
01702   }
01703 
01704  template<typename Double>
01705  ADvar<Double>&
01706 ADvar<Double>::operator/=(Double R) {
01707   ADVari *Lcv = this->cv;
01708   this->cv = new ADvar1s<Double>(Lcv->Val / R, 1./R, Lcv RAD_ACA);
01709   return *this;
01710   }
01711 
01712  template<typename Double>
01713  ADvari<Double>&
01714 acos(const ADvari<Double> &v) {
01715   Double t = v.Val, t1 = 1. - t*t, d1 = -1./std::sqrt(t1);
01716   return *(new ADvar1g<Double>(std::acos(t), d1, t*d1/t1, &v));
01717   }
01718 
01719  template<typename Double>
01720  ADvari<Double>&
01721 acosh(const ADvari<Double> &v) {
01722   Double d1, t, t1, t2;
01723   t = v.Val;
01724   t1 = std::sqrt(t2 = t*t - 1.);
01725   d1 = 1. / t1;
01726   return *(new ADvar1g<Double>(std::log(t + t1), d1, -t*d1/t2, &v));
01727   }
01728 
01729  template<typename Double>
01730  ADvari<Double>&
01731 asin(const ADvari<Double> &v) {
01732   Double d1, t, t1;
01733   t = v.Val;
01734   d1 = 1. / std::sqrt(t1 = 1. - t*t);
01735   return *(new ADvar1g<Double>(std::asin(t), d1, t*d1/t1, &v));
01736   }
01737 
01738  template<typename Double>
01739  ADvari<Double>&
01740 asinh(const ADvari<Double> &v) {
01741   Double d1, t, t1, t2, td;
01742   t = v.Val;
01743   t1 = std::sqrt(t2 = t*t + 1.);
01744   d1 = 1. / t1;
01745   td = 1.;
01746   if (t < 0.)
01747     td = -1.;
01748   return *(new ADvar1g<Double>(td*std::log(t*td + t1), d1, -(t/t2)*d1, &v));
01749   }
01750 
01751  template<typename Double>
01752  ADvari<Double>&
01753 atan(const ADvari<Double> &v) {
01754   Double t = v.Val, d1 = 1./(1. + t*t);
01755   return *(new ADvar1g<Double>(std::atan(t), d1, -(t+t)*d1*d1, &v));
01756   }
01757 
01758  template<typename Double>
01759  ADvari<Double>&
01760 atanh(const ADvari<Double> &v) {
01761   Double t = v.Val, d1 = 1./(1. - t*t);
01762   return *(new ADvar1g<Double>(0.5*std::log((1.+t)/(1.-t)), d1, (t+t)*d1*d1, &v));
01763   }
01764 
01765  template<typename Double>
01766  ADvari<Double>&
01767 atan2(const ADvari<Double> &L, const ADvari<Double> &R) {
01768   Double R2, t, t2, x, x2, y, y2;
01769   x = L.Val;
01770   y = R.Val;
01771   x2 = x*x;
01772   y2 = y*y;
01773   t = 1./(x2 + y2);
01774   t2 = t*t;
01775   R2 = 2.*t2*x*y;
01776   return *(new ADvar2g<Double>(std::atan2(x,y), y*t, -x*t, -R2, t2*(x2 - y2), R2, &L, &R));
01777   }
01778 
01779  template<typename Double>
01780  ADvari<Double>&
01781 atan2(Double x, const ADvari<Double> &R) {
01782   Double t, x2, y, y2;
01783   y = R.Val;
01784   x2 = x*x;
01785   y2 = y*y;
01786   t = 1./(x2 + y2);
01787   return *(new ADvar1g<Double>(std::atan2(x,y), -x*t, 2.*t*t*x*y, &R));
01788   }
01789 
01790  template<typename Double>
01791  ADvari<Double>&
01792 atan2(const ADvari<Double> &L, Double y) {
01793   Double t, x, x2, y2;
01794   x = L.Val;
01795   x2 = x*x;
01796   y2 = y*y;
01797   t = 1./(x2 + y2);
01798   return *(new ADvar1g<Double>(std::atan2(x,y), y*t, -2.*t*t*x*y, &L));
01799   }
01800 
01801  template<typename Double>
01802  ADvari<Double>&
01803 max(const ADvari<Double> &L, const ADvari<Double> &R) {
01804   const ADvari<Double> &x = L.Val >= R.Val ? L : R;
01805   return *(new ADvar1<Double>(Hv_copy, x.Val, &x.adc.One, &x));
01806   }
01807 
01808  template<typename Double>
01809  ADvari<Double>&
01810 max(Double L, const ADvari<Double> &R) {
01811   if (L >= R.Val)
01812     return *(new ADvari<Double>(Hv_const, L));
01813   return *(new ADvar1<Double>(Hv_copy, R.Val, &R.adc.One, &R));
01814   }
01815 
01816  template<typename Double>
01817  ADvari<Double>&
01818 max(const ADvari<Double> &L, Double R) {
01819   if (L.Val >= R)
01820     return *(new ADvar1<Double>(Hv_copy, L.Val, &L.adc.One, &L));
01821   return *(new ADvari<Double>(Hv_const, R));
01822   }
01823 
01824  template<typename Double>
01825  ADvari<Double>&
01826 min(const ADvari<Double> &L, const ADvari<Double> &R) {
01827   const ADvari<Double> &x = L.Val <= R.Val ? L : R;
01828   return *(new ADvar1<Double>(Hv_copy, x.Val, &x.adc.One, &x));
01829   }
01830 
01831  template<typename Double>
01832  ADvari<Double>&
01833 min(Double L, const ADvari<Double> &R) {
01834   if (L <= R.Val)
01835     return *(new ADvari<Double>(Hv_const, L));
01836   return *(new ADvar1<Double>(Hv_copy, R.Val, &R.adc.One, &R));
01837   }
01838 
01839  template<typename Double>
01840  ADvari<Double>&
01841 min(const ADvari<Double> &L, Double R) {
01842   if (L.Val <= R)
01843     return *(new ADvar1<Double>(Hv_copy, L.Val, &L.adc.One, &L));
01844   return *(new ADvari<Double>(Hv_const, R));
01845   }
01846 
01847  template<typename Double>
01848  ADvari<Double>&
01849 cos(const ADvari<Double> &v) {
01850   Double t = std::cos(v.Val);
01851   return *(new ADvar1g<Double>(t, -std::sin(v.Val), -t, &v));
01852   }
01853 
01854  template<typename Double>
01855  ADvari<Double>&
01856 cosh(const ADvari<Double> &v) {
01857   Double t = std::cosh(v.Val);
01858   return *(new ADvar1g<Double>(t, std::sinh(v.Val), t, &v));
01859   }
01860 
01861  template<typename Double>
01862  ADvari<Double>&
01863 exp(const ADvari<Double> &v) {
01864   Double t = std::exp(v.Val);
01865   return *(new ADvar1g<Double>(t, t, t, &v));
01866   }
01867 
01868  template<typename Double>
01869  ADvari<Double>&
01870 log(const ADvari<Double> &v) {
01871   Double x = v.Val, d1 = 1. / x;
01872   return *(new ADvar1g<Double>(std::log(x), d1, -d1*d1, &v));
01873   }
01874 
01875  template<typename Double>
01876  ADvari<Double>&
01877 log10(const ADvari<Double> &v) {
01878   static double num = 1. / std::log(10.);
01879   Double d1, t, x;
01880   x = v.Val;
01881   t = 1. / x;
01882   d1 = num * t;
01883   return *(new ADvar1g<Double>(std::log10(x), d1, -d1*t, &v));
01884   }
01885 
01886  template<typename Double>
01887  ADvari<Double>&
01888 pow(const ADvari<Double> &L, const ADvari<Double> &R) {
01889   Double dx, dy, t, x, xlog, xym1, y;
01890   x = L.Val;
01891   y = R.Val;
01892   t = std::pow(x,y);
01893   xym1 = t / x;
01894   xlog = std::log(x);
01895   dx = y*xym1;
01896   dy = t * xlog;
01897   return *(new ADvar2g<Double>(t, dx, dy, (y-1.)*dx/x, xym1*(1. + y*xlog), dy*xlog, &L, &R));
01898   }
01899 
01900  template<typename Double>
01901  ADvari<Double>&
01902 pow(Double x, const ADvari<Double> &R) {
01903   Double dy, t, xlog, y;
01904   y = R.Val;
01905   t = std::pow(x,y);
01906   xlog = std::log(x);
01907   dy = t * xlog;
01908   return *(new ADvar1g<Double>(t, dy, dy*xlog, &R));
01909   }
01910 
01911  template<typename Double>
01912  ADvari<Double>&
01913 pow(const ADvari<Double> &L, Double y) {
01914   Double dx, t, x;
01915   x = L.Val;
01916   t = std::pow(x,y);
01917   dx = y*t/x;
01918   return *(new ADvar1g<Double>(t, dx, (y-1.)*dx/x, &L));
01919   }
01920 
01921  template<typename Double>
01922  ADvari<Double>&
01923 sin(const ADvari<Double> &v) {
01924   Double t = std::sin(v.Val);
01925   return *(new ADvar1g<Double>(t, std::cos(v.Val), -t, &v));
01926   }
01927 
01928  template<typename Double>
01929  ADvari<Double>&
01930 sinh(const ADvari<Double> &v) {
01931   Double t = std::sinh(v.Val);
01932   return *(new ADvar1g<Double>(t, std::cosh(v.Val), t, &v));
01933   }
01934 
01935  template<typename Double>
01936  ADvari<Double>&
01937 sqrt(const ADvari<Double> &v) {
01938   Double t = std::sqrt(v.Val);
01939   Double d1 = 0.5 / t;
01940   return *(new ADvar1g<Double>(t, d1, -0.5*d1/v.Val, &v));
01941   }
01942 
01943  template<typename Double>
01944  ADvari<Double>&
01945 tan(const ADvari<Double> &v) {
01946   Double d1, rv, t;
01947   rv = std::tan(v.Val);
01948   t = 1. / std::cos(v.Val);
01949   d1 = t*t;
01950   return *(new ADvar1g<Double>(rv, d1, (rv+rv)*d1, &v));
01951   }
01952 
01953  template<typename Double>
01954  ADvari<Double>&
01955 tanh(const ADvari<Double> &v) {
01956   Double d1, rv, t;
01957   rv = std::tanh(v.Val);
01958   t = 1. / std::cosh(v.Val);
01959   d1 = t*t;
01960   return *(new ADvar1g<Double>(rv, d1, -(rv+rv)*d1, &v));
01961   }
01962 
01963  template<typename Double>
01964  ADvari<Double>&
01965 abs(const ADvari<Double> &v) {
01966   Double t, p;
01967   p = 1.;
01968   if ((t = v.Val) < 0) {
01969     t = -t;
01970     p = -p;
01971     }
01972   return *(new ADvar1g<Double>(t, p, 0., &v));
01973   }
01974 
01975  template<typename Double>
01976  ADvari<Double>&
01977 fabs(const ADvari<Double> &v) { // Synonym for "abs"
01978         // "fabs" is not the best choice of name,
01979         // but this name is used at Sandia.
01980   Double t, p;
01981   p = 1.;
01982   if ((t = v.Val) < 0) {
01983     t = -t;
01984     p = -p;
01985     }
01986   return *(new ADvar1g<Double>(t, p, 0., &v));
01987   }
01988 
01989  template<typename Double>
01990  ADvari<Double>&
01991 ADf1(Double f, Double g, Double h, const ADvari<Double> &x) {
01992   return *(new ADvar1g<Double>(f, g, h, &x));
01993   }
01994 
01995  template<typename Double>
01996  inline ADvari<Double>&
01997 ADf1(Double f, Double g, Double h, const IndepADvar<Double> &x) {
01998   return *(new ADvar1g<Double>(f, g, h, x.cv));
01999   }
02000 
02001  template<typename Double>
02002  ADvari<Double>&
02003 ADf2(Double f, Double gx, Double gy, Double hxx, Double hxy, Double hyy,
02004     const ADvari<Double> &x, const ADvari<Double> &y) {
02005   return *(new ADvar2g<Double>(f, gx, gy, hxx, hxy, hyy, &x, &y));
02006   }
02007 
02008  template<typename Double>
02009  ADvari<Double>&
02010 ADf2(Double f, Double gx, Double gy, Double hxx, Double hxy, Double hyy,
02011     const ADvari<Double> &x, const IndepADvar<Double> &y) {
02012   return *(new ADvar2g<Double>(f, gx, gy, hxx, hxy, hyy, &x, y.cv));
02013   }
02014 
02015  template<typename Double>
02016  ADvari<Double>&
02017 ADf2(Double f, Double gx, Double gy, Double hxx, Double hxy, Double hyy,
02018     const IndepADvar<Double> &x, const ADvari<Double> &y) {
02019   return *(new ADvar2g<Double>(f, gx, gy, hxx, hxy, hyy, x.cv, &y));
02020   }
02021 
02022  template<typename Double>
02023  ADvari<Double>&
02024 ADf2(Double f, Double gx, Double gy, Double hxx, Double hxy, Double hyy,
02025     const IndepADvar<Double> &x, const IndepADvar<Double> &y) {
02026   return *(new ADvar2g<Double>(f, gx, gy, hxx, hxy, hyy, x.cv, y.cv));
02027   }
02028 
02029  template<typename Double>
02030  ADvari<Double>&
02031 ADfn(Double f, int n, const IndepADvar<Double> *x, const Double *g, const Double *h) {
02032   return *(new ADvarn<Double>(f, n, x, g, h));
02033   }
02034 
02035  template<typename Double>
02036  inline ADvari<Double>&
02037 ADfn(Double f, int n, const ADvar<Double> *x, const Double *g, const Double *h) {
02038   return ADfn<Double>(f, n, (IndepADvar<Double>*)x, g, h);
02039   }
02040 
02041  template<typename Double>
02042  void
02043 ADcontext<Double>::Hvprod(int n, ADvar<Double> **x, Double *v, Double *hv)
02044 {
02045   ADVari *a, *aL, *aR, **ap, **ape;
02046   ADVari_block *b, *b0;
02047   DErp *d;
02048   Double aO, adO, *g, *h, *h0, t, tL, tR;
02049   int i, j, k, m;
02050   for(i = 0; i < n; i++) {
02051     a = x[i]->cv;
02052     a->dO = v[i];
02053     a->aO = a->adO = 0.;
02054     }
02055   ADVari::adc.Aibusy->limit = ADVari::adc.Ainext;
02056   a = 0;
02057   for(b0 = 0, b = ADVari::adc.AiFirst; b; b0 = b, b = b->next) {
02058     ap = b->pADvari;
02059     ape = b->limit;
02060     while(ap < ape) {
02061       a = *ap++;
02062       a->aO = a->adO = 0.;
02063       switch(a->opclass) {
02064        case Hv_copy:
02065         a->dO = ((ADVar1*)a)->d.c->dO;
02066         break;
02067        case Hv_binary:
02068         a->dO =   ((ADVar2g*)a)->pL * ((ADVar2g*)a)->dL.c->dO
02069           + ((ADVar2g*)a)->pR * ((ADVar2g*)a)->dR.c->dO;
02070         break;
02071        case Hv_unary:
02072         a->dO = ((ADVar1g*)a)->pL * ((ADVar1g*)a)->d.c->dO;
02073         break;
02074        case Hv_negate:
02075         a->dO = -((ADVar1*)a)->d.c->dO;
02076         break;
02077        case Hv_plusLR:
02078         a->dO = ((ADVar2*)a)->dL.c->dO + ((ADVar2*)a)->dR.c->dO;
02079         break;
02080        case Hv_minusLR:
02081         a->dO = ((ADVar2*)a)->dL.c->dO - ((ADVar2*)a)->dR.c->dO;
02082         break;
02083        case Hv_timesL:
02084         a->dO = ((ADVar1s*)a)->pL * ((ADVar1s*)a)->d.c->dO;
02085         break;
02086        case Hv_timesLR:
02087         a->dO =   ((ADVar2*)a)->dR.c->Val * ((ADVar2*)a)->dL.c->dO
02088           + ((ADVar2*)a)->dL.c->Val * ((ADVar2*)a)->dR.c->dO;
02089         break;
02090        case Hv_quotLR:
02091         a->dO =   ((ADVar2q*)a)->pL * ((ADVar2q*)a)->dL.c->dO
02092           + ((ADVar2q*)a)->pR * ((ADVar2q*)a)->dR.c->dO;
02093         break;
02094        case Hv_nary:
02095         d = ((ADVarn*)a)->D;
02096         m = ((ADVarn*)a)->n;
02097         g = ((ADVarn*)a)->G;
02098         t = 0.;
02099         for(i = 0; i < m; i++)
02100           t += g[i] * d[i].c->dO;
02101         a->dO = t;
02102        }
02103       }
02104     }
02105   if (a)
02106     a->adO = 1.;
02107   for(b = b0; b; b = b->prev) {
02108     ape = b->pADvari;
02109     ap = b->limit;
02110     while(ap > ape) {
02111       a = *--ap;
02112       aO = a->aO;
02113       adO = a->adO;
02114       switch(a->opclass) {
02115        case Hv_copy:
02116         aL = ((ADVar1*)a)->d.c;
02117         aL->aO += aO;
02118         aL->adO += adO;
02119         break;
02120        case Hv_binary:
02121         aL = ((ADVar2g*)a)->dL.c;
02122         aR = ((ADVar2g*)a)->dR.c;
02123         tL = adO*aL->dO;
02124         tR = adO*aR->dO;
02125         aL->aO += aO*((ADVar2g*)a)->pL
02126           + tL*((ADVar2g*)a)->pL2
02127           + tR*((ADVar2g*)a)->pLR;
02128         aR->aO += aO*((ADVar2g*)a)->pR
02129           + tL*((ADVar2g*)a)->pLR
02130           + tR*((ADVar2g*)a)->pR2;
02131         aL->adO += adO * ((ADVar2g*)a)->pL;
02132         aR->adO += adO * ((ADVar2g*)a)->pR;
02133         break;
02134        case Hv_unary:
02135         aL = ((ADVar1g*)a)->d.c;
02136         aL->aO += aO * ((ADVar1g*)a)->pL
02137           + adO * aL->dO * ((ADVar1g*)a)->pL2;
02138         aL->adO += adO * ((ADVar1g*)a)->pL;
02139         break;
02140        case Hv_negate:
02141         aL = ((ADVar1*)a)->d.c;
02142         aL->aO -= aO;
02143         aL->adO -= adO;
02144         break;
02145        case Hv_plusLR:
02146         aL = ((ADVar2*)a)->dL.c;
02147         aR = ((ADVar2*)a)->dR.c;
02148         aL->aO += aO;
02149         aL->adO += adO;
02150         aR->aO += aO;
02151         aR->adO += adO;
02152         break;
02153        case Hv_minusLR:
02154         aL = ((ADVar2*)a)->dL.c;
02155         aR = ((ADVar2*)a)->dR.c;
02156         aL->aO += aO;
02157         aL->adO += adO;
02158         aR->aO -= aO;
02159         aR->adO -= adO;
02160         break;
02161        case Hv_timesL:
02162         aL = ((ADVar1s*)a)->d.c;
02163         aL->aO += aO * (tL = ((ADVar1s*)a)->pL);
02164         aL->adO += adO * tL;
02165         break;
02166        case Hv_timesLR:
02167         aL = ((ADVar2*)a)->dL.c;
02168         aR = ((ADVar2*)a)->dR.c;
02169         aL->aO += aO * (tL = aR->Val) + adO*aR->dO;
02170         aR->aO += aO * (tR = aL->Val) + adO*aL->dO;
02171         aL->adO += adO * tL;
02172         aR->adO += adO * tR;
02173         break;
02174        case Hv_quotLR:
02175         aL = ((ADVar2q*)a)->dL.c;
02176         aR = ((ADVar2q*)a)->dR.c;
02177         tL = adO*aL->dO;
02178         tR = adO*aR->dO;
02179         aL->aO += aO*((ADVar2q*)a)->pL
02180           + tR*((ADVar2q*)a)->pLR;
02181         aR->aO += aO*((ADVar2q*)a)->pR
02182           + tL*((ADVar2q*)a)->pLR
02183           + tR*((ADVar2q*)a)->pR2;
02184         aL->adO += adO * ((ADVar2q*)a)->pL;
02185         aR->adO += adO * ((ADVar2q*)a)->pR;
02186         break;
02187        case Hv_nary:
02188         d  = ((ADVarn*)a)->D;
02189         m  = ((ADVarn*)a)->n;
02190         g  = ((ADVarn*)a)->G;
02191         h0 = ((ADVarn*)a)->H;
02192         for(i = 0; i < m; i++) {
02193           aL = d[i].c;
02194           aL->adO += adO * (t = g[i]);
02195           aL->aO += t*aO;
02196           t = adO * aL->dO;
02197           for(h = h0, j = 0; j <= i; j++)
02198             d[j].c->aO += t * *h++;
02199           h0 = h--;
02200           for(k = j; j < m; j++)
02201             d[j].c->aO += t * *(h += k++);
02202           }
02203        }
02204       }
02205     }
02206   for(i = 0; i < n; i++) {
02207     a = x[i]->cv;
02208     a->dO = 0.;
02209     hv[i] = a->aO;
02210     }
02211   }
02212 
02213  template<typename Double>
02214  inline Double
02215 val(const ADvari<Double> &x) {
02216   return x.Val;
02217   }
02218 
02219 #undef RAD_ACA
02220 #define A (ADvari<Double>*)
02221 #ifdef RAD_Const_WARN
02222 #define C(x) (((x)->opno < 0) ? RAD_Const_Warn(x) : 0, *A x)
02223 #else
02224 #define C(x) *A x
02225 #endif
02226 #define T template<typename Double> inline
02227 #define F ADvari<Double>&
02228 #define Ai const ADvari<Double>&
02229 #define AI const IndepADvar<Double>&
02230 #define D Double
02231 #define T2(r,f) \
02232  T r f(Ai L, AI R) { return f(L, C(R.cv)); }\
02233  T r f(AI L, Ai R) { return f(C(L.cv), R); }\
02234  T r f(AI L, AI R) { return f(C(L.cv), C(R.cv)); }\
02235  T r f(AI L, D R) { return f(C(L.cv), R); }\
02236  T r f(Ai L, Dtype R) { return f(L, (D)R); }\
02237  T r f(AI L, Dtype R) { return f(C(L.cv), (D)R); }\
02238  T r f(Ai L, long R) { return f(L, (D)R); }\
02239  T r f(AI L, long R) { return f(C(L.cv), (D)R); }\
02240  T r f(Ai L, int R) { return f(L, (D)R); }\
02241  T r f(AI L, int R) { return f(C(L.cv), (D)R); }\
02242  T r f(D L, AI R) { return f(L, C(R.cv)); }\
02243  T r f(Dtype L, Ai R) { return f((D)L, R); }\
02244  T r f(Dtype L, AI R) { return f((D)L, C(R.cv)); }\
02245  T r f(long L, Ai R) { return f((D)L, R); }\
02246  T r f(long L, AI R) { return f((D)L, C(R.cv)); }\
02247  T r f(int L, Ai R) { return f((D)L, R); }\
02248  T r f(int L, AI R) { return f((D)L, C(R.cv)); }
02249 
02250 T2(F, operator+)
02251 T2(F, operator-)
02252 T2(F, operator*)
02253 T2(F, operator/)
02254 T2(F, atan2)
02255 T2(F, pow)
02256 T2(F, max)
02257 T2(F, min)
02258 T2(int, operator<)
02259 T2(int, operator<=)
02260 T2(int, operator==)
02261 T2(int, operator!=)
02262 T2(int, operator>=)
02263 T2(int, operator>)
02264 
02265 #undef T2
02266 #undef D
02267 
02268 #define T1(f)\
02269  T F f(AI x) { return f(C(x.cv)); }
02270 
02271 T1(operator+)
02272 T1(operator-)
02273 T1(abs)
02274 T1(acos)
02275 T1(acosh)
02276 T1(asin)
02277 T1(asinh)
02278 T1(atan)
02279 T1(atanh)
02280 T1(cos)
02281 T1(cosh)
02282 T1(exp)
02283 T1(log)
02284 T1(log10)
02285 T1(sin)
02286 T1(sinh)
02287 T1(sqrt)
02288 T1(tan)
02289 T1(tanh)
02290 T1(fabs)
02291 
02292 T F copy(AI x)
02293 { return *(new ADvar1<Double>(Hv_copy, x.cv->Val, &ADcontext<Double>::One, (ADvari<Double>*)x.cv)); }
02294 
02295 T F copy(Ai x)
02296 { return *(new ADvar1<Double>(Hv_copy, x.Val, &ADcontext<Double>::One, (ADvari<Double>*)&x)); }
02297 
02298 #undef T1
02299 #undef AI
02300 #undef Ai
02301 #undef F
02302 #undef T
02303 #undef A
02304 #undef C
02305 #undef Ttype
02306 #undef Dtype
02307 
02308 } /* namespace Rad2 */
02309 } /* namespace Sacado */
02310 
02311 #endif /* SACADO_TRAD2_H */

Generated on Wed May 12 21:59:07 2010 for Sacado Package Browser (Single Doxygen Collection) by  doxygen 1.4.7