base_complex.hpp

View page source

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.

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/core/cppad_assert.hpp>

CondExpOp

The type std::complex<double> does not support the < , <= , >= , and > operators; see Not Ordered . Hence these operators and CondExpOp function are defined by

# define CPPAD_TEMP(op)                                          \
    inline bool operator op(                                      \
        const std::complex<double>& left   ,                       \
        const std::complex<double>& right  )                       \
    {  CppAD::ErrorHandler::Call(                                 \
            true     , __LINE__ , __FILE__ ,                        \
            "std::complex<double> " #op " std::complex<double>" ,   \
            "Error: std::complex is not an ordered type"            \
        );                                                         \
        return false;                                              \
    }
namespace CppAD {
    CPPAD_TEMP(<)
    CPPAD_TEMP(<=)
    CPPAD_TEMP(>=)
    CPPAD_TEMP(>)
    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);
    }
}
# undef CPPAD_TEMP

CondExpRel

The CPPAD_COND_EXP_REL macro invocation

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

used CondExpOp above to define CondExp Rel 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 IdenticalCon(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 IdenticalEqualCon(
        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 compiler 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(fabs)
    CPPAD_USER_MACRO(acos)
    CPPAD_USER_MACRO(asin)
    CPPAD_USER_MACRO(atan)
    CPPAD_USER_MACRO(sign)
    CPPAD_USER_MACRO(asinh)
    CPPAD_USER_MACRO(acosh)
    CPPAD_USER_MACRO(atanh)
    CPPAD_USER_MACRO(erf)
    CPPAD_USER_MACRO(erfc)
    CPPAD_USER_MACRO(expm1)
    CPPAD_USER_MACRO(log1p)
}

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