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_Ops.hpp
Go to the documentation of this file.
1 // @HEADER
2 // ***********************************************************************
3 //
4 // Sacado Package
5 // Copyright (2006) Sandia Corporation
6 //
7 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
8 // the U.S. Government retains certain rights in this software.
9 //
10 // This library is free software; you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as
12 // published by the Free Software Foundation; either version 2.1 of the
13 // License, or (at your option) any later version.
14 //
15 // This library is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 // Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public
21 // License along with this library; if not, write to the Free Software
22 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
23 // USA
24 // Questions? Contact David M. Gay (dmgay@sandia.gov) or Eric T. Phipps
25 // (etphipp@sandia.gov).
26 //
27 // ***********************************************************************
28 //
29 // The forward-mode AD classes in Sacado are a derivative work of the
30 // expression template classes in the Fad package by Nicolas Di Cesare.
31 // The following banner is included in the original Fad source code:
32 //
33 // ************ DO NOT REMOVE THIS BANNER ****************
34 //
35 // Nicolas Di Cesare <Nicolas.Dicesare@ann.jussieu.fr>
36 // http://www.ann.jussieu.fr/~dicesare
37 //
38 // CEMRACS 98 : C++ courses,
39 // templates : new C++ techniques
40 // for scientific computing
41 //
42 //********************************************************
43 //
44 // A short implementation ( not all operators and
45 // functions are overloaded ) of 1st order Automatic
46 // Differentiation in forward mode (FAD) using
47 // EXPRESSION TEMPLATES.
48 //
49 //********************************************************
50 // @HEADER
51 
52 #ifndef SACADO_ELRCACHEFAD_OPS_HPP
53 #define SACADO_ELRCACHEFAD_OPS_HPP
54 
56 #include "Sacado_cmath.hpp"
58 #include "Sacado_mpl_is_same.hpp"
59 #include <ostream> // for std::ostream
60 
61 namespace Sacado {
62  namespace ELRCacheFad {
63 
64  //
65  // UnaryPlusOp
66  //
67 
68  template <typename ExprT>
69  class UnaryPlusOp {};
70 
71  template <typename ExprT>
72  class Expr< UnaryPlusOp<ExprT> > {
73  public:
74 
75  typedef typename ExprT::value_type value_type;
76  typedef typename ExprT::scalar_type scalar_type;
77 
78  typedef typename ExprT::base_expr_type base_expr_type;
79 
80  static const int num_args = ExprT::num_args;
81 
82  static const bool is_linear = true;
83 
85  Expr(const ExprT& expr_) : expr(expr_) {}
86 
88  int size() const { return expr.size(); }
89 
90  template <int Arg>
92  bool isActive() const { return expr.template isActive<Arg>(); }
93 
95  bool updateValue() const { return expr.updateValue(); }
96 
98  void cache() const {
99  expr.cache();
100  }
101 
103  value_type val() const {
104  return expr.val();
105  }
106 
109  value_type partials[]) const {
110  expr.computePartials(bar, partials);
111  }
112 
114  void getTangents(int i, value_type dots[]) const {
115  expr.getTangents(i, dots); }
116 
117  template <int Arg>
118  value_type getTangent(int i) const {
119  return expr.template getTangent<Arg>(i);
120  }
121 
123  bool isLinear() const {
124  return expr.isLinear();
125  }
126 
128  bool hasFastAccess() const {
129  return expr.hasFastAccess();
130  }
131 
133  const value_type dx(int i) const {
134  return expr.dx(i);
135  }
136 
138  const value_type fastAccessDx(int i) const {
139  return expr.fastAccessDx(i);
140  }
141 
143  const value_type* getDx(int j) const {
144  return expr.getDx(j);
145  }
146 
147  protected:
148 
149  const ExprT& expr;
150  };
151 
152  template <typename T>
155  operator+ (const Expr<T>& expr)
156  {
157  typedef UnaryPlusOp< Expr<T> > expr_t;
158 
159  return Expr<expr_t>(expr);
160  }
161 
162  //
163  // UnaryMinusOp
164  //
165  template <typename ExprT>
166  class UnaryMinusOp {};
167 
168  template <typename ExprT>
169  class Expr< UnaryMinusOp<ExprT> > {
170  public:
171 
172  typedef typename ExprT::value_type value_type;
173  typedef typename ExprT::scalar_type scalar_type;
174 
175  typedef typename ExprT::base_expr_type base_expr_type;
176 
177  static const int num_args = ExprT::num_args;
178 
179  static const bool is_linear = true;
180 
182  Expr(const ExprT& expr_) : expr(expr_) {}
183 
185  int size() const { return expr.size(); }
186 
187  template <int Arg>
189  bool isActive() const { return expr.template isActive<Arg>(); }
190 
192  bool updateValue() const { return expr.updateValue(); }
193 
195  void cache() const {
196  expr.cache();
197  }
198 
200  value_type val() const {
201  return -expr.val();
202  }
203 
206  value_type partials[]) const {
207  expr.computePartials(-bar, partials);
208  }
209 
211  void getTangents(int i, value_type dots[]) const {
212  expr.getTangents(i, dots); }
213 
214  template <int Arg>
216  value_type getTangent(int i) const {
217  return expr.template getTangent<Arg>(i);
218  }
219 
221  bool isLinear() const {
222  return expr.isLinear();
223  }
224 
226  bool hasFastAccess() const {
227  return expr.hasFastAccess();
228  }
229 
231  const value_type dx(int i) const {
232  return -expr.dx(i);
233  }
234 
236  const value_type fastAccessDx(int i) const {
237  return -expr.fastAccessDx(i);
238  }
239 
241  const value_type* getDx(int j) const {
242  return expr.getDx(j);
243  }
244 
245  protected:
246 
247  const ExprT& expr;
248  };
249 
250  template <typename T>
253  operator- (const Expr<T>& expr)
254  {
255  typedef UnaryMinusOp< Expr<T> > expr_t;
256 
257  return Expr<expr_t>(expr);
258  }
259 
260  //
261  // AbsOp
262  //
263 
264  template <typename ExprT>
265  class AbsOp {};
266 
267  template <typename ExprT>
268  class Expr< AbsOp<ExprT> > {
269  public:
270 
271  typedef typename ExprT::value_type value_type;
272  typedef typename ExprT::scalar_type scalar_type;
273 
274  typedef typename ExprT::base_expr_type base_expr_type;
275 
276  static const int num_args = ExprT::num_args;
277 
278  static const bool is_linear = false;
279 
281  Expr(const ExprT& expr_) : expr(expr_) {}
282 
284  int size() const { return expr.size(); }
285 
286  template <int Arg>
288  bool isActive() const { return expr.template isActive<Arg>(); }
289 
291  bool updateValue() const { return expr.updateValue(); }
292 
294  void cache() const {
295  expr.cache();
296  v = expr.val();
297  v_pos = (v >= 0);
298  }
299 
301  value_type val() const {
302  return std::abs(v);
303  }
304 
307  value_type partials[]) const {
308  if (v_pos)
309  expr.computePartials(bar, partials);
310  else
311  expr.computePartials(-bar, partials);
312  }
313 
315  void getTangents(int i, value_type dots[]) const {
316  expr.getTangents(i, dots); }
317 
318  template <int Arg>
320  value_type getTangent(int i) const {
321  return expr.template getTangent<Arg>(i);
322  }
323 
325  bool isLinear() const {
326  return false;
327  }
328 
330  bool hasFastAccess() const {
331  return expr.hasFastAccess();
332  }
333 
335  const value_type dx(int i) const {
336  if (v_pos) return expr.dx(i);
337  else return -expr.dx(i);
338  }
339 
341  const value_type fastAccessDx(int i) const {
342  if (v_pos) return expr.fastAccessDx(i);
343  else return -expr.fastAccessDx(i);
344  }
345 
347  const value_type* getDx(int j) const {
348  return expr.getDx(j);
349  }
350 
351  protected:
352 
353  const ExprT& expr;
354  mutable value_type v;
355  mutable bool v_pos;
356  };
357 
358  template <typename T>
361  abs (const Expr<T>& expr)
362  {
363  typedef AbsOp< Expr<T> > expr_t;
364 
365  return Expr<expr_t>(expr);
366  }
367 
368  //
369  // FAbsOp
370  //
371 
372  template <typename ExprT>
373  class FAbsOp {};
374 
375  template <typename ExprT>
376  class Expr< FAbsOp<ExprT> > {
377  public:
378 
379  typedef typename ExprT::value_type value_type;
380  typedef typename ExprT::scalar_type scalar_type;
381 
382  typedef typename ExprT::base_expr_type base_expr_type;
383 
384  static const int num_args = ExprT::num_args;
385 
386  static const bool is_linear = false;
387 
389  Expr(const ExprT& expr_) : expr(expr_) {}
390 
392  int size() const { return expr.size(); }
393 
394  template <int Arg>
396  bool isActive() const { return expr.template isActive<Arg>(); }
397 
399  bool updateValue() const { return expr.updateValue(); }
400 
402  void cache() const {
403  expr.cache();
404  v = expr.val();
405  v_pos = (v >= 0);
406  }
407 
409  value_type val() const {
410  return std::fabs(v);
411  }
412 
415  value_type partials[]) const {
416  if (v_pos)
417  expr.computePartials(bar, partials);
418  else
419  expr.computePartials(-bar, partials);
420  }
421 
423  void getTangents(int i, value_type dots[]) const {
424  expr.getTangents(i, dots); }
425 
426  template <int Arg>
428  value_type getTangent(int i) const {
429  return expr.template getTangent<Arg>(i);
430  }
431 
433  bool isLinear() const {
434  return false;
435  }
436 
438  bool hasFastAccess() const {
439  return expr.hasFastAccess();
440  }
441 
443  const value_type dx(int i) const {
444  if (v_pos) return expr.dx(i);
445  else return -expr.dx(i);
446  }
447 
449  const value_type fastAccessDx(int i) const {
450  if (v_pos) return expr.fastAccessDx(i);
451  else return -expr.fastAccessDx(i);
452  }
453 
455  const value_type* getDx(int j) const {
456  return expr.getDx(j);
457  }
458 
459  protected:
460 
461  const ExprT& expr;
462  mutable value_type v;
463  mutable bool v_pos;
464  };
465 
466  template <typename T>
469  fabs (const Expr<T>& expr)
470  {
471  typedef FAbsOp< Expr<T> > expr_t;
472 
473  return Expr<expr_t>(expr);
474  }
475 
476  }
477 }
478 
479 #define FAD_UNARYOP_MACRO(OPNAME,OP,PARTIAL,VALUE) \
480 namespace Sacado { \
481  namespace ELRCacheFad { \
482  \
483  template <typename ExprT> \
484  class OP {}; \
485  \
486  template <typename ExprT> \
487  class Expr< OP<ExprT> > { \
488  public: \
489  \
490  typedef typename ExprT::value_type value_type; \
491  typedef typename ExprT::scalar_type scalar_type; \
492  \
493  typedef typename ExprT::base_expr_type base_expr_type; \
494  \
495  static const int num_args = ExprT::num_args; \
496  \
497  static const bool is_linear = false; \
498  \
499  KOKKOS_INLINE_FUNCTION \
500  Expr(const ExprT& expr_) : expr(expr_) {} \
501  \
502  KOKKOS_INLINE_FUNCTION \
503  int size() const { return expr.size(); } \
504  \
505  template <int Arg> \
506  KOKKOS_INLINE_FUNCTION \
507  bool isActive() const { return expr.template isActive<Arg>(); } \
508  \
509  KOKKOS_INLINE_FUNCTION \
510  bool updateValue() const { return expr.updateValue(); } \
511  \
512  KOKKOS_INLINE_FUNCTION \
513  void cache() const { \
514  expr.cache(); \
515  v = expr.val(); \
516  PARTIAL; \
517  } \
518  \
519  KOKKOS_INLINE_FUNCTION \
520  value_type val() const { \
521  return VALUE; \
522  } \
523  \
524  KOKKOS_INLINE_FUNCTION \
525  void computePartials(const value_type& bar, \
526  value_type partials[]) const { \
527  expr.computePartials(bar*a, partials); \
528  } \
529  \
530  KOKKOS_INLINE_FUNCTION \
531  void getTangents(int i, value_type dots[]) const { \
532  expr.getTangents(i, dots); } \
533  \
534  template <int Arg> \
535  KOKKOS_INLINE_FUNCTION \
536  value_type getTangent(int i) const { \
537  return expr.template getTangent<Arg>(i); \
538  } \
539  \
540  KOKKOS_INLINE_FUNCTION \
541  bool isLinear() const { \
542  return false; \
543  } \
544  \
545  KOKKOS_INLINE_FUNCTION \
546  bool hasFastAccess() const { \
547  return expr.hasFastAccess(); \
548  } \
549  \
550  KOKKOS_INLINE_FUNCTION \
551  const value_type dx(int i) const { \
552  return expr.dx(i)*a; \
553  } \
554  \
555  KOKKOS_INLINE_FUNCTION \
556  const value_type fastAccessDx(int i) const { \
557  return expr.fastAccessDx(i)*a; \
558  } \
559  \
560  KOKKOS_INLINE_FUNCTION \
561  const value_type* getDx(int j) const { \
562  return expr.getDx(j); \
563  } \
564  \
565  protected: \
566  \
567  const ExprT& expr; \
568  mutable value_type v; \
569  mutable value_type a; \
570  }; \
571  \
572  template <typename T> \
573  KOKKOS_INLINE_FUNCTION \
574  Expr< OP< Expr<T> > > \
575  OPNAME (const Expr<T>& expr) \
576  { \
577  typedef OP< Expr<T> > expr_t; \
578  \
579  return Expr<expr_t>(expr); \
580  } \
581  } \
582 }
583 
585  ExpOp,
586  a = std::exp(v),
587  a)
590  a=scalar_type(1.0)/v,
591  std::log(v))
594  a = scalar_type(1.0)/(std::log(scalar_type(10.0))*v),
595  std::log10(v))
598  a = scalar_type(1.0)/(scalar_type(2.0)*std::sqrt(v)),
599  std::sqrt(v))
602  a = -std::sin(v),
603  std::cos(v))
606  a = std::cos(v),
607  std::sin(v))
610  a = scalar_type(1.0)+std::tan(v)*std::tan(v),
611  std::tan(v))
614  a = scalar_type(-1.0)/std::sqrt(scalar_type(1.0)-v*v),
615  std::acos(v))
618  a = scalar_type(1.0)/std::sqrt(scalar_type(1.0)-v*v),
619  std::asin(v))
622  a = scalar_type(1.0)/(scalar_type(1.0)+v*v),
623  std::atan(v))
626  a = std::sinh(v),
627  std::cosh(v))
630  a = std::cosh(v),
631  std::sinh(v))
634  a = scalar_type(1.0)/(std::cosh(v)*std::cosh(v)),
635  std::tanh(v))
638  a = scalar_type(1.0)/std::sqrt((v-scalar_type(1.0))*(v+scalar_type(1.0))),
639  std::acosh(v))
642  a = scalar_type(1.0)/std::sqrt(scalar_type(1.0)+v*v),
643  std::asinh(v))
646  a = scalar_type(1.0)/(scalar_type(1.0)-v*v),
647  std::atanh(v))
648 #ifdef HAVE_SACADO_CXX11
650  CbrtOp,
651  a = scalar_type(1.0)/(scalar_type(3.0)*std::cbrt(v*v)),
652  std::cbrt(v))
653 #endif
654 
655 #undef FAD_UNARYOP_MACRO
656 
657 //
658 // Binary operators
659 //
660 namespace Sacado {
661  namespace ELRCacheFad {
662 
663  //
664  // AdditionOp
665  //
666 
667  template <typename ExprT1, typename ExprT2>
668  class AdditionOp {};
669 
670  template <typename ExprT1, typename ExprT2>
671  class Expr< AdditionOp<ExprT1,ExprT2> > {
672 
673  public:
674 
675  typedef typename ExprT1::value_type value_type_1;
676  typedef typename ExprT2::value_type value_type_2;
677  typedef typename Sacado::Promote<value_type_1,
678  value_type_2>::type value_type;
679  typedef typename ExprT1::scalar_type scalar_type_1;
680  typedef typename ExprT2::scalar_type scalar_type_2;
681  typedef typename Sacado::Promote<scalar_type_1,
682  scalar_type_2>::type scalar_type;
683 
684  typedef typename ExprT1::base_expr_type base_expr_type_1;
685  typedef typename ExprT2::base_expr_type base_expr_type_2;
686  typedef typename Sacado::Promote<base_expr_type_1,
687  base_expr_type_2>::type base_expr_type;
688 
689  static const int num_args1 = ExprT1::num_args;
690  static const int num_args2 = ExprT2::num_args;
691  static const int num_args = num_args1 + num_args2;
692 
693  static const bool is_linear = ExprT1::is_linear && ExprT2::is_linear;
694 
696  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
697  expr1(expr1_), expr2(expr2_) {}
698 
700  int size() const {
701  int sz1 = expr1.size(), sz2 = expr2.size();
702  return sz1 > sz2 ? sz1 : sz2;
703  }
704 
705  template <int Arg>
707  bool isActive() const {
708  if (Arg < num_args1)
709  return expr1.template isActive<Arg>();
710  else
711  return expr2.template isActive<Arg-num_args1>();
712  }
713 
715  bool updateValue() const {
716  return expr1.updateValue() && expr2.updateValue();
717  }
718 
720  void cache() const {
721  expr1.cache();
722  expr2.cache();
723  }
724 
726  value_type val() const {
727  return expr1.val()+expr2.val();
728  }
729 
731  void computePartials(const value_type& bar,
732  value_type partials[]) const {
733  if (num_args1 > 0)
734  expr1.computePartials(bar, partials);
735  if (num_args2 > 0)
736  expr2.computePartials(bar, partials+num_args1);
737  }
738 
740  void getTangents(int i, value_type dots[]) const {
741  expr1.getTangents(i, dots);
742  expr2.getTangents(i, dots+num_args1);
743  }
744 
745  template <int Arg>
747  value_type getTangent(int i) const {
748  if (Arg < num_args1)
749  return expr1.template getTangent<Arg>(i);
750  else
751  return expr2.template getTangent<Arg-num_args1>(i);
752  }
753 
755  bool isLinear() const {
756  return expr1.isLinear() && expr2.isLinear();
757  }
758 
760  bool hasFastAccess() const {
761  return expr1.hasFastAccess() && expr2.hasFastAccess();
762  }
763 
765  const value_type dx(int i) const {
766  return expr1.dx(i) + expr2.dx(i);
767  }
768 
770  const value_type fastAccessDx(int i) const {
771  return expr1.fastAccessDx(i) + expr2.fastAccessDx(i);
772  }
773 
775  const value_type* getDx(int j) const {
776  if (j < num_args1)
777  return expr1.getDx(j);
778  else
779  return expr2.getDx(j-num_args1);
780  }
781 
782  protected:
783 
784  const ExprT1& expr1;
785  const ExprT2& expr2;
786 
787  };
788 
789  template <typename ExprT1, typename T2>
790  class Expr< AdditionOp<ExprT1, ConstExpr<T2> > > {
791 
792  public:
793 
794  typedef ConstExpr<T2> ExprT2;
795  typedef typename ExprT1::value_type value_type_1;
796  typedef typename ExprT2::value_type value_type_2;
797  typedef typename Sacado::Promote<value_type_1,
798  value_type_2>::type value_type;
799  typedef typename ExprT1::scalar_type scalar_type_1;
800  typedef typename ExprT2::scalar_type scalar_type_2;
801  typedef typename Sacado::Promote<scalar_type_1,
802  scalar_type_2>::type scalar_type;
803 
804  typedef typename ExprT1::base_expr_type base_expr_type_1;
805  typedef typename ExprT2::base_expr_type base_expr_type_2;
806  typedef typename Sacado::Promote<base_expr_type_1,
807  base_expr_type_2>::type base_expr_type;
808 
809  static const int num_args = ExprT1::num_args;
810 
811  static const bool is_linear = ExprT1::is_linear;
812 
814  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
815  expr1(expr1_), expr2(expr2_) {}
816 
818  int size() const {
819  return expr1.size();
820  }
821 
822  template <int Arg>
824  bool isActive() const {
825  return expr1.template isActive<Arg>();
826  }
827 
829  bool updateValue() const {
830  return expr1.updateValue();
831  }
832 
834  void cache() const {
835  expr1.cache();
836  }
837 
839  value_type val() const {
840  return expr1.val() + expr2.val();
841  }
842 
844  void computePartials(const value_type& bar,
845  value_type partials[]) const {
846  expr1.computePartials(bar, partials);
847  }
848 
850  void getTangents(int i, value_type dots[]) const {
851  expr1.getTangents(i, dots);
852  }
853 
854  template <int Arg>
856  value_type getTangent(int i) const {
857  return expr1.template getTangent<Arg>(i);
858  }
859 
861  bool isLinear() const {
862  return expr1.isLinear();
863  }
864 
866  bool hasFastAccess() const {
867  return expr1.hasFastAccess();
868  }
869 
871  const value_type dx(int i) const {
872  return expr1.dx(i);
873  }
874 
876  const value_type fastAccessDx(int i) const {
877  return expr1.fastAccessDx(i);
878  }
879 
881  const value_type* getDx(int j) const {
882  return expr1.getDx(j);
883  }
884 
885  protected:
886 
887  const ExprT1& expr1;
888  ExprT2 expr2;
889 
890  };
891 
892  template <typename T1, typename ExprT2>
893  class Expr< AdditionOp< ConstExpr<T1>,ExprT2> > {
894 
895  public:
896 
897  typedef ConstExpr<T1> ExprT1;
898  typedef typename ExprT1::value_type value_type_1;
899  typedef typename ExprT2::value_type value_type_2;
900  typedef typename Sacado::Promote<value_type_1,
901  value_type_2>::type value_type;
902  typedef typename ExprT1::scalar_type scalar_type_1;
903  typedef typename ExprT2::scalar_type scalar_type_2;
904  typedef typename Sacado::Promote<scalar_type_1,
905  scalar_type_2>::type scalar_type;
906 
907  typedef typename ExprT1::base_expr_type base_expr_type_1;
908  typedef typename ExprT2::base_expr_type base_expr_type_2;
909  typedef typename Sacado::Promote<base_expr_type_1,
910  base_expr_type_2>::type base_expr_type;
911 
912  static const int num_args = ExprT2::num_args;
913 
914  static const bool is_linear = ExprT2::is_linear;
915 
917  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
918  expr1(expr1_), expr2(expr2_) {}
919 
921  int size() const {
922  return expr2.size();
923  }
924 
925  template <int Arg>
927  bool isActive() const {
928  return expr2.template isActive<Arg>();
929  }
930 
932  bool updateValue() const {
933  return expr2.updateValue();
934  }
935 
937  void cache() const {
938  expr2.cache();
939  }
940 
942  value_type val() const {
943  return expr1.val() + expr2.val();
944  }
945 
947  void computePartials(const value_type& bar,
948  value_type partials[]) const {
949  expr2.computePartials(bar, partials);
950  }
951 
953  void getTangents(int i, value_type dots[]) const {
954  expr2.getTangents(i, dots);
955  }
956 
957  template <int Arg>
959  value_type getTangent(int i) const {
960  return expr2.template getTangent<Arg>(i);
961  }
962 
964  bool isLinear() const {
965  return expr2.isLinear();
966  }
967 
969  bool hasFastAccess() const {
970  return expr2.hasFastAccess();
971  }
972 
974  const value_type dx(int i) const {
975  return expr2.dx(i);
976  }
977 
979  const value_type fastAccessDx(int i) const {
980  return expr2.fastAccessDx(i);
981  }
982 
984  const value_type* getDx(int j) const {
985  return expr2.getDx(j);
986  }
987 
988  protected:
989 
990  ExprT1 expr1;
991  const ExprT2& expr2;
992 
993  };
994 
995  //
996  // SubtractionOp
997  //
998 
999  template <typename ExprT1, typename ExprT2>
1000  class SubtractionOp {};
1001 
1002  template <typename ExprT1, typename ExprT2>
1003  class Expr< SubtractionOp<ExprT1,ExprT2> > {
1004 
1005  public:
1006 
1007  typedef typename ExprT1::value_type value_type_1;
1008  typedef typename ExprT2::value_type value_type_2;
1009  typedef typename Sacado::Promote<value_type_1,
1010  value_type_2>::type value_type;
1011  typedef typename ExprT1::scalar_type scalar_type_1;
1012  typedef typename ExprT2::scalar_type scalar_type_2;
1013  typedef typename Sacado::Promote<scalar_type_1,
1014  scalar_type_2>::type scalar_type;
1015 
1016  typedef typename ExprT1::base_expr_type base_expr_type_1;
1017  typedef typename ExprT2::base_expr_type base_expr_type_2;
1018  typedef typename Sacado::Promote<base_expr_type_1,
1019  base_expr_type_2>::type base_expr_type;
1020 
1021  static const int num_args1 = ExprT1::num_args;
1022  static const int num_args2 = ExprT2::num_args;
1023  static const int num_args = num_args1 + num_args2;
1024 
1025  static const bool is_linear = ExprT1::is_linear && ExprT2::is_linear;
1026 
1028  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
1029  expr1(expr1_), expr2(expr2_) {}
1030 
1032  int size() const {
1033  int sz1 = expr1.size(), sz2 = expr2.size();
1034  return sz1 > sz2 ? sz1 : sz2;
1035  }
1036 
1037  template <int Arg>
1039  bool isActive() const {
1040  if (Arg < num_args1)
1041  return expr1.template isActive<Arg>();
1042  else
1043  return expr2.template isActive<Arg-num_args1>();
1044  }
1045 
1047  bool updateValue() const {
1048  return expr1.updateValue() && expr2.updateValue();
1049  }
1050 
1052  void cache() const {
1053  expr1.cache();
1054  expr2.cache();
1055  }
1056 
1058  value_type val() const {
1059  return expr1.val()-expr2.val();
1060  }
1061 
1063  void computePartials(const value_type& bar,
1064  value_type partials[]) const {
1065  if (num_args1 > 0)
1066  expr1.computePartials(bar, partials);
1067  if (num_args2 > 0)
1068  expr2.computePartials(-bar, partials+num_args1);
1069  }
1070 
1072  void getTangents(int i, value_type dots[]) const {
1073  expr1.getTangents(i, dots);
1074  expr2.getTangents(i, dots+num_args1);
1075  }
1076 
1077  template <int Arg>
1079  value_type getTangent(int i) const {
1080  if (Arg < num_args1)
1081  return expr1.template getTangent<Arg>(i);
1082  else
1083  return expr2.template getTangent<Arg-num_args1>(i);
1084  }
1085 
1087  bool isLinear() const {
1088  return expr1.isLinear() && expr2.isLinear();
1089  }
1090 
1092  bool hasFastAccess() const {
1093  return expr1.hasFastAccess() && expr2.hasFastAccess();
1094  }
1095 
1097  const value_type dx(int i) const {
1098  return expr1.dx(i) - expr2.dx(i);
1099  }
1100 
1102  const value_type fastAccessDx(int i) const {
1103  return expr1.fastAccessDx(i) - expr2.fastAccessDx(i);
1104  }
1105 
1107  const value_type* getDx(int j) const {
1108  if (j < num_args1)
1109  return expr1.getDx(j);
1110  else
1111  return expr2.getDx(j-num_args1);
1112  }
1113 
1114  protected:
1115 
1116  const ExprT1& expr1;
1117  const ExprT2& expr2;
1118 
1119  };
1120 
1121  template <typename ExprT1, typename T2>
1122  class Expr< SubtractionOp<ExprT1, ConstExpr<T2> > > {
1123 
1124  public:
1125 
1126  typedef ConstExpr<T2> ExprT2;
1127  typedef typename ExprT1::value_type value_type_1;
1128  typedef typename ExprT2::value_type value_type_2;
1129  typedef typename Sacado::Promote<value_type_1,
1130  value_type_2>::type value_type;
1131  typedef typename ExprT1::scalar_type scalar_type_1;
1132  typedef typename ExprT2::scalar_type scalar_type_2;
1133  typedef typename Sacado::Promote<scalar_type_1,
1134  scalar_type_2>::type scalar_type;
1135 
1136  typedef typename ExprT1::base_expr_type base_expr_type_1;
1137  typedef typename ExprT2::base_expr_type base_expr_type_2;
1138  typedef typename Sacado::Promote<base_expr_type_1,
1139  base_expr_type_2>::type base_expr_type;
1140 
1141  static const int num_args = ExprT1::num_args;
1142 
1143  static const bool is_linear = ExprT1::is_linear;
1144 
1146  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
1147  expr1(expr1_), expr2(expr2_) {}
1148 
1150  int size() const {
1151  return expr1.size();
1152  }
1153 
1154  template <int Arg>
1156  bool isActive() const {
1157  return expr1.template isActive<Arg>();
1158  }
1159 
1161  bool updateValue() const {
1162  return expr1.updateValue();
1163  }
1164 
1166  void cache() const {
1167  expr1.cache();
1168  }
1169 
1171  value_type val() const {
1172  return expr1.val() - expr2.val();
1173  }
1174 
1176  void computePartials(const value_type& bar,
1177  value_type partials[]) const {
1178  expr1.computePartials(bar, partials);
1179  }
1180 
1182  void getTangents(int i, value_type dots[]) const {
1183  expr1.getTangents(i, dots);
1184  }
1185 
1186  template <int Arg>
1188  value_type getTangent(int i) const {
1189  return expr1.template getTangent<Arg>(i);
1190  }
1191 
1193  bool isLinear() const {
1194  return expr1.isLinear();
1195  }
1196 
1198  bool hasFastAccess() const {
1199  return expr1.hasFastAccess();
1200  }
1201 
1203  const value_type dx(int i) const {
1204  return expr1.dx(i);
1205  }
1206 
1208  const value_type fastAccessDx(int i) const {
1209  return expr1.fastAccessDx(i);
1210  }
1211 
1213  const value_type* getDx(int j) const {
1214  return expr1.getDx(j);
1215  }
1216 
1217  protected:
1218 
1219  const ExprT1& expr1;
1220  ExprT2 expr2;
1221 
1222  };
1223 
1224  template <typename T1, typename ExprT2>
1225  class Expr< SubtractionOp< ConstExpr<T1>,ExprT2> > {
1226 
1227  public:
1228 
1229  typedef ConstExpr<T1> ExprT1;
1230  typedef typename ExprT1::value_type value_type_1;
1231  typedef typename ExprT2::value_type value_type_2;
1232  typedef typename Sacado::Promote<value_type_1,
1233  value_type_2>::type value_type;
1234  typedef typename ExprT1::scalar_type scalar_type_1;
1235  typedef typename ExprT2::scalar_type scalar_type_2;
1236  typedef typename Sacado::Promote<scalar_type_1,
1237  scalar_type_2>::type scalar_type;
1238 
1239  typedef typename ExprT1::base_expr_type base_expr_type_1;
1240  typedef typename ExprT2::base_expr_type base_expr_type_2;
1241  typedef typename Sacado::Promote<base_expr_type_1,
1242  base_expr_type_2>::type base_expr_type;
1243 
1244  static const int num_args = ExprT2::num_args;
1245 
1246  static const bool is_linear = ExprT2::is_linear;
1247 
1249  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
1250  expr1(expr1_), expr2(expr2_) {}
1251 
1253  int size() const {
1254  return expr2.size();
1255  }
1256 
1257  template <int Arg>
1259  bool isActive() const {
1260  return expr2.template isActive<Arg>();
1261  }
1262 
1264  bool updateValue() const {
1265  return expr2.updateValue();
1266  }
1267 
1269  void cache() const {
1270  expr2.cache();
1271  }
1272 
1274  value_type val() const {
1275  return expr1.val() - expr2.val();
1276  }
1277 
1279  void computePartials(const value_type& bar,
1280  value_type partials[]) const {
1281  expr2.computePartials(-bar, partials);
1282  }
1283 
1285  void getTangents(int i, value_type dots[]) const {
1286  expr2.getTangents(i, dots);
1287  }
1288 
1289  template <int Arg>
1291  value_type getTangent(int i) const {
1292  return expr2.template getTangent<Arg>(i);
1293  }
1294 
1296  bool isLinear() const {
1297  return expr2.isLinear();
1298  }
1299 
1301  bool hasFastAccess() const {
1302  return expr2.hasFastAccess();
1303  }
1304 
1306  const value_type dx(int i) const {
1307  return -expr2.dx(i);
1308  }
1309 
1311  const value_type fastAccessDx(int i) const {
1312  return -expr2.fastAccessDx(i);
1313  }
1314 
1316  const value_type* getDx(int j) const {
1317  return expr2.getDx(j);
1318  }
1319 
1320  protected:
1321 
1322  ExprT1 expr1;
1323  const ExprT2& expr2;
1324 
1325  };
1326 
1327  //
1328  // MultiplicationOp
1329  //
1330 
1331  template <typename ExprT1, typename ExprT2>
1332  class MultiplicationOp {};
1333 
1334  template <typename ExprT1, typename ExprT2>
1335  class Expr< MultiplicationOp<ExprT1,ExprT2> > {
1336 
1337  public:
1338 
1339  typedef typename ExprT1::value_type value_type_1;
1340  typedef typename ExprT2::value_type value_type_2;
1341  typedef typename Sacado::Promote<value_type_1,
1342  value_type_2>::type value_type;
1343  typedef typename ExprT1::scalar_type scalar_type_1;
1344  typedef typename ExprT2::scalar_type scalar_type_2;
1345  typedef typename Sacado::Promote<scalar_type_1,
1346  scalar_type_2>::type scalar_type;
1347 
1348  typedef typename ExprT1::base_expr_type base_expr_type_1;
1349  typedef typename ExprT2::base_expr_type base_expr_type_2;
1350  typedef typename Sacado::Promote<base_expr_type_1,
1351  base_expr_type_2>::type base_expr_type;
1352 
1353  static const int num_args1 = ExprT1::num_args;
1354  static const int num_args2 = ExprT2::num_args;
1355  static const int num_args = num_args1 + num_args2;
1356 
1357  static const bool is_linear = false;
1358 
1360  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
1361  expr1(expr1_), expr2(expr2_) {}
1362 
1364  int size() const {
1365  int sz1 = expr1.size(), sz2 = expr2.size();
1366  return sz1 > sz2 ? sz1 : sz2;
1367  }
1368 
1369  template <int Arg>
1371  bool isActive() const {
1372  if (Arg < num_args1)
1373  return expr1.template isActive<Arg>();
1374  else
1375  return expr2.template isActive<Arg-num_args1>();
1376  }
1377 
1379  bool updateValue() const {
1380  return expr1.updateValue() && expr2.updateValue();
1381  }
1382 
1384  void cache() const {
1385  expr1.cache();
1386  expr2.cache();
1387  v1 = expr1.val();
1388  v2 = expr2.val();
1389  }
1390 
1392  value_type val() const {
1393  return v1*v2;
1394  }
1395 
1397  void computePartials(const value_type& bar,
1398  value_type partials[]) const {
1399  if (num_args1 > 0)
1400  expr1.computePartials(bar*v2, partials);
1401  if (num_args2 > 0)
1402  expr2.computePartials(bar*v1, partials+num_args1);
1403  }
1404 
1406  void getTangents(int i, value_type dots[]) const {
1407  expr1.getTangents(i, dots);
1408  expr2.getTangents(i, dots+num_args1);
1409  }
1410 
1411  template <int Arg>
1413  value_type getTangent(int i) const {
1414  if (Arg < num_args1)
1415  return expr1.template getTangent<Arg>(i);
1416  else
1417  return expr2.template getTangent<Arg-num_args1>(i);
1418  }
1419 
1421  bool isLinear() const {
1422  return false;
1423  }
1424 
1426  bool hasFastAccess() const {
1427  return expr1.hasFastAccess() && expr2.hasFastAccess();
1428  }
1429 
1431  const value_type dx(int i) const {
1432  if (expr1.size() > 0 && expr2.size() > 0)
1433  return v1*expr2.dx(i) + expr1.dx(i)*v2;
1434  else if (expr1.size() > 0)
1435  return expr1.dx(i)*v2;
1436  else
1437  return v1*expr2.dx(i);
1438  }
1439 
1441  const value_type fastAccessDx(int i) const {
1442  return v1*expr2.fastAccessDx(i) + expr1.fastAccessDx(i)*v2;
1443  }
1444 
1446  const value_type* getDx(int j) const {
1447  if (j < num_args1)
1448  return expr1.getDx(j);
1449  else
1450  return expr2.getDx(j-num_args1);
1451  }
1452 
1453  protected:
1454 
1455  const ExprT1& expr1;
1456  const ExprT2& expr2;
1457  mutable value_type_1 v1;
1458  mutable value_type_2 v2;
1459 
1460  };
1461 
1462  template <typename ExprT1, typename T2>
1463  class Expr< MultiplicationOp<ExprT1, ConstExpr<T2> > > {
1464 
1465  public:
1466 
1467  typedef ConstExpr<T2> ExprT2;
1468  typedef typename ExprT1::value_type value_type_1;
1469  typedef typename ExprT2::value_type value_type_2;
1470  typedef typename Sacado::Promote<value_type_1,
1471  value_type_2>::type value_type;
1472  typedef typename ExprT1::scalar_type scalar_type_1;
1473  typedef typename ExprT2::scalar_type scalar_type_2;
1474  typedef typename Sacado::Promote<scalar_type_1,
1475  scalar_type_2>::type scalar_type;
1476 
1477  typedef typename ExprT1::base_expr_type base_expr_type_1;
1478  typedef typename ExprT2::base_expr_type base_expr_type_2;
1479  typedef typename Sacado::Promote<base_expr_type_1,
1480  base_expr_type_2>::type base_expr_type;
1481 
1482  static const int num_args = ExprT1::num_args;
1483 
1484  static const bool is_linear = ExprT1::is_linear;
1485 
1487  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
1488  expr1(expr1_), expr2(expr2_) {}
1489 
1491  int size() const {
1492  return expr1.size();
1493  }
1494 
1495  template <int Arg>
1497  bool isActive() const {
1498  return expr1.template isActive<Arg>();
1499  }
1500 
1502  bool updateValue() const {
1503  return expr1.updateValue();
1504  }
1505 
1507  void cache() const {
1508  expr1.cache();
1509  }
1510 
1512  value_type val() const {
1513  return expr1.val()*expr2.val();
1514  }
1515 
1517  void computePartials(const value_type& bar,
1518  value_type partials[]) const {
1519  expr1.computePartials(bar*expr2.val(), partials);
1520  }
1521 
1523  void getTangents(int i, value_type dots[]) const {
1524  expr1.getTangents(i, dots);
1525  }
1526 
1527  template <int Arg>
1529  value_type getTangent(int i) const {
1530  return expr1.template getTangent<Arg>(i);
1531  }
1532 
1534  bool isLinear() const {
1535  return expr1.isLinear();
1536  }
1537 
1539  bool hasFastAccess() const {
1540  return expr1.hasFastAccess();
1541  }
1542 
1544  const value_type dx(int i) const {
1545  return expr1.dx(i)*expr2.val();
1546  }
1547 
1549  const value_type fastAccessDx(int i) const {
1550  return expr1.fastAccessDx(i)*expr2.val();
1551  }
1552 
1554  const value_type* getDx(int j) const {
1555  return expr1.getDx(j);
1556  }
1557 
1558  protected:
1559 
1560  const ExprT1& expr1;
1561  ExprT2 expr2;
1562 
1563  };
1564 
1565  template <typename T1, typename ExprT2>
1566  class Expr< MultiplicationOp< ConstExpr<T1>,ExprT2> > {
1567 
1568  public:
1569 
1570  typedef ConstExpr<T1> ExprT1;
1571  typedef typename ExprT1::value_type value_type_1;
1572  typedef typename ExprT2::value_type value_type_2;
1573  typedef typename Sacado::Promote<value_type_1,
1574  value_type_2>::type value_type;
1575  typedef typename ExprT1::scalar_type scalar_type_1;
1576  typedef typename ExprT2::scalar_type scalar_type_2;
1577  typedef typename Sacado::Promote<scalar_type_1,
1578  scalar_type_2>::type scalar_type;
1579 
1580  typedef typename ExprT1::base_expr_type base_expr_type_1;
1581  typedef typename ExprT2::base_expr_type base_expr_type_2;
1582  typedef typename Sacado::Promote<base_expr_type_1,
1583  base_expr_type_2>::type base_expr_type;
1584 
1585  static const int num_args = ExprT2::num_args;
1586 
1587  static const bool is_linear = ExprT2::is_linear;
1588 
1590  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
1591  expr1(expr1_), expr2(expr2_) {}
1592 
1594  int size() const {
1595  return expr2.size();
1596  }
1597 
1598  template <int Arg>
1600  bool isActive() const {
1601  return expr2.template isActive<Arg>();
1602  }
1603 
1605  bool updateValue() const {
1606  return expr2.updateValue();
1607  }
1608 
1610  void cache() const {
1611  expr2.cache();
1612  }
1613 
1615  value_type val() const {
1616  return expr1.val()*expr2.val();
1617  }
1618 
1620  void computePartials(const value_type& bar,
1621  value_type partials[]) const {
1622  expr2.computePartials(bar*expr1.val(), partials);
1623  }
1624 
1626  void getTangents(int i, value_type dots[]) const {
1627  expr2.getTangents(i, dots);
1628  }
1629 
1630  template <int Arg>
1632  value_type getTangent(int i) const {
1633  return expr2.template getTangent<Arg>(i);
1634  }
1635 
1637  bool isLinear() const {
1638  return expr2.isLinear();
1639  }
1640 
1642  bool hasFastAccess() const {
1643  return expr2.hasFastAccess();
1644  }
1645 
1647  const value_type dx(int i) const {
1648  return expr1.val()*expr2.dx(i);
1649  }
1650 
1652  const value_type fastAccessDx(int i) const {
1653  return expr1.val()*expr2.fastAccessDx(i);
1654  }
1655 
1657  const value_type* getDx(int j) const {
1658  return expr2.getDx(j);
1659  }
1660 
1661  protected:
1662 
1663  ExprT1 expr1;
1664  const ExprT2& expr2;
1665 
1666  };
1667 
1668  //
1669  // DivisionOp
1670  //
1671 
1672  template <typename ExprT1, typename ExprT2>
1673  class DivisionOp {};
1674 
1675  template <typename ExprT1, typename ExprT2>
1676  class Expr< DivisionOp<ExprT1,ExprT2> > {
1677 
1678  public:
1679 
1680  typedef typename ExprT1::value_type value_type_1;
1681  typedef typename ExprT2::value_type value_type_2;
1682  typedef typename Sacado::Promote<value_type_1,
1683  value_type_2>::type value_type;
1684  typedef typename ExprT1::scalar_type scalar_type_1;
1685  typedef typename ExprT2::scalar_type scalar_type_2;
1686  typedef typename Sacado::Promote<scalar_type_1,
1687  scalar_type_2>::type scalar_type;
1688 
1689  typedef typename ExprT1::base_expr_type base_expr_type_1;
1690  typedef typename ExprT2::base_expr_type base_expr_type_2;
1691  typedef typename Sacado::Promote<base_expr_type_1,
1692  base_expr_type_2>::type base_expr_type;
1693 
1694  static const int num_args1 = ExprT1::num_args;
1695  static const int num_args2 = ExprT2::num_args;
1696  static const int num_args = num_args1 + num_args2;
1697 
1698  static const bool is_linear = false;
1699 
1701  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
1702  expr1(expr1_), expr2(expr2_) {}
1703 
1705  int size() const {
1706  int sz1 = expr1.size(), sz2 = expr2.size();
1707  return sz1 > sz2 ? sz1 : sz2;
1708  }
1709 
1710  template <int Arg>
1712  bool isActive() const {
1713  if (Arg < num_args1)
1714  return expr1.template isActive<Arg>();
1715  else
1716  return expr2.template isActive<Arg-num_args1>();
1717  }
1718 
1720  bool updateValue() const {
1721  return expr1.updateValue() && expr2.updateValue();
1722  }
1723 
1725  void cache() const {
1726  expr1.cache();
1727  expr2.cache();
1728  const value_type_1 v1 = expr1.val();
1729  const value_type_2 v2 = expr2.val();
1730  a = scalar_type(1.0)/v2;
1731  v = v1*a;
1732  b = -v/v2;
1733  }
1734 
1736  value_type val() const {
1737  return v;
1738  }
1739 
1741  void computePartials(const value_type& bar,
1742  value_type partials[]) const {
1743  if (num_args1 > 0)
1744  expr1.computePartials(bar*a, partials);
1745  if (num_args2 > 0)
1746  expr2.computePartials(bar*b, partials+num_args1);
1747  }
1748 
1750  void getTangents(int i, value_type dots[]) const {
1751  expr1.getTangents(i, dots);
1752  expr2.getTangents(i, dots+num_args1);
1753  }
1754 
1755  template <int Arg>
1757  value_type getTangent(int i) const {
1758  if (Arg < num_args1)
1759  return expr1.template getTangent<Arg>(i);
1760  else
1761  return expr2.template getTangent<Arg-num_args1>(i);
1762  }
1763 
1765  bool isLinear() const {
1766  return false;
1767  }
1768 
1770  bool hasFastAccess() const {
1771  return expr1.hasFastAccess() && expr2.hasFastAccess();
1772  }
1773 
1775  const value_type dx(int i) const {
1776  if (expr1.size() > 0 && expr2.size() > 0)
1777  return expr1.dx(i)*a + expr2.dx(i)*b;
1778  else if (expr1.size() > 0)
1779  return expr1.dx(i)*a;
1780  else
1781  return expr1.val()*b;
1782  }
1783 
1785  const value_type fastAccessDx(int i) const {
1786  return expr1.fastAccessDx(i)*a + expr2.fastAccessDx(i)*b;
1787  }
1788 
1790  const value_type* getDx(int j) const {
1791  if (j < num_args1)
1792  return expr1.getDx(j);
1793  else
1794  return expr2.getDx(j-num_args1);
1795  }
1796 
1797  protected:
1798 
1799  const ExprT1& expr1;
1800  const ExprT2& expr2;
1801  mutable value_type v;
1802  mutable value_type a;
1803  mutable value_type b;
1804 
1805  };
1806 
1807  template <typename ExprT1, typename T2>
1808  class Expr< DivisionOp<ExprT1, ConstExpr<T2> > > {
1809 
1810  public:
1811 
1812  typedef ConstExpr<T2> ExprT2;
1813  typedef typename ExprT1::value_type value_type_1;
1814  typedef typename ExprT2::value_type value_type_2;
1815  typedef typename Sacado::Promote<value_type_1,
1816  value_type_2>::type value_type;
1817  typedef typename ExprT1::scalar_type scalar_type_1;
1818  typedef typename ExprT2::scalar_type scalar_type_2;
1819  typedef typename Sacado::Promote<scalar_type_1,
1820  scalar_type_2>::type scalar_type;
1821 
1822  typedef typename ExprT1::base_expr_type base_expr_type_1;
1823  typedef typename ExprT2::base_expr_type base_expr_type_2;
1824  typedef typename Sacado::Promote<base_expr_type_1,
1825  base_expr_type_2>::type base_expr_type;
1826 
1827  static const int num_args = ExprT1::num_args;
1828 
1829  static const bool is_linear = ExprT1::is_linear;
1830 
1832  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
1833  expr1(expr1_), expr2(expr2_) {}
1834 
1836  int size() const {
1837  return expr1.size();
1838  }
1839 
1840  template <int Arg>
1842  bool isActive() const {
1843  return expr1.template isActive<Arg>();
1844  }
1845 
1847  bool updateValue() const {
1848  return expr1.updateValue();
1849  }
1850 
1852  void cache() const {
1853  expr1.cache();
1854  const value_type_1 v1 = expr1.val();
1855  a = scalar_type(1.0)/expr2.val();
1856  v = v1*a;
1857  }
1858 
1860  value_type val() const {
1861  return v;
1862  }
1863 
1865  void computePartials(const value_type& bar,
1866  value_type partials[]) const {
1867  expr1.computePartials(bar*a, partials);
1868  }
1869 
1871  void getTangents(int i, value_type dots[]) const {
1872  expr1.getTangents(i, dots);
1873  }
1874 
1875  template <int Arg>
1877  value_type getTangent(int i) const {
1878  return expr1.template getTangent<Arg>(i);
1879  }
1880 
1882  bool isLinear() const {
1883  return expr1.isLinear();
1884  }
1885 
1887  bool hasFastAccess() const {
1888  return expr1.hasFastAccess();
1889  }
1890 
1892  const value_type dx(int i) const {
1893  return expr1.dx(i)*a;
1894  }
1895 
1897  const value_type fastAccessDx(int i) const {
1898  return expr1.fastAccessDx(i)*a;
1899  }
1900 
1902  const value_type* getDx(int j) const {
1903  return expr1.getDx(j);
1904  }
1905 
1906  protected:
1907 
1908  const ExprT1& expr1;
1909  ExprT2 expr2;
1910  mutable value_type v;
1911  mutable value_type a;
1912 
1913  };
1914 
1915  template <typename T1, typename ExprT2>
1916  class Expr< DivisionOp< ConstExpr<T1>,ExprT2> > {
1917 
1918  public:
1919 
1920  typedef ConstExpr<T1> ExprT1;
1921  typedef typename ExprT1::value_type value_type_1;
1922  typedef typename ExprT2::value_type value_type_2;
1923  typedef typename Sacado::Promote<value_type_1,
1924  value_type_2>::type value_type;
1925  typedef typename ExprT1::scalar_type scalar_type_1;
1926  typedef typename ExprT2::scalar_type scalar_type_2;
1927  typedef typename Sacado::Promote<scalar_type_1,
1928  scalar_type_2>::type scalar_type;
1929 
1930  typedef typename ExprT1::base_expr_type base_expr_type_1;
1931  typedef typename ExprT2::base_expr_type base_expr_type_2;
1932  typedef typename Sacado::Promote<base_expr_type_1,
1933  base_expr_type_2>::type base_expr_type;
1934 
1935  static const int num_args = ExprT2::num_args;
1936 
1937  static const bool is_linear = false;
1938 
1940  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
1941  expr1(expr1_), expr2(expr2_) {}
1942 
1944  int size() const {
1945  return expr2.size();
1946  }
1947 
1948  template <int Arg>
1950  bool isActive() const {
1951  return expr2.template isActive<Arg>();
1952  }
1953 
1955  bool updateValue() const {
1956  return expr2.updateValue();
1957  }
1958 
1960  void cache() const {
1961  expr2.cache();
1962  const value_type_2 v2 = expr2.val();
1963  v = expr1.val()/v2;
1964  b = -v/v2;
1965  }
1966 
1968  value_type val() const {
1969  return v;
1970  }
1971 
1973  void computePartials(const value_type& bar,
1974  value_type partials[]) const {
1975  expr2.computePartials(bar*b, partials);
1976  }
1977 
1979  void getTangents(int i, value_type dots[]) const {
1980  expr2.getTangents(i, dots);
1981  }
1982 
1983  template <int Arg>
1985  value_type getTangent(int i) const {
1986  return expr2.template getTangent<Arg>(i);
1987  }
1988 
1990  bool isLinear() const {
1991  return false;
1992  }
1993 
1995  bool hasFastAccess() const {
1996  return expr2.hasFastAccess();
1997  }
1998 
2000  const value_type dx(int i) const {
2001  return expr2.dx(i)*b;
2002  }
2003 
2005  const value_type fastAccessDx(int i) const {
2006  return expr2.fastAccessDx(i)*b;
2007  }
2008 
2010  const value_type* getDx(int j) const {
2011  return expr2.getDx(j);
2012  }
2013 
2014  protected:
2015 
2016  ExprT1 expr1;
2017  const ExprT2& expr2;
2018  mutable value_type v;
2019  mutable value_type b;
2020 
2021  };
2022 
2023  //
2024  // Atan2Op
2025  //
2026 
2027  template <typename ExprT1, typename ExprT2>
2028  class Atan2Op {};
2029 
2030  template <typename ExprT1, typename ExprT2>
2031  class Expr< Atan2Op<ExprT1,ExprT2> > {
2032 
2033  public:
2034 
2035  typedef typename ExprT1::value_type value_type_1;
2036  typedef typename ExprT2::value_type value_type_2;
2037  typedef typename Sacado::Promote<value_type_1,
2038  value_type_2>::type value_type;
2039  typedef typename ExprT1::scalar_type scalar_type_1;
2040  typedef typename ExprT2::scalar_type scalar_type_2;
2041  typedef typename Sacado::Promote<scalar_type_1,
2042  scalar_type_2>::type scalar_type;
2043 
2044  typedef typename ExprT1::base_expr_type base_expr_type_1;
2045  typedef typename ExprT2::base_expr_type base_expr_type_2;
2046  typedef typename Sacado::Promote<base_expr_type_1,
2047  base_expr_type_2>::type base_expr_type;
2048 
2049  static const int num_args1 = ExprT1::num_args;
2050  static const int num_args2 = ExprT2::num_args;
2051  static const int num_args = num_args1 + num_args2;
2052 
2053  static const bool is_linear = false;
2054 
2056  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
2057  expr1(expr1_), expr2(expr2_) {}
2058 
2060  int size() const {
2061  int sz1 = expr1.size(), sz2 = expr2.size();
2062  return sz1 > sz2 ? sz1 : sz2;
2063  }
2064 
2065  template <int Arg>
2067  bool isActive() const {
2068  if (Arg < num_args1)
2069  return expr1.template isActive<Arg>();
2070  else
2071  return expr2.template isActive<Arg-num_args1>();
2072  }
2073 
2075  bool updateValue() const {
2076  return expr1.updateValue() && expr2.updateValue();
2077  }
2078 
2080  void cache() const {
2081  expr1.cache();
2082  expr2.cache();
2083  const value_type_1 v1 = expr1.val();
2084  const value_type_2 v2 = expr2.val();
2085  a = scalar_type(1.0)/(v1*v1 + v2*v2);
2086  b = -v1*a;
2087  a = v2*a;
2088  v = std::atan2(v1,v2);
2089  }
2090 
2092  value_type val() const {
2093  return v;
2094  }
2095 
2097  void computePartials(const value_type& bar,
2098  value_type partials[]) const {
2099  if (num_args1 > 0)
2100  expr1.computePartials(bar*a, partials);
2101  if (num_args2 > 0)
2102  expr2.computePartials(bar*b, partials+num_args1);
2103  }
2104 
2106  void getTangents(int i, value_type dots[]) const {
2107  expr1.getTangents(i, dots);
2108  expr2.getTangents(i, dots+num_args1);
2109  }
2110 
2111  template <int Arg>
2113  value_type getTangent(int i) const {
2114  if (Arg < num_args1)
2115  return expr1.template getTangent<Arg>(i);
2116  else
2117  return expr2.template getTangent<Arg-num_args1>(i);
2118  }
2119 
2121  bool isLinear() const {
2122  return false;
2123  }
2124 
2126  bool hasFastAccess() const {
2127  return expr1.hasFastAccess() && expr2.hasFastAccess();
2128  }
2129 
2131  const value_type dx(int i) const {
2132  if (expr1.size() > 0 && expr2.size() > 0)
2133  return expr1.dx(i)*a + expr2.dx(i)*b;
2134  else if (expr1.size() > 0)
2135  return expr1.dx(i)*a;
2136  else
2137  return expr1.val()*b;
2138  }
2139 
2141  const value_type fastAccessDx(int i) const {
2142  return expr1.fastAccessDx(i)*a + expr2.fastAccessDx(i)*b;
2143  }
2144 
2146  const value_type* getDx(int j) const {
2147  if (j < num_args1)
2148  return expr1.getDx(j);
2149  else
2150  return expr2.getDx(j-num_args1);
2151  }
2152 
2153  protected:
2154 
2155  const ExprT1& expr1;
2156  const ExprT2& expr2;
2157  mutable value_type v;
2158  mutable value_type a;
2159  mutable value_type b;
2160 
2161  };
2162 
2163  template <typename ExprT1, typename T2>
2164  class Expr< Atan2Op<ExprT1, ConstExpr<T2> > > {
2165 
2166  public:
2167 
2168  typedef ConstExpr<T2> ExprT2;
2169  typedef typename ExprT1::value_type value_type_1;
2170  typedef typename ExprT2::value_type value_type_2;
2171  typedef typename Sacado::Promote<value_type_1,
2172  value_type_2>::type value_type;
2173  typedef typename ExprT1::scalar_type scalar_type_1;
2174  typedef typename ExprT2::scalar_type scalar_type_2;
2175  typedef typename Sacado::Promote<scalar_type_1,
2176  scalar_type_2>::type scalar_type;
2177 
2178  typedef typename ExprT1::base_expr_type base_expr_type_1;
2179  typedef typename ExprT2::base_expr_type base_expr_type_2;
2180  typedef typename Sacado::Promote<base_expr_type_1,
2181  base_expr_type_2>::type base_expr_type;
2182 
2183  static const int num_args = ExprT1::num_args;
2184 
2185  static const bool is_linear = false;
2186 
2188  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
2189  expr1(expr1_), expr2(expr2_) {}
2190 
2192  int size() const {
2193  return expr1.size();
2194  }
2195 
2196  template <int Arg>
2198  bool isActive() const {
2199  return expr1.template isActive<Arg>();
2200  }
2201 
2203  bool updateValue() const {
2204  return expr1.updateValue();
2205  }
2206 
2208  void cache() const {
2209  expr1.cache();
2210  const value_type_1 v1 = expr1.val();
2211  const value_type_2 v2 = expr2.val();
2212  a = v2/(v1*v1 + v2*v2);
2213  v = std::atan2(v1,v2);
2214  }
2215 
2217  value_type val() const {
2218  return v;
2219  }
2220 
2222  void computePartials(const value_type& bar,
2223  value_type partials[]) const {
2224  expr1.computePartials(bar*a, partials);
2225  }
2226 
2228  void getTangents(int i, value_type dots[]) const {
2229  expr1.getTangents(i, dots);
2230  }
2231 
2232  template <int Arg>
2234  value_type getTangent(int i) const {
2235  return expr1.template getTangent<Arg>(i);
2236  }
2237 
2239  bool isLinear() const {
2240  return false;
2241  }
2242 
2244  bool hasFastAccess() const {
2245  return expr1.hasFastAccess();
2246  }
2247 
2249  const value_type dx(int i) const {
2250  return expr1.dx(i)*a;
2251  }
2252 
2254  const value_type fastAccessDx(int i) const {
2255  return expr1.fastAccessDx(i)*a;
2256  }
2257 
2259  const value_type* getDx(int j) const {
2260  return expr1.getDx(j);
2261  }
2262 
2263  protected:
2264 
2265  const ExprT1& expr1;
2266  ExprT2 expr2;
2267  mutable value_type v;
2268  mutable value_type a;
2269 
2270  };
2271 
2272  template <typename T1, typename ExprT2>
2273  class Expr< Atan2Op< ConstExpr<T1>,ExprT2> > {
2274 
2275  public:
2276 
2277  typedef ConstExpr<T1> ExprT1;
2278  typedef typename ExprT1::value_type value_type_1;
2279  typedef typename ExprT2::value_type value_type_2;
2280  typedef typename Sacado::Promote<value_type_1,
2281  value_type_2>::type value_type;
2282  typedef typename ExprT1::scalar_type scalar_type_1;
2283  typedef typename ExprT2::scalar_type scalar_type_2;
2284  typedef typename Sacado::Promote<scalar_type_1,
2285  scalar_type_2>::type scalar_type;
2286 
2287  typedef typename ExprT1::base_expr_type base_expr_type_1;
2288  typedef typename ExprT2::base_expr_type base_expr_type_2;
2289  typedef typename Sacado::Promote<base_expr_type_1,
2290  base_expr_type_2>::type base_expr_type;
2291 
2292  static const int num_args = ExprT2::num_args;
2293 
2294  static const bool is_linear = false;
2295 
2297  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
2298  expr1(expr1_), expr2(expr2_) {}
2299 
2301  int size() const {
2302  return expr2.size();
2303  }
2304 
2305  template <int Arg>
2307  bool isActive() const {
2308  return expr2.template isActive<Arg>();
2309  }
2310 
2312  bool updateValue() const {
2313  return expr2.updateValue();
2314  }
2315 
2317  void cache() const {
2318  expr2.cache();
2319  const value_type_1 v1 = expr1.val();
2320  const value_type_2 v2 = expr2.val();
2321  b = -v1/(v1*v1 + v2*v2);
2322  v = std::atan2(v1,v2);
2323  }
2324 
2326  value_type val() const {
2327  return v;
2328  }
2329 
2331  void computePartials(const value_type& bar,
2332  value_type partials[]) const {
2333  expr2.computePartials(bar*b, partials);
2334  }
2335 
2337  void getTangents(int i, value_type dots[]) const {
2338  expr2.getTangents(i, dots);
2339  }
2340 
2341  template <int Arg>
2343  value_type getTangent(int i) const {
2344  return expr2.template getTangent<Arg>(i);
2345  }
2346 
2348  bool isLinear() const {
2349  return false;
2350  }
2351 
2353  bool hasFastAccess() const {
2354  return expr2.hasFastAccess();
2355  }
2356 
2358  const value_type dx(int i) const {
2359  return expr2.dx(i)*b;
2360  }
2361 
2363  const value_type fastAccessDx(int i) const {
2364  return expr2.fastAccessDx(i)*b;
2365  }
2366 
2368  const value_type* getDx(int j) const {
2369  return expr2.getDx(j);
2370  }
2371 
2372  protected:
2373 
2374  ExprT1 expr1;
2375  const ExprT2& expr2;
2376  mutable value_type v;
2377  mutable value_type b;
2378 
2379  };
2380 
2381  //
2382  // PowerOp
2383  //
2384 
2385  template <typename ExprT1, typename ExprT2>
2386  class PowerOp {};
2387 
2388  template <typename ExprT1, typename ExprT2>
2389  class Expr< PowerOp<ExprT1,ExprT2> > {
2390 
2391  public:
2392 
2393  typedef typename ExprT1::value_type value_type_1;
2394  typedef typename ExprT2::value_type value_type_2;
2395  typedef typename Sacado::Promote<value_type_1,
2396  value_type_2>::type value_type;
2397  typedef typename ExprT1::scalar_type scalar_type_1;
2398  typedef typename ExprT2::scalar_type scalar_type_2;
2399  typedef typename Sacado::Promote<scalar_type_1,
2400  scalar_type_2>::type scalar_type;
2401 
2402  typedef typename ExprT1::base_expr_type base_expr_type_1;
2403  typedef typename ExprT2::base_expr_type base_expr_type_2;
2404  typedef typename Sacado::Promote<base_expr_type_1,
2405  base_expr_type_2>::type base_expr_type;
2406 
2407  static const int num_args1 = ExprT1::num_args;
2408  static const int num_args2 = ExprT2::num_args;
2409  static const int num_args = num_args1 + num_args2;
2410 
2411  static const bool is_linear = false;
2412 
2414  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
2415  expr1(expr1_), expr2(expr2_) {}
2416 
2418  int size() const {
2419  int sz1 = expr1.size(), sz2 = expr2.size();
2420  return sz1 > sz2 ? sz1 : sz2;
2421  }
2422 
2423  template <int Arg>
2425  bool isActive() const {
2426  if (Arg < num_args1)
2427  return expr1.template isActive<Arg>();
2428  else
2429  return expr2.template isActive<Arg-num_args1>();
2430  }
2431 
2433  bool updateValue() const {
2434  return expr1.updateValue() && expr2.updateValue();
2435  }
2436 
2438  void cache() const {
2439  expr1.cache();
2440  expr2.cache();
2441  const value_type_1 v1 = expr1.val();
2442  const value_type_2 v2 = expr2.val();
2443  v = std::pow(v1,v2);
2444  if (v1 == scalar_type(0.0)) {
2445  a = scalar_type(0.0);
2446  b = scalar_type(0.0);
2447  }
2448  else {
2449  a = v*v2/v1;
2450  b = v*std::log(v1);
2451  }
2452  }
2453 
2455  value_type val() const {
2456  return v;
2457  }
2458 
2460  void computePartials(const value_type& bar,
2461  value_type partials[]) const {
2462  if (num_args1 > 0)
2463  expr1.computePartials(bar*a, partials);
2464  if (num_args2 > 0)
2465  expr2.computePartials(bar*b, partials+num_args1);
2466  }
2467 
2469  void getTangents(int i, value_type dots[]) const {
2470  expr1.getTangents(i, dots);
2471  expr2.getTangents(i, dots+num_args1);
2472  }
2473 
2474  template <int Arg>
2476  value_type getTangent(int i) const {
2477  if (Arg < num_args1)
2478  return expr1.template getTangent<Arg>(i);
2479  else
2480  return expr2.template getTangent<Arg-num_args1>(i);
2481  }
2482 
2484  bool isLinear() const {
2485  return false;
2486  }
2487 
2489  bool hasFastAccess() const {
2490  return expr1.hasFastAccess() && expr2.hasFastAccess();
2491  }
2492 
2494  const value_type dx(int i) const {
2495  if (expr1.size() > 0 && expr2.size() > 0)
2496  return expr1.dx(i)*a + expr2.dx(i)*b;
2497  else if (expr1.size() > 0)
2498  return expr1.dx(i)*a;
2499  else
2500  return expr1.val()*b;
2501  }
2502 
2504  const value_type fastAccessDx(int i) const {
2505  return expr1.fastAccessDx(i)*a + expr2.fastAccessDx(i)*b;
2506  }
2507 
2509  const value_type* getDx(int j) const {
2510  if (j < num_args1)
2511  return expr1.getDx(j);
2512  else
2513  return expr2.getDx(j-num_args1);
2514  }
2515 
2516  protected:
2517 
2518  const ExprT1& expr1;
2519  const ExprT2& expr2;
2520  mutable value_type v;
2521  mutable value_type a;
2522  mutable value_type b;
2523 
2524  };
2525 
2526  template <typename ExprT1, typename T2>
2527  class Expr< PowerOp<ExprT1, ConstExpr<T2> > > {
2528 
2529  public:
2530 
2531  typedef ConstExpr<T2> ExprT2;
2532  typedef typename ExprT1::value_type value_type_1;
2533  typedef typename ExprT2::value_type value_type_2;
2534  typedef typename Sacado::Promote<value_type_1,
2535  value_type_2>::type value_type;
2536  typedef typename ExprT1::scalar_type scalar_type_1;
2537  typedef typename ExprT2::scalar_type scalar_type_2;
2538  typedef typename Sacado::Promote<scalar_type_1,
2539  scalar_type_2>::type scalar_type;
2540 
2541  typedef typename ExprT1::base_expr_type base_expr_type_1;
2542  typedef typename ExprT2::base_expr_type base_expr_type_2;
2543  typedef typename Sacado::Promote<base_expr_type_1,
2544  base_expr_type_2>::type base_expr_type;
2545 
2546  static const int num_args = ExprT1::num_args;
2547 
2548  static const bool is_linear = false;
2549 
2551  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
2552  expr1(expr1_), expr2(expr2_) {}
2553 
2555  int size() const {
2556  return expr1.size();
2557  }
2558 
2559  template <int Arg>
2561  bool isActive() const {
2562  return expr1.template isActive<Arg>();
2563  }
2564 
2566  bool updateValue() const {
2567  return expr1.updateValue();
2568  }
2569 
2571  void cache() const {
2572  expr1.cache();
2573  const value_type_1 v1 = expr1.val();
2574  const value_type_2 v2 = expr2.val();
2575  v = std::pow(v1,v2);
2576  if (v1 == scalar_type(0.0)) {
2577  a = scalar_type(0.0);
2578  }
2579  else {
2580  a = v*v2/v1;
2581  }
2582  }
2583 
2585  value_type val() const {
2586  return v;
2587  }
2588 
2590  void computePartials(const value_type& bar,
2591  value_type partials[]) const {
2592  expr1.computePartials(bar*a, partials);
2593  }
2594 
2596  void getTangents(int i, value_type dots[]) const {
2597  expr1.getTangents(i, dots);
2598  }
2599 
2600  template <int Arg>
2602  value_type getTangent(int i) const {
2603  return expr1.template getTangent<Arg>(i);
2604  }
2605 
2607  bool isLinear() const {
2608  return false;
2609  }
2610 
2612  bool hasFastAccess() const {
2613  return expr1.hasFastAccess();
2614  }
2615 
2617  const value_type dx(int i) const {
2618  return expr1.dx(i)*a;
2619  }
2620 
2622  const value_type fastAccessDx(int i) const {
2623  return expr1.fastAccessDx(i)*a;
2624  }
2625 
2627  const value_type* getDx(int j) const {
2628  return expr1.getDx(j);
2629  }
2630 
2631  protected:
2632 
2633  const ExprT1& expr1;
2634  ExprT2 expr2;
2635  mutable value_type v;
2636  mutable value_type a;
2637 
2638  };
2639 
2640  template <typename T1, typename ExprT2>
2641  class Expr< PowerOp< ConstExpr<T1>,ExprT2> > {
2642 
2643  public:
2644 
2645  typedef ConstExpr<T1> ExprT1;
2646  typedef typename ExprT1::value_type value_type_1;
2647  typedef typename ExprT2::value_type value_type_2;
2648  typedef typename Sacado::Promote<value_type_1,
2649  value_type_2>::type value_type;
2650  typedef typename ExprT1::scalar_type scalar_type_1;
2651  typedef typename ExprT2::scalar_type scalar_type_2;
2652  typedef typename Sacado::Promote<scalar_type_1,
2653  scalar_type_2>::type scalar_type;
2654 
2655  typedef typename ExprT1::base_expr_type base_expr_type_1;
2656  typedef typename ExprT2::base_expr_type base_expr_type_2;
2657  typedef typename Sacado::Promote<base_expr_type_1,
2658  base_expr_type_2>::type base_expr_type;
2659 
2660  static const int num_args = ExprT2::num_args;
2661 
2662  static const bool is_linear = false;
2663 
2665  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
2666  expr1(expr1_), expr2(expr2_) {}
2667 
2669  int size() const {
2670  return expr2.size();
2671  }
2672 
2673  template <int Arg>
2675  bool isActive() const {
2676  return expr2.template isActive<Arg>();
2677  }
2678 
2680  bool updateValue() const {
2681  return expr2.updateValue();
2682  }
2683 
2685  void cache() const {
2686  expr2.cache();
2687  const value_type_1 v1 = expr1.val();
2688  const value_type_2 v2 = expr2.val();
2689  v = std::pow(v1,v2);
2690  if (v1 == scalar_type(0.0)) {
2691  b = scalar_type(0.0);
2692  }
2693  else {
2694  b = v*std::log(v1);
2695  }
2696  }
2697 
2699  value_type val() const {
2700  return v;
2701  }
2702 
2704  void computePartials(const value_type& bar,
2705  value_type partials[]) const {
2706  expr2.computePartials(bar*b, partials);
2707  }
2708 
2710  void getTangents(int i, value_type dots[]) const {
2711  expr2.getTangents(i, dots);
2712  }
2713 
2714  template <int Arg>
2716  value_type getTangent(int i) const {
2717  return expr2.template getTangent<Arg>(i);
2718  }
2719 
2721  bool isLinear() const {
2722  return false;
2723  }
2724 
2726  bool hasFastAccess() const {
2727  return expr2.hasFastAccess();
2728  }
2729 
2731  const value_type dx(int i) const {
2732  return expr2.dx(i)*b;
2733  }
2734 
2736  const value_type fastAccessDx(int i) const {
2737  return expr2.fastAccessDx(i)*b;
2738  }
2739 
2741  const value_type* getDx(int j) const {
2742  return expr2.getDx(j);
2743  }
2744 
2745  protected:
2746 
2747  ExprT1 expr1;
2748  const ExprT2& expr2;
2749  mutable value_type v;
2750  mutable value_type b;
2751 
2752  };
2753 
2754  //
2755  // MaxOp
2756  //
2757 
2758  template <typename ExprT1, typename ExprT2>
2759  class MaxOp {};
2760 
2761  template <typename ExprT1, typename ExprT2>
2762  class Expr< MaxOp<ExprT1,ExprT2> > {
2763 
2764  public:
2765 
2766  typedef typename ExprT1::value_type value_type_1;
2767  typedef typename ExprT2::value_type value_type_2;
2768  typedef typename Sacado::Promote<value_type_1,
2769  value_type_2>::type value_type;
2770  typedef typename ExprT1::scalar_type scalar_type_1;
2771  typedef typename ExprT2::scalar_type scalar_type_2;
2772  typedef typename Sacado::Promote<scalar_type_1,
2773  scalar_type_2>::type scalar_type;
2774 
2775  typedef typename ExprT1::base_expr_type base_expr_type_1;
2776  typedef typename ExprT2::base_expr_type base_expr_type_2;
2777  typedef typename Sacado::Promote<base_expr_type_1,
2778  base_expr_type_2>::type base_expr_type;
2779 
2780  static const int num_args1 = ExprT1::num_args;
2781  static const int num_args2 = ExprT2::num_args;
2782  static const int num_args = num_args1 + num_args2;
2783 
2784  static const bool is_linear = false;
2785 
2787  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
2788  expr1(expr1_), expr2(expr2_) {}
2789 
2791  int size() const {
2792  int sz1 = expr1.size(), sz2 = expr2.size();
2793  return sz1 > sz2 ? sz1 : sz2;
2794  }
2795 
2796  template <int Arg>
2798  bool isActive() const {
2799  if (Arg < num_args1)
2800  return expr1.template isActive<Arg>();
2801  else
2802  return expr2.template isActive<Arg-num_args1>();
2803  }
2804 
2806  bool updateValue() const {
2807  return expr1.updateValue() && expr2.updateValue();
2808  }
2809 
2811  void cache() const {
2812  expr1.cache();
2813  expr2.cache();
2814  const value_type_1 v1 = expr1.val();
2815  const value_type_2 v2 = expr2.val();
2816  max_v1 = (v1 >= v2);
2817  v = max_v1 ? v1 : v2;
2818  }
2819 
2821  value_type val() const {
2822  return v;
2823  }
2824 
2826  void computePartials(const value_type& bar,
2827  value_type partials[]) const {
2828  if (num_args1 > 0) {
2829  if (max_v1)
2830  expr1.computePartials(bar, partials);
2831  else
2832  expr1.computePartials(value_type(0.0), partials);
2833  }
2834  if (num_args2 > 0) {
2835  if (max_v1)
2836  expr2.computePartials(value_type(0.0), partials+num_args1);
2837  else
2838  expr2.computePartials(bar, partials+num_args1);
2839  }
2840  }
2841 
2843  void getTangents(int i, value_type dots[]) const {
2844  expr1.getTangents(i, dots);
2845  expr2.getTangents(i, dots+num_args1);
2846  }
2847 
2848  template <int Arg>
2850  value_type getTangent(int i) const {
2851  if (Arg < num_args1)
2852  return expr1.template getTangent<Arg>(i);
2853  else
2854  return expr2.template getTangent<Arg-num_args1>(i);
2855  }
2856 
2858  bool isLinear() const {
2859  return false;
2860  }
2861 
2863  bool hasFastAccess() const {
2864  return expr1.hasFastAccess() && expr2.hasFastAccess();
2865  }
2866 
2868  const value_type dx(int i) const {
2869  return max_v1 ? expr1.dx(i) : expr2.dx(i);
2870  }
2871 
2873  const value_type fastAccessDx(int i) const {
2874  return max_v1 ? expr1.fastAccessDx(i) : expr2.fastAccessDx(i);
2875  }
2876 
2878  const value_type* getDx(int j) const {
2879  if (j < num_args1)
2880  return expr1.getDx(j);
2881  else
2882  return expr2.getDx(j-num_args1);
2883  }
2884 
2885  protected:
2886 
2887  const ExprT1& expr1;
2888  const ExprT2& expr2;
2889  mutable value_type v;
2890  mutable bool max_v1;
2891 
2892  };
2893 
2894  template <typename ExprT1, typename T2>
2895  class Expr< MaxOp<ExprT1, ConstExpr<T2> > > {
2896 
2897  public:
2898 
2899  typedef ConstExpr<T2> ExprT2;
2900  typedef typename ExprT1::value_type value_type_1;
2901  typedef typename ExprT2::value_type value_type_2;
2902  typedef typename Sacado::Promote<value_type_1,
2903  value_type_2>::type value_type;
2904  typedef typename ExprT1::scalar_type scalar_type_1;
2905  typedef typename ExprT2::scalar_type scalar_type_2;
2906  typedef typename Sacado::Promote<scalar_type_1,
2907  scalar_type_2>::type scalar_type;
2908 
2909  typedef typename ExprT1::base_expr_type base_expr_type_1;
2910  typedef typename ExprT2::base_expr_type base_expr_type_2;
2911  typedef typename Sacado::Promote<base_expr_type_1,
2912  base_expr_type_2>::type base_expr_type;
2913 
2914  static const int num_args = ExprT1::num_args;
2915 
2916  static const bool is_linear = false;
2917 
2919  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
2920  expr1(expr1_), expr2(expr2_) {}
2921 
2923  int size() const {
2924  return expr1.size();
2925  }
2926 
2927  template <int Arg>
2929  bool isActive() const {
2930  return expr1.template isActive<Arg>();
2931  }
2932 
2934  bool updateValue() const {
2935  return expr1.updateValue();
2936  }
2937 
2939  void cache() const {
2940  expr1.cache();
2941  const value_type_1 v1 = expr1.val();
2942  const value_type_2 v2 = expr2.val();
2943  max_v1 = (v1 >= v2);
2944  v = max_v1 ? v1 : v2;
2945  }
2946 
2948  value_type val() const {
2949  return v;
2950  }
2951 
2953  void computePartials(const value_type& bar,
2954  value_type partials[]) const {
2955  if (max_v1)
2956  expr1.computePartials(bar, partials);
2957  else
2958  expr1.computePartials(value_type(0.0), partials);
2959  }
2960 
2962  void getTangents(int i, value_type dots[]) const {
2963  expr1.getTangents(i, dots);
2964  }
2965 
2966  template <int Arg>
2968  value_type getTangent(int i) const {
2969  return expr1.template getTangent<Arg>(i);
2970  }
2971 
2973  bool isLinear() const {
2974  return false;
2975  }
2976 
2978  bool hasFastAccess() const {
2979  return expr1.hasFastAccess();
2980  }
2981 
2983  const value_type dx(int i) const {
2984  return max_v1 ? expr1.dx(i) : value_type(0.0);
2985  }
2986 
2988  const value_type fastAccessDx(int i) const {
2989  return max_v1 ? expr1.fastAccessDx(i) : value_type(0.0);
2990  }
2991 
2993  const value_type* getDx(int j) const {
2994  return expr1.getDx(j);
2995  }
2996 
2997  protected:
2998 
2999  const ExprT1& expr1;
3000  ExprT2 expr2;
3001  mutable value_type v;
3002  mutable bool max_v1;
3003 
3004  };
3005 
3006  template <typename T1, typename ExprT2>
3007  class Expr< MaxOp< ConstExpr<T1>,ExprT2> > {
3008 
3009  public:
3010 
3011  typedef ConstExpr<T1> ExprT1;
3012  typedef typename ExprT1::value_type value_type_1;
3013  typedef typename ExprT2::value_type value_type_2;
3014  typedef typename Sacado::Promote<value_type_1,
3015  value_type_2>::type value_type;
3016  typedef typename ExprT1::scalar_type scalar_type_1;
3017  typedef typename ExprT2::scalar_type scalar_type_2;
3018  typedef typename Sacado::Promote<scalar_type_1,
3019  scalar_type_2>::type scalar_type;
3020 
3021  typedef typename ExprT1::base_expr_type base_expr_type_1;
3022  typedef typename ExprT2::base_expr_type base_expr_type_2;
3023  typedef typename Sacado::Promote<base_expr_type_1,
3024  base_expr_type_2>::type base_expr_type;
3025 
3026  static const int num_args = ExprT2::num_args;
3027 
3028  static const bool is_linear = false;
3029 
3031  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
3032  expr1(expr1_), expr2(expr2_) {}
3033 
3035  int size() const {
3036  return expr2.size();
3037  }
3038 
3039  template <int Arg>
3041  bool isActive() const {
3042  return expr2.template isActive<Arg>();
3043  }
3044 
3046  bool updateValue() const {
3047  return expr2.updateValue();
3048  }
3049 
3051  void cache() const {
3052  expr2.cache();
3053  const value_type_1 v1 = expr1.val();
3054  const value_type_2 v2 = expr2.val();
3055  max_v1 = (v1 >= v2);
3056  v = max_v1 ? v1 : v2;
3057  }
3058 
3060  value_type val() const {
3061  return v;
3062  }
3063 
3065  void computePartials(const value_type& bar,
3066  value_type partials[]) const {
3067  if (max_v1)
3068  expr2.computePartials(value_type(0.0), partials);
3069  else
3070  expr2.computePartials(bar, partials);
3071  }
3072 
3074  void getTangents(int i, value_type dots[]) const {
3075  expr2.getTangents(i, dots);
3076  }
3077 
3078  template <int Arg>
3080  value_type getTangent(int i) const {
3081  return expr2.template getTangent<Arg>(i);
3082  }
3083 
3085  bool isLinear() const {
3086  return false;
3087  }
3088 
3090  bool hasFastAccess() const {
3091  return expr2.hasFastAccess();
3092  }
3093 
3095  const value_type dx(int i) const {
3096  return max_v1 ? value_type(0.0) : expr2.dx(i);
3097  }
3098 
3100  const value_type fastAccessDx(int i) const {
3101  return max_v1 ? value_type(0.0) : expr2.fastAccessDx(i);
3102  }
3103 
3105  const value_type* getDx(int j) const {
3106  return expr2.getDx(j);
3107  }
3108 
3109  protected:
3110 
3111  ExprT1 expr1;
3112  const ExprT2& expr2;
3113  mutable value_type v;
3114  mutable bool max_v1;
3115 
3116  };
3117 
3118  //
3119  // MinOp
3120  //
3121 
3122  template <typename ExprT1, typename ExprT2>
3123  class MinOp {};
3124 
3125  template <typename ExprT1, typename ExprT2>
3126  class Expr< MinOp<ExprT1,ExprT2> > {
3127 
3128  public:
3129 
3130  typedef typename ExprT1::value_type value_type_1;
3131  typedef typename ExprT2::value_type value_type_2;
3132  typedef typename Sacado::Promote<value_type_1,
3133  value_type_2>::type value_type;
3134  typedef typename ExprT1::scalar_type scalar_type_1;
3135  typedef typename ExprT2::scalar_type scalar_type_2;
3136  typedef typename Sacado::Promote<scalar_type_1,
3137  scalar_type_2>::type scalar_type;
3138 
3139  typedef typename ExprT1::base_expr_type base_expr_type_1;
3140  typedef typename ExprT2::base_expr_type base_expr_type_2;
3141  typedef typename Sacado::Promote<base_expr_type_1,
3142  base_expr_type_2>::type base_expr_type;
3143 
3144  static const int num_args1 = ExprT1::num_args;
3145  static const int num_args2 = ExprT2::num_args;
3146  static const int num_args = num_args1 + num_args2;
3147 
3148  static const bool is_linear = false;
3149 
3151  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
3152  expr1(expr1_), expr2(expr2_) {}
3153 
3155  int size() const {
3156  int sz1 = expr1.size(), sz2 = expr2.size();
3157  return sz1 > sz2 ? sz1 : sz2;
3158  }
3159 
3160  template <int Arg>
3162  bool isActive() const {
3163  if (Arg < num_args1)
3164  return expr1.template isActive<Arg>();
3165  else
3166  return expr2.template isActive<Arg-num_args1>();
3167  }
3168 
3170  bool updateValue() const {
3171  return expr1.updateValue() && expr2.updateValue();
3172  }
3173 
3175  void cache() const {
3176  expr1.cache();
3177  expr2.cache();
3178  const value_type_1 v1 = expr1.val();
3179  const value_type_2 v2 = expr2.val();
3180  min_v1 = (v1 <= v2);
3181  v = min_v1 ? v1 : v2;
3182  }
3183 
3185  value_type val() const {
3186  return v;
3187  }
3188 
3190  void computePartials(const value_type& bar,
3191  value_type partials[]) const {
3192  if (num_args1 > 0) {
3193  if (min_v1)
3194  expr1.computePartials(bar, partials);
3195  else
3196  expr1.computePartials(value_type(0.0), partials);
3197  }
3198  if (num_args2 > 0) {
3199  if (min_v1)
3200  expr2.computePartials(value_type(0.0), partials+num_args1);
3201  else
3202  expr2.computePartials(bar, partials+num_args1);
3203  }
3204  }
3205 
3207  void getTangents(int i, value_type dots[]) const {
3208  expr1.getTangents(i, dots);
3209  expr2.getTangents(i, dots+num_args1);
3210  }
3211 
3212  template <int Arg>
3214  value_type getTangent(int i) const {
3215  if (Arg < num_args1)
3216  return expr1.template getTangent<Arg>(i);
3217  else
3218  return expr2.template getTangent<Arg-num_args1>(i);
3219  }
3220 
3222  bool isLinear() const {
3223  return false;
3224  }
3225 
3227  bool hasFastAccess() const {
3228  return expr1.hasFastAccess() && expr2.hasFastAccess();
3229  }
3230 
3232  const value_type dx(int i) const {
3233  return min_v1 ? expr1.dx(i) : expr2.dx(i);
3234  }
3235 
3237  const value_type fastAccessDx(int i) const {
3238  return min_v1 ? expr1.fastAccessDx(i) : expr2.fastAccessDx(i);
3239  }
3240 
3242  const value_type* getDx(int j) const {
3243  if (j < num_args1)
3244  return expr1.getDx(j);
3245  else
3246  return expr2.getDx(j-num_args1);
3247  }
3248 
3249  protected:
3250 
3251  const ExprT1& expr1;
3252  const ExprT2& expr2;
3253  mutable value_type v;
3254  mutable bool min_v1;
3255 
3256  };
3257 
3258  template <typename ExprT1, typename T2>
3259  class Expr< MinOp<ExprT1, ConstExpr<T2> > > {
3260 
3261  public:
3262 
3263  typedef ConstExpr<T2> ExprT2;
3264  typedef typename ExprT1::value_type value_type_1;
3265  typedef typename ExprT2::value_type value_type_2;
3266  typedef typename Sacado::Promote<value_type_1,
3267  value_type_2>::type value_type;
3268  typedef typename ExprT1::scalar_type scalar_type_1;
3269  typedef typename ExprT2::scalar_type scalar_type_2;
3270  typedef typename Sacado::Promote<scalar_type_1,
3271  scalar_type_2>::type scalar_type;
3272 
3273  typedef typename ExprT1::base_expr_type base_expr_type_1;
3274  typedef typename ExprT2::base_expr_type base_expr_type_2;
3275  typedef typename Sacado::Promote<base_expr_type_1,
3276  base_expr_type_2>::type base_expr_type;
3277 
3278  static const int num_args = ExprT1::num_args;
3279 
3280  static const bool is_linear = false;
3281 
3283  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
3284  expr1(expr1_), expr2(expr2_) {}
3285 
3287  int size() const {
3288  return expr1.size();
3289  }
3290 
3291  template <int Arg>
3293  bool isActive() const {
3294  return expr1.template isActive<Arg>();
3295  }
3296 
3298  bool updateValue() const {
3299  return expr1.updateValue();
3300  }
3301 
3303  void cache() const {
3304  expr1.cache();
3305  const value_type_1 v1 = expr1.val();
3306  const value_type_2 v2 = expr2.val();
3307  min_v1 = (v1 <= v2);
3308  v = min_v1 ? v1 : v2;
3309  }
3310 
3312  value_type val() const {
3313  return v;
3314  }
3315 
3317  void computePartials(const value_type& bar,
3318  value_type partials[]) const {
3319  if (min_v1)
3320  expr1.computePartials(bar, partials);
3321  else
3322  expr1.computePartials(value_type(0.0), partials);
3323  }
3324 
3326  void getTangents(int i, value_type dots[]) const {
3327  expr1.getTangents(i, dots);
3328  }
3329 
3330  template <int Arg>
3332  value_type getTangent(int i) const {
3333  return expr1.template getTangent<Arg>(i);
3334  }
3335 
3337  bool isLinear() const {
3338  return false;
3339  }
3340 
3342  bool hasFastAccess() const {
3343  return expr1.hasFastAccess();
3344  }
3345 
3347  const value_type dx(int i) const {
3348  return min_v1 ? expr1.dx(i) : value_type(0.0);
3349  }
3350 
3352  const value_type fastAccessDx(int i) const {
3353  return min_v1 ? expr1.fastAccessDx(i) : value_type(0.0);
3354  }
3355 
3357  const value_type* getDx(int j) const {
3358  return expr1.getDx(j);
3359  }
3360 
3361  protected:
3362 
3363  const ExprT1& expr1;
3364  ExprT2 expr2;
3365  mutable value_type v;
3366  mutable bool min_v1;
3367 
3368  };
3369 
3370  template <typename T1, typename ExprT2>
3371  class Expr< MinOp< ConstExpr<T1>,ExprT2> > {
3372 
3373  public:
3374 
3375  typedef ConstExpr<T1> ExprT1;
3376  typedef typename ExprT1::value_type value_type_1;
3377  typedef typename ExprT2::value_type value_type_2;
3378  typedef typename Sacado::Promote<value_type_1,
3379  value_type_2>::type value_type;
3380  typedef typename ExprT1::scalar_type scalar_type_1;
3381  typedef typename ExprT2::scalar_type scalar_type_2;
3382  typedef typename Sacado::Promote<scalar_type_1,
3383  scalar_type_2>::type scalar_type;
3384 
3385  typedef typename ExprT1::base_expr_type base_expr_type_1;
3386  typedef typename ExprT2::base_expr_type base_expr_type_2;
3387  typedef typename Sacado::Promote<base_expr_type_1,
3388  base_expr_type_2>::type base_expr_type;
3389 
3390  static const int num_args = ExprT2::num_args;
3391 
3392  static const bool is_linear = false;
3393 
3395  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
3396  expr1(expr1_), expr2(expr2_) {}
3397 
3399  int size() const {
3400  return expr2.size();
3401  }
3402 
3403  template <int Arg>
3405  bool isActive() const {
3406  return expr2.template isActive<Arg>();
3407  }
3408 
3410  bool updateValue() const {
3411  return expr2.updateValue();
3412  }
3413 
3415  void cache() const {
3416  expr2.cache();
3417  const value_type_1 v1 = expr1.val();
3418  const value_type_2 v2 = expr2.val();
3419  min_v1 = (v1 <= v2);
3420  v = min_v1 ? v1 : v2;
3421  }
3422 
3424  value_type val() const {
3425  return v;
3426  }
3427 
3429  void computePartials(const value_type& bar,
3430  value_type partials[]) const {
3431  if (min_v1)
3432  expr2.computePartials(value_type(0.0), partials);
3433  else
3434  expr2.computePartials(bar, partials);
3435  }
3436 
3438  void getTangents(int i, value_type dots[]) const {
3439  expr2.getTangents(i, dots);
3440  }
3441 
3442  template <int Arg>
3444  value_type getTangent(int i) const {
3445  return expr2.template getTangent<Arg>(i);
3446  }
3447 
3449  bool isLinear() const {
3450  return false;
3451  }
3452 
3454  bool hasFastAccess() const {
3455  return expr2.hasFastAccess();
3456  }
3457 
3459  const value_type dx(int i) const {
3460  return min_v1 ? value_type(0.0) : expr2.dx(i);
3461  }
3462 
3464  const value_type fastAccessDx(int i) const {
3465  return min_v1 ? value_type(0.0) : expr2.fastAccessDx(i);
3466  }
3467 
3469  const value_type* getDx(int j) const {
3470  return expr2.getDx(j);
3471  }
3472 
3473  protected:
3474 
3475  ExprT1 expr1;
3476  const ExprT2& expr2;
3477  mutable value_type v;
3478  mutable bool min_v1;
3479 
3480  };
3481 
3482  }
3483 
3484 }
3485 
3486 #define FAD_BINARYOP_MACRO(OPNAME,OP) \
3487 namespace Sacado { \
3488  namespace ELRCacheFad { \
3489  \
3490  template <typename T1, typename T2> \
3491  KOKKOS_INLINE_FUNCTION \
3492  SACADO_FAD_OP_ENABLE_EXPR_EXPR(OP) \
3493  OPNAME (const T1& expr1, const T2& expr2) \
3494  { \
3495  typedef OP< T1, T2 > expr_t; \
3496  \
3497  return Expr<expr_t>(expr1, expr2); \
3498  } \
3499  \
3500  template <typename T> \
3501  KOKKOS_INLINE_FUNCTION \
3502  Expr< OP< Expr<T>, Expr<T> > > \
3503  OPNAME (const Expr<T>& expr1, const Expr<T>& expr2) \
3504  { \
3505  typedef OP< Expr<T>, Expr<T> > expr_t; \
3506  \
3507  return Expr<expr_t>(expr1, expr2); \
3508  } \
3509  \
3510  template <typename T> \
3511  KOKKOS_INLINE_FUNCTION \
3512  Expr< OP< ConstExpr<typename Expr<T>::value_type>, \
3513  Expr<T> > > \
3514  OPNAME (const typename Expr<T>::value_type& c, \
3515  const Expr<T>& expr) \
3516  { \
3517  typedef ConstExpr<typename Expr<T>::value_type> ConstT; \
3518  typedef OP< ConstT, Expr<T> > expr_t; \
3519  \
3520  return Expr<expr_t>(ConstT(c), expr); \
3521  } \
3522  \
3523  template <typename T> \
3524  KOKKOS_INLINE_FUNCTION \
3525  Expr< OP< Expr<T>, \
3526  ConstExpr<typename Expr<T>::value_type> > > \
3527  OPNAME (const Expr<T>& expr, \
3528  const typename Expr<T>::value_type& c) \
3529  { \
3530  typedef ConstExpr<typename Expr<T>::value_type> ConstT; \
3531  typedef OP< Expr<T>, ConstT > expr_t; \
3532  \
3533  return Expr<expr_t>(expr, ConstT(c)); \
3534  } \
3535  \
3536  template <typename T> \
3537  KOKKOS_INLINE_FUNCTION \
3538  SACADO_FAD_OP_ENABLE_SCALAR_EXPR(OP) \
3539  OPNAME (const typename Expr<T>::scalar_type& c, \
3540  const Expr<T>& expr) \
3541  { \
3542  typedef ConstExpr<typename Expr<T>::scalar_type> ConstT; \
3543  typedef OP< ConstT, Expr<T> > expr_t; \
3544  \
3545  return Expr<expr_t>(ConstT(c), expr); \
3546  } \
3547  \
3548  template <typename T> \
3549  KOKKOS_INLINE_FUNCTION \
3550  SACADO_FAD_OP_ENABLE_EXPR_SCALAR(OP) \
3551  OPNAME (const Expr<T>& expr, \
3552  const typename Expr<T>::scalar_type& c) \
3553  { \
3554  typedef ConstExpr<typename Expr<T>::scalar_type> ConstT; \
3555  typedef OP< Expr<T>, ConstT > expr_t; \
3556  \
3557  return Expr<expr_t>(expr, ConstT(c)); \
3558  } \
3559  } \
3560 }
3561 
3562 
3563 FAD_BINARYOP_MACRO(operator+, AdditionOp)
3566 FAD_BINARYOP_MACRO(operator/, DivisionOp)
3571 
3572 #undef FAD_BINARYOP_MACRO
3573 
3574 //-------------------------- Relational Operators -----------------------
3575 
3576 #define FAD_RELOP_MACRO(OP) \
3577 namespace Sacado { \
3578  namespace ELRCacheFad { \
3579  template <typename ExprT1, typename ExprT2> \
3580  KOKKOS_INLINE_FUNCTION \
3581  bool \
3582  operator OP (const Expr<ExprT1>& expr1, \
3583  const Expr<ExprT2>& expr2) \
3584  { \
3585  expr1.cache(); \
3586  expr2.cache(); \
3587  return expr1.val() OP expr2.val(); \
3588  } \
3589  \
3590  template <typename ExprT2> \
3591  KOKKOS_INLINE_FUNCTION \
3592  bool \
3593  operator OP (const typename Expr<ExprT2>::value_type& a, \
3594  const Expr<ExprT2>& expr2) \
3595  { \
3596  expr2.cache(); \
3597  return a OP expr2.val(); \
3598  } \
3599  \
3600  template <typename ExprT1> \
3601  KOKKOS_INLINE_FUNCTION \
3602  bool \
3603  operator OP (const Expr<ExprT1>& expr1, \
3604  const typename Expr<ExprT1>::value_type& b) \
3605  { \
3606  expr1.cache(); \
3607  return expr1.val() OP b; \
3608  } \
3609  } \
3610 }
3611 
3612 FAD_RELOP_MACRO(==)
3613 FAD_RELOP_MACRO(!=)
3614 FAD_RELOP_MACRO(<)
3615 FAD_RELOP_MACRO(>)
3616 FAD_RELOP_MACRO(<=)
3617 FAD_RELOP_MACRO(>=)
3618 FAD_RELOP_MACRO(<<=)
3619 FAD_RELOP_MACRO(>>=)
3620 FAD_RELOP_MACRO(&)
3621 FAD_RELOP_MACRO(|)
3622 
3623 #undef FAD_RELOP_MACRO
3624 
3625 namespace Sacado {
3626 
3627  namespace ELRCacheFad {
3628 
3629  template <typename ExprT>
3631  bool operator ! (const Expr<ExprT>& expr)
3632  {
3633  expr.cache();
3634  return ! expr.val();
3635  }
3636 
3637  } // namespace ELRCacheFad
3638 
3639 } // namespace Sacado
3640 
3641 //-------------------------- Boolean Operators -----------------------
3642 namespace Sacado {
3643 
3644  namespace ELRCacheFad {
3645 
3646  template <typename ExprT>
3648  bool toBool(const Expr<ExprT>& x) {
3649  x.cache();
3650  bool is_zero = (x.val() == 0.0);
3651  for (int i=0; i<x.size(); i++)
3652  is_zero = is_zero && (x.dx(i) == 0.0);
3653  return !is_zero;
3654  }
3655 
3656  } // namespace Fad
3657 
3658 } // namespace Sacado
3659 
3660 #define FAD_BOOL_MACRO(OP) \
3661 namespace Sacado { \
3662  namespace ELRCacheFad { \
3663  template <typename ExprT1, typename ExprT2> \
3664  KOKKOS_INLINE_FUNCTION \
3665  bool \
3666  operator OP (const Expr<ExprT1>& expr1, \
3667  const Expr<ExprT2>& expr2) \
3668  { \
3669  return toBool(expr1) OP toBool(expr2); \
3670  } \
3671  \
3672  template <typename ExprT2> \
3673  KOKKOS_INLINE_FUNCTION \
3674  bool \
3675  operator OP (const typename Expr<ExprT2>::value_type& a, \
3676  const Expr<ExprT2>& expr2) \
3677  { \
3678  return a OP toBool(expr2); \
3679  } \
3680  \
3681  template <typename ExprT1> \
3682  KOKKOS_INLINE_FUNCTION \
3683  bool \
3684  operator OP (const Expr<ExprT1>& expr1, \
3685  const typename Expr<ExprT1>::value_type& b) \
3686  { \
3687  return toBool(expr1) OP b; \
3688  } \
3689  } \
3690 }
3691 
3692 FAD_BOOL_MACRO(&&)
3693 FAD_BOOL_MACRO(||)
3694 
3695 #undef FAD_BOOL_MACRO
3696 
3697 //-------------------------- I/O Operators -----------------------
3698 
3699 namespace Sacado {
3700 
3701  namespace ELRCacheFad {
3702 
3703  template <typename ExprT>
3704  std::ostream& operator << (std::ostream& os, const Expr<ExprT>& x) {
3705  os << x.val() << " [";
3706 
3707  for (int i=0; i< x.size(); i++) {
3708  os << " " << x.dx(i);
3709  }
3710 
3711  os << " ]";
3712  return os;
3713  }
3714 
3715  } // namespace Fad
3716 
3717 } // namespace Sacado
3718 
3719 #endif // SACADO_CACHEFAD_OPS_HPP
KOKKOS_INLINE_FUNCTION const value_type * getDx(int j) const
cbrt(expr.val())
KOKKOS_INLINE_FUNCTION bool isLinear() const
expr expr AdditionOp
expr expr SinOp
KOKKOS_INLINE_FUNCTION const value_type * getDx(int j) const
expr2 expr1 expr2 expr2 c *expr2 c *expr1 c *expr2 c *expr1 MaxOp
asinh(expr.val())
expr expr expr1 expr1 expr2 expr1 expr1 c expr2 expr1 expr2 expr1 expr2 expr1 expr1 expr1 expr2 expr1 expr1 c expr2 expr1 expr2 expr1 expr2 expr1 MultiplicationOp
KOKKOS_INLINE_FUNCTION Expr< AbsOp< Expr< T > > > abs(const Expr< T > &expr)
KOKKOS_INLINE_FUNCTION bool isLinear() const
#define FAD_UNARYOP_MACRO(OPNAME, OP, USING, VALUE, DX, FASTACCESSDX)
KOKKOS_INLINE_FUNCTION Expr< FAbsOp< Expr< T > > > fabs(const Expr< T > &expr)
asin(expr.val())
cosh(expr.val())
KOKKOS_INLINE_FUNCTION value_type val() const
expr expr dx(i)
abs(expr.val())
KOKKOS_INLINE_FUNCTION value_type val() const
KOKKOS_INLINE_FUNCTION void getTangents(int i, value_type dots[]) const
expr2 expr1 expr2 expr2 c *expr2 c *expr1 c *expr2 c *expr1 MinOp
atanh(expr.val())
KOKKOS_INLINE_FUNCTION Expr(const ExprT &expr_)
expr expr expr1 expr1 expr2 expr1 expr1 c expr2 expr1 expr2 expr1 expr2 expr1 expr1 expr1 expr2 expr1 expr1 c expr2 expr1 expr2 expr1 expr2 expr1 expr1 expr1 expr1 expr1 expr1 c *expr2 expr1 c *expr2 expr1 c *expr2 expr1 expr1 expr1 expr2 expr1 expr1 c expr2 expr1 expr2 expr1 expr2 expr1 Atan2Op
expr expr CoshOp
expr expr ATanhOp
KOKKOS_INLINE_FUNCTION const value_type dx(int i) const
expr expr TanhOp
KOKKOS_INLINE_FUNCTION const value_type fastAccessDx(int i) const
KOKKOS_INLINE_FUNCTION value_type getTangent(int i) const
expr expr SqrtOp
expr expr ASinhOp
expr bar
KOKKOS_INLINE_FUNCTION void getTangents(int i, value_type dots[]) const
atan(expr.val())
KOKKOS_INLINE_FUNCTION Expr(const ExprT &expr_)
KOKKOS_INLINE_FUNCTION bool hasFastAccess() const
expr expr expr1 expr1 expr2 expr1 expr1 c expr2 expr1 expr2 expr1 expr2 expr1 expr1 expr1 expr2 expr1 expr1 c expr2 expr1 expr2 expr1 expr2 expr1 expr1 expr1 expr1 expr1 expr1 c *expr2 expr1 c *expr2 expr1 c *expr2 expr1 DivisionOp
KOKKOS_INLINE_FUNCTION mpl::enable_if_c< ExprLevel< Expr< T1 > >::value==ExprLevel< Expr< T2 > >::value, Expr< PowerOp< Expr< T1 >, Expr< T2 > > > >::type pow(const Expr< T1 > &expr1, const Expr< T2 > &expr2)
KOKKOS_INLINE_FUNCTION const value_type fastAccessDx(int i) const
KOKKOS_INLINE_FUNCTION void computePartials(const value_type &bar, value_type partials[]) const
expr val()
#define KOKKOS_INLINE_FUNCTION
KOKKOS_INLINE_FUNCTION void cache() const
tanh(expr.val())
expr expr CosOp
KOKKOS_INLINE_FUNCTION bool operator!(const Expr< ExprT > &expr)
KOKKOS_INLINE_FUNCTION value_type getTangent(int i) const
expr expr ATanOp
SimpleFad< ValueT > min(const SimpleFad< ValueT > &a, const SimpleFad< ValueT > &b)
expr expr ACosOp
#define FAD_RELOP_MACRO(OP)
KOKKOS_INLINE_FUNCTION bool updateValue() const
sqrt(expr.val())
Wrapper for a generic expression template.
sinh(expr.val())
KOKKOS_INLINE_FUNCTION value_type val() const
tan(expr.val())
KOKKOS_INLINE_FUNCTION const value_type fastAccessDx(int i) const
KOKKOS_INLINE_FUNCTION bool isActive() const
KOKKOS_INLINE_FUNCTION bool updateValue() const
#define FAD_BOOL_MACRO(OP)
KOKKOS_INLINE_FUNCTION bool toBool(const Expr< ExprT > &x)
atan2(expr1.val(), expr2.val())
KOKKOS_INLINE_FUNCTION void computePartials(const value_type &bar, value_type partials[]) const
sin(expr.val())
KOKKOS_INLINE_FUNCTION Expr(const ExprT &expr_)
KOKKOS_INLINE_FUNCTION const value_type dx(int i) const
expr expr expr fastAccessDx(i)) FAD_UNARYOP_MACRO(exp
KOKKOS_INLINE_FUNCTION bool hasFastAccess() const
KOKKOS_INLINE_FUNCTION const value_type * getDx(int j) const
KOKKOS_INLINE_FUNCTION void computePartials(const value_type &bar, value_type partials[]) const
KOKKOS_INLINE_FUNCTION Expr< UnaryPlusOp< Expr< T > > > operator+(const Expr< T > &expr)
log(expr.val())
expr expr ACoshOp
KOKKOS_INLINE_FUNCTION bool isActive() const
KOKKOS_INLINE_FUNCTION const value_type fastAccessDx(int i) const
expr expr Log10Op
expr expr SinhOp
KOKKOS_INLINE_FUNCTION void getTangents(int i, value_type dots[]) const
KOKKOS_INLINE_FUNCTION const value_type dx(int i) const
acosh(expr.val())
acos(expr.val())
SimpleFad< ValueT > max(const SimpleFad< ValueT > &a, const SimpleFad< ValueT > &b)
expr expr ASinOp
KOKKOS_INLINE_FUNCTION const value_type * getDx(int j) const
KOKKOS_INLINE_FUNCTION value_type val() const
KOKKOS_INLINE_FUNCTION void cache() const
KOKKOS_INLINE_FUNCTION value_type getTangent(int i) const
KOKKOS_INLINE_FUNCTION void getTangents(int i, value_type dots[]) const
exp(expr.val())
expr expr expr1 expr1 expr2 expr1 expr1 c expr2 expr1 expr2 expr1 expr2 expr1 SubtractionOp
#define FAD_BINARYOP_MACRO(OPNAME, OP)
expr expr expr ExpOp
fabs(expr.val())
KOKKOS_INLINE_FUNCTION Expr(const ExprT &expr_)
expr expr TanOp
KOKKOS_INLINE_FUNCTION void computePartials(const value_type &bar, value_type partials[]) const
log10(expr.val())
Base template specification for Promote.
cos(expr.val())
KOKKOS_INLINE_FUNCTION const value_type dx(int i) const
KOKKOS_INLINE_FUNCTION Expr< UnaryMinusOp< Expr< T > > > operator-(const Expr< T > &expr)
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 PowerOp