Enable use of AD<Base> where Base is std::complex<double>
Keywords: enable use ad<base> where base is std::complex<double> example include order condexpop condexprel equalopseq identical ordered integer azmul isnan valid unary math invalid pow numeric_limits to_string

| Prev | Next |  |  |  |  |  |  |

Enable use of AD<Base> where Base is std::complex<double>
Example
The file complex_poly.cpp contains an example use of `std::complex<double>` type for a CppAD `Base` type. It returns true if it succeeds and false otherwise.
Include Order
This file is included before `<cppad/cppad.hpp>` so it is necessary to define the error handler in addition to including base_require.hpp `

    # include <limits>
    # include <complex>
    # include <cppad/base_require.hpp>
    # include <cppad/local/cppad_assert.hpp>

` CondExpOp
The type `std::complex<double>` does not supports the `<`, `<=`, `==`, `>=`, and `>` operators; see not ordered . Hence its `CondExpOp` function is defined by `

    namespace CppAD {
         inline std::complex<double> CondExpOp(
              enum CppAD::CompareOp      cop        ,
              const std::complex<double> &left      ,
              const std::complex<double> &right     ,
              const std::complex<double> &trueCase  ,
              const std::complex<double> &falseCase )
         {    CppAD::ErrorHandler::Call(
                   true     , __LINE__ , __FILE__ ,
                   "std::complex<float> CondExpOp(...)",
                   "Error: cannot use CondExp with a complex type"
              );
              return std::complex<double>(0);
         }
    }

`
CondExpRel
The CPPAD_COND_EXP_REL macro invocation `

    namespace CppAD {
         CPPAD_COND_EXP_REL( std::complex<double> )
    }

` used `CondExpOp` above to define `CondExpRel` for `std::complex<double>` arguments and `Rel` equal to `Lt`, `Le`, `Eq`, `Ge`, and `Gt`.
EqualOpSeq
Complex numbers do not carry operation sequence information. Thus they are equal in this sense if and only if there values are equal. `

    namespace CppAD {
         inline bool EqualOpSeq(
              const std::complex<double> &x ,
              const std::complex<double> &y )
         {    return x == y;
         }
    }

`
Identical
Complex numbers do not carry operation sequence information. Thus they are all parameters so the identical functions just check values. `

    namespace CppAD {
         inline bool IdenticalPar(const std::complex<double> &x)
         {    return true; }
         inline bool IdenticalZero(const std::complex<double> &x)
         {    return (x == std::complex<double>(0., 0.) ); }
         inline bool IdenticalOne(const std::complex<double> &x)
         {    return (x == std::complex<double>(1., 0.) ); }
         inline bool IdenticalEqualPar(
              const std::complex<double> &x, const std::complex<double> &y)
         {    return (x == y); }
    }

`
Ordered
Complex types do not support comparison operators, `

    # undef  CPPAD_USER_MACRO
    # define CPPAD_USER_MACRO(Fun)                                     \
    inline bool Fun(const std::complex<double>& x)                     \
    {      CppAD::ErrorHandler::Call(                                  \
                   true     , __LINE__ , __FILE__ ,                    \
                   #Fun"(x)",                                          \
                   "Error: cannot use " #Fun " with x complex<double> " \
           );                                                          \
           return false;                                               \
    }
    namespace CppAD {
         CPPAD_USER_MACRO(LessThanZero)
         CPPAD_USER_MACRO(LessThanOrZero)
         CPPAD_USER_MACRO(GreaterThanOrZero)
         CPPAD_USER_MACRO(GreaterThanZero)
         inline bool abs_geq(
              const std::complex<double>& x ,
              const std::complex<double>& y )
         {    return std::abs(x) >= std::abs(y); }
    }

`
Integer
The implementation of this function must agree with the CppAD user specifications for complex arguments to the Integer function: `

    namespace CppAD {
         inline int Integer(const std::complex<double> &x)
         {    return static_cast<int>( x.real() ); }
    }

`
azmul `

    namespace CppAD {
         CPPAD_AZMUL( std::complex<double> )
    }

`
isnan
The gcc 4.1.1 complier defines the function `
int std::complex<double>::isnan( std::complex<double> z )
` (which is not specified in the C++ 1998 standard ISO/IEC 14882). This causes an ambiguity between the function above and the CppAD isnan template function. We avoid this ambiguity by defining a non-template version of this function in the CppAD namespace. `

    namespace CppAD {
         inline bool isnan(const std::complex<double>& z)
         {    return (z != z);
         }
    }

`
Valid Unary Math
The following macro invocations define the standard unary math functions that are valid with complex arguments and are required to use `AD< std::complex<double> >`. `

    namespace CppAD {
         CPPAD_STANDARD_MATH_UNARY(std::complex<double>, cos)
         CPPAD_STANDARD_MATH_UNARY(std::complex<double>, cosh)
         CPPAD_STANDARD_MATH_UNARY(std::complex<double>, exp)
         CPPAD_STANDARD_MATH_UNARY(std::complex<double>, log)
         CPPAD_STANDARD_MATH_UNARY(std::complex<double>, sin)
         CPPAD_STANDARD_MATH_UNARY(std::complex<double>, sinh)
         CPPAD_STANDARD_MATH_UNARY(std::complex<double>, sqrt)
    }

`
Invalid Unary Math
The following macro definition and invocations define the standard unary math functions that are invalid with complex arguments and are required to use `AD< std::complex<double> >`. `

    # undef  CPPAD_USER_MACRO
    # define CPPAD_USER_MACRO(Fun)                                     \
    inline std::complex<double> Fun(const std::complex<double>& x)     \
    {      CppAD::ErrorHandler::Call(                                  \
                   true     , __LINE__ , __FILE__ ,                    \
                   #Fun"(x)",                                          \
                   "Error: cannot use " #Fun " with x complex<double> " \
           );                                                          \
           return std::complex<double>(0);                             \
    }
    namespace CppAD {
         CPPAD_USER_MACRO(abs)
         CPPAD_USER_MACRO(acos)
         CPPAD_USER_MACRO(asin)
         CPPAD_USER_MACRO(atan)
         CPPAD_USER_MACRO(sign)
    # if CPPAD_USE_CPLUSPLUS_2011
         CPPAD_USER_MACRO(erf)
         CPPAD_USER_MACRO(asinh)
         CPPAD_USER_MACRO(acosh)
         CPPAD_USER_MACRO(atanh)
         CPPAD_USER_MACRO(expm1)
         CPPAD_USER_MACRO(log1p)
    # endif
    }

`
pow
The following defines a `CppAD::pow` function that is required to use `AD< std::complex<double> >`: `

    namespace CppAD {
         inline std::complex<double> pow(
              const std::complex<double> &x ,
              const std::complex<double> &y )
         {    return std::pow(x, y); }
    }

`
numeric_limits
The following defines the CppAD numeric_limits for the type `std::complex<double>`: `

    namespace CppAD {
         CPPAD_NUMERIC_LIMITS(double, std::complex<double>)
    }

`
to_string
The following defines the function CppAD to_string for the type `std::complex<double>`: `

    namespace CppAD {
         CPPAD_TO_STRING(std::complex<double>)
    }

`

Input File: cppad/local/base_complex.hpp