Planeshift
|
00001 /***************************************************************************\ 00002 |* Function Parser for C++ v4.5.2 *| 00003 |*-------------------------------------------------------------------------*| 00004 |* Copyright: Juha Nieminen, Joel Yliluoma *| 00005 |* *| 00006 |* This library is distributed under the terms of the *| 00007 |* GNU Lesser General Public License version 3. *| 00008 |* (See lgpl.txt and gpl.txt for the license text.) *| 00009 \***************************************************************************/ 00010 00011 // NOTE: 00012 // This file contains only internal types for the function parser library. 00013 // You don't need to include this file in your code. Include "fparser.hh" 00014 // only. 00015 00016 #ifndef ONCE_FPARSER_AUX_H_ 00017 #define ONCE_FPARSER_AUX_H_ 00018 00019 #include "fptypes.h" 00020 00021 #include <cmath> 00022 00023 #ifdef FP_SUPPORT_MPFR_FLOAT_TYPE 00024 #include "mpfr/MpfrFloat.h" 00025 #endif 00026 00027 #ifdef FP_SUPPORT_GMP_INT_TYPE 00028 #include "mpfr/GmpInt.h" 00029 #endif 00030 00031 #ifdef FP_SUPPORT_COMPLEX_NUMBERS 00032 #include <complex> 00033 #endif 00034 00035 #ifdef ONCE_FPARSER_H_ 00036 namespace FUNCTIONPARSERTYPES 00037 { 00038 template<typename> 00039 struct IsIntType 00040 { 00041 enum { result = false }; 00042 }; 00043 template<> 00044 struct IsIntType<long> 00045 { 00046 enum { result = true }; 00047 }; 00048 #ifdef FP_SUPPORT_GMP_INT_TYPE 00049 template<> 00050 struct IsIntType<GmpInt> 00051 { 00052 enum { result = true }; 00053 }; 00054 #endif 00055 00056 template<typename> 00057 struct IsComplexType 00058 { 00059 enum { result = false }; 00060 }; 00061 #ifdef FP_SUPPORT_COMPLEX_NUMBERS 00062 template<typename T> 00063 struct IsComplexType<std::complex<T> > 00064 { 00065 enum { result = true }; 00066 }; 00067 #endif 00068 00069 00070 //========================================================================== 00071 // Constants 00072 //========================================================================== 00073 template<typename Value_t> 00074 inline Value_t fp_const_pi() // CONSTANT_PI 00075 { 00076 return Value_t(3.1415926535897932384626433832795028841971693993751L); 00077 } 00078 00079 template<typename Value_t> 00080 inline Value_t fp_const_e() // CONSTANT_E 00081 { 00082 return Value_t(2.7182818284590452353602874713526624977572L); 00083 } 00084 template<typename Value_t> 00085 inline Value_t fp_const_einv() // CONSTANT_EI 00086 { 00087 return Value_t(0.367879441171442321595523770161460867445811131L); 00088 } 00089 template<typename Value_t> 00090 inline Value_t fp_const_log2() // CONSTANT_L2, CONSTANT_L2EI 00091 { 00092 return Value_t(0.69314718055994530941723212145817656807550013436025525412L); 00093 } 00094 template<typename Value_t> 00095 inline Value_t fp_const_log10() // CONSTANT_L10, CONSTANT_L10EI 00096 { 00097 return Value_t(2.302585092994045684017991454684364207601101488628772976L); 00098 } 00099 template<typename Value_t> 00100 inline Value_t fp_const_log2inv() // CONSTANT_L2I, CONSTANT_L2E 00101 { 00102 return Value_t(1.442695040888963407359924681001892137426645954L); 00103 } 00104 template<typename Value_t> 00105 inline Value_t fp_const_log10inv() // CONSTANT_L10I, CONSTANT_L10E 00106 { 00107 return Value_t(0.434294481903251827651128918916605082294397L); 00108 } 00109 00110 template<typename Value_t> 00111 inline const Value_t& fp_const_deg_to_rad() // CONSTANT_DR 00112 { 00113 static const Value_t factor = fp_const_pi<Value_t>() / Value_t(180); // to rad from deg 00114 return factor; 00115 } 00116 00117 template<typename Value_t> 00118 inline const Value_t& fp_const_rad_to_deg() // CONSTANT_RD 00119 { 00120 static const Value_t factor = Value_t(180) / fp_const_pi<Value_t>(); // to deg from rad 00121 return factor; 00122 } 00123 00124 #ifdef FP_SUPPORT_MPFR_FLOAT_TYPE 00125 template<> 00126 inline MpfrFloat fp_const_pi<MpfrFloat>() { return MpfrFloat::const_pi(); } 00127 00128 template<> 00129 inline MpfrFloat fp_const_e<MpfrFloat>() { return MpfrFloat::const_e(); } 00130 00131 template<> 00132 inline MpfrFloat fp_const_einv<MpfrFloat>() { return MpfrFloat(1) / MpfrFloat::const_e(); } 00133 00134 template<> 00135 inline MpfrFloat fp_const_log2<MpfrFloat>() { return MpfrFloat::const_log2(); } 00136 00137 /* 00138 template<> 00139 inline MpfrFloat fp_const_log10<MpfrFloat>() { return fp_log(MpfrFloat(10)); } 00140 00141 template<> 00142 inline MpfrFloat fp_const_log2inv<MpfrFloat>() { return MpfrFloat(1) / MpfrFloat::const_log2(); } 00143 00144 template<> 00145 inline MpfrFloat fp_const_log10inv<MpfrFloat>() { return fp_log10(MpfrFloat::const_e()); } 00146 */ 00147 #endif 00148 00149 00150 //========================================================================== 00151 // Generic math functions 00152 //========================================================================== 00153 template<typename Value_t> 00154 inline Value_t fp_abs(const Value_t& x) { return std::fabs(x); } 00155 00156 template<typename Value_t> 00157 inline Value_t fp_acos(const Value_t& x) { return std::acos(x); } 00158 00159 template<typename Value_t> 00160 inline Value_t fp_asin(const Value_t& x) { return std::asin(x); } 00161 00162 template<typename Value_t> 00163 inline Value_t fp_atan(const Value_t& x) { return std::atan(x); } 00164 00165 template<typename Value_t> 00166 inline Value_t fp_atan2(const Value_t& x, const Value_t& y) 00167 { return std::atan2(x, y); } 00168 00169 template<typename Value_t> 00170 inline Value_t fp_ceil(const Value_t& x) { return std::ceil(x); } 00171 00172 template<typename Value_t> 00173 inline Value_t fp_cos(const Value_t& x) { return std::cos(x); } 00174 00175 template<typename Value_t> 00176 inline Value_t fp_cosh(const Value_t& x) { return std::cosh(x); } 00177 00178 template<typename Value_t> 00179 inline Value_t fp_exp(const Value_t& x) { return std::exp(x); } 00180 00181 template<typename Value_t> 00182 inline Value_t fp_floor(const Value_t& x) { return std::floor(x); } 00183 00184 template<typename Value_t> 00185 inline Value_t fp_log(const Value_t& x) { return std::log(x); } 00186 00187 template<typename Value_t> 00188 inline Value_t fp_mod(const Value_t& x, const Value_t& y) 00189 { return std::fmod(x, y); } 00190 00191 template<typename Value_t> 00192 inline Value_t fp_sin(const Value_t& x) { return std::sin(x); } 00193 00194 template<typename Value_t> 00195 inline Value_t fp_sinh(const Value_t& x) { return std::sinh(x); } 00196 00197 template<typename Value_t> 00198 inline Value_t fp_sqrt(const Value_t& x) { return std::sqrt(x); } 00199 00200 template<typename Value_t> 00201 inline Value_t fp_tan(const Value_t& x) { return std::tan(x); } 00202 00203 template<typename Value_t> 00204 inline Value_t fp_tanh(const Value_t& x) { return std::tanh(x); } 00205 00206 #ifdef FP_SUPPORT_CPLUSPLUS11_MATH_FUNCS 00207 template<typename Value_t> 00208 inline Value_t fp_asinh(const Value_t& x) { return std::asinh(x); } 00209 00210 template<typename Value_t> 00211 inline Value_t fp_acosh(const Value_t& x) { return std::acosh(x); } 00212 00213 template<typename Value_t> 00214 inline Value_t fp_atanh(const Value_t& x) { return std::atanh(x); } 00215 #else 00216 template<typename Value_t> 00217 inline Value_t fp_asinh(const Value_t& x) 00218 { return fp_log(x + fp_sqrt(x*x + Value_t(1))); } 00219 00220 template<typename Value_t> 00221 inline Value_t fp_acosh(const Value_t& x) 00222 { return fp_log(x + fp_sqrt(x*x - Value_t(1))); } 00223 00224 template<typename Value_t> 00225 inline Value_t fp_atanh(const Value_t& x) 00226 { 00227 return fp_log( (Value_t(1)+x) / (Value_t(1)-x)) * Value_t(0.5); 00228 // Note: x = +1 causes division by zero 00229 // x = -1 causes log(0) 00230 // Thus, x must not be +-1 00231 } 00232 #endif // FP_SUPPORT_ASINH 00233 00234 #ifdef FP_SUPPORT_CPLUSPLUS11_MATH_FUNCS 00235 template<typename Value_t> 00236 inline Value_t fp_hypot(const Value_t& x, const Value_t& y) 00237 { return std::hypot(x,y); } 00238 00239 template<typename Value_t> 00240 inline std::complex<Value_t> fp_hypot 00241 (const std::complex<Value_t>& x, const std::complex<Value_t>& y) 00242 { return fp_sqrt(x*x + y*y); } 00243 #else 00244 template<typename Value_t> 00245 inline Value_t fp_hypot(const Value_t& x, const Value_t& y) 00246 { return fp_sqrt(x*x + y*y); } 00247 #endif 00248 00249 template<typename Value_t> 00250 inline Value_t fp_pow_base(const Value_t& x, const Value_t& y) 00251 { return std::pow(x, y); } 00252 00253 #ifdef FP_SUPPORT_CPLUSPLUS11_MATH_FUNCS 00254 template<typename Value_t> 00255 inline Value_t fp_log2(const Value_t& x) { return std::log2(x); } 00256 00257 template<typename Value_t> 00258 inline std::complex<Value_t> fp_log2(const std::complex<Value_t>& x) 00259 { 00260 return fp_log(x) * fp_const_log2inv<Value_t>(); 00261 } 00262 #else 00263 template<typename Value_t> 00264 inline Value_t fp_log2(const Value_t& x) 00265 { 00266 return fp_log(x) * fp_const_log2inv<Value_t>(); 00267 } 00268 #endif // FP_SUPPORT_LOG2 00269 00270 template<typename Value_t> 00271 inline Value_t fp_log10(const Value_t& x) 00272 { 00273 return fp_log(x) * fp_const_log10inv<Value_t>(); 00274 } 00275 00276 template<typename Value_t> 00277 inline Value_t fp_trunc(const Value_t& x) 00278 { 00279 return x < Value_t() ? fp_ceil(x) : fp_floor(x); 00280 } 00281 00282 template<typename Value_t> 00283 inline Value_t fp_int(const Value_t& x) 00284 { 00285 return x < Value_t() ? 00286 fp_ceil(x - Value_t(0.5)) : fp_floor(x + Value_t(0.5)); 00287 } 00288 00289 template<typename Value_t> 00290 inline void fp_sinCos(Value_t& sinvalue, Value_t& cosvalue, 00291 const Value_t& param) 00292 { 00293 // Assuming that "cosvalue" and "param" do not 00294 // overlap, but "sinvalue" and "param" may. 00295 cosvalue = fp_cos(param); 00296 sinvalue = fp_sin(param); 00297 } 00298 00299 template<typename Value_t> 00300 inline void fp_sinhCosh(Value_t& sinhvalue, Value_t& coshvalue, 00301 const Value_t& param) 00302 { 00303 const Value_t ex(fp_exp(param)), emx(fp_exp(-param)); 00304 sinhvalue = Value_t(0.5)*(ex-emx); 00305 coshvalue = Value_t(0.5)*(ex+emx); 00306 } 00307 00308 template<typename Value_t> 00309 struct Epsilon 00310 { 00311 static Value_t value; 00312 static Value_t defaultValue() { return 0; } 00313 }; 00314 00315 template<> inline double Epsilon<double>::defaultValue() { return 1E-12; } 00316 template<> inline float Epsilon<float>::defaultValue() { return 1E-5F; } 00317 template<> inline long double Epsilon<long double>::defaultValue() { return 1E-14L; } 00318 00319 template<> inline std::complex<double> 00320 Epsilon<std::complex<double> >::defaultValue() { return 1E-12; } 00321 00322 template<> inline std::complex<float> 00323 Epsilon<std::complex<float> >::defaultValue() { return 1E-5F; } 00324 00325 template<> inline std::complex<long double> 00326 Epsilon<std::complex<long double> >::defaultValue() { return 1E-14L; } 00327 00328 #ifdef FP_SUPPORT_MPFR_FLOAT_TYPE 00329 template<> inline MpfrFloat 00330 Epsilon<MpfrFloat>::defaultValue() { return MpfrFloat::someEpsilon(); } 00331 #endif 00332 00333 template<typename Value_t> Value_t Epsilon<Value_t>::value = 00334 Epsilon<Value_t>::defaultValue(); 00335 00336 00337 #ifdef _GNU_SOURCE 00338 inline void fp_sinCos(double& sin, double& cos, const double& a) 00339 { 00340 sincos(a, &sin, &cos); 00341 } 00342 inline void fp_sinCos(float& sin, float& cos, const float& a) 00343 { 00344 sincosf(a, &sin, &cos); 00345 } 00346 inline void fp_sinCos(long double& sin, long double& cos, 00347 const long double& a) 00348 { 00349 sincosl(a, &sin, &cos); 00350 } 00351 #endif 00352 00353 00354 // ------------------------------------------------------------------------- 00355 // Long int 00356 // ------------------------------------------------------------------------- 00357 inline long fp_abs(const long& x) { return x < 0 ? -x : x; } 00358 inline long fp_acos(const long&) { return 0; } 00359 inline long fp_asin(const long&) { return 0; } 00360 inline long fp_atan(const long&) { return 0; } 00361 inline long fp_atan2(const long&, const long&) { return 0; } 00362 inline long fp_cbrt(const long&) { return 0; } 00363 inline long fp_ceil(const long& x) { return x; } 00364 inline long fp_cos(const long&) { return 0; } 00365 inline long fp_cosh(const long&) { return 0; } 00366 inline long fp_exp(const long&) { return 0; } 00367 inline long fp_exp2(const long&) { return 0; } 00368 inline long fp_floor(const long& x) { return x; } 00369 inline long fp_log(const long&) { return 0; } 00370 inline long fp_log2(const long&) { return 0; } 00371 inline long fp_log10(const long&) { return 0; } 00372 inline long fp_mod(const long& x, const long& y) { return x % y; } 00373 inline long fp_pow(const long&, const long&) { return 0; } 00374 inline long fp_sin(const long&) { return 0; } 00375 inline long fp_sinh(const long&) { return 0; } 00376 inline long fp_sqrt(const long&) { return 1; } 00377 inline long fp_tan(const long&) { return 0; } 00378 inline long fp_tanh(const long&) { return 0; } 00379 inline long fp_asinh(const long&) { return 0; } 00380 inline long fp_acosh(const long&) { return 0; } 00381 inline long fp_atanh(const long&) { return 0; } 00382 inline long fp_pow_base(const long&, const long&) { return 0; } 00383 inline void fp_sinCos(long&, long&, const long&) {} 00384 inline void fp_sinhCosh(long&, long&, const long&) {} 00385 00386 //template<> inline long fp_epsilon<long>() { return 0; } 00387 00388 00389 // ------------------------------------------------------------------------- 00390 // MpfrFloat 00391 // ------------------------------------------------------------------------- 00392 #ifdef FP_SUPPORT_MPFR_FLOAT_TYPE 00393 inline MpfrFloat fp_abs(const MpfrFloat& x) { return MpfrFloat::abs(x); } 00394 inline MpfrFloat fp_acos(const MpfrFloat& x) { return MpfrFloat::acos(x); } 00395 inline MpfrFloat fp_acosh(const MpfrFloat& x) { return MpfrFloat::acosh(x); } 00396 inline MpfrFloat fp_asin(const MpfrFloat& x) { return MpfrFloat::asin(x); } 00397 inline MpfrFloat fp_asinh(const MpfrFloat& x) { return MpfrFloat::asinh(x); } 00398 inline MpfrFloat fp_atan(const MpfrFloat& x) { return MpfrFloat::atan(x); } 00399 inline MpfrFloat fp_atan2(const MpfrFloat& x, const MpfrFloat& y) 00400 { return MpfrFloat::atan2(x, y); } 00401 inline MpfrFloat fp_atanh(const MpfrFloat& x) { return MpfrFloat::atanh(x); } 00402 inline MpfrFloat fp_cbrt(const MpfrFloat& x) { return MpfrFloat::cbrt(x); } 00403 inline MpfrFloat fp_ceil(const MpfrFloat& x) { return MpfrFloat::ceil(x); } 00404 inline MpfrFloat fp_cos(const MpfrFloat& x) { return MpfrFloat::cos(x); } 00405 inline MpfrFloat fp_cosh(const MpfrFloat& x) { return MpfrFloat::cosh(x); } 00406 inline MpfrFloat fp_exp(const MpfrFloat& x) { return MpfrFloat::exp(x); } 00407 inline MpfrFloat fp_exp2(const MpfrFloat& x) { return MpfrFloat::exp2(x); } 00408 inline MpfrFloat fp_floor(const MpfrFloat& x) { return MpfrFloat::floor(x); } 00409 inline MpfrFloat fp_hypot(const MpfrFloat& x, const MpfrFloat& y) 00410 { return MpfrFloat::hypot(x, y); } 00411 inline MpfrFloat fp_int(const MpfrFloat& x) { return MpfrFloat::round(x); } 00412 inline MpfrFloat fp_log(const MpfrFloat& x) { return MpfrFloat::log(x); } 00413 inline MpfrFloat fp_log2(const MpfrFloat& x) { return MpfrFloat::log2(x); } 00414 inline MpfrFloat fp_log10(const MpfrFloat& x) { return MpfrFloat::log10(x); } 00415 inline MpfrFloat fp_mod(const MpfrFloat& x, const MpfrFloat& y) { return x % y; } 00416 inline MpfrFloat fp_sin(const MpfrFloat& x) { return MpfrFloat::sin(x); } 00417 inline MpfrFloat fp_sinh(const MpfrFloat& x) { return MpfrFloat::sinh(x); } 00418 inline MpfrFloat fp_sqrt(const MpfrFloat& x) { return MpfrFloat::sqrt(x); } 00419 inline MpfrFloat fp_tan(const MpfrFloat& x) { return MpfrFloat::tan(x); } 00420 inline MpfrFloat fp_tanh(const MpfrFloat& x) { return MpfrFloat::tanh(x); } 00421 inline MpfrFloat fp_trunc(const MpfrFloat& x) { return MpfrFloat::trunc(x); } 00422 00423 inline MpfrFloat fp_pow(const MpfrFloat& x, const MpfrFloat& y) { return MpfrFloat::pow(x, y); } 00424 inline MpfrFloat fp_pow_base(const MpfrFloat& x, const MpfrFloat& y) { return MpfrFloat::pow(x, y); } 00425 00426 00427 inline void fp_sinCos(MpfrFloat& sin, MpfrFloat& cos, const MpfrFloat& a) 00428 { 00429 MpfrFloat::sincos(a, sin, cos); 00430 } 00431 00432 inline void fp_sinhCosh(MpfrFloat& sinhvalue, MpfrFloat& coshvalue, 00433 const MpfrFloat& param) 00434 { 00435 const MpfrFloat paramCopy = param; 00436 sinhvalue = fp_sinh(paramCopy); 00437 coshvalue = fp_cosh(paramCopy); 00438 } 00439 #endif // FP_SUPPORT_MPFR_FLOAT_TYPE 00440 00441 00442 // ------------------------------------------------------------------------- 00443 // GMP int 00444 // ------------------------------------------------------------------------- 00445 #ifdef FP_SUPPORT_GMP_INT_TYPE 00446 inline GmpInt fp_abs(const GmpInt& x) { return GmpInt::abs(x); } 00447 inline GmpInt fp_acos(const GmpInt&) { return 0; } 00448 inline GmpInt fp_acosh(const GmpInt&) { return 0; } 00449 inline GmpInt fp_asin(const GmpInt&) { return 0; } 00450 inline GmpInt fp_asinh(const GmpInt&) { return 0; } 00451 inline GmpInt fp_atan(const GmpInt&) { return 0; } 00452 inline GmpInt fp_atan2(const GmpInt&, const GmpInt&) { return 0; } 00453 inline GmpInt fp_atanh(const GmpInt&) { return 0; } 00454 inline GmpInt fp_cbrt(const GmpInt&) { return 0; } 00455 inline GmpInt fp_ceil(const GmpInt& x) { return x; } 00456 inline GmpInt fp_cos(const GmpInt&) { return 0; } 00457 inline GmpInt fp_cosh(const GmpInt&) { return 0; } 00458 inline GmpInt fp_exp(const GmpInt&) { return 0; } 00459 inline GmpInt fp_exp2(const GmpInt&) { return 0; } 00460 inline GmpInt fp_floor(const GmpInt& x) { return x; } 00461 inline GmpInt fp_hypot(const GmpInt&, const GmpInt&) { return 0; } 00462 inline GmpInt fp_int(const GmpInt& x) { return x; } 00463 inline GmpInt fp_log(const GmpInt&) { return 0; } 00464 inline GmpInt fp_log2(const GmpInt&) { return 0; } 00465 inline GmpInt fp_log10(const GmpInt&) { return 0; } 00466 inline GmpInt fp_mod(const GmpInt& x, const GmpInt& y) { return x % y; } 00467 inline GmpInt fp_pow(const GmpInt&, const GmpInt&) { return 0; } 00468 inline GmpInt fp_sin(const GmpInt&) { return 0; } 00469 inline GmpInt fp_sinh(const GmpInt&) { return 0; } 00470 inline GmpInt fp_sqrt(const GmpInt&) { return 0; } 00471 inline GmpInt fp_tan(const GmpInt&) { return 0; } 00472 inline GmpInt fp_tanh(const GmpInt&) { return 0; } 00473 inline GmpInt fp_trunc(const GmpInt& x) { return x; } 00474 inline GmpInt fp_pow_base(const GmpInt&, const GmpInt&) { return 0; } 00475 inline void fp_sinCos(GmpInt&, GmpInt&, const GmpInt&) {} 00476 inline void fp_sinhCosh(GmpInt&, GmpInt&, const GmpInt&) {} 00477 #endif // FP_SUPPORT_GMP_INT_TYPE 00478 00479 00480 #ifdef FP_SUPPORT_CPLUSPLUS11_MATH_FUNCS 00481 template<typename Value_t> 00482 inline Value_t fp_cbrt(const Value_t& x) { return std::cbrt(x); } 00483 #else 00484 template<typename Value_t> 00485 inline Value_t fp_cbrt(const Value_t& x) 00486 { 00487 return (x > Value_t() ? fp_exp(fp_log( x) / Value_t(3)) : 00488 x < Value_t() ? -fp_exp(fp_log(-x) / Value_t(3)) : 00489 Value_t()); 00490 } 00491 #endif 00492 00493 // ------------------------------------------------------------------------- 00494 // Synthetic functions and fallbacks for when an optimized 00495 // implementation or a library function is not available 00496 // ------------------------------------------------------------------------- 00497 template<typename Value_t> inline Value_t fp_arg(const Value_t& x); 00498 template<typename Value_t> inline Value_t fp_exp2(const Value_t& x); 00499 template<typename Value_t> inline Value_t fp_int(const Value_t& x); 00500 template<typename Value_t> inline Value_t fp_trunc(const Value_t& x); 00501 template<typename Value_t> 00502 inline void fp_sinCos(Value_t& , Value_t& , const Value_t& ); 00503 template<typename Value_t> 00504 inline void fp_sinhCosh(Value_t& , Value_t& , const Value_t& ); 00505 00506 #ifdef FP_SUPPORT_COMPLEX_NUMBERS 00507 /* NOTE: Complex multiplication of a and b can be done with: 00508 tmp = b.real * (a.real + a.imag) 00509 result.real = tmp - a.imag * (b.real + b.imag) 00510 result.imag = tmp + a.real * (b.imag - b.real) 00511 This has fewer multiplications than the standard 00512 algorithm. Take note, if you support mpfr complex one day. 00513 */ 00514 00515 template<typename T> 00516 struct FP_ProbablyHasFastLibcComplex 00517 { enum { result = false }; }; 00518 /* The generic sqrt() etc. implementations in libstdc++ 00519 * are very plain and non-optimized; however, it contains 00520 * callbacks to libc complex math functions where possible, 00521 * and I suspect that those may actually be well optimized. 00522 * So we use std:: functions when we suspect they may be fast, 00523 * and otherwise we use our own optimized implementations. 00524 */ 00525 #ifdef __GNUC__ 00526 template<> struct FP_ProbablyHasFastLibcComplex<float> 00527 { enum { result = true }; }; 00528 template<> struct FP_ProbablyHasFastLibcComplex<double> 00529 { enum { result = true }; }; 00530 template<> struct FP_ProbablyHasFastLibcComplex<long double> 00531 { enum { result = true }; }; 00532 #endif 00533 00534 template<typename T> 00535 inline const std::complex<T> fp_make_imag(const std::complex<T>& v) 00536 { 00537 return std::complex<T> ( T(), v.real() ); 00538 } 00539 00540 template<typename T> 00541 inline std::complex<T> fp_real(const std::complex<T>& x) 00542 { 00543 return x.real(); 00544 } 00545 template<typename T> 00546 inline std::complex<T> fp_imag(const std::complex<T>& x) 00547 { 00548 return x.imag(); 00549 } 00550 template<typename T> 00551 inline std::complex<T> fp_arg(const std::complex<T>& x) 00552 { 00553 return std::arg(x); 00554 } 00555 template<typename T> 00556 inline std::complex<T> fp_conj(const std::complex<T>& x) 00557 { 00558 return std::conj(x); 00559 } 00560 template<typename T, bool> 00561 inline std::complex<T> fp_polar(const T& x, const T& y) 00562 { 00563 T si, co; fp_sinCos(si, co, y); 00564 return std::complex<T> (x*co, x*si); 00565 } 00566 template<typename T> 00567 inline std::complex<T> fp_polar(const std::complex<T>& x, const std::complex<T>& y) 00568 { 00569 // x * cos(y) + i * x * sin(y) -- arguments are supposed to be REAL numbers 00570 return fp_polar<T,true> (x.real(), y.real()); 00571 //return std::polar(x.real(), y.real()); 00572 //return x * (fp_cos(y) + (std::complex<T>(0,1) * fp_sin(y)); 00573 } 00574 00575 // These provide fallbacks in case there's no library function 00576 template<typename T> 00577 inline std::complex<T> fp_floor(const std::complex<T>& x) 00578 { 00579 return std::complex<T> (fp_floor(x.real()), fp_floor(x.imag())); 00580 } 00581 template<typename T> 00582 inline std::complex<T> fp_trunc(const std::complex<T>& x) 00583 { 00584 return std::complex<T> (fp_trunc(x.real()), fp_trunc(x.imag())); 00585 } 00586 template<typename T> 00587 inline std::complex<T> fp_int(const std::complex<T>& x) 00588 { 00589 return std::complex<T> (fp_int(x.real()), fp_int(x.imag())); 00590 } 00591 template<typename T> 00592 inline std::complex<T> fp_ceil(const std::complex<T>& x) 00593 { 00594 return std::complex<T> (fp_ceil(x.real()), fp_ceil(x.imag())); 00595 } 00596 template<typename T> 00597 inline std::complex<T> fp_abs(const std::complex<T>& x) 00598 { 00599 return std::abs(x); 00600 //T extent = fp_max(fp_abs(x.real()), fp_abs(x.imag())); 00601 //if(extent == T()) return x; 00602 //return extent * fp_hypot(x.real() / extent, x.imag() / extent); 00603 } 00604 template<typename T> 00605 inline std::complex<T> fp_exp(const std::complex<T>& x) 00606 { 00607 if(FP_ProbablyHasFastLibcComplex<T>::result) 00608 return std::exp(x); 00609 return fp_polar<T,true>(fp_exp(x.real()), x.imag()); 00610 } 00611 template<typename T> 00612 inline std::complex<T> fp_log(const std::complex<T>& x) 00613 { 00614 if(FP_ProbablyHasFastLibcComplex<T>::result) 00615 return std::log(x); 00616 // log(abs(x)) + i*arg(x) 00617 // log(Xr^2+Xi^2)*0.5 + i*arg(x) 00618 if(x.imag()==T()) 00619 return std::complex<T>( fp_log(fp_abs(x.real())), 00620 fp_arg(x.real()) ); // Note: Uses real-value fp_arg() here! 00621 return std::complex<T>( 00622 fp_log(std::norm(x)) * T(0.5), 00623 fp_arg(x).real() ); 00624 } 00625 template<typename T> 00626 inline std::complex<T> fp_sqrt(const std::complex<T>& x) 00627 { 00628 if(FP_ProbablyHasFastLibcComplex<T>::result) 00629 return std::sqrt(x); 00630 return fp_polar<T,true> (fp_sqrt(fp_abs(x).real()), 00631 T(0.5)*fp_arg(x).real()); 00632 } 00633 template<typename T> 00634 inline std::complex<T> fp_acos(const std::complex<T>& x) 00635 { 00636 // -i * log(x + i * sqrt(1 - x^2)) 00637 const std::complex<T> i (T(), T(1)); 00638 return -i * fp_log(x + i * fp_sqrt(T(1) - x*x)); 00639 // Note: Real version of acos() cannot handle |x| > 1, 00640 // because it would cause sqrt(negative value). 00641 } 00642 template<typename T> 00643 inline std::complex<T> fp_asin(const std::complex<T>& x) 00644 { 00645 // -i * log(i*x + sqrt(1 - x^2)) 00646 const std::complex<T> i (T(), T(1)); 00647 return -i * fp_log(i*x + fp_sqrt(T(1) - x*x)); 00648 // Note: Real version of asin() cannot handle |x| > 1, 00649 // because it would cause sqrt(negative value). 00650 } 00651 template<typename T> 00652 inline std::complex<T> fp_atan(const std::complex<T>& x) 00653 { 00654 // 0.5i * (log(1-i*x) - log(1+i*x)) 00655 // -0.5i * log( (1+i*x) / (1-i*x) ) 00656 const std::complex<T> i (T(), T(1)); 00657 return (T(-0.5)*i) * fp_log( (T(1)+i*x) / (T(1)-i*x) ); 00658 // Note: x = -1i causes division by zero 00659 // x = +1i causes log(0) 00660 // Thus, x must not be +-1i 00661 } 00662 template<typename T> 00663 inline std::complex<T> fp_cos(const std::complex<T>& x) 00664 { 00665 return std::cos(x); 00666 // // (exp(i*x) + exp(-i*x)) / (2) 00667 // //const std::complex<T> i (T(), T(1)); 00668 // //return (fp_exp(i*x) + fp_exp(-i*x)) * T(0.5); 00669 // // Also: cos(Xr)*cosh(Xi) - i*sin(Xr)*sinh(Xi) 00670 // return std::complex<T> ( 00671 // fp_cos(x.real())*fp_cosh(x.imag()), 00672 // -fp_sin(x.real())*fp_sinh(x.imag())); 00673 } 00674 template<typename T> 00675 inline std::complex<T> fp_sin(const std::complex<T>& x) 00676 { 00677 return std::sin(x); 00678 // // (exp(i*x) - exp(-i*x)) / (2i) 00679 // //const std::complex<T> i (T(), T(1)); 00680 // //return (fp_exp(i*x) - fp_exp(-i*x)) * (T(-0.5)*i); 00681 // // Also: sin(Xr)*cosh(Xi) + cos(Xr)*sinh(Xi) 00682 // return std::complex<T> ( 00683 // fp_sin(x.real())*fp_cosh(x.imag()), 00684 // fp_cos(x.real())*fp_sinh(x.imag())); 00685 } 00686 template<typename T> 00687 inline void fp_sinCos( 00688 std::complex<T>& sinvalue, 00689 std::complex<T>& cosvalue, 00690 const std::complex<T>& x) 00691 { 00692 //const std::complex<T> i (T(), T(1)), expix(fp_exp(i*x)), expmix(fp_exp((-i)*x)); 00693 //cosvalue = (expix + expmix) * T(0.5); 00694 //sinvalue = (expix - expmix) * (i*T(-0.5)); 00695 // The above expands to the following: 00696 T srx, crx; fp_sinCos(srx, crx, x.real()); 00697 T six, cix; fp_sinhCosh(six, cix, x.imag()); 00698 sinvalue = std::complex<T>(srx*cix, crx*six); 00699 cosvalue = std::complex<T>(crx*cix, -srx*six); 00700 } 00701 template<typename T> 00702 inline void fp_sinhCosh( 00703 std::complex<T>& sinhvalue, 00704 std::complex<T>& coshvalue, 00705 const std::complex<T>& x) 00706 { 00707 T srx, crx; fp_sinhCosh(srx, crx, x.real()); 00708 T six, cix; fp_sinCos(six, cix, x.imag()); 00709 sinhvalue = std::complex<T>(srx*cix, crx*six); 00710 coshvalue = std::complex<T>(crx*cix, srx*six); 00711 } 00712 template<typename T> 00713 inline std::complex<T> fp_tan(const std::complex<T>& x) 00714 { 00715 return std::tan(x); 00716 //std::complex<T> si, co; 00717 //fp_sinCos(si, co, x); 00718 //return si/co; 00719 // // (i-i*exp(2i*x)) / (exp(2i*x)+1) 00720 // const std::complex<T> i (T(), T(1)), exp2ix=fp_exp((2*i)*x); 00721 // return (i-i*exp2ix) / (exp2ix+T(1)); 00722 // // Also: sin(x)/cos(y) 00723 // // return fp_sin(x)/fp_cos(x); 00724 } 00725 template<typename T> 00726 inline std::complex<T> fp_cosh(const std::complex<T>& x) 00727 { 00728 return std::cosh(x); 00729 // // (exp(x) + exp(-x)) * 0.5 00730 // // Also: cosh(Xr)*cos(Xi) + i*sinh(Xr)*sin(Xi) 00731 // return std::complex<T> ( 00732 // fp_cosh(x.real())*fp_cos(x.imag()), 00733 // fp_sinh(x.real())*fp_sin(x.imag())); 00734 } 00735 template<typename T> 00736 inline std::complex<T> fp_sinh(const std::complex<T>& x) 00737 { 00738 return std::sinh(x); 00739 // // (exp(x) - exp(-x)) * 0.5 00740 // // Also: sinh(Xr)*cos(Xi) + i*cosh(Xr)*sin(Xi) 00741 // return std::complex<T> ( 00742 // fp_sinh(x.real())*fp_cos(x.imag()), 00743 // fp_cosh(x.real())*fp_sin(x.imag())); 00744 } 00745 template<typename T> 00746 inline std::complex<T> fp_tanh(const std::complex<T>& x) 00747 { 00748 return std::tanh(x); 00749 //std::complex<T> si, co; 00750 //fp_sinhCosh(si, co, x); 00751 //return si/co; 00752 // // (exp(2*x)-1) / (exp(2*x)+1) 00753 // // Also: sinh(x)/tanh(x) 00754 // const std::complex<T> exp2x=fp_exp(x+x); 00755 // return (exp2x-T(1)) / (exp2x+T(1)); 00756 } 00757 00758 #ifdef FP_SUPPORT_CPLUSPLUS11_MATH_FUNCS 00759 template<typename T> 00760 inline std::complex<T> fp_acosh(const std::complex<T>& x) 00761 { return fp_log(x + fp_sqrt(x*x - std::complex<T>(1))); } 00762 template<typename T> 00763 inline std::complex<T> fp_asinh(const std::complex<T>& x) 00764 { return fp_log(x + fp_sqrt(x*x + std::complex<T>(1))); } 00765 template<typename T> 00766 inline std::complex<T> fp_atanh(const std::complex<T>& x) 00767 { return fp_log( (std::complex<T>(1)+x) / (std::complex<T>(1)-x)) 00768 * std::complex<T>(0.5); } 00769 #endif 00770 template<typename T> 00771 inline std::complex<T> fp_pow(const std::complex<T>& x, const std::complex<T>& y) 00772 { 00773 // return std::pow(x,y); 00774 00775 // With complex numbers, pow(x,y) can be solved with 00776 // the general formula: exp(y*log(x)). It handles 00777 // all special cases gracefully. 00778 // It expands to the following: 00779 // A) 00780 // t1 = log(x) 00781 // t2 = y * t1 00782 // res = exp(t2) 00783 // B) 00784 // t1.r = log(x.r * x.r + x.i * x.i) * 0.5 \ fp_log() 00785 // t1.i = atan2(x.i, x.r) / 00786 // t2.r = y.r*t1.r - y.i*t1.i \ multiplication 00787 // t2.i = y.r*t1.i + y.i*t1.r / 00788 // rho = exp(t2.r) \ fp_exp() 00789 // theta = t2.i / 00790 // res.r = rho * cos(theta) \ fp_polar(), called from 00791 // res.i = rho * sin(theta) / fp_exp(). Uses sincos(). 00792 // Aside from the common "norm" calculation in atan2() 00793 // and in the log parameter, both of which are part of fp_log(), 00794 // there does not seem to be any incentive to break this 00795 // function down further; it would not help optimizing it. 00796 // However, we do handle the following special cases: 00797 // 00798 // When x is real (positive or negative): 00799 // t1.r = log(abs(x.r)) 00800 // t1.i = x.r<0 ? -pi : 0 00801 // When y is real: 00802 // t2.r = y.r * t1.r 00803 // t2.i = y.r * t1.i 00804 const std::complex<T> t = 00805 (x.imag() != T()) 00806 ? fp_log(x) 00807 : std::complex<T> (fp_log(fp_abs(x.real())), 00808 fp_arg(x.real())); // Note: Uses real-value fp_arg() here! 00809 return y.imag() != T() 00810 ? fp_exp(y * t) 00811 : fp_polar<T,true> (fp_exp(y.real()*t.real()), y.real()*t.imag()); 00812 } 00813 template<typename T> 00814 inline std::complex<T> fp_cbrt(const std::complex<T>& x) 00815 { 00816 // For real numbers, prefer giving a real solution 00817 // rather than a complex solution. 00818 // For example, cbrt(-3) has the following three solutions: 00819 // A) 0.7211247966535 + 1.2490247864016i 00820 // B) 0.7211247966535 - 1.2490247864016i 00821 // C) -1.442249593307 00822 // exp(log(x)/3) gives A, but we prefer to give C. 00823 if(x.imag() == T()) return fp_cbrt(x.real()); 00824 const std::complex<T> t(fp_log(x)); 00825 return fp_polar<T,true> (fp_exp(t.real() / T(3)), t.imag() / T(3)); 00826 } 00827 00828 template<typename T> 00829 inline std::complex<T> fp_exp2(const std::complex<T>& x) 00830 { 00831 // pow(2, x) 00832 // polar(2^Xr, Xi*log(2)) 00833 return fp_polar<T,true> (fp_exp2(x.real()), x.imag()*fp_const_log2<T>()); 00834 } 00835 template<typename T> 00836 inline std::complex<T> fp_mod(const std::complex<T>& x, const std::complex<T>& y) 00837 { 00838 // Modulo function is probably not defined for complex numbers. 00839 // But we do our best to calculate it the same way as it is done 00840 // with real numbers, so that at least it is in some way "consistent". 00841 if(y.imag() == 0) return fp_mod(x.real(), y.real()); // optimization 00842 std::complex<T> n = fp_trunc(x / y); 00843 return x - n * y; 00844 } 00845 00846 /* libstdc++ already defines a streaming operator for complex values, 00847 * but we redefine our own that it is compatible with the input 00848 * accepted by fparser. I.e. instead of (5,3) we now get (5+3i), 00849 * and instead of (-4,0) we now get -4. 00850 */ 00851 template<typename T> 00852 inline std::ostream& operator<<(std::ostream& os, const std::complex<T>& value) 00853 { 00854 if(value.imag() == T()) return os << value.real(); 00855 if(value.real() == T()) return os << value.imag() << 'i'; 00856 if(value.imag() < T()) 00857 return os << '(' << value.real() << "-" << -value.imag() << "i)"; 00858 else 00859 return os << '(' << value.real() << "+" << value.imag() << "i)"; 00860 } 00861 00862 /* Less-than or greater-than operators are not technically defined 00863 * for Complex types. However, in fparser and its tool set, these 00864 * operators are widely required to be present. 00865 * Our implementation here is based on converting the complex number 00866 * into a scalar and the doing a scalar comparison on the value. 00867 * The means by which the number is changed into a scalar is based 00868 * on the following principles: 00869 * - Does not introduce unjustified amounts of extra inaccuracy 00870 * - Is transparent to purely real values 00871 * (this disqualifies something like x.real() + x.imag()) 00872 * - Does not ignore the imaginary value completely 00873 * (this may be relevant especially in testbed) 00874 * - Is not so complicated that it would slow down a great deal 00875 * 00876 * Basically our formula here is the same as std::abs(), 00877 * except that it keeps the sign of the original real number, 00878 * and it does not do a sqrt() calculation that is not really 00879 * needed because we are only interested in the relative magnitudes. 00880 * 00881 * Equality and nonequality operators must not need to be overloaded. 00882 * They are already implemented in standard, and we must 00883 * not introduce flawed equality assumptions. 00884 */ 00885 template<typename T> 00886 inline T fp_complexScalarize(const std::complex<T>& x) 00887 { 00888 T res(std::norm(x)); 00889 if(x.real() < T()) res = -res; 00890 return res; 00891 } 00892 template<typename T> 00893 inline T fp_realComplexScalarize(const T& x) 00894 { 00895 T res(x*x); 00896 if(x < T()) res = -res; 00897 return res; 00898 } 00899 // { return x.real() * (T(1.0) + fp_abs(x.imag())); } 00900 #define d(op) \ 00901 template<typename T> \ 00902 inline bool operator op (const std::complex<T>& x, T y) \ 00903 { return fp_complexScalarize(x) op fp_realComplexScalarize(y); } \ 00904 template<typename T> \ 00905 inline bool operator op (const std::complex<T>& x, const std::complex<T>& y) \ 00906 { return fp_complexScalarize(x) op \ 00907 fp_complexScalarize(y); } \ 00908 template<typename T> \ 00909 inline bool operator op (T x, const std::complex<T>& y) \ 00910 { return fp_realComplexScalarize(x) op fp_complexScalarize(y); } 00911 d( < ) d( <= ) d( > ) d( >= ) 00912 #undef d 00913 #endif 00914 00915 template<typename Value_t> 00916 inline Value_t fp_real(const Value_t& x) { return x; } 00917 template<typename Value_t> 00918 inline Value_t fp_imag(const Value_t& ) { return Value_t(); } 00919 template<typename Value_t> 00920 inline Value_t fp_arg(const Value_t& x) 00921 { return x < Value_t() ? -fp_const_pi<Value_t>() : Value_t(); } 00922 template<typename Value_t> 00923 inline Value_t fp_conj(const Value_t& x) { return x; } 00924 template<typename Value_t> 00925 inline Value_t fp_polar(const Value_t& x, const Value_t& y) 00926 { return x * fp_cos(y); } // This is of course a meaningless function. 00927 00928 template<typename Value_t> 00929 inline std::complex<Value_t> fp_atan2(const std::complex<Value_t>& y, 00930 const std::complex<Value_t>& x) 00931 { 00932 if(y == Value_t()) return fp_arg(x); 00933 if(x == Value_t()) return fp_const_pi<Value_t>() * Value_t(-0.5); 00934 // 2*atan(y / (sqrt(x^2+y^2) + x) ) 00935 // 2*atan( (sqrt(x^2+y^2) - x) / y) 00936 std::complex<Value_t> res( fp_atan(y / (fp_hypot(x,y) + x)) ); 00937 return res+res; 00938 } 00939 00940 // ------------------------------------------------------------------------- 00941 // Comparison 00942 // ------------------------------------------------------------------------- 00943 template<typename Value_t> 00944 inline bool fp_equal(const Value_t& x, const Value_t& y) 00945 { return IsIntType<Value_t>::result 00946 ? (x == y) 00947 : (fp_abs(x - y) <= Epsilon<Value_t>::value); } 00948 00949 template<typename Value_t> 00950 inline bool fp_nequal(const Value_t& x, const Value_t& y) 00951 { return IsIntType<Value_t>::result 00952 ? (x != y) 00953 : (fp_abs(x - y) > Epsilon<Value_t>::value); } 00954 00955 template<typename Value_t> 00956 inline bool fp_less(const Value_t& x, const Value_t& y) 00957 { return IsIntType<Value_t>::result 00958 ? (x < y) 00959 : (x < y - Epsilon<Value_t>::value); } 00960 00961 template<typename Value_t> 00962 inline bool fp_lessOrEq(const Value_t& x, const Value_t& y) 00963 { return IsIntType<Value_t>::result 00964 ? (x <= y) 00965 : (x <= y + Epsilon<Value_t>::value); } 00966 00967 00968 template<typename Value_t> 00969 inline bool fp_greater(const Value_t& x, const Value_t& y) 00970 { return fp_less(y, x); } 00971 00972 template<typename Value_t> 00973 inline bool fp_greaterOrEq(const Value_t& x, const Value_t& y) 00974 { return fp_lessOrEq(y, x); } 00975 00976 template<typename Value_t> 00977 inline bool fp_truth(const Value_t& d) 00978 { 00979 return IsIntType<Value_t>::result 00980 ? d != Value_t() 00981 : fp_abs(d) >= Value_t(0.5); 00982 } 00983 00984 template<typename Value_t> 00985 inline bool fp_absTruth(const Value_t& abs_d) 00986 { 00987 return IsIntType<Value_t>::result 00988 ? abs_d > Value_t() 00989 : abs_d >= Value_t(0.5); 00990 } 00991 00992 template<typename Value_t> 00993 inline const Value_t& fp_min(const Value_t& d1, const Value_t& d2) 00994 { return d1<d2 ? d1 : d2; } 00995 00996 template<typename Value_t> 00997 inline const Value_t& fp_max(const Value_t& d1, const Value_t& d2) 00998 { return d1>d2 ? d1 : d2; } 00999 01000 template<typename Value_t> 01001 inline const Value_t fp_not(const Value_t& b) 01002 { return Value_t(!fp_truth(b)); } 01003 01004 template<typename Value_t> 01005 inline const Value_t fp_notNot(const Value_t& b) 01006 { return Value_t(fp_truth(b)); } 01007 01008 template<typename Value_t> 01009 inline const Value_t fp_absNot(const Value_t& b) 01010 { return Value_t(!fp_absTruth(b)); } 01011 01012 template<typename Value_t> 01013 inline const Value_t fp_absNotNot(const Value_t& b) 01014 { return Value_t(fp_absTruth(b)); } 01015 01016 template<typename Value_t> 01017 inline const Value_t fp_and(const Value_t& a, const Value_t& b) 01018 { return Value_t(fp_truth(a) && fp_truth(b)); } 01019 01020 template<typename Value_t> 01021 inline const Value_t fp_or(const Value_t& a, const Value_t& b) 01022 { return Value_t(fp_truth(a) || fp_truth(b)); } 01023 01024 template<typename Value_t> 01025 inline const Value_t fp_absAnd(const Value_t& a, const Value_t& b) 01026 { return Value_t(fp_absTruth(a) && fp_absTruth(b)); } 01027 01028 template<typename Value_t> 01029 inline const Value_t fp_absOr(const Value_t& a, const Value_t& b) 01030 { return Value_t(fp_absTruth(a) || fp_absTruth(b)); } 01031 01032 template<typename Value_t> 01033 inline const Value_t fp_make_imag(const Value_t& ) // Imaginary 1. In real mode, always zero. 01034 { 01035 return Value_t(); 01036 } 01037 01039 /* Opcode analysis functions are used by fp_opcode_add.inc */ 01040 /* Moved here from fparser.cc because fp_opcode_add.inc 01041 * is also now included by fpoptimizer.cc 01042 */ 01043 bool IsLogicalOpcode(unsigned op); 01044 bool IsComparisonOpcode(unsigned op); 01045 unsigned OppositeComparisonOpcode(unsigned op); 01046 bool IsNeverNegativeValueOpcode(unsigned op); 01047 bool IsAlwaysIntegerOpcode(unsigned op); 01048 bool IsUnaryOpcode(unsigned op); 01049 bool IsBinaryOpcode(unsigned op); 01050 bool IsVarOpcode(unsigned op); 01051 bool IsCommutativeOrParamSwappableBinaryOpcode(unsigned op); 01052 unsigned GetParamSwappedBinaryOpcode(unsigned op); 01053 01054 template<bool ComplexType> 01055 bool HasInvalidRangesOpcode(unsigned op); 01056 01057 template<typename Value_t> 01058 inline Value_t DegreesToRadians(const Value_t& degrees) 01059 { 01060 return degrees * fp_const_deg_to_rad<Value_t>(); 01061 } 01062 01063 template<typename Value_t> 01064 inline Value_t RadiansToDegrees(const Value_t& radians) 01065 { 01066 return radians * fp_const_rad_to_deg<Value_t>(); 01067 } 01068 01069 template<typename Value_t> 01070 inline long makeLongInteger(const Value_t& value) 01071 { 01072 return (long) fp_int(value); 01073 } 01074 01075 #ifdef FP_SUPPORT_COMPLEX_NUMBERS 01076 template<typename T> 01077 inline long makeLongInteger(const std::complex<T>& value) 01078 { 01079 return (long) fp_int( std::abs(value) ); 01080 } 01081 #endif 01082 01083 // Is value an integer that fits in "long" datatype? 01084 template<typename Value_t> 01085 inline bool isLongInteger(const Value_t& value) 01086 { 01087 return value == Value_t( makeLongInteger(value) ); 01088 } 01089 01090 template<typename Value_t> 01091 inline bool isOddInteger(const Value_t& value) 01092 { 01093 const Value_t halfValue = (value + Value_t(1)) * Value_t(0.5); 01094 return fp_equal(halfValue, fp_floor(halfValue)); 01095 } 01096 01097 template<typename Value_t> 01098 inline bool isEvenInteger(const Value_t& value) 01099 { 01100 const Value_t halfValue = value * Value_t(0.5); 01101 return fp_equal(halfValue, fp_floor(halfValue)); 01102 } 01103 01104 template<typename Value_t> 01105 inline bool isInteger(const Value_t& value) 01106 { 01107 return fp_equal(value, fp_floor(value)); 01108 } 01109 01110 #ifdef FP_SUPPORT_LONG_INT_TYPE 01111 template<> 01112 inline bool isEvenInteger(const long& value) 01113 { 01114 return value%2 == 0; 01115 } 01116 01117 template<> 01118 inline bool isInteger(const long&) { return true; } 01119 01120 template<> 01121 inline bool isLongInteger(const long&) { return true; } 01122 01123 template<> 01124 inline long makeLongInteger(const long& value) 01125 { 01126 return value; 01127 } 01128 #endif 01129 01130 #ifdef FP_SUPPORT_MPFR_FLOAT_TYPE 01131 template<> 01132 inline bool isInteger(const MpfrFloat& value) { return value.isInteger(); } 01133 01134 template<> 01135 inline bool isEvenInteger(const MpfrFloat& value) 01136 { 01137 return isInteger(value) && value%2 == 0; 01138 } 01139 01140 template<> 01141 inline long makeLongInteger(const MpfrFloat& value) 01142 { 01143 return (long) value.toInt(); 01144 } 01145 #endif 01146 01147 #ifdef FP_SUPPORT_GMP_INT_TYPE 01148 template<> 01149 inline bool isEvenInteger(const GmpInt& value) 01150 { 01151 return value%2 == 0; 01152 } 01153 01154 template<> 01155 inline bool isInteger(const GmpInt&) { return true; } 01156 01157 template<> 01158 inline long makeLongInteger(const GmpInt& value) 01159 { 01160 return (long) value.toInt(); 01161 } 01162 #endif 01163 01164 #ifdef FP_SUPPORT_LONG_INT_TYPE 01165 template<> 01166 inline bool isOddInteger(const long& value) 01167 { 01168 return value%2 != 0; 01169 } 01170 #endif 01171 01172 #ifdef FP_SUPPORT_MPFR_FLOAT_TYPE 01173 template<> 01174 inline bool isOddInteger(const MpfrFloat& value) 01175 { 01176 return value.isInteger() && value%2 != 0; 01177 } 01178 #endif 01179 01180 #ifdef FP_SUPPORT_GMP_INT_TYPE 01181 template<> 01182 inline bool isOddInteger(const GmpInt& value) 01183 { 01184 return value%2 != 0; 01185 } 01186 #endif 01187 01188 01189 // ------------------------------------------------------------------------- 01190 // fp_pow 01191 // ------------------------------------------------------------------------- 01192 // Commented versions in fparser.cc 01193 template<typename Value_t> 01194 inline Value_t fp_pow_with_exp_log(const Value_t& x, const Value_t& y) 01195 { 01196 return fp_exp(fp_log(x) * y); 01197 } 01198 01199 template<typename Value_t> 01200 inline Value_t fp_powi(Value_t x, unsigned long y) 01201 { 01202 Value_t result(1); 01203 while(y != 0) 01204 { 01205 if(y & 1) { result *= x; y -= 1; } 01206 else { x *= x; y /= 2; } 01207 } 01208 return result; 01209 } 01210 01211 template<typename Value_t> 01212 Value_t fp_pow(const Value_t& x, const Value_t& y) 01213 { 01214 if(x == Value_t(1)) return Value_t(1); 01215 if(isLongInteger(y)) 01216 { 01217 if(y >= Value_t(0)) 01218 return fp_powi(x, makeLongInteger(y)); 01219 else 01220 return Value_t(1) / fp_powi(x, -makeLongInteger(y)); 01221 } 01222 if(y >= Value_t(0)) 01223 { 01224 if(x > Value_t(0)) return fp_pow_with_exp_log(x, y); 01225 if(x == Value_t(0)) return Value_t(0); 01226 if(!isInteger(y*Value_t(16))) 01227 return -fp_pow_with_exp_log(-x, y); 01228 } 01229 else 01230 { 01231 if(x > Value_t(0)) return fp_pow_with_exp_log(Value_t(1) / x, -y); 01232 if(x < Value_t(0)) 01233 { 01234 if(!isInteger(y*Value_t(-16))) 01235 return -fp_pow_with_exp_log(Value_t(-1) / x, -y); 01236 } 01237 } 01238 return fp_pow_base(x, y); 01239 } 01240 01241 template<typename Value_t> 01242 inline Value_t fp_exp2(const Value_t& x) 01243 { 01244 return fp_pow(Value_t(2), x); 01245 } 01246 } // namespace FUNCTIONPARSERTYPES 01247 01248 #endif // ONCE_FPARSER_H_ 01249 #endif // ONCE_FPARSER_AUX_H_