00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
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*);
00053
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>
00064 #endif
00065 #endif
00066
00067 namespace Sacado {
00068 namespace Rad2 {
00069
00070
00071 #ifndef RAD_NO_USING_STDCC
00072
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
00120 #endif
00121 #endif
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 {
00158
00159
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 {
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> {
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 {
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
00244 };
00245
00246
00247
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 }
00326 }
00327 #define SNS Sacado::Rad2
00328 namespace std {
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 {
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;
00422 mutable Double aval;
00423 mutable Double dO;
00424 mutable Double aO;
00425 mutable Double adO;
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*) {}
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.) {}
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> {
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() {};
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 {
00567 private:
00568 IndepADvar& operator=(IndepADvar&x) {
00569
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
00653
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> {
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() { }
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
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
00781 #endif
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:
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> {
00850 public:
00851 typedef ADvar1<Double> ADVar1;
00852 typedef typename ADVar1::ADVari ADVari;
00853 Double pL;
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> {
00865 public:
00866 typedef ADvar1<Double> ADVar1;
00867 typedef typename ADVar1::ADVari ADVari;
00868 Double pL;
00869 Double pL2;
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> {
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> {
00915 public:
00916 typedef ADvar2<Double> ADVar2;
00917 typedef typename ADVar2::ADVari ADVari;
00918 typedef typename ADVar2::DErp DErp;
00919 Double pL;
00920 Double pR;
00921 Double pLR;
00922 Double pR2;
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> {
00938 public:
00939 typedef ADvar2<Double> ADVar2;
00940 typedef typename ADVar2::ADVari ADVari;
00941 Double pL;
00942 Double pR;
00943 Double pL2;
00944 Double pLR;
00945 Double pR2;
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> {
00954
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
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
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
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;
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
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
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
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
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
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
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
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) {
01978
01979
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 }
02309 }
02310
02311 #endif