| Prev | Next |  |  |  |  |  |  |

Enable use of AD<Base> where Base is Adolc's adouble Type
Syntax
`# include <cppad/example/base_adolc.hpp>
`
Example
The file mul_level_adolc.cpp contains an example use of Adolc's `adouble` type for a CppAD `Base` type. It returns true if it succeeds and false otherwise. The file mul_level_adolc_ode.cpp contains a more realistic (and complex) example.
Include Files
This file `base_adolc.hpp` requires `adouble` to be defined. In addition, it is included before `<cppad/cppad.hpp>`, but it needs to include parts of CppAD that are used by this file. This is done with the following include commands:

    # include <adolc/adolc.h>
    # include <cppad/base_require.hpp>

CondExpOp
The type `adouble` supports a conditional assignment function with the syntax `
condassign(a, b, c, d)
` which evaluates to `
a = (b > 0) ? c : d;
` This enables one to include conditionals in the recording of `adouble` operations and later evaluation for different values of the independent variables (in the same spirit as the CppAD CondExp function).

    namespace CppAD {
         inline adouble CondExpOp(
              enum  CppAD::CompareOp     cop ,
              const adouble            &left ,
              const adouble           &right ,
              const adouble        &trueCase ,
              const adouble       &falseCase )
         {     adouble result;
              switch( cop )
              {
                   case CompareLt: // left < right
                   condassign(result, right - left, trueCase, falseCase);
                   break;

                   case CompareLe: // left <= right
                   condassign(result, left - right, falseCase, trueCase);
                   break;

                   case CompareEq: // left == right
                   condassign(result, left - right, falseCase, trueCase);
                   condassign(result, right - left, falseCase, result);
                   break;

                   case CompareGe: // left >= right
                   condassign(result, right - left, falseCase, trueCase);
                   break;

                   case CompareGt: // left > right
                   condassign(result, left - right, trueCase, falseCase);
                   break;
                   default:
                   CppAD::ErrorHandler::Call(
                        true     , __LINE__ , __FILE__ ,
                        "CppAD::CondExp",
                        "Error: for unknown reason."
                   );
                   result = trueCase;
              }
              return result;
         }
    }

CondExpRel
The CPPAD_COND_EXP_REL macro invocation

    namespace CppAD {
         CPPAD_COND_EXP_REL(adouble)
    }

EqualOpSeq
The Adolc user interface does not specify a way to determine if two `adouble` variables correspond to the same operations sequence. Make `EqualOpSeq` an error if it gets used:

    namespace CppAD {
         inline bool EqualOpSeq(const adouble &x, const adouble &y)
         {     CppAD::ErrorHandler::Call(
                   true     , __LINE__ , __FILE__ ,
                   "CppAD::EqualOpSeq(x, y)",
                   "Error: adouble does not support EqualOpSeq."
              );
              return false;
         }
    }

Identical
The Adolc user interface does not specify a way to determine if an `adouble` depends on the independent variables. To be safe (but slow) return `false` in all the cases below.

    namespace CppAD {
         inline bool IdenticalPar(const adouble &x)
         {     return false; }
         inline bool IdenticalZero(const adouble &x)
         {     return false; }
         inline bool IdenticalOne(const adouble &x)
         {     return false; }
         inline bool IdenticalEqualPar(const adouble &x, const adouble &y)
         {     return false; }
    }

Integer

         inline int Integer(const adouble &x)
         {    return static_cast<int>( x.getValue() ); }

azmul

    namespace CppAD {
         CPPAD_AZMUL( adouble )
    }

Ordered

    namespace CppAD {
         inline bool GreaterThanZero(const adouble &x)
         {    return (x > 0); }
         inline bool GreaterThanOrZero(const adouble &x)
         {    return (x >= 0); }
         inline bool LessThanZero(const adouble &x)
         {    return (x < 0); }
         inline bool LessThanOrZero(const adouble &x)
         {    return (x <= 0); }
         inline bool abs_geq(const adouble& x, const adouble& y)
         {     return fabs(x) >= fabs(y); }
    }

Unary Standard Math
The following required functions are defined by the Adolc package for the `adouble` base case: `
` `acos`, `asin`, `atan`, `cos`, `cosh`, `exp`, `fabs`, `log`, `sin`, `sinh`, `sqrt`, `tan`.
erf, asinh, acosh, atanh, expm1, log1p
If the erf, asinh, acosh, atanh, expm1, log1p , functions are supported by the compiler, they must also be supported by a `Base` type; The adolc package does not support these functions so make their use an error:

    namespace CppAD {
    # define CPPAD_BASE_ADOLC_NO_SUPPORT(fun)                         \
        inline adouble fun(const adouble& x)                          \
        {   CPPAD_ASSERT_KNOWN(                                       \
                false,                                                \
                #fun ": adolc does not support this function"         \
            );                                                        \
            return 0.0;                                               \
        }
    # if CPPAD_USE_CPLUSPLUS_2011
         CPPAD_BASE_ADOLC_NO_SUPPORT(erf)
         CPPAD_BASE_ADOLC_NO_SUPPORT(asinh)
         CPPAD_BASE_ADOLC_NO_SUPPORT(acosh)
         CPPAD_BASE_ADOLC_NO_SUPPORT(atanh)
         CPPAD_BASE_ADOLC_NO_SUPPORT(expm1)
         CPPAD_BASE_ADOLC_NO_SUPPORT(log1p)
    # endif
    # undef CPPAD_BASE_ADOLC_NO_SUPPORT
    }

sign
This required function is defined using the `codassign` function so that its `adouble` operation sequence does not depend on the value of `x` .

    namespace CppAD {
         inline adouble sign(const adouble& x)
         {     adouble s_plus, s_minus, half(.5);
              // set s_plus to sign(x)/2,  except for case x == 0, s_plus = -.5
              condassign(s_plus,  +x, -half, +half);
              // set s_minus to -sign(x)/2, except for case x == 0, s_minus = -.5
              condassign(s_minus, -x, -half, +half);
              // set s to sign(x)
              return s_plus - s_minus;
         }
    }

abs
This required function uses the adolc `fabs` function:

    namespace CppAD {
         inline adouble abs(const adouble& x)
         {     return fabs(x); }
    }

pow
This required function is defined by the Adolc package for the `adouble` base case.
numeric_limits
The following defines the CppAD numeric_limits for the type `adouble`:

    namespace CppAD {
         CPPAD_NUMERIC_LIMITS(double, adouble)
    }

to_string
The following defines the CppAD to_string function for the type `adouble`:

    namespace CppAD {
         template <> struct to_string_struct<adouble>
         {     std::string operator()(const adouble& x)
              {     std::stringstream os;
                   int n_digits = 1 + std::numeric_limits<double>::digits10;
                   os << std::setprecision(n_digits);
                   os << x.value();
                   return os.str();
              }
         };
    }

hash_code
It appears that an `adouble` object can have fields that are not initialized. This results in a `valgrind` error when these fields are used by the default hashing function. For this reason, the `adouble` class overrides the default definition.

    namespace CppAD {
         inline unsigned short hash_code(const adouble& x)
         {     unsigned short code = 0;
              double value = x.value();
              if( value == 0.0 )
                   return code;
              double log_x = std::log( fabs( value ) );
              // assume log( std::numeric_limits<double>::max() ) is near 700
              code = static_cast<unsigned short>(
                   (CPPAD_HASH_TABLE_SIZE / 700 + 1) * log_x
              );
              code = code % CPPAD_HASH_TABLE_SIZE;
              return code;
         }
    }

Note that after the hash codes match, the Identical function will be used to make sure two values are the same and one can replace the other. A more sophisticated implementation of the `Identical` function would detect which `adouble` values depend on the `adouble` independent variables (and hence can change).

Input File: cppad/example/base_adolc.hpp