Sacado Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Sacado_ELRFad_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_ELRFAD_GENERALFAD_HPP
34 #define SACADO_ELRFAD_GENERALFAD_HPP
35 
37 #include "Sacado_dummy_arg.hpp"
38 #include "Sacado_mpl_range_c.hpp"
39 #include "Sacado_mpl_for_each.hpp"
40 #include<ostream>
41 
42 namespace Sacado {
43 
45  namespace ELRFad {
46 
48 
53  template <typename T, typename Storage>
54  class GeneralFad : public Storage {
55 
56  public:
57 
59  typedef typename RemoveConst<T>::type value_type;
60 
63 
68 
71  GeneralFad() : Storage(T(0.)) {}
72 
74 
77  template <typename S>
80  Storage(x) {}
81 
83 
87  GeneralFad(const int sz, const T & x, const DerivInit zero_out = InitDerivArray) :
88  Storage(sz, x, zero_out) {}
89 
91 
97  GeneralFad(const int sz, const int i, const T & x) :
98  Storage(sz, x, InitDerivArray) {
99  this->fastAccessDx(i)=1.;
100  }
101 
104  GeneralFad(const Storage& s) : Storage(s) {}
105 
109  Storage(x) {}
110 
112  template <typename S>
115  Storage(x.size(), T(0.), NoInitDerivArray) {
116  const int sz = x.size();
117  if (sz) {
118 
119  if (Expr<S>::is_linear) {
120  if (x.hasFastAccess())
121  for(int i=0; i<sz; ++i)
122  this->fastAccessDx(i) = x.fastAccessDx(i);
123  else
124  for(int i=0; i<sz; ++i)
125  this->fastAccessDx(i) = x.dx(i);
126  }
127  else {
128 
129  if (x.hasFastAccess()) {
130  // Compute partials
131  FastLocalAccumOp< Expr<S> > op(x);
132 
133  // Compute each tangent direction
134  for(op.i=0; op.i<sz; ++op.i) {
135  op.t = T(0.);
136 
137  // Automatically unrolled loop that computes
138  // for (int j=0; j<N; j++)
139  // op.t += op.partials[j] * x.getTangent<j>(i);
141 
142  this->fastAccessDx(op.i) = op.t;
143  }
144  }
145  else {
146  // Compute partials
148 
149  // Compute each tangent direction
150  for(op.i=0; op.i<sz; ++op.i) {
151  op.t = T(0.);
152 
153  // Automatically unrolled loop that computes
154  // for (int j=0; j<N; j++)
155  // op.t += op.partials[j] * x.getTangent<j>(i);
157 
158  this->fastAccessDx(op.i) = op.t;
159  }
160  }
161 
162  }
163 
164  }
165 
166  // Compute value
167  this->val() = x.val();
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  const int xsz = x.size();
274  if (xsz != this->size())
275  this->resizeAndZero(xsz);
276 
277  const int sz = this->size();
278 
279  // For ViewStorage, the resize above may not in fact resize the
280  // derivative array, so it is possible that sz != xsz at this point.
281  // The only valid use case here is sz > xsz == 0, so we use sz in the
282  // assignment below
283 
284  if (sz) {
285 
286  if (Expr<S>::is_linear) {
287  if (x.hasFastAccess())
288  for(int i=0; i<sz; ++i)
289  this->fastAccessDx(i) = x.fastAccessDx(i);
290  else
291  for(int i=0; i<sz; ++i)
292  this->fastAccessDx(i) = x.dx(i);
293  }
294  else {
295 
296  if (x.hasFastAccess()) {
297  // Compute partials
298  FastLocalAccumOp< Expr<S> > op(x);
299 
300  // Compute each tangent direction
301  for(op.i=0; op.i<sz; ++op.i) {
302  op.t = T(0.);
303 
304  // Automatically unrolled loop that computes
305  // for (int j=0; j<N; j++)
306  // op.t += op.partials[j] * x.getTangent<j>(i);
308 
309  this->fastAccessDx(op.i) = op.t;
310  }
311  }
312  else {
313  // Compute partials
314  SlowLocalAccumOp< Expr<S> > op(x);
315 
316  // Compute each tangent direction
317  for(op.i=0; op.i<sz; ++op.i) {
318  op.t = T(0.);
319 
320  // Automatically unrolled loop that computes
321  // for (int j=0; j<N; j++)
322  // op.t += op.partials[j] * x.getTangent<j>(i);
324 
325  this->fastAccessDx(op.i) = op.t;
326  }
327  }
328  }
329  }
330 
331  // Compute value
332  this->val() = x.val();
333 
334  return *this;
335  }
336 
338 
343 
345  template <typename S>
347  SACADO_ENABLE_VALUE_FUNC(GeneralFad&) operator += (const S& v) {
348  this->val() += v;
349  return *this;
350  }
351 
353  template <typename S>
355  SACADO_ENABLE_VALUE_FUNC(GeneralFad&) operator -= (const S& v) {
356  this->val() -= v;
357  return *this;
358  }
359 
361  template <typename S>
363  SACADO_ENABLE_VALUE_FUNC(GeneralFad&) operator *= (const S& v) {
364  const int sz = this->size();
365  this->val() *= v;
366  for (int i=0; i<sz; ++i)
367  this->fastAccessDx(i) *= v;
368  return *this;
369  }
370 
372  template <typename S>
374  SACADO_ENABLE_VALUE_FUNC(GeneralFad&) operator /= (const S& v) {
375  const int sz = this->size();
376  this->val() /= v;
377  for (int i=0; i<sz; ++i)
378  this->fastAccessDx(i) /= v;
379  return *this;
380  }
381 
384  GeneralFad& operator += (const GeneralFad& x) {
385  const int xsz = x.size(), sz = this->size();
386 
387 #if defined(SACADO_DEBUG) && !defined(__CUDA_ARCH__ )
388  if ((xsz != sz) && (xsz != 0) && (sz != 0))
389  throw "Fad Error: Attempt to assign with incompatible sizes";
390 #endif
391 
392  if (xsz) {
393  if (sz) {
394  for (int i=0; i<sz; ++i)
395  this->fastAccessDx(i) += x.fastAccessDx(i);
396  }
397  else {
398  this->resizeAndZero(xsz);
399  for (int i=0; i<xsz; ++i)
400  this->fastAccessDx(i) = x.fastAccessDx(i);
401  }
402  }
403 
404  this->val() += x.val();
405 
406  return *this;
407  }
408 
411  GeneralFad& operator -= (const GeneralFad& x) {
412  const int xsz = x.size(), sz = this->size();
413 
414 #if defined(SACADO_DEBUG) && !defined(__CUDA_ARCH__ )
415  if ((xsz != sz) && (xsz != 0) && (sz != 0))
416  throw "Fad Error: Attempt to assign with incompatible sizes";
417 #endif
418 
419  if (xsz) {
420  if (sz) {
421  for(int i=0; i<sz; ++i)
422  this->fastAccessDx(i) -= x.fastAccessDx(i);
423  }
424  else {
425  this->resizeAndZero(xsz);
426  for(int i=0; i<xsz; ++i)
427  this->fastAccessDx(i) = -x.fastAccessDx(i);
428  }
429  }
430 
431  this->val() -= x.val();
432 
433 
434  return *this;
435  }
436 
439  GeneralFad& operator *= (const GeneralFad& x) {
440  const int xsz = x.size(), sz = this->size();
441  T xval = x.val();
442  T v = this->val();
443 
444 #if defined(SACADO_DEBUG) && !defined(__CUDA_ARCH__ )
445  if ((xsz != sz) && (xsz != 0) && (sz != 0))
446  throw "Fad Error: Attempt to assign with incompatible sizes";
447 #endif
448 
449  if (xsz) {
450  if (sz) {
451  for(int i=0; i<sz; ++i)
452  this->fastAccessDx(i) = v*x.fastAccessDx(i) + this->fastAccessDx(i)*xval;
453  }
454  else {
455  this->resizeAndZero(xsz);
456  for(int i=0; i<xsz; ++i)
457  this->fastAccessDx(i) = v*x.fastAccessDx(i);
458  }
459  }
460  else {
461  if (sz) {
462  for (int i=0; i<sz; ++i)
463  this->fastAccessDx(i) *= xval;
464  }
465  }
466 
467  this->val() *= xval;
468 
469  return *this;
470  }
471 
474  GeneralFad& operator /= (const GeneralFad& x) {
475  const int xsz = x.size(), sz = this->size();
476  T xval = x.val();
477  T v = this->val();
478 
479 #if defined(SACADO_DEBUG) && !defined(__CUDA_ARCH__ )
480  if ((xsz != sz) && (xsz != 0) && (sz != 0))
481  throw "Fad Error: Attempt to assign with incompatible sizes";
482 #endif
483 
484  if (xsz) {
485  if (sz) {
486  for(int i=0; i<sz; ++i)
487  this->fastAccessDx(i) =
488  ( this->fastAccessDx(i)*xval - v*x.fastAccessDx(i) )/ (xval*xval);
489  }
490  else {
491  this->resizeAndZero(xsz);
492  for(int i=0; i<xsz; ++i)
493  this->fastAccessDx(i) = - v*x.fastAccessDx(i) / (xval*xval);
494  }
495  }
496  else {
497  if (sz) {
498  for (int i=0; i<sz; ++i)
499  this->fastAccessDx(i) /= xval;
500  }
501  }
502 
503  this->val() /= xval;
504 
505  return *this;
506  }
507 
509  template <typename S>
511  SACADO_ENABLE_EXPR_FUNC(GeneralFad&) operator += (const Expr<S>& x) {
512  const int xsz = x.size(), sz = this->size();
513 
514 #if defined(SACADO_DEBUG) && !defined(__CUDA_ARCH__ )
515  if ((xsz != sz) && (xsz != 0) && (sz != 0))
516  throw "Fad Error: Attempt to assign with incompatible sizes";
517 #endif
518 
519  if (Expr<S>::is_linear) {
520  if (xsz) {
521  if (sz) {
522  if (x.hasFastAccess())
523  for (int i=0; i<sz; ++i)
524  this->fastAccessDx(i) += x.fastAccessDx(i);
525  else
526  for (int i=0; i<sz; ++i)
527  this->fastAccessDx(i) += x.dx(i);
528  }
529  else {
530  this->resizeAndZero(xsz);
531  if (x.hasFastAccess())
532  for (int i=0; i<xsz; ++i)
533  this->fastAccessDx(i) = x.fastAccessDx(i);
534  else
535  for (int i=0; i<xsz; ++i)
536  this->fastAccessDx(i) = x.dx(i);
537  }
538  }
539  }
540  else {
541 
542  if (xsz) {
543 
544  if (sz != xsz)
545  this->resizeAndZero(xsz);
546 
547  if (x.hasFastAccess()) {
548  // Compute partials
549  FastLocalAccumOp< Expr<S> > op(x);
550 
551  // Compute each tangent direction
552  for(op.i=0; op.i<xsz; ++op.i) {
553  op.t = T(0.);
554 
555  // Automatically unrolled loop that computes
556  // for (int j=0; j<N; j++)
557  // op.t += op.partials[j] * x.getTangent<j>(i);
559 
560  this->fastAccessDx(op.i) += op.t;
561  }
562  }
563  else {
564  // Compute partials
565  SlowLocalAccumOp< Expr<S> > op(x);
566 
567  // Compute each tangent direction
568  for(op.i=0; op.i<xsz; ++op.i) {
569  op.t = T(0.);
570 
571  // Automatically unrolled loop that computes
572  // for (int j=0; j<N; j++)
573  // op.t += op.partials[j] * x.getTangent<j>(i);
575 
576  this->fastAccessDx(op.i) += op.t;
577  }
578  }
579 
580  }
581 
582  }
583 
584  // Compute value
585  this->val() += x.val();
586 
587  return *this;
588  }
589 
591  template <typename S>
593  SACADO_ENABLE_EXPR_FUNC(GeneralFad&) operator -= (const Expr<S>& x) {
594  const int xsz = x.size(), sz = this->size();
595 
596 #if defined(SACADO_DEBUG) && !defined(__CUDA_ARCH__ )
597  if ((xsz != sz) && (xsz != 0) && (sz != 0))
598  throw "Fad Error: Attempt to assign with incompatible sizes";
599 #endif
600 
601  if (Expr<S>::is_linear) {
602  if (xsz) {
603  if (sz) {
604  if (x.hasFastAccess())
605  for(int i=0; i<sz; ++i)
606  this->fastAccessDx(i) -= x.fastAccessDx(i);
607  else
608  for (int i=0; i<sz; ++i)
609  this->fastAccessDx(i) -= x.dx(i);
610  }
611  else {
612  this->resizeAndZero(xsz);
613  if (x.hasFastAccess())
614  for(int i=0; i<xsz; ++i)
615  this->fastAccessDx(i) = -x.fastAccessDx(i);
616  else
617  for (int i=0; i<xsz; ++i)
618  this->fastAccessDx(i) = -x.dx(i);
619  }
620  }
621  }
622  else {
623 
624  if (xsz) {
625 
626  if (sz != xsz)
627  this->resizeAndZero(xsz);
628 
629  if (x.hasFastAccess()) {
630  // Compute partials
631  FastLocalAccumOp< Expr<S> > op(x);
632 
633  // Compute each tangent direction
634  for(op.i=0; op.i<xsz; ++op.i) {
635  op.t = T(0.);
636 
637  // Automatically unrolled loop that computes
638  // for (int j=0; j<N; j++)
639  // op.t += op.partials[j] * x.getTangent<j>(i);
641 
642  this->fastAccessDx(op.i) -= op.t;
643  }
644  }
645  else {
646  // Compute partials
647  SlowLocalAccumOp< Expr<S> > op(x);
648 
649  // Compute each tangent direction
650  for(op.i=0; op.i<xsz; ++op.i) {
651  op.t = T(0.);
652 
653  // Automatically unrolled loop that computes
654  // for (int j=0; j<N; j++)
655  // op.t += op.partials[j] * x.getTangent<j>(i);
657 
658  this->fastAccessDx(op.i) -= op.t;
659  }
660  }
661  }
662 
663  }
664 
665  this->val() -= x.val();
666 
667  return *this;
668  }
669 
671  template <typename S>
673  SACADO_ENABLE_EXPR_FUNC(GeneralFad&) operator *= (const Expr<S>& x) {
674  const int xsz = x.size(), sz = this->size();
675  T xval = x.val();
676  T v = this->val();
677 
678 #if defined(SACADO_DEBUG) && !defined(__CUDA_ARCH__ )
679  if ((xsz != sz) && (xsz != 0) && (sz != 0))
680  throw "Fad Error: Attempt to assign with incompatible sizes";
681 #endif
682 
683  if (Expr<S>::is_linear) {
684  if (xsz) {
685  if (sz) {
686  if (x.hasFastAccess())
687  for(int i=0; i<sz; ++i)
688  this->fastAccessDx(i) = v*x.fastAccessDx(i) + this->fastAccessDx(i)*xval;
689  else
690  for (int i=0; i<sz; ++i)
691  this->fastAccessDx(i) = v*x.dx(i) + this->fastAccessDx(i)*xval;
692  }
693  else {
694  this->resizeAndZero(xsz);
695  if (x.hasFastAccess())
696  for(int i=0; i<xsz; ++i)
697  this->fastAccessDx(i) = v*x.fastAccessDx(i);
698  else
699  for (int i=0; i<xsz; ++i)
700  this->fastAccessDx(i) = v*x.dx(i);
701  }
702  }
703  else {
704  if (sz) {
705  for (int i=0; i<sz; ++i)
706  this->fastAccessDx(i) *= xval;
707  }
708  }
709  }
710  else {
711 
712  if (xsz) {
713 
714  if (sz) {
715 
716  if (x.hasFastAccess()) {
717  // Compute partials
718  FastLocalAccumOp< Expr<S> > op(x);
719 
720  // Compute each tangent direction
721  for(op.i=0; op.i<xsz; ++op.i) {
722  op.t = T(0.);
723 
724  // Automatically unrolled loop that computes
725  // for (int j=0; j<N; j++)
726  // op.t += op.partials[j] * x.getTangent<j>(i);
728 
729  this->fastAccessDx(op.i) =
730  v * op.t + this->fastAccessDx(op.i) * xval;
731  }
732  }
733  else {
734  // Compute partials
735  SlowLocalAccumOp< Expr<S> > op(x);
736 
737  // Compute each tangent direction
738  for(op.i=0; op.i<xsz; ++op.i) {
739  op.t = T(0.);
740 
741  // Automatically unrolled loop that computes
742  // for (int j=0; j<N; j++)
743  // op.t += op.partials[j] * x.getTangent<j>(i);
745 
746  this->fastAccessDx(op.i) =
747  v * op.t + this->fastAccessDx(op.i) * xval;
748  }
749  }
750 
751  }
752 
753  else {
754 
755  this->resizeAndZero(xsz);
756 
757  if (x.hasFastAccess()) {
758  // Compute partials
759  FastLocalAccumOp< Expr<S> > op(x);
760 
761  // Compute each tangent direction
762  for(op.i=0; op.i<xsz; ++op.i) {
763  op.t = T(0.);
764 
765  // Automatically unrolled loop that computes
766  // for (int j=0; j<N; j++)
767  // op.t += op.partials[j] * x.getTangent<j>(i);
769 
770  this->fastAccessDx(op.i) = v * op.t;
771  }
772  }
773  else {
774  // Compute partials
775  SlowLocalAccumOp< Expr<S> > op(x);
776 
777  // Compute each tangent direction
778  for(op.i=0; op.i<xsz; ++op.i) {
779  op.t = T(0.);
780 
781  // Automatically unrolled loop that computes
782  // for (int j=0; j<N; j++)
783  // op.t += op.partials[j] * x.getTangent<j>(i);
785 
786  this->fastAccessDx(op.i) = v * op.t;
787  }
788  }
789 
790  }
791 
792  }
793 
794  else {
795 
796  if (sz) {
797  for (int i=0; i<sz; ++i)
798  this->fastAccessDx(i) *= xval;
799  }
800 
801  }
802 
803  }
804 
805  this->val() *= xval;
806 
807  return *this;
808  }
809 
811  template <typename S>
813  SACADO_ENABLE_EXPR_FUNC(GeneralFad&) operator /= (const Expr<S>& x) {
814  const int xsz = x.size(), sz = this->size();
815  T xval = x.val();
816  T v = this->val();
817 
818 #if defined(SACADO_DEBUG) && !defined(__CUDA_ARCH__ )
819  if ((xsz != sz) && (xsz != 0) && (sz != 0))
820  throw "Fad Error: Attempt to assign with incompatible sizes";
821 #endif
822 
823  if (Expr<S>::is_linear) {
824  if (xsz) {
825  if (sz) {
826  if (x.hasFastAccess())
827  for(int i=0; i<sz; ++i)
828  this->fastAccessDx(i) = ( this->fastAccessDx(i)*xval - v*x.fastAccessDx(i) )/ (xval*xval);
829  else
830  for (int i=0; i<sz; ++i)
831  this->fastAccessDx(i) = ( this->fastAccessDx(i)*xval - v*x.dx(i) )/ (xval*xval);
832  }
833  else {
834  this->resizeAndZero(xsz);
835  if (x.hasFastAccess())
836  for(int i=0; i<xsz; ++i)
837  this->fastAccessDx(i) = - v*x.fastAccessDx(i) / (xval*xval);
838  else
839  for (int i=0; i<xsz; ++i)
840  this->fastAccessDx(i) = -v*x.dx(i) / (xval*xval);
841  }
842  }
843  else {
844  if (sz) {
845  for (int i=0; i<sz; ++i)
846  this->fastAccessDx(i) /= xval;
847  }
848  }
849  }
850  else {
851 
852  if (xsz) {
853 
854  T xval2 = xval*xval;
855 
856  if (sz) {
857 
858  if (x.hasFastAccess()) {
859  // Compute partials
860  FastLocalAccumOp< Expr<S> > op(x);
861 
862  // Compute each tangent direction
863  for(op.i=0; op.i<xsz; ++op.i) {
864  op.t = T(0.);
865 
866  // Automatically unrolled loop that computes
867  // for (int j=0; j<N; j++)
868  // op.t += op.partials[j] * x.getTangent<j>(i);
870 
871  this->fastAccessDx(op.i) =
872  (this->fastAccessDx(op.i) * xval - v * op.t) / xval2;
873  }
874  }
875  else {
876  // Compute partials
877  SlowLocalAccumOp< Expr<S> > op(x);
878 
879  // Compute each tangent direction
880  for(op.i=0; op.i<xsz; ++op.i) {
881  op.t = T(0.);
882 
883  // Automatically unrolled loop that computes
884  // for (int j=0; j<N; j++)
885  // op.t += op.partials[j] * x.getTangent<j>(i);
887 
888  this->fastAccessDx(op.i) =
889  (this->fastAccessDx(op.i) * xval - v * op.t) / xval2;
890  }
891  }
892 
893  }
894 
895  else {
896 
897  this->resizeAndZero(xsz);
898 
899  if (x.hasFastAccess()) {
900  // Compute partials
901  FastLocalAccumOp< Expr<S> > op(x);
902 
903  // Compute each tangent direction
904  for(op.i=0; op.i<xsz; ++op.i) {
905  op.t = T(0.);
906 
907  // Automatically unrolled loop that computes
908  // for (int j=0; j<N; j++)
909  // op.t += op.partials[j] * x.getTangent<j>(i);
911 
912  this->fastAccessDx(op.i) = (-v * op.t) / xval2;
913  }
914  }
915  else {
916  // Compute partials
917  SlowLocalAccumOp< Expr<S> > op(x);
918 
919  // Compute each tangent direction
920  for(op.i=0; op.i<xsz; ++op.i) {
921  op.t = T(0.);
922 
923  // Automatically unrolled loop that computes
924  // for (int j=0; j<N; j++)
925  // op.t += op.partials[j] * x.getTangent<j>(i);
927 
928  this->fastAccessDx(op.i) = (-v * op.t) / xval2;
929  }
930  }
931 
932  }
933 
934  }
935 
936  else {
937 
938  if (sz) {
939  for (int i=0; i<sz; ++i)
940  this->fastAccessDx(i) /= xval;
941  }
942 
943  }
944 
945  }
946 
947  this->val() /= xval;
948 
949  return *this;
950  }
951 
953 
954  protected:
955 
956  // Functor for mpl::for_each to compute the local accumulation
957  // of a tangent derivative
958  //
959  // We use getTangent<>() to get dx components from expression
960  // arguments instead of getting the argument directly or extracting
961  // the dx array due to striding in ViewFad (or could use striding
962  // directly here if we need to get dx array).
963  template <typename ExprT>
964  struct FastLocalAccumOp {
965  typedef typename ExprT::value_type value_type;
966  static const int N = ExprT::num_args;
967  const ExprT& x;
968  mutable value_type t;
969  value_type partials[N];
970  int i;
972  FastLocalAccumOp(const ExprT& x_) : x(x_) {
973  x.computePartials(value_type(1.), partials);
974  }
975  template <typename ArgT>
977  void operator () (ArgT arg) const {
978  const int Arg = ArgT::value;
979  t += partials[Arg] * x.template getTangent<Arg>(i);
980  }
981  };
982 
983  template <typename ExprT>
984  struct SlowLocalAccumOp : FastLocalAccumOp<ExprT> {
986  SlowLocalAccumOp(const ExprT& x_) :
987  FastLocalAccumOp<ExprT>(x_) {}
988  template <typename ArgT>
990  void operator () (ArgT arg) const {
991  const int Arg = ArgT::value;
992  if (this->x.template isActive<Arg>())
993  this->t += this->partials[Arg] * this->x.template getTangent<Arg>(this->i);
994  }
995  };
996 
997  }; // class GeneralFad
998 
999 
1000  template <typename T, typename Storage>
1001  std::ostream& operator << (std::ostream& os,
1002  const GeneralFad<T,Storage>& x) {
1003  os << x.val() << " [";
1004 
1005  for (int i=0; i< x.size(); i++) {
1006  os << " " << x.dx(i);
1007  }
1008 
1009  os << " ]";
1010  return os;
1011  }
1012 
1013  } // namespace ELRFad
1014 
1015 } // namespace Sacado
1016 
1017 #endif // SACADO_ELRFAD_GENERALFAD_HPP
RemoveConst< T >::type value_type
Typename of values.
SACADO_INLINE_FUNCTION bool updateValue() const
Return whether this Fad object has an updated value.
void f()
SACADO_INLINE_FUNCTION SlowLocalAccumOp(const ExprT &x_)
expr expr dx(i)
SACADO_INLINE_FUNCTION ~GeneralFad()
Destructor.
SACADO_INLINE_FUNCTION GeneralFad(const Storage &s)
Constructor with supplied storage s.
#define SACADO_ENABLE_VALUE_CTOR_DECL
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(const Expr< S > &x, SACADO_ENABLE_EXPR_CTOR_DECL)
Copy constructor from any Expression object.
SACADO_INLINE_FUNCTION SACADO_ENABLE_EXPR_FUNC(bool) isEqualTo(const Expr< S > &x) const
Returns whether two Fad objects have the same values.
SACADO_INLINE_FUNCTION SACADO_ENABLE_VALUE_FUNC(GeneralFad &) operator
Assignment operator with constant right-hand-side.
expr val()
#define T
Definition: Sacado_rad.hpp:553
SACADO_INLINE_FUNCTION void setIsConstant(bool is_const)
Set whether variable is constant.
SACADO_INLINE_FUNCTION GeneralFad(const int sz, const int i, const T &x)
Constructor with size sz, index i, and value x.
SACADO_INLINE_FUNCTION GeneralFad(const GeneralFad &x)
Copy constructor.
Base template specification for testing equivalence.
static double x_
SACADO_INLINE_FUNCTION bool hasFastAccess() const
Returns true if derivative array is not empty.
Do not initialize the derivative array.
std::ostream & operator<<(std::ostream &os, const GeneralFad< T, Storage > &x)
const int N
SACADO_INLINE_FUNCTION bool isPassive() const
Returns true if derivative array is empty.
SACADO_INLINE_FUNCTION void diff(const int ith, const int n)
Set GeneralFad object as the ith independent variable.
SACADO_INLINE_FUNCTION void cache() const
Cache values.
DerivInit
Enum use to signal whether the derivative array should be initialized in AD object constructors...
Forward-mode AD class templated on the storage for the derivative array.
int value
Wrapper for a generic expression template.
expr expr expr fastAccessDx(i)) FAD_UNARYOP_MACRO(exp
SACADO_INLINE_FUNCTION GeneralFad(const S &x, SACADO_ENABLE_VALUE_CTOR_DECL)
Constructor with supplied value x.
Initialize the derivative array.
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 int availableSize() const
Returns number of derivative components that can be stored without reallocation.
#define SACADO_INLINE_FUNCTION
SACADO_INLINE_FUNCTION GeneralFad()
Default constructor.
ScalarType< value_type >::type scalar_type
Typename of scalar&#39;s (which may be different from T)
SACADO_INLINE_FUNCTION void operator()(ArgT arg) const