Sacado Package Browser (Single Doxygen Collection)  Version of the Day
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  explicit 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  explicit 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  explicit 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  explicit 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  SACADO_INLINE_FUNCTION \
500  explicit Expr(const ExprT& expr_) : expr(expr_) {} \
501  \
502  SACADO_INLINE_FUNCTION \
503  int size() const { return expr.size(); } \
504  \
505  template <int Arg> \
506  SACADO_INLINE_FUNCTION \
507  bool isActive() const { return expr.template isActive<Arg>(); } \
508  \
509  SACADO_INLINE_FUNCTION \
510  bool updateValue() const { return expr.updateValue(); } \
511  \
512  SACADO_INLINE_FUNCTION \
513  void cache() const { \
514  expr.cache(); \
515  v = expr.val(); \
516  PARTIAL; \
517  } \
518  \
519  SACADO_INLINE_FUNCTION \
520  value_type val() const { \
521  return VALUE; \
522  } \
523  \
524  SACADO_INLINE_FUNCTION \
525  void computePartials(const value_type& bar, \
526  value_type partials[]) const { \
527  expr.computePartials(bar*a, partials); \
528  } \
529  \
530  SACADO_INLINE_FUNCTION \
531  void getTangents(int i, value_type dots[]) const { \
532  expr.getTangents(i, dots); } \
533  \
534  template <int Arg> \
535  SACADO_INLINE_FUNCTION \
536  value_type getTangent(int i) const { \
537  return expr.template getTangent<Arg>(i); \
538  } \
539  \
540  SACADO_INLINE_FUNCTION \
541  bool isLinear() const { \
542  return false; \
543  } \
544  \
545  SACADO_INLINE_FUNCTION \
546  bool hasFastAccess() const { \
547  return expr.hasFastAccess(); \
548  } \
549  \
550  SACADO_INLINE_FUNCTION \
551  const value_type dx(int i) const { \
552  return expr.dx(i)*a; \
553  } \
554  \
555  SACADO_INLINE_FUNCTION \
556  const value_type fastAccessDx(int i) const { \
557  return expr.fastAccessDx(i)*a; \
558  } \
559  \
560  SACADO_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  SACADO_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 = (v == value_type(0.0) ? value_type(0.0) : value_type(scalar_type(1.0)/(scalar_type(2.0)*std::sqrt(v)))),
603  std::sqrt(v))
606  a = -std::sin(v),
607  std::cos(v))
610  a = std::cos(v),
611  std::sin(v))
614  a = scalar_type(1.0)+std::tan(v)*std::tan(v),
615  std::tan(v))
618  a = scalar_type(-1.0)/std::sqrt(scalar_type(1.0)-v*v),
619  std::acos(v))
622  a = scalar_type(1.0)/std::sqrt(scalar_type(1.0)-v*v),
623  std::asin(v))
626  a = scalar_type(1.0)/(scalar_type(1.0)+v*v),
627  std::atan(v))
630  a = std::sinh(v),
631  std::cosh(v))
634  a = std::cosh(v),
635  std::sinh(v))
638  a = scalar_type(1.0)-std::tanh(v)*std::tanh(v),
639  std::tanh(v))
642  a = scalar_type(1.0)/std::sqrt((v-scalar_type(1.0))*(v+scalar_type(1.0))),
643  std::acosh(v))
646  a = scalar_type(1.0)/std::sqrt(scalar_type(1.0)+v*v),
647  std::asinh(v))
650  a = scalar_type(1.0)/(scalar_type(1.0)-v*v),
651  std::atanh(v))
652 #ifdef HAVE_SACADO_CXX11
654  CbrtOp,
655  a = scalar_type(1.0)/(scalar_type(3.0)*std::cbrt(v*v)),
656  std::cbrt(v))
657 #endif
658 
659 #undef FAD_UNARYOP_MACRO
660 
661 //
662 // Binary operators
663 //
664 namespace Sacado {
665  namespace ELRCacheFad {
666 
667  //
668  // AdditionOp
669  //
670 
671  template <typename ExprT1, typename ExprT2>
672  class AdditionOp {};
673 
674  template <typename ExprT1, typename ExprT2>
675  class Expr< AdditionOp<ExprT1,ExprT2> > {
676 
677  public:
678 
679  typedef typename ExprT1::value_type value_type_1;
680  typedef typename ExprT2::value_type value_type_2;
681  typedef typename Sacado::Promote<value_type_1,
682  value_type_2>::type value_type;
683  typedef typename ExprT1::scalar_type scalar_type_1;
684  typedef typename ExprT2::scalar_type scalar_type_2;
685  typedef typename Sacado::Promote<scalar_type_1,
686  scalar_type_2>::type scalar_type;
687 
688  typedef typename ExprT1::base_expr_type base_expr_type_1;
689  typedef typename ExprT2::base_expr_type base_expr_type_2;
690  typedef typename Sacado::Promote<base_expr_type_1,
691  base_expr_type_2>::type base_expr_type;
692 
693  static const int num_args1 = ExprT1::num_args;
694  static const int num_args2 = ExprT2::num_args;
695  static const int num_args = num_args1 + num_args2;
696 
697  static const bool is_linear = ExprT1::is_linear && ExprT2::is_linear;
698 
700  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
701  expr1(expr1_), expr2(expr2_) {}
702 
704  int size() const {
705  int sz1 = expr1.size(), sz2 = expr2.size();
706  return sz1 > sz2 ? sz1 : sz2;
707  }
708 
709  template <int Arg>
711  bool isActive() const {
712  if (Arg < num_args1)
713  return expr1.template isActive<Arg>();
714  else
715  return expr2.template isActive<Arg-num_args1>();
716  }
717 
719  bool updateValue() const {
720  return expr1.updateValue() && expr2.updateValue();
721  }
722 
724  void cache() const {
725  expr1.cache();
726  expr2.cache();
727  }
728 
730  value_type val() const {
731  return expr1.val()+expr2.val();
732  }
733 
735  void computePartials(const value_type& bar,
736  value_type partials[]) const {
737  if (num_args1 > 0)
738  expr1.computePartials(bar, partials);
739  if (num_args2 > 0)
740  expr2.computePartials(bar, partials+num_args1);
741  }
742 
744  void getTangents(int i, value_type dots[]) const {
745  expr1.getTangents(i, dots);
746  expr2.getTangents(i, dots+num_args1);
747  }
748 
749  template <int Arg>
751  value_type getTangent(int i) const {
752  if (Arg < num_args1)
753  return expr1.template getTangent<Arg>(i);
754  else
755  return expr2.template getTangent<Arg-num_args1>(i);
756  }
757 
759  bool isLinear() const {
760  return expr1.isLinear() && expr2.isLinear();
761  }
762 
764  bool hasFastAccess() const {
765  return expr1.hasFastAccess() && expr2.hasFastAccess();
766  }
767 
769  const value_type dx(int i) const {
770  return expr1.dx(i) + expr2.dx(i);
771  }
772 
774  const value_type fastAccessDx(int i) const {
775  return expr1.fastAccessDx(i) + expr2.fastAccessDx(i);
776  }
777 
779  const value_type* getDx(int j) const {
780  if (j < num_args1)
781  return expr1.getDx(j);
782  else
783  return expr2.getDx(j-num_args1);
784  }
785 
786  protected:
787 
788  const ExprT1& expr1;
789  const ExprT2& expr2;
790 
791  };
792 
793  template <typename ExprT1, typename T2>
794  class Expr< AdditionOp<ExprT1, ConstExpr<T2> > > {
795 
796  public:
797 
798  typedef ConstExpr<T2> ExprT2;
799  typedef typename ExprT1::value_type value_type_1;
800  typedef typename ExprT2::value_type value_type_2;
801  typedef typename Sacado::Promote<value_type_1,
802  value_type_2>::type value_type;
803  typedef typename ExprT1::scalar_type scalar_type_1;
804  typedef typename ExprT2::scalar_type scalar_type_2;
805  typedef typename Sacado::Promote<scalar_type_1,
806  scalar_type_2>::type scalar_type;
807 
808  typedef typename ExprT1::base_expr_type base_expr_type_1;
809  typedef typename ExprT2::base_expr_type base_expr_type_2;
810  typedef typename Sacado::Promote<base_expr_type_1,
811  base_expr_type_2>::type base_expr_type;
812 
813  static const int num_args = ExprT1::num_args;
814 
815  static const bool is_linear = ExprT1::is_linear;
816 
818  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
819  expr1(expr1_), expr2(expr2_) {}
820 
822  int size() const {
823  return expr1.size();
824  }
825 
826  template <int Arg>
828  bool isActive() const {
829  return expr1.template isActive<Arg>();
830  }
831 
833  bool updateValue() const {
834  return expr1.updateValue();
835  }
836 
838  void cache() const {
839  expr1.cache();
840  }
841 
843  value_type val() const {
844  return expr1.val() + expr2.val();
845  }
846 
848  void computePartials(const value_type& bar,
849  value_type partials[]) const {
850  expr1.computePartials(bar, partials);
851  }
852 
854  void getTangents(int i, value_type dots[]) const {
855  expr1.getTangents(i, dots);
856  }
857 
858  template <int Arg>
860  value_type getTangent(int i) const {
861  return expr1.template getTangent<Arg>(i);
862  }
863 
865  bool isLinear() const {
866  return expr1.isLinear();
867  }
868 
870  bool hasFastAccess() const {
871  return expr1.hasFastAccess();
872  }
873 
875  const value_type dx(int i) const {
876  return expr1.dx(i);
877  }
878 
880  const value_type fastAccessDx(int i) const {
881  return expr1.fastAccessDx(i);
882  }
883 
885  const value_type* getDx(int j) const {
886  return expr1.getDx(j);
887  }
888 
889  protected:
890 
891  const ExprT1& expr1;
892  ExprT2 expr2;
893 
894  };
895 
896  template <typename T1, typename ExprT2>
897  class Expr< AdditionOp< ConstExpr<T1>,ExprT2> > {
898 
899  public:
900 
901  typedef ConstExpr<T1> ExprT1;
902  typedef typename ExprT1::value_type value_type_1;
903  typedef typename ExprT2::value_type value_type_2;
904  typedef typename Sacado::Promote<value_type_1,
905  value_type_2>::type value_type;
906  typedef typename ExprT1::scalar_type scalar_type_1;
907  typedef typename ExprT2::scalar_type scalar_type_2;
908  typedef typename Sacado::Promote<scalar_type_1,
909  scalar_type_2>::type scalar_type;
910 
911  typedef typename ExprT1::base_expr_type base_expr_type_1;
912  typedef typename ExprT2::base_expr_type base_expr_type_2;
913  typedef typename Sacado::Promote<base_expr_type_1,
914  base_expr_type_2>::type base_expr_type;
915 
916  static const int num_args = ExprT2::num_args;
917 
918  static const bool is_linear = ExprT2::is_linear;
919 
921  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
922  expr1(expr1_), expr2(expr2_) {}
923 
925  int size() const {
926  return expr2.size();
927  }
928 
929  template <int Arg>
931  bool isActive() const {
932  return expr2.template isActive<Arg>();
933  }
934 
936  bool updateValue() const {
937  return expr2.updateValue();
938  }
939 
941  void cache() const {
942  expr2.cache();
943  }
944 
946  value_type val() const {
947  return expr1.val() + expr2.val();
948  }
949 
951  void computePartials(const value_type& bar,
952  value_type partials[]) const {
953  expr2.computePartials(bar, partials);
954  }
955 
957  void getTangents(int i, value_type dots[]) const {
958  expr2.getTangents(i, dots);
959  }
960 
961  template <int Arg>
963  value_type getTangent(int i) const {
964  return expr2.template getTangent<Arg>(i);
965  }
966 
968  bool isLinear() const {
969  return expr2.isLinear();
970  }
971 
973  bool hasFastAccess() const {
974  return expr2.hasFastAccess();
975  }
976 
978  const value_type dx(int i) const {
979  return expr2.dx(i);
980  }
981 
983  const value_type fastAccessDx(int i) const {
984  return expr2.fastAccessDx(i);
985  }
986 
988  const value_type* getDx(int j) const {
989  return expr2.getDx(j);
990  }
991 
992  protected:
993 
994  ExprT1 expr1;
995  const ExprT2& expr2;
996 
997  };
998 
999  //
1000  // SubtractionOp
1001  //
1002 
1003  template <typename ExprT1, typename ExprT2>
1004  class SubtractionOp {};
1005 
1006  template <typename ExprT1, typename ExprT2>
1007  class Expr< SubtractionOp<ExprT1,ExprT2> > {
1008 
1009  public:
1010 
1011  typedef typename ExprT1::value_type value_type_1;
1012  typedef typename ExprT2::value_type value_type_2;
1013  typedef typename Sacado::Promote<value_type_1,
1014  value_type_2>::type value_type;
1015  typedef typename ExprT1::scalar_type scalar_type_1;
1016  typedef typename ExprT2::scalar_type scalar_type_2;
1017  typedef typename Sacado::Promote<scalar_type_1,
1018  scalar_type_2>::type scalar_type;
1019 
1020  typedef typename ExprT1::base_expr_type base_expr_type_1;
1021  typedef typename ExprT2::base_expr_type base_expr_type_2;
1022  typedef typename Sacado::Promote<base_expr_type_1,
1023  base_expr_type_2>::type base_expr_type;
1024 
1025  static const int num_args1 = ExprT1::num_args;
1026  static const int num_args2 = ExprT2::num_args;
1027  static const int num_args = num_args1 + num_args2;
1028 
1029  static const bool is_linear = ExprT1::is_linear && ExprT2::is_linear;
1030 
1032  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
1033  expr1(expr1_), expr2(expr2_) {}
1034 
1036  int size() const {
1037  int sz1 = expr1.size(), sz2 = expr2.size();
1038  return sz1 > sz2 ? sz1 : sz2;
1039  }
1040 
1041  template <int Arg>
1043  bool isActive() const {
1044  if (Arg < num_args1)
1045  return expr1.template isActive<Arg>();
1046  else
1047  return expr2.template isActive<Arg-num_args1>();
1048  }
1049 
1051  bool updateValue() const {
1052  return expr1.updateValue() && expr2.updateValue();
1053  }
1054 
1056  void cache() const {
1057  expr1.cache();
1058  expr2.cache();
1059  }
1060 
1062  value_type val() const {
1063  return expr1.val()-expr2.val();
1064  }
1065 
1067  void computePartials(const value_type& bar,
1068  value_type partials[]) const {
1069  if (num_args1 > 0)
1070  expr1.computePartials(bar, partials);
1071  if (num_args2 > 0)
1072  expr2.computePartials(-bar, partials+num_args1);
1073  }
1074 
1076  void getTangents(int i, value_type dots[]) const {
1077  expr1.getTangents(i, dots);
1078  expr2.getTangents(i, dots+num_args1);
1079  }
1080 
1081  template <int Arg>
1083  value_type getTangent(int i) const {
1084  if (Arg < num_args1)
1085  return expr1.template getTangent<Arg>(i);
1086  else
1087  return expr2.template getTangent<Arg-num_args1>(i);
1088  }
1089 
1091  bool isLinear() const {
1092  return expr1.isLinear() && expr2.isLinear();
1093  }
1094 
1096  bool hasFastAccess() const {
1097  return expr1.hasFastAccess() && expr2.hasFastAccess();
1098  }
1099 
1101  const value_type dx(int i) const {
1102  return expr1.dx(i) - expr2.dx(i);
1103  }
1104 
1106  const value_type fastAccessDx(int i) const {
1107  return expr1.fastAccessDx(i) - expr2.fastAccessDx(i);
1108  }
1109 
1111  const value_type* getDx(int j) const {
1112  if (j < num_args1)
1113  return expr1.getDx(j);
1114  else
1115  return expr2.getDx(j-num_args1);
1116  }
1117 
1118  protected:
1119 
1120  const ExprT1& expr1;
1121  const ExprT2& expr2;
1122 
1123  };
1124 
1125  template <typename ExprT1, typename T2>
1126  class Expr< SubtractionOp<ExprT1, ConstExpr<T2> > > {
1127 
1128  public:
1129 
1130  typedef ConstExpr<T2> ExprT2;
1131  typedef typename ExprT1::value_type value_type_1;
1132  typedef typename ExprT2::value_type value_type_2;
1133  typedef typename Sacado::Promote<value_type_1,
1134  value_type_2>::type value_type;
1135  typedef typename ExprT1::scalar_type scalar_type_1;
1136  typedef typename ExprT2::scalar_type scalar_type_2;
1137  typedef typename Sacado::Promote<scalar_type_1,
1138  scalar_type_2>::type scalar_type;
1139 
1140  typedef typename ExprT1::base_expr_type base_expr_type_1;
1141  typedef typename ExprT2::base_expr_type base_expr_type_2;
1142  typedef typename Sacado::Promote<base_expr_type_1,
1143  base_expr_type_2>::type base_expr_type;
1144 
1145  static const int num_args = ExprT1::num_args;
1146 
1147  static const bool is_linear = ExprT1::is_linear;
1148 
1150  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
1151  expr1(expr1_), expr2(expr2_) {}
1152 
1154  int size() const {
1155  return expr1.size();
1156  }
1157 
1158  template <int Arg>
1160  bool isActive() const {
1161  return expr1.template isActive<Arg>();
1162  }
1163 
1165  bool updateValue() const {
1166  return expr1.updateValue();
1167  }
1168 
1170  void cache() const {
1171  expr1.cache();
1172  }
1173 
1175  value_type val() const {
1176  return expr1.val() - expr2.val();
1177  }
1178 
1180  void computePartials(const value_type& bar,
1181  value_type partials[]) const {
1182  expr1.computePartials(bar, partials);
1183  }
1184 
1186  void getTangents(int i, value_type dots[]) const {
1187  expr1.getTangents(i, dots);
1188  }
1189 
1190  template <int Arg>
1192  value_type getTangent(int i) const {
1193  return expr1.template getTangent<Arg>(i);
1194  }
1195 
1197  bool isLinear() const {
1198  return expr1.isLinear();
1199  }
1200 
1202  bool hasFastAccess() const {
1203  return expr1.hasFastAccess();
1204  }
1205 
1207  const value_type dx(int i) const {
1208  return expr1.dx(i);
1209  }
1210 
1212  const value_type fastAccessDx(int i) const {
1213  return expr1.fastAccessDx(i);
1214  }
1215 
1217  const value_type* getDx(int j) const {
1218  return expr1.getDx(j);
1219  }
1220 
1221  protected:
1222 
1223  const ExprT1& expr1;
1224  ExprT2 expr2;
1225 
1226  };
1227 
1228  template <typename T1, typename ExprT2>
1229  class Expr< SubtractionOp< ConstExpr<T1>,ExprT2> > {
1230 
1231  public:
1232 
1233  typedef ConstExpr<T1> ExprT1;
1234  typedef typename ExprT1::value_type value_type_1;
1235  typedef typename ExprT2::value_type value_type_2;
1236  typedef typename Sacado::Promote<value_type_1,
1237  value_type_2>::type value_type;
1238  typedef typename ExprT1::scalar_type scalar_type_1;
1239  typedef typename ExprT2::scalar_type scalar_type_2;
1240  typedef typename Sacado::Promote<scalar_type_1,
1241  scalar_type_2>::type scalar_type;
1242 
1243  typedef typename ExprT1::base_expr_type base_expr_type_1;
1244  typedef typename ExprT2::base_expr_type base_expr_type_2;
1245  typedef typename Sacado::Promote<base_expr_type_1,
1246  base_expr_type_2>::type base_expr_type;
1247 
1248  static const int num_args = ExprT2::num_args;
1249 
1250  static const bool is_linear = ExprT2::is_linear;
1251 
1253  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
1254  expr1(expr1_), expr2(expr2_) {}
1255 
1257  int size() const {
1258  return expr2.size();
1259  }
1260 
1261  template <int Arg>
1263  bool isActive() const {
1264  return expr2.template isActive<Arg>();
1265  }
1266 
1268  bool updateValue() const {
1269  return expr2.updateValue();
1270  }
1271 
1273  void cache() const {
1274  expr2.cache();
1275  }
1276 
1278  value_type val() const {
1279  return expr1.val() - expr2.val();
1280  }
1281 
1283  void computePartials(const value_type& bar,
1284  value_type partials[]) const {
1285  expr2.computePartials(-bar, partials);
1286  }
1287 
1289  void getTangents(int i, value_type dots[]) const {
1290  expr2.getTangents(i, dots);
1291  }
1292 
1293  template <int Arg>
1295  value_type getTangent(int i) const {
1296  return expr2.template getTangent<Arg>(i);
1297  }
1298 
1300  bool isLinear() const {
1301  return expr2.isLinear();
1302  }
1303 
1305  bool hasFastAccess() const {
1306  return expr2.hasFastAccess();
1307  }
1308 
1310  const value_type dx(int i) const {
1311  return -expr2.dx(i);
1312  }
1313 
1315  const value_type fastAccessDx(int i) const {
1316  return -expr2.fastAccessDx(i);
1317  }
1318 
1320  const value_type* getDx(int j) const {
1321  return expr2.getDx(j);
1322  }
1323 
1324  protected:
1325 
1326  ExprT1 expr1;
1327  const ExprT2& expr2;
1328 
1329  };
1330 
1331  //
1332  // MultiplicationOp
1333  //
1334 
1335  template <typename ExprT1, typename ExprT2>
1336  class MultiplicationOp {};
1337 
1338  template <typename ExprT1, typename ExprT2>
1339  class Expr< MultiplicationOp<ExprT1,ExprT2> > {
1340 
1341  public:
1342 
1343  typedef typename ExprT1::value_type value_type_1;
1344  typedef typename ExprT2::value_type value_type_2;
1345  typedef typename Sacado::Promote<value_type_1,
1346  value_type_2>::type value_type;
1347  typedef typename ExprT1::scalar_type scalar_type_1;
1348  typedef typename ExprT2::scalar_type scalar_type_2;
1349  typedef typename Sacado::Promote<scalar_type_1,
1350  scalar_type_2>::type scalar_type;
1351 
1352  typedef typename ExprT1::base_expr_type base_expr_type_1;
1353  typedef typename ExprT2::base_expr_type base_expr_type_2;
1354  typedef typename Sacado::Promote<base_expr_type_1,
1355  base_expr_type_2>::type base_expr_type;
1356 
1357  static const int num_args1 = ExprT1::num_args;
1358  static const int num_args2 = ExprT2::num_args;
1359  static const int num_args = num_args1 + num_args2;
1360 
1361  static const bool is_linear = false;
1362 
1364  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
1365  expr1(expr1_), expr2(expr2_) {}
1366 
1368  int size() const {
1369  int sz1 = expr1.size(), sz2 = expr2.size();
1370  return sz1 > sz2 ? sz1 : sz2;
1371  }
1372 
1373  template <int Arg>
1375  bool isActive() const {
1376  if (Arg < num_args1)
1377  return expr1.template isActive<Arg>();
1378  else
1379  return expr2.template isActive<Arg-num_args1>();
1380  }
1381 
1383  bool updateValue() const {
1384  return expr1.updateValue() && expr2.updateValue();
1385  }
1386 
1388  void cache() const {
1389  expr1.cache();
1390  expr2.cache();
1391  v1 = expr1.val();
1392  v2 = expr2.val();
1393  }
1394 
1396  value_type val() const {
1397  return v1*v2;
1398  }
1399 
1401  void computePartials(const value_type& bar,
1402  value_type partials[]) const {
1403  if (num_args1 > 0)
1404  expr1.computePartials(bar*v2, partials);
1405  if (num_args2 > 0)
1406  expr2.computePartials(bar*v1, partials+num_args1);
1407  }
1408 
1410  void getTangents(int i, value_type dots[]) const {
1411  expr1.getTangents(i, dots);
1412  expr2.getTangents(i, dots+num_args1);
1413  }
1414 
1415  template <int Arg>
1417  value_type getTangent(int i) const {
1418  if (Arg < num_args1)
1419  return expr1.template getTangent<Arg>(i);
1420  else
1421  return expr2.template getTangent<Arg-num_args1>(i);
1422  }
1423 
1425  bool isLinear() const {
1426  return false;
1427  }
1428 
1430  bool hasFastAccess() const {
1431  return expr1.hasFastAccess() && expr2.hasFastAccess();
1432  }
1433 
1435  const value_type dx(int i) const {
1436  if (expr1.size() > 0 && expr2.size() > 0)
1437  return v1*expr2.dx(i) + expr1.dx(i)*v2;
1438  else if (expr1.size() > 0)
1439  return expr1.dx(i)*v2;
1440  else
1441  return v1*expr2.dx(i);
1442  }
1443 
1445  const value_type fastAccessDx(int i) const {
1446  return v1*expr2.fastAccessDx(i) + expr1.fastAccessDx(i)*v2;
1447  }
1448 
1450  const value_type* getDx(int j) const {
1451  if (j < num_args1)
1452  return expr1.getDx(j);
1453  else
1454  return expr2.getDx(j-num_args1);
1455  }
1456 
1457  protected:
1458 
1459  const ExprT1& expr1;
1460  const ExprT2& expr2;
1461  mutable value_type_1 v1;
1462  mutable value_type_2 v2;
1463 
1464  };
1465 
1466  template <typename ExprT1, typename T2>
1467  class Expr< MultiplicationOp<ExprT1, ConstExpr<T2> > > {
1468 
1469  public:
1470 
1471  typedef ConstExpr<T2> ExprT2;
1472  typedef typename ExprT1::value_type value_type_1;
1473  typedef typename ExprT2::value_type value_type_2;
1474  typedef typename Sacado::Promote<value_type_1,
1475  value_type_2>::type value_type;
1476  typedef typename ExprT1::scalar_type scalar_type_1;
1477  typedef typename ExprT2::scalar_type scalar_type_2;
1478  typedef typename Sacado::Promote<scalar_type_1,
1479  scalar_type_2>::type scalar_type;
1480 
1481  typedef typename ExprT1::base_expr_type base_expr_type_1;
1482  typedef typename ExprT2::base_expr_type base_expr_type_2;
1483  typedef typename Sacado::Promote<base_expr_type_1,
1484  base_expr_type_2>::type base_expr_type;
1485 
1486  static const int num_args = ExprT1::num_args;
1487 
1488  static const bool is_linear = ExprT1::is_linear;
1489 
1491  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
1492  expr1(expr1_), expr2(expr2_) {}
1493 
1495  int size() const {
1496  return expr1.size();
1497  }
1498 
1499  template <int Arg>
1501  bool isActive() const {
1502  return expr1.template isActive<Arg>();
1503  }
1504 
1506  bool updateValue() const {
1507  return expr1.updateValue();
1508  }
1509 
1511  void cache() const {
1512  expr1.cache();
1513  }
1514 
1516  value_type val() const {
1517  return expr1.val()*expr2.val();
1518  }
1519 
1521  void computePartials(const value_type& bar,
1522  value_type partials[]) const {
1523  expr1.computePartials(bar*expr2.val(), partials);
1524  }
1525 
1527  void getTangents(int i, value_type dots[]) const {
1528  expr1.getTangents(i, dots);
1529  }
1530 
1531  template <int Arg>
1533  value_type getTangent(int i) const {
1534  return expr1.template getTangent<Arg>(i);
1535  }
1536 
1538  bool isLinear() const {
1539  return expr1.isLinear();
1540  }
1541 
1543  bool hasFastAccess() const {
1544  return expr1.hasFastAccess();
1545  }
1546 
1548  const value_type dx(int i) const {
1549  return expr1.dx(i)*expr2.val();
1550  }
1551 
1553  const value_type fastAccessDx(int i) const {
1554  return expr1.fastAccessDx(i)*expr2.val();
1555  }
1556 
1558  const value_type* getDx(int j) const {
1559  return expr1.getDx(j);
1560  }
1561 
1562  protected:
1563 
1564  const ExprT1& expr1;
1565  ExprT2 expr2;
1566 
1567  };
1568 
1569  template <typename T1, typename ExprT2>
1570  class Expr< MultiplicationOp< ConstExpr<T1>,ExprT2> > {
1571 
1572  public:
1573 
1574  typedef ConstExpr<T1> ExprT1;
1575  typedef typename ExprT1::value_type value_type_1;
1576  typedef typename ExprT2::value_type value_type_2;
1577  typedef typename Sacado::Promote<value_type_1,
1578  value_type_2>::type value_type;
1579  typedef typename ExprT1::scalar_type scalar_type_1;
1580  typedef typename ExprT2::scalar_type scalar_type_2;
1581  typedef typename Sacado::Promote<scalar_type_1,
1582  scalar_type_2>::type scalar_type;
1583 
1584  typedef typename ExprT1::base_expr_type base_expr_type_1;
1585  typedef typename ExprT2::base_expr_type base_expr_type_2;
1586  typedef typename Sacado::Promote<base_expr_type_1,
1587  base_expr_type_2>::type base_expr_type;
1588 
1589  static const int num_args = ExprT2::num_args;
1590 
1591  static const bool is_linear = ExprT2::is_linear;
1592 
1594  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
1595  expr1(expr1_), expr2(expr2_) {}
1596 
1598  int size() const {
1599  return expr2.size();
1600  }
1601 
1602  template <int Arg>
1604  bool isActive() const {
1605  return expr2.template isActive<Arg>();
1606  }
1607 
1609  bool updateValue() const {
1610  return expr2.updateValue();
1611  }
1612 
1614  void cache() const {
1615  expr2.cache();
1616  }
1617 
1619  value_type val() const {
1620  return expr1.val()*expr2.val();
1621  }
1622 
1624  void computePartials(const value_type& bar,
1625  value_type partials[]) const {
1626  expr2.computePartials(bar*expr1.val(), partials);
1627  }
1628 
1630  void getTangents(int i, value_type dots[]) const {
1631  expr2.getTangents(i, dots);
1632  }
1633 
1634  template <int Arg>
1636  value_type getTangent(int i) const {
1637  return expr2.template getTangent<Arg>(i);
1638  }
1639 
1641  bool isLinear() const {
1642  return expr2.isLinear();
1643  }
1644 
1646  bool hasFastAccess() const {
1647  return expr2.hasFastAccess();
1648  }
1649 
1651  const value_type dx(int i) const {
1652  return expr1.val()*expr2.dx(i);
1653  }
1654 
1656  const value_type fastAccessDx(int i) const {
1657  return expr1.val()*expr2.fastAccessDx(i);
1658  }
1659 
1661  const value_type* getDx(int j) const {
1662  return expr2.getDx(j);
1663  }
1664 
1665  protected:
1666 
1667  ExprT1 expr1;
1668  const ExprT2& expr2;
1669 
1670  };
1671 
1672  //
1673  // DivisionOp
1674  //
1675 
1676  template <typename ExprT1, typename ExprT2>
1677  class DivisionOp {};
1678 
1679  template <typename ExprT1, typename ExprT2>
1680  class Expr< DivisionOp<ExprT1,ExprT2> > {
1681 
1682  public:
1683 
1684  typedef typename ExprT1::value_type value_type_1;
1685  typedef typename ExprT2::value_type value_type_2;
1686  typedef typename Sacado::Promote<value_type_1,
1687  value_type_2>::type value_type;
1688  typedef typename ExprT1::scalar_type scalar_type_1;
1689  typedef typename ExprT2::scalar_type scalar_type_2;
1690  typedef typename Sacado::Promote<scalar_type_1,
1691  scalar_type_2>::type scalar_type;
1692 
1693  typedef typename ExprT1::base_expr_type base_expr_type_1;
1694  typedef typename ExprT2::base_expr_type base_expr_type_2;
1695  typedef typename Sacado::Promote<base_expr_type_1,
1696  base_expr_type_2>::type base_expr_type;
1697 
1698  static const int num_args1 = ExprT1::num_args;
1699  static const int num_args2 = ExprT2::num_args;
1700  static const int num_args = num_args1 + num_args2;
1701 
1702  static const bool is_linear = false;
1703 
1705  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
1706  expr1(expr1_), expr2(expr2_) {}
1707 
1709  int size() const {
1710  int sz1 = expr1.size(), sz2 = expr2.size();
1711  return sz1 > sz2 ? sz1 : sz2;
1712  }
1713 
1714  template <int Arg>
1716  bool isActive() const {
1717  if (Arg < num_args1)
1718  return expr1.template isActive<Arg>();
1719  else
1720  return expr2.template isActive<Arg-num_args1>();
1721  }
1722 
1724  bool updateValue() const {
1725  return expr1.updateValue() && expr2.updateValue();
1726  }
1727 
1729  void cache() const {
1730  expr1.cache();
1731  expr2.cache();
1732  const value_type_1 v1 = expr1.val();
1733  const value_type_2 v2 = expr2.val();
1734  a = scalar_type(1.0)/v2;
1735  v = v1*a;
1736  b = -v/v2;
1737  }
1738 
1740  value_type val() const {
1741  return v;
1742  }
1743 
1745  void computePartials(const value_type& bar,
1746  value_type partials[]) const {
1747  if (num_args1 > 0)
1748  expr1.computePartials(bar*a, partials);
1749  if (num_args2 > 0)
1750  expr2.computePartials(bar*b, partials+num_args1);
1751  }
1752 
1754  void getTangents(int i, value_type dots[]) const {
1755  expr1.getTangents(i, dots);
1756  expr2.getTangents(i, dots+num_args1);
1757  }
1758 
1759  template <int Arg>
1761  value_type getTangent(int i) const {
1762  if (Arg < num_args1)
1763  return expr1.template getTangent<Arg>(i);
1764  else
1765  return expr2.template getTangent<Arg-num_args1>(i);
1766  }
1767 
1769  bool isLinear() const {
1770  return false;
1771  }
1772 
1774  bool hasFastAccess() const {
1775  return expr1.hasFastAccess() && expr2.hasFastAccess();
1776  }
1777 
1779  const value_type dx(int i) const {
1780  if (expr1.size() > 0 && expr2.size() > 0)
1781  return expr1.dx(i)*a + expr2.dx(i)*b;
1782  else if (expr1.size() > 0)
1783  return expr1.dx(i)*a;
1784  else
1785  return expr1.val()*b;
1786  }
1787 
1789  const value_type fastAccessDx(int i) const {
1790  return expr1.fastAccessDx(i)*a + expr2.fastAccessDx(i)*b;
1791  }
1792 
1794  const value_type* getDx(int j) const {
1795  if (j < num_args1)
1796  return expr1.getDx(j);
1797  else
1798  return expr2.getDx(j-num_args1);
1799  }
1800 
1801  protected:
1802 
1803  const ExprT1& expr1;
1804  const ExprT2& expr2;
1805  mutable value_type v;
1806  mutable value_type a;
1807  mutable value_type b;
1808 
1809  };
1810 
1811  template <typename ExprT1, typename T2>
1812  class Expr< DivisionOp<ExprT1, ConstExpr<T2> > > {
1813 
1814  public:
1815 
1816  typedef ConstExpr<T2> ExprT2;
1817  typedef typename ExprT1::value_type value_type_1;
1818  typedef typename ExprT2::value_type value_type_2;
1819  typedef typename Sacado::Promote<value_type_1,
1820  value_type_2>::type value_type;
1821  typedef typename ExprT1::scalar_type scalar_type_1;
1822  typedef typename ExprT2::scalar_type scalar_type_2;
1823  typedef typename Sacado::Promote<scalar_type_1,
1824  scalar_type_2>::type scalar_type;
1825 
1826  typedef typename ExprT1::base_expr_type base_expr_type_1;
1827  typedef typename ExprT2::base_expr_type base_expr_type_2;
1828  typedef typename Sacado::Promote<base_expr_type_1,
1829  base_expr_type_2>::type base_expr_type;
1830 
1831  static const int num_args = ExprT1::num_args;
1832 
1833  static const bool is_linear = ExprT1::is_linear;
1834 
1836  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
1837  expr1(expr1_), expr2(expr2_) {}
1838 
1840  int size() const {
1841  return expr1.size();
1842  }
1843 
1844  template <int Arg>
1846  bool isActive() const {
1847  return expr1.template isActive<Arg>();
1848  }
1849 
1851  bool updateValue() const {
1852  return expr1.updateValue();
1853  }
1854 
1856  void cache() const {
1857  expr1.cache();
1858  const value_type_1 v1 = expr1.val();
1859  a = scalar_type(1.0)/expr2.val();
1860  v = v1*a;
1861  }
1862 
1864  value_type val() const {
1865  return v;
1866  }
1867 
1869  void computePartials(const value_type& bar,
1870  value_type partials[]) const {
1871  expr1.computePartials(bar*a, partials);
1872  }
1873 
1875  void getTangents(int i, value_type dots[]) const {
1876  expr1.getTangents(i, dots);
1877  }
1878 
1879  template <int Arg>
1881  value_type getTangent(int i) const {
1882  return expr1.template getTangent<Arg>(i);
1883  }
1884 
1886  bool isLinear() const {
1887  return expr1.isLinear();
1888  }
1889 
1891  bool hasFastAccess() const {
1892  return expr1.hasFastAccess();
1893  }
1894 
1896  const value_type dx(int i) const {
1897  return expr1.dx(i)*a;
1898  }
1899 
1901  const value_type fastAccessDx(int i) const {
1902  return expr1.fastAccessDx(i)*a;
1903  }
1904 
1906  const value_type* getDx(int j) const {
1907  return expr1.getDx(j);
1908  }
1909 
1910  protected:
1911 
1912  const ExprT1& expr1;
1913  ExprT2 expr2;
1914  mutable value_type v;
1915  mutable value_type a;
1916 
1917  };
1918 
1919  template <typename T1, typename ExprT2>
1920  class Expr< DivisionOp< ConstExpr<T1>,ExprT2> > {
1921 
1922  public:
1923 
1924  typedef ConstExpr<T1> ExprT1;
1925  typedef typename ExprT1::value_type value_type_1;
1926  typedef typename ExprT2::value_type value_type_2;
1927  typedef typename Sacado::Promote<value_type_1,
1928  value_type_2>::type value_type;
1929  typedef typename ExprT1::scalar_type scalar_type_1;
1930  typedef typename ExprT2::scalar_type scalar_type_2;
1931  typedef typename Sacado::Promote<scalar_type_1,
1932  scalar_type_2>::type scalar_type;
1933 
1934  typedef typename ExprT1::base_expr_type base_expr_type_1;
1935  typedef typename ExprT2::base_expr_type base_expr_type_2;
1936  typedef typename Sacado::Promote<base_expr_type_1,
1937  base_expr_type_2>::type base_expr_type;
1938 
1939  static const int num_args = ExprT2::num_args;
1940 
1941  static const bool is_linear = false;
1942 
1944  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
1945  expr1(expr1_), expr2(expr2_) {}
1946 
1948  int size() const {
1949  return expr2.size();
1950  }
1951 
1952  template <int Arg>
1954  bool isActive() const {
1955  return expr2.template isActive<Arg>();
1956  }
1957 
1959  bool updateValue() const {
1960  return expr2.updateValue();
1961  }
1962 
1964  void cache() const {
1965  expr2.cache();
1966  const value_type_2 v2 = expr2.val();
1967  v = expr1.val()/v2;
1968  b = -v/v2;
1969  }
1970 
1972  value_type val() const {
1973  return v;
1974  }
1975 
1977  void computePartials(const value_type& bar,
1978  value_type partials[]) const {
1979  expr2.computePartials(bar*b, partials);
1980  }
1981 
1983  void getTangents(int i, value_type dots[]) const {
1984  expr2.getTangents(i, dots);
1985  }
1986 
1987  template <int Arg>
1989  value_type getTangent(int i) const {
1990  return expr2.template getTangent<Arg>(i);
1991  }
1992 
1994  bool isLinear() const {
1995  return false;
1996  }
1997 
1999  bool hasFastAccess() const {
2000  return expr2.hasFastAccess();
2001  }
2002 
2004  const value_type dx(int i) const {
2005  return expr2.dx(i)*b;
2006  }
2007 
2009  const value_type fastAccessDx(int i) const {
2010  return expr2.fastAccessDx(i)*b;
2011  }
2012 
2014  const value_type* getDx(int j) const {
2015  return expr2.getDx(j);
2016  }
2017 
2018  protected:
2019 
2020  ExprT1 expr1;
2021  const ExprT2& expr2;
2022  mutable value_type v;
2023  mutable value_type b;
2024 
2025  };
2026 
2027  //
2028  // Atan2Op
2029  //
2030 
2031  template <typename ExprT1, typename ExprT2>
2032  class Atan2Op {};
2033 
2034  template <typename ExprT1, typename ExprT2>
2035  class Expr< Atan2Op<ExprT1,ExprT2> > {
2036 
2037  public:
2038 
2039  typedef typename ExprT1::value_type value_type_1;
2040  typedef typename ExprT2::value_type value_type_2;
2041  typedef typename Sacado::Promote<value_type_1,
2042  value_type_2>::type value_type;
2043  typedef typename ExprT1::scalar_type scalar_type_1;
2044  typedef typename ExprT2::scalar_type scalar_type_2;
2045  typedef typename Sacado::Promote<scalar_type_1,
2046  scalar_type_2>::type scalar_type;
2047 
2048  typedef typename ExprT1::base_expr_type base_expr_type_1;
2049  typedef typename ExprT2::base_expr_type base_expr_type_2;
2050  typedef typename Sacado::Promote<base_expr_type_1,
2051  base_expr_type_2>::type base_expr_type;
2052 
2053  static const int num_args1 = ExprT1::num_args;
2054  static const int num_args2 = ExprT2::num_args;
2055  static const int num_args = num_args1 + num_args2;
2056 
2057  static const bool is_linear = false;
2058 
2060  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
2061  expr1(expr1_), expr2(expr2_) {}
2062 
2064  int size() const {
2065  int sz1 = expr1.size(), sz2 = expr2.size();
2066  return sz1 > sz2 ? sz1 : sz2;
2067  }
2068 
2069  template <int Arg>
2071  bool isActive() const {
2072  if (Arg < num_args1)
2073  return expr1.template isActive<Arg>();
2074  else
2075  return expr2.template isActive<Arg-num_args1>();
2076  }
2077 
2079  bool updateValue() const {
2080  return expr1.updateValue() && expr2.updateValue();
2081  }
2082 
2084  void cache() const {
2085  expr1.cache();
2086  expr2.cache();
2087  const value_type_1 v1 = expr1.val();
2088  const value_type_2 v2 = expr2.val();
2089  a = scalar_type(1.0)/(v1*v1 + v2*v2);
2090  b = -v1*a;
2091  a = v2*a;
2092  v = std::atan2(v1,v2);
2093  }
2094 
2096  value_type val() const {
2097  return v;
2098  }
2099 
2101  void computePartials(const value_type& bar,
2102  value_type partials[]) const {
2103  if (num_args1 > 0)
2104  expr1.computePartials(bar*a, partials);
2105  if (num_args2 > 0)
2106  expr2.computePartials(bar*b, partials+num_args1);
2107  }
2108 
2110  void getTangents(int i, value_type dots[]) const {
2111  expr1.getTangents(i, dots);
2112  expr2.getTangents(i, dots+num_args1);
2113  }
2114 
2115  template <int Arg>
2117  value_type getTangent(int i) const {
2118  if (Arg < num_args1)
2119  return expr1.template getTangent<Arg>(i);
2120  else
2121  return expr2.template getTangent<Arg-num_args1>(i);
2122  }
2123 
2125  bool isLinear() const {
2126  return false;
2127  }
2128 
2130  bool hasFastAccess() const {
2131  return expr1.hasFastAccess() && expr2.hasFastAccess();
2132  }
2133 
2135  const value_type dx(int i) const {
2136  if (expr1.size() > 0 && expr2.size() > 0)
2137  return expr1.dx(i)*a + expr2.dx(i)*b;
2138  else if (expr1.size() > 0)
2139  return expr1.dx(i)*a;
2140  else
2141  return expr1.val()*b;
2142  }
2143 
2145  const value_type fastAccessDx(int i) const {
2146  return expr1.fastAccessDx(i)*a + expr2.fastAccessDx(i)*b;
2147  }
2148 
2150  const value_type* getDx(int j) const {
2151  if (j < num_args1)
2152  return expr1.getDx(j);
2153  else
2154  return expr2.getDx(j-num_args1);
2155  }
2156 
2157  protected:
2158 
2159  const ExprT1& expr1;
2160  const ExprT2& expr2;
2161  mutable value_type v;
2162  mutable value_type a;
2163  mutable value_type b;
2164 
2165  };
2166 
2167  template <typename ExprT1, typename T2>
2168  class Expr< Atan2Op<ExprT1, ConstExpr<T2> > > {
2169 
2170  public:
2171 
2172  typedef ConstExpr<T2> ExprT2;
2173  typedef typename ExprT1::value_type value_type_1;
2174  typedef typename ExprT2::value_type value_type_2;
2175  typedef typename Sacado::Promote<value_type_1,
2176  value_type_2>::type value_type;
2177  typedef typename ExprT1::scalar_type scalar_type_1;
2178  typedef typename ExprT2::scalar_type scalar_type_2;
2179  typedef typename Sacado::Promote<scalar_type_1,
2180  scalar_type_2>::type scalar_type;
2181 
2182  typedef typename ExprT1::base_expr_type base_expr_type_1;
2183  typedef typename ExprT2::base_expr_type base_expr_type_2;
2184  typedef typename Sacado::Promote<base_expr_type_1,
2185  base_expr_type_2>::type base_expr_type;
2186 
2187  static const int num_args = ExprT1::num_args;
2188 
2189  static const bool is_linear = false;
2190 
2192  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
2193  expr1(expr1_), expr2(expr2_) {}
2194 
2196  int size() const {
2197  return expr1.size();
2198  }
2199 
2200  template <int Arg>
2202  bool isActive() const {
2203  return expr1.template isActive<Arg>();
2204  }
2205 
2207  bool updateValue() const {
2208  return expr1.updateValue();
2209  }
2210 
2212  void cache() const {
2213  expr1.cache();
2214  const value_type_1 v1 = expr1.val();
2215  const value_type_2 v2 = expr2.val();
2216  a = v2/(v1*v1 + v2*v2);
2217  v = std::atan2(v1,v2);
2218  }
2219 
2221  value_type val() const {
2222  return v;
2223  }
2224 
2226  void computePartials(const value_type& bar,
2227  value_type partials[]) const {
2228  expr1.computePartials(bar*a, partials);
2229  }
2230 
2232  void getTangents(int i, value_type dots[]) const {
2233  expr1.getTangents(i, dots);
2234  }
2235 
2236  template <int Arg>
2238  value_type getTangent(int i) const {
2239  return expr1.template getTangent<Arg>(i);
2240  }
2241 
2243  bool isLinear() const {
2244  return false;
2245  }
2246 
2248  bool hasFastAccess() const {
2249  return expr1.hasFastAccess();
2250  }
2251 
2253  const value_type dx(int i) const {
2254  return expr1.dx(i)*a;
2255  }
2256 
2258  const value_type fastAccessDx(int i) const {
2259  return expr1.fastAccessDx(i)*a;
2260  }
2261 
2263  const value_type* getDx(int j) const {
2264  return expr1.getDx(j);
2265  }
2266 
2267  protected:
2268 
2269  const ExprT1& expr1;
2270  ExprT2 expr2;
2271  mutable value_type v;
2272  mutable value_type a;
2273 
2274  };
2275 
2276  template <typename T1, typename ExprT2>
2277  class Expr< Atan2Op< ConstExpr<T1>,ExprT2> > {
2278 
2279  public:
2280 
2281  typedef ConstExpr<T1> ExprT1;
2282  typedef typename ExprT1::value_type value_type_1;
2283  typedef typename ExprT2::value_type value_type_2;
2284  typedef typename Sacado::Promote<value_type_1,
2285  value_type_2>::type value_type;
2286  typedef typename ExprT1::scalar_type scalar_type_1;
2287  typedef typename ExprT2::scalar_type scalar_type_2;
2288  typedef typename Sacado::Promote<scalar_type_1,
2289  scalar_type_2>::type scalar_type;
2290 
2291  typedef typename ExprT1::base_expr_type base_expr_type_1;
2292  typedef typename ExprT2::base_expr_type base_expr_type_2;
2293  typedef typename Sacado::Promote<base_expr_type_1,
2294  base_expr_type_2>::type base_expr_type;
2295 
2296  static const int num_args = ExprT2::num_args;
2297 
2298  static const bool is_linear = false;
2299 
2301  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
2302  expr1(expr1_), expr2(expr2_) {}
2303 
2305  int size() const {
2306  return expr2.size();
2307  }
2308 
2309  template <int Arg>
2311  bool isActive() const {
2312  return expr2.template isActive<Arg>();
2313  }
2314 
2316  bool updateValue() const {
2317  return expr2.updateValue();
2318  }
2319 
2321  void cache() const {
2322  expr2.cache();
2323  const value_type_1 v1 = expr1.val();
2324  const value_type_2 v2 = expr2.val();
2325  b = -v1/(v1*v1 + v2*v2);
2326  v = std::atan2(v1,v2);
2327  }
2328 
2330  value_type val() const {
2331  return v;
2332  }
2333 
2335  void computePartials(const value_type& bar,
2336  value_type partials[]) const {
2337  expr2.computePartials(bar*b, partials);
2338  }
2339 
2341  void getTangents(int i, value_type dots[]) const {
2342  expr2.getTangents(i, dots);
2343  }
2344 
2345  template <int Arg>
2347  value_type getTangent(int i) const {
2348  return expr2.template getTangent<Arg>(i);
2349  }
2350 
2352  bool isLinear() const {
2353  return false;
2354  }
2355 
2357  bool hasFastAccess() const {
2358  return expr2.hasFastAccess();
2359  }
2360 
2362  const value_type dx(int i) const {
2363  return expr2.dx(i)*b;
2364  }
2365 
2367  const value_type fastAccessDx(int i) const {
2368  return expr2.fastAccessDx(i)*b;
2369  }
2370 
2372  const value_type* getDx(int j) const {
2373  return expr2.getDx(j);
2374  }
2375 
2376  protected:
2377 
2378  ExprT1 expr1;
2379  const ExprT2& expr2;
2380  mutable value_type v;
2381  mutable value_type b;
2382 
2383  };
2384 
2385  //
2386  // PowerOp
2387  //
2388 
2389  template <typename ExprT1, typename ExprT2>
2390  class PowerOp {};
2391 
2392  template <typename ExprT1, typename ExprT2>
2393  class Expr< PowerOp<ExprT1,ExprT2> > {
2394 
2395  public:
2396 
2397  typedef typename ExprT1::value_type value_type_1;
2398  typedef typename ExprT2::value_type value_type_2;
2399  typedef typename Sacado::Promote<value_type_1,
2400  value_type_2>::type value_type;
2401  typedef typename ExprT1::scalar_type scalar_type_1;
2402  typedef typename ExprT2::scalar_type scalar_type_2;
2403  typedef typename Sacado::Promote<scalar_type_1,
2404  scalar_type_2>::type scalar_type;
2405 
2406  typedef typename ExprT1::base_expr_type base_expr_type_1;
2407  typedef typename ExprT2::base_expr_type base_expr_type_2;
2408  typedef typename Sacado::Promote<base_expr_type_1,
2409  base_expr_type_2>::type base_expr_type;
2410 
2411  static const int num_args1 = ExprT1::num_args;
2412  static const int num_args2 = ExprT2::num_args;
2413  static const int num_args = num_args1 + num_args2;
2414 
2415  static const bool is_linear = false;
2416 
2418  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
2419  expr1(expr1_), expr2(expr2_) {}
2420 
2422  int size() const {
2423  int sz1 = expr1.size(), sz2 = expr2.size();
2424  return sz1 > sz2 ? sz1 : sz2;
2425  }
2426 
2427  template <int Arg>
2429  bool isActive() const {
2430  if (Arg < num_args1)
2431  return expr1.template isActive<Arg>();
2432  else
2433  return expr2.template isActive<Arg-num_args1>();
2434  }
2435 
2437  bool updateValue() const {
2438  return expr1.updateValue() && expr2.updateValue();
2439  }
2440 
2442  void cache() const {
2443  expr1.cache();
2444  expr2.cache();
2445  const value_type_1 v1 = expr1.val();
2446  const value_type_2 v2 = expr2.val();
2447  v = std::pow(v1,v2);
2448  if (expr2.size() == 0 && v2 == scalar_type(1.0)) {
2449  a = scalar_type(1.0);
2450  b = scalar_type(0.0);
2451  }
2452  else if (v1 == scalar_type(0.0)) {
2453  a = scalar_type(0.0);
2454  b = scalar_type(0.0);
2455  }
2456  else {
2457  a = v*v2/v1;
2458  b = v*std::log(v1);
2459  }
2460  }
2461 
2463  value_type val() const {
2464  return v;
2465  }
2466 
2468  void computePartials(const value_type& bar,
2469  value_type partials[]) const {
2470  if (num_args1 > 0)
2471  expr1.computePartials(bar*a, partials);
2472  if (num_args2 > 0)
2473  expr2.computePartials(bar*b, partials+num_args1);
2474  }
2475 
2477  void getTangents(int i, value_type dots[]) const {
2478  expr1.getTangents(i, dots);
2479  expr2.getTangents(i, dots+num_args1);
2480  }
2481 
2482  template <int Arg>
2484  value_type getTangent(int i) const {
2485  if (Arg < num_args1)
2486  return expr1.template getTangent<Arg>(i);
2487  else
2488  return expr2.template getTangent<Arg-num_args1>(i);
2489  }
2490 
2492  bool isLinear() const {
2493  return false;
2494  }
2495 
2497  bool hasFastAccess() const {
2498  return expr1.hasFastAccess() && expr2.hasFastAccess();
2499  }
2500 
2502  const value_type dx(int i) const {
2503  if (expr1.size() > 0 && expr2.size() > 0)
2504  return expr1.dx(i)*a + expr2.dx(i)*b;
2505  else if (expr1.size() > 0)
2506  return expr1.dx(i)*a;
2507  else
2508  return expr1.val()*b;
2509  }
2510 
2512  const value_type fastAccessDx(int i) const {
2513  return expr1.fastAccessDx(i)*a + expr2.fastAccessDx(i)*b;
2514  }
2515 
2517  const value_type* getDx(int j) const {
2518  if (j < num_args1)
2519  return expr1.getDx(j);
2520  else
2521  return expr2.getDx(j-num_args1);
2522  }
2523 
2524  protected:
2525 
2526  const ExprT1& expr1;
2527  const ExprT2& expr2;
2528  mutable value_type v;
2529  mutable value_type a;
2530  mutable value_type b;
2531 
2532  };
2533 
2534  template <typename ExprT1, typename T2>
2535  class Expr< PowerOp<ExprT1, ConstExpr<T2> > > {
2536 
2537  public:
2538 
2539  typedef ConstExpr<T2> ExprT2;
2540  typedef typename ExprT1::value_type value_type_1;
2541  typedef typename ExprT2::value_type value_type_2;
2542  typedef typename Sacado::Promote<value_type_1,
2543  value_type_2>::type value_type;
2544  typedef typename ExprT1::scalar_type scalar_type_1;
2545  typedef typename ExprT2::scalar_type scalar_type_2;
2546  typedef typename Sacado::Promote<scalar_type_1,
2547  scalar_type_2>::type scalar_type;
2548 
2549  typedef typename ExprT1::base_expr_type base_expr_type_1;
2550  typedef typename ExprT2::base_expr_type base_expr_type_2;
2551  typedef typename Sacado::Promote<base_expr_type_1,
2552  base_expr_type_2>::type base_expr_type;
2553 
2554  static const int num_args = ExprT1::num_args;
2555 
2556  static const bool is_linear = false;
2557 
2559  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
2560  expr1(expr1_), expr2(expr2_) {}
2561 
2563  int size() const {
2564  return expr1.size();
2565  }
2566 
2567  template <int Arg>
2569  bool isActive() const {
2570  return expr1.template isActive<Arg>();
2571  }
2572 
2574  bool updateValue() const {
2575  return expr1.updateValue();
2576  }
2577 
2579  void cache() const {
2580  expr1.cache();
2581  const value_type_1 v1 = expr1.val();
2582  const value_type_2 v2 = expr2.val();
2583  v = std::pow(v1,v2);
2584  if (v2 == scalar_type(1.0)) {
2585  a = scalar_type(1.0);
2586  }
2587  else if (v1 == scalar_type(0.0)) {
2588  a = scalar_type(0.0);
2589  }
2590  else {
2591  a = v*v2/v1;
2592  }
2593  }
2594 
2596  value_type val() const {
2597  return v;
2598  }
2599 
2601  void computePartials(const value_type& bar,
2602  value_type partials[]) const {
2603  expr1.computePartials(bar*a, partials);
2604  }
2605 
2607  void getTangents(int i, value_type dots[]) const {
2608  expr1.getTangents(i, dots);
2609  }
2610 
2611  template <int Arg>
2613  value_type getTangent(int i) const {
2614  return expr1.template getTangent<Arg>(i);
2615  }
2616 
2618  bool isLinear() const {
2619  return false;
2620  }
2621 
2623  bool hasFastAccess() const {
2624  return expr1.hasFastAccess();
2625  }
2626 
2628  const value_type dx(int i) const {
2629  return expr1.dx(i)*a;
2630  }
2631 
2633  const value_type fastAccessDx(int i) const {
2634  return expr1.fastAccessDx(i)*a;
2635  }
2636 
2638  const value_type* getDx(int j) const {
2639  return expr1.getDx(j);
2640  }
2641 
2642  protected:
2643 
2644  const ExprT1& expr1;
2645  ExprT2 expr2;
2646  mutable value_type v;
2647  mutable value_type a;
2648 
2649  };
2650 
2651  template <typename T1, typename ExprT2>
2652  class Expr< PowerOp< ConstExpr<T1>,ExprT2> > {
2653 
2654  public:
2655 
2656  typedef ConstExpr<T1> ExprT1;
2657  typedef typename ExprT1::value_type value_type_1;
2658  typedef typename ExprT2::value_type value_type_2;
2659  typedef typename Sacado::Promote<value_type_1,
2660  value_type_2>::type value_type;
2661  typedef typename ExprT1::scalar_type scalar_type_1;
2662  typedef typename ExprT2::scalar_type scalar_type_2;
2663  typedef typename Sacado::Promote<scalar_type_1,
2664  scalar_type_2>::type scalar_type;
2665 
2666  typedef typename ExprT1::base_expr_type base_expr_type_1;
2667  typedef typename ExprT2::base_expr_type base_expr_type_2;
2668  typedef typename Sacado::Promote<base_expr_type_1,
2669  base_expr_type_2>::type base_expr_type;
2670 
2671  static const int num_args = ExprT2::num_args;
2672 
2673  static const bool is_linear = false;
2674 
2676  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
2677  expr1(expr1_), expr2(expr2_) {}
2678 
2680  int size() const {
2681  return expr2.size();
2682  }
2683 
2684  template <int Arg>
2686  bool isActive() const {
2687  return expr2.template isActive<Arg>();
2688  }
2689 
2691  bool updateValue() const {
2692  return expr2.updateValue();
2693  }
2694 
2696  void cache() const {
2697  expr2.cache();
2698  const value_type_1 v1 = expr1.val();
2699  const value_type_2 v2 = expr2.val();
2700  v = std::pow(v1,v2);
2701  if (v1 == scalar_type(0.0)) {
2702  b = scalar_type(0.0);
2703  }
2704  else {
2705  b = v*std::log(v1);
2706  }
2707  }
2708 
2710  value_type val() const {
2711  return v;
2712  }
2713 
2715  void computePartials(const value_type& bar,
2716  value_type partials[]) const {
2717  expr2.computePartials(bar*b, partials);
2718  }
2719 
2721  void getTangents(int i, value_type dots[]) const {
2722  expr2.getTangents(i, dots);
2723  }
2724 
2725  template <int Arg>
2727  value_type getTangent(int i) const {
2728  return expr2.template getTangent<Arg>(i);
2729  }
2730 
2732  bool isLinear() const {
2733  return false;
2734  }
2735 
2737  bool hasFastAccess() const {
2738  return expr2.hasFastAccess();
2739  }
2740 
2742  const value_type dx(int i) const {
2743  return expr2.dx(i)*b;
2744  }
2745 
2747  const value_type fastAccessDx(int i) const {
2748  return expr2.fastAccessDx(i)*b;
2749  }
2750 
2752  const value_type* getDx(int j) const {
2753  return expr2.getDx(j);
2754  }
2755 
2756  protected:
2757 
2758  ExprT1 expr1;
2759  const ExprT2& expr2;
2760  mutable value_type v;
2761  mutable value_type b;
2762 
2763  };
2764 
2765  //
2766  // MaxOp
2767  //
2768 
2769  template <typename ExprT1, typename ExprT2>
2770  class MaxOp {};
2771 
2772  template <typename ExprT1, typename ExprT2>
2773  class Expr< MaxOp<ExprT1,ExprT2> > {
2774 
2775  public:
2776 
2777  typedef typename ExprT1::value_type value_type_1;
2778  typedef typename ExprT2::value_type value_type_2;
2779  typedef typename Sacado::Promote<value_type_1,
2780  value_type_2>::type value_type;
2781  typedef typename ExprT1::scalar_type scalar_type_1;
2782  typedef typename ExprT2::scalar_type scalar_type_2;
2783  typedef typename Sacado::Promote<scalar_type_1,
2784  scalar_type_2>::type scalar_type;
2785 
2786  typedef typename ExprT1::base_expr_type base_expr_type_1;
2787  typedef typename ExprT2::base_expr_type base_expr_type_2;
2788  typedef typename Sacado::Promote<base_expr_type_1,
2789  base_expr_type_2>::type base_expr_type;
2790 
2791  static const int num_args1 = ExprT1::num_args;
2792  static const int num_args2 = ExprT2::num_args;
2793  static const int num_args = num_args1 + num_args2;
2794 
2795  static const bool is_linear = false;
2796 
2798  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
2799  expr1(expr1_), expr2(expr2_) {}
2800 
2802  int size() const {
2803  int sz1 = expr1.size(), sz2 = expr2.size();
2804  return sz1 > sz2 ? sz1 : sz2;
2805  }
2806 
2807  template <int Arg>
2809  bool isActive() const {
2810  if (Arg < num_args1)
2811  return expr1.template isActive<Arg>();
2812  else
2813  return expr2.template isActive<Arg-num_args1>();
2814  }
2815 
2817  bool updateValue() const {
2818  return expr1.updateValue() && expr2.updateValue();
2819  }
2820 
2822  void cache() const {
2823  expr1.cache();
2824  expr2.cache();
2825  const value_type_1 v1 = expr1.val();
2826  const value_type_2 v2 = expr2.val();
2827  max_v1 = (v1 >= v2);
2828  v = max_v1 ? v1 : v2;
2829  }
2830 
2832  value_type val() const {
2833  return v;
2834  }
2835 
2837  void computePartials(const value_type& bar,
2838  value_type partials[]) const {
2839  if (num_args1 > 0) {
2840  if (max_v1)
2841  expr1.computePartials(bar, partials);
2842  else
2843  expr1.computePartials(value_type(0.0), partials);
2844  }
2845  if (num_args2 > 0) {
2846  if (max_v1)
2847  expr2.computePartials(value_type(0.0), partials+num_args1);
2848  else
2849  expr2.computePartials(bar, partials+num_args1);
2850  }
2851  }
2852 
2854  void getTangents(int i, value_type dots[]) const {
2855  expr1.getTangents(i, dots);
2856  expr2.getTangents(i, dots+num_args1);
2857  }
2858 
2859  template <int Arg>
2861  value_type getTangent(int i) const {
2862  if (Arg < num_args1)
2863  return expr1.template getTangent<Arg>(i);
2864  else
2865  return expr2.template getTangent<Arg-num_args1>(i);
2866  }
2867 
2869  bool isLinear() const {
2870  return false;
2871  }
2872 
2874  bool hasFastAccess() const {
2875  return expr1.hasFastAccess() && expr2.hasFastAccess();
2876  }
2877 
2879  const value_type dx(int i) const {
2880  return max_v1 ? expr1.dx(i) : expr2.dx(i);
2881  }
2882 
2884  const value_type fastAccessDx(int i) const {
2885  return max_v1 ? expr1.fastAccessDx(i) : expr2.fastAccessDx(i);
2886  }
2887 
2889  const value_type* getDx(int j) const {
2890  if (j < num_args1)
2891  return expr1.getDx(j);
2892  else
2893  return expr2.getDx(j-num_args1);
2894  }
2895 
2896  protected:
2897 
2898  const ExprT1& expr1;
2899  const ExprT2& expr2;
2900  mutable value_type v;
2901  mutable bool max_v1;
2902 
2903  };
2904 
2905  template <typename ExprT1, typename T2>
2906  class Expr< MaxOp<ExprT1, ConstExpr<T2> > > {
2907 
2908  public:
2909 
2910  typedef ConstExpr<T2> ExprT2;
2911  typedef typename ExprT1::value_type value_type_1;
2912  typedef typename ExprT2::value_type value_type_2;
2913  typedef typename Sacado::Promote<value_type_1,
2914  value_type_2>::type value_type;
2915  typedef typename ExprT1::scalar_type scalar_type_1;
2916  typedef typename ExprT2::scalar_type scalar_type_2;
2917  typedef typename Sacado::Promote<scalar_type_1,
2918  scalar_type_2>::type scalar_type;
2919 
2920  typedef typename ExprT1::base_expr_type base_expr_type_1;
2921  typedef typename ExprT2::base_expr_type base_expr_type_2;
2922  typedef typename Sacado::Promote<base_expr_type_1,
2923  base_expr_type_2>::type base_expr_type;
2924 
2925  static const int num_args = ExprT1::num_args;
2926 
2927  static const bool is_linear = false;
2928 
2930  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
2931  expr1(expr1_), expr2(expr2_) {}
2932 
2934  int size() const {
2935  return expr1.size();
2936  }
2937 
2938  template <int Arg>
2940  bool isActive() const {
2941  return expr1.template isActive<Arg>();
2942  }
2943 
2945  bool updateValue() const {
2946  return expr1.updateValue();
2947  }
2948 
2950  void cache() const {
2951  expr1.cache();
2952  const value_type_1 v1 = expr1.val();
2953  const value_type_2 v2 = expr2.val();
2954  max_v1 = (v1 >= v2);
2955  v = max_v1 ? v1 : v2;
2956  }
2957 
2959  value_type val() const {
2960  return v;
2961  }
2962 
2964  void computePartials(const value_type& bar,
2965  value_type partials[]) const {
2966  if (max_v1)
2967  expr1.computePartials(bar, partials);
2968  else
2969  expr1.computePartials(value_type(0.0), partials);
2970  }
2971 
2973  void getTangents(int i, value_type dots[]) const {
2974  expr1.getTangents(i, dots);
2975  }
2976 
2977  template <int Arg>
2979  value_type getTangent(int i) const {
2980  return expr1.template getTangent<Arg>(i);
2981  }
2982 
2984  bool isLinear() const {
2985  return false;
2986  }
2987 
2989  bool hasFastAccess() const {
2990  return expr1.hasFastAccess();
2991  }
2992 
2994  const value_type dx(int i) const {
2995  return max_v1 ? expr1.dx(i) : value_type(0.0);
2996  }
2997 
2999  const value_type fastAccessDx(int i) const {
3000  return max_v1 ? expr1.fastAccessDx(i) : value_type(0.0);
3001  }
3002 
3004  const value_type* getDx(int j) const {
3005  return expr1.getDx(j);
3006  }
3007 
3008  protected:
3009 
3010  const ExprT1& expr1;
3011  ExprT2 expr2;
3012  mutable value_type v;
3013  mutable bool max_v1;
3014 
3015  };
3016 
3017  template <typename T1, typename ExprT2>
3018  class Expr< MaxOp< ConstExpr<T1>,ExprT2> > {
3019 
3020  public:
3021 
3022  typedef ConstExpr<T1> ExprT1;
3023  typedef typename ExprT1::value_type value_type_1;
3024  typedef typename ExprT2::value_type value_type_2;
3025  typedef typename Sacado::Promote<value_type_1,
3026  value_type_2>::type value_type;
3027  typedef typename ExprT1::scalar_type scalar_type_1;
3028  typedef typename ExprT2::scalar_type scalar_type_2;
3029  typedef typename Sacado::Promote<scalar_type_1,
3030  scalar_type_2>::type scalar_type;
3031 
3032  typedef typename ExprT1::base_expr_type base_expr_type_1;
3033  typedef typename ExprT2::base_expr_type base_expr_type_2;
3034  typedef typename Sacado::Promote<base_expr_type_1,
3035  base_expr_type_2>::type base_expr_type;
3036 
3037  static const int num_args = ExprT2::num_args;
3038 
3039  static const bool is_linear = false;
3040 
3042  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
3043  expr1(expr1_), expr2(expr2_) {}
3044 
3046  int size() const {
3047  return expr2.size();
3048  }
3049 
3050  template <int Arg>
3052  bool isActive() const {
3053  return expr2.template isActive<Arg>();
3054  }
3055 
3057  bool updateValue() const {
3058  return expr2.updateValue();
3059  }
3060 
3062  void cache() const {
3063  expr2.cache();
3064  const value_type_1 v1 = expr1.val();
3065  const value_type_2 v2 = expr2.val();
3066  max_v1 = (v1 >= v2);
3067  v = max_v1 ? v1 : v2;
3068  }
3069 
3071  value_type val() const {
3072  return v;
3073  }
3074 
3076  void computePartials(const value_type& bar,
3077  value_type partials[]) const {
3078  if (max_v1)
3079  expr2.computePartials(value_type(0.0), partials);
3080  else
3081  expr2.computePartials(bar, partials);
3082  }
3083 
3085  void getTangents(int i, value_type dots[]) const {
3086  expr2.getTangents(i, dots);
3087  }
3088 
3089  template <int Arg>
3091  value_type getTangent(int i) const {
3092  return expr2.template getTangent<Arg>(i);
3093  }
3094 
3096  bool isLinear() const {
3097  return false;
3098  }
3099 
3101  bool hasFastAccess() const {
3102  return expr2.hasFastAccess();
3103  }
3104 
3106  const value_type dx(int i) const {
3107  return max_v1 ? value_type(0.0) : expr2.dx(i);
3108  }
3109 
3111  const value_type fastAccessDx(int i) const {
3112  return max_v1 ? value_type(0.0) : expr2.fastAccessDx(i);
3113  }
3114 
3116  const value_type* getDx(int j) const {
3117  return expr2.getDx(j);
3118  }
3119 
3120  protected:
3121 
3122  ExprT1 expr1;
3123  const ExprT2& expr2;
3124  mutable value_type v;
3125  mutable bool max_v1;
3126 
3127  };
3128 
3129  //
3130  // MinOp
3131  //
3132 
3133  template <typename ExprT1, typename ExprT2>
3134  class MinOp {};
3135 
3136  template <typename ExprT1, typename ExprT2>
3137  class Expr< MinOp<ExprT1,ExprT2> > {
3138 
3139  public:
3140 
3141  typedef typename ExprT1::value_type value_type_1;
3142  typedef typename ExprT2::value_type value_type_2;
3143  typedef typename Sacado::Promote<value_type_1,
3144  value_type_2>::type value_type;
3145  typedef typename ExprT1::scalar_type scalar_type_1;
3146  typedef typename ExprT2::scalar_type scalar_type_2;
3147  typedef typename Sacado::Promote<scalar_type_1,
3148  scalar_type_2>::type scalar_type;
3149 
3150  typedef typename ExprT1::base_expr_type base_expr_type_1;
3151  typedef typename ExprT2::base_expr_type base_expr_type_2;
3152  typedef typename Sacado::Promote<base_expr_type_1,
3153  base_expr_type_2>::type base_expr_type;
3154 
3155  static const int num_args1 = ExprT1::num_args;
3156  static const int num_args2 = ExprT2::num_args;
3157  static const int num_args = num_args1 + num_args2;
3158 
3159  static const bool is_linear = false;
3160 
3162  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
3163  expr1(expr1_), expr2(expr2_) {}
3164 
3166  int size() const {
3167  int sz1 = expr1.size(), sz2 = expr2.size();
3168  return sz1 > sz2 ? sz1 : sz2;
3169  }
3170 
3171  template <int Arg>
3173  bool isActive() const {
3174  if (Arg < num_args1)
3175  return expr1.template isActive<Arg>();
3176  else
3177  return expr2.template isActive<Arg-num_args1>();
3178  }
3179 
3181  bool updateValue() const {
3182  return expr1.updateValue() && expr2.updateValue();
3183  }
3184 
3186  void cache() const {
3187  expr1.cache();
3188  expr2.cache();
3189  const value_type_1 v1 = expr1.val();
3190  const value_type_2 v2 = expr2.val();
3191  min_v1 = (v1 <= v2);
3192  v = min_v1 ? v1 : v2;
3193  }
3194 
3196  value_type val() const {
3197  return v;
3198  }
3199 
3201  void computePartials(const value_type& bar,
3202  value_type partials[]) const {
3203  if (num_args1 > 0) {
3204  if (min_v1)
3205  expr1.computePartials(bar, partials);
3206  else
3207  expr1.computePartials(value_type(0.0), partials);
3208  }
3209  if (num_args2 > 0) {
3210  if (min_v1)
3211  expr2.computePartials(value_type(0.0), partials+num_args1);
3212  else
3213  expr2.computePartials(bar, partials+num_args1);
3214  }
3215  }
3216 
3218  void getTangents(int i, value_type dots[]) const {
3219  expr1.getTangents(i, dots);
3220  expr2.getTangents(i, dots+num_args1);
3221  }
3222 
3223  template <int Arg>
3225  value_type getTangent(int i) const {
3226  if (Arg < num_args1)
3227  return expr1.template getTangent<Arg>(i);
3228  else
3229  return expr2.template getTangent<Arg-num_args1>(i);
3230  }
3231 
3233  bool isLinear() const {
3234  return false;
3235  }
3236 
3238  bool hasFastAccess() const {
3239  return expr1.hasFastAccess() && expr2.hasFastAccess();
3240  }
3241 
3243  const value_type dx(int i) const {
3244  return min_v1 ? expr1.dx(i) : expr2.dx(i);
3245  }
3246 
3248  const value_type fastAccessDx(int i) const {
3249  return min_v1 ? expr1.fastAccessDx(i) : expr2.fastAccessDx(i);
3250  }
3251 
3253  const value_type* getDx(int j) const {
3254  if (j < num_args1)
3255  return expr1.getDx(j);
3256  else
3257  return expr2.getDx(j-num_args1);
3258  }
3259 
3260  protected:
3261 
3262  const ExprT1& expr1;
3263  const ExprT2& expr2;
3264  mutable value_type v;
3265  mutable bool min_v1;
3266 
3267  };
3268 
3269  template <typename ExprT1, typename T2>
3270  class Expr< MinOp<ExprT1, ConstExpr<T2> > > {
3271 
3272  public:
3273 
3274  typedef ConstExpr<T2> ExprT2;
3275  typedef typename ExprT1::value_type value_type_1;
3276  typedef typename ExprT2::value_type value_type_2;
3277  typedef typename Sacado::Promote<value_type_1,
3278  value_type_2>::type value_type;
3279  typedef typename ExprT1::scalar_type scalar_type_1;
3280  typedef typename ExprT2::scalar_type scalar_type_2;
3281  typedef typename Sacado::Promote<scalar_type_1,
3282  scalar_type_2>::type scalar_type;
3283 
3284  typedef typename ExprT1::base_expr_type base_expr_type_1;
3285  typedef typename ExprT2::base_expr_type base_expr_type_2;
3286  typedef typename Sacado::Promote<base_expr_type_1,
3287  base_expr_type_2>::type base_expr_type;
3288 
3289  static const int num_args = ExprT1::num_args;
3290 
3291  static const bool is_linear = false;
3292 
3294  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
3295  expr1(expr1_), expr2(expr2_) {}
3296 
3298  int size() const {
3299  return expr1.size();
3300  }
3301 
3302  template <int Arg>
3304  bool isActive() const {
3305  return expr1.template isActive<Arg>();
3306  }
3307 
3309  bool updateValue() const {
3310  return expr1.updateValue();
3311  }
3312 
3314  void cache() const {
3315  expr1.cache();
3316  const value_type_1 v1 = expr1.val();
3317  const value_type_2 v2 = expr2.val();
3318  min_v1 = (v1 <= v2);
3319  v = min_v1 ? v1 : v2;
3320  }
3321 
3323  value_type val() const {
3324  return v;
3325  }
3326 
3328  void computePartials(const value_type& bar,
3329  value_type partials[]) const {
3330  if (min_v1)
3331  expr1.computePartials(bar, partials);
3332  else
3333  expr1.computePartials(value_type(0.0), partials);
3334  }
3335 
3337  void getTangents(int i, value_type dots[]) const {
3338  expr1.getTangents(i, dots);
3339  }
3340 
3341  template <int Arg>
3343  value_type getTangent(int i) const {
3344  return expr1.template getTangent<Arg>(i);
3345  }
3346 
3348  bool isLinear() const {
3349  return false;
3350  }
3351 
3353  bool hasFastAccess() const {
3354  return expr1.hasFastAccess();
3355  }
3356 
3358  const value_type dx(int i) const {
3359  return min_v1 ? expr1.dx(i) : value_type(0.0);
3360  }
3361 
3363  const value_type fastAccessDx(int i) const {
3364  return min_v1 ? expr1.fastAccessDx(i) : value_type(0.0);
3365  }
3366 
3368  const value_type* getDx(int j) const {
3369  return expr1.getDx(j);
3370  }
3371 
3372  protected:
3373 
3374  const ExprT1& expr1;
3375  ExprT2 expr2;
3376  mutable value_type v;
3377  mutable bool min_v1;
3378 
3379  };
3380 
3381  template <typename T1, typename ExprT2>
3382  class Expr< MinOp< ConstExpr<T1>,ExprT2> > {
3383 
3384  public:
3385 
3386  typedef ConstExpr<T1> ExprT1;
3387  typedef typename ExprT1::value_type value_type_1;
3388  typedef typename ExprT2::value_type value_type_2;
3389  typedef typename Sacado::Promote<value_type_1,
3390  value_type_2>::type value_type;
3391  typedef typename ExprT1::scalar_type scalar_type_1;
3392  typedef typename ExprT2::scalar_type scalar_type_2;
3393  typedef typename Sacado::Promote<scalar_type_1,
3394  scalar_type_2>::type scalar_type;
3395 
3396  typedef typename ExprT1::base_expr_type base_expr_type_1;
3397  typedef typename ExprT2::base_expr_type base_expr_type_2;
3398  typedef typename Sacado::Promote<base_expr_type_1,
3399  base_expr_type_2>::type base_expr_type;
3400 
3401  static const int num_args = ExprT2::num_args;
3402 
3403  static const bool is_linear = false;
3404 
3406  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
3407  expr1(expr1_), expr2(expr2_) {}
3408 
3410  int size() const {
3411  return expr2.size();
3412  }
3413 
3414  template <int Arg>
3416  bool isActive() const {
3417  return expr2.template isActive<Arg>();
3418  }
3419 
3421  bool updateValue() const {
3422  return expr2.updateValue();
3423  }
3424 
3426  void cache() const {
3427  expr2.cache();
3428  const value_type_1 v1 = expr1.val();
3429  const value_type_2 v2 = expr2.val();
3430  min_v1 = (v1 <= v2);
3431  v = min_v1 ? v1 : v2;
3432  }
3433 
3435  value_type val() const {
3436  return v;
3437  }
3438 
3440  void computePartials(const value_type& bar,
3441  value_type partials[]) const {
3442  if (min_v1)
3443  expr2.computePartials(value_type(0.0), partials);
3444  else
3445  expr2.computePartials(bar, partials);
3446  }
3447 
3449  void getTangents(int i, value_type dots[]) const {
3450  expr2.getTangents(i, dots);
3451  }
3452 
3453  template <int Arg>
3455  value_type getTangent(int i) const {
3456  return expr2.template getTangent<Arg>(i);
3457  }
3458 
3460  bool isLinear() const {
3461  return false;
3462  }
3463 
3465  bool hasFastAccess() const {
3466  return expr2.hasFastAccess();
3467  }
3468 
3470  const value_type dx(int i) const {
3471  return min_v1 ? value_type(0.0) : expr2.dx(i);
3472  }
3473 
3475  const value_type fastAccessDx(int i) const {
3476  return min_v1 ? value_type(0.0) : expr2.fastAccessDx(i);
3477  }
3478 
3480  const value_type* getDx(int j) const {
3481  return expr2.getDx(j);
3482  }
3483 
3484  protected:
3485 
3486  ExprT1 expr1;
3487  const ExprT2& expr2;
3488  mutable value_type v;
3489  mutable bool min_v1;
3490 
3491  };
3492 
3493  }
3494 
3495 }
3496 
3497 #define FAD_BINARYOP_MACRO(OPNAME,OP) \
3498 namespace Sacado { \
3499  namespace ELRCacheFad { \
3500  \
3501  template <typename T1, typename T2> \
3502  SACADO_INLINE_FUNCTION \
3503  SACADO_FAD_OP_ENABLE_EXPR_EXPR(OP) \
3504  OPNAME (const T1& expr1, const T2& expr2) \
3505  { \
3506  typedef OP< T1, T2 > expr_t; \
3507  \
3508  return Expr<expr_t>(expr1, expr2); \
3509  } \
3510  \
3511  template <typename T> \
3512  SACADO_INLINE_FUNCTION \
3513  Expr< OP< Expr<T>, Expr<T> > > \
3514  OPNAME (const Expr<T>& expr1, const Expr<T>& expr2) \
3515  { \
3516  typedef OP< Expr<T>, Expr<T> > expr_t; \
3517  \
3518  return Expr<expr_t>(expr1, expr2); \
3519  } \
3520  \
3521  template <typename T> \
3522  SACADO_INLINE_FUNCTION \
3523  Expr< OP< ConstExpr<typename Expr<T>::value_type>, \
3524  Expr<T> > > \
3525  OPNAME (const typename Expr<T>::value_type& c, \
3526  const Expr<T>& expr) \
3527  { \
3528  typedef ConstExpr<typename Expr<T>::value_type> ConstT; \
3529  typedef OP< ConstT, Expr<T> > expr_t; \
3530  \
3531  return Expr<expr_t>(ConstT(c), expr); \
3532  } \
3533  \
3534  template <typename T> \
3535  SACADO_INLINE_FUNCTION \
3536  Expr< OP< Expr<T>, \
3537  ConstExpr<typename Expr<T>::value_type> > > \
3538  OPNAME (const Expr<T>& expr, \
3539  const typename Expr<T>::value_type& c) \
3540  { \
3541  typedef ConstExpr<typename Expr<T>::value_type> ConstT; \
3542  typedef OP< Expr<T>, ConstT > expr_t; \
3543  \
3544  return Expr<expr_t>(expr, ConstT(c)); \
3545  } \
3546  \
3547  template <typename T> \
3548  SACADO_INLINE_FUNCTION \
3549  SACADO_FAD_OP_ENABLE_SCALAR_EXPR(OP) \
3550  OPNAME (const typename Expr<T>::scalar_type& c, \
3551  const Expr<T>& expr) \
3552  { \
3553  typedef ConstExpr<typename Expr<T>::scalar_type> ConstT; \
3554  typedef OP< ConstT, Expr<T> > expr_t; \
3555  \
3556  return Expr<expr_t>(ConstT(c), expr); \
3557  } \
3558  \
3559  template <typename T> \
3560  SACADO_INLINE_FUNCTION \
3561  SACADO_FAD_OP_ENABLE_EXPR_SCALAR(OP) \
3562  OPNAME (const Expr<T>& expr, \
3563  const typename Expr<T>::scalar_type& c) \
3564  { \
3565  typedef ConstExpr<typename Expr<T>::scalar_type> ConstT; \
3566  typedef OP< Expr<T>, ConstT > expr_t; \
3567  \
3568  return Expr<expr_t>(expr, ConstT(c)); \
3569  } \
3570  } \
3571 }
3572 
3573 
3574 FAD_BINARYOP_MACRO(operator+, AdditionOp)
3577 FAD_BINARYOP_MACRO(operator/, DivisionOp)
3582 
3583 #undef FAD_BINARYOP_MACRO
3584 
3585 //-------------------------- Relational Operators -----------------------
3586 
3587 #define FAD_RELOP_MACRO(OP) \
3588 namespace Sacado { \
3589  namespace ELRCacheFad { \
3590  template <typename ExprT1, typename ExprT2> \
3591  SACADO_INLINE_FUNCTION \
3592  bool \
3593  operator OP (const Expr<ExprT1>& expr1, \
3594  const Expr<ExprT2>& expr2) \
3595  { \
3596  expr1.cache(); \
3597  expr2.cache(); \
3598  return expr1.val() OP expr2.val(); \
3599  } \
3600  \
3601  template <typename ExprT2> \
3602  SACADO_INLINE_FUNCTION \
3603  bool \
3604  operator OP (const typename Expr<ExprT2>::value_type& a, \
3605  const Expr<ExprT2>& expr2) \
3606  { \
3607  expr2.cache(); \
3608  return a OP expr2.val(); \
3609  } \
3610  \
3611  template <typename ExprT1> \
3612  SACADO_INLINE_FUNCTION \
3613  bool \
3614  operator OP (const Expr<ExprT1>& expr1, \
3615  const typename Expr<ExprT1>::value_type& b) \
3616  { \
3617  expr1.cache(); \
3618  return expr1.val() OP b; \
3619  } \
3620  } \
3621 }
3622 
3623 FAD_RELOP_MACRO(==)
3624 FAD_RELOP_MACRO(!=)
3625 FAD_RELOP_MACRO(<)
3626 FAD_RELOP_MACRO(>)
3627 FAD_RELOP_MACRO(<=)
3628 FAD_RELOP_MACRO(>=)
3629 FAD_RELOP_MACRO(<<=)
3630 FAD_RELOP_MACRO(>>=)
3631 FAD_RELOP_MACRO(&)
3632 FAD_RELOP_MACRO(|)
3633 
3634 #undef FAD_RELOP_MACRO
3635 
3636 namespace Sacado {
3637 
3638  namespace ELRCacheFad {
3639 
3640  template <typename ExprT>
3642  bool operator ! (const Expr<ExprT>& expr)
3643  {
3644  expr.cache();
3645  return ! expr.val();
3646  }
3647 
3648  } // namespace ELRCacheFad
3649 
3650 } // namespace Sacado
3651 
3652 //-------------------------- Boolean Operators -----------------------
3653 namespace Sacado {
3654 
3655  namespace ELRCacheFad {
3656 
3657  template <typename ExprT>
3659  bool toBool(const Expr<ExprT>& x) {
3660  x.cache();
3661  bool is_zero = (x.val() == 0.0);
3662  for (int i=0; i<x.size(); i++)
3663  is_zero = is_zero && (x.dx(i) == 0.0);
3664  return !is_zero;
3665  }
3666 
3667  } // namespace Fad
3668 
3669 } // namespace Sacado
3670 
3671 #define FAD_BOOL_MACRO(OP) \
3672 namespace Sacado { \
3673  namespace ELRCacheFad { \
3674  template <typename ExprT1, typename ExprT2> \
3675  SACADO_INLINE_FUNCTION \
3676  bool \
3677  operator OP (const Expr<ExprT1>& expr1, \
3678  const Expr<ExprT2>& expr2) \
3679  { \
3680  return toBool(expr1) OP toBool(expr2); \
3681  } \
3682  \
3683  template <typename ExprT2> \
3684  SACADO_INLINE_FUNCTION \
3685  bool \
3686  operator OP (const typename Expr<ExprT2>::value_type& a, \
3687  const Expr<ExprT2>& expr2) \
3688  { \
3689  return a OP toBool(expr2); \
3690  } \
3691  \
3692  template <typename ExprT1> \
3693  SACADO_INLINE_FUNCTION \
3694  bool \
3695  operator OP (const Expr<ExprT1>& expr1, \
3696  const typename Expr<ExprT1>::value_type& b) \
3697  { \
3698  return toBool(expr1) OP b; \
3699  } \
3700  } \
3701 }
3702 
3703 FAD_BOOL_MACRO(&&)
3704 FAD_BOOL_MACRO(||)
3705 
3706 #undef FAD_BOOL_MACRO
3707 
3708 //-------------------------- I/O Operators -----------------------
3709 
3710 namespace Sacado {
3711 
3712  namespace ELRCacheFad {
3713 
3714  template <typename ExprT>
3715  std::ostream& operator << (std::ostream& os, const Expr<ExprT>& x) {
3716  os << x.val() << " [";
3717 
3718  for (int i=0; i< x.size(); i++) {
3719  os << " " << x.dx(i);
3720  }
3721 
3722  os << " ]";
3723  return os;
3724  }
3725 
3726  } // namespace Fad
3727 
3728 } // namespace Sacado
3729 
3730 #endif // SACADO_CACHEFAD_OPS_HPP
SACADO_INLINE_FUNCTION const value_type fastAccessDx(int i) const
SACADO_INLINE_FUNCTION const value_type dx(int i) const
cbrt(expr.val())
expr2 expr1 expr2 expr2 c *expr2 c *expr1 c *expr2 c *expr1 MaxOp
asinh(expr.val())
SACADO_INLINE_FUNCTION bool isActive() const
SACADO_INLINE_FUNCTION Expr(const ExprT &expr_)
asin(expr.val())
cosh(expr.val())
SACADO_INLINE_FUNCTION void computePartials(const value_type &bar, value_type partials[]) const
expr expr dx(i)
float acosh(float x)
#define FAD_UNARYOP_MACRO(OPNAME, OP, PARTIAL, VALUE)
SACADO_INLINE_FUNCTION bool isLinear() const
atanh(expr.val())
SACADO_INLINE_FUNCTION value_type val() const
SACADO_INLINE_FUNCTION bool hasFastAccess() const
SACADO_INLINE_FUNCTION value_type val() const
SACADO_INLINE_FUNCTION void computePartials(const value_type &bar, value_type partials[]) const
SACADO_INLINE_FUNCTION value_type getTangent(int i) const
atan(expr.val())
SACADO_INLINE_FUNCTION void computePartials(const value_type &bar, value_type partials[]) const
SACADO_INLINE_FUNCTION const value_type dx(int i) const
expr1 expr1 expr2 expr1 expr1 c expr2 expr1 expr2 expr1 expr2 expr1 MultiplicationOp
SACADO_INLINE_FUNCTION bool toBool(const Expr< ExprT > &x)
SACADO_INLINE_FUNCTION value_type val() const
SACADO_INLINE_FUNCTION Expr< FAbsOp< Expr< T > > > fabs(const Expr< T > &expr)
SACADO_INLINE_FUNCTION const value_type fastAccessDx(int i) const
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 val()
SACADO_INLINE_FUNCTION const value_type * getDx(int j) const
SACADO_INLINE_FUNCTION const value_type fastAccessDx(int i) const
SACADO_INLINE_FUNCTION value_type val() const
tanh(expr.val())
float asinh(float x)
#define T2(r, f)
Definition: Sacado_rad.hpp:578
SimpleFad< ValueT > min(const SimpleFad< ValueT > &a, const SimpleFad< ValueT > &b)
SACADO_INLINE_FUNCTION Expr< UnaryPlusOp< Expr< T > > > operator+(const Expr< T > &expr)
SACADO_INLINE_FUNCTION bool updateValue() const
SACADO_INLINE_FUNCTION bool hasFastAccess() const
#define FAD_RELOP_MACRO(OP)
SACADO_INLINE_FUNCTION value_type getTangent(int i) const
SACADO_INLINE_FUNCTION Expr(const ExprT &expr_)
sqrt(expr.val())
Wrapper for a generic expression template.
sinh(expr.val())
tan(expr.val())
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
SACADO_INLINE_FUNCTION const value_type * getDx(int j) const
#define T1(r, f)
Definition: Sacado_rad.hpp:603
SACADO_INLINE_FUNCTION void getTangents(int i, value_type dots[]) const
SACADO_INLINE_FUNCTION bool isLinear() const
SACADO_INLINE_FUNCTION const value_type dx(int i) const
#define FAD_BOOL_MACRO(OP)
SACADO_INLINE_FUNCTION void getTangents(int i, value_type dots[]) const
atan2(expr1.val(), expr2.val())
SACADO_INLINE_FUNCTION bool operator!(const Expr< ExprT > &expr)
SACADO_INLINE_FUNCTION bool updateValue() const
SACADO_INLINE_FUNCTION Expr< AbsOp< Expr< T > > > abs(const Expr< T > &expr)
sin(expr.val())
SACADO_INLINE_FUNCTION const value_type * getDx(int j) const
expr expr expr fastAccessDx(i)) FAD_UNARYOP_MACRO(exp
SACADO_INLINE_FUNCTION T safe_sqrt(const T &x)
SACADO_INLINE_FUNCTION bool isActive() const
log(expr.val())
acosh(expr.val())
SACADO_INLINE_FUNCTION Expr(const ExprT &expr_)
SACADO_INLINE_FUNCTION Expr< UnaryMinusOp< Expr< T > > > operator-(const Expr< T > &expr)
acos(expr.val())
SimpleFad< ValueT > max(const SimpleFad< ValueT > &a, const SimpleFad< ValueT > &b)
SACADO_INLINE_FUNCTION Expr(const ExprT &expr_)
float atanh(float x)
SACADO_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)
SACADO_INLINE_FUNCTION const value_type fastAccessDx(int i) const
SACADO_INLINE_FUNCTION void computePartials(const value_type &bar, value_type partials[]) const
SACADO_INLINE_FUNCTION void getTangents(int i, value_type dots[]) const
#define SACADO_INLINE_FUNCTION
exp(expr.val())
SACADO_INLINE_FUNCTION value_type getTangent(int i) const
SACADO_INLINE_FUNCTION void getTangents(int i, value_type dots[]) const
#define FAD_BINARYOP_MACRO(OPNAME, OP)
expr expr expr ExpOp
SACADO_INLINE_FUNCTION const value_type dx(int i) const
SACADO_INLINE_FUNCTION const value_type * getDx(int j) const
log10(expr.val())
Base template specification for Promote.
cos(expr.val())
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