Sacado Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Sacado_radops2.cpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // Sacado Package
4 //
5 // Copyright 2006 NTESS and the Sacado contributors.
6 // SPDX-License-Identifier: LGPL-2.1-or-later
7 // *****************************************************************************
8 // @HEADER
9 
10 // Support routines for Hessian-vector products via the RAD package
11 // (Reverse Automatic Differentiation) -- a package specialized for
12 // function and gradient evaluations, and herewith extended for Hessian-
13 // vector products. This specialization is for several Hessian-vector
14 // products at one point, where the vectors are determined on the fly,
15 // e.g., by the conjugate-gradient algorithm. Where the vectors are known
16 // in advance, nestings of RAD and FAD might be more efficient.
17 // RAD Hessian-vector product extension written in 2007 by David M. Gay at
18 // Sandia National Labs, Albuquerque, NM.
19 
20 #include "Sacado_rad2.hpp"
21 
22 #ifndef SACADO_NO_NAMESPACE
23 namespace Sacado {
24 namespace Rad2d { // "2" for 2nd derivatives, "d" for "double"
25 #endif
26 
27 #ifdef RAD_AUTO_AD_Const
28 ADvari *ADvari::First_ADvari, **ADvari::Last_ADvari = &ADvari::First_ADvari;
29 #undef RAD_DEBUG_BLOCKKEEP
30 #else
31 #ifdef RAD_DEBUG_BLOCKKEEP
32 #if !(RAD_DEBUG_BLOCKKEEP > 0)
33 #undef RAD_DEBUG_BLOCKKEEP
34 #else
35 extern "C" void _uninit_f2c(void *x, int type, long len);
36 #define TYDREAL 5
37 static ADmemblock *rad_Oldcurmb;
38 static int rad_busy_blocks;
39 #endif /*RAD_DEBUG_BLOCKKEEP > 0*/
40 #endif /*RAD_DEBUG_BLOCKKEEP*/
41 #endif /*RAD_AUTO_AD_Const*/
42 
43 Derp *Derp::LastDerp = 0;
44 ADcontext ADvari::adc;
45 CADcontext ConstADvari::cadc;
46 ConstADvari *ConstADvari::lastcad;
47 static int rad_need_reinit;
48 #ifdef RAD_DEBUG_BLOCKKEEP
49 static size_t rad_mleft_save;
50 #endif
51 
52 const double CADcontext::One = 1., CADcontext::negOne = -1.;
53 
55 {
56  First.next = 0;
57  Busy = &First;
58  Free = 0;
59  Mbase = (char*)First.memblk;
60  Mleft = sizeof(First.memblk);
61  Aibusy = &AiFirst;
62  Aifree = 0;
64  AiFirst.next = AiFirst.prev = 0;
66  }
67 
68  void*
70 {
71  ADmemblock *mb, *mb0, *mb1, *mbf, *x;
72  ADvari_block *b;
73 #ifdef RAD_AUTO_AD_Const
74  ADvari *a, *anext;
75  IndepADvar *v;
76 #endif /* RAD_AUTO_AD_Const */
77 
78  if (rad_need_reinit && this == &ADvari::adc) {
79  rad_need_reinit = 0;
80  Derp::LastDerp = 0;
81  Aibusy = b = &AiFirst;
82  Aifree = b->next;
83  b->next = b->prev = 0;
85 #ifdef RAD_DEBUG_BLOCKKEEP
86  Mleft = rad_mleft_save;
87  if (Mleft < sizeof(First.memblk))
88  _uninit_f2c(Mbase + Mleft, TYDREAL,
89  (sizeof(First.memblk) - Mleft)/sizeof(double));
90  if ((mb = Busy->next)) {
91  if (!(mb0 = rad_Oldcurmb))
92  mb0 = &First;
93  for(;; mb = mb->next) {
94  _uninit_f2c(mb->memblk, TYDREAL,
95  sizeof(First.memblk)/sizeof(double));
96  if (mb == mb0)
97  break;
98  }
99  }
100  rad_Oldcurmb = Busy;
101  if (rad_busy_blocks >= RAD_DEBUG_BLOCKKEEP) {
102  rad_busy_blocks = 0;
103  rad_Oldcurmb = 0;
104  mb0 = &First;
105  mbf = Free;
106  for(mb = Busy; mb != mb0; mb = mb1) {
107  mb1 = mb->next;
108  mb->next = mbf;
109  mbf = mb;
110  }
111  Free = mbf;
112  Busy = mb;
113  Mbase = (char*)First.memblk;
114  Mleft = sizeof(First.memblk);
115  }
116 
117 #else /* !RAD_DEBUG_BLOCKKEEP */
118 
119  mb0 = &ADvari::adc.First;
120  mbf = ADvari::adc.Free;
121  for(mb = ADvari::adc.Busy; mb != mb0; mb = mb1) {
122  mb1 = mb->next;
123  mb->next = mbf;
124  mbf = mb;
125  }
126  ADvari::adc.Free = mbf;
127  ADvari::adc.Busy = mb;
130 #ifdef RAD_AUTO_AD_Const
131  *ADvari::Last_ADvari = 0;
132  ADvari::Last_ADvari = &ADvari::First_ADvari;
133  if ((anext = ADvari::First_ADvari)) {
134  while((a = anext)) {
135  anext = a->Next;
136  if ((v = a->padv))
137  v->cv = new ADvari(v, a->Val);
138  }
139  }
140 #endif /*RAD_AUTO_AD_Const*/
141 #endif /* RAD_DEBUG_BLOCKKEEP */
142  if (Mleft >= len)
143  return Mbase + (Mleft -= len);
144  }
145 
146  if ((x = Free))
147  Free = x->next;
148  else
149  x = new ADmemblock;
150 #ifdef RAD_DEBUG_BLOCKKEEP
151  rad_busy_blocks++;
152 #endif
153  x->next = Busy;
154  Busy = x;
155  return (Mbase = (char*)x->memblk) +
156  (Mleft = sizeof(First.memblk) - len);
157  }
158 
159  void
161 {
162  ADvari_block *ob, *nb;
163  ob = Aibusy;
164  ob->limit = Ailimit; // should be unnecessary, but harmless
165  if ((nb = Aifree))
166  Aifree = nb->next;
167  else
168  nb = new ADvari_block;
169  Aibusy = Aibusy->next = nb;
170  nb->limit = Ailimit = (Ainext = nb->pADvari) + ADvari_block::Gulp;
171  ob->next = nb;
172  nb->prev = ob;
173  nb->next = 0;
174  }
175 
176  void
177 ADcontext::Gradcomp(int wantgrad)
178 {
179  Derp *d;
180 
181  if (rad_need_reinit && wantgrad) {
182  for(d = Derp::LastDerp; d; d = d->next)
183  d->c->aval = 0;
184  }
185  else {
186  rad_need_reinit = 1;
187 #ifdef RAD_DEBUG_BLOCKKEEP
188  rad_mleft_save = ADvari::adc.Mleft;
189 #endif
190  ADvari::adc.Mleft = 0;
191  }
192 
193  if ((d = Derp::LastDerp) && wantgrad) {
194  d->b->aval = 1;
195  do d->c->aval += *d->a * d->b->aval;
196  while((d = d->next));
197  }
198  }
199 
200  void
201 ADcontext::Weighted_Gradcomp(int n, ADvar **v, double *w)
202 {
203  Derp *d;
204  int i;
205 
206  if (rad_need_reinit) {
207  for(d = Derp::LastDerp; d; d = d->next)
208  d->c->aval = 0;
209  }
210  else {
211  rad_need_reinit = 1;
212 #ifdef RAD_DEBUG_BLOCKKEEP
213  rad_mleft_save = ADvari::adc.Mleft;
214 #endif
215  ADvari::adc.Mleft = 0;
216  }
217  if ((d = Derp::LastDerp)) {
218  for(i = 0; i < n; i++)
219  v[i]->cv->aval = w[i];
220  do d->c->aval += *d->a * d->b->aval;
221  while((d = d->next));
222  }
223  }
224 
225 #ifdef RAD_AUTO_AD_Const
226 
227 IndepADvar::IndepADvar(double d)
228 {
229  cv = new ADvari(this, d);
230  }
231 
233 {
234  cv = new ADvari(this, (double)d);
235  }
236 
238 {
239  cv = new ADvari(this, (double)d);
240  }
241 
242 #else
244 IndepADvar::IndepADvar(double d)
245 {
246  ADvari *x = new ADvari(Hv_const, d);
247  cv = x;
248  }
249 
251 {
252  ADvari *x = new ADvari(Hv_const, (double)d);
253  cv = x;
254  }
255 
257 {
258  ADvari *x = new ADvari(Hv_const, (double)d);
259  cv = x;
260  }
261 
262 #endif /*RAD_AUTO_AD_Const*/
263 
264  void
266 {
267 #ifdef RAD_AUTO_AD_Const
268  ADvari *x = new ADvari(this, d);
269 #else
271  ? new ConstADvari(d)
272  : new ADvari(Hv_const, d);
273 #endif
274  cv = x;
275  }
276 
278 {
279  ConstADvari *x = new ConstADvari(0.);
280  cv = x;
281  }
282 
283  void
285 {
286  ConstADvari *x = new ConstADvari(d);
287  cv = x;
288  }
290 {
291  ConstADvari *y = new ConstADvari(x.Val);
292  new Derp(&CADcontext::One, y, &x); /* for side effect; value not used */
293  cv = y;
294  }
295 
296  void
298 {
299  ConstADvari *ncv = new ConstADvari(v.val());
300  ((IndepADvar*)&v)->cv = ncv;
301  }
302 
303  void
305 {
307  while(x) {
308  x->aval = 0;
309  x = x->prevcad;
310  }
311  }
312 
313 #ifdef RAD_AUTO_AD_Const
314 
315 ADvari::ADvari(const IndepADvar *x, double d): Val(d), aval(0.)
316 {
317  opclass = Hv_const;
318  *Last_ADvari = this;
319  Last_ADvari = &Next;
320  padv = (IndepADvar*)x;
321  }
322 
323 ADvar1::ADvar1(const IndepADvar *x, const IndepADvar &y):
324  ADvari(Hv_copy, y.cv->Val), d(&CADcontext::One, this, y.cv)
325 {
326  *ADvari::Last_ADvari = this;
327  ADvari::Last_ADvari = &Next;
328  padv = (IndepADvar*)x;
329  }
330 
331 ADvar1::ADvar1(const IndepADvar *x, const ADvari &y):
332  ADvari(Hv_copy, y.Val), d(&CADcontext::One, this, &y)
333 {
334  *ADvari::Last_ADvari = this;
335  ADvari::Last_ADvari = &Next;
336  padv = (IndepADvar*)x;
337  }
338 
339 #else
340 
341  ADvar&
343 { This->cv = new ADvar1(Hv_copy, x.Val, &CADcontext::One, (ADvari*)&x); return *This; }
344 
345  IndepADvar&
347 { This->cv = new ADvar1(Hv_copy, x.Val, &CADcontext::One, (ADvari*)&x); return *This; }
348 
349 #endif /*RAD_AUTO_AD_Const*/
350 
351 ADvar2q::ADvar2q(double val1, double Lp, double Rp,
352  double LR, double R2, const ADvari *Lcv, const ADvari *Rcv):
353  ADvar2(Hv_quotLR,val1,Lcv,&pL,Rcv,&pR),
354  pL(Lp), pR(Rp), pLR(LR), pR2(R2) { }
355 
356 ADvar2g::ADvar2g(double val1, double Lp, double Rp,
357  double L2, double LR, double R2, const ADvari *Lcv, const ADvari *Rcv):
358  ADvar2(Hv_binary,val1,Lcv,&pL,Rcv,&pR),
359  pL(Lp), pR(Rp), pL2(L2), pLR(LR), pR2(R2) { }
360 
361  IndepADvar&
363 {
364 #ifdef RAD_AUTO_AD_Const
365  if (cv)
366  cv->padv = 0;
367  cv = new ADvari(this,d);
368 #else
369  cv = new ADvari(Hv_const, d);
370 #endif
371  return *this;
372  }
373 
374  ADvar&
376 {
377 #ifdef RAD_AUTO_AD_Const
378  if (cv)
379  cv->padv = 0;
380  cv = new ADvari(this, d);
381 #else
383  ? new ConstADvari(d)
384  : new ADvari(Hv_const, d);
385 #endif
386  return *this;
387  }
388 
389  ADvari&
390 operator-(const ADvari &T) {
391  return *(new ADvar1(Hv_negate, -T.Val, &CADcontext::negOne, &T));
392  }
393 
394  ADvari&
395 operator+(const ADvari &L, const ADvari &R) {
396  return *(new ADvar2(Hv_plusLR,L.Val + R.Val, &L, &CADcontext::One, &R, &CADcontext::One));
397  }
398 
399  ADvar&
401  ADvari *Lcv = cv;
402 #ifdef RAD_AUTO_AD_Const
403  Lcv->padv = 0;
404 #endif
405  cv = new ADvar2(Hv_plusLR, Lcv->Val + R.Val, Lcv, &CADcontext::One, &R, &CADcontext::One);
406  return *this;
407  }
408 
409  ADvari&
410 operator+(const ADvari &L, double R) {
411  return *(new ADvar1(Hv_copy, L.Val + R, &CADcontext::One, &L));
412  }
413 
414  ADvar&
416  ADvari *tcv = cv;
417 #ifdef RAD_AUTO_AD_Const
418  tcv->padv = 0;
419 #endif
420  cv = new ADvar1(Hv_copy, tcv->Val + R, &CADcontext::One, tcv);
421  return *this;
422  }
423 
424  ADvari&
425 operator+(double L, const ADvari &R) {
426  return *(new ADvar1(Hv_copy, L + R.Val, &CADcontext::One, &R));
427  }
428 
429  ADvari&
430 operator-(const ADvari &L, const ADvari &R) {
431  return *(new ADvar2(Hv_minusLR,L.Val - R.Val, &L, &CADcontext::One, &R, &CADcontext::negOne));
432  }
433 
434  ADvar&
436  ADvari *Lcv = cv;
437 #ifdef RAD_AUTO_AD_Const
438  Lcv->padv = 0;
439 #endif
440  cv = new ADvar2(Hv_minusLR, Lcv->Val - R.Val, Lcv, &CADcontext::One, &R, &CADcontext::negOne);
441  return *this;
442  }
443 
444  ADvari&
445 operator-(const ADvari &L, double R) {
446  return *(new ADvar1(Hv_copy, L.Val - R, &CADcontext::One, &L));
447  }
448 
449  ADvar&
451  ADvari *tcv = cv;
452 #ifdef RAD_AUTO_AD_Const
453  tcv->padv = 0;
454 #endif
455  cv = new ADvar1(Hv_copy, tcv->Val - R, &CADcontext::One, tcv);
456  return *this;
457  }
458 
459  ADvari&
460 operator-(double L, const ADvari &R) {
461  return *(new ADvar1(Hv_negate, L - R.Val, &CADcontext::negOne, &R));
462  }
463 
464  ADvari&
465 operator*(const ADvari &L, const ADvari &R) {
466  return *(new ADvar2(Hv_timesLR, L.Val * R.Val, &L, &R.Val, &R, &L.Val));
467  }
468 
469  ADvar&
471  ADvari *Lcv = cv;
472 #ifdef RAD_AUTO_AD_Const
473  Lcv->padv = 0;
474 #endif
475  cv = new ADvar2(Hv_timesLR, Lcv->Val * R.Val, Lcv, &R.Val, &R, &Lcv->Val);
476  return *this;
477  }
478 
479  ADvari&
480 operator*(const ADvari &L, double R) {
481  return *(new ADvar1s(L.Val * R, R, &L));
482  }
483 
484  ADvar&
486  ADvari *Lcv = cv;
487 #ifdef RAD_AUTO_AD_Const
488  Lcv->padv = 0;
489 #endif
490  cv = new ADvar1s(Lcv->Val * R, R, Lcv);
491  return *this;
492  }
493 
494  ADvari&
495 operator*(double L, const ADvari &R) {
496  return *(new ADvar1s(L * R.Val, L, &R));
497  }
498 
499  ADvari&
500 operator/(const ADvari &L, const ADvari &R) {
501  double Lv = L.Val, Rv = R.Val, pL = 1. / Rv, q = Lv/Rv, qpL = q*pL;
502  return *(new ADvar2q(q, pL, -qpL, -pL*pL, 2.*pL*qpL, &L, &R));
503  }
504 
505  ADvar&
507  ADvari *Lcv = cv;
508 #ifdef RAD_AUTO_AD_Const
509  Lcv->padv = 0;
510 #endif
511  double Lv = Lcv->Val, Rv = R.Val, pL = 1. / Rv, q = Lv/Rv, qpL = q*pL;
512  cv = new ADvar2q(q, pL, -qpL, -pL*pL, 2.*pL*qpL, Lcv, &R);
513  return *this;
514  }
515 
516  ADvari&
517 operator/(const ADvari &L, double R) {
518  return *(new ADvar1s(L.Val / R, 1./R, &L));
519  }
520 
521  ADvari&
522 operator/(double L, const ADvari &R) {
523  double recip = 1. / R.Val;
524  double q = L * recip;
525  double d1 = -q*recip;
526  return *(new ADvar1g(q, d1, -q*d1, &R));
527  }
528 
529  ADvar&
531  ADvari *Lcv = cv;
532 #ifdef RAD_AUTO_AD_Const
533  Lcv->padv = 0;
534 #endif
535  cv = new ADvar1s(Lcv->Val / R, 1./R, Lcv);
536  return *this;
537  }
538 
539  ADvari&
540 acos(const ADvari &v) {
541  double t = v.Val;
542  double t1 = 1. - t*t;
543  double d1 = -1. / sqrt(t1);
544  return *(new ADvar1g(acos(t), d1, t*d1/t1, &v));
545  }
546 
547  ADvari&
548 acosh(const ADvari &v) {
549  double d1, t, t1, t2;
550  t = v.Val;
551  t1 = sqrt(t2 = t*t - 1.);
552  d1 = 1./t1;
553  return *(new ADvar1g(log(t + t1), d1, -t*d1/t2, &v));
554  }
555 
556  ADvari&
557 asin(const ADvari &v) {
558  double d1, t, t1;
559  t = v.Val;
560  d1 = 1. / sqrt(t1 = 1. - t*t);
561  return *(new ADvar1g(asin(t), d1, t*d1/t1, &v));
562  }
563 
564  ADvari&
565 asinh(const ADvari &v) {
566  double d1, t, t1, t2, td;
567  t = v.Val;
568  t1 = sqrt(t2 = t*t + 1.);
569  d1 = 1. / t1;
570  td = 1.;
571  if (t < 0.)
572  td = -1.;
573  return *(new ADvar1g(td*log(t*td + t1), d1, -(t/t2)*d1, &v));
574  }
575 
576  ADvari&
577 atan(const ADvari &v) {
578  double d1, t;
579  t = v.Val;
580  d1 = 1./(1. + t*t);
581  return *(new ADvar1g(atan(t), d1, -(t+t)*d1*d1, &v));
582  }
583 
584  ADvari&
585 atanh(const ADvari &v) {
586  double t = v.Val;
587  double d1 = 1./(1. - t*t);
588  return *(new ADvar1g(0.5*log((1.+t)/(1.-t)), d1, (t+t)*d1*d1, &v));
589  }
590 
591  ADvari&
592 max(const ADvari &L, const ADvari &R) {
593  const ADvari &x = L.Val >= R.Val ? L : R;
594  return *(new ADvar1(Hv_copy, x.Val, &CADcontext::One, &x));
595  }
596 
597  ADvari&
598 max(double L, const ADvari &R) {
599  if (L >= R.Val)
600  return *(new ADvari(Hv_const, L));
601  return *(new ADvar1(Hv_copy, R.Val, &CADcontext::One, &R));
602  }
603 
604  ADvari&
605 max(const ADvari &L, double R) {
606  if (L.Val >= R)
607  return *(new ADvar1(Hv_copy, L.Val, &CADcontext::One, &L));
608  return *(new ADvari(Hv_const, R));
609  }
610 
611  ADvari&
612 min(const ADvari &L, const ADvari &R) {
613  const ADvari &x = L.Val <= R.Val ? L : R;
614  return *(new ADvar1(Hv_copy, x.Val, &CADcontext::One, &x));
615  }
616 
617  ADvari&
618 min(double L, const ADvari &R) {
619  if (L <= R.Val)
620  return *(new ADvari(Hv_const, L));
621  return *(new ADvar1(Hv_copy, R.Val, &CADcontext::One, &R));
622  }
623 
624  ADvari&
625 min(const ADvari &L, double R) {
626  if (L.Val <= R)
627  return *(new ADvar1(Hv_copy, L.Val, &CADcontext::One, &L));
628  return *(new ADvari(Hv_const, R));
629  }
630 
631  ADvari&
632 atan2(const ADvari &L, const ADvari &R) {
633  double x = L.Val, y = R.Val;
634  double x2 = x*x, y2 = y*y;
635  double t = 1./(x2 + y2);
636  double t2 = t*t;
637  double R2 = 2.*t2*x*y;
638  return *(new ADvar2g(atan2(x,y), y*t, -x*t, -R2, t2*(x2 - y2), R2, &L, &R));
639  }
640 
641  ADvari&
642 atan2(double x, const ADvari &R) {
643  double y = R.Val;
644  double x2 = x*x, y2 = y*y;
645  double t = 1./(x2 + y2);
646  return *(new ADvar1g(atan2(x,y), -x*t, 2.*t*t*x*y, &R));
647  }
648 
649  ADvari&
650 atan2(const ADvari &L, double y) {
651  double x = L.Val;
652  double x2 = x*x, y2 = y*y;
653  double t = 1./(x2 + y2);
654  return *(new ADvar1g(atan2(x,y), y*t, -2.*t*t*x*y, &L));
655  }
656 
657  ADvari&
658 cos(const ADvari &v) {
659  double t = cos(v.Val);
660  return *(new ADvar1g(t, -sin(v.Val), -t, &v));
661  }
662 
663  ADvari&
664 cosh(const ADvari &v) {
665  double t = cosh(v.Val);
666  return *(new ADvar1g(t, sinh(v.Val), t, &v));
667  }
668 
669  ADvari&
670 exp(const ADvari &v) {
671  double t = exp(v.Val);
672  return *(new ADvar1g(t, t, t, &v));
673  }
674 
675  ADvari&
676 log(const ADvari &v) {
677  double x = v.Val;
678  double d1 = 1. / x;
679  return *(new ADvar1g(log(x), d1, -d1*d1, &v));
680  }
681 
682  ADvari&
683 log10(const ADvari &v) {
684  static double num = 1. / log(10.);
685  double x = v.Val, t = 1. / x;
686  double d1 = num * t;
687  return *(new ADvar1g(log10(x), d1, -d1*t, &v));
688  }
689 
690  ADvari&
691 pow(const ADvari &L, const ADvari &R) {
692  double x = L.Val, y = R.Val, t = pow(x,y);
693  double xym1 = t/x;
694  double xlog = log(x);
695  double dx = y*xym1;
696  double dy = t * xlog;
697  return *(new ADvar2g(t, dx, dy, (y-1.)*dx/x, xym1*(1. + y*xlog), dy*xlog, &L, &R));
698  }
699 
700  ADvari&
701 pow(double x, const ADvari &R) {
702  double y = R.Val, t = pow(x,y);
703  double xlog = log(x);
704  double dy = t * xlog;
705  return *(new ADvar1g(t, dy, dy*xlog, &R));
706  }
707 
708  ADvari&
709 pow(const ADvari &L, double y) {
710  double x = L.Val, t = pow(x,y);
711  double dx = y*t/x;
712  return *(new ADvar1g(t, dx, (y-1.)*dx/x, &L));
713  }
714 
715  ADvari&
716 sin(const ADvari &v) {
717  double t = sin(v.Val);
718  return *(new ADvar1g(t, cos(v.Val), -t, &v));
719  }
720 
721  ADvari&
722 sinh(const ADvari &v) {
723  double t = sinh(v.Val);
724  return *(new ADvar1g(t, cosh(v.Val), t, &v));
725  }
726 
727  ADvari&
728 sqrt(const ADvari &v) {
729  double t = sqrt(v.Val);
730  double d1 = 0.5/t;
731  return *(new ADvar1g(t, d1, -0.5*d1/v.Val, &v));
732  }
733 
734  ADvari&
735 tan(const ADvari &v) {
736  double d1, rv, t;
737  rv = tan(v.Val);
738  t = 1. / cos(v.Val);
739  d1 = t*t;
740  return *(new ADvar1g(rv, d1, (rv+rv)*d1, &v));
741  }
742 
743  ADvari&
744 tanh(const ADvari &v) {
745  double d1, rv, t;
746  rv = tanh(v.Val);
747  t = 1. / cosh(v.Val);
748  d1 = t*t;
749  return *(new ADvar1g(rv, d1, -(rv+rv)*d1, &v));
750  }
751 
752  ADvari&
753 fabs(const ADvari &v) { // "fabs" is not the best choice of name,
754  // but this name is used at Sandia.
755  double t, p;
756  p = 1;
757  if ((t = v.Val) < 0) {
758  t = -t;
759  p = -p;
760  }
761  return *(new ADvar1g(t, p, 0., &v));
762  }
763 
764  ADvari&
765 ADf1(double f, double g, double h, const ADvari &x) {
766  return *(new ADvar1g(f, g, h, &x));
767  }
768 
769  ADvari&
770 ADf2(double f, double gx, double gy, double hxx, double hxy, double hyy,
771  const ADvari &x, const ADvari &y) {
772  return *(new ADvar2g(f, gx, gy, hxx, hxy, hyy, &x, &y));
773  }
774 
775  ADvarn::ADvarn(double val1, int n1, const ADvar *x, const double *g, const double *h):
776  ADvari(Hv_nary,val1), n(n1)
777 {
778  Derp *d1, *dlast;
779  double *a1;
780  int i, nh;
781 
782  a1 = G = (double*)ADvari::adc.Memalloc(n1*sizeof(*g));
783  d1 = D = (Derp*)ADvari::adc.Memalloc(n1*sizeof(Derp));
784  dlast = Derp::LastDerp;
785  for(i = 0; i < n1; i++, d1++) {
786  d1->next = dlast;
787  dlast = d1;
788  a1[i] = g[i];
789  d1->a = &a1[i];
790  d1->b = this;
791  d1->c = x[i].cv;
792  }
793  Derp::LastDerp = dlast;
794  nh = (n1*(n1+1)) >> 1;
795  a1 = H = (double*)ADvari::adc.Memalloc(nh * sizeof(*h));
796  for(i = 0; i < nh; i++)
797  a1[i] = h[i];
798  }
799 
800  ADvari&
801 ADfn(double f, int n, const ADvar *x, const double *g, const double *h) {
802  return *(new ADvarn(f, n, x, g, h));
803  }
804 
805  void
806 ADcontext::Hvprod(int n, ADvar **x, double *v, double *hv)
807 {
808  ADvari *a, *aL, *aR, **ap, **ape;
809  ADvari_block *b, *b0;
810  Derp *d;
811  double aO, adO, *g, *h, *h0, t, tL, tR;
812  int i, j, k, m;
813  for(i = 0; i < n; i++) {
814  a = x[i]->cv;
815  a->dO = v[i];
816  a->aO = a->adO = 0.;
817  }
819  a = 0;
820  for(b0 = 0, b = &ADvari::adc.AiFirst; b; b0 = b, b = b->next) {
821  ap = b->pADvari;
822  ape = b->limit;
823  while(ap < ape) {
824  a = *ap++;
825  a->aO = a->adO = 0.;
826  switch(a->opclass) {
827  case Hv_copy:
828  a->dO = ((ADvar1*)a)->d.c->dO;
829  break;
830  case Hv_binary:
831  a->dO = ((ADvar2g*)a)->pL * ((ADvar2g*)a)->dL.c->dO
832  + ((ADvar2g*)a)->pR * ((ADvar2g*)a)->dR.c->dO;
833  break;
834  case Hv_unary:
835  a->dO = ((ADvar1g*)a)->pL * ((ADvar1g*)a)->d.c->dO;
836  break;
837  case Hv_negate:
838  a->dO = -((ADvar1*)a)->d.c->dO;
839  break;
840  case Hv_plusLR:
841  a->dO = ((ADvar2*)a)->dL.c->dO + ((ADvar2*)a)->dR.c->dO;
842  break;
843  case Hv_minusLR:
844  a->dO = ((ADvar2*)a)->dL.c->dO - ((ADvar2*)a)->dR.c->dO;
845  break;
846  case Hv_timesL:
847  a->dO = ((ADvar1s*)a)->pL * ((ADvar1s*)a)->d.c->dO;
848  break;
849  case Hv_timesLR:
850  a->dO = ((ADvar2*)a)->dR.c->Val * ((ADvar2*)a)->dL.c->dO
851  + ((ADvar2*)a)->dL.c->Val * ((ADvar2*)a)->dR.c->dO;
852  break;
853  case Hv_quotLR:
854  a->dO = ((ADvar2q*)a)->pL * ((ADvar2q*)a)->dL.c->dO
855  + ((ADvar2q*)a)->pR * ((ADvar2q*)a)->dR.c->dO;
856  case Hv_const: // This case does not arise; the intent here
857  // is to eliminate a red-herring compiler warning.
858  break;
859  case Hv_nary:
860  d = ((ADvarn*)a)->D;
861  m = ((ADvarn*)a)->n;
862  g = ((ADvarn*)a)->G;
863  t = 0.;
864  for(i = 0; i < m; i++)
865  t += g[i] * d[i].c->dO;
866  a->dO = t;
867  }
868  }
869  }
870  if (a)
871  a->adO = 1.;
872  for(b = b0; b; b = b->prev) {
873  ape = b->pADvari;
874  ap = b->limit;
875  while(ap > ape) {
876  a = *--ap;
877  aO = a->aO;
878  adO = a->adO;
879  switch(a->opclass) {
880  case Hv_copy:
881  aL = ((ADvar1*)a)->d.c;
882  aL->aO += aO;
883  aL->adO += adO;
884  break;
885  case Hv_binary:
886  aL = ((ADvar2g*)a)->dL.c;
887  aR = ((ADvar2g*)a)->dR.c;
888  tL = adO*aL->dO;
889  tR = adO*aR->dO;
890  aL->aO += aO*((ADvar2g*)a)->pL
891  + tL*((ADvar2g*)a)->pL2
892  + tR*((ADvar2g*)a)->pLR;
893  aR->aO += aO*((ADvar2g*)a)->pR
894  + tL*((ADvar2g*)a)->pLR
895  + tR*((ADvar2g*)a)->pR2;
896  aL->adO += adO * ((ADvar2g*)a)->pL;
897  aR->adO += adO * ((ADvar2g*)a)->pR;
898  break;
899  case Hv_unary:
900  aL = ((ADvar1g*)a)->d.c;
901  aL->aO += aO * ((ADvar1g*)a)->pL
902  + adO * aL->dO * ((ADvar1g*)a)->pL2;
903  aL->adO += adO * ((ADvar1g*)a)->pL;
904  break;
905  case Hv_negate:
906  aL = ((ADvar1*)a)->d.c;
907  aL->aO -= aO;
908  aL->adO -= adO;
909  break;
910  case Hv_plusLR:
911  aL = ((ADvar2*)a)->dL.c;
912  aR = ((ADvar2*)a)->dR.c;
913  aL->aO += aO;
914  aL->adO += adO;
915  aR->aO += aO;
916  aR->adO += adO;
917  break;
918  case Hv_minusLR:
919  aL = ((ADvar2*)a)->dL.c;
920  aR = ((ADvar2*)a)->dR.c;
921  aL->aO += aO;
922  aL->adO += adO;
923  aR->aO -= aO;
924  aR->adO -= adO;
925  break;
926  case Hv_timesL:
927  aL = ((ADvar1s*)a)->d.c;
928  aL->aO += aO * (tL = ((ADvar1s*)a)->pL);
929  aL->adO += adO * tL;
930  break;
931  case Hv_timesLR:
932  aL = ((ADvar2*)a)->dL.c;
933  aR = ((ADvar2*)a)->dR.c;
934  aL->aO += aO * (tL = aR->Val) + adO*aR->dO;
935  aR->aO += aO * (tR = aL->Val) + adO*aL->dO;
936  aL->adO += adO * tL;
937  aR->adO += adO * tR;
938  break;
939  case Hv_quotLR:
940  aL = ((ADvar2q*)a)->dL.c;
941  aR = ((ADvar2q*)a)->dR.c;
942  tL = adO*aL->dO;
943  tR = adO*aR->dO;
944  aL->aO += aO*((ADvar2q*)a)->pL
945  + tR*((ADvar2q*)a)->pLR;
946  aR->aO += aO*((ADvar2q*)a)->pR
947  + tL*((ADvar2q*)a)->pLR
948  + tR*((ADvar2q*)a)->pR2;
949  aL->adO += adO * ((ADvar2q*)a)->pL;
950  aR->adO += adO * ((ADvar2q*)a)->pR;
951  case Hv_const: // This case does not arise; the intent here
952  // is to eliminate a red-herring compiler warning.
953  break;
954  case Hv_nary:
955  d = ((ADvarn*)a)->D;
956  m = ((ADvarn*)a)->n;
957  g = ((ADvarn*)a)->G;
958  h0 = ((ADvarn*)a)->H;
959  for(i = 0; i < m; i++) {
960  aL = d[i].c;
961  aL->adO += adO * (t = g[i]);
962  aL->aO += t*aO;
963  t = adO * aL->dO;
964  for(h = h0, j = 0; j <= i; j++)
965  d[j].c->aO += t * *h++;
966  h0 = h--;
967  for(k = j; j < m; j++)
968  d[j].c->aO += t * *(h += k++);
969  }
970  }
971  }
972  }
973  for(i = 0; i < n; i++) {
974  a = x[i]->cv;
975  a->dO = 0.;
976  hv[i] = a->aO;
977  }
978  }
979 
980 #ifndef SACADO_NO_NAMESPACE
981 } // namespace Rad2d
982 } // namespace Sacado
983 #endif
const char * p
ADvari & cos(const ADvari &v)
ADvar & operator/=(const ADvari &)
ADvari & operator-(const ADvari &T)
ADvar & operator-=(const ADvari &)
Advari_Opclass opclass
expr expr dx(i)
static void aval_reset(void)
ADvarn(double val1, int n1, const ADvar *x, const double *g, const double *h)
#define TYDREAL
Definition: uninit.c:47
static const double negOne
const double * a
ADvari & operator/(const ADvari &L, const ADvari &R)
ADvari & asinh(const ADvari &v)
ADvar2g(double val1, double Lp, double Rp, double L2, double LR, double R2, const ADvari *Lcv, const ADvari *Rcv)
ADvar2q(double val1, double Lp, double Rp, double LR, double R2, const ADvari *Lcv, const ADvari *Rcv)
IndepADvar & operator=(const IndepADvar &x)
static ConstADvari * lastcad
static void AD_Const(const IndepADvar &)
ADvari & operator*(const ADvari &L, const ADvari &R)
ADvari & acosh(const ADvari &v)
ADvari & operator+(ADvari &T)
ADvari & sinh(const ADvari &v)
ADvari & atanh(const ADvari &v)
Sacado::Rad::ADvar< double > R
Definition: ad_example.cpp:22
ADvari & min(const ADvari &L, const ADvari &R)
ADvari & exp(const ADvari &v)
#define T
Definition: Sacado_rad.hpp:553
ADvari & fabs(const ADvari &v)
ADvari & log10(const ADvari &v)
expr expr1 expr1 expr1 c expr2 expr1 expr2 expr1 expr2 expr1 expr1 expr1 expr1 c expr2 expr1 expr2 expr1 expr2 expr1 expr1 expr1 expr1 c *expr2 expr1 expr2 expr1 expr2 expr1 expr1 expr1 expr1 c expr2 expr1 expr2 expr1 expr2 expr1 expr1 expr1 expr2 expr1 expr2 expr1 expr1 expr1 expr2 expr1 expr2 expr1 expr1 expr1 c
static ADcontext adc
static const double One
void ADvar_ctr(double d)
ADvari & asin(const ADvari &v)
const ADvari * b
ADvari & ADf2(double f, double gx, double gy, double hxx, double hxy, double hyy, const ADvari &x, const ADvari &y)
static CADcontext cadc
static Derp * LastDerp
ADvari & atan(const ADvari &v)
ADvari & cosh(const ADvari &v)
void g()
ADvari & sin(const ADvari &v)
ADvari & tan(const ADvari &v)
static void Hvprod(int, ADvar **, double *, double *)
ADvari & sqrt(const ADvari &v)
void * new_ADmemblock(size_t)
static void Weighted_Gradcomp(int, ADvar **, double *)
ADvari & max(const ADvari &L, const ADvari &R)
static int rad_need_reinit
ADvar & ADvar_operatoreq(ADvar *This, const ADvari &x)
ADvari & pow(const ADvari &L, const ADvari &R)
ADvar1(Advari_Opclass oc, double val1, const double *a1, const ADvari *c1)
ADvari & log(const ADvari &v)
ADvari & acos(const ADvari &v)
ADvar & operator+=(const ADvari &)
ADvar & operator=(const ADvari &x)
ADvari & atan2(const ADvari &L, const ADvari &R)
ADvari & ADf1(double f, double g, double h, const ADvari &x)
ADvari & ADfn(double f, int n, const ADvar *x, const double *g, const double *h)
int n
ADvari & tanh(const ADvari &v)
ADvar & operator*=(const ADvari &)
const double y