text: /* --------------------------------------------------------------------------
  CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
  
  CppAD is distributed under the terms of the
               Eclipse Public License Version 2.0.
  
  This Source Code may also be made available under the following
  Secondary License when the conditions for such availability set forth
  in the Eclipse Public License, Version 2.0 are satisfied:
        GNU General Public License, Version 2.0 or later.
  ---------------------------------------------------------------------------- */
  /*
  ! WARNING: This file is used as an example by FunConstruct and Dependent
  
  $begin fun_check.cpp$$
  $spell
      abs
  $$
  
  $section ADFun Check and Re-Tape: Example and Test$$
  
  
  
  
  $srcfile%example/general/fun_check.cpp%0%// BEGIN C++%// END C++%1%$$
  
  $end
  */
  // BEGIN C++
  # include <cppad/cppad.hpp>
  
  namespace { // -----------------------------------------------------------
  // define the template function object Fun<Type,Vector> in empty namespace
  template <class Type, class Vector>
  class Fun {
  private:
      size_t n;
  public:
      // function constructor
      Fun(size_t n_) : n(n_)
      { }
      // function evaluator
      Vector operator() (const Vector &x)
      {   Vector y(n);
          size_t i;
          for(i = 0; i < n; i++)
          {   // This operaiton sequence depends on x
              if( x[i] >= 0 )
                  y[i] = exp(x[i]);
              else
                  y[i] = exp(-x[i]);
          }
          return y;
      }
  };
  // template function FunCheckCases<Vector, ADVector> in empty namespace
  template <class Vector, class ADVector>
  bool FunCheckCases(void)
  {   bool ok = true;
      using CppAD::AD;
      using CppAD::ADFun;
      using CppAD::Independent;
      double eps99 = 99.0 * std::numeric_limits<double>::epsilon();
  
      // use the ADFun default constructor
      ADFun<double> f;
  
      // domain space vector
      size_t n = 2;
      ADVector X(n);
      X[0] = -1.;
      X[1] = 1.;
  
      // declare independent variables and starting recording
      Independent(X);
  
      // create function object to use with AD<double>
      Fun< AD<double>, ADVector > G(n);
  
      // range space vector
      size_t m = n;
      ADVector Y(m);
      Y = G(X);
  
      // stop tape and store operation sequence in f : X -> Y
      f.Dependent(X, Y);
      ok &= (f.size_order() == 0);  // no implicit forward operation
  
      // create function object to use with double
      Fun<double, Vector> g(n);
  
      // function values should agree when the independent variable
      // values are the same as during recording
      Vector x(n);
      size_t j;
      for(j = 0; j < n; j++)
          x[j] = Value(X[j]);
      double r = eps99;
      double a = eps99;
      ok      &= FunCheck(f, g, x, a, r);
  
      // function values should not agree when the independent variable
      // values are the negative of values during recording
      for(j = 0; j < n; j++)
          x[j] = - Value(X[j]);
      ok      &= ! FunCheck(f, g, x, a, r);
  
      // re-tape to obtain the new AD of double operation sequence
      for(j = 0; j < n; j++)
          X[j] = x[j];
      Independent(X);
      Y = G(X);
  
      // stop tape and store operation sequence in f : X -> Y
      f.Dependent(X, Y);
      ok &= (f.size_order() == 0);  // no implicit forward with this x
  
      // function values should agree now
      ok      &= FunCheck(f, g, x, a, r);
  
      return ok;
  }
  } // End empty namespace
  # include <vector>
  # include <valarray>
  bool FunCheck(void)
  {   bool ok = true;
      typedef CppAD::vector<double>                Vector1;
      typedef CppAD::vector< CppAD::AD<double> > ADVector1;
      typedef   std::vector<double>                Vector2;
      typedef   std::vector< CppAD::AD<double> > ADVector2;
      typedef std::valarray<double>                Vector3;
      typedef std::valarray< CppAD::AD<double> > ADVector3;
      // Run with Vector and ADVector equal to three different cases
      // all of which are Simple Vectors with elements of type
      // double and AD<double> respectively.
      ok &= FunCheckCases< Vector1, ADVector2 >();
      ok &= FunCheckCases< Vector2, ADVector3 >();
      ok &= FunCheckCases< Vector3, ADVector1 >();
      return ok;
  }
  // END C++
  