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
00040 #include "Sacado_rad2.hpp"
00041
00042 #ifndef SACADO_NO_NAMESPACE
00043 namespace Sacado {
00044 namespace Rad2d {
00045 #endif
00046
00047 #ifdef RAD_AUTO_AD_Const
00048 ADvari *ADvari::First_ADvari, **ADvari::Last_ADvari = &ADvari::First_ADvari;
00049 #undef RAD_DEBUG_BLOCKKEEP
00050 #else
00051 #ifdef RAD_DEBUG_BLOCKKEEP
00052 #if !(RAD_DEBUG_BLOCKKEEP > 0)
00053 #undef RAD_DEBUG_BLOCKKEEP
00054 #else
00055 extern "C" void _uninit_f2c(void *x, int type, long len);
00056 #define TYDREAL 5
00057 static ADmemblock *rad_Oldcurmb;
00058 static int rad_busy_blocks;
00059 #endif
00060 #endif
00061 #endif
00062
00063 Derp *Derp::LastDerp = 0;
00064 ADcontext ADvari::adc;
00065 CADcontext ConstADvari::cadc;
00066 ConstADvari *ConstADvari::lastcad;
00067 static int rad_need_reinit;
00068 #ifdef RAD_DEBUG_BLOCKKEEP
00069 static size_t rad_mleft_save;
00070 #endif
00071
00072 const double CADcontext::One = 1., CADcontext::negOne = -1.;
00073
00074 ADcontext::ADcontext()
00075 {
00076 First.next = 0;
00077 Busy = &First;
00078 Free = 0;
00079 Mbase = (char*)First.memblk;
00080 Mleft = sizeof(First.memblk);
00081 Aibusy = &AiFirst;
00082 Aifree = 0;
00083 Ainext = AiFirst.pADvari;
00084 AiFirst.next = AiFirst.prev = 0;
00085 AiFirst.limit = Ailimit = AiFirst.pADvari + ADvari_block::Gulp;
00086 }
00087
00088 void*
00089 ADcontext::new_ADmemblock(size_t len)
00090 {
00091 ADmemblock *mb, *mb0, *mb1, *mbf, *x;
00092 ADvari_block *b;
00093 #ifdef RAD_AUTO_AD_Const
00094 ADvari *a, *anext;
00095 IndepADvar *v;
00096 #endif
00097
00098 if (rad_need_reinit && this == &ADvari::adc) {
00099 rad_need_reinit = 0;
00100 Derp::LastDerp = 0;
00101 Aibusy = b = &AiFirst;
00102 Aifree = b->next;
00103 b->next = b->prev = 0;
00104 Ailimit = b->limit = (Ainext = b->pADvari) + ADvari_block::Gulp;
00105 #ifdef RAD_DEBUG_BLOCKKEEP
00106 Mleft = rad_mleft_save;
00107 if (Mleft < sizeof(First.memblk))
00108 _uninit_f2c(Mbase + Mleft, TYDREAL,
00109 (sizeof(First.memblk) - Mleft)/sizeof(double));
00110 if (mb = Busy->next) {
00111 if (!(mb0 = rad_Oldcurmb))
00112 mb0 = &First;
00113 for(;; mb = mb->next) {
00114 _uninit_f2c(mb->memblk, TYDREAL,
00115 sizeof(First.memblk)/sizeof(double));
00116 if (mb == mb0)
00117 break;
00118 }
00119 }
00120 rad_Oldcurmb = Busy;
00121 if (rad_busy_blocks >= RAD_DEBUG_BLOCKKEEP) {
00122 rad_busy_blocks = 0;
00123 rad_Oldcurmb = 0;
00124 mb0 = &First;
00125 mbf = Free;
00126 for(mb = Busy; mb != mb0; mb = mb1) {
00127 mb1 = mb->next;
00128 mb->next = mbf;
00129 mbf = mb;
00130 }
00131 Free = mbf;
00132 Busy = mb;
00133 Mbase = (char*)First.memblk;
00134 Mleft = sizeof(First.memblk);
00135 }
00136
00137 #else
00138
00139 mb0 = &ADvari::adc.First;
00140 mbf = ADvari::adc.Free;
00141 for(mb = ADvari::adc.Busy; mb != mb0; mb = mb1) {
00142 mb1 = mb->next;
00143 mb->next = mbf;
00144 mbf = mb;
00145 }
00146 ADvari::adc.Free = mbf;
00147 ADvari::adc.Busy = mb;
00148 ADvari::adc.Mbase = (char*)ADvari::adc.First.memblk;
00149 ADvari::adc.Mleft = sizeof(ADvari::adc.First.memblk);
00150 #ifdef RAD_AUTO_AD_Const
00151 *ADvari::Last_ADvari = 0;
00152 ADvari::Last_ADvari = &ADvari::First_ADvari;
00153 if (anext = ADvari::First_ADvari) {
00154 while(a = anext) {
00155 anext = a->Next;
00156 if (v = a->padv)
00157 v->cv = new ADvari(v, a->Val);
00158 }
00159 }
00160 #endif
00161 #endif
00162 if (Mleft >= len)
00163 return Mbase + (Mleft -= len);
00164 }
00165
00166 if (x = Free)
00167 Free = x->next;
00168 else
00169 x = new ADmemblock;
00170 #ifdef RAD_DEBUG_BLOCKKEEP
00171 rad_busy_blocks++;
00172 #endif
00173 x->next = Busy;
00174 Busy = x;
00175 return (Mbase = (char*)x->memblk) +
00176 (Mleft = sizeof(First.memblk) - len);
00177 }
00178
00179 void
00180 ADcontext::new_ADvari_block()
00181 {
00182 ADvari_block *ob, *nb;
00183 ob = Aibusy;
00184 ob->limit = Ailimit;
00185 if (nb = Aifree)
00186 Aifree = nb->next;
00187 else
00188 nb = new ADvari_block;
00189 Aibusy = Aibusy->next = nb;
00190 nb->limit = Ailimit = (Ainext = nb->pADvari) + ADvari_block::Gulp;
00191 ob->next = nb;
00192 nb->prev = ob;
00193 nb->next = 0;
00194 }
00195
00196 void
00197 ADcontext::Gradcomp()
00198 {
00199 Derp *d;
00200
00201 if (rad_need_reinit) {
00202 for(d = Derp::LastDerp; d; d = d->next)
00203 d->c->aval = 0;
00204 }
00205 else {
00206 rad_need_reinit = 1;
00207 #ifdef RAD_DEBUG_BLOCKKEEP
00208 rad_mleft_save = ADvari::adc.Mleft;
00209 #endif
00210 ADvari::adc.Mleft = 0;
00211 }
00212
00213 if (d = Derp::LastDerp) {
00214 d->b->aval = 1;
00215 do d->c->aval += *d->a * d->b->aval;
00216 while(d = d->next);
00217 }
00218 }
00219
00220 void
00221 ADcontext::Weighted_Gradcomp(int n, ADvar **v, double *w)
00222 {
00223 Derp *d;
00224 int i;
00225
00226 if (rad_need_reinit) {
00227 for(d = Derp::LastDerp; d; d = d->next)
00228 d->c->aval = 0;
00229 }
00230 else {
00231 rad_need_reinit = 1;
00232 #ifdef RAD_DEBUG_BLOCKKEEP
00233 rad_mleft_save = ADvari::adc.Mleft;
00234 #endif
00235 ADvari::adc.Mleft = 0;
00236 }
00237 if (d = Derp::LastDerp) {
00238 for(i = 0; i < n; i++)
00239 v[i]->cv->aval = w[i];
00240 do d->c->aval += *d->a * d->b->aval;
00241 while(d = d->next);
00242 }
00243 }
00244
00245 #ifdef RAD_AUTO_AD_Const
00246
00247 IndepADvar::IndepADvar(double d)
00248 {
00249 cv = new ADvari(Hv_const, this, d);
00250 }
00251
00252 IndepADvar::IndepADvar(int d)
00253 {
00254 cv = new ADvari(Hv_const, this, (double)d);
00255 }
00256
00257 IndepADvar::IndepADvar(long d)
00258 {
00259 cv = new ADvari(Hv_const, this, (double)d);
00260 }
00261
00262 #else
00264 IndepADvar::IndepADvar(double d)
00265 {
00266 ADvari *x = new ADvari(Hv_const, d);
00267 cv = x;
00268 }
00269
00270 IndepADvar::IndepADvar(int d)
00271 {
00272 ADvari *x = new ADvari(Hv_const, (double)d);
00273 cv = x;
00274 }
00275
00276 IndepADvar::IndepADvar(long d)
00277 {
00278 ADvari *x = new ADvari(Hv_const, (double)d);
00279 cv = x;
00280 }
00281
00282 #endif
00283
00284 void
00285 ADvar::ADvar_ctr(double d)
00286 {
00287 #ifdef RAD_AUTO_AD_Const
00288 ADvari *x = new ADvari(Hv_const, this, d);
00289 #else
00290 ADvari *x = ConstADvari::cadc.fpval_implies_const
00291 ? new ConstADvari(d)
00292 : new ADvari(Hv_const, d);
00293 #endif
00294 cv = x;
00295 }
00296
00297 ConstADvar::ConstADvar()
00298 {
00299 ConstADvari *x = new ConstADvari(0.);
00300 cv = x;
00301 }
00302
00303 void
00304 ConstADvar::ConstADvar_ctr(double d)
00305 {
00306 ConstADvari *x = new ConstADvari(d);
00307 cv = x;
00308 }
00309 ConstADvar::ConstADvar(const ADvari &x)
00310 {
00311 ConstADvari *y = new ConstADvari(x.Val);
00312 Derp *d = new Derp(&CADcontext::One, y, &x);
00313 cv = y;
00314 }
00315
00316 void
00317 IndepADvar::AD_Const(const IndepADvar &v)
00318 {
00319 ConstADvari *ncv = new ConstADvari(v.val());
00320 ((IndepADvar*)&v)->cv = ncv;
00321 }
00322
00323 void
00324 ConstADvari::aval_reset()
00325 {
00326 ConstADvari *x = ConstADvari::lastcad;
00327 while(x) {
00328 x->aval = 0;
00329 x = x->prevcad;
00330 }
00331 }
00332
00333 #ifdef RAD_AUTO_AD_Const
00334
00335 ADvari::ADvari(const IndepADvar *x, double d): Val(d), aval(0.)
00336 {
00337 opclass = Hv_const;
00338 *Last_ADvari = this;
00339 Last_ADvari = &Next;
00340 padv = (IndepADvar*)x;
00341 }
00342
00343 ADvar1::ADvar1(const IndepADvar *x, const IndepADvar &y):
00344 ADvari(Hv_copy, y.cv->Val), d(&CADcontext::One, this, y.cv)
00345 {
00346 *ADvari::Last_ADvari = this;
00347 ADvari::Last_ADvari = &Next;
00348 padv = (IndepADvar*)x;
00349 }
00350
00351 ADvar1::ADvar1(const IndepADvar *x, const ADvari &y):
00352 ADvari(Hv_copy, y.Val), d(&CADcontext::One, this, &y)
00353 {
00354 *ADvari::Last_ADvari = this;
00355 ADvari::Last_ADvari = &Next;
00356 padv = (IndepADvar*)x;
00357 }
00358
00359 #else
00360
00361 ADvar&
00362 ADvar_operatoreq(ADvar *This, const ADvari &x)
00363 { This->cv = new ADvar1(Hv_copy, x.Val, &CADcontext::One, (ADvari*)&x); return *This; }
00364
00365 IndepADvar&
00366 ADvar_operatoreq(IndepADvar *This, const ADvari &x)
00367 { This->cv = new ADvar1(Hv_copy, x.Val, &CADcontext::One, (ADvari*)&x); return *This; }
00368
00369 #endif
00370
00371 ADvar2q::ADvar2q(double val1, double Lp, double Rp,
00372 double LR, double R2, const ADvari *Lcv, const ADvari *Rcv):
00373 ADvar2(Hv_quotLR,val1,Lcv,&pL,Rcv,&pR),
00374 pL(Lp), pR(Rp), pLR(LR), pR2(R2) { }
00375
00376 ADvar2g::ADvar2g(double val1, double Lp, double Rp,
00377 double L2, double LR, double R2, const ADvari *Lcv, const ADvari *Rcv):
00378 ADvar2(Hv_binary,val1,Lcv,&pL,Rcv,&pR),
00379 pL(Lp), pR(Rp), pL2(L2), pLR(LR), pR2(R2) { }
00380
00381 IndepADvar&
00382 IndepADvar::operator=(double d)
00383 {
00384 #ifdef RAD_AUTO_AD_Const
00385 if (cv)
00386 cv->padv = 0;
00387 cv = new ADvari(Hv_const, this,d);
00388 #else
00389 cv = new ADvari(Hv_const, d);
00390 #endif
00391 return *this;
00392 }
00393
00394 ADvar&
00395 ADvar::operator=(double d)
00396 {
00397 #ifdef RAD_AUTO_AD_Const
00398 if (cv)
00399 cv->padv = 0;
00400 cv = new ADvari(Hv_const, this,d);
00401 #else
00402 cv = ConstADvari::cadc.fpval_implies_const
00403 ? new ConstADvari(d)
00404 : new ADvari(Hv_const, d);
00405 #endif
00406 return *this;
00407 }
00408
00409 ADvari&
00410 operator-(const ADvari &T) {
00411 return *(new ADvar1(Hv_negate, -T.Val, &CADcontext::negOne, &T));
00412 }
00413
00414 ADvari&
00415 operator+(const ADvari &L, const ADvari &R) {
00416 return *(new ADvar2(Hv_plusLR,L.Val + R.Val, &L, &CADcontext::One, &R, &CADcontext::One));
00417 }
00418
00419 ADvar&
00420 ADvar::operator+=(const ADvari &R) {
00421 ADvari *Lcv = cv;
00422 #ifdef RAD_AUTO_AD_Const
00423 Lcv->padv = 0;
00424 #endif
00425 cv = new ADvar2(Hv_plusLR, Lcv->Val + R.Val, Lcv, &CADcontext::One, &R, &CADcontext::One);
00426 return *this;
00427 }
00428
00429 ADvari&
00430 operator+(const ADvari &L, double R) {
00431 return *(new ADvar1(Hv_copy, L.Val + R, &CADcontext::One, &L));
00432 }
00433
00434 ADvar&
00435 ADvar::operator+=(double R) {
00436 ADvari *tcv = cv;
00437 #ifdef RAD_AUTO_AD_Const
00438 tcv->padv = 0;
00439 #endif
00440 cv = new ADvar1(Hv_copy, tcv->Val + R, &CADcontext::One, tcv);
00441 return *this;
00442 }
00443
00444 ADvari&
00445 operator+(double L, const ADvari &R) {
00446 return *(new ADvar1(Hv_copy, L + R.Val, &CADcontext::One, &R));
00447 }
00448
00449 ADvari&
00450 operator-(const ADvari &L, const ADvari &R) {
00451 return *(new ADvar2(Hv_minusLR,L.Val - R.Val, &L, &CADcontext::One, &R, &CADcontext::negOne));
00452 }
00453
00454 ADvar&
00455 ADvar::operator-=(const ADvari &R) {
00456 ADvari *Lcv = cv;
00457 #ifdef RAD_AUTO_AD_Const
00458 Lcv->padv = 0;
00459 #endif
00460 cv = new ADvar2(Hv_minusLR, Lcv->Val - R.Val, Lcv, &CADcontext::One, &R, &CADcontext::negOne);
00461 return *this;
00462 }
00463
00464 ADvari&
00465 operator-(const ADvari &L, double R) {
00466 return *(new ADvar1(Hv_copy, L.Val - R, &CADcontext::One, &L));
00467 }
00468
00469 ADvar&
00470 ADvar::operator-=(double R) {
00471 ADvari *tcv = cv;
00472 #ifdef RAD_AUTO_AD_Const
00473 tcv->padv = 0;
00474 #endif
00475 cv = new ADvar1(Hv_copy, tcv->Val - R, &CADcontext::One, tcv);
00476 return *this;
00477 }
00478
00479 ADvari&
00480 operator-(double L, const ADvari &R) {
00481 return *(new ADvar1(Hv_negate, L - R.Val, &CADcontext::negOne, &R));
00482 }
00483
00484 ADvari&
00485 operator*(const ADvari &L, const ADvari &R) {
00486 return *(new ADvar2(Hv_timesLR, L.Val * R.Val, &L, &R.Val, &R, &L.Val));
00487 }
00488
00489 ADvar&
00490 ADvar::operator*=(const ADvari &R) {
00491 ADvari *Lcv = cv;
00492 #ifdef RAD_AUTO_AD_Const
00493 Lcv->padv = 0;
00494 #endif
00495 cv = new ADvar2(Hv_timesLR, Lcv->Val * R.Val, Lcv, &R.Val, &R, &Lcv->Val);
00496 return *this;
00497 }
00498
00499 ADvari&
00500 operator*(const ADvari &L, double R) {
00501 return *(new ADvar1s(L.Val * R, R, &L));
00502 }
00503
00504 ADvar&
00505 ADvar::operator*=(double R) {
00506 ADvari *Lcv = cv;
00507 #ifdef RAD_AUTO_AD_Const
00508 Lcv->padv = 0;
00509 #endif
00510 cv = new ADvar1s(Lcv->Val * R, R, Lcv);
00511 return *this;
00512 }
00513
00514 ADvari&
00515 operator*(double L, const ADvari &R) {
00516 return *(new ADvar1s(L * R.Val, L, &R));
00517 }
00518
00519 ADvari&
00520 operator/(const ADvari &L, const ADvari &R) {
00521 double Lv = L.Val, Rv = R.Val, pL = 1. / Rv, q = Lv/Rv, qpL = q*pL;
00522 return *(new ADvar2q(q, pL, -qpL, -pL*pL, 2.*pL*qpL, &L, &R));
00523 }
00524
00525 ADvar&
00526 ADvar::operator/=(const ADvari &R) {
00527 ADvari *Lcv = cv;
00528 #ifdef RAD_AUTO_AD_Const
00529 Lcv->padv = 0;
00530 #endif
00531 double Lv = Lcv->Val, Rv = R.Val, pL = 1. / Rv, q = Lv/Rv, qpL = q*pL;
00532 cv = new ADvar2q(q, pL, -qpL, -pL*pL, 2.*pL*qpL, Lcv, &R);
00533 return *this;
00534 }
00535
00536 ADvari&
00537 operator/(const ADvari &L, double R) {
00538 return *(new ADvar1s(L.Val / R, 1./R, &L));
00539 }
00540
00541 ADvari&
00542 operator/(double L, const ADvari &R) {
00543 double recip = 1. / R.Val;
00544 double q = L * recip;
00545 double d1 = -q*recip;
00546 return *(new ADvar1g(q, d1, -q*d1, &R));
00547 }
00548
00549 ADvar&
00550 ADvar::operator/=(double R) {
00551 ADvari *Lcv = cv;
00552 #ifdef RAD_AUTO_AD_Const
00553 Lcv->padv = 0;
00554 #endif
00555 cv = new ADvar1s(Lcv->Val / R, 1./R, Lcv);
00556 return *this;
00557 }
00558
00559 ADvari&
00560 acos(const ADvari &v) {
00561 double t = v.Val;
00562 double t1 = 1. - t*t;
00563 double d1 = -1. / sqrt(t1);
00564 return *(new ADvar1g(acos(t), d1, t*d1/t1, &v));
00565 }
00566
00567 ADvari&
00568 acosh(const ADvari &v) {
00569 double d1, t, t1, t2;
00570 t = v.Val;
00571 t1 = sqrt(t2 = t*t - 1.);
00572 d1 = 1./t1;
00573 return *(new ADvar1g(log(t + t1), d1, -t*d1/t2, &v));
00574 }
00575
00576 ADvari&
00577 asin(const ADvari &v) {
00578 double d1, t, t1;
00579 t = v.Val;
00580 d1 = 1. / sqrt(t1 = 1. - t*t);
00581 return *(new ADvar1g(asin(t), d1, t*d1/t1, &v));
00582 }
00583
00584 ADvari&
00585 asinh(const ADvari &v) {
00586 double d1, t, t1, t2, td;
00587 t = v.Val;
00588 t1 = sqrt(t2 = t*t + 1.);
00589 d1 = 1. / t1;
00590 td = 1.;
00591 if (t < 0.)
00592 td = -1.;
00593 return *(new ADvar1g(td*log(t*td + t1), d1, -(t/t2)*d1, &v));
00594 }
00595
00596 ADvari&
00597 atan(const ADvari &v) {
00598 double d1, t;
00599 t = v.Val;
00600 d1 = 1./(1. + t*t);
00601 return *(new ADvar1g(atan(t), d1, -(t+t)*d1*d1, &v));
00602 }
00603
00604 ADvari&
00605 atanh(const ADvari &v) {
00606 double t = v.Val;
00607 double d1 = 1./(1. - t*t);
00608 return *(new ADvar1g(0.5*log((1.+t)/(1.-t)), d1, (t+t)*d1*d1, &v));
00609 }
00610
00611 ADvari&
00612 max(const ADvari &L, const ADvari &R) {
00613 const ADvari &x = L.Val >= R.Val ? L : R;
00614 return *(new ADvar1(Hv_copy, x.Val, &CADcontext::One, &x));
00615 }
00616
00617 ADvari&
00618 max(double L, const ADvari &R) {
00619 if (L >= R.Val)
00620 return *(new ADvari(Hv_const, L));
00621 return *(new ADvar1(Hv_copy, R.Val, &CADcontext::One, &R));
00622 }
00623
00624 ADvari&
00625 max(const ADvari &L, double R) {
00626 if (L.Val >= R)
00627 return *(new ADvar1(Hv_copy, L.Val, &CADcontext::One, &L));
00628 return *(new ADvari(Hv_const, R));
00629 }
00630
00631 ADvari&
00632 min(const ADvari &L, const ADvari &R) {
00633 const ADvari &x = L.Val <= R.Val ? L : R;
00634 return *(new ADvar1(Hv_copy, x.Val, &CADcontext::One, &x));
00635 }
00636
00637 ADvari&
00638 min(double L, const ADvari &R) {
00639 if (L <= R.Val)
00640 return *(new ADvari(Hv_const, L));
00641 return *(new ADvar1(Hv_copy, R.Val, &CADcontext::One, &R));
00642 }
00643
00644 ADvari&
00645 min(const ADvari &L, double R) {
00646 if (L.Val <= R)
00647 return *(new ADvar1(Hv_copy, L.Val, &CADcontext::One, &L));
00648 return *(new ADvari(Hv_const, R));
00649 }
00650
00651 ADvari&
00652 atan2(const ADvari &L, const ADvari &R) {
00653 double x = L.Val, y = R.Val;
00654 double x2 = x*x, y2 = y*y;
00655 double t = 1./(x2 + y2);
00656 double t2 = t*t;
00657 double R2 = 2.*t2*x*y;
00658 return *(new ADvar2g(atan2(x,y), y*t, -x*t, -R2, t2*(x2 - y2), R2, &L, &R));
00659 }
00660
00661 ADvari&
00662 atan2(double x, const ADvari &R) {
00663 double y = R.Val;
00664 double x2 = x*x, y2 = y*y;
00665 double t = 1./(x2 + y2);
00666 return *(new ADvar1g(atan2(x,y), -x*t, 2.*t*t*x*y, &R));
00667 }
00668
00669 ADvari&
00670 atan2(const ADvari &L, double y) {
00671 double x = L.Val;
00672 double x2 = x*x, y2 = y*y;
00673 double t = 1./(x2 + y2);
00674 return *(new ADvar1g(atan2(x,y), y*t, -2.*t*t*x*y, &L));
00675 }
00676
00677 ADvari&
00678 cos(const ADvari &v) {
00679 double t = cos(v.Val);
00680 return *(new ADvar1g(t, -sin(v.Val), -t, &v));
00681 }
00682
00683 ADvari&
00684 cosh(const ADvari &v) {
00685 double t = cosh(v.Val);
00686 return *(new ADvar1g(t, sinh(v.Val), t, &v));
00687 }
00688
00689 ADvari&
00690 exp(const ADvari &v) {
00691 double t = exp(v.Val);
00692 return *(new ADvar1g(t, t, t, &v));
00693 }
00694
00695 ADvari&
00696 log(const ADvari &v) {
00697 double x = v.Val;
00698 double d1 = 1. / x;
00699 return *(new ADvar1g(log(x), d1, -d1*d1, &v));
00700 }
00701
00702 ADvari&
00703 log10(const ADvari &v) {
00704 static double num = 1. / log(10.);
00705 double x = v.Val, t = 1. / x;
00706 double d1 = num * t;
00707 return *(new ADvar1g(log10(x), d1, -d1*t, &v));
00708 }
00709
00710 ADvari&
00711 pow(const ADvari &L, const ADvari &R) {
00712 double x = L.Val, y = R.Val, t = pow(x,y);
00713 double xym1 = t/x;
00714 double xlog = log(x);
00715 double dx = y*xym1;
00716 double dy = t * xlog;
00717 return *(new ADvar2g(t, dx, dy, (y-1.)*dx/x, xym1*(1. + y*xlog), dy*xlog, &L, &R));
00718 }
00719
00720 ADvari&
00721 pow(double x, const ADvari &R) {
00722 double y = R.Val, t = pow(x,y);
00723 double xlog = log(x);
00724 double dy = t * xlog;
00725 return *(new ADvar1g(t, dy, dy*xlog, &R));
00726 }
00727
00728 ADvari&
00729 pow(const ADvari &L, double y) {
00730 double x = L.Val, t = pow(x,y);
00731 double dx = y*t/x;
00732 return *(new ADvar1g(t, dx, (y-1.)*dx/x, &L));
00733 }
00734
00735 ADvari&
00736 sin(const ADvari &v) {
00737 double t = sin(v.Val);
00738 return *(new ADvar1g(t, cos(v.Val), -t, &v));
00739 }
00740
00741 ADvari&
00742 sinh(const ADvari &v) {
00743 double t = sinh(v.Val);
00744 return *(new ADvar1g(t, cosh(v.Val), t, &v));
00745 }
00746
00747 ADvari&
00748 sqrt(const ADvari &v) {
00749 double t = sqrt(v.Val);
00750 double d1 = 0.5/t;
00751 return *(new ADvar1g(t, d1, -0.5*d1/v.Val, &v));
00752 }
00753
00754 ADvari&
00755 tan(const ADvari &v) {
00756 double d1, rv, t;
00757 rv = tan(v.Val);
00758 t = 1. / cos(v.Val);
00759 d1 = t*t;
00760 return *(new ADvar1g(rv, d1, (rv+rv)*d1, &v));
00761 }
00762
00763 ADvari&
00764 tanh(const ADvari &v) {
00765 double d1, rv, t;
00766 rv = tanh(v.Val);
00767 t = 1. / cosh(v.Val);
00768 d1 = t*t;
00769 return *(new ADvar1g(rv, d1, -(rv+rv)*d1, &v));
00770 }
00771
00772 ADvari&
00773 fabs(const ADvari &v) {
00774
00775 double t, p;
00776 p = 1;
00777 if ((t = v.Val) < 0) {
00778 t = -t;
00779 p = -p;
00780 }
00781 return *(new ADvar1g(t, p, 0., &v));
00782 }
00783
00784 ADvari&
00785 ADf1(double f, double g, double h, const ADvari &x) {
00786 return *(new ADvar1g(f, g, h, &x));
00787 }
00788
00789 ADvari&
00790 ADf2(double f, double gx, double gy, double hxx, double hxy, double hyy,
00791 const ADvari &x, const ADvari &y) {
00792 return *(new ADvar2g(f, gx, gy, hxx, hxy, hyy, &x, &y));
00793 }
00794
00795 ADvarn::ADvarn(double val1, int n1, const ADvar *x, const double *g, const double *h):
00796 n(n1), ADvari(Hv_nary,val1)
00797 {
00798 Derp *d1, *dlast;
00799 double *a1;
00800 int i, nh;
00801
00802 a1 = G = (double*)ADvari::adc.Memalloc(n*sizeof(*g));
00803 d1 = D = (Derp*)ADvari::adc.Memalloc(n*sizeof(Derp));
00804 dlast = Derp::LastDerp;
00805 for(i = 0; i < n1; i++, d1++) {
00806 d1->next = dlast;
00807 dlast = d1;
00808 a1[i] = g[i];
00809 d1->a = &a1[i];
00810 d1->b = this;
00811 d1->c = x[i].cv;
00812 }
00813 Derp::LastDerp = dlast;
00814 nh = (n*(n+1)) >> 1;
00815 a1 = H = (double*)ADvari::adc.Memalloc(nh * sizeof(*h));
00816 for(i = 0; i < nh; i++)
00817 a1[i] = h[i];
00818 }
00819
00820 ADvari&
00821 ADfn(double f, int n, const ADvar *x, const double *g, const double *h) {
00822 return *(new ADvarn(f, n, x, g, h));
00823 }
00824
00825 void
00826 ADcontext::Hvprod(int n, ADvar **x, double *v, double *hv)
00827 {
00828 ADvari *a, *aL, *aR, **ap, **ape;
00829 ADvari_block *b, *b0;
00830 Derp *d;
00831 double aO, adO, *g, *h, *h0, t, tL, tR;
00832 int i, j, k, m;
00833 for(i = 0; i < n; i++) {
00834 a = x[i]->cv;
00835 a->dO = v[i];
00836 a->aO = a->adO = 0.;
00837 }
00838 ADvari::adc.Aibusy->limit = ADvari::adc.Ainext;
00839 a = 0;
00840 for(b0 = 0, b = &ADvari::adc.AiFirst; b; b0 = b, b = b->next) {
00841 ap = b->pADvari;
00842 ape = b->limit;
00843 while(ap < ape) {
00844 a = *ap++;
00845 a->aO = a->adO = 0.;
00846 switch(a->opclass) {
00847 case Hv_copy:
00848 a->dO = ((ADvar1*)a)->d.c->dO;
00849 break;
00850 case Hv_binary:
00851 a->dO = ((ADvar2g*)a)->pL * ((ADvar2g*)a)->dL.c->dO
00852 + ((ADvar2g*)a)->pR * ((ADvar2g*)a)->dR.c->dO;
00853 break;
00854 case Hv_unary:
00855 a->dO = ((ADvar1g*)a)->pL * ((ADvar1g*)a)->d.c->dO;
00856 break;
00857 case Hv_negate:
00858 a->dO = -((ADvar1*)a)->d.c->dO;
00859 break;
00860 case Hv_plusLR:
00861 a->dO = ((ADvar2*)a)->dL.c->dO + ((ADvar2*)a)->dR.c->dO;
00862 break;
00863 case Hv_minusLR:
00864 a->dO = ((ADvar2*)a)->dL.c->dO - ((ADvar2*)a)->dR.c->dO;
00865 break;
00866 case Hv_timesL:
00867 a->dO = ((ADvar1s*)a)->pL * ((ADvar1s*)a)->d.c->dO;
00868 break;
00869 case Hv_timesLR:
00870 a->dO = ((ADvar2*)a)->dR.c->Val * ((ADvar2*)a)->dL.c->dO
00871 + ((ADvar2*)a)->dL.c->Val * ((ADvar2*)a)->dR.c->dO;
00872 break;
00873 case Hv_quotLR:
00874 a->dO = ((ADvar2q*)a)->pL * ((ADvar2q*)a)->dL.c->dO
00875 + ((ADvar2q*)a)->pR * ((ADvar2q*)a)->dR.c->dO;
00876 break;
00877 case Hv_nary:
00878 d = ((ADvarn*)a)->D;
00879 m = ((ADvarn*)a)->n;
00880 g = ((ADvarn*)a)->G;
00881 t = 0.;
00882 for(i = 0; i < m; i++)
00883 t += g[i] * d[i].c->dO;
00884 a->dO = t;
00885 }
00886 }
00887 }
00888 if (a)
00889 a->adO = 1.;
00890 for(b = b0; b; b = b->prev) {
00891 ape = b->pADvari;
00892 ap = b->limit;
00893 while(ap > ape) {
00894 a = *--ap;
00895 aO = a->aO;
00896 adO = a->adO;
00897 switch(a->opclass) {
00898 case Hv_copy:
00899 aL = ((ADvar1*)a)->d.c;
00900 aL->aO += aO;
00901 aL->adO += adO;
00902 break;
00903 case Hv_binary:
00904 aL = ((ADvar2g*)a)->dL.c;
00905 aR = ((ADvar2g*)a)->dR.c;
00906 tL = adO*aL->dO;
00907 tR = adO*aR->dO;
00908 aL->aO += aO*((ADvar2g*)a)->pL
00909 + tL*((ADvar2g*)a)->pL2
00910 + tR*((ADvar2g*)a)->pLR;
00911 aR->aO += aO*((ADvar2g*)a)->pR
00912 + tL*((ADvar2g*)a)->pLR
00913 + tR*((ADvar2g*)a)->pR2;
00914 aL->adO += adO * ((ADvar2g*)a)->pL;
00915 aR->adO += adO * ((ADvar2g*)a)->pR;
00916 break;
00917 case Hv_unary:
00918 aL = ((ADvar1g*)a)->d.c;
00919 aL->aO += aO * ((ADvar1g*)a)->pL
00920 + adO * aL->dO * ((ADvar1g*)a)->pL2;
00921 aL->adO += adO * ((ADvar1g*)a)->pL;
00922 break;
00923 case Hv_negate:
00924 aL = ((ADvar1*)a)->d.c;
00925 aL->aO -= aO;
00926 aL->adO -= adO;
00927 break;
00928 case Hv_plusLR:
00929 aL = ((ADvar2*)a)->dL.c;
00930 aR = ((ADvar2*)a)->dR.c;
00931 aL->aO += aO;
00932 aL->adO += adO;
00933 aR->aO += aO;
00934 aR->adO += adO;
00935 break;
00936 case Hv_minusLR:
00937 aL = ((ADvar2*)a)->dL.c;
00938 aR = ((ADvar2*)a)->dR.c;
00939 aL->aO += aO;
00940 aL->adO += adO;
00941 aR->aO -= aO;
00942 aR->adO -= adO;
00943 break;
00944 case Hv_timesL:
00945 aL = ((ADvar1s*)a)->d.c;
00946 aL->aO += aO * (tL = ((ADvar1s*)a)->pL);
00947 aL->adO += adO * tL;
00948 break;
00949 case Hv_timesLR:
00950 aL = ((ADvar2*)a)->dL.c;
00951 aR = ((ADvar2*)a)->dR.c;
00952 aL->aO += aO * (tL = aR->Val) + adO*aR->dO;
00953 aR->aO += aO * (tR = aL->Val) + adO*aL->dO;
00954 aL->adO += adO * tL;
00955 aR->adO += adO * tR;
00956 break;
00957 case Hv_quotLR:
00958 aL = ((ADvar2q*)a)->dL.c;
00959 aR = ((ADvar2q*)a)->dR.c;
00960 tL = adO*aL->dO;
00961 tR = adO*aR->dO;
00962 aL->aO += aO*((ADvar2q*)a)->pL
00963 + tR*((ADvar2q*)a)->pLR;
00964 aR->aO += aO*((ADvar2q*)a)->pR
00965 + tL*((ADvar2q*)a)->pLR
00966 + tR*((ADvar2q*)a)->pR2;
00967 aL->adO += adO * ((ADvar2q*)a)->pL;
00968 aR->adO += adO * ((ADvar2q*)a)->pR;
00969 break;
00970 case Hv_nary:
00971 d = ((ADvarn*)a)->D;
00972 m = ((ADvarn*)a)->n;
00973 g = ((ADvarn*)a)->G;
00974 h0 = ((ADvarn*)a)->H;
00975 for(i = 0; i < m; i++) {
00976 aL = d[i].c;
00977 aL->adO += adO * (t = g[i]);
00978 aL->aO += t*aO;
00979 t = adO * aL->dO;
00980 for(h = h0, j = 0; j <= i; j++)
00981 d[j].c->aO += t * *h++;
00982 h0 = h--;
00983 for(k = j; j < m; j++)
00984 d[j].c->aO += t * *(h += k++);
00985 }
00986 }
00987 }
00988 }
00989 for(i = 0; i < n; i++) {
00990 a = x[i]->cv;
00991 a->dO = 0.;
00992 hv[i] = a->aO;
00993 }
00994 }
00995
00996 #ifndef SACADO_NO_NAMESPACE
00997 }
00998 }
00999 #endif