Sacado Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Sacado_ELRCacheFad_GeneralFad.hpp
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 // ***********************************************************************
9 //
10 // The forward-mode AD classes in Sacado are a derivative work of the
11 // expression template classes in the Fad package by Nicolas Di Cesare.
12 // The following banner is included in the original Fad source code:
13 //
14 // ************ DO NOT REMOVE THIS BANNER ****************
15 //
16 // Nicolas Di Cesare <Nicolas.Dicesare@ann.jussieu.fr>
17 // http://www.ann.jussieu.fr/~dicesare
18 //
19 // CEMRACS 98 : C++ courses,
20 // templates : new C++ techniques
21 // for scientific computing
22 //
23 //********************************************************
24 //
25 // A short implementation ( not all operators and
26 // functions are overloaded ) of 1st order Automatic
27 // Differentiation in forward mode (FAD) using
28 // EXPRESSION TEMPLATES.
29 //
30 //********************************************************
31 // @HEADER
32 
33 #ifndef SACADO_ELRCACHEFAD_GENERALFAD_HPP
34 #define SACADO_ELRCACHEFAD_GENERALFAD_HPP
35 
37 #include "Sacado_mpl_range_c.hpp"
38 #include "Sacado_mpl_for_each.hpp"
39 
40 namespace Sacado {
41 
43  namespace ELRCacheFad {
44 
46 
51  template <typename T, typename Storage>
52  class GeneralFad : public Storage {
53 
54  public:
55 
57  typedef typename RemoveConst<T>::type value_type;
58 
61 
66 
69  GeneralFad() : Storage(T(0.)) {}
70 
72 
75  template <typename S>
78  Storage(x) {}
79 
81 
85  GeneralFad(const int sz, const T & x, const DerivInit zero_out = InitDerivArray) :
86  Storage(sz, x, zero_out) {}
87 
89 
95  GeneralFad(const int sz, const int i, const T & x) :
96  Storage(sz, x, InitDerivArray) {
97  this->fastAccessDx(i)=1.;
98  }
99 
102  GeneralFad(const Storage& s) : Storage(s) {}
103 
107  Storage(x) {}
108 
110  template <typename S>
113  Storage(x.size(), T(0.), NoInitDerivArray) {
114  x.cache();
115 
116  const int sz = x.size();
117 
118  // Compute value
119  this->val() = x.val();
120 
121  if (sz) {
122 
123  if (Expr<S>::is_linear) {
124  if (x.hasFastAccess())
125  for(int i=0; i<sz; ++i)
126  this->fastAccessDx(i) = x.fastAccessDx(i);
127  else
128  for(int i=0; i<sz; ++i)
129  this->fastAccessDx(i) = x.dx(i);
130  }
131  else {
132 
133  if (x.hasFastAccess()) {
134  // Compute partials
135  FastLocalAccumOp< Expr<S> > op(x);
136 
137  // Compute each tangent direction
138  for(op.i=0; op.i<sz; ++op.i) {
139  op.t = T(0.);
140 
141  // Automatically unrolled loop that computes
142  // for (int j=0; j<N; j++)
143  // op.t += op.partials[j] * x.getTangent<j>(i);
145 
146  this->fastAccessDx(op.i) = op.t;
147  }
148  }
149  else {
150  // Compute partials
152 
153  // Compute each tangent direction
154  for(op.i=0; op.i<sz; ++op.i) {
155  op.t = T(0.);
156 
157  // Automatically unrolled loop that computes
158  // for (int j=0; j<N; j++)
159  // op.t += op.partials[j] * x.getTangent<j>(i);
161 
162  this->fastAccessDx(op.i) = op.t;
163  }
164  }
165 
166  }
167  }
168  }
169 
173 
175 
182  void diff(const int ith, const int n) {
183  if (this->size() != n)
184  this->resize(n);
185 
186  this->zero();
187  this->fastAccessDx(ith) = T(1.);
188 
189  }
190 
193  void setUpdateValue(bool update_val) { }
194 
197  bool updateValue() const { return true; }
198 
201  void cache() const {}
202 
204  template <typename S>
206  SACADO_ENABLE_EXPR_FUNC(bool) isEqualTo(const Expr<S>& x) const {
207  typedef IsEqual<value_type> IE;
208  if (x.size() != this->size()) return false;
209  bool eq = IE::eval(x.val(), this->val());
210  for (int i=0; i<this->size(); i++)
211  eq = eq && IE::eval(x.dx(i), this->dx(i));
212  return eq;
213  }
214 
216 
221 
227  int availableSize() const { return this->length(); }
228 
231  bool hasFastAccess() const { return this->size()!=0;}
232 
235  bool isPassive() const { return this->size()==0;}
236 
239  void setIsConstant(bool is_const) {
240  if (is_const && this->size()!=0)
241  this->resize(0);
242  }
243 
245 
250 
252  template <typename S>
254  SACADO_ENABLE_VALUE_FUNC(GeneralFad&) operator=(const S& v) {
255  this->val() = v;
256  if (this->size()) this->resize(0);
257  return *this;
258  }
259 
262  GeneralFad&
263  operator=(const GeneralFad& x) {
264  // Copy value & dx_
265  Storage::operator=(x);
266  return *this;
267  }
268 
270  template <typename S>
272  SACADO_ENABLE_EXPR_FUNC(GeneralFad&) operator=(const Expr<S>& x) {
273  x.cache();
274 
275  const int xsz = x.size();
276 
277  if (xsz != this->size())
278  this->resizeAndZero(xsz);
279 
280  const int sz = this->size();
281 
282  // For ViewStorage, the resize above may not in fact resize the
283  // derivative array, so it is possible that sz != xsz at this point.
284  // The only valid use case here is sz > xsz == 0, so we use sz in the
285  // assignment below
286 
287  if (sz) {
288 
289  if (Expr<S>::is_linear) {
290  if (x.hasFastAccess())
291  for(int i=0; i<sz; ++i)
292  this->fastAccessDx(i) = x.fastAccessDx(i);
293  else
294  for(int i=0; i<sz; ++i)
295  this->fastAccessDx(i) = x.dx(i);
296  }
297  else {
298 
299  if (x.hasFastAccess()) {
300  // Compute partials
301  FastLocalAccumOp< Expr<S> > op(x);
302 
303  // Compute each tangent direction
304  for(op.i=0; op.i<sz; ++op.i) {
305  op.t = T(0.);
306 
307  // Automatically unrolled loop that computes
308  // for (int j=0; j<N; j++)
309  // op.t += op.partials[j] * x.getTangent<j>(i);
311 
312  this->fastAccessDx(op.i) = op.t;
313  }
314  }
315  else {
316  // Compute partials
317  SlowLocalAccumOp< Expr<S> > op(x);
318 
319  // Compute each tangent direction
320  for(op.i=0; op.i<sz; ++op.i) {
321  op.t = T(0.);
322 
323  // Automatically unrolled loop that computes
324  // for (int j=0; j<N; j++)
325  // op.t += op.partials[j] * x.getTangent<j>(i);
327 
328  this->fastAccessDx(op.i) = op.t;
329  }
330  }
331 
332  }
333 
334  }
335 
336  this->val() = x.val();
337 
338  return *this;
339  }
340 
342 
347 
349  template <typename S>
351  SACADO_ENABLE_VALUE_FUNC(GeneralFad&) operator += (const S& v) {
352  this->val() += v;
353  return *this;
354  }
355 
357  template <typename S>
359  SACADO_ENABLE_VALUE_FUNC(GeneralFad&) operator -= (const S& v) {
360  this->val() -= v;
361  return *this;
362  }
363 
365  template <typename S>
367  SACADO_ENABLE_VALUE_FUNC(GeneralFad&) operator *= (const S& v) {
368  const int sz = this->size();
369  this->val() *= v;
370  for (int i=0; i<sz; ++i)
371  this->fastAccessDx(i) *= v;
372  return *this;
373  }
374 
376  template <typename S>
378  SACADO_ENABLE_VALUE_FUNC(GeneralFad&) operator /= (const S& v) {
379  const int sz = this->size();
380  this->val() /= v;
381  for (int i=0; i<sz; ++i)
382  this->fastAccessDx(i) /= v;
383  return *this;
384  }
385 
388  GeneralFad& operator += (const GeneralFad& x) {
389  const int xsz = x.size(), sz = this->size();
390 
391 #if defined(SACADO_DEBUG) && !defined(__CUDA_ARCH__ )
392  if ((xsz != sz) && (xsz != 0) && (sz != 0))
393  throw "Fad Error: Attempt to assign with incompatible sizes";
394 #endif
395 
396  if (xsz) {
397  if (sz) {
398  for (int i=0; i<sz; ++i)
399  this->fastAccessDx(i) += x.fastAccessDx(i);
400  }
401  else {
402  this->resizeAndZero(xsz);
403  for (int i=0; i<xsz; ++i)
404  this->fastAccessDx(i) = x.fastAccessDx(i);
405  }
406  }
407 
408  this->val() += x.val();
409 
410  return *this;
411  }
412 
415  GeneralFad& operator -= (const GeneralFad& x) {
416  const int xsz = x.size(), sz = this->size();
417 
418 #if defined(SACADO_DEBUG) && !defined(__CUDA_ARCH__ )
419  if ((xsz != sz) && (xsz != 0) && (sz != 0))
420  throw "Fad Error: Attempt to assign with incompatible sizes";
421 #endif
422 
423  if (xsz) {
424  if (sz) {
425  for(int i=0; i<sz; ++i)
426  this->fastAccessDx(i) -= x.fastAccessDx(i);
427  }
428  else {
429  this->resizeAndZero(xsz);
430  for(int i=0; i<xsz; ++i)
431  this->fastAccessDx(i) = -x.fastAccessDx(i);
432  }
433  }
434 
435  this->val() -= x.val();
436 
437 
438  return *this;
439  }
440 
443  GeneralFad& operator *= (const GeneralFad& x) {
444  const int xsz = x.size(), sz = this->size();
445  T xval = x.val();
446  T v = this->val();
447 
448 #if defined(SACADO_DEBUG) && !defined(__CUDA_ARCH__ )
449  if ((xsz != sz) && (xsz != 0) && (sz != 0))
450  throw "Fad Error: Attempt to assign with incompatible sizes";
451 #endif
452 
453  if (xsz) {
454  if (sz) {
455  for(int i=0; i<sz; ++i)
456  this->fastAccessDx(i) = v*x.fastAccessDx(i) + this->fastAccessDx(i)*xval;
457  }
458  else {
459  this->resizeAndZero(xsz);
460  for(int i=0; i<xsz; ++i)
461  this->fastAccessDx(i) = v*x.fastAccessDx(i);
462  }
463  }
464  else {
465  if (sz) {
466  for (int i=0; i<sz; ++i)
467  this->fastAccessDx(i) *= xval;
468  }
469  }
470 
471  this->val() *= xval;
472 
473  return *this;
474  }
475 
478  GeneralFad& operator /= (const GeneralFad& x) {
479  const int xsz = x.size(), sz = this->size();
480  T xval = x.val();
481  T v = this->val();
482 
483 #if defined(SACADO_DEBUG) && !defined(__CUDA_ARCH__ )
484  if ((xsz != sz) && (xsz != 0) && (sz != 0))
485  throw "Fad Error: Attempt to assign with incompatible sizes";
486 #endif
487 
488  if (xsz) {
489  if (sz) {
490  for(int i=0; i<sz; ++i)
491  this->fastAccessDx(i) =
492  ( this->fastAccessDx(i)*xval - v*x.fastAccessDx(i) )/ (xval*xval);
493  }
494  else {
495  this->resizeAndZero(xsz);
496  for(int i=0; i<xsz; ++i)
497  this->fastAccessDx(i) = - v*x.fastAccessDx(i) / (xval*xval);
498  }
499  }
500  else {
501  if (sz) {
502  for (int i=0; i<sz; ++i)
503  this->fastAccessDx(i) /= xval;
504  }
505  }
506 
507  this->val() /= xval;
508 
509  return *this;
510  }
511 
513  template <typename S>
515  SACADO_ENABLE_EXPR_FUNC(GeneralFad&) operator += (const Expr<S>& x) {
516  x.cache();
517 
518  const int xsz = x.size(), sz = this->size();
519 
520 #if defined(SACADO_DEBUG) && !defined(__CUDA_ARCH__ )
521  if ((xsz != sz) && (xsz != 0) && (sz != 0))
522  throw "Fad Error: Attempt to assign with incompatible sizes";
523 #endif
524 
525  if (Expr<S>::is_linear) {
526  if (xsz) {
527  if (sz) {
528  if (x.hasFastAccess())
529  for (int i=0; i<sz; ++i)
530  this->fastAccessDx(i) += x.fastAccessDx(i);
531  else
532  for (int i=0; i<sz; ++i)
533  this->fastAccessDx(i) += x.dx(i);
534  }
535  else {
536  this->resizeAndZero(xsz);
537  if (x.hasFastAccess())
538  for (int i=0; i<xsz; ++i)
539  this->fastAccessDx(i) = x.fastAccessDx(i);
540  else
541  for (int i=0; i<xsz; ++i)
542  this->fastAccessDx(i) = x.dx(i);
543  }
544  }
545  }
546  else {
547 
548  if (xsz) {
549 
550  if (sz != xsz)
551  this->resizeAndZero(xsz);
552 
553  if (x.hasFastAccess()) {
554  // Compute partials
555  FastLocalAccumOp< Expr<S> > op(x);
556 
557  // Compute each tangent direction
558  for(op.i=0; op.i<xsz; ++op.i) {
559  op.t = T(0.);
560 
561  // Automatically unrolled loop that computes
562  // for (int j=0; j<N; j++)
563  // op.t += op.partials[j] * x.getTangent<j>(i);
565 
566  this->fastAccessDx(op.i) += op.t;
567  }
568  }
569  else {
570  // Compute partials
571  SlowLocalAccumOp< Expr<S> > op(x);
572 
573  // Compute each tangent direction
574  for(op.i=0; op.i<xsz; ++op.i) {
575  op.t = T(0.);
576 
577  // Automatically unrolled loop that computes
578  // for (int j=0; j<N; j++)
579  // op.t += op.partials[j] * x.getTangent<j>(i);
581 
582  this->fastAccessDx(op.i) += op.t;
583  }
584  }
585 
586  }
587 
588  }
589 
590  this->val() += x.val();
591 
592  return *this;
593  }
594 
596  template <typename S>
598  SACADO_ENABLE_EXPR_FUNC(GeneralFad&) operator -= (const Expr<S>& x) {
599  x.cache();
600 
601  const int xsz = x.size(), sz = this->size();
602 
603 #if defined(SACADO_DEBUG) && !defined(__CUDA_ARCH__ )
604  if ((xsz != sz) && (xsz != 0) && (sz != 0))
605  throw "Fad Error: Attempt to assign with incompatible sizes";
606 #endif
607 
608  if (Expr<S>::is_linear) {
609  if (xsz) {
610  if (sz) {
611  if (x.hasFastAccess())
612  for(int i=0; i<sz; ++i)
613  this->fastAccessDx(i) -= x.fastAccessDx(i);
614  else
615  for (int i=0; i<sz; ++i)
616  this->fastAccessDx(i) -= x.dx(i);
617  }
618  else {
619  this->resizeAndZero(xsz);
620  if (x.hasFastAccess())
621  for(int i=0; i<xsz; ++i)
622  this->fastAccessDx(i) = -x.fastAccessDx(i);
623  else
624  for (int i=0; i<xsz; ++i)
625  this->fastAccessDx(i) = -x.dx(i);
626  }
627  }
628  }
629  else {
630 
631  if (xsz) {
632 
633  if (sz != xsz)
634  this->resizeAndZero(xsz);
635 
636  if (x.hasFastAccess()) {
637  // Compute partials
638  FastLocalAccumOp< Expr<S> > op(x);
639 
640  // Compute each tangent direction
641  for(op.i=0; op.i<xsz; ++op.i) {
642  op.t = T(0.);
643 
644  // Automatically unrolled loop that computes
645  // for (int j=0; j<N; j++)
646  // op.t += op.partials[j] * x.getTangent<j>(i);
648 
649  this->fastAccessDx(op.i) -= op.t;
650  }
651  }
652  else {
653  // Compute partials
654  SlowLocalAccumOp< Expr<S> > op(x);
655 
656  // Compute each tangent direction
657  for(op.i=0; op.i<xsz; ++op.i) {
658  op.t = T(0.);
659 
660  // Automatically unrolled loop that computes
661  // for (int j=0; j<N; j++)
662  // op.t += op.partials[j] * x.getTangent<j>(i);
664 
665  this->fastAccessDx(op.i) -= op.t;
666  }
667  }
668 
669  }
670 
671  }
672 
673  this->val() -= x.val();
674 
675  return *this;
676  }
677 
679  template <typename S>
681  SACADO_ENABLE_EXPR_FUNC(GeneralFad&) operator *= (const Expr<S>& x) {
682  x.cache();
683 
684  const int xsz = x.size(), sz = this->size();
685  T xval = x.val();
686  T v = this->val();
687 
688 #if defined(SACADO_DEBUG) && !defined(__CUDA_ARCH__ )
689  if ((xsz != sz) && (xsz != 0) && (sz != 0))
690  throw "Fad Error: Attempt to assign with incompatible sizes";
691 #endif
692 
693  if (Expr<S>::is_linear) {
694  if (xsz) {
695  if (sz) {
696  if (x.hasFastAccess())
697  for(int i=0; i<sz; ++i)
698  this->fastAccessDx(i) = v*x.fastAccessDx(i) + this->fastAccessDx(i)*xval;
699  else
700  for (int i=0; i<sz; ++i)
701  this->fastAccessDx(i) = v*x.dx(i) + this->fastAccessDx(i)*xval;
702  }
703  else {
704  this->resizeAndZero(xsz);
705  if (x.hasFastAccess())
706  for(int i=0; i<xsz; ++i)
707  this->fastAccessDx(i) = v*x.fastAccessDx(i);
708  else
709  for (int i=0; i<xsz; ++i)
710  this->fastAccessDx(i) = v*x.dx(i);
711  }
712  }
713  else {
714  if (sz) {
715  for (int i=0; i<sz; ++i)
716  this->fastAccessDx(i) *= xval;
717  }
718  }
719  }
720  else {
721 
722  if (xsz) {
723 
724  if (sz) {
725 
726  if (x.hasFastAccess()) {
727  // Compute partials
728  FastLocalAccumOp< Expr<S> > op(x);
729 
730  // Compute each tangent direction
731  for(op.i=0; op.i<xsz; ++op.i) {
732  op.t = T(0.);
733 
734  // Automatically unrolled loop that computes
735  // for (int j=0; j<N; j++)
736  // op.t += op.partials[j] * x.getTangent<j>(i);
738 
739  this->fastAccessDx(op.i) =
740  v * op.t + this->fastAccessDx(op.i) * xval;
741  }
742  }
743  else {
744  // Compute partials
745  SlowLocalAccumOp< Expr<S> > op(x);
746 
747  // Compute each tangent direction
748  for(op.i=0; op.i<xsz; ++op.i) {
749  op.t = T(0.);
750 
751  // Automatically unrolled loop that computes
752  // for (int j=0; j<N; j++)
753  // op.t += op.partials[j] * x.getTangent<j>(i);
755 
756  this->fastAccessDx(op.i) =
757  v * op.t + this->fastAccessDx(op.i) * xval;
758  }
759  }
760 
761  }
762 
763  else {
764 
765  this->resizeAndZero(xsz);
766 
767  if (x.hasFastAccess()) {
768  // Compute partials
769  FastLocalAccumOp< Expr<S> > op(x);
770 
771  // Compute each tangent direction
772  for(op.i=0; op.i<xsz; ++op.i) {
773  op.t = T(0.);
774 
775  // Automatically unrolled loop that computes
776  // for (int j=0; j<N; j++)
777  // op.t += op.partials[j] * x.getTangent<j>(i);
779 
780  this->fastAccessDx(op.i) = v * op.t;
781  }
782  }
783  else {
784  // Compute partials
785  SlowLocalAccumOp< Expr<S> > op(x);
786 
787  // Compute each tangent direction
788  for(op.i=0; op.i<xsz; ++op.i) {
789  op.t = T(0.);
790 
791  // Automatically unrolled loop that computes
792  // for (int j=0; j<N; j++)
793  // op.t += op.partials[j] * x.getTangent<j>(i);
795 
796  this->fastAccessDx(op.i) = v * op.t;
797  }
798  }
799 
800  }
801 
802  }
803 
804  else {
805 
806  if (sz) {
807  for (int i=0; i<sz; ++i)
808  this->fastAccessDx(i) *= xval;
809  }
810 
811  }
812 
813  }
814 
815  this->val() *= xval;
816 
817  return *this;
818  }
819 
821  template <typename S>
823  SACADO_ENABLE_EXPR_FUNC(GeneralFad&) operator /= (const Expr<S>& x) {
824  x.cache();
825 
826  const int xsz = x.size(), sz = this->size();
827  T xval = x.val();
828  T v = this->val();
829 
830 #if defined(SACADO_DEBUG) && !defined(__CUDA_ARCH__ )
831  if ((xsz != sz) && (xsz != 0) && (sz != 0))
832  throw "Fad Error: Attempt to assign with incompatible sizes";
833 #endif
834 
835  if (Expr<S>::is_linear) {
836  if (xsz) {
837  if (sz) {
838  if (x.hasFastAccess())
839  for(int i=0; i<sz; ++i)
840  this->fastAccessDx(i) = ( this->fastAccessDx(i)*xval - v*x.fastAccessDx(i) )/ (xval*xval);
841  else
842  for (int i=0; i<sz; ++i)
843  this->fastAccessDx(i) = ( this->fastAccessDx(i)*xval - v*x.dx(i) )/ (xval*xval);
844  }
845  else {
846  this->resizeAndZero(xsz);
847  if (x.hasFastAccess())
848  for(int i=0; i<xsz; ++i)
849  this->fastAccessDx(i) = - v*x.fastAccessDx(i) / (xval*xval);
850  else
851  for (int i=0; i<xsz; ++i)
852  this->fastAccessDx(i) = -v*x.dx(i) / (xval*xval);
853  }
854  }
855  else {
856  if (sz) {
857  for (int i=0; i<sz; ++i)
858  this->fastAccessDx(i) /= xval;
859  }
860  }
861  }
862  else {
863 
864  if (xsz) {
865 
866  T xval2 = xval*xval;
867 
868  if (sz) {
869 
870  if (x.hasFastAccess()) {
871  // Compute partials
872  FastLocalAccumOp< Expr<S> > op(x);
873 
874  // Compute each tangent direction
875  for(op.i=0; op.i<xsz; ++op.i) {
876  op.t = T(0.);
877 
878  // Automatically unrolled loop that computes
879  // for (int j=0; j<N; j++)
880  // op.t += op.partials[j] * x.getTangent<j>(i);
882 
883  this->fastAccessDx(op.i) =
884  (this->fastAccessDx(op.i) * xval - v * op.t) / xval2;
885  }
886  }
887  else {
888  // Compute partials
889  SlowLocalAccumOp< Expr<S> > op(x);
890 
891  // Compute each tangent direction
892  for(op.i=0; op.i<xsz; ++op.i) {
893  op.t = T(0.);
894 
895  // Automatically unrolled loop that computes
896  // for (int j=0; j<N; j++)
897  // op.t += op.partials[j] * x.getTangent<j>(i);
899 
900  this->fastAccessDx(op.i) =
901  (this->fastAccessDx(op.i) * xval - v * op.t) / xval2;
902  }
903  }
904 
905  }
906 
907  else {
908 
909  this->resizeAndZero(xsz);
910 
911  if (x.hasFastAccess()) {
912  // Compute partials
913  FastLocalAccumOp< Expr<S> > op(x);
914 
915  // Compute each tangent direction
916  for(op.i=0; op.i<xsz; ++op.i) {
917  op.t = T(0.);
918 
919  // Automatically unrolled loop that computes
920  // for (int j=0; j<N; j++)
921  // op.t += op.partials[j] * x.getTangent<j>(i);
923 
924  this->fastAccessDx(op.i) = (-v * op.t) / xval2;
925  }
926  }
927  else {
928  // Compute partials
929  SlowLocalAccumOp< Expr<S> > op(x);
930 
931  // Compute each tangent direction
932  for(op.i=0; op.i<xsz; ++op.i) {
933  op.t = T(0.);
934 
935  // Automatically unrolled loop that computes
936  // for (int j=0; j<N; j++)
937  // op.t += op.partials[j] * x.getTangent<j>(i);
939 
940  this->fastAccessDx(op.i) = (-v * op.t) / xval2;
941  }
942  }
943 
944  }
945 
946  }
947 
948  else {
949 
950  if (sz) {
951  for (int i=0; i<sz; ++i)
952  this->fastAccessDx(i) /= xval;
953  }
954 
955  }
956 
957  }
958 
959  this->val() /= xval;
960 
961  return *this;
962  }
963 
965 
966  protected:
967 
968  // Functor for mpl::for_each to compute the local accumulation
969  // of a tangent derivative
970  //
971  // We use getTangent<>() to get dx components from expression
972  // arguments instead of getting the argument directly or extracting
973  // the dx array due to striding in ViewFad (or could use striding
974  // directly here if we need to get dx array).
975  template <typename ExprT>
976  struct FastLocalAccumOp {
977  typedef typename ExprT::value_type value_type;
978  static const int N = ExprT::num_args;
979  const ExprT& x;
980  mutable value_type t;
981  value_type partials[N];
982  int i;
984  FastLocalAccumOp(const ExprT& x_) : x(x_) {
985  x.computePartials(value_type(1.), partials);
986  }
987  template <typename ArgT>
989  void operator () (ArgT arg) const {
990  const int Arg = ArgT::value;
991  t += partials[Arg] * x.template getTangent<Arg>(i);
992  }
993  };
994 
995  template <typename ExprT>
996  struct SlowLocalAccumOp : FastLocalAccumOp<ExprT> {
998  SlowLocalAccumOp(const ExprT& x_) :
999  FastLocalAccumOp<ExprT>(x_) {}
1000  template <typename ArgT>
1002  void operator () (ArgT arg) const {
1003  const int Arg = ArgT::value;
1004  if (this->x.template isActive<Arg>())
1005  this->t += this->partials[Arg] * this->x.template getTangent<Arg>(this->i);
1006  }
1007  };
1008 
1009  }; // class GeneralFad
1010 
1011 
1012  template <typename T, typename Storage>
1013  std::ostream& operator << (std::ostream& os,
1014  const GeneralFad<T,Storage>& x) {
1015  os << x.val() << " [";
1016 
1017  for (int i=0; i< x.size(); i++) {
1018  os << " " << x.dx(i);
1019  }
1020 
1021  os << " ]";
1022  return os;
1023  }
1024 
1025  } // namespace ELRCacheFad
1026 
1027 } // namespace Sacado
1028 
1029 #endif // SACADO_ELRCACHEFAD_GENERALFAD_HPP
SACADO_INLINE_FUNCTION bool updateValue() const
Return whether this Fad object has an updated value.
void f()
expr expr dx(i)
SACADO_INLINE_FUNCTION GeneralFad(const Storage &s)
Constructor with supplied storage s.
#define SACADO_ENABLE_VALUE_CTOR_DECL
RemoveConst< T >::type value_type
Typename of values.
SACADO_INLINE_FUNCTION void setUpdateValue(bool update_val)
Set whether this Fad object should update values.
#define SACADO_ENABLE_EXPR_CTOR_DECL
SACADO_INLINE_FUNCTION GeneralFad()
Default constructor.
expr val()
SACADO_INLINE_FUNCTION void cache() const
Cache values.
#define T
Definition: Sacado_rad.hpp:553
SACADO_INLINE_FUNCTION GeneralFad(const int sz, const T &x, const DerivInit zero_out=InitDerivArray)
Constructor with size sz and value x.
SACADO_INLINE_FUNCTION SACADO_ENABLE_VALUE_FUNC(GeneralFad &) operator
Assignment operator with constant right-hand-side.
Base template specification for testing equivalence.
SACADO_INLINE_FUNCTION bool isPassive() const
Returns true if derivative array is empty.
static double x_
SACADO_INLINE_FUNCTION ~GeneralFad()
Destructor.
Wrapper for a generic expression template.
SACADO_INLINE_FUNCTION GeneralFad(const GeneralFad &x)
Copy constructor.
SACADO_INLINE_FUNCTION void operator()(ArgT arg) const
Do not initialize the derivative array.
const int N
DerivInit
Enum use to signal whether the derivative array should be initialized in AD object constructors...
SACADO_INLINE_FUNCTION SACADO_ENABLE_EXPR_FUNC(bool) isEqualTo(const Expr< S > &x) const
Returns whether two Fad objects have the same values.
std::ostream & operator<<(std::ostream &os, const GeneralFad< T, Storage > &x)
ScalarType< value_type >::type scalar_type
Typename of scalar&#39;s (which may be different from T)
int value
SACADO_INLINE_FUNCTION void setIsConstant(bool is_const)
Set whether variable is constant.
expr expr expr fastAccessDx(i)) FAD_UNARYOP_MACRO(exp
SACADO_INLINE_FUNCTION GeneralFad(const Expr< S > &x, SACADO_ENABLE_EXPR_CTOR_DECL)
Copy constructor from any Expression object.
Forward-mode AD class templated on the storage for the derivative array.
SACADO_INLINE_FUNCTION int availableSize() const
Returns number of derivative components that can be stored without reallocation.
SACADO_INLINE_FUNCTION GeneralFad(const S &x, SACADO_ENABLE_VALUE_CTOR_DECL)
Constructor with supplied value x.
Initialize the derivative array.
SACADO_INLINE_FUNCTION bool hasFastAccess() const
Returns true if derivative array is not empty.
SACADO_INLINE_FUNCTION GeneralFad(const int sz, const int i, const T &x)
Constructor with size sz, index i, and value x.
#define SACADO_INLINE_FUNCTION
SACADO_INLINE_FUNCTION void diff(const int ith, const int n)
Set GeneralFad object as the ith independent variable.