CppAD: A C++ Algorithmic Differentiation Package
20130918
|
00001 /* $Id$ */ 00002 # ifndef CPPAD_BASE_COMPLEX_INCLUDED 00003 # define CPPAD_BASE_COMPLEX_INCLUDED 00004 /* -------------------------------------------------------------------------- 00005 CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-13 Bradley M. Bell 00006 00007 CppAD is distributed under multiple licenses. This distribution is under 00008 the terms of the 00009 Eclipse 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 # include <limits> 00015 # include <complex> 00016 00017 // needed before one can use CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL 00018 # include <cppad/thread_alloc.hpp> 00019 00020 /* 00021 $begin base_complex.hpp$$ 00022 $spell 00023 eps 00024 abs_geq 00025 Rel 00026 Lt Le Eq Ge Gt 00027 imag 00028 gcc 00029 isnan 00030 cppad.hpp 00031 sqrt 00032 exp 00033 cos 00034 std 00035 const 00036 CppAD 00037 Op 00038 inline 00039 enum 00040 undef 00041 acos 00042 asin 00043 atan 00044 erf 00045 Cond 00046 namespace 00047 bool 00048 $$ 00049 00050 $index complex, double Base$$ 00051 $index Base, double complex$$ 00052 $index double, complex Base$$ 00053 00054 $section Enable use of AD<Base> where Base is std::complex<double>$$ 00055 00056 $children% 00057 example/complex_poly.cpp% 00058 example/not_complex_ad.cpp 00059 %$$ 00060 00061 $head Example$$ 00062 The file $cref complex_poly.cpp$$ contains an example use of 00063 $code std::complex<double>$$ type for a CppAD $icode Base$$ type. 00064 It returns true if it succeeds and false otherwise. 00065 00066 $head See Also$$ 00067 The file $cref not_complex_ad.cpp$$ contains an example using 00068 complex arithmetic where the function is not complex differentiable. 00069 00070 $head Include Order$$ 00071 This file is included before $code <cppad/cppad.hpp>$$ 00072 so it is necessary to define the error handler 00073 in addition to including 00074 $cref/base_require.hpp/base_require/Include Order/$$ 00075 $codep */ 00076 # include <limits> 00077 # include <complex> 00078 # include <cppad/base_require.hpp> 00079 # include <cppad/local/cppad_assert.hpp> 00080 00081 /* $$ 00082 00083 $head CondExpOp$$ 00084 The type $code std::complex<double>$$ does not supports the 00085 $code <$$, $code <=$$, $code ==$$, $code >=$$, and $code >$$ operators; see 00086 $cref/not ordered/base_cond_exp/CondExpTemplate/Not Ordered/$$. 00087 Hence its $code CondExpOp$$ function is defined by 00088 $codep */ 00089 namespace CppAD { 00090 inline std::complex<double> CondExpOp( 00091 enum CppAD::CompareOp cop , 00092 const std::complex<double> &left , 00093 const std::complex<double> &right , 00094 const std::complex<double> &trueCase , 00095 const std::complex<double> &falseCase ) 00096 { CppAD::ErrorHandler::Call( 00097 true , __LINE__ , __FILE__ , 00098 "std::complex<float> CondExpOp(...)", 00099 "Error: cannot use CondExp with a complex type" 00100 ); 00101 return std::complex<double>(0); 00102 } 00103 } 00104 /* $$ 00105 00106 $head CondExpRel$$ 00107 The $cref/CPPAD_COND_EXP_REL/base_cond_exp/CondExpRel/$$ macro invocation 00108 $codep */ 00109 namespace CppAD { 00110 CPPAD_COND_EXP_REL( std::complex<double> ) 00111 } 00112 /* $$ 00113 used $code CondExpOp$$ above to 00114 define $codei%CondExp%Rel%$$ for $code std::complex<double>$$ arguments 00115 and $icode%Rel%$$ equal to 00116 $code Lt$$, $code Le$$, $code Eq$$, $code Ge$$, and $code Gt$$. 00117 00118 $head EqualOpSeq$$ 00119 Complex numbers do not carry operation sequence information. 00120 Thus they are equal in this sense if and only if there values are equal. 00121 $codep */ 00122 namespace CppAD { 00123 inline bool EqualOpSeq( 00124 const std::complex<double> &x , 00125 const std::complex<double> &y ) 00126 { return x == y; 00127 } 00128 } 00129 /* $$ 00130 00131 $head Identical$$ 00132 Complex numbers do not carry operation sequence information. 00133 Thus they are all parameters so the identical functions just check values. 00134 $codep */ 00135 namespace CppAD { 00136 inline bool IdenticalPar(const std::complex<double> &x) 00137 { return true; } 00138 inline bool IdenticalZero(const std::complex<double> &x) 00139 { return (x == std::complex<double>(0., 0.) ); } 00140 inline bool IdenticalOne(const std::complex<double> &x) 00141 { return (x == std::complex<double>(1., 0.) ); } 00142 inline bool IdenticalEqualPar( 00143 const std::complex<double> &x, const std::complex<double> &y) 00144 { return (x == y); } 00145 } 00146 /* $$ 00147 00148 $head Ordered$$ 00149 Complex types do not support comparison operators, 00150 $codep */ 00151 # undef CPPAD_USER_MACRO 00152 # define CPPAD_USER_MACRO(Fun) \ 00153 inline bool Fun(const std::complex<double>& x) \ 00154 { CppAD::ErrorHandler::Call( \ 00155 true , __LINE__ , __FILE__ , \ 00156 #Fun"(x)", \ 00157 "Error: cannot use " #Fun " with x complex<double> " \ 00158 ); \ 00159 return false; \ 00160 } 00161 namespace CppAD { 00162 CPPAD_USER_MACRO(LessThanZero) 00163 CPPAD_USER_MACRO(LessThanOrZero) 00164 CPPAD_USER_MACRO(GreaterThanOrZero) 00165 CPPAD_USER_MACRO(GreaterThanZero) 00166 inline bool abs_geq( 00167 const std::complex<double>& x , 00168 const std::complex<double>& y ) 00169 { return std::abs(x) >= std::abs(y); } 00170 } 00171 /* $$ 00172 00173 $head Integer$$ 00174 The implementation of this function must agree 00175 with the CppAD user specifications for complex arguments to the 00176 $cref/Integer/Integer/x/Complex Types/$$ function: 00177 $codep */ 00178 namespace CppAD { 00179 inline int Integer(const std::complex<double> &x) 00180 { return static_cast<int>( x.real() ); } 00181 } 00182 /* $$ 00183 00184 $head isnan$$ 00185 The gcc 4.1.1 complier defines the function 00186 $codei% 00187 int std::complex<double>::isnan( std::complex<double> %z% ) 00188 %$$ 00189 (which is not specified in the C++ 1998 standard ISO/IEC 14882). 00190 This causes an ambiguity between the function above and the CppAD 00191 $cref/isnan/nan/$$ template function. 00192 We avoid this ambiguity by defining a non-template version of 00193 this function in the CppAD namespace. 00194 $codep */ 00195 namespace CppAD { 00196 inline bool isnan(const std::complex<double>& z) 00197 { return (z != z); 00198 } 00199 } 00200 /* $$ 00201 00202 $head Valid Unary Math$$ 00203 The following macro invocations define the standard unary 00204 math functions that are valid with complex arguments and are 00205 required to use $code AD< std::complex<double> >$$. 00206 $codep */ 00207 namespace CppAD { 00208 CPPAD_STANDARD_MATH_UNARY(std::complex<double>, cos) 00209 CPPAD_STANDARD_MATH_UNARY(std::complex<double>, cosh) 00210 CPPAD_STANDARD_MATH_UNARY(std::complex<double>, exp) 00211 CPPAD_STANDARD_MATH_UNARY(std::complex<double>, log) 00212 CPPAD_STANDARD_MATH_UNARY(std::complex<double>, sin) 00213 CPPAD_STANDARD_MATH_UNARY(std::complex<double>, sinh) 00214 CPPAD_STANDARD_MATH_UNARY(std::complex<double>, sqrt) 00215 } 00216 /* $$ 00217 00218 $head Invalid Unary Math$$ 00219 The following macro definition and invocations define the standard unary 00220 math functions that are invalid with complex arguments and are 00221 required to use $code AD< std::complex<double> >$$. 00222 $codep */ 00223 # undef CPPAD_USER_MACRO 00224 # define CPPAD_USER_MACRO(Fun) \ 00225 inline std::complex<double> Fun(const std::complex<double>& x) \ 00226 { CppAD::ErrorHandler::Call( \ 00227 true , __LINE__ , __FILE__ , \ 00228 #Fun"(x)", \ 00229 "Error: cannot use " #Fun " with x complex<double> " \ 00230 ); \ 00231 return std::complex<double>(0); \ 00232 } 00233 namespace CppAD { 00234 CPPAD_USER_MACRO(abs) 00235 CPPAD_USER_MACRO(acos) 00236 CPPAD_USER_MACRO(asin) 00237 CPPAD_USER_MACRO(atan) 00238 CPPAD_USER_MACRO(sign) 00239 } 00240 /* $$ 00241 00242 $head pow $$ 00243 The following defines a $code CppAD::pow$$ function that 00244 is required to use $code AD< std::complex<double> >$$: 00245 $codep */ 00246 namespace CppAD { 00247 inline std::complex<double> pow( 00248 const std::complex<double> &x , 00249 const std::complex<double> &y ) 00250 { return std::pow(x, y); } 00251 } 00252 /*$$ 00253 00254 $head limits$$ 00255 The following defines the numeric limits functions 00256 $code epsilon$$, $code min$$, and $code max$$ for the type 00257 $code std::complex<double>$$. 00258 It also defines the deprecated $code epsilon$$ function: 00259 $codep */ 00260 namespace CppAD { 00261 template <> 00262 class numeric_limits< std::complex<double> > { 00263 public: 00264 // machine epsilon 00265 static std::complex<double> epsilon(void) 00266 { double eps = std::numeric_limits<double>::epsilon(); 00267 return std::complex<double>(eps, 0.0); 00268 } 00269 // minimum positive normalized value 00270 static std::complex<double> min(void) 00271 { double min = std::numeric_limits<double>::min(); 00272 return std::complex<double>(min, 0.0); 00273 } 00274 // maximum finite value 00275 static std::complex<double> max(void) 00276 { double max = std::numeric_limits<double>::max(); 00277 return std::complex<double>(max, 0.0); 00278 } 00279 }; 00280 // deprecated machine epsilon 00281 template <> 00282 inline std::complex<double> epsilon< std::complex<double> > (void) 00283 { return numeric_limits< std::complex<double> >::epsilon(); } 00284 } 00285 /* $$ 00286 $end 00287 */ 00288 # undef CPPAD_USER_MACRO_ONE 00289 # define CPPAD_USER_MACRO_ONE(Fun) \ 00290 inline bool Fun(const std::complex<float>& x) \ 00291 { CppAD::ErrorHandler::Call( \ 00292 true , __LINE__ , __FILE__ , \ 00293 #Fun"(x)", \ 00294 "Error: cannot use " #Fun " with x complex<float> " \ 00295 ); \ 00296 return false; \ 00297 } 00298 # undef CPPAD_USER_MACRO_TWO 00299 # define CPPAD_USER_MACRO_TWO(Fun) \ 00300 inline std::complex<float> Fun(const std::complex<float>& x) \ 00301 { CppAD::ErrorHandler::Call( \ 00302 true , __LINE__ , __FILE__ , \ 00303 #Fun"(x)", \ 00304 "Error: cannot use " #Fun " with x complex<float> " \ 00305 ); \ 00306 return std::complex<float>(0); \ 00307 } 00308 namespace CppAD { 00309 // CondExpOp ------------------------------------------------------ 00310 inline std::complex<float> CondExpOp( 00311 enum CppAD::CompareOp cop , 00312 const std::complex<float> &left , 00313 const std::complex<float> &right , 00314 const std::complex<float> &trueCase , 00315 const std::complex<float> &falseCase ) 00316 { CppAD::ErrorHandler::Call( 00317 true , __LINE__ , __FILE__ , 00318 "std::complex<float> CondExpOp(...)", 00319 "Error: cannot use CondExp with a complex type" 00320 ); 00321 return std::complex<float>(0); 00322 } 00323 // CondExpRel -------------------------------------------------------- 00324 CPPAD_COND_EXP_REL( std::complex<float> ) 00325 // EqualOpSeq ----------------------------------------------------- 00326 inline bool EqualOpSeq( 00327 const std::complex<float> &x , 00328 const std::complex<float> &y ) 00329 { return x == y; 00330 } 00331 // Identical ------------------------------------------------------ 00332 inline bool IdenticalPar(const std::complex<float> &x) 00333 { return true; } 00334 inline bool IdenticalZero(const std::complex<float> &x) 00335 { return (x == std::complex<float>(0., 0.) ); } 00336 inline bool IdenticalOne(const std::complex<float> &x) 00337 { return (x == std::complex<float>(1., 0.) ); } 00338 inline bool IdenticalEqualPar( 00339 const std::complex<float> &x, const std::complex<float> &y) 00340 { return (x == y); } 00341 // Ordered -------------------------------------------------------- 00342 CPPAD_USER_MACRO_ONE(LessThanZero) 00343 CPPAD_USER_MACRO_ONE(LessThanOrZero) 00344 CPPAD_USER_MACRO_ONE(GreaterThanOrZero) 00345 CPPAD_USER_MACRO_ONE(GreaterThanZero) 00346 inline bool abs_geq( 00347 const std::complex<float>& x , 00348 const std::complex<float>& y ) 00349 { return std::abs(x) >= std::abs(y); } 00350 // Integer ------------------------------------------------------ 00351 inline int Integer(const std::complex<float> &x) 00352 { return static_cast<int>( x.real() ); } 00353 // isnan ------------------------------------------------------------- 00354 inline bool isnan(const std::complex<float>& z) 00355 { return (z != z); 00356 } 00357 // Valid standard math functions -------------------------------- 00358 CPPAD_STANDARD_MATH_UNARY(std::complex<float>, cos) 00359 CPPAD_STANDARD_MATH_UNARY(std::complex<float>, cosh) 00360 CPPAD_STANDARD_MATH_UNARY(std::complex<float>, exp) 00361 CPPAD_STANDARD_MATH_UNARY(std::complex<float>, log) 00362 CPPAD_STANDARD_MATH_UNARY(std::complex<float>, sin) 00363 CPPAD_STANDARD_MATH_UNARY(std::complex<float>, sinh) 00364 CPPAD_STANDARD_MATH_UNARY(std::complex<float>, sqrt) 00365 // Invalid standrd math functions ------------------------------- 00366 CPPAD_USER_MACRO_TWO(abs) 00367 CPPAD_USER_MACRO_TWO(acos) 00368 CPPAD_USER_MACRO_TWO(asin) 00369 CPPAD_USER_MACRO_TWO(atan) 00370 CPPAD_USER_MACRO_TWO(sign) 00371 // The pow function 00372 inline std::complex<float> pow( 00373 const std::complex<float> &x , 00374 const std::complex<float> &y ) 00375 { return std::pow(x, y); } 00376 // numeric_limits ------------------------------------------------- 00377 template <> 00378 class numeric_limits< std::complex<float> > { 00379 public: 00380 /// machine epsilon 00381 static std::complex<float> epsilon(void) 00382 { float eps = std::numeric_limits<float>::epsilon(); 00383 return std::complex<float>(eps, 0.0); 00384 } 00385 /// minimum positive normalized value 00386 static std::complex<float> min(void) 00387 { float min = std::numeric_limits<float>::min(); 00388 return std::complex<float>(min, 0.0); 00389 } 00390 /// maximum finite value 00391 static std::complex<float> max(void) 00392 { float max = std::numeric_limits<float>::max(); 00393 return std::complex<float>(max, 0.0); 00394 } 00395 }; 00396 template <> 00397 inline std::complex<float> epsilon< std::complex<float> >(void) 00398 { return numeric_limits< std::complex<float> >::epsilon(); } 00399 } 00400 00401 // undefine macros only used by this file 00402 # undef CPPAD_USER_MACRO 00403 # undef CPPAD_USER_MACRO_ONE 00404 # undef CPPAD_USER_MACRO_TWO 00405 00406 # endif