Enable use of AD<Base> where Base is Adolc's adouble Type
Keywords: enable use ad<base> where base is adolc's adouble type syntax example include files condexpop condexprel equalopseq identical integer azmul ordered unary standard math erf asinh acosh atanh expm1 log1p sign abs pow numeric_limits

| 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)
    }

`

Input File: cppad/example/base_adolc.hpp