# ifndef CPPAD_BASE_COMPLEX_INCLUDED
# define CPPAD_BASE_COMPLEX_INCLUDED
/* --------------------------------------------------------------------------
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-07 Bradley M. Bell
CppAD is distributed under multiple licenses. This distribution is under
the terms of the
Common Public License Version 1.0.
A copy of this license is included in the COPYING file of this distribution.
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
-------------------------------------------------------------------------- */
/*
$begin base_complex.hpp$$
$spell
cppad.hpp
sqrt
exp
cos
std
const
CppAD
Op
inline
enum
undef
acos
asin
atan
erf
Cond
namespace
bool
$$
$index complex, double Base$$
$index Base, double complex$$
$index double, complex Base$$
$section Enable use of AD where Base is std::complex$$
$children%
example/complex_poly.cpp%
example/not_complex_ad.cpp
%$$
$head Example$$
The file $cref/ComplexPoly.cpp/$$ contains an example use of
$code std::complex$$ type for a CppAD $italic Base$$ type.
It returns true if it succeeds and false otherwise.
$head See Also$$
The file $cref/not_complex_ad.cpp/$$ contains an example using
complex arithmetic where the function is not complex differentiable.
$head Include File$$
This file is included before $code $$
so it is necessary to define the error handler
in addition to including
$cref/declare.hpp/base_require/declare.hpp/$$
$codep */
# include
# include
# include
/* $$
$head CondExpOp$$
The conditional expressions $cref/CondExp/$$
requires ordered comparisons (e.g., $code <$$)
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:
$codep */
namespace CppAD {
inline std::complex CondExpOp(
enum CppAD::CompareOp cop ,
const std::complex &left ,
const std::complex &right ,
const std::complex &trueCase ,
const std::complex &falseCase )
{ CppAD::ErrorHandler::Call(
true , __LINE__ , __FILE__ ,
"std::complex CondExpOp(...)",
"Error: cannot use CondExp with a complex type"
);
return std::complex(0);
}
}
/* $$
$head EqualOpSeq$$
Complex numbers do not carry operation sequence information.
Thus they are equal in this sense if and only if there values are equal.
$codep */
namespace CppAD {
inline bool EqualOpSeq(
const std::complex &x ,
const std::complex &y )
{ return x == y;
}
}
/* $$
$head Identical$$
Complex numbers do not carry operation sequence information.
Thus they are all parameters so the identical functions just check values.
$codep */
namespace CppAD {
inline bool IdenticalPar(const std::complex &x)
{ return true; }
inline bool IdenticalZero(const std::complex &x)
{ return (x == std::complex(0., 0.) ); }
inline bool IdenticalOne(const std::complex &x)
{ return (x == std::complex(1., 0.) ); }
inline bool IdenticalEqualPar(
const std::complex &x, const std::complex &y)
{ return (x == y); }
}
/* $$
$head Ordered$$
$codep */
namespace CppAD {
inline bool GreaterThanZero(const std::complex &x)
{ CppAD::ErrorHandler::Call(
true , __LINE__ , __FILE__ ,
"GreaterThanZero(x)",
"Error: cannot use GreaterThanZero with complex"
);
return false;
}
inline bool GreaterThanOrZero(const std::complex &x)
{ CppAD::ErrorHandler::Call(
true , __LINE__ , __FILE__ ,
"GreaterThanZero(x)",
"Error: cannot use GreaterThanZero with complex"
);
return false;
}
inline bool LessThanZero(const std::complex &x)
{ CppAD::ErrorHandler::Call(
true , __LINE__ , __FILE__ ,
"LessThanZero(x)",
"Error: cannot use LessThanZero with complex"
);
return false;
}
inline bool LessThanOrZero(const std::complex &x)
{ CppAD::ErrorHandler::Call(
true , __LINE__ , __FILE__ ,
"LessThanZero(x)",
"Error: cannot use LessThanZero with complex"
);
return false;
}
}
/* $$
$head Integer$$
The implementation of this function must agree
with the CppAD user specifications for complex arguments to the
$cref/Integer/Integer/x/Complex Types/$$ function:
$codep */
namespace CppAD {
inline int Integer(const std::complex &x)
{ return static_cast( x.real() ); }
}
/* $$
$head Standard Functions$$
$subhead Valid Complex Functions$$
The following standard math functions,
that are required by $cref/base_require/$$,
are defined by
$code std::complex$$:
$code cos$$,
$code cosh$$,
$code exp$$,
$code log$$,
$code pow$$,
$code sin$$,
$code sinh$$,
$code sqrt$$.
$codep */
# define CPPAD_USER_MACRO(function) \
inline std::complex function(const std::complex &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 pow(
const std::complex &x ,
const std::complex &y )
{ return std::pow(x, y); }
CPPAD_USER_MACRO(sin)
CPPAD_USER_MACRO(sinh)
CPPAD_USER_MACRO(sqrt)
}
# undef CPPAD_USER_MACRO
/* $$
$subhead Invalid Complex Functions$$
The other standard math functions,
(and $code abs$$) required by $cref/base_require/$$
are not defined for complex types
(see $cref/abs/abs/Complex Types/$$).
Hence we make it an error to use them.
(Note that the standard math functions are not defined in the CppAD namespace.)
$codep */
# define CPPAD_USER_MACRO(function) \
inline std::complex function(const std::complex &x) \
{ CppAD::ErrorHandler::Call( \
true , __LINE__ , __FILE__ , \
"std::complex", \
"Error: cannot use " #function " with complex " \
); \
return std::complex(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
/* $$
$end
*/
# define CPPAD_VALID_COMPLEX_CASE(function) \
inline std::complex function(const std::complex &x) \
{ return std::function(x); }
# define CPPAD_INVALID_COMPLEX_CASE(function) \
inline std::complex function(const std::complex &x) \
{ CppAD::ErrorHandler::Call( \
true , __LINE__ , __FILE__ , \
"std::complex", \
"Error: cannot use " #function " with a complex type" \
); \
return std::complex(0); \
}
namespace CppAD {
// CondExpOp ------------------------------------------------------
inline std::complex CondExpOp(
enum CppAD::CompareOp cop ,
const std::complex &left ,
const std::complex &right ,
const std::complex &trueCase ,
const std::complex &falseCase )
{ CppAD::ErrorHandler::Call(
true , __LINE__ , __FILE__ ,
"std::complex CondExpOp(...)",
"Error: cannot use CondExp with a complex type"
);
return std::complex(0);
}
// EqualOpSeq -----------------------------------------------------
inline bool EqualOpSeq(
const std::complex &x ,
const std::complex &y )
{ return x == y;
}
// Identical ------------------------------------------------------
inline bool IdenticalPar(const std::complex &x)
{ return true; }
inline bool IdenticalZero(const std::complex &x)
{ return (x == std::complex(0., 0.) ); }
inline bool IdenticalOne(const std::complex &x)
{ return (x == std::complex(1., 0.) ); }
inline bool IdenticalEqualPar(
const std::complex &x, const std::complex &y)
{ return (x == y); }
// Ordered --------------------------------------------------------
inline bool GreaterThanZero(const std::complex &x)
{ CppAD::ErrorHandler::Call(
true , __LINE__ , __FILE__ ,
"GreaterThanZero(x)",
"Error: cannot use GreaterThanZero with complex"
);
return false;
}
inline bool GreaterThanOrZero(const std::complex &x)
{ CppAD::ErrorHandler::Call(
true , __LINE__ , __FILE__ ,
"GreaterThanOrZero(x)",
"Error: cannot use GreaterThanOrZero with complex"
);
return false;
}
inline bool LessThanZero(const std::complex &x)
{ CppAD::ErrorHandler::Call(
true , __LINE__ , __FILE__ ,
"LessThanZero(x)",
"Error: cannot use LessThanZero with complex"
);
return false;
}
inline bool LessThanOrZero(const std::complex &x)
{ CppAD::ErrorHandler::Call(
true , __LINE__ , __FILE__ ,
"LessThanOrZero(x)",
"Error: cannot use LessThanOrZero with complex"
);
return false;
}
// Integer ------------------------------------------------------
inline int Integer(const std::complex &x)
{ return static_cast( x.real() ); }
// Valid standard math functions --------------------------------
CPPAD_VALID_COMPLEX_CASE(cos)
CPPAD_VALID_COMPLEX_CASE(cosh)
CPPAD_VALID_COMPLEX_CASE(exp)
CPPAD_VALID_COMPLEX_CASE(log)
inline std::complex pow(
const std::complex &x ,
const std::complex &y )
{ return std::pow(x, y); }
CPPAD_VALID_COMPLEX_CASE(sin)
CPPAD_VALID_COMPLEX_CASE(sinh)
CPPAD_VALID_COMPLEX_CASE(sqrt)
// Invalid standrd math functions -------------------------------
CPPAD_INVALID_COMPLEX_CASE(abs)
CPPAD_INVALID_COMPLEX_CASE(acos)
CPPAD_INVALID_COMPLEX_CASE(asin)
CPPAD_INVALID_COMPLEX_CASE(atan)
CPPAD_INVALID_COMPLEX_CASE(erf)
}
# undef CPPAD_INVALID_COMPLEX_CASE
# endif