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