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 <ostream> // for std::ostream
59 
60 namespace Sacado {
61  namespace ELRCacheFad {
62 
63  //
64  // UnaryPlusOp
65  //
66 
67  template <typename ExprT>
68  class UnaryPlusOp {};
69 
70  template <typename ExprT>
71  class Expr< UnaryPlusOp<ExprT> > {
72  public:
73 
74  typedef typename ExprT::value_type value_type;
75  typedef typename ExprT::scalar_type scalar_type;
76 
77  typedef typename ExprT::base_expr_type base_expr_type;
78 
79  static const int num_args = ExprT::num_args;
80 
81  static const bool is_linear = true;
82 
84  explicit Expr(const ExprT& expr_) : expr(expr_) {}
85 
87  int size() const { return expr.size(); }
88 
89  template <int Arg>
91  bool isActive() const { return expr.template isActive<Arg>(); }
92 
94  bool updateValue() const { return expr.updateValue(); }
95 
97  void cache() const {
98  expr.cache();
99  }
100 
102  value_type val() const {
103  return expr.val();
104  }
105 
108  value_type partials[]) const {
109  expr.computePartials(bar, partials);
110  }
111 
113  void getTangents(int i, value_type dots[]) const {
114  expr.getTangents(i, dots); }
115 
116  template <int Arg>
117  value_type getTangent(int i) const {
118  return expr.template getTangent<Arg>(i);
119  }
120 
122  bool isLinear() const {
123  return expr.isLinear();
124  }
125 
127  bool hasFastAccess() const {
128  return expr.hasFastAccess();
129  }
130 
132  const value_type dx(int i) const {
133  return expr.dx(i);
134  }
135 
137  const value_type fastAccessDx(int i) const {
138  return expr.fastAccessDx(i);
139  }
140 
142  const value_type* getDx(int j) const {
143  return expr.getDx(j);
144  }
145 
146  protected:
147 
148  const ExprT& expr;
149  };
150 
151  template <typename T>
154  operator+ (const Expr<T>& expr)
155  {
156  typedef UnaryPlusOp< Expr<T> > expr_t;
157 
158  return Expr<expr_t>(expr);
159  }
160 
161  //
162  // UnaryMinusOp
163  //
164  template <typename ExprT>
165  class UnaryMinusOp {};
166 
167  template <typename ExprT>
168  class Expr< UnaryMinusOp<ExprT> > {
169  public:
170 
171  typedef typename ExprT::value_type value_type;
172  typedef typename ExprT::scalar_type scalar_type;
173 
174  typedef typename ExprT::base_expr_type base_expr_type;
175 
176  static const int num_args = ExprT::num_args;
177 
178  static const bool is_linear = true;
179 
181  explicit Expr(const ExprT& expr_) : expr(expr_) {}
182 
184  int size() const { return expr.size(); }
185 
186  template <int Arg>
188  bool isActive() const { return expr.template isActive<Arg>(); }
189 
191  bool updateValue() const { return expr.updateValue(); }
192 
194  void cache() const {
195  expr.cache();
196  }
197 
199  value_type val() const {
200  return -expr.val();
201  }
202 
205  value_type partials[]) const {
206  expr.computePartials(-bar, partials);
207  }
208 
210  void getTangents(int i, value_type dots[]) const {
211  expr.getTangents(i, dots); }
212 
213  template <int Arg>
215  value_type getTangent(int i) const {
216  return expr.template getTangent<Arg>(i);
217  }
218 
220  bool isLinear() const {
221  return expr.isLinear();
222  }
223 
225  bool hasFastAccess() const {
226  return expr.hasFastAccess();
227  }
228 
230  const value_type dx(int i) const {
231  return -expr.dx(i);
232  }
233 
235  const value_type fastAccessDx(int i) const {
236  return -expr.fastAccessDx(i);
237  }
238 
240  const value_type* getDx(int j) const {
241  return expr.getDx(j);
242  }
243 
244  protected:
245 
246  const ExprT& expr;
247  };
248 
249  template <typename T>
252  operator- (const Expr<T>& expr)
253  {
254  typedef UnaryMinusOp< Expr<T> > expr_t;
255 
256  return Expr<expr_t>(expr);
257  }
258 
259  //
260  // AbsOp
261  //
262 
263  template <typename ExprT>
264  class AbsOp {};
265 
266  template <typename ExprT>
267  class Expr< AbsOp<ExprT> > {
268  public:
269 
270  typedef typename ExprT::value_type value_type;
271  typedef typename ExprT::scalar_type scalar_type;
272 
273  typedef typename ExprT::base_expr_type base_expr_type;
274 
275  static const int num_args = ExprT::num_args;
276 
277  static const bool is_linear = false;
278 
280  explicit Expr(const ExprT& expr_) : expr(expr_) {}
281 
283  int size() const { return expr.size(); }
284 
285  template <int Arg>
287  bool isActive() const { return expr.template isActive<Arg>(); }
288 
290  bool updateValue() const { return expr.updateValue(); }
291 
293  void cache() const {
294  expr.cache();
295  v = expr.val();
296  v_pos = (v >= 0);
297  }
298 
300  value_type val() const {
301  return std::abs(v);
302  }
303 
306  value_type partials[]) const {
307  if (v_pos)
308  expr.computePartials(bar, partials);
309  else
310  expr.computePartials(-bar, partials);
311  }
312 
314  void getTangents(int i, value_type dots[]) const {
315  expr.getTangents(i, dots); }
316 
317  template <int Arg>
319  value_type getTangent(int i) const {
320  return expr.template getTangent<Arg>(i);
321  }
322 
324  bool isLinear() const {
325  return false;
326  }
327 
329  bool hasFastAccess() const {
330  return expr.hasFastAccess();
331  }
332 
334  const value_type dx(int i) const {
335  if (v_pos) return expr.dx(i);
336  else return -expr.dx(i);
337  }
338 
340  const value_type fastAccessDx(int i) const {
341  if (v_pos) return expr.fastAccessDx(i);
342  else return -expr.fastAccessDx(i);
343  }
344 
346  const value_type* getDx(int j) const {
347  return expr.getDx(j);
348  }
349 
350  protected:
351 
352  const ExprT& expr;
353  mutable value_type v;
354  mutable bool v_pos;
355  };
356 
357  template <typename T>
360  abs (const Expr<T>& expr)
361  {
362  typedef AbsOp< Expr<T> > expr_t;
363 
364  return Expr<expr_t>(expr);
365  }
366 
367  //
368  // FAbsOp
369  //
370 
371  template <typename ExprT>
372  class FAbsOp {};
373 
374  template <typename ExprT>
375  class Expr< FAbsOp<ExprT> > {
376  public:
377 
378  typedef typename ExprT::value_type value_type;
379  typedef typename ExprT::scalar_type scalar_type;
380 
381  typedef typename ExprT::base_expr_type base_expr_type;
382 
383  static const int num_args = ExprT::num_args;
384 
385  static const bool is_linear = false;
386 
388  explicit Expr(const ExprT& expr_) : expr(expr_) {}
389 
391  int size() const { return expr.size(); }
392 
393  template <int Arg>
395  bool isActive() const { return expr.template isActive<Arg>(); }
396 
398  bool updateValue() const { return expr.updateValue(); }
399 
401  void cache() const {
402  expr.cache();
403  v = expr.val();
404  v_pos = (v >= 0);
405  }
406 
408  value_type val() const {
409  return std::fabs(v);
410  }
411 
414  value_type partials[]) const {
415  if (v_pos)
416  expr.computePartials(bar, partials);
417  else
418  expr.computePartials(-bar, partials);
419  }
420 
422  void getTangents(int i, value_type dots[]) const {
423  expr.getTangents(i, dots); }
424 
425  template <int Arg>
427  value_type getTangent(int i) const {
428  return expr.template getTangent<Arg>(i);
429  }
430 
432  bool isLinear() const {
433  return false;
434  }
435 
437  bool hasFastAccess() const {
438  return expr.hasFastAccess();
439  }
440 
442  const value_type dx(int i) const {
443  if (v_pos) return expr.dx(i);
444  else return -expr.dx(i);
445  }
446 
448  const value_type fastAccessDx(int i) const {
449  if (v_pos) return expr.fastAccessDx(i);
450  else return -expr.fastAccessDx(i);
451  }
452 
454  const value_type* getDx(int j) const {
455  return expr.getDx(j);
456  }
457 
458  protected:
459 
460  const ExprT& expr;
461  mutable value_type v;
462  mutable bool v_pos;
463  };
464 
465  template <typename T>
468  fabs (const Expr<T>& expr)
469  {
470  typedef FAbsOp< Expr<T> > expr_t;
471 
472  return Expr<expr_t>(expr);
473  }
474 
475  }
476 }
477 
478 #define FAD_UNARYOP_MACRO(OPNAME,OP,PARTIAL,VALUE) \
479 namespace Sacado { \
480  namespace ELRCacheFad { \
481  \
482  template <typename ExprT> \
483  class OP {}; \
484  \
485  template <typename ExprT> \
486  class Expr< OP<ExprT> > { \
487  public: \
488  \
489  typedef typename ExprT::value_type value_type; \
490  typedef typename ExprT::scalar_type scalar_type; \
491  \
492  typedef typename ExprT::base_expr_type base_expr_type; \
493  \
494  static const int num_args = ExprT::num_args; \
495  \
496  static const bool is_linear = false; \
497  \
498  SACADO_INLINE_FUNCTION \
499  explicit Expr(const ExprT& expr_) : expr(expr_) {} \
500  \
501  SACADO_INLINE_FUNCTION \
502  int size() const { return expr.size(); } \
503  \
504  template <int Arg> \
505  SACADO_INLINE_FUNCTION \
506  bool isActive() const { return expr.template isActive<Arg>(); } \
507  \
508  SACADO_INLINE_FUNCTION \
509  bool updateValue() const { return expr.updateValue(); } \
510  \
511  SACADO_INLINE_FUNCTION \
512  void cache() const { \
513  expr.cache(); \
514  v = expr.val(); \
515  PARTIAL; \
516  } \
517  \
518  SACADO_INLINE_FUNCTION \
519  value_type val() const { \
520  return VALUE; \
521  } \
522  \
523  SACADO_INLINE_FUNCTION \
524  void computePartials(const value_type& bar, \
525  value_type partials[]) const { \
526  expr.computePartials(bar*a, partials); \
527  } \
528  \
529  SACADO_INLINE_FUNCTION \
530  void getTangents(int i, value_type dots[]) const { \
531  expr.getTangents(i, dots); } \
532  \
533  template <int Arg> \
534  SACADO_INLINE_FUNCTION \
535  value_type getTangent(int i) const { \
536  return expr.template getTangent<Arg>(i); \
537  } \
538  \
539  SACADO_INLINE_FUNCTION \
540  bool isLinear() const { \
541  return false; \
542  } \
543  \
544  SACADO_INLINE_FUNCTION \
545  bool hasFastAccess() const { \
546  return expr.hasFastAccess(); \
547  } \
548  \
549  SACADO_INLINE_FUNCTION \
550  const value_type dx(int i) const { \
551  return expr.dx(i)*a; \
552  } \
553  \
554  SACADO_INLINE_FUNCTION \
555  const value_type fastAccessDx(int i) const { \
556  return expr.fastAccessDx(i)*a; \
557  } \
558  \
559  SACADO_INLINE_FUNCTION \
560  const value_type* getDx(int j) const { \
561  return expr.getDx(j); \
562  } \
563  \
564  protected: \
565  \
566  const ExprT& expr; \
567  mutable value_type v; \
568  mutable value_type a; \
569  }; \
570  \
571  template <typename T> \
572  SACADO_INLINE_FUNCTION \
573  Expr< OP< Expr<T> > > \
574  OPNAME (const Expr<T>& expr) \
575  { \
576  typedef OP< Expr<T> > expr_t; \
577  \
578  return Expr<expr_t>(expr); \
579  } \
580  } \
581 }
582 
584  ExpOp,
585  a = std::exp(v),
586  a)
589  a=scalar_type(1.0)/v,
590  std::log(v))
593  a = scalar_type(1.0)/(std::log(scalar_type(10.0))*v),
594  std::log10(v))
597  a = scalar_type(1.0)/(scalar_type(2.0)*std::sqrt(v)),
598  std::sqrt(v))
601  a = (v == value_type(0.0) ? value_type(0.0) : value_type(scalar_type(1.0)/(scalar_type(2.0)*std::sqrt(v)))),
602  std::sqrt(v))
605  a = -std::sin(v),
606  std::cos(v))
609  a = std::cos(v),
610  std::sin(v))
613  a = scalar_type(1.0)+std::tan(v)*std::tan(v),
614  std::tan(v))
617  a = scalar_type(-1.0)/std::sqrt(scalar_type(1.0)-v*v),
618  std::acos(v))
621  a = scalar_type(1.0)/std::sqrt(scalar_type(1.0)-v*v),
622  std::asin(v))
625  a = scalar_type(1.0)/(scalar_type(1.0)+v*v),
626  std::atan(v))
629  a = std::sinh(v),
630  std::cosh(v))
633  a = std::cosh(v),
634  std::sinh(v))
637  a = scalar_type(1.0)-std::tanh(v)*std::tanh(v),
638  std::tanh(v))
641  a = scalar_type(1.0)/std::sqrt((v-scalar_type(1.0))*(v+scalar_type(1.0))),
642  std::acosh(v))
645  a = scalar_type(1.0)/std::sqrt(scalar_type(1.0)+v*v),
646  std::asinh(v))
649  a = scalar_type(1.0)/(scalar_type(1.0)-v*v),
650  std::atanh(v))
653  a = scalar_type(1.0)/(scalar_type(3.0)*std::cbrt(v*v)),
654  std::cbrt(v))
655 
656 #undef FAD_UNARYOP_MACRO
657 
658 //
659 // Binary operators
660 //
661 namespace Sacado {
662  namespace ELRCacheFad {
663 
664  //
665  // AdditionOp
666  //
667 
668  template <typename ExprT1, typename ExprT2>
669  class AdditionOp {};
670 
671  template <typename ExprT1, typename ExprT2>
672  class Expr< AdditionOp<ExprT1,ExprT2> > {
673 
674  public:
675 
676  typedef typename ExprT1::value_type value_type_1;
677  typedef typename ExprT2::value_type value_type_2;
678  typedef typename Sacado::Promote<value_type_1,
679  value_type_2>::type value_type;
680  typedef typename ExprT1::scalar_type scalar_type_1;
681  typedef typename ExprT2::scalar_type scalar_type_2;
682  typedef typename Sacado::Promote<scalar_type_1,
683  scalar_type_2>::type scalar_type;
684 
685  typedef typename ExprT1::base_expr_type base_expr_type_1;
686  typedef typename ExprT2::base_expr_type base_expr_type_2;
687  typedef typename Sacado::Promote<base_expr_type_1,
688  base_expr_type_2>::type base_expr_type;
689 
690  static const int num_args1 = ExprT1::num_args;
691  static const int num_args2 = ExprT2::num_args;
692  static const int num_args = num_args1 + num_args2;
693 
694  static const bool is_linear = ExprT1::is_linear && ExprT2::is_linear;
695 
697  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
698  expr1(expr1_), expr2(expr2_) {}
699 
701  int size() const {
702  int sz1 = expr1.size(), sz2 = expr2.size();
703  return sz1 > sz2 ? sz1 : sz2;
704  }
705 
706  template <int Arg>
708  bool isActive() const {
709  if (Arg < num_args1)
710  return expr1.template isActive<Arg>();
711  else
712  return expr2.template isActive<Arg-num_args1>();
713  }
714 
716  bool updateValue() const {
717  return expr1.updateValue() && expr2.updateValue();
718  }
719 
721  void cache() const {
722  expr1.cache();
723  expr2.cache();
724  }
725 
727  value_type val() const {
728  return expr1.val()+expr2.val();
729  }
730 
732  void computePartials(const value_type& bar,
733  value_type partials[]) const {
734  if (num_args1 > 0)
735  expr1.computePartials(bar, partials);
736  if (num_args2 > 0)
737  expr2.computePartials(bar, partials+num_args1);
738  }
739 
741  void getTangents(int i, value_type dots[]) const {
742  expr1.getTangents(i, dots);
743  expr2.getTangents(i, dots+num_args1);
744  }
745 
746  template <int Arg>
748  value_type getTangent(int i) const {
749  if (Arg < num_args1)
750  return expr1.template getTangent<Arg>(i);
751  else
752  return expr2.template getTangent<Arg-num_args1>(i);
753  }
754 
756  bool isLinear() const {
757  return expr1.isLinear() && expr2.isLinear();
758  }
759 
761  bool hasFastAccess() const {
762  return expr1.hasFastAccess() && expr2.hasFastAccess();
763  }
764 
766  const value_type dx(int i) const {
767  return expr1.dx(i) + expr2.dx(i);
768  }
769 
771  const value_type fastAccessDx(int i) const {
772  return expr1.fastAccessDx(i) + expr2.fastAccessDx(i);
773  }
774 
776  const value_type* getDx(int j) const {
777  if (j < num_args1)
778  return expr1.getDx(j);
779  else
780  return expr2.getDx(j-num_args1);
781  }
782 
783  protected:
784 
785  const ExprT1& expr1;
786  const ExprT2& expr2;
787 
788  };
789 
790  template <typename ExprT1, typename T2>
791  class Expr< AdditionOp<ExprT1, ConstExpr<T2> > > {
792 
793  public:
794 
795  typedef ConstExpr<T2> ExprT2;
796  typedef typename ExprT1::value_type value_type_1;
797  typedef typename ExprT2::value_type value_type_2;
798  typedef typename Sacado::Promote<value_type_1,
799  value_type_2>::type value_type;
800  typedef typename ExprT1::scalar_type scalar_type_1;
801  typedef typename ExprT2::scalar_type scalar_type_2;
802  typedef typename Sacado::Promote<scalar_type_1,
803  scalar_type_2>::type scalar_type;
804 
805  typedef typename ExprT1::base_expr_type base_expr_type_1;
806  typedef typename ExprT2::base_expr_type base_expr_type_2;
807  typedef typename Sacado::Promote<base_expr_type_1,
808  base_expr_type_2>::type base_expr_type;
809 
810  static const int num_args = ExprT1::num_args;
811 
812  static const bool is_linear = ExprT1::is_linear;
813 
815  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
816  expr1(expr1_), expr2(expr2_) {}
817 
819  int size() const {
820  return expr1.size();
821  }
822 
823  template <int Arg>
825  bool isActive() const {
826  return expr1.template isActive<Arg>();
827  }
828 
830  bool updateValue() const {
831  return expr1.updateValue();
832  }
833 
835  void cache() const {
836  expr1.cache();
837  }
838 
840  value_type val() const {
841  return expr1.val() + expr2.val();
842  }
843 
845  void computePartials(const value_type& bar,
846  value_type partials[]) const {
847  expr1.computePartials(bar, partials);
848  }
849 
851  void getTangents(int i, value_type dots[]) const {
852  expr1.getTangents(i, dots);
853  }
854 
855  template <int Arg>
857  value_type getTangent(int i) const {
858  return expr1.template getTangent<Arg>(i);
859  }
860 
862  bool isLinear() const {
863  return expr1.isLinear();
864  }
865 
867  bool hasFastAccess() const {
868  return expr1.hasFastAccess();
869  }
870 
872  const value_type dx(int i) const {
873  return expr1.dx(i);
874  }
875 
877  const value_type fastAccessDx(int i) const {
878  return expr1.fastAccessDx(i);
879  }
880 
882  const value_type* getDx(int j) const {
883  return expr1.getDx(j);
884  }
885 
886  protected:
887 
888  const ExprT1& expr1;
889  ExprT2 expr2;
890 
891  };
892 
893  template <typename T1, typename ExprT2>
894  class Expr< AdditionOp< ConstExpr<T1>,ExprT2> > {
895 
896  public:
897 
898  typedef ConstExpr<T1> ExprT1;
899  typedef typename ExprT1::value_type value_type_1;
900  typedef typename ExprT2::value_type value_type_2;
901  typedef typename Sacado::Promote<value_type_1,
902  value_type_2>::type value_type;
903  typedef typename ExprT1::scalar_type scalar_type_1;
904  typedef typename ExprT2::scalar_type scalar_type_2;
905  typedef typename Sacado::Promote<scalar_type_1,
906  scalar_type_2>::type scalar_type;
907 
908  typedef typename ExprT1::base_expr_type base_expr_type_1;
909  typedef typename ExprT2::base_expr_type base_expr_type_2;
910  typedef typename Sacado::Promote<base_expr_type_1,
911  base_expr_type_2>::type base_expr_type;
912 
913  static const int num_args = ExprT2::num_args;
914 
915  static const bool is_linear = ExprT2::is_linear;
916 
918  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
919  expr1(expr1_), expr2(expr2_) {}
920 
922  int size() const {
923  return expr2.size();
924  }
925 
926  template <int Arg>
928  bool isActive() const {
929  return expr2.template isActive<Arg>();
930  }
931 
933  bool updateValue() const {
934  return expr2.updateValue();
935  }
936 
938  void cache() const {
939  expr2.cache();
940  }
941 
943  value_type val() const {
944  return expr1.val() + expr2.val();
945  }
946 
948  void computePartials(const value_type& bar,
949  value_type partials[]) const {
950  expr2.computePartials(bar, partials);
951  }
952 
954  void getTangents(int i, value_type dots[]) const {
955  expr2.getTangents(i, dots);
956  }
957 
958  template <int Arg>
960  value_type getTangent(int i) const {
961  return expr2.template getTangent<Arg>(i);
962  }
963 
965  bool isLinear() const {
966  return expr2.isLinear();
967  }
968 
970  bool hasFastAccess() const {
971  return expr2.hasFastAccess();
972  }
973 
975  const value_type dx(int i) const {
976  return expr2.dx(i);
977  }
978 
980  const value_type fastAccessDx(int i) const {
981  return expr2.fastAccessDx(i);
982  }
983 
985  const value_type* getDx(int j) const {
986  return expr2.getDx(j);
987  }
988 
989  protected:
990 
991  ExprT1 expr1;
992  const ExprT2& expr2;
993 
994  };
995 
996  //
997  // SubtractionOp
998  //
999 
1000  template <typename ExprT1, typename ExprT2>
1001  class SubtractionOp {};
1002 
1003  template <typename ExprT1, typename ExprT2>
1004  class Expr< SubtractionOp<ExprT1,ExprT2> > {
1005 
1006  public:
1007 
1008  typedef typename ExprT1::value_type value_type_1;
1009  typedef typename ExprT2::value_type value_type_2;
1010  typedef typename Sacado::Promote<value_type_1,
1011  value_type_2>::type value_type;
1012  typedef typename ExprT1::scalar_type scalar_type_1;
1013  typedef typename ExprT2::scalar_type scalar_type_2;
1014  typedef typename Sacado::Promote<scalar_type_1,
1015  scalar_type_2>::type scalar_type;
1016 
1017  typedef typename ExprT1::base_expr_type base_expr_type_1;
1018  typedef typename ExprT2::base_expr_type base_expr_type_2;
1019  typedef typename Sacado::Promote<base_expr_type_1,
1020  base_expr_type_2>::type base_expr_type;
1021 
1022  static const int num_args1 = ExprT1::num_args;
1023  static const int num_args2 = ExprT2::num_args;
1024  static const int num_args = num_args1 + num_args2;
1025 
1026  static const bool is_linear = ExprT1::is_linear && ExprT2::is_linear;
1027 
1029  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
1030  expr1(expr1_), expr2(expr2_) {}
1031 
1033  int size() const {
1034  int sz1 = expr1.size(), sz2 = expr2.size();
1035  return sz1 > sz2 ? sz1 : sz2;
1036  }
1037 
1038  template <int Arg>
1040  bool isActive() const {
1041  if (Arg < num_args1)
1042  return expr1.template isActive<Arg>();
1043  else
1044  return expr2.template isActive<Arg-num_args1>();
1045  }
1046 
1048  bool updateValue() const {
1049  return expr1.updateValue() && expr2.updateValue();
1050  }
1051 
1053  void cache() const {
1054  expr1.cache();
1055  expr2.cache();
1056  }
1057 
1059  value_type val() const {
1060  return expr1.val()-expr2.val();
1061  }
1062 
1064  void computePartials(const value_type& bar,
1065  value_type partials[]) const {
1066  if (num_args1 > 0)
1067  expr1.computePartials(bar, partials);
1068  if (num_args2 > 0)
1069  expr2.computePartials(-bar, partials+num_args1);
1070  }
1071 
1073  void getTangents(int i, value_type dots[]) const {
1074  expr1.getTangents(i, dots);
1075  expr2.getTangents(i, dots+num_args1);
1076  }
1077 
1078  template <int Arg>
1080  value_type getTangent(int i) const {
1081  if (Arg < num_args1)
1082  return expr1.template getTangent<Arg>(i);
1083  else
1084  return expr2.template getTangent<Arg-num_args1>(i);
1085  }
1086 
1088  bool isLinear() const {
1089  return expr1.isLinear() && expr2.isLinear();
1090  }
1091 
1093  bool hasFastAccess() const {
1094  return expr1.hasFastAccess() && expr2.hasFastAccess();
1095  }
1096 
1098  const value_type dx(int i) const {
1099  return expr1.dx(i) - expr2.dx(i);
1100  }
1101 
1103  const value_type fastAccessDx(int i) const {
1104  return expr1.fastAccessDx(i) - expr2.fastAccessDx(i);
1105  }
1106 
1108  const value_type* getDx(int j) const {
1109  if (j < num_args1)
1110  return expr1.getDx(j);
1111  else
1112  return expr2.getDx(j-num_args1);
1113  }
1114 
1115  protected:
1116 
1117  const ExprT1& expr1;
1118  const ExprT2& expr2;
1119 
1120  };
1121 
1122  template <typename ExprT1, typename T2>
1123  class Expr< SubtractionOp<ExprT1, ConstExpr<T2> > > {
1124 
1125  public:
1126 
1127  typedef ConstExpr<T2> ExprT2;
1128  typedef typename ExprT1::value_type value_type_1;
1129  typedef typename ExprT2::value_type value_type_2;
1130  typedef typename Sacado::Promote<value_type_1,
1131  value_type_2>::type value_type;
1132  typedef typename ExprT1::scalar_type scalar_type_1;
1133  typedef typename ExprT2::scalar_type scalar_type_2;
1134  typedef typename Sacado::Promote<scalar_type_1,
1135  scalar_type_2>::type scalar_type;
1136 
1137  typedef typename ExprT1::base_expr_type base_expr_type_1;
1138  typedef typename ExprT2::base_expr_type base_expr_type_2;
1139  typedef typename Sacado::Promote<base_expr_type_1,
1140  base_expr_type_2>::type base_expr_type;
1141 
1142  static const int num_args = ExprT1::num_args;
1143 
1144  static const bool is_linear = ExprT1::is_linear;
1145 
1147  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
1148  expr1(expr1_), expr2(expr2_) {}
1149 
1151  int size() const {
1152  return expr1.size();
1153  }
1154 
1155  template <int Arg>
1157  bool isActive() const {
1158  return expr1.template isActive<Arg>();
1159  }
1160 
1162  bool updateValue() const {
1163  return expr1.updateValue();
1164  }
1165 
1167  void cache() const {
1168  expr1.cache();
1169  }
1170 
1172  value_type val() const {
1173  return expr1.val() - expr2.val();
1174  }
1175 
1177  void computePartials(const value_type& bar,
1178  value_type partials[]) const {
1179  expr1.computePartials(bar, partials);
1180  }
1181 
1183  void getTangents(int i, value_type dots[]) const {
1184  expr1.getTangents(i, dots);
1185  }
1186 
1187  template <int Arg>
1189  value_type getTangent(int i) const {
1190  return expr1.template getTangent<Arg>(i);
1191  }
1192 
1194  bool isLinear() const {
1195  return expr1.isLinear();
1196  }
1197 
1199  bool hasFastAccess() const {
1200  return expr1.hasFastAccess();
1201  }
1202 
1204  const value_type dx(int i) const {
1205  return expr1.dx(i);
1206  }
1207 
1209  const value_type fastAccessDx(int i) const {
1210  return expr1.fastAccessDx(i);
1211  }
1212 
1214  const value_type* getDx(int j) const {
1215  return expr1.getDx(j);
1216  }
1217 
1218  protected:
1219 
1220  const ExprT1& expr1;
1221  ExprT2 expr2;
1222 
1223  };
1224 
1225  template <typename T1, typename ExprT2>
1226  class Expr< SubtractionOp< ConstExpr<T1>,ExprT2> > {
1227 
1228  public:
1229 
1230  typedef ConstExpr<T1> ExprT1;
1231  typedef typename ExprT1::value_type value_type_1;
1232  typedef typename ExprT2::value_type value_type_2;
1233  typedef typename Sacado::Promote<value_type_1,
1234  value_type_2>::type value_type;
1235  typedef typename ExprT1::scalar_type scalar_type_1;
1236  typedef typename ExprT2::scalar_type scalar_type_2;
1237  typedef typename Sacado::Promote<scalar_type_1,
1238  scalar_type_2>::type scalar_type;
1239 
1240  typedef typename ExprT1::base_expr_type base_expr_type_1;
1241  typedef typename ExprT2::base_expr_type base_expr_type_2;
1242  typedef typename Sacado::Promote<base_expr_type_1,
1243  base_expr_type_2>::type base_expr_type;
1244 
1245  static const int num_args = ExprT2::num_args;
1246 
1247  static const bool is_linear = ExprT2::is_linear;
1248 
1250  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
1251  expr1(expr1_), expr2(expr2_) {}
1252 
1254  int size() const {
1255  return expr2.size();
1256  }
1257 
1258  template <int Arg>
1260  bool isActive() const {
1261  return expr2.template isActive<Arg>();
1262  }
1263 
1265  bool updateValue() const {
1266  return expr2.updateValue();
1267  }
1268 
1270  void cache() const {
1271  expr2.cache();
1272  }
1273 
1275  value_type val() const {
1276  return expr1.val() - expr2.val();
1277  }
1278 
1280  void computePartials(const value_type& bar,
1281  value_type partials[]) const {
1282  expr2.computePartials(-bar, partials);
1283  }
1284 
1286  void getTangents(int i, value_type dots[]) const {
1287  expr2.getTangents(i, dots);
1288  }
1289 
1290  template <int Arg>
1292  value_type getTangent(int i) const {
1293  return expr2.template getTangent<Arg>(i);
1294  }
1295 
1297  bool isLinear() const {
1298  return expr2.isLinear();
1299  }
1300 
1302  bool hasFastAccess() const {
1303  return expr2.hasFastAccess();
1304  }
1305 
1307  const value_type dx(int i) const {
1308  return -expr2.dx(i);
1309  }
1310 
1312  const value_type fastAccessDx(int i) const {
1313  return -expr2.fastAccessDx(i);
1314  }
1315 
1317  const value_type* getDx(int j) const {
1318  return expr2.getDx(j);
1319  }
1320 
1321  protected:
1322 
1323  ExprT1 expr1;
1324  const ExprT2& expr2;
1325 
1326  };
1327 
1328  //
1329  // MultiplicationOp
1330  //
1331 
1332  template <typename ExprT1, typename ExprT2>
1333  class MultiplicationOp {};
1334 
1335  template <typename ExprT1, typename ExprT2>
1336  class Expr< MultiplicationOp<ExprT1,ExprT2> > {
1337 
1338  public:
1339 
1340  typedef typename ExprT1::value_type value_type_1;
1341  typedef typename ExprT2::value_type value_type_2;
1342  typedef typename Sacado::Promote<value_type_1,
1343  value_type_2>::type value_type;
1344  typedef typename ExprT1::scalar_type scalar_type_1;
1345  typedef typename ExprT2::scalar_type scalar_type_2;
1346  typedef typename Sacado::Promote<scalar_type_1,
1347  scalar_type_2>::type scalar_type;
1348 
1349  typedef typename ExprT1::base_expr_type base_expr_type_1;
1350  typedef typename ExprT2::base_expr_type base_expr_type_2;
1351  typedef typename Sacado::Promote<base_expr_type_1,
1352  base_expr_type_2>::type base_expr_type;
1353 
1354  static const int num_args1 = ExprT1::num_args;
1355  static const int num_args2 = ExprT2::num_args;
1356  static const int num_args = num_args1 + num_args2;
1357 
1358  static const bool is_linear = false;
1359 
1361  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
1362  expr1(expr1_), expr2(expr2_) {}
1363 
1365  int size() const {
1366  int sz1 = expr1.size(), sz2 = expr2.size();
1367  return sz1 > sz2 ? sz1 : sz2;
1368  }
1369 
1370  template <int Arg>
1372  bool isActive() const {
1373  if (Arg < num_args1)
1374  return expr1.template isActive<Arg>();
1375  else
1376  return expr2.template isActive<Arg-num_args1>();
1377  }
1378 
1380  bool updateValue() const {
1381  return expr1.updateValue() && expr2.updateValue();
1382  }
1383 
1385  void cache() const {
1386  expr1.cache();
1387  expr2.cache();
1388  v1 = expr1.val();
1389  v2 = expr2.val();
1390  }
1391 
1393  value_type val() const {
1394  return v1*v2;
1395  }
1396 
1398  void computePartials(const value_type& bar,
1399  value_type partials[]) const {
1400  if (num_args1 > 0)
1401  expr1.computePartials(bar*v2, partials);
1402  if (num_args2 > 0)
1403  expr2.computePartials(bar*v1, partials+num_args1);
1404  }
1405 
1407  void getTangents(int i, value_type dots[]) const {
1408  expr1.getTangents(i, dots);
1409  expr2.getTangents(i, dots+num_args1);
1410  }
1411 
1412  template <int Arg>
1414  value_type getTangent(int i) const {
1415  if (Arg < num_args1)
1416  return expr1.template getTangent<Arg>(i);
1417  else
1418  return expr2.template getTangent<Arg-num_args1>(i);
1419  }
1420 
1422  bool isLinear() const {
1423  return false;
1424  }
1425 
1427  bool hasFastAccess() const {
1428  return expr1.hasFastAccess() && expr2.hasFastAccess();
1429  }
1430 
1432  const value_type dx(int i) const {
1433  if (expr1.size() > 0 && expr2.size() > 0)
1434  return v1*expr2.dx(i) + expr1.dx(i)*v2;
1435  else if (expr1.size() > 0)
1436  return expr1.dx(i)*v2;
1437  else
1438  return v1*expr2.dx(i);
1439  }
1440 
1442  const value_type fastAccessDx(int i) const {
1443  return v1*expr2.fastAccessDx(i) + expr1.fastAccessDx(i)*v2;
1444  }
1445 
1447  const value_type* getDx(int j) const {
1448  if (j < num_args1)
1449  return expr1.getDx(j);
1450  else
1451  return expr2.getDx(j-num_args1);
1452  }
1453 
1454  protected:
1455 
1456  const ExprT1& expr1;
1457  const ExprT2& expr2;
1458  mutable value_type_1 v1;
1459  mutable value_type_2 v2;
1460 
1461  };
1462 
1463  template <typename ExprT1, typename T2>
1464  class Expr< MultiplicationOp<ExprT1, ConstExpr<T2> > > {
1465 
1466  public:
1467 
1468  typedef ConstExpr<T2> ExprT2;
1469  typedef typename ExprT1::value_type value_type_1;
1470  typedef typename ExprT2::value_type value_type_2;
1471  typedef typename Sacado::Promote<value_type_1,
1472  value_type_2>::type value_type;
1473  typedef typename ExprT1::scalar_type scalar_type_1;
1474  typedef typename ExprT2::scalar_type scalar_type_2;
1475  typedef typename Sacado::Promote<scalar_type_1,
1476  scalar_type_2>::type scalar_type;
1477 
1478  typedef typename ExprT1::base_expr_type base_expr_type_1;
1479  typedef typename ExprT2::base_expr_type base_expr_type_2;
1480  typedef typename Sacado::Promote<base_expr_type_1,
1481  base_expr_type_2>::type base_expr_type;
1482 
1483  static const int num_args = ExprT1::num_args;
1484 
1485  static const bool is_linear = ExprT1::is_linear;
1486 
1488  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
1489  expr1(expr1_), expr2(expr2_) {}
1490 
1492  int size() const {
1493  return expr1.size();
1494  }
1495 
1496  template <int Arg>
1498  bool isActive() const {
1499  return expr1.template isActive<Arg>();
1500  }
1501 
1503  bool updateValue() const {
1504  return expr1.updateValue();
1505  }
1506 
1508  void cache() const {
1509  expr1.cache();
1510  }
1511 
1513  value_type val() const {
1514  return expr1.val()*expr2.val();
1515  }
1516 
1518  void computePartials(const value_type& bar,
1519  value_type partials[]) const {
1520  expr1.computePartials(bar*expr2.val(), partials);
1521  }
1522 
1524  void getTangents(int i, value_type dots[]) const {
1525  expr1.getTangents(i, dots);
1526  }
1527 
1528  template <int Arg>
1530  value_type getTangent(int i) const {
1531  return expr1.template getTangent<Arg>(i);
1532  }
1533 
1535  bool isLinear() const {
1536  return expr1.isLinear();
1537  }
1538 
1540  bool hasFastAccess() const {
1541  return expr1.hasFastAccess();
1542  }
1543 
1545  const value_type dx(int i) const {
1546  return expr1.dx(i)*expr2.val();
1547  }
1548 
1550  const value_type fastAccessDx(int i) const {
1551  return expr1.fastAccessDx(i)*expr2.val();
1552  }
1553 
1555  const value_type* getDx(int j) const {
1556  return expr1.getDx(j);
1557  }
1558 
1559  protected:
1560 
1561  const ExprT1& expr1;
1562  ExprT2 expr2;
1563 
1564  };
1565 
1566  template <typename T1, typename ExprT2>
1567  class Expr< MultiplicationOp< ConstExpr<T1>,ExprT2> > {
1568 
1569  public:
1570 
1571  typedef ConstExpr<T1> ExprT1;
1572  typedef typename ExprT1::value_type value_type_1;
1573  typedef typename ExprT2::value_type value_type_2;
1574  typedef typename Sacado::Promote<value_type_1,
1575  value_type_2>::type value_type;
1576  typedef typename ExprT1::scalar_type scalar_type_1;
1577  typedef typename ExprT2::scalar_type scalar_type_2;
1578  typedef typename Sacado::Promote<scalar_type_1,
1579  scalar_type_2>::type scalar_type;
1580 
1581  typedef typename ExprT1::base_expr_type base_expr_type_1;
1582  typedef typename ExprT2::base_expr_type base_expr_type_2;
1583  typedef typename Sacado::Promote<base_expr_type_1,
1584  base_expr_type_2>::type base_expr_type;
1585 
1586  static const int num_args = ExprT2::num_args;
1587 
1588  static const bool is_linear = ExprT2::is_linear;
1589 
1591  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
1592  expr1(expr1_), expr2(expr2_) {}
1593 
1595  int size() const {
1596  return expr2.size();
1597  }
1598 
1599  template <int Arg>
1601  bool isActive() const {
1602  return expr2.template isActive<Arg>();
1603  }
1604 
1606  bool updateValue() const {
1607  return expr2.updateValue();
1608  }
1609 
1611  void cache() const {
1612  expr2.cache();
1613  }
1614 
1616  value_type val() const {
1617  return expr1.val()*expr2.val();
1618  }
1619 
1621  void computePartials(const value_type& bar,
1622  value_type partials[]) const {
1623  expr2.computePartials(bar*expr1.val(), partials);
1624  }
1625 
1627  void getTangents(int i, value_type dots[]) const {
1628  expr2.getTangents(i, dots);
1629  }
1630 
1631  template <int Arg>
1633  value_type getTangent(int i) const {
1634  return expr2.template getTangent<Arg>(i);
1635  }
1636 
1638  bool isLinear() const {
1639  return expr2.isLinear();
1640  }
1641 
1643  bool hasFastAccess() const {
1644  return expr2.hasFastAccess();
1645  }
1646 
1648  const value_type dx(int i) const {
1649  return expr1.val()*expr2.dx(i);
1650  }
1651 
1653  const value_type fastAccessDx(int i) const {
1654  return expr1.val()*expr2.fastAccessDx(i);
1655  }
1656 
1658  const value_type* getDx(int j) const {
1659  return expr2.getDx(j);
1660  }
1661 
1662  protected:
1663 
1664  ExprT1 expr1;
1665  const ExprT2& expr2;
1666 
1667  };
1668 
1669  //
1670  // DivisionOp
1671  //
1672 
1673  template <typename ExprT1, typename ExprT2>
1674  class DivisionOp {};
1675 
1676  template <typename ExprT1, typename ExprT2>
1677  class Expr< DivisionOp<ExprT1,ExprT2> > {
1678 
1679  public:
1680 
1681  typedef typename ExprT1::value_type value_type_1;
1682  typedef typename ExprT2::value_type value_type_2;
1683  typedef typename Sacado::Promote<value_type_1,
1684  value_type_2>::type value_type;
1685  typedef typename ExprT1::scalar_type scalar_type_1;
1686  typedef typename ExprT2::scalar_type scalar_type_2;
1687  typedef typename Sacado::Promote<scalar_type_1,
1688  scalar_type_2>::type scalar_type;
1689 
1690  typedef typename ExprT1::base_expr_type base_expr_type_1;
1691  typedef typename ExprT2::base_expr_type base_expr_type_2;
1692  typedef typename Sacado::Promote<base_expr_type_1,
1693  base_expr_type_2>::type base_expr_type;
1694 
1695  static const int num_args1 = ExprT1::num_args;
1696  static const int num_args2 = ExprT2::num_args;
1697  static const int num_args = num_args1 + num_args2;
1698 
1699  static const bool is_linear = false;
1700 
1702  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
1703  expr1(expr1_), expr2(expr2_) {}
1704 
1706  int size() const {
1707  int sz1 = expr1.size(), sz2 = expr2.size();
1708  return sz1 > sz2 ? sz1 : sz2;
1709  }
1710 
1711  template <int Arg>
1713  bool isActive() const {
1714  if (Arg < num_args1)
1715  return expr1.template isActive<Arg>();
1716  else
1717  return expr2.template isActive<Arg-num_args1>();
1718  }
1719 
1721  bool updateValue() const {
1722  return expr1.updateValue() && expr2.updateValue();
1723  }
1724 
1726  void cache() const {
1727  expr1.cache();
1728  expr2.cache();
1729  const value_type_1 v1 = expr1.val();
1730  const value_type_2 v2 = expr2.val();
1731  a = scalar_type(1.0)/v2;
1732  v = v1*a;
1733  b = -v/v2;
1734  }
1735 
1737  value_type val() const {
1738  return v;
1739  }
1740 
1742  void computePartials(const value_type& bar,
1743  value_type partials[]) const {
1744  if (num_args1 > 0)
1745  expr1.computePartials(bar*a, partials);
1746  if (num_args2 > 0)
1747  expr2.computePartials(bar*b, partials+num_args1);
1748  }
1749 
1751  void getTangents(int i, value_type dots[]) const {
1752  expr1.getTangents(i, dots);
1753  expr2.getTangents(i, dots+num_args1);
1754  }
1755 
1756  template <int Arg>
1758  value_type getTangent(int i) const {
1759  if (Arg < num_args1)
1760  return expr1.template getTangent<Arg>(i);
1761  else
1762  return expr2.template getTangent<Arg-num_args1>(i);
1763  }
1764 
1766  bool isLinear() const {
1767  return false;
1768  }
1769 
1771  bool hasFastAccess() const {
1772  return expr1.hasFastAccess() && expr2.hasFastAccess();
1773  }
1774 
1776  const value_type dx(int i) const {
1777  if (expr1.size() > 0 && expr2.size() > 0)
1778  return expr1.dx(i)*a + expr2.dx(i)*b;
1779  else if (expr1.size() > 0)
1780  return expr1.dx(i)*a;
1781  else
1782  return expr1.val()*b;
1783  }
1784 
1786  const value_type fastAccessDx(int i) const {
1787  return expr1.fastAccessDx(i)*a + expr2.fastAccessDx(i)*b;
1788  }
1789 
1791  const value_type* getDx(int j) const {
1792  if (j < num_args1)
1793  return expr1.getDx(j);
1794  else
1795  return expr2.getDx(j-num_args1);
1796  }
1797 
1798  protected:
1799 
1800  const ExprT1& expr1;
1801  const ExprT2& expr2;
1802  mutable value_type v;
1803  mutable value_type a;
1804  mutable value_type b;
1805 
1806  };
1807 
1808  template <typename ExprT1, typename T2>
1809  class Expr< DivisionOp<ExprT1, ConstExpr<T2> > > {
1810 
1811  public:
1812 
1813  typedef ConstExpr<T2> ExprT2;
1814  typedef typename ExprT1::value_type value_type_1;
1815  typedef typename ExprT2::value_type value_type_2;
1816  typedef typename Sacado::Promote<value_type_1,
1817  value_type_2>::type value_type;
1818  typedef typename ExprT1::scalar_type scalar_type_1;
1819  typedef typename ExprT2::scalar_type scalar_type_2;
1820  typedef typename Sacado::Promote<scalar_type_1,
1821  scalar_type_2>::type scalar_type;
1822 
1823  typedef typename ExprT1::base_expr_type base_expr_type_1;
1824  typedef typename ExprT2::base_expr_type base_expr_type_2;
1825  typedef typename Sacado::Promote<base_expr_type_1,
1826  base_expr_type_2>::type base_expr_type;
1827 
1828  static const int num_args = ExprT1::num_args;
1829 
1830  static const bool is_linear = ExprT1::is_linear;
1831 
1833  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
1834  expr1(expr1_), expr2(expr2_) {}
1835 
1837  int size() const {
1838  return expr1.size();
1839  }
1840 
1841  template <int Arg>
1843  bool isActive() const {
1844  return expr1.template isActive<Arg>();
1845  }
1846 
1848  bool updateValue() const {
1849  return expr1.updateValue();
1850  }
1851 
1853  void cache() const {
1854  expr1.cache();
1855  const value_type_1 v1 = expr1.val();
1856  a = scalar_type(1.0)/expr2.val();
1857  v = v1*a;
1858  }
1859 
1861  value_type val() const {
1862  return v;
1863  }
1864 
1866  void computePartials(const value_type& bar,
1867  value_type partials[]) const {
1868  expr1.computePartials(bar*a, partials);
1869  }
1870 
1872  void getTangents(int i, value_type dots[]) const {
1873  expr1.getTangents(i, dots);
1874  }
1875 
1876  template <int Arg>
1878  value_type getTangent(int i) const {
1879  return expr1.template getTangent<Arg>(i);
1880  }
1881 
1883  bool isLinear() const {
1884  return expr1.isLinear();
1885  }
1886 
1888  bool hasFastAccess() const {
1889  return expr1.hasFastAccess();
1890  }
1891 
1893  const value_type dx(int i) const {
1894  return expr1.dx(i)*a;
1895  }
1896 
1898  const value_type fastAccessDx(int i) const {
1899  return expr1.fastAccessDx(i)*a;
1900  }
1901 
1903  const value_type* getDx(int j) const {
1904  return expr1.getDx(j);
1905  }
1906 
1907  protected:
1908 
1909  const ExprT1& expr1;
1910  ExprT2 expr2;
1911  mutable value_type v;
1912  mutable value_type a;
1913 
1914  };
1915 
1916  template <typename T1, typename ExprT2>
1917  class Expr< DivisionOp< ConstExpr<T1>,ExprT2> > {
1918 
1919  public:
1920 
1921  typedef ConstExpr<T1> ExprT1;
1922  typedef typename ExprT1::value_type value_type_1;
1923  typedef typename ExprT2::value_type value_type_2;
1924  typedef typename Sacado::Promote<value_type_1,
1925  value_type_2>::type value_type;
1926  typedef typename ExprT1::scalar_type scalar_type_1;
1927  typedef typename ExprT2::scalar_type scalar_type_2;
1928  typedef typename Sacado::Promote<scalar_type_1,
1929  scalar_type_2>::type scalar_type;
1930 
1931  typedef typename ExprT1::base_expr_type base_expr_type_1;
1932  typedef typename ExprT2::base_expr_type base_expr_type_2;
1933  typedef typename Sacado::Promote<base_expr_type_1,
1934  base_expr_type_2>::type base_expr_type;
1935 
1936  static const int num_args = ExprT2::num_args;
1937 
1938  static const bool is_linear = false;
1939 
1941  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
1942  expr1(expr1_), expr2(expr2_) {}
1943 
1945  int size() const {
1946  return expr2.size();
1947  }
1948 
1949  template <int Arg>
1951  bool isActive() const {
1952  return expr2.template isActive<Arg>();
1953  }
1954 
1956  bool updateValue() const {
1957  return expr2.updateValue();
1958  }
1959 
1961  void cache() const {
1962  expr2.cache();
1963  const value_type_2 v2 = expr2.val();
1964  v = expr1.val()/v2;
1965  b = -v/v2;
1966  }
1967 
1969  value_type val() const {
1970  return v;
1971  }
1972 
1974  void computePartials(const value_type& bar,
1975  value_type partials[]) const {
1976  expr2.computePartials(bar*b, partials);
1977  }
1978 
1980  void getTangents(int i, value_type dots[]) const {
1981  expr2.getTangents(i, dots);
1982  }
1983 
1984  template <int Arg>
1986  value_type getTangent(int i) const {
1987  return expr2.template getTangent<Arg>(i);
1988  }
1989 
1991  bool isLinear() const {
1992  return false;
1993  }
1994 
1996  bool hasFastAccess() const {
1997  return expr2.hasFastAccess();
1998  }
1999 
2001  const value_type dx(int i) const {
2002  return expr2.dx(i)*b;
2003  }
2004 
2006  const value_type fastAccessDx(int i) const {
2007  return expr2.fastAccessDx(i)*b;
2008  }
2009 
2011  const value_type* getDx(int j) const {
2012  return expr2.getDx(j);
2013  }
2014 
2015  protected:
2016 
2017  ExprT1 expr1;
2018  const ExprT2& expr2;
2019  mutable value_type v;
2020  mutable value_type b;
2021 
2022  };
2023 
2024  //
2025  // Atan2Op
2026  //
2027 
2028  template <typename ExprT1, typename ExprT2>
2029  class Atan2Op {};
2030 
2031  template <typename ExprT1, typename ExprT2>
2032  class Expr< Atan2Op<ExprT1,ExprT2> > {
2033 
2034  public:
2035 
2036  typedef typename ExprT1::value_type value_type_1;
2037  typedef typename ExprT2::value_type value_type_2;
2038  typedef typename Sacado::Promote<value_type_1,
2039  value_type_2>::type value_type;
2040  typedef typename ExprT1::scalar_type scalar_type_1;
2041  typedef typename ExprT2::scalar_type scalar_type_2;
2042  typedef typename Sacado::Promote<scalar_type_1,
2043  scalar_type_2>::type scalar_type;
2044 
2045  typedef typename ExprT1::base_expr_type base_expr_type_1;
2046  typedef typename ExprT2::base_expr_type base_expr_type_2;
2047  typedef typename Sacado::Promote<base_expr_type_1,
2048  base_expr_type_2>::type base_expr_type;
2049 
2050  static const int num_args1 = ExprT1::num_args;
2051  static const int num_args2 = ExprT2::num_args;
2052  static const int num_args = num_args1 + num_args2;
2053 
2054  static const bool is_linear = false;
2055 
2057  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
2058  expr1(expr1_), expr2(expr2_) {}
2059 
2061  int size() const {
2062  int sz1 = expr1.size(), sz2 = expr2.size();
2063  return sz1 > sz2 ? sz1 : sz2;
2064  }
2065 
2066  template <int Arg>
2068  bool isActive() const {
2069  if (Arg < num_args1)
2070  return expr1.template isActive<Arg>();
2071  else
2072  return expr2.template isActive<Arg-num_args1>();
2073  }
2074 
2076  bool updateValue() const {
2077  return expr1.updateValue() && expr2.updateValue();
2078  }
2079 
2081  void cache() const {
2082  expr1.cache();
2083  expr2.cache();
2084  const value_type_1 v1 = expr1.val();
2085  const value_type_2 v2 = expr2.val();
2086  a = scalar_type(1.0)/(v1*v1 + v2*v2);
2087  b = -v1*a;
2088  a = v2*a;
2089  v = std::atan2(v1,v2);
2090  }
2091 
2093  value_type val() const {
2094  return v;
2095  }
2096 
2098  void computePartials(const value_type& bar,
2099  value_type partials[]) const {
2100  if (num_args1 > 0)
2101  expr1.computePartials(bar*a, partials);
2102  if (num_args2 > 0)
2103  expr2.computePartials(bar*b, partials+num_args1);
2104  }
2105 
2107  void getTangents(int i, value_type dots[]) const {
2108  expr1.getTangents(i, dots);
2109  expr2.getTangents(i, dots+num_args1);
2110  }
2111 
2112  template <int Arg>
2114  value_type getTangent(int i) const {
2115  if (Arg < num_args1)
2116  return expr1.template getTangent<Arg>(i);
2117  else
2118  return expr2.template getTangent<Arg-num_args1>(i);
2119  }
2120 
2122  bool isLinear() const {
2123  return false;
2124  }
2125 
2127  bool hasFastAccess() const {
2128  return expr1.hasFastAccess() && expr2.hasFastAccess();
2129  }
2130 
2132  const value_type dx(int i) const {
2133  if (expr1.size() > 0 && expr2.size() > 0)
2134  return expr1.dx(i)*a + expr2.dx(i)*b;
2135  else if (expr1.size() > 0)
2136  return expr1.dx(i)*a;
2137  else
2138  return expr1.val()*b;
2139  }
2140 
2142  const value_type fastAccessDx(int i) const {
2143  return expr1.fastAccessDx(i)*a + expr2.fastAccessDx(i)*b;
2144  }
2145 
2147  const value_type* getDx(int j) const {
2148  if (j < num_args1)
2149  return expr1.getDx(j);
2150  else
2151  return expr2.getDx(j-num_args1);
2152  }
2153 
2154  protected:
2155 
2156  const ExprT1& expr1;
2157  const ExprT2& expr2;
2158  mutable value_type v;
2159  mutable value_type a;
2160  mutable value_type b;
2161 
2162  };
2163 
2164  template <typename ExprT1, typename T2>
2165  class Expr< Atan2Op<ExprT1, ConstExpr<T2> > > {
2166 
2167  public:
2168 
2169  typedef ConstExpr<T2> ExprT2;
2170  typedef typename ExprT1::value_type value_type_1;
2171  typedef typename ExprT2::value_type value_type_2;
2172  typedef typename Sacado::Promote<value_type_1,
2173  value_type_2>::type value_type;
2174  typedef typename ExprT1::scalar_type scalar_type_1;
2175  typedef typename ExprT2::scalar_type scalar_type_2;
2176  typedef typename Sacado::Promote<scalar_type_1,
2177  scalar_type_2>::type scalar_type;
2178 
2179  typedef typename ExprT1::base_expr_type base_expr_type_1;
2180  typedef typename ExprT2::base_expr_type base_expr_type_2;
2181  typedef typename Sacado::Promote<base_expr_type_1,
2182  base_expr_type_2>::type base_expr_type;
2183 
2184  static const int num_args = ExprT1::num_args;
2185 
2186  static const bool is_linear = false;
2187 
2189  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
2190  expr1(expr1_), expr2(expr2_) {}
2191 
2193  int size() const {
2194  return expr1.size();
2195  }
2196 
2197  template <int Arg>
2199  bool isActive() const {
2200  return expr1.template isActive<Arg>();
2201  }
2202 
2204  bool updateValue() const {
2205  return expr1.updateValue();
2206  }
2207 
2209  void cache() const {
2210  expr1.cache();
2211  const value_type_1 v1 = expr1.val();
2212  const value_type_2 v2 = expr2.val();
2213  a = v2/(v1*v1 + v2*v2);
2214  v = std::atan2(v1,v2);
2215  }
2216 
2218  value_type val() const {
2219  return v;
2220  }
2221 
2223  void computePartials(const value_type& bar,
2224  value_type partials[]) const {
2225  expr1.computePartials(bar*a, partials);
2226  }
2227 
2229  void getTangents(int i, value_type dots[]) const {
2230  expr1.getTangents(i, dots);
2231  }
2232 
2233  template <int Arg>
2235  value_type getTangent(int i) const {
2236  return expr1.template getTangent<Arg>(i);
2237  }
2238 
2240  bool isLinear() const {
2241  return false;
2242  }
2243 
2245  bool hasFastAccess() const {
2246  return expr1.hasFastAccess();
2247  }
2248 
2250  const value_type dx(int i) const {
2251  return expr1.dx(i)*a;
2252  }
2253 
2255  const value_type fastAccessDx(int i) const {
2256  return expr1.fastAccessDx(i)*a;
2257  }
2258 
2260  const value_type* getDx(int j) const {
2261  return expr1.getDx(j);
2262  }
2263 
2264  protected:
2265 
2266  const ExprT1& expr1;
2267  ExprT2 expr2;
2268  mutable value_type v;
2269  mutable value_type a;
2270 
2271  };
2272 
2273  template <typename T1, typename ExprT2>
2274  class Expr< Atan2Op< ConstExpr<T1>,ExprT2> > {
2275 
2276  public:
2277 
2278  typedef ConstExpr<T1> ExprT1;
2279  typedef typename ExprT1::value_type value_type_1;
2280  typedef typename ExprT2::value_type value_type_2;
2281  typedef typename Sacado::Promote<value_type_1,
2282  value_type_2>::type value_type;
2283  typedef typename ExprT1::scalar_type scalar_type_1;
2284  typedef typename ExprT2::scalar_type scalar_type_2;
2285  typedef typename Sacado::Promote<scalar_type_1,
2286  scalar_type_2>::type scalar_type;
2287 
2288  typedef typename ExprT1::base_expr_type base_expr_type_1;
2289  typedef typename ExprT2::base_expr_type base_expr_type_2;
2290  typedef typename Sacado::Promote<base_expr_type_1,
2291  base_expr_type_2>::type base_expr_type;
2292 
2293  static const int num_args = ExprT2::num_args;
2294 
2295  static const bool is_linear = false;
2296 
2298  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
2299  expr1(expr1_), expr2(expr2_) {}
2300 
2302  int size() const {
2303  return expr2.size();
2304  }
2305 
2306  template <int Arg>
2308  bool isActive() const {
2309  return expr2.template isActive<Arg>();
2310  }
2311 
2313  bool updateValue() const {
2314  return expr2.updateValue();
2315  }
2316 
2318  void cache() const {
2319  expr2.cache();
2320  const value_type_1 v1 = expr1.val();
2321  const value_type_2 v2 = expr2.val();
2322  b = -v1/(v1*v1 + v2*v2);
2323  v = std::atan2(v1,v2);
2324  }
2325 
2327  value_type val() const {
2328  return v;
2329  }
2330 
2332  void computePartials(const value_type& bar,
2333  value_type partials[]) const {
2334  expr2.computePartials(bar*b, partials);
2335  }
2336 
2338  void getTangents(int i, value_type dots[]) const {
2339  expr2.getTangents(i, dots);
2340  }
2341 
2342  template <int Arg>
2344  value_type getTangent(int i) const {
2345  return expr2.template getTangent<Arg>(i);
2346  }
2347 
2349  bool isLinear() const {
2350  return false;
2351  }
2352 
2354  bool hasFastAccess() const {
2355  return expr2.hasFastAccess();
2356  }
2357 
2359  const value_type dx(int i) const {
2360  return expr2.dx(i)*b;
2361  }
2362 
2364  const value_type fastAccessDx(int i) const {
2365  return expr2.fastAccessDx(i)*b;
2366  }
2367 
2369  const value_type* getDx(int j) const {
2370  return expr2.getDx(j);
2371  }
2372 
2373  protected:
2374 
2375  ExprT1 expr1;
2376  const ExprT2& expr2;
2377  mutable value_type v;
2378  mutable value_type b;
2379 
2380  };
2381 
2382  //
2383  // PowerOp
2384  //
2385 
2386  template <typename ExprT1, typename ExprT2>
2387  class PowerOp {};
2388 
2389  template <typename ExprT1, typename ExprT2>
2390  class Expr< PowerOp<ExprT1,ExprT2> > {
2391 
2392  public:
2393 
2394  typedef typename ExprT1::value_type value_type_1;
2395  typedef typename ExprT2::value_type value_type_2;
2396  typedef typename Sacado::Promote<value_type_1,
2397  value_type_2>::type value_type;
2398  typedef typename ExprT1::scalar_type scalar_type_1;
2399  typedef typename ExprT2::scalar_type scalar_type_2;
2400  typedef typename Sacado::Promote<scalar_type_1,
2401  scalar_type_2>::type scalar_type;
2402 
2403  typedef typename ExprT1::base_expr_type base_expr_type_1;
2404  typedef typename ExprT2::base_expr_type base_expr_type_2;
2405  typedef typename Sacado::Promote<base_expr_type_1,
2406  base_expr_type_2>::type base_expr_type;
2407 
2408  static const int num_args1 = ExprT1::num_args;
2409  static const int num_args2 = ExprT2::num_args;
2410  static const int num_args = num_args1 + num_args2;
2411 
2412  static const bool is_linear = false;
2413 
2415  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
2416  expr1(expr1_), expr2(expr2_) {}
2417 
2419  int size() const {
2420  int sz1 = expr1.size(), sz2 = expr2.size();
2421  return sz1 > sz2 ? sz1 : sz2;
2422  }
2423 
2424  template <int Arg>
2426  bool isActive() const {
2427  if (Arg < num_args1)
2428  return expr1.template isActive<Arg>();
2429  else
2430  return expr2.template isActive<Arg-num_args1>();
2431  }
2432 
2434  bool updateValue() const {
2435  return expr1.updateValue() && expr2.updateValue();
2436  }
2437 
2439  void cache() const {
2440  expr1.cache();
2441  expr2.cache();
2442  const value_type_1 v1 = expr1.val();
2443  const value_type_2 v2 = expr2.val();
2444  v = std::pow(v1,v2);
2445  if (expr2.size() == 0 && v2 == scalar_type(1.0)) {
2446  a = scalar_type(1.0);
2447  b = scalar_type(0.0);
2448  }
2449  else if (v1 == scalar_type(0.0)) {
2450  a = scalar_type(0.0);
2451  b = scalar_type(0.0);
2452  }
2453  else {
2454  a = v*v2/v1;
2455  b = v*std::log(v1);
2456  }
2457  }
2458 
2460  value_type val() const {
2461  return v;
2462  }
2463 
2465  void computePartials(const value_type& bar,
2466  value_type partials[]) const {
2467  if (num_args1 > 0)
2468  expr1.computePartials(bar*a, partials);
2469  if (num_args2 > 0)
2470  expr2.computePartials(bar*b, partials+num_args1);
2471  }
2472 
2474  void getTangents(int i, value_type dots[]) const {
2475  expr1.getTangents(i, dots);
2476  expr2.getTangents(i, dots+num_args1);
2477  }
2478 
2479  template <int Arg>
2481  value_type getTangent(int i) const {
2482  if (Arg < num_args1)
2483  return expr1.template getTangent<Arg>(i);
2484  else
2485  return expr2.template getTangent<Arg-num_args1>(i);
2486  }
2487 
2489  bool isLinear() const {
2490  return false;
2491  }
2492 
2494  bool hasFastAccess() const {
2495  return expr1.hasFastAccess() && expr2.hasFastAccess();
2496  }
2497 
2499  const value_type dx(int i) const {
2500  if (expr1.size() > 0 && expr2.size() > 0)
2501  return expr1.dx(i)*a + expr2.dx(i)*b;
2502  else if (expr1.size() > 0)
2503  return expr1.dx(i)*a;
2504  else
2505  return expr1.val()*b;
2506  }
2507 
2509  const value_type fastAccessDx(int i) const {
2510  return expr1.fastAccessDx(i)*a + expr2.fastAccessDx(i)*b;
2511  }
2512 
2514  const value_type* getDx(int j) const {
2515  if (j < num_args1)
2516  return expr1.getDx(j);
2517  else
2518  return expr2.getDx(j-num_args1);
2519  }
2520 
2521  protected:
2522 
2523  const ExprT1& expr1;
2524  const ExprT2& expr2;
2525  mutable value_type v;
2526  mutable value_type a;
2527  mutable value_type b;
2528 
2529  };
2530 
2531  template <typename ExprT1, typename T2>
2532  class Expr< PowerOp<ExprT1, ConstExpr<T2> > > {
2533 
2534  public:
2535 
2536  typedef ConstExpr<T2> ExprT2;
2537  typedef typename ExprT1::value_type value_type_1;
2538  typedef typename ExprT2::value_type value_type_2;
2539  typedef typename Sacado::Promote<value_type_1,
2540  value_type_2>::type value_type;
2541  typedef typename ExprT1::scalar_type scalar_type_1;
2542  typedef typename ExprT2::scalar_type scalar_type_2;
2543  typedef typename Sacado::Promote<scalar_type_1,
2544  scalar_type_2>::type scalar_type;
2545 
2546  typedef typename ExprT1::base_expr_type base_expr_type_1;
2547  typedef typename ExprT2::base_expr_type base_expr_type_2;
2548  typedef typename Sacado::Promote<base_expr_type_1,
2549  base_expr_type_2>::type base_expr_type;
2550 
2551  static const int num_args = ExprT1::num_args;
2552 
2553  static const bool is_linear = false;
2554 
2556  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
2557  expr1(expr1_), expr2(expr2_) {}
2558 
2560  int size() const {
2561  return expr1.size();
2562  }
2563 
2564  template <int Arg>
2566  bool isActive() const {
2567  return expr1.template isActive<Arg>();
2568  }
2569 
2571  bool updateValue() const {
2572  return expr1.updateValue();
2573  }
2574 
2576  void cache() const {
2577  expr1.cache();
2578  const value_type_1 v1 = expr1.val();
2579  const value_type_2 v2 = expr2.val();
2580  v = std::pow(v1,v2);
2581  if (v2 == scalar_type(1.0)) {
2582  a = scalar_type(1.0);
2583  }
2584  else if (v1 == scalar_type(0.0)) {
2585  a = scalar_type(0.0);
2586  }
2587  else {
2588  a = v*v2/v1;
2589  }
2590  }
2591 
2593  value_type val() const {
2594  return v;
2595  }
2596 
2598  void computePartials(const value_type& bar,
2599  value_type partials[]) const {
2600  expr1.computePartials(bar*a, partials);
2601  }
2602 
2604  void getTangents(int i, value_type dots[]) const {
2605  expr1.getTangents(i, dots);
2606  }
2607 
2608  template <int Arg>
2610  value_type getTangent(int i) const {
2611  return expr1.template getTangent<Arg>(i);
2612  }
2613 
2615  bool isLinear() const {
2616  return false;
2617  }
2618 
2620  bool hasFastAccess() const {
2621  return expr1.hasFastAccess();
2622  }
2623 
2625  const value_type dx(int i) const {
2626  return expr1.dx(i)*a;
2627  }
2628 
2630  const value_type fastAccessDx(int i) const {
2631  return expr1.fastAccessDx(i)*a;
2632  }
2633 
2635  const value_type* getDx(int j) const {
2636  return expr1.getDx(j);
2637  }
2638 
2639  protected:
2640 
2641  const ExprT1& expr1;
2642  ExprT2 expr2;
2643  mutable value_type v;
2644  mutable value_type a;
2645 
2646  };
2647 
2648  template <typename T1, typename ExprT2>
2649  class Expr< PowerOp< ConstExpr<T1>,ExprT2> > {
2650 
2651  public:
2652 
2653  typedef ConstExpr<T1> ExprT1;
2654  typedef typename ExprT1::value_type value_type_1;
2655  typedef typename ExprT2::value_type value_type_2;
2656  typedef typename Sacado::Promote<value_type_1,
2657  value_type_2>::type value_type;
2658  typedef typename ExprT1::scalar_type scalar_type_1;
2659  typedef typename ExprT2::scalar_type scalar_type_2;
2660  typedef typename Sacado::Promote<scalar_type_1,
2661  scalar_type_2>::type scalar_type;
2662 
2663  typedef typename ExprT1::base_expr_type base_expr_type_1;
2664  typedef typename ExprT2::base_expr_type base_expr_type_2;
2665  typedef typename Sacado::Promote<base_expr_type_1,
2666  base_expr_type_2>::type base_expr_type;
2667 
2668  static const int num_args = ExprT2::num_args;
2669 
2670  static const bool is_linear = false;
2671 
2673  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
2674  expr1(expr1_), expr2(expr2_) {}
2675 
2677  int size() const {
2678  return expr2.size();
2679  }
2680 
2681  template <int Arg>
2683  bool isActive() const {
2684  return expr2.template isActive<Arg>();
2685  }
2686 
2688  bool updateValue() const {
2689  return expr2.updateValue();
2690  }
2691 
2693  void cache() const {
2694  expr2.cache();
2695  const value_type_1 v1 = expr1.val();
2696  const value_type_2 v2 = expr2.val();
2697  v = std::pow(v1,v2);
2698  if (v1 == scalar_type(0.0)) {
2699  b = scalar_type(0.0);
2700  }
2701  else {
2702  b = v*std::log(v1);
2703  }
2704  }
2705 
2707  value_type val() const {
2708  return v;
2709  }
2710 
2712  void computePartials(const value_type& bar,
2713  value_type partials[]) const {
2714  expr2.computePartials(bar*b, partials);
2715  }
2716 
2718  void getTangents(int i, value_type dots[]) const {
2719  expr2.getTangents(i, dots);
2720  }
2721 
2722  template <int Arg>
2724  value_type getTangent(int i) const {
2725  return expr2.template getTangent<Arg>(i);
2726  }
2727 
2729  bool isLinear() const {
2730  return false;
2731  }
2732 
2734  bool hasFastAccess() const {
2735  return expr2.hasFastAccess();
2736  }
2737 
2739  const value_type dx(int i) const {
2740  return expr2.dx(i)*b;
2741  }
2742 
2744  const value_type fastAccessDx(int i) const {
2745  return expr2.fastAccessDx(i)*b;
2746  }
2747 
2749  const value_type* getDx(int j) const {
2750  return expr2.getDx(j);
2751  }
2752 
2753  protected:
2754 
2755  ExprT1 expr1;
2756  const ExprT2& expr2;
2757  mutable value_type v;
2758  mutable value_type b;
2759 
2760  };
2761 
2762  //
2763  // MaxOp
2764  //
2765 
2766  template <typename ExprT1, typename ExprT2>
2767  class MaxOp {};
2768 
2769  template <typename ExprT1, typename ExprT2>
2770  class Expr< MaxOp<ExprT1,ExprT2> > {
2771 
2772  public:
2773 
2774  typedef typename ExprT1::value_type value_type_1;
2775  typedef typename ExprT2::value_type value_type_2;
2776  typedef typename Sacado::Promote<value_type_1,
2777  value_type_2>::type value_type;
2778  typedef typename ExprT1::scalar_type scalar_type_1;
2779  typedef typename ExprT2::scalar_type scalar_type_2;
2780  typedef typename Sacado::Promote<scalar_type_1,
2781  scalar_type_2>::type scalar_type;
2782 
2783  typedef typename ExprT1::base_expr_type base_expr_type_1;
2784  typedef typename ExprT2::base_expr_type base_expr_type_2;
2785  typedef typename Sacado::Promote<base_expr_type_1,
2786  base_expr_type_2>::type base_expr_type;
2787 
2788  static const int num_args1 = ExprT1::num_args;
2789  static const int num_args2 = ExprT2::num_args;
2790  static const int num_args = num_args1 + num_args2;
2791 
2792  static const bool is_linear = false;
2793 
2795  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
2796  expr1(expr1_), expr2(expr2_) {}
2797 
2799  int size() const {
2800  int sz1 = expr1.size(), sz2 = expr2.size();
2801  return sz1 > sz2 ? sz1 : sz2;
2802  }
2803 
2804  template <int Arg>
2806  bool isActive() const {
2807  if (Arg < num_args1)
2808  return expr1.template isActive<Arg>();
2809  else
2810  return expr2.template isActive<Arg-num_args1>();
2811  }
2812 
2814  bool updateValue() const {
2815  return expr1.updateValue() && expr2.updateValue();
2816  }
2817 
2819  void cache() const {
2820  expr1.cache();
2821  expr2.cache();
2822  const value_type_1 v1 = expr1.val();
2823  const value_type_2 v2 = expr2.val();
2824  max_v1 = (v1 >= v2);
2825  v = max_v1 ? v1 : v2;
2826  }
2827 
2829  value_type val() const {
2830  return v;
2831  }
2832 
2834  void computePartials(const value_type& bar,
2835  value_type partials[]) const {
2836  if (num_args1 > 0) {
2837  if (max_v1)
2838  expr1.computePartials(bar, partials);
2839  else
2840  expr1.computePartials(value_type(0.0), partials);
2841  }
2842  if (num_args2 > 0) {
2843  if (max_v1)
2844  expr2.computePartials(value_type(0.0), partials+num_args1);
2845  else
2846  expr2.computePartials(bar, partials+num_args1);
2847  }
2848  }
2849 
2851  void getTangents(int i, value_type dots[]) const {
2852  expr1.getTangents(i, dots);
2853  expr2.getTangents(i, dots+num_args1);
2854  }
2855 
2856  template <int Arg>
2858  value_type getTangent(int i) const {
2859  if (Arg < num_args1)
2860  return expr1.template getTangent<Arg>(i);
2861  else
2862  return expr2.template getTangent<Arg-num_args1>(i);
2863  }
2864 
2866  bool isLinear() const {
2867  return false;
2868  }
2869 
2871  bool hasFastAccess() const {
2872  return expr1.hasFastAccess() && expr2.hasFastAccess();
2873  }
2874 
2876  const value_type dx(int i) const {
2877  return max_v1 ? expr1.dx(i) : expr2.dx(i);
2878  }
2879 
2881  const value_type fastAccessDx(int i) const {
2882  return max_v1 ? expr1.fastAccessDx(i) : expr2.fastAccessDx(i);
2883  }
2884 
2886  const value_type* getDx(int j) const {
2887  if (j < num_args1)
2888  return expr1.getDx(j);
2889  else
2890  return expr2.getDx(j-num_args1);
2891  }
2892 
2893  protected:
2894 
2895  const ExprT1& expr1;
2896  const ExprT2& expr2;
2897  mutable value_type v;
2898  mutable bool max_v1;
2899 
2900  };
2901 
2902  template <typename ExprT1, typename T2>
2903  class Expr< MaxOp<ExprT1, ConstExpr<T2> > > {
2904 
2905  public:
2906 
2907  typedef ConstExpr<T2> ExprT2;
2908  typedef typename ExprT1::value_type value_type_1;
2909  typedef typename ExprT2::value_type value_type_2;
2910  typedef typename Sacado::Promote<value_type_1,
2911  value_type_2>::type value_type;
2912  typedef typename ExprT1::scalar_type scalar_type_1;
2913  typedef typename ExprT2::scalar_type scalar_type_2;
2914  typedef typename Sacado::Promote<scalar_type_1,
2915  scalar_type_2>::type scalar_type;
2916 
2917  typedef typename ExprT1::base_expr_type base_expr_type_1;
2918  typedef typename ExprT2::base_expr_type base_expr_type_2;
2919  typedef typename Sacado::Promote<base_expr_type_1,
2920  base_expr_type_2>::type base_expr_type;
2921 
2922  static const int num_args = ExprT1::num_args;
2923 
2924  static const bool is_linear = false;
2925 
2927  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
2928  expr1(expr1_), expr2(expr2_) {}
2929 
2931  int size() const {
2932  return expr1.size();
2933  }
2934 
2935  template <int Arg>
2937  bool isActive() const {
2938  return expr1.template isActive<Arg>();
2939  }
2940 
2942  bool updateValue() const {
2943  return expr1.updateValue();
2944  }
2945 
2947  void cache() const {
2948  expr1.cache();
2949  const value_type_1 v1 = expr1.val();
2950  const value_type_2 v2 = expr2.val();
2951  max_v1 = (v1 >= v2);
2952  v = max_v1 ? v1 : v2;
2953  }
2954 
2956  value_type val() const {
2957  return v;
2958  }
2959 
2961  void computePartials(const value_type& bar,
2962  value_type partials[]) const {
2963  if (max_v1)
2964  expr1.computePartials(bar, partials);
2965  else
2966  expr1.computePartials(value_type(0.0), partials);
2967  }
2968 
2970  void getTangents(int i, value_type dots[]) const {
2971  expr1.getTangents(i, dots);
2972  }
2973 
2974  template <int Arg>
2976  value_type getTangent(int i) const {
2977  return expr1.template getTangent<Arg>(i);
2978  }
2979 
2981  bool isLinear() const {
2982  return false;
2983  }
2984 
2986  bool hasFastAccess() const {
2987  return expr1.hasFastAccess();
2988  }
2989 
2991  const value_type dx(int i) const {
2992  return max_v1 ? expr1.dx(i) : value_type(0.0);
2993  }
2994 
2996  const value_type fastAccessDx(int i) const {
2997  return max_v1 ? expr1.fastAccessDx(i) : value_type(0.0);
2998  }
2999 
3001  const value_type* getDx(int j) const {
3002  return expr1.getDx(j);
3003  }
3004 
3005  protected:
3006 
3007  const ExprT1& expr1;
3008  ExprT2 expr2;
3009  mutable value_type v;
3010  mutable bool max_v1;
3011 
3012  };
3013 
3014  template <typename T1, typename ExprT2>
3015  class Expr< MaxOp< ConstExpr<T1>,ExprT2> > {
3016 
3017  public:
3018 
3019  typedef ConstExpr<T1> ExprT1;
3020  typedef typename ExprT1::value_type value_type_1;
3021  typedef typename ExprT2::value_type value_type_2;
3022  typedef typename Sacado::Promote<value_type_1,
3023  value_type_2>::type value_type;
3024  typedef typename ExprT1::scalar_type scalar_type_1;
3025  typedef typename ExprT2::scalar_type scalar_type_2;
3026  typedef typename Sacado::Promote<scalar_type_1,
3027  scalar_type_2>::type scalar_type;
3028 
3029  typedef typename ExprT1::base_expr_type base_expr_type_1;
3030  typedef typename ExprT2::base_expr_type base_expr_type_2;
3031  typedef typename Sacado::Promote<base_expr_type_1,
3032  base_expr_type_2>::type base_expr_type;
3033 
3034  static const int num_args = ExprT2::num_args;
3035 
3036  static const bool is_linear = false;
3037 
3039  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
3040  expr1(expr1_), expr2(expr2_) {}
3041 
3043  int size() const {
3044  return expr2.size();
3045  }
3046 
3047  template <int Arg>
3049  bool isActive() const {
3050  return expr2.template isActive<Arg>();
3051  }
3052 
3054  bool updateValue() const {
3055  return expr2.updateValue();
3056  }
3057 
3059  void cache() const {
3060  expr2.cache();
3061  const value_type_1 v1 = expr1.val();
3062  const value_type_2 v2 = expr2.val();
3063  max_v1 = (v1 >= v2);
3064  v = max_v1 ? v1 : v2;
3065  }
3066 
3068  value_type val() const {
3069  return v;
3070  }
3071 
3073  void computePartials(const value_type& bar,
3074  value_type partials[]) const {
3075  if (max_v1)
3076  expr2.computePartials(value_type(0.0), partials);
3077  else
3078  expr2.computePartials(bar, partials);
3079  }
3080 
3082  void getTangents(int i, value_type dots[]) const {
3083  expr2.getTangents(i, dots);
3084  }
3085 
3086  template <int Arg>
3088  value_type getTangent(int i) const {
3089  return expr2.template getTangent<Arg>(i);
3090  }
3091 
3093  bool isLinear() const {
3094  return false;
3095  }
3096 
3098  bool hasFastAccess() const {
3099  return expr2.hasFastAccess();
3100  }
3101 
3103  const value_type dx(int i) const {
3104  return max_v1 ? value_type(0.0) : expr2.dx(i);
3105  }
3106 
3108  const value_type fastAccessDx(int i) const {
3109  return max_v1 ? value_type(0.0) : expr2.fastAccessDx(i);
3110  }
3111 
3113  const value_type* getDx(int j) const {
3114  return expr2.getDx(j);
3115  }
3116 
3117  protected:
3118 
3119  ExprT1 expr1;
3120  const ExprT2& expr2;
3121  mutable value_type v;
3122  mutable bool max_v1;
3123 
3124  };
3125 
3126  //
3127  // MinOp
3128  //
3129 
3130  template <typename ExprT1, typename ExprT2>
3131  class MinOp {};
3132 
3133  template <typename ExprT1, typename ExprT2>
3134  class Expr< MinOp<ExprT1,ExprT2> > {
3135 
3136  public:
3137 
3138  typedef typename ExprT1::value_type value_type_1;
3139  typedef typename ExprT2::value_type value_type_2;
3140  typedef typename Sacado::Promote<value_type_1,
3141  value_type_2>::type value_type;
3142  typedef typename ExprT1::scalar_type scalar_type_1;
3143  typedef typename ExprT2::scalar_type scalar_type_2;
3144  typedef typename Sacado::Promote<scalar_type_1,
3145  scalar_type_2>::type scalar_type;
3146 
3147  typedef typename ExprT1::base_expr_type base_expr_type_1;
3148  typedef typename ExprT2::base_expr_type base_expr_type_2;
3149  typedef typename Sacado::Promote<base_expr_type_1,
3150  base_expr_type_2>::type base_expr_type;
3151 
3152  static const int num_args1 = ExprT1::num_args;
3153  static const int num_args2 = ExprT2::num_args;
3154  static const int num_args = num_args1 + num_args2;
3155 
3156  static const bool is_linear = false;
3157 
3159  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
3160  expr1(expr1_), expr2(expr2_) {}
3161 
3163  int size() const {
3164  int sz1 = expr1.size(), sz2 = expr2.size();
3165  return sz1 > sz2 ? sz1 : sz2;
3166  }
3167 
3168  template <int Arg>
3170  bool isActive() const {
3171  if (Arg < num_args1)
3172  return expr1.template isActive<Arg>();
3173  else
3174  return expr2.template isActive<Arg-num_args1>();
3175  }
3176 
3178  bool updateValue() const {
3179  return expr1.updateValue() && expr2.updateValue();
3180  }
3181 
3183  void cache() const {
3184  expr1.cache();
3185  expr2.cache();
3186  const value_type_1 v1 = expr1.val();
3187  const value_type_2 v2 = expr2.val();
3188  min_v1 = (v1 <= v2);
3189  v = min_v1 ? v1 : v2;
3190  }
3191 
3193  value_type val() const {
3194  return v;
3195  }
3196 
3198  void computePartials(const value_type& bar,
3199  value_type partials[]) const {
3200  if (num_args1 > 0) {
3201  if (min_v1)
3202  expr1.computePartials(bar, partials);
3203  else
3204  expr1.computePartials(value_type(0.0), partials);
3205  }
3206  if (num_args2 > 0) {
3207  if (min_v1)
3208  expr2.computePartials(value_type(0.0), partials+num_args1);
3209  else
3210  expr2.computePartials(bar, partials+num_args1);
3211  }
3212  }
3213 
3215  void getTangents(int i, value_type dots[]) const {
3216  expr1.getTangents(i, dots);
3217  expr2.getTangents(i, dots+num_args1);
3218  }
3219 
3220  template <int Arg>
3222  value_type getTangent(int i) const {
3223  if (Arg < num_args1)
3224  return expr1.template getTangent<Arg>(i);
3225  else
3226  return expr2.template getTangent<Arg-num_args1>(i);
3227  }
3228 
3230  bool isLinear() const {
3231  return false;
3232  }
3233 
3235  bool hasFastAccess() const {
3236  return expr1.hasFastAccess() && expr2.hasFastAccess();
3237  }
3238 
3240  const value_type dx(int i) const {
3241  return min_v1 ? expr1.dx(i) : expr2.dx(i);
3242  }
3243 
3245  const value_type fastAccessDx(int i) const {
3246  return min_v1 ? expr1.fastAccessDx(i) : expr2.fastAccessDx(i);
3247  }
3248 
3250  const value_type* getDx(int j) const {
3251  if (j < num_args1)
3252  return expr1.getDx(j);
3253  else
3254  return expr2.getDx(j-num_args1);
3255  }
3256 
3257  protected:
3258 
3259  const ExprT1& expr1;
3260  const ExprT2& expr2;
3261  mutable value_type v;
3262  mutable bool min_v1;
3263 
3264  };
3265 
3266  template <typename ExprT1, typename T2>
3267  class Expr< MinOp<ExprT1, ConstExpr<T2> > > {
3268 
3269  public:
3270 
3271  typedef ConstExpr<T2> ExprT2;
3272  typedef typename ExprT1::value_type value_type_1;
3273  typedef typename ExprT2::value_type value_type_2;
3274  typedef typename Sacado::Promote<value_type_1,
3275  value_type_2>::type value_type;
3276  typedef typename ExprT1::scalar_type scalar_type_1;
3277  typedef typename ExprT2::scalar_type scalar_type_2;
3278  typedef typename Sacado::Promote<scalar_type_1,
3279  scalar_type_2>::type scalar_type;
3280 
3281  typedef typename ExprT1::base_expr_type base_expr_type_1;
3282  typedef typename ExprT2::base_expr_type base_expr_type_2;
3283  typedef typename Sacado::Promote<base_expr_type_1,
3284  base_expr_type_2>::type base_expr_type;
3285 
3286  static const int num_args = ExprT1::num_args;
3287 
3288  static const bool is_linear = false;
3289 
3291  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
3292  expr1(expr1_), expr2(expr2_) {}
3293 
3295  int size() const {
3296  return expr1.size();
3297  }
3298 
3299  template <int Arg>
3301  bool isActive() const {
3302  return expr1.template isActive<Arg>();
3303  }
3304 
3306  bool updateValue() const {
3307  return expr1.updateValue();
3308  }
3309 
3311  void cache() const {
3312  expr1.cache();
3313  const value_type_1 v1 = expr1.val();
3314  const value_type_2 v2 = expr2.val();
3315  min_v1 = (v1 <= v2);
3316  v = min_v1 ? v1 : v2;
3317  }
3318 
3320  value_type val() const {
3321  return v;
3322  }
3323 
3325  void computePartials(const value_type& bar,
3326  value_type partials[]) const {
3327  if (min_v1)
3328  expr1.computePartials(bar, partials);
3329  else
3330  expr1.computePartials(value_type(0.0), partials);
3331  }
3332 
3334  void getTangents(int i, value_type dots[]) const {
3335  expr1.getTangents(i, dots);
3336  }
3337 
3338  template <int Arg>
3340  value_type getTangent(int i) const {
3341  return expr1.template getTangent<Arg>(i);
3342  }
3343 
3345  bool isLinear() const {
3346  return false;
3347  }
3348 
3350  bool hasFastAccess() const {
3351  return expr1.hasFastAccess();
3352  }
3353 
3355  const value_type dx(int i) const {
3356  return min_v1 ? expr1.dx(i) : value_type(0.0);
3357  }
3358 
3360  const value_type fastAccessDx(int i) const {
3361  return min_v1 ? expr1.fastAccessDx(i) : value_type(0.0);
3362  }
3363 
3365  const value_type* getDx(int j) const {
3366  return expr1.getDx(j);
3367  }
3368 
3369  protected:
3370 
3371  const ExprT1& expr1;
3372  ExprT2 expr2;
3373  mutable value_type v;
3374  mutable bool min_v1;
3375 
3376  };
3377 
3378  template <typename T1, typename ExprT2>
3379  class Expr< MinOp< ConstExpr<T1>,ExprT2> > {
3380 
3381  public:
3382 
3383  typedef ConstExpr<T1> ExprT1;
3384  typedef typename ExprT1::value_type value_type_1;
3385  typedef typename ExprT2::value_type value_type_2;
3386  typedef typename Sacado::Promote<value_type_1,
3387  value_type_2>::type value_type;
3388  typedef typename ExprT1::scalar_type scalar_type_1;
3389  typedef typename ExprT2::scalar_type scalar_type_2;
3390  typedef typename Sacado::Promote<scalar_type_1,
3391  scalar_type_2>::type scalar_type;
3392 
3393  typedef typename ExprT1::base_expr_type base_expr_type_1;
3394  typedef typename ExprT2::base_expr_type base_expr_type_2;
3395  typedef typename Sacado::Promote<base_expr_type_1,
3396  base_expr_type_2>::type base_expr_type;
3397 
3398  static const int num_args = ExprT2::num_args;
3399 
3400  static const bool is_linear = false;
3401 
3403  Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
3404  expr1(expr1_), expr2(expr2_) {}
3405 
3407  int size() const {
3408  return expr2.size();
3409  }
3410 
3411  template <int Arg>
3413  bool isActive() const {
3414  return expr2.template isActive<Arg>();
3415  }
3416 
3418  bool updateValue() const {
3419  return expr2.updateValue();
3420  }
3421 
3423  void cache() const {
3424  expr2.cache();
3425  const value_type_1 v1 = expr1.val();
3426  const value_type_2 v2 = expr2.val();
3427  min_v1 = (v1 <= v2);
3428  v = min_v1 ? v1 : v2;
3429  }
3430 
3432  value_type val() const {
3433  return v;
3434  }
3435 
3437  void computePartials(const value_type& bar,
3438  value_type partials[]) const {
3439  if (min_v1)
3440  expr2.computePartials(value_type(0.0), partials);
3441  else
3442  expr2.computePartials(bar, partials);
3443  }
3444 
3446  void getTangents(int i, value_type dots[]) const {
3447  expr2.getTangents(i, dots);
3448  }
3449 
3450  template <int Arg>
3452  value_type getTangent(int i) const {
3453  return expr2.template getTangent<Arg>(i);
3454  }
3455 
3457  bool isLinear() const {
3458  return false;
3459  }
3460 
3462  bool hasFastAccess() const {
3463  return expr2.hasFastAccess();
3464  }
3465 
3467  const value_type dx(int i) const {
3468  return min_v1 ? value_type(0.0) : expr2.dx(i);
3469  }
3470 
3472  const value_type fastAccessDx(int i) const {
3473  return min_v1 ? value_type(0.0) : expr2.fastAccessDx(i);
3474  }
3475 
3477  const value_type* getDx(int j) const {
3478  return expr2.getDx(j);
3479  }
3480 
3481  protected:
3482 
3483  ExprT1 expr1;
3484  const ExprT2& expr2;
3485  mutable value_type v;
3486  mutable bool min_v1;
3487 
3488  };
3489 
3490  }
3491 
3492 }
3493 
3494 #define FAD_BINARYOP_MACRO(OPNAME,OP) \
3495 namespace Sacado { \
3496  namespace ELRCacheFad { \
3497  \
3498  template <typename T1, typename T2> \
3499  SACADO_INLINE_FUNCTION \
3500  SACADO_FAD_OP_ENABLE_EXPR_EXPR(OP) \
3501  OPNAME (const T1& expr1, const T2& expr2) \
3502  { \
3503  typedef OP< T1, T2 > expr_t; \
3504  \
3505  return Expr<expr_t>(expr1, expr2); \
3506  } \
3507  \
3508  template <typename T> \
3509  SACADO_INLINE_FUNCTION \
3510  Expr< OP< Expr<T>, Expr<T> > > \
3511  OPNAME (const Expr<T>& expr1, const Expr<T>& expr2) \
3512  { \
3513  typedef OP< Expr<T>, Expr<T> > expr_t; \
3514  \
3515  return Expr<expr_t>(expr1, expr2); \
3516  } \
3517  \
3518  template <typename T> \
3519  SACADO_INLINE_FUNCTION \
3520  Expr< OP< ConstExpr<typename Expr<T>::value_type>, \
3521  Expr<T> > > \
3522  OPNAME (const typename Expr<T>::value_type& c, \
3523  const Expr<T>& expr) \
3524  { \
3525  typedef ConstExpr<typename Expr<T>::value_type> ConstT; \
3526  typedef OP< ConstT, Expr<T> > expr_t; \
3527  \
3528  return Expr<expr_t>(ConstT(c), expr); \
3529  } \
3530  \
3531  template <typename T> \
3532  SACADO_INLINE_FUNCTION \
3533  Expr< OP< Expr<T>, \
3534  ConstExpr<typename Expr<T>::value_type> > > \
3535  OPNAME (const Expr<T>& expr, \
3536  const typename Expr<T>::value_type& c) \
3537  { \
3538  typedef ConstExpr<typename Expr<T>::value_type> ConstT; \
3539  typedef OP< Expr<T>, ConstT > expr_t; \
3540  \
3541  return Expr<expr_t>(expr, ConstT(c)); \
3542  } \
3543  \
3544  template <typename T> \
3545  SACADO_INLINE_FUNCTION \
3546  SACADO_FAD_OP_ENABLE_SCALAR_EXPR(OP) \
3547  OPNAME (const typename Expr<T>::scalar_type& c, \
3548  const Expr<T>& expr) \
3549  { \
3550  typedef ConstExpr<typename Expr<T>::scalar_type> ConstT; \
3551  typedef OP< ConstT, Expr<T> > expr_t; \
3552  \
3553  return Expr<expr_t>(ConstT(c), expr); \
3554  } \
3555  \
3556  template <typename T> \
3557  SACADO_INLINE_FUNCTION \
3558  SACADO_FAD_OP_ENABLE_EXPR_SCALAR(OP) \
3559  OPNAME (const Expr<T>& expr, \
3560  const typename Expr<T>::scalar_type& c) \
3561  { \
3562  typedef ConstExpr<typename Expr<T>::scalar_type> ConstT; \
3563  typedef OP< Expr<T>, ConstT > expr_t; \
3564  \
3565  return Expr<expr_t>(expr, ConstT(c)); \
3566  } \
3567  } \
3568 }
3569 
3570 
3571 FAD_BINARYOP_MACRO(operator+, AdditionOp)
3574 FAD_BINARYOP_MACRO(operator/, DivisionOp)
3579 
3580 #undef FAD_BINARYOP_MACRO
3581 
3582 //-------------------------- Relational Operators -----------------------
3583 
3584 #define FAD_RELOP_MACRO(OP) \
3585 namespace Sacado { \
3586  namespace ELRCacheFad { \
3587  template <typename ExprT1, typename ExprT2> \
3588  SACADO_INLINE_FUNCTION \
3589  bool \
3590  operator OP (const Expr<ExprT1>& expr1, \
3591  const Expr<ExprT2>& expr2) \
3592  { \
3593  expr1.cache(); \
3594  expr2.cache(); \
3595  return expr1.val() OP expr2.val(); \
3596  } \
3597  \
3598  template <typename ExprT2> \
3599  SACADO_INLINE_FUNCTION \
3600  bool \
3601  operator OP (const typename Expr<ExprT2>::value_type& a, \
3602  const Expr<ExprT2>& expr2) \
3603  { \
3604  expr2.cache(); \
3605  return a OP expr2.val(); \
3606  } \
3607  \
3608  template <typename ExprT1> \
3609  SACADO_INLINE_FUNCTION \
3610  bool \
3611  operator OP (const Expr<ExprT1>& expr1, \
3612  const typename Expr<ExprT1>::value_type& b) \
3613  { \
3614  expr1.cache(); \
3615  return expr1.val() OP b; \
3616  } \
3617  } \
3618 }
3619 
3620 FAD_RELOP_MACRO(==)
3621 FAD_RELOP_MACRO(!=)
3622 FAD_RELOP_MACRO(<)
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 
3631 #undef FAD_RELOP_MACRO
3632 
3633 namespace Sacado {
3634 
3635  namespace ELRCacheFad {
3636 
3637  template <typename ExprT>
3639  bool operator ! (const Expr<ExprT>& expr)
3640  {
3641  expr.cache();
3642  return ! expr.val();
3643  }
3644 
3645  } // namespace ELRCacheFad
3646 
3647 } // namespace Sacado
3648 
3649 //-------------------------- Boolean Operators -----------------------
3650 namespace Sacado {
3651 
3652  namespace ELRCacheFad {
3653 
3654  template <typename ExprT>
3656  bool toBool(const Expr<ExprT>& x) {
3657  x.cache();
3658  bool is_zero = (x.val() == 0.0);
3659  for (int i=0; i<x.size(); i++)
3660  is_zero = is_zero && (x.dx(i) == 0.0);
3661  return !is_zero;
3662  }
3663 
3664  } // namespace Fad
3665 
3666 } // namespace Sacado
3667 
3668 #define FAD_BOOL_MACRO(OP) \
3669 namespace Sacado { \
3670  namespace ELRCacheFad { \
3671  template <typename ExprT1, typename ExprT2> \
3672  SACADO_INLINE_FUNCTION \
3673  bool \
3674  operator OP (const Expr<ExprT1>& expr1, \
3675  const Expr<ExprT2>& expr2) \
3676  { \
3677  return toBool(expr1) OP toBool(expr2); \
3678  } \
3679  \
3680  template <typename ExprT2> \
3681  SACADO_INLINE_FUNCTION \
3682  bool \
3683  operator OP (const typename Expr<ExprT2>::value_type& a, \
3684  const Expr<ExprT2>& expr2) \
3685  { \
3686  return a OP toBool(expr2); \
3687  } \
3688  \
3689  template <typename ExprT1> \
3690  SACADO_INLINE_FUNCTION \
3691  bool \
3692  operator OP (const Expr<ExprT1>& expr1, \
3693  const typename Expr<ExprT1>::value_type& b) \
3694  { \
3695  return toBool(expr1) OP b; \
3696  } \
3697  } \
3698 }
3699 
3700 FAD_BOOL_MACRO(&&)
3701 FAD_BOOL_MACRO(||)
3702 
3703 #undef FAD_BOOL_MACRO
3704 
3705 //-------------------------- I/O Operators -----------------------
3706 
3707 namespace Sacado {
3708 
3709  namespace ELRCacheFad {
3710 
3711  template <typename ExprT>
3712  std::ostream& operator << (std::ostream& os, const Expr<ExprT>& x) {
3713  os << x.val() << " [";
3714 
3715  for (int i=0; i< x.size(); i++) {
3716  os << " " << x.dx(i);
3717  }
3718 
3719  os << " ]";
3720  return os;
3721  }
3722 
3723  } // namespace Fad
3724 
3725 } // namespace Sacado
3726 
3727 #endif // SACADO_CACHEFAD_OPS_HPP
cbrt(expr.val())
SACADO_INLINE_FUNCTION bool isActive() const
SACADO_INLINE_FUNCTION void cache() const
expr expr SinOp
SACADO_INLINE_FUNCTION const value_type dx(int i) const
expr2 expr1 expr2 expr2 c *expr2 c *expr1 c *expr2 c *expr1 MaxOp
asinh(expr.val())
SACADO_INLINE_FUNCTION value_type getTangent(int i) const
SACADO_INLINE_FUNCTION Expr(const ExprT &expr_)
SACADO_INLINE_FUNCTION value_type getTangent(int i) const
#define FAD_UNARYOP_MACRO(OPNAME, OP, USING, VALUE, DX, FASTACCESSDX)
asin(expr.val())
SACADO_INLINE_FUNCTION void getTangents(int i, value_type dots[]) const
cosh(expr.val())
expr expr dx(i)
abs(expr.val())
atanh(expr.val())
SACADO_INLINE_FUNCTION const value_type dx(int i) const
SACADO_INLINE_FUNCTION value_type val() const
SACADO_INLINE_FUNCTION const value_type * getDx(int j) const
expr expr CoshOp
expr expr ATanhOp
SACADO_INLINE_FUNCTION const value_type * getDx(int j) const
expr expr TanhOp
SACADO_INLINE_FUNCTION value_type val() const
SACADO_INLINE_FUNCTION bool updateValue() const
expr expr SqrtOp
expr expr ASinhOp
expr bar
atan(expr.val())
SACADO_INLINE_FUNCTION const value_type * getDx(int j) 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 bool isLinear() const
SACADO_INLINE_FUNCTION Expr< FAbsOp< Expr< T > > > fabs(const Expr< T > &expr)
SACADO_INLINE_FUNCTION bool hasFastAccess() 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 fastAccessDx(int i) const
SACADO_INLINE_FUNCTION const value_type fastAccessDx(int i) const
tanh(expr.val())
expr expr CosOp
SACADO_INLINE_FUNCTION bool updateValue() const
#define FAD_BINARYOP_MACRO(OPNAME, OP, USING, VALUE, DX, CDX1, CDX2, FASTACCESSDX, VAL_CONST_DX_1, VAL_CONST_DX_2, CONST_DX_1, CONST_DX_2, CONST_FASTACCESSDX_1, CONST_FASTACCESSDX_2)
SACADO_INLINE_FUNCTION value_type getTangent(int i) const
expr expr ATanOp
SACADO_INLINE_FUNCTION value_type val() const
SimpleFad< ValueT > min(const SimpleFad< ValueT > &a, const SimpleFad< ValueT > &b)
SACADO_INLINE_FUNCTION Expr< UnaryPlusOp< Expr< T > > > operator+(const Expr< T > &expr)
expr expr ACosOp
#define FAD_RELOP_MACRO(OP)
SACADO_INLINE_FUNCTION Expr(const ExprT &expr_)
SACADO_INLINE_FUNCTION void computePartials(const value_type &bar, value_type partials[]) const
SACADO_INLINE_FUNCTION void getTangents(int i, value_type dots[]) const
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 void getTangents(int i, value_type dots[]) const
SACADO_INLINE_FUNCTION void cache() const
#define FAD_BOOL_MACRO(OP)
atan2(expr1.val(), expr2.val())
SACADO_INLINE_FUNCTION bool operator!(const Expr< ExprT > &expr)
SACADO_INLINE_FUNCTION const value_type * getDx(int j) const
SACADO_INLINE_FUNCTION const value_type fastAccessDx(int i) const
SACADO_INLINE_FUNCTION Expr< AbsOp< Expr< T > > > abs(const Expr< T > &expr)
sin(expr.val())
SACADO_INLINE_FUNCTION const value_type dx(int i) const
expr expr expr fastAccessDx(i)) FAD_UNARYOP_MACRO(exp
SACADO_INLINE_FUNCTION const value_type fastAccessDx(int i) const
SACADO_INLINE_FUNCTION void getTangents(int i, value_type dots[]) const
SACADO_INLINE_FUNCTION T safe_sqrt(const T &x)
log(expr.val())
expr expr ACoshOp
expr expr Log10Op
expr expr SinhOp
acosh(expr.val())
SACADO_INLINE_FUNCTION Expr(const ExprT &expr_)
SACADO_INLINE_FUNCTION Expr< UnaryMinusOp< Expr< T > > > operator-(const Expr< T > &expr)
SACADO_INLINE_FUNCTION const value_type dx(int i) const
acos(expr.val())
SimpleFad< ValueT > max(const SimpleFad< ValueT > &a, const SimpleFad< ValueT > &b)
expr expr ASinOp
SACADO_INLINE_FUNCTION value_type val() const
SACADO_INLINE_FUNCTION Expr(const ExprT &expr_)
SACADO_INLINE_FUNCTION bool isActive() const
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 void computePartials(const value_type &bar, value_type partials[]) const
SACADO_INLINE_FUNCTION void computePartials(const value_type &bar, value_type partials[]) const
SACADO_INLINE_FUNCTION bool hasFastAccess() const
#define SACADO_INLINE_FUNCTION
exp(expr.val())
expr expr expr ExpOp
SACADO_INLINE_FUNCTION bool isLinear() const
fabs(expr.val())
SACADO_INLINE_FUNCTION void computePartials(const value_type &bar, value_type partials[]) const
expr expr TanOp
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