Prev Next zdouble.cpp Headings

@(@\newcommand{\W}[1]{ \; #1 \; } \newcommand{\R}[1]{ {\rm #1} } \newcommand{\B}[1]{ {\bf #1} } \newcommand{\D}[2]{ \frac{\partial #1}{\partial #2} } \newcommand{\DD}[3]{ \frac{\partial^2 #1}{\partial #2 \partial #3} } \newcommand{\Dpow}[2]{ \frac{\partial^{#1}}{\partial {#2}^{#1}} } \newcommand{\dpow}[2]{ \frac{ {\rm d}^{#1}}{{\rm d}\, {#2}^{#1}} }@)@
zdouble: Example and Test
# include <cppad/cppad.hpp>

namespace {
     template <class Base> bool test_one(void)
     {     bool ok = true;
          Base eps99 = 99. * std::numeric_limits<double>::epsilon();

          typedef CppAD::AD<Base>   a1type;
          typedef CppAD::AD<a1type> a2type;

          // value during taping
          size_t n = 2;
          CPPAD_TESTVECTOR(Base) x(n);
          x[0] = 0.0;
          x[1] = 0.0;

          // declare independent variable
          CPPAD_TESTVECTOR(a2type) a2x(n);
          for (size_t j = 0; j < n; j++)
               a2x[j] = a2type( a1type(x[j]) );
          Independent(a2x);

          // zero and one as a2type values
          a2type a2zero = a2type(0.0);
          a2type a2one  = a2type(1.0);

          // h(x) = x[0] / x[1] if x[1] > x[0] else 1.0
          a2type h_x = CondExpGt(a2x[1], a2x[0], a2x[0] / a2x[1], a2one);

          // f(x) = h(x) if x[0] > 0.0 else 0.0
          //      = x[0] / x[1] if x[1] > x[0]  and x[0] > 0.0
          //      = 1.0         if x[0] >= x[1] and x[0] > 0.0
          //      = 0.0         if x[0] <= 0.0
          a2type f_x = CondExpGt(a2x[0], a2zero, h_x, a2one);

          // define the function f(x)
          size_t m = 1;
          CPPAD_TESTVECTOR(a2type) a2y(m);
          a2y[0] = f_x;
          CppAD::ADFun<a1type> af1;
          af1.Dependent(a2x, a2y);

          // Define function g(x) = gradient of f(x)
          CPPAD_TESTVECTOR(a1type) a1x(n), a1z(n), a1w(m);
          for (size_t j = 0; j < n; j++)
               a1x[j] = a1type(x[j]);
          a1w[0] = a1type(1.0);
          Independent(a1x);
          af1.Forward(0, a1x);
          a1z = af1.Reverse(1, a1w);
          CppAD::ADFun<Base> g;
          g.Dependent(a1x, a1z);

          // check result for a case where f(x) = 0.0;
          CPPAD_TESTVECTOR(Base) z(2);
          x[0] = 0.0;
          x[1] = 0.0;
          z    = g.Forward(0, x);
          ok &= z[0] == 0.0;
          ok &= z[1] == 0.0;

          // check result for a case where f(x) = 1.0;
          x[0] = 1.0;
          x[1] = 0.5;
          z    = g.Forward(0, x);
          ok &= z[0] == 0.0;
          ok &= z[1] == 0.0;

          // check result for a case where f(x) = x[0] / x[1];
          x[0] = 1.0;
          x[1] = 2.0;
          z    = g.Forward(0, x);
          ok &= CppAD::NearEqual(z[0], 1.0/x[1], eps99, eps99);
          ok &= CppAD::NearEqual(z[1], - x[0]/(x[1]*x[1]), eps99, eps99);

          return ok;
     }
     bool test_two(void)
     {     bool ok = true;
          using CppAD::zdouble;
          //
          zdouble eps = CppAD::numeric_limits<zdouble>::epsilon();
          ok          &= eps == std::numeric_limits<double>::epsilon();
          //
          zdouble min = CppAD::numeric_limits<zdouble>::min();
          ok          &= min == std::numeric_limits<double>::min();
          //
          zdouble max = CppAD::numeric_limits<zdouble>::max();
          ok          &= max == std::numeric_limits<double>::max();
          //
          zdouble nan = CppAD::numeric_limits<zdouble>::quiet_NaN();
          ok          &= nan != nan;
          //
          int digits10 = CppAD::numeric_limits<zdouble>::digits10;
          ok          &= digits10 == std::numeric_limits<double>::digits10;
          //
          return ok;
     }
}

bool zdouble(void)
{     bool ok = true;
     using CppAD::AD;
     using CppAD::NearEqual;
     using CppAD::zdouble;
     //
     ok &= test_one<zdouble>();
     ok &= test_one<double>();
     //
     ok &= test_two();
     //
     return ok;
}

Input File: example/deprecated/zdouble.cpp