Planeshift

fpaux.h

Go to the documentation of this file.
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_