inline Sacado::ELRCacheFad::Expr< Sacado::ELRCacheFad::SFadExprTag<T,Num> >::
Expr(const Expr<S>& x) : update_val_(x.updateValue())
{
#ifdef SACADO_DEBUG
  if (x.size() != Num)
    throw "ELRCacheFad::SFad() Error:  Attempt to assign with incompatible sizes";
#endif

  x.cache();

  if (update_val_)
    this->val() = x.val();
  else
    this->val() = T(0.);

  // Number of arguments
  const int N = Expr<S>::num_args;

  // Compute partials
  LocalAccumOp< Expr<S> > op(x);
  
  // Compute each tangent direction
  for(int i=0; i<Num; ++i) {
    op.t = T(0.);
    op.i = i;

    // Automatically unrolled loop that computes
    // for (int j=0; j<N; j++)
    //   op.t += op.partials[j] * x.getTangent<j>(i);
    Sacado::mpl::for_each< mpl::range_c< int, 0, N > > f(op);

    dx_[i] = op.t;

  }
}
inline Sacado::CacheFad::Expr< Sacado::CacheFad::SFadExprTag<T,Num> >::
Expr(const Expr<S>& x) : update_val_(x.updateValue())
{
#ifdef SACADO_DEBUG
  if (x.size() != Num)
    throw "CacheFad::SFad() Error:  Attempt to assign with incompatible sizes";
#endif

  x.cache();

  if (update_val_)
    this->val() = x.val();
  else
    this->val() = T(0.);

  for(int i=0; i<Num; ++i) 
    dx_[i] = x.fastAccessDx(i);
}
inline Sacado::CacheFad::Expr< Sacado::CacheFad::SFadExprTag<T,Num> >& 
Sacado::CacheFad::Expr< Sacado::CacheFad::SFadExprTag<T,Num> >::
operator=(const Expr<S>& x) 
{
#ifdef SACADO_DEBUG
  if (x.size() != Num)
    throw "CacheFad::operator=() Error:  Attempt to assign with incompatible sizes";
#endif

  x.cache();

  for(int i=0; i<Num; ++i)
    dx_[i] = x.fastAccessDx(i);
  
  update_val_ = x.updateValue();
  if (update_val_)
    val_ = x.val();
  
  return *this;
}
inline Sacado::ELRCacheFad::GeneralFad<T,Storage>::
GeneralFad(const Expr<S>& x) :
  Storage(T(0.)),
  update_val_(x.updateValue())
{
  x.cache();

  int sz = x.size();

  // Compute value
  if (update_val_)
    this->val() = x.val();

  if (sz != this->size()) 
    this->resize(sz);

  if (sz) {

    if (Expr<S>::is_linear) {
      if (x.hasFastAccess())
        for(int i=0; i<sz; ++i)
          this->fastAccessDx(i) = x.fastAccessDx(i);
      else
        for(int i=0; i<sz; ++i)
          this->fastAccessDx(i) = x.dx(i);
    }
    else {

      // Number of arguments
      const int N = Expr<S>::num_args;

      if (x.hasFastAccess()) {
	// Compute partials
	FastLocalAccumOp< Expr<S> > op(x);
  
	// Compute each tangent direction
	for(op.i=0; op.i<sz; ++op.i) {
	  op.t = T(0.);

	  // Automatically unrolled loop that computes
	  // for (int j=0; j<N; j++)
	  //   op.t += op.partials[j] * x.getTangent<j>(i);
	  Sacado::mpl::for_each< mpl::range_c< int, 0, N > > f(op);
	  
	  this->fastAccessDx(op.i) = op.t;
	}
      }
      else {
	// Compute partials
	SlowLocalAccumOp< Expr<S> > op(x);
  
	// Compute each tangent direction
	for(op.i=0; op.i<sz; ++op.i) {
	  op.t = T(0.);

	  // Automatically unrolled loop that computes
	  // for (int j=0; j<N; j++)
	  //   op.t += op.partials[j] * x.getTangent<j>(i);
	  Sacado::mpl::for_each< mpl::range_c< int, 0, N > > f(op);
	  
	  this->fastAccessDx(op.i) = op.t;
	}
      }

    }
  }
}