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