Prev Next

Enable use of AD<Base> where Base is std::complex<double>

Example
The file ComplexPoly.cpp contains an example use of std::complex<double> type for a CppAD Base type. It returns true if it succeeds and false otherwise.

See Also
The file not_complex_ad.cpp contains an example using complex arithmetic where the function is not complex differentiable.

Include File
This file is included before <cppad/cppad.hpp> so it is necessary to define the error handler in addition to including declare.hpp
# include <complex>
# include <cppad/declare.hpp>
# include <cppad/error_handler.hpp>

CondExpOp
The conditional expressions CondExp requires ordered comparisons (e.g., <) and the C++ standard complex types do not allow for ordered comparisons. Thus, we make it an error to use the conditional comparisons with complex types:
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);
     }
}

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
namespace CppAD {
     inline bool GreaterThanZero(const std::complex<double> &x)
     {    CppAD::ErrorHandler::Call(
               true     , __LINE__ , __FILE__ ,
               "GreaterThanZero(x)",
               "Error: cannot use GreaterThanZero with complex"
          );
          return false;
     }
     inline bool GreaterThanOrZero(const std::complex<double> &x)
     {    CppAD::ErrorHandler::Call(
               true     , __LINE__ , __FILE__ ,
               "GreaterThanZero(x)",
               "Error: cannot use GreaterThanZero with complex"
          );
          return false;
     }
     inline bool LessThanZero(const std::complex<double> &x)
     {    CppAD::ErrorHandler::Call(
               true     , __LINE__ , __FILE__ ,
               "LessThanZero(x)",
               "Error: cannot use LessThanZero with complex"
          );
          return false;
     }
     inline bool LessThanOrZero(const std::complex<double> &x)
     {    CppAD::ErrorHandler::Call(
               true     , __LINE__ , __FILE__ ,
               "LessThanZero(x)",
               "Error: cannot use LessThanZero with complex"
          );
          return false;
     }
}

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

Standard Functions

Valid Complex Functions
The following standard math functions, that are required by base_require , are defined by std::complex: cos, cosh, exp, log, pow, sin, sinh, sqrt.
# define CPPAD_USER_MACRO(function)                                   \
inline std::complex<double> function(const std::complex<double> &x)   \
{    return std::function(x); }

namespace CppAD {
     CPPAD_USER_MACRO(cos)
     CPPAD_USER_MACRO(cosh)
     CPPAD_USER_MACRO(exp)
     CPPAD_USER_MACRO(log)
     inline std::complex<double> pow(
          const std::complex<double> &x , 
          const std::complex<double> &y )
     {    return std::pow(x, y); }
     CPPAD_USER_MACRO(sin)
     CPPAD_USER_MACRO(sinh)
     CPPAD_USER_MACRO(sqrt)
}
# undef CPPAD_USER_MACRO

Invalid Complex Functions
The other standard math functions, (and abs) required by base_require are not defined for complex types (see abs ). Hence we make it an error to use them. (Note that the standard math functions are not defined in the CppAD namespace.)
# define CPPAD_USER_MACRO(function)                                          \
inline std::complex<double> function(const std::complex<double> &x)          \
{      CppAD::ErrorHandler::Call(                                            \
               true     , __LINE__ , __FILE__ ,                              \
               "std::complex<double>",                                       \
               "Error: cannot use " #function " with 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(erf)
}
# undef CPPAD_USER_MACRO

Input File: cppad/local/base_complex.hpp