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
00036
00037
00038
00039 #ifndef SACADO_RAD2_H
00040 #define SACADO_RAD2_H
00041
00042 #include <stddef.h>
00043 #include <cmath>
00044 #include <math.h>
00045
00046 #ifndef SACADO_NO_NAMESPACE
00047 namespace Sacado {
00048 namespace Rad2d {
00049 #endif
00050
00051
00052 #ifndef RAD_NO_USING_STDCC
00053
00054 using std::exp;
00055 using std::log;
00056 using std::log10;
00057 using std::sqrt;
00058 using std::cos;
00059 using std::sin;
00060 using std::tan;
00061 using std::acos;
00062 using std::asin;
00063 using std::atan;
00064 using std::cosh;
00065 using std::sinh;
00066 using std::tanh;
00067 using std::abs;
00068 using std::fabs;
00069 using std::atan2;
00070 using std::pow;
00071 #endif //NO_USING_STDCC
00072
00073 class ADvar;
00074 class ADvari;
00075 class ADvar1;
00076 class ADvar2;
00077 class ConstADvar;
00078 class Derp;
00079 class IndepADvar;
00080
00081 struct
00082 ADmemblock {
00083
00084
00085 ADmemblock *next;
00086 double memblk[2000];
00087 };
00088
00089 struct
00090 ADvari_block {
00091 enum { Gulp = 1021 };
00092 ADvari_block *next, *prev;
00093 ADvari **limit;
00094 ADvari *pADvari[Gulp];
00095 };
00096
00097 class
00098 ADcontext {
00099 ADmemblock *Busy, *Free;
00100 char *Mbase;
00101 size_t Mleft;
00102 ADvari **Ailimit, **Ainext;
00103 ADvari_block *Aibusy, *Aifree;
00104 ADmemblock First;
00105 ADvari_block AiFirst;
00106 void *new_ADmemblock(size_t);
00107 void new_ADvari_block();
00108 public:
00109 ADcontext();
00110 void *Memalloc(size_t len);
00111 static void Gradcomp();
00112 static void Hvprod(int, ADvar**, double*, double*);
00113 static void Weighted_Gradcomp(int, ADvar**, double*);
00114 inline void ADvari_record(ADvari *x) {
00115 if (Ainext >= Ailimit)
00116 new_ADvari_block();
00117 *Ainext++ = x;
00118 }
00119 };
00120
00121 inline void *ADcontext::Memalloc(size_t len) {
00122 if (Mleft >= len)
00123 return Mbase + (Mleft -= len);
00124 return new_ADmemblock(len);
00125 }
00126
00127 class
00128 CADcontext: public ADcontext {
00129 protected:
00130 bool fpval_implies_const;
00131 public:
00132 friend class ADvar;
00133 CADcontext(): ADcontext() { fpval_implies_const = false; }
00134 static const double One, negOne;
00135 };
00136
00137 class
00138 Derp {
00139 public:
00140 friend class ADvarn;
00141 static Derp *LastDerp;
00142 Derp *next;
00143 const double *a;
00144 const ADvari *b;
00145 mutable ADvari *c;
00146 void *operator new(size_t);
00147 void operator delete(void*) {}
00148 inline Derp(){};
00149 Derp(const ADvari *);
00150 Derp(const double *, const ADvari *);
00151 Derp(const double *, const ADvari *, const ADvari *);
00152
00153 };
00154
00155 inline Derp::Derp(const ADvari *c1): c((ADvari*)c1) {
00156 next = LastDerp;
00157 LastDerp = this;
00158 }
00159
00160 inline Derp::Derp(const double *a1, const ADvari *c1):
00161 a(a1), c((ADvari*)c1) {
00162 next = LastDerp;
00163 LastDerp = this;
00164 }
00165
00166 inline Derp::Derp(const double *a1, const ADvari *b1, const ADvari *c1):
00167 a(a1), b(b1), c((ADvari*)c1) {
00168 next = LastDerp;
00169 LastDerp = this;
00170 }
00171
00172 enum Advari_Opclass {
00173 Hv_const,
00174 Hv_copy,
00175 Hv_binary,
00176 Hv_unary,
00177 Hv_negate,
00178 Hv_plusLR,
00179 Hv_minusLR,
00180 Hv_timesL,
00181 Hv_timesLR,
00182 Hv_quotLR,
00183 Hv_nary
00184 };
00185
00186 extern ADvari& ADf1(double f, double g, double h, const ADvari &x);
00187 extern ADvari& ADf2(double f, double gx, double gy, double hxx,
00188 double hxy, double hyy, const ADvari &x, const ADvari &y);
00189 extern ADvari& ADfn(double f, int n, const ADvar *x, const double *g, const double *h);
00190
00191 class
00192 ADvari {
00193 public:
00194 static ADcontext adc;
00195 Advari_Opclass opclass;
00196 double Val;
00197 mutable double aval;
00198 mutable double dO;
00199 mutable double aO;
00200 mutable double adO;
00201 void *operator new(size_t len) { return ADvari::adc.Memalloc(len); }
00202 void operator delete(void*) {}
00203 inline ADvari(Advari_Opclass oc, double t):
00204 opclass(oc), Val(t), aval(0.), dO(0.)
00205 { if (oc != Hv_const) ADvari::adc.ADvari_record(this); }
00206 inline ADvari(Advari_Opclass oc, double t, double ta):
00207 opclass(oc), Val(t), aval(ta), dO(0.)
00208 { if (oc != Hv_const) ADvari::adc.ADvari_record(this); }
00209 private:
00210 inline ADvari(): Val(0.), aval(0.), dO(0.) {}
00211 public:
00212 friend class ConstADvari;
00213 #ifdef RAD_AUTO_AD_Const
00214 friend class ADcontext;
00215 friend class ADvar1;
00216 friend class ADvar;
00217 friend class ConstADvar;
00218 friend class IndepADvar;
00219 private:
00220 ADvari *Next;
00221 static ADvari *First_ADvari, **Last_ADvari;
00222 protected:
00223 IndepADvar *padv;
00224 public:
00225 ADvari(const IndepADvar *, double);
00226 #endif
00227 #define F friend
00228 #define R ADvari&
00229 #define Ai const ADvari&
00230 #define T1(r,f) F r f(Ai);
00231 #define T2(r,f) \
00232 F r f(Ai,Ai); \
00233 F r f(double,Ai); \
00234 F r f(Ai,double);
00235 T1(R,operator+)
00236 T2(R,operator+)
00237 T1(R,operator-)
00238 T2(R,operator-)
00239 T2(R,operator*)
00240 T2(R,operator/)
00241 T1(R,abs)
00242 T1(R,acos)
00243 T1(R,acosh)
00244 T1(R,asin)
00245 T1(R,asinh)
00246 T1(R,atan)
00247 T1(R,atanh)
00248 T2(R,atan2)
00249 T2(R,max)
00250 T2(R,min)
00251 T1(R,cos)
00252 T1(R,cosh)
00253 T1(R,exp)
00254 T1(R,log)
00255 T1(R,log10)
00256 T2(R,pow)
00257 T1(R,sin)
00258 T1(R,sinh)
00259 T1(R,sqrt)
00260 T1(R,tan)
00261 T1(R,tanh)
00262 T1(R,fabs)
00263 T1(R,copy)
00264 T2(int,operator<)
00265 T2(int,operator<=)
00266 T2(int,operator==)
00267 T2(int,operator!=)
00268 T2(int,operator>=)
00269 T2(int,operator>)
00270 #undef T2
00271 #undef T1
00272 #undef Ai
00273 #undef R
00274 #undef F
00275
00276 friend ADvari& ADf1(double f, double g, double h, const ADvari &x);
00277 friend ADvari& ADf2(double f, double gx, double gy, double hxx,
00278 double hxy, double hyy, const ADvari &x, const ADvari &y);
00279 friend ADvari& ADfn(double f, int n, const ADvar *x, const double *g, const double *h);
00280 };
00281
00282 inline void* Derp::operator new(size_t len) { return ADvari::adc.Memalloc(len); }
00283
00284
00285 class
00286 ADvar1: public ADvari {
00287 public:
00288 Derp d;
00289 ADvar1(Advari_Opclass oc, double val1, const double *a1, const ADvari *c1):
00290 ADvari(oc,val1), d(a1,this,c1) {}
00291 #ifdef RAD_AUTO_AD_Const
00292 ADvar1(const IndepADvar *, const IndepADvar &);
00293 ADvar1(const IndepADvar *, const ADvari &);
00294 #endif
00295 };
00296
00297 class
00298 ConstADvari: public ADvari {
00299 private:
00300 ConstADvari *prevcad;
00301 ConstADvari() {};
00302 static ConstADvari *lastcad;
00303 public:
00304 static CADcontext cadc;
00305 inline void *operator new(size_t len) { return ConstADvari::cadc.Memalloc(len); }
00306 inline ConstADvari(double t): ADvari(Hv_copy, t) { prevcad = lastcad; lastcad = this; }
00307 static void aval_reset(void);
00308 };
00309
00310 class
00311 IndepADvar
00312 {
00313 private:
00314 inline IndepADvar& operator=(const IndepADvar &x) {
00315
00316 #ifdef RAD_AUTO_AD_Const
00317 if (cv)
00318 cv->padv = 0;
00319 cv = new ADvar1(this,x);
00320 return *this;
00321 #else
00322 #ifdef RAD_EQ_ALIAS
00323 cv = x.cv;
00324 return *this;
00325 #else
00326 return ADvar_operatoreq(this,*x.cv);
00327 #endif
00328 #endif
00329 }
00330 protected:
00331 static void AD_Const(const IndepADvar&);
00332 ADvari *cv;
00333 public:
00334 typedef double value_type;
00335 friend class ADvar;
00336 friend class ADvar1;
00337 friend class ADvarn;
00338 friend class ADcontext;
00339 IndepADvar(double);
00340 IndepADvar(int);
00341 IndepADvar(long);
00342 IndepADvar& operator=(double);
00343 #ifdef RAD_AUTO_AD_Const
00344 inline IndepADvar(const IndepADvar &x) { cv = x.cv ? new ADvar1(this, x) : 0; };
00345 inline IndepADvar() { cv = 0; }
00346 inline ~IndepADvar() {
00347 if (cv)
00348 cv->padv = 0;
00349 }
00350 #else
00351 inline IndepADvar() {
00352 #ifndef RAD_EQ_ALIAS
00353 cv = 0;
00354 #endif
00355 }
00356 inline ~IndepADvar() {}
00357 friend IndepADvar& ADvar_operatoreq(IndepADvar*, const ADvari&);
00358 #endif
00359
00360 friend void AD_Const(const IndepADvar&);
00361
00362 inline operator ADvari&() { return *cv; }
00363 inline operator ADvari&() const { return *(ADvari*)cv; }
00364
00365 inline double val() const { return cv->Val; }
00366 inline double adj() const { return cv->aval; }
00367 static inline void Gradcomp() { ADcontext::Gradcomp(); }
00368 static inline void Hvprod(int n, ADvar **vp, double *v, double *hv)
00369 { ADcontext::Hvprod(n, vp, v, hv); }
00370 static inline void aval_reset() { ConstADvari::aval_reset(); }
00371 static inline void Weighted_Gradcomp(int n, ADvar **v, double *w)
00372 { ADcontext::Weighted_Gradcomp(n, v, w); }
00373
00374
00375 #define Ai const ADvari&
00376 #define AI const IndepADvar&
00377 #define T2(r,f) \
00378 r f(AI,AI);\
00379 r f(Ai,AI);\
00380 r f(AI,Ai);\
00381 r f(double,AI);\
00382 r f(AI,double);
00383 #define T1(f) friend ADvari& f(AI);
00384
00385 #define F friend ADvari&
00386 T2(F, operator+)
00387 T2(F, operator-)
00388 T2(F, operator*)
00389 T2(F, operator/)
00390 T2(F, atan2)
00391 T2(F, max)
00392 T2(F, min)
00393 T2(F, pow)
00394 #undef F
00395 #define F friend int
00396 T2(F, operator<)
00397 T2(F, operator<=)
00398 T2(F, operator==)
00399 T2(F, operator!=)
00400 T2(F, operator>=)
00401 T2(F, operator>)
00402
00403 T1(operator+)
00404 T1(operator-)
00405 T1(abs)
00406 T1(acos)
00407 T1(acosh)
00408 T1(asin)
00409 T1(asinh)
00410 T1(atan)
00411 T1(atanh)
00412 T1(cos)
00413 T1(cosh)
00414 T1(exp)
00415 T1(log)
00416 T1(log10)
00417 T1(sin)
00418 T1(sinh)
00419 T1(sqrt)
00420 T1(tan)
00421 T1(tanh)
00422 T1(fabs)
00423 T1(copy)
00424
00425 #undef T1
00426 #undef T2
00427 #undef F
00428 #undef Ai
00429 #undef AI
00430
00431 };
00432
00433 class
00434 ADvar: public IndepADvar {
00435 void ADvar_ctr(double d);
00436 public:
00437 inline ADvar() { }
00438 inline ADvar(double d) { ADvar_ctr(d); }
00439 inline ADvar(int i) { ADvar_ctr((double)i); }
00440 inline ADvar(long i) { ADvar_ctr((double)i); }
00441 inline ~ADvar() {}
00442 #ifdef RAD_AUTO_AD_Const
00443 friend class ADvar1;
00444 inline ADvar(const IndepADvar &x) { cv = x.cv ? new ADvar1(this, x) : 0; }
00445 inline ADvar(ADvari &x) { cv = &x; x.padv = this; }
00446 inline ADvar& operator=(const IndepADvar &x) {
00447 if (cv)
00448 cv->padv = 0;
00449 cv = new ADvar1(this,x);
00450 return *this;
00451 }
00452 inline ADvar& operator=(const ADvari &x) {
00453 if (cv)
00454 cv->padv = 0;
00455 cv = new ADvar1(this, x);
00456 return *this;
00457 }
00458 #else
00459 friend ADvar& ADvar_operatoreq(ADvar*, const ADvari&);
00460 #ifdef RAD_EQ_ALIAS
00461
00462 inline ADvar(const IndepADvar &x) { cv = x.cv; }
00463 inline ADvar(const ADvari &x) { cv = (ADvari*)&x; }
00464 inline ADvar& operator=(const ADvari &x) { cv = (ADvari*)&x; return *this; }
00465 inline ADvar& operator=(const IndepADvar &x) { cv = (ADvari*)x.cv; return *this; }
00466 #else
00467 ADvar(const IndepADvar &x) { cv = x.cv ?
00468 new ADvar1(Hv_copy, x.cv->Val, &CADcontext::One, x.cv) : 0; }
00469 ADvar(const ADvari &x) { cv = new ADvar1(Hv_copy, x.Val, &CADcontext::One, &x); }
00470 inline ADvar& operator=(const ADvari &x) { return ADvar_operatoreq(this,x); }
00471 inline ADvar& operator=(const IndepADvar &x) { return ADvar_operatoreq(this,*x.cv); }
00472 #endif
00473 #endif
00474 ADvar& operator=(double);
00475 ADvar& operator+=(const ADvari&);
00476 ADvar& operator+=(double);
00477 ADvar& operator-=(const ADvari&);
00478 ADvar& operator-=(double);
00479 ADvar& operator*=(const ADvari&);
00480 ADvar& operator*=(double);
00481 ADvar& operator/=(const ADvari&);
00482 ADvar& operator/=(double);
00483 inline static bool get_fpval_implies_const(void)
00484 { return ConstADvari::cadc.fpval_implies_const; }
00485 inline static void set_fpval_implies_const(bool newval)
00486 { ConstADvari::cadc.fpval_implies_const = newval; }
00487 inline static bool setget_fpval_implies_const(bool newval) {
00488 bool oldval = ConstADvari::cadc.fpval_implies_const;
00489 ConstADvari::cadc.fpval_implies_const = newval;
00490 return oldval;
00491 }
00492 static inline void Gradcomp() { ADcontext::Gradcomp(); }
00493 static inline void Hvprod(int n, ADvar **vp, double *v, double *hv)
00494 { ADcontext::Hvprod(n, vp, v, hv); }
00495 static inline void aval_reset() { ConstADvari::aval_reset(); }
00496 static inline void Weighted_Gradcomp(int n, ADvar **v, double *w)
00497 { ADcontext::Weighted_Gradcomp(n, v, w); }
00498 };
00499
00500 inline void AD_Const(const IndepADvar&v) { IndepADvar::AD_Const(v); }
00501
00502 class
00503 ConstADvar: public ADvar {
00504 private:
00505 ConstADvar& operator+=(const ADvari&);
00506 ConstADvar& operator+=(double);
00507 ConstADvar& operator-=(const ADvari&);
00508 ConstADvar& operator-=(double);
00509 ConstADvar& operator*=(const ADvari&);
00510 ConstADvar& operator*=(double);
00511 ConstADvar& operator/=(const ADvari&);
00512 ConstADvar& operator/=(double);
00513 void ConstADvar_ctr(double);
00514 public:
00515 inline ConstADvar(double d) { ConstADvar_ctr(d); }
00516 inline ConstADvar(int i) { ConstADvar_ctr((double)i); }
00517 inline ConstADvar(long i) { ConstADvar_ctr((double)i); }
00518 ConstADvar(const ADvari &x);
00519 #ifdef RAD_AUTO_AD_Const
00520 ConstADvar(const IndepADvar &x) { cv = new ADvar1(this,x); }
00521 #endif
00522 inline ~ConstADvar(){}
00523 #ifdef RAD_NO_CONST_UPDATE
00524 private:
00525 #endif
00526 ConstADvar();
00527 inline ConstADvar& operator=(double d) { cv->Val = d; return *this; }
00528 inline ConstADvar& operator=(const IndepADvar& d) { cv->Val = d.val(); return *this; }
00529 };
00530
00531 class
00532 ADvar1s: public ADvar1 {
00533 public:
00534 double pL;
00535 ADvar1s(double val1, double d1, const ADvari *c1):
00536 ADvar1(Hv_timesL,val1,&pL,c1), pL(d1) {}
00537 };
00538
00539 class
00540 ADvar1g: public ADvar1 {
00541 public:
00542 double pL;
00543 double pL2;
00544 ADvar1g(double val1, double d1, double d2, const ADvari *c1):
00545 ADvar1(Hv_unary,val1,&pL,c1), pL(d1), pL2(d2) {}
00546 };
00547
00548 class
00549 ADvar2: public ADvari {
00550 public:
00551 Derp dL, dR;
00552 ADvar2(Advari_Opclass oc, double val1, const ADvari *Lcv, const double *Lc,
00553 const ADvari *Rcv, const double *Rc): ADvari(oc,val1) {
00554 dR.next = Derp::LastDerp;
00555 dL.next = &dR;
00556 Derp::LastDerp = &dL;
00557 dL.a = Lc;
00558 dL.c = (ADvari*)Lcv;
00559 dR.a = Rc;
00560 dR.c = (ADvari*)Rcv;
00561 dL.b = dR.b = this;
00562 }
00563 };
00564
00565 class
00566 ADvar2q: public ADvar2 {
00567 public:
00568 double pL;
00569 double pR;
00570 double pLR;
00571 double pR2;
00572 ADvar2q(double val1, double Lp, double Rp, double LR, double R2,
00573 const ADvari *Lcv, const ADvari *Rcv);
00574 };
00575
00576 class
00577 ADvar2g: public ADvar2 {
00578 public:
00579 double pL;
00580 double pR;
00581 double pL2;
00582 double pLR;
00583 double pR2;
00584 ADvar2g(double val1, double Lp, double Rp, double L2, double LR, double R2,
00585 const ADvari *Lcv, const ADvari *Rcv);
00586 };
00587
00588 class
00589 ADvarn: public ADvari {
00590 public:
00591 int n;
00592 double *G, *H;
00593 Derp *D;
00594 ADvarn(double val1, int n1, const ADvar *x, const double *g, const double *h);
00595 };
00596
00597 inline ADvari &operator+(ADvari &T) { return T; }
00598 inline ADvari &operator+(const ADvari &T) { return (ADvari&) T; }
00599
00600 inline int operator<(const ADvari &L, const ADvari &R) { return L.Val < R.Val; }
00601 inline int operator<(const ADvari &L, double R) { return L.Val < R; }
00602 inline int operator<(double L, const ADvari &R) { return L < R.Val; }
00603
00604 inline int operator<=(const ADvari &L, const ADvari &R) { return L.Val <= R.Val; }
00605 inline int operator<=(const ADvari &L, double R) { return L.Val <= R; }
00606 inline int operator<=(double L, const ADvari &R) { return L <= R.Val; }
00607
00608 inline int operator==(const ADvari &L, const ADvari &R) { return L.Val == R.Val; }
00609 inline int operator==(const ADvari &L, double R) { return L.Val == R; }
00610 inline int operator==(double L, const ADvari &R) { return L == R.Val; }
00611
00612 inline int operator!=(const ADvari &L, const ADvari &R) { return L.Val != R.Val; }
00613 inline int operator!=(const ADvari &L, double R) { return L.Val != R; }
00614 inline int operator!=(double L, const ADvari &R) { return L != R.Val; }
00615
00616 inline int operator>=(const ADvari &L, const ADvari &R) { return L.Val >= R.Val; }
00617 inline int operator>=(const ADvari &L, double R) { return L.Val >= R; }
00618 inline int operator>=(double L, const ADvari &R) { return L >= R.Val; }
00619
00620 inline int operator>(const ADvari &L, const ADvari &R) { return L.Val > R.Val; }
00621 inline int operator>(const ADvari &L, double R) { return L.Val > R; }
00622 inline int operator>(double L, const ADvari &R) { return L > R.Val; }
00623
00624 inline ADvari& copy(const IndepADvar &x)
00625 { return *(new ADvar1(Hv_copy, x.cv->Val, &CADcontext::One, x.cv)); }
00626
00627 inline ADvari& copy(const ADvari &x)
00628 { return *(new ADvar1(Hv_copy, x.Val, &CADcontext::One, &x)); }
00629
00630 inline ADvari& abs(const ADvari &x)
00631 { return fabs(x); }
00632
00633 #define A (ADvari*)
00634 #define T inline
00635 #define F ADvari&
00636 #define Ai const ADvari&
00637 #define AI const IndepADvar&
00638 #define D double
00639 #define T2(r,f) \
00640 T r f(Ai L, AI R) { return f(L, *A R.cv); }\
00641 T r f(AI L, Ai R) { return f(*A L.cv, R); }\
00642 T r f(AI L, AI R) { return f(*A L.cv, *A R.cv); }\
00643 T r f(AI L, D R) { return f(*A L.cv, R); }\
00644 T r f(D L, AI R) { return f(L, *A R.cv); }
00645
00646 T2(F, operator+)
00647 T2(F, operator-)
00648 T2(F, operator*)
00649 T2(F, operator/)
00650 T2(F, atan2)
00651 T2(F, pow)
00652 T2(F, max)
00653 T2(F, min)
00654 T2(int, operator<)
00655 T2(int, operator<=)
00656 T2(int, operator==)
00657 T2(int, operator!=)
00658 T2(int, operator>=)
00659 T2(int, operator>)
00660
00661 #undef T2
00662 #undef D
00663
00664 #define T1(f)\
00665 T F f(AI x) { return f(*A x.cv); }
00666
00667 T1(operator+)
00668 T1(operator-)
00669 T1(abs)
00670 T1(acos)
00671 T1(acosh)
00672 T1(asin)
00673 T1(asinh)
00674 T1(atan)
00675 T1(atanh)
00676 T1(cos)
00677 T1(cosh)
00678 T1(exp)
00679 T1(log)
00680 T1(log10)
00681 T1(sin)
00682 T1(sinh)
00683 T1(sqrt)
00684 T1(tan)
00685 T1(tanh)
00686 T1(fabs)
00687
00688 #undef T1
00689 #undef AI
00690 #undef Ai
00691 #undef F
00692 #undef T
00693 #undef A
00694
00695 #ifndef SACADO_NO_NAMESPACE
00696 }
00697 }
00698 #endif // SACADO_NAMESPACE
00699 #endif // SACADO_RAD2_H