CppAD: A C++ Algorithmic Differentiation Package 20110419
|
00001 /* $Id$ */ 00002 # ifndef CPPAD_BASE_COMPLEX_INCLUDED 00003 # define CPPAD_BASE_COMPLEX_INCLUDED 00004 /* -------------------------------------------------------------------------- 00005 CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-08 Bradley M. Bell 00006 00007 CppAD is distributed under multiple licenses. This distribution is under 00008 the terms of the 00009 Common Public License Version 1.0. 00010 00011 A copy of this license is included in the COPYING file of this distribution. 00012 Please visit http://www.coin-or.org/CppAD/ for information on other licenses. 00013 -------------------------------------------------------------------------- */ 00014 /* 00015 $begin base_complex.hpp$$ 00016 $spell 00017 cppad.hpp 00018 sqrt 00019 exp 00020 cos 00021 std 00022 const 00023 CppAD 00024 Op 00025 inline 00026 enum 00027 undef 00028 acos 00029 asin 00030 atan 00031 erf 00032 Cond 00033 namespace 00034 bool 00035 $$ 00036 00037 $index complex, double Base$$ 00038 $index Base, double complex$$ 00039 $index double, complex Base$$ 00040 00041 $section Enable use of AD<Base> where Base is std::complex<double>$$ 00042 00043 $children% 00044 example/complex_poly.cpp% 00045 example/not_complex_ad.cpp 00046 %$$ 00047 00048 $head Example$$ 00049 The file $cref/ComplexPoly.cpp/$$ contains an example use of 00050 $code std::complex<double>$$ type for a CppAD $italic Base$$ type. 00051 It returns true if it succeeds and false otherwise. 00052 00053 $head See Also$$ 00054 The file $cref/not_complex_ad.cpp/$$ contains an example using 00055 complex arithmetic where the function is not complex differentiable. 00056 00057 $head Include File$$ 00058 This file is included before $code <cppad/cppad.hpp>$$ 00059 so it is necessary to define the error handler 00060 in addition to including 00061 $cref/declare.hpp/base_require/declare.hpp/$$ 00062 $codep */ 00063 # include <complex> 00064 # include <cppad/declare.hpp> 00065 # include <cppad/error_handler.hpp> 00066 /* $$ 00067 00068 $head CondExpOp$$ 00069 The conditional expressions $cref/CondExp/$$ 00070 requires ordered comparisons (e.g., $code <$$) 00071 and the C++ standard complex types do not allow for ordered comparisons. 00072 Thus, we make it an error to use the conditional comparisons 00073 with complex types: 00074 $codep */ 00075 namespace CppAD { 00076 inline std::complex<double> CondExpOp( 00077 enum CppAD::CompareOp cop , 00078 const std::complex<double> &left , 00079 const std::complex<double> &right , 00080 const std::complex<double> &trueCase , 00081 const std::complex<double> &falseCase ) 00082 { CppAD::ErrorHandler::Call( 00083 true , __LINE__ , __FILE__ , 00084 "std::complex<float> CondExpOp(...)", 00085 "Error: cannot use CondExp with a complex type" 00086 ); 00087 return std::complex<double>(0); 00088 } 00089 } 00090 /* $$ 00091 00092 $head EqualOpSeq$$ 00093 Complex numbers do not carry operation sequence information. 00094 Thus they are equal in this sense if and only if there values are equal. 00095 $codep */ 00096 namespace CppAD { 00097 inline bool EqualOpSeq( 00098 const std::complex<double> &x , 00099 const std::complex<double> &y ) 00100 { return x == y; 00101 } 00102 } 00103 /* $$ 00104 00105 $head Identical$$ 00106 Complex numbers do not carry operation sequence information. 00107 Thus they are all parameters so the identical functions just check values. 00108 $codep */ 00109 namespace CppAD { 00110 inline bool IdenticalPar(const std::complex<double> &x) 00111 { return true; } 00112 inline bool IdenticalZero(const std::complex<double> &x) 00113 { return (x == std::complex<double>(0., 0.) ); } 00114 inline bool IdenticalOne(const std::complex<double> &x) 00115 { return (x == std::complex<double>(1., 0.) ); } 00116 inline bool IdenticalEqualPar( 00117 const std::complex<double> &x, const std::complex<double> &y) 00118 { return (x == y); } 00119 } 00120 /* $$ 00121 00122 $head Ordered$$ 00123 00124 $codep */ 00125 namespace CppAD { 00126 inline bool GreaterThanZero(const std::complex<double> &x) 00127 { CppAD::ErrorHandler::Call( 00128 true , __LINE__ , __FILE__ , 00129 "GreaterThanZero(x)", 00130 "Error: cannot use GreaterThanZero with complex" 00131 ); 00132 return false; 00133 } 00134 inline bool GreaterThanOrZero(const std::complex<double> &x) 00135 { CppAD::ErrorHandler::Call( 00136 true , __LINE__ , __FILE__ , 00137 "GreaterThanZero(x)", 00138 "Error: cannot use GreaterThanZero with complex" 00139 ); 00140 return false; 00141 } 00142 inline bool LessThanZero(const std::complex<double> &x) 00143 { CppAD::ErrorHandler::Call( 00144 true , __LINE__ , __FILE__ , 00145 "LessThanZero(x)", 00146 "Error: cannot use LessThanZero with complex" 00147 ); 00148 return false; 00149 } 00150 inline bool LessThanOrZero(const std::complex<double> &x) 00151 { CppAD::ErrorHandler::Call( 00152 true , __LINE__ , __FILE__ , 00153 "LessThanZero(x)", 00154 "Error: cannot use LessThanZero with complex" 00155 ); 00156 return false; 00157 } 00158 } 00159 /* $$ 00160 00161 $head Integer$$ 00162 The implementation of this function must agree 00163 with the CppAD user specifications for complex arguments to the 00164 $cref/Integer/Integer/x/Complex Types/$$ function: 00165 $codep */ 00166 namespace CppAD { 00167 inline int Integer(const std::complex<double> &x) 00168 { return static_cast<int>( x.real() ); } 00169 } 00170 /* $$ 00171 00172 $head Standard Functions$$ 00173 00174 $subhead Valid Complex Functions$$ 00175 The following standard math functions, 00176 that are required by $cref/base_require/$$, 00177 are defined by 00178 $code std::complex$$: 00179 $code cos$$, 00180 $code cosh$$, 00181 $code exp$$, 00182 $code log$$, 00183 $code pow$$, 00184 $code sin$$, 00185 $code sinh$$, 00186 $code sqrt$$. 00187 $codep */ 00188 # define CPPAD_USER_MACRO(function) \ 00189 inline std::complex<double> function(const std::complex<double> &x) \ 00190 { return std::function(x); } 00191 00192 namespace CppAD { 00193 CPPAD_USER_MACRO(cos) 00194 CPPAD_USER_MACRO(cosh) 00195 CPPAD_USER_MACRO(exp) 00196 CPPAD_USER_MACRO(log) 00197 inline std::complex<double> pow( 00198 const std::complex<double> &x , 00199 const std::complex<double> &y ) 00200 { return std::pow(x, y); } 00201 CPPAD_USER_MACRO(sin) 00202 CPPAD_USER_MACRO(sinh) 00203 CPPAD_USER_MACRO(sqrt) 00204 } 00205 # undef CPPAD_USER_MACRO 00206 /* $$ 00207 00208 $subhead Invalid Complex Functions$$ 00209 The other standard math functions, 00210 (and $code abs$$) required by $cref/base_require/$$ 00211 are not defined for complex types 00212 (see $cref/abs/abs/Complex Types/$$). 00213 Hence we make it an error to use them. 00214 (Note that the standard math functions are not defined in the CppAD namespace.) 00215 $codep */ 00216 # define CPPAD_USER_MACRO(function) \ 00217 inline std::complex<double> function(const std::complex<double> &x) \ 00218 { CppAD::ErrorHandler::Call( \ 00219 true , __LINE__ , __FILE__ , \ 00220 "std::complex<double>", \ 00221 "Error: cannot use " #function " with complex<double> " \ 00222 ); \ 00223 return std::complex<double>(0); \ 00224 } 00225 00226 namespace CppAD { 00227 CPPAD_USER_MACRO(acos) 00228 CPPAD_USER_MACRO(asin) 00229 CPPAD_USER_MACRO(atan) 00230 } 00231 # undef CPPAD_USER_MACRO 00232 /* $$ 00233 $end 00234 */ 00235 # define CPPAD_VALID_COMPLEX_CASE(function) \ 00236 inline std::complex<float> function(const std::complex<float> &x) \ 00237 { return std::function(x); } 00238 00239 # define CPPAD_INVALID_COMPLEX_CASE(function) \ 00240 inline std::complex<float> function(const std::complex<float> &x) \ 00241 { CppAD::ErrorHandler::Call( \ 00242 true , __LINE__ , __FILE__ , \ 00243 "std::complex<float>", \ 00244 "Error: cannot use " #function " with a complex type" \ 00245 ); \ 00246 return std::complex<float>(0); \ 00247 } 00248 namespace CppAD { 00249 // CondExpOp ------------------------------------------------------ 00250 inline std::complex<float> CondExpOp( 00251 enum CppAD::CompareOp cop , 00252 const std::complex<float> &left , 00253 const std::complex<float> &right , 00254 const std::complex<float> &trueCase , 00255 const std::complex<float> &falseCase ) 00256 { CppAD::ErrorHandler::Call( 00257 true , __LINE__ , __FILE__ , 00258 "std::complex<float> CondExpOp(...)", 00259 "Error: cannot use CondExp with a complex type" 00260 ); 00261 return std::complex<float>(0); 00262 } 00263 // EqualOpSeq ----------------------------------------------------- 00264 inline bool EqualOpSeq( 00265 const std::complex<float> &x , 00266 const std::complex<float> &y ) 00267 { return x == y; 00268 } 00269 // Identical ------------------------------------------------------ 00270 inline bool IdenticalPar(const std::complex<float> &x) 00271 { return true; } 00272 inline bool IdenticalZero(const std::complex<float> &x) 00273 { return (x == std::complex<float>(0., 0.) ); } 00274 inline bool IdenticalOne(const std::complex<float> &x) 00275 { return (x == std::complex<float>(1., 0.) ); } 00276 inline bool IdenticalEqualPar( 00277 const std::complex<float> &x, const std::complex<float> &y) 00278 { return (x == y); } 00279 // Ordered -------------------------------------------------------- 00280 inline bool GreaterThanZero(const std::complex<float> &x) 00281 { CppAD::ErrorHandler::Call( 00282 true , __LINE__ , __FILE__ , 00283 "GreaterThanZero(x)", 00284 "Error: cannot use GreaterThanZero with complex" 00285 ); 00286 return false; 00287 } 00288 inline bool GreaterThanOrZero(const std::complex<float> &x) 00289 { CppAD::ErrorHandler::Call( 00290 true , __LINE__ , __FILE__ , 00291 "GreaterThanOrZero(x)", 00292 "Error: cannot use GreaterThanOrZero with complex" 00293 ); 00294 return false; 00295 } 00296 inline bool LessThanZero(const std::complex<float> &x) 00297 { CppAD::ErrorHandler::Call( 00298 true , __LINE__ , __FILE__ , 00299 "LessThanZero(x)", 00300 "Error: cannot use LessThanZero with complex" 00301 ); 00302 return false; 00303 } 00304 inline bool LessThanOrZero(const std::complex<float> &x) 00305 { CppAD::ErrorHandler::Call( 00306 true , __LINE__ , __FILE__ , 00307 "LessThanOrZero(x)", 00308 "Error: cannot use LessThanOrZero with complex" 00309 ); 00310 return false; 00311 } 00312 // Integer ------------------------------------------------------ 00313 inline int Integer(const std::complex<float> &x) 00314 { return static_cast<int>( x.real() ); } 00315 // Valid standard math functions -------------------------------- 00316 CPPAD_VALID_COMPLEX_CASE(cos) 00317 CPPAD_VALID_COMPLEX_CASE(cosh) 00318 CPPAD_VALID_COMPLEX_CASE(exp) 00319 CPPAD_VALID_COMPLEX_CASE(log) 00320 inline std::complex<float> pow( 00321 const std::complex<float> &x , 00322 const std::complex<float> &y ) 00323 { return std::pow(x, y); } 00324 CPPAD_VALID_COMPLEX_CASE(sin) 00325 CPPAD_VALID_COMPLEX_CASE(sinh) 00326 CPPAD_VALID_COMPLEX_CASE(sqrt) 00327 // Invalid standrd math functions ------------------------------- 00328 CPPAD_INVALID_COMPLEX_CASE(abs) 00329 CPPAD_INVALID_COMPLEX_CASE(acos) 00330 CPPAD_INVALID_COMPLEX_CASE(asin) 00331 CPPAD_INVALID_COMPLEX_CASE(atan) 00332 CPPAD_INVALID_COMPLEX_CASE(erf) 00333 } 00334 # undef CPPAD_INVALID_COMPLEX_CASE 00335 00336 # endif