Planeshift
fpaux.h
Go to the documentation of this file.
1 /***************************************************************************\
2 |* Function Parser for C++ v4.5.2 *|
3 |*-------------------------------------------------------------------------*|
4 |* Copyright: Juha Nieminen, Joel Yliluoma *|
5 |* *|
6 |* This library is distributed under the terms of the *|
7 |* GNU Lesser General Public License version 3. *|
8 |* (See lgpl.txt and gpl.txt for the license text.) *|
9 \***************************************************************************/
10 
11 // NOTE:
12 // This file contains only internal types for the function parser library.
13 // You don't need to include this file in your code. Include "fparser.hh"
14 // only.
15 
16 #ifndef ONCE_FPARSER_AUX_H_
17 #define ONCE_FPARSER_AUX_H_
18 
19 #include "fptypes.h"
20 
21 #include <cmath>
22 
23 #ifdef FP_SUPPORT_MPFR_FLOAT_TYPE
24 #include "mpfr/MpfrFloat.h"
25 #endif
26 
27 #ifdef FP_SUPPORT_GMP_INT_TYPE
28 #include "mpfr/GmpInt.h"
29 #endif
30 
31 #ifdef FP_SUPPORT_COMPLEX_NUMBERS
32 #include <complex>
33 #endif
34 
35 #ifdef ONCE_FPARSER_H_
36 namespace FUNCTIONPARSERTYPES
37 {
38  template<typename>
39  struct IsIntType
40  {
41  enum { result = false };
42  };
43  template<>
44  struct IsIntType<long>
45  {
46  enum { result = true };
47  };
48 #ifdef FP_SUPPORT_GMP_INT_TYPE
49  template<>
50  struct IsIntType<GmpInt>
51  {
52  enum { result = true };
53  };
54 #endif
55 
56  template<typename>
57  struct IsComplexType
58  {
59  enum { result = false };
60  };
61 #ifdef FP_SUPPORT_COMPLEX_NUMBERS
62  template<typename T>
63  struct IsComplexType<std::complex<T> >
64  {
65  enum { result = true };
66  };
67 #endif
68 
69 
70 //==========================================================================
71 // Constants
72 //==========================================================================
73  template<typename Value_t>
74  inline Value_t fp_const_pi() // CONSTANT_PI
75  {
76  return Value_t(3.1415926535897932384626433832795028841971693993751L);
77  }
78 
79  template<typename Value_t>
80  inline Value_t fp_const_e() // CONSTANT_E
81  {
82  return Value_t(2.7182818284590452353602874713526624977572L);
83  }
84  template<typename Value_t>
85  inline Value_t fp_const_einv() // CONSTANT_EI
86  {
87  return Value_t(0.367879441171442321595523770161460867445811131L);
88  }
89  template<typename Value_t>
90  inline Value_t fp_const_log2() // CONSTANT_L2, CONSTANT_L2EI
91  {
92  return Value_t(0.69314718055994530941723212145817656807550013436025525412L);
93  }
94  template<typename Value_t>
95  inline Value_t fp_const_log10() // CONSTANT_L10, CONSTANT_L10EI
96  {
97  return Value_t(2.302585092994045684017991454684364207601101488628772976L);
98  }
99  template<typename Value_t>
100  inline Value_t fp_const_log2inv() // CONSTANT_L2I, CONSTANT_L2E
101  {
102  return Value_t(1.442695040888963407359924681001892137426645954L);
103  }
104  template<typename Value_t>
105  inline Value_t fp_const_log10inv() // CONSTANT_L10I, CONSTANT_L10E
106  {
107  return Value_t(0.434294481903251827651128918916605082294397L);
108  }
109 
110  template<typename Value_t>
111  inline const Value_t& fp_const_deg_to_rad() // CONSTANT_DR
112  {
113  static const Value_t factor = fp_const_pi<Value_t>() / Value_t(180); // to rad from deg
114  return factor;
115  }
116 
117  template<typename Value_t>
118  inline const Value_t& fp_const_rad_to_deg() // CONSTANT_RD
119  {
120  static const Value_t factor = Value_t(180) / fp_const_pi<Value_t>(); // to deg from rad
121  return factor;
122  }
123 
124 #ifdef FP_SUPPORT_MPFR_FLOAT_TYPE
125  template<>
126  inline MpfrFloat fp_const_pi<MpfrFloat>() { return MpfrFloat::const_pi(); }
127 
128  template<>
129  inline MpfrFloat fp_const_e<MpfrFloat>() { return MpfrFloat::const_e(); }
130 
131  template<>
132  inline MpfrFloat fp_const_einv<MpfrFloat>() { return MpfrFloat(1) / MpfrFloat::const_e(); }
133 
134  template<>
135  inline MpfrFloat fp_const_log2<MpfrFloat>() { return MpfrFloat::const_log2(); }
136 
137  /*
138  template<>
139  inline MpfrFloat fp_const_log10<MpfrFloat>() { return fp_log(MpfrFloat(10)); }
140 
141  template<>
142  inline MpfrFloat fp_const_log2inv<MpfrFloat>() { return MpfrFloat(1) / MpfrFloat::const_log2(); }
143 
144  template<>
145  inline MpfrFloat fp_const_log10inv<MpfrFloat>() { return fp_log10(MpfrFloat::const_e()); }
146  */
147 #endif
148 
149 
150 //==========================================================================
151 // Generic math functions
152 //==========================================================================
153  template<typename Value_t>
154  inline Value_t fp_abs(const Value_t& x) { return std::fabs(x); }
155 
156  template<typename Value_t>
157  inline Value_t fp_acos(const Value_t& x) { return std::acos(x); }
158 
159  template<typename Value_t>
160  inline Value_t fp_asin(const Value_t& x) { return std::asin(x); }
161 
162  template<typename Value_t>
163  inline Value_t fp_atan(const Value_t& x) { return std::atan(x); }
164 
165  template<typename Value_t>
166  inline Value_t fp_atan2(const Value_t& x, const Value_t& y)
167  { return std::atan2(x, y); }
168 
169  template<typename Value_t>
170  inline Value_t fp_ceil(const Value_t& x) { return std::ceil(x); }
171 
172  template<typename Value_t>
173  inline Value_t fp_cos(const Value_t& x) { return std::cos(x); }
174 
175  template<typename Value_t>
176  inline Value_t fp_cosh(const Value_t& x) { return std::cosh(x); }
177 
178  template<typename Value_t>
179  inline Value_t fp_exp(const Value_t& x) { return std::exp(x); }
180 
181  template<typename Value_t>
182  inline Value_t fp_floor(const Value_t& x) { return std::floor(x); }
183 
184  template<typename Value_t>
185  inline Value_t fp_log(const Value_t& x) { return std::log(x); }
186 
187  template<typename Value_t>
188  inline Value_t fp_mod(const Value_t& x, const Value_t& y)
189  { return std::fmod(x, y); }
190 
191  template<typename Value_t>
192  inline Value_t fp_sin(const Value_t& x) { return std::sin(x); }
193 
194  template<typename Value_t>
195  inline Value_t fp_sinh(const Value_t& x) { return std::sinh(x); }
196 
197  template<typename Value_t>
198  inline Value_t fp_sqrt(const Value_t& x) { return std::sqrt(x); }
199 
200  template<typename Value_t>
201  inline Value_t fp_tan(const Value_t& x) { return std::tan(x); }
202 
203  template<typename Value_t>
204  inline Value_t fp_tanh(const Value_t& x) { return std::tanh(x); }
205 
206 #ifdef FP_SUPPORT_CPLUSPLUS11_MATH_FUNCS
207  template<typename Value_t>
208  inline Value_t fp_asinh(const Value_t& x) { return std::asinh(x); }
209 
210  template<typename Value_t>
211  inline Value_t fp_acosh(const Value_t& x) { return std::acosh(x); }
212 
213  template<typename Value_t>
214  inline Value_t fp_atanh(const Value_t& x) { return std::atanh(x); }
215 #else
216  template<typename Value_t>
217  inline Value_t fp_asinh(const Value_t& x)
218  { return fp_log(x + fp_sqrt(x*x + Value_t(1))); }
219 
220  template<typename Value_t>
221  inline Value_t fp_acosh(const Value_t& x)
222  { return fp_log(x + fp_sqrt(x*x - Value_t(1))); }
223 
224  template<typename Value_t>
225  inline Value_t fp_atanh(const Value_t& x)
226  {
227  return fp_log( (Value_t(1)+x) / (Value_t(1)-x)) * Value_t(0.5);
228  // Note: x = +1 causes division by zero
229  // x = -1 causes log(0)
230  // Thus, x must not be +-1
231  }
232 #endif // FP_SUPPORT_ASINH
233 
234 #ifdef FP_SUPPORT_CPLUSPLUS11_MATH_FUNCS
235  template<typename Value_t>
236  inline Value_t fp_hypot(const Value_t& x, const Value_t& y)
237  { return std::hypot(x,y); }
238 
239  template<typename Value_t>
240  inline std::complex<Value_t> fp_hypot
241  (const std::complex<Value_t>& x, const std::complex<Value_t>& y)
242  { return fp_sqrt(x*x + y*y); }
243 #else
244  template<typename Value_t>
245  inline Value_t fp_hypot(const Value_t& x, const Value_t& y)
246  { return fp_sqrt(x*x + y*y); }
247 #endif
248 
249  template<typename Value_t>
250  inline Value_t fp_pow_base(const Value_t& x, const Value_t& y)
251  { return std::pow(x, y); }
252 
253 #ifdef FP_SUPPORT_CPLUSPLUS11_MATH_FUNCS
254  template<typename Value_t>
255  inline Value_t fp_log2(const Value_t& x) { return std::log2(x); }
256 
257  template<typename Value_t>
258  inline std::complex<Value_t> fp_log2(const std::complex<Value_t>& x)
259  {
260  return fp_log(x) * fp_const_log2inv<Value_t>();
261  }
262 #else
263  template<typename Value_t>
264  inline Value_t fp_log2(const Value_t& x)
265  {
266  return fp_log(x) * fp_const_log2inv<Value_t>();
267  }
268 #endif // FP_SUPPORT_LOG2
269 
270  template<typename Value_t>
271  inline Value_t fp_log10(const Value_t& x)
272  {
273  return fp_log(x) * fp_const_log10inv<Value_t>();
274  }
275 
276  template<typename Value_t>
277  inline Value_t fp_trunc(const Value_t& x)
278  {
279  return x < Value_t() ? fp_ceil(x) : fp_floor(x);
280  }
281 
282  template<typename Value_t>
283  inline Value_t fp_int(const Value_t& x)
284  {
285  return x < Value_t() ?
286  fp_ceil(x - Value_t(0.5)) : fp_floor(x + Value_t(0.5));
287  }
288 
289  template<typename Value_t>
290  inline void fp_sinCos(Value_t& sinvalue, Value_t& cosvalue,
291  const Value_t& param)
292  {
293  // Assuming that "cosvalue" and "param" do not
294  // overlap, but "sinvalue" and "param" may.
295  cosvalue = fp_cos(param);
296  sinvalue = fp_sin(param);
297  }
298 
299  template<typename Value_t>
300  inline void fp_sinhCosh(Value_t& sinhvalue, Value_t& coshvalue,
301  const Value_t& param)
302  {
303  const Value_t ex(fp_exp(param)), emx(fp_exp(-param));
304  sinhvalue = Value_t(0.5)*(ex-emx);
305  coshvalue = Value_t(0.5)*(ex+emx);
306  }
307 
308  template<typename Value_t>
309  struct Epsilon
310  {
311  static Value_t value;
312  static Value_t defaultValue() { return 0; }
313  };
314 
315  template<> inline double Epsilon<double>::defaultValue() { return 1E-12; }
316  template<> inline float Epsilon<float>::defaultValue() { return 1E-5F; }
317  template<> inline long double Epsilon<long double>::defaultValue() { return 1E-14L; }
318 
319  template<> inline std::complex<double>
320  Epsilon<std::complex<double> >::defaultValue() { return 1E-12; }
321 
322  template<> inline std::complex<float>
323  Epsilon<std::complex<float> >::defaultValue() { return 1E-5F; }
324 
325  template<> inline std::complex<long double>
326  Epsilon<std::complex<long double> >::defaultValue() { return 1E-14L; }
327 
328 #ifdef FP_SUPPORT_MPFR_FLOAT_TYPE
329  template<> inline MpfrFloat
330  Epsilon<MpfrFloat>::defaultValue() { return MpfrFloat::someEpsilon(); }
331 #endif
332 
333  template<typename Value_t> Value_t Epsilon<Value_t>::value =
334  Epsilon<Value_t>::defaultValue();
335 
336 
337 #ifdef _GNU_SOURCE
338  inline void fp_sinCos(double& sin, double& cos, const double& a)
339  {
340  sincos(a, &sin, &cos);
341  }
342  inline void fp_sinCos(float& sin, float& cos, const float& a)
343  {
344  sincosf(a, &sin, &cos);
345  }
346  inline void fp_sinCos(long double& sin, long double& cos,
347  const long double& a)
348  {
349  sincosl(a, &sin, &cos);
350  }
351 #endif
352 
353 
354 // -------------------------------------------------------------------------
355 // Long int
356 // -------------------------------------------------------------------------
357  inline long fp_abs(const long& x) { return x < 0 ? -x : x; }
358  inline long fp_acos(const long&) { return 0; }
359  inline long fp_asin(const long&) { return 0; }
360  inline long fp_atan(const long&) { return 0; }
361  inline long fp_atan2(const long&, const long&) { return 0; }
362  inline long fp_cbrt(const long&) { return 0; }
363  inline long fp_ceil(const long& x) { return x; }
364  inline long fp_cos(const long&) { return 0; }
365  inline long fp_cosh(const long&) { return 0; }
366  inline long fp_exp(const long&) { return 0; }
367  inline long fp_exp2(const long&) { return 0; }
368  inline long fp_floor(const long& x) { return x; }
369  inline long fp_log(const long&) { return 0; }
370  inline long fp_log2(const long&) { return 0; }
371  inline long fp_log10(const long&) { return 0; }
372  inline long fp_mod(const long& x, const long& y) { return x % y; }
373  inline long fp_pow(const long&, const long&) { return 0; }
374  inline long fp_sin(const long&) { return 0; }
375  inline long fp_sinh(const long&) { return 0; }
376  inline long fp_sqrt(const long&) { return 1; }
377  inline long fp_tan(const long&) { return 0; }
378  inline long fp_tanh(const long&) { return 0; }
379  inline long fp_asinh(const long&) { return 0; }
380  inline long fp_acosh(const long&) { return 0; }
381  inline long fp_atanh(const long&) { return 0; }
382  inline long fp_pow_base(const long&, const long&) { return 0; }
383  inline void fp_sinCos(long&, long&, const long&) {}
384  inline void fp_sinhCosh(long&, long&, const long&) {}
385 
386  //template<> inline long fp_epsilon<long>() { return 0; }
387 
388 
389 // -------------------------------------------------------------------------
390 // MpfrFloat
391 // -------------------------------------------------------------------------
392 #ifdef FP_SUPPORT_MPFR_FLOAT_TYPE
393  inline MpfrFloat fp_abs(const MpfrFloat& x) { return MpfrFloat::abs(x); }
394  inline MpfrFloat fp_acos(const MpfrFloat& x) { return MpfrFloat::acos(x); }
395  inline MpfrFloat fp_acosh(const MpfrFloat& x) { return MpfrFloat::acosh(x); }
396  inline MpfrFloat fp_asin(const MpfrFloat& x) { return MpfrFloat::asin(x); }
397  inline MpfrFloat fp_asinh(const MpfrFloat& x) { return MpfrFloat::asinh(x); }
398  inline MpfrFloat fp_atan(const MpfrFloat& x) { return MpfrFloat::atan(x); }
399  inline MpfrFloat fp_atan2(const MpfrFloat& x, const MpfrFloat& y)
400  { return MpfrFloat::atan2(x, y); }
401  inline MpfrFloat fp_atanh(const MpfrFloat& x) { return MpfrFloat::atanh(x); }
402  inline MpfrFloat fp_cbrt(const MpfrFloat& x) { return MpfrFloat::cbrt(x); }
403  inline MpfrFloat fp_ceil(const MpfrFloat& x) { return MpfrFloat::ceil(x); }
404  inline MpfrFloat fp_cos(const MpfrFloat& x) { return MpfrFloat::cos(x); }
405  inline MpfrFloat fp_cosh(const MpfrFloat& x) { return MpfrFloat::cosh(x); }
406  inline MpfrFloat fp_exp(const MpfrFloat& x) { return MpfrFloat::exp(x); }
407  inline MpfrFloat fp_exp2(const MpfrFloat& x) { return MpfrFloat::exp2(x); }
408  inline MpfrFloat fp_floor(const MpfrFloat& x) { return MpfrFloat::floor(x); }
409  inline MpfrFloat fp_hypot(const MpfrFloat& x, const MpfrFloat& y)
410  { return MpfrFloat::hypot(x, y); }
411  inline MpfrFloat fp_int(const MpfrFloat& x) { return MpfrFloat::round(x); }
412  inline MpfrFloat fp_log(const MpfrFloat& x) { return MpfrFloat::log(x); }
413  inline MpfrFloat fp_log2(const MpfrFloat& x) { return MpfrFloat::log2(x); }
414  inline MpfrFloat fp_log10(const MpfrFloat& x) { return MpfrFloat::log10(x); }
415  inline MpfrFloat fp_mod(const MpfrFloat& x, const MpfrFloat& y) { return x % y; }
416  inline MpfrFloat fp_sin(const MpfrFloat& x) { return MpfrFloat::sin(x); }
417  inline MpfrFloat fp_sinh(const MpfrFloat& x) { return MpfrFloat::sinh(x); }
418  inline MpfrFloat fp_sqrt(const MpfrFloat& x) { return MpfrFloat::sqrt(x); }
419  inline MpfrFloat fp_tan(const MpfrFloat& x) { return MpfrFloat::tan(x); }
420  inline MpfrFloat fp_tanh(const MpfrFloat& x) { return MpfrFloat::tanh(x); }
421  inline MpfrFloat fp_trunc(const MpfrFloat& x) { return MpfrFloat::trunc(x); }
422 
423  inline MpfrFloat fp_pow(const MpfrFloat& x, const MpfrFloat& y) { return MpfrFloat::pow(x, y); }
424  inline MpfrFloat fp_pow_base(const MpfrFloat& x, const MpfrFloat& y) { return MpfrFloat::pow(x, y); }
425 
426 
427  inline void fp_sinCos(MpfrFloat& sin, MpfrFloat& cos, const MpfrFloat& a)
428  {
429  MpfrFloat::sincos(a, sin, cos);
430  }
431 
432  inline void fp_sinhCosh(MpfrFloat& sinhvalue, MpfrFloat& coshvalue,
433  const MpfrFloat& param)
434  {
435  const MpfrFloat paramCopy = param;
436  sinhvalue = fp_sinh(paramCopy);
437  coshvalue = fp_cosh(paramCopy);
438  }
439 #endif // FP_SUPPORT_MPFR_FLOAT_TYPE
440 
441 
442 // -------------------------------------------------------------------------
443 // GMP int
444 // -------------------------------------------------------------------------
445 #ifdef FP_SUPPORT_GMP_INT_TYPE
446  inline GmpInt fp_abs(const GmpInt& x) { return GmpInt::abs(x); }
447  inline GmpInt fp_acos(const GmpInt&) { return 0; }
448  inline GmpInt fp_acosh(const GmpInt&) { return 0; }
449  inline GmpInt fp_asin(const GmpInt&) { return 0; }
450  inline GmpInt fp_asinh(const GmpInt&) { return 0; }
451  inline GmpInt fp_atan(const GmpInt&) { return 0; }
452  inline GmpInt fp_atan2(const GmpInt&, const GmpInt&) { return 0; }
453  inline GmpInt fp_atanh(const GmpInt&) { return 0; }
454  inline GmpInt fp_cbrt(const GmpInt&) { return 0; }
455  inline GmpInt fp_ceil(const GmpInt& x) { return x; }
456  inline GmpInt fp_cos(const GmpInt&) { return 0; }
457  inline GmpInt fp_cosh(const GmpInt&) { return 0; }
458  inline GmpInt fp_exp(const GmpInt&) { return 0; }
459  inline GmpInt fp_exp2(const GmpInt&) { return 0; }
460  inline GmpInt fp_floor(const GmpInt& x) { return x; }
461  inline GmpInt fp_hypot(const GmpInt&, const GmpInt&) { return 0; }
462  inline GmpInt fp_int(const GmpInt& x) { return x; }
463  inline GmpInt fp_log(const GmpInt&) { return 0; }
464  inline GmpInt fp_log2(const GmpInt&) { return 0; }
465  inline GmpInt fp_log10(const GmpInt&) { return 0; }
466  inline GmpInt fp_mod(const GmpInt& x, const GmpInt& y) { return x % y; }
467  inline GmpInt fp_pow(const GmpInt&, const GmpInt&) { return 0; }
468  inline GmpInt fp_sin(const GmpInt&) { return 0; }
469  inline GmpInt fp_sinh(const GmpInt&) { return 0; }
470  inline GmpInt fp_sqrt(const GmpInt&) { return 0; }
471  inline GmpInt fp_tan(const GmpInt&) { return 0; }
472  inline GmpInt fp_tanh(const GmpInt&) { return 0; }
473  inline GmpInt fp_trunc(const GmpInt& x) { return x; }
474  inline GmpInt fp_pow_base(const GmpInt&, const GmpInt&) { return 0; }
475  inline void fp_sinCos(GmpInt&, GmpInt&, const GmpInt&) {}
476  inline void fp_sinhCosh(GmpInt&, GmpInt&, const GmpInt&) {}
477 #endif // FP_SUPPORT_GMP_INT_TYPE
478 
479 
480 #ifdef FP_SUPPORT_CPLUSPLUS11_MATH_FUNCS
481  template<typename Value_t>
482  inline Value_t fp_cbrt(const Value_t& x) { return std::cbrt(x); }
483 #else
484  template<typename Value_t>
485  inline Value_t fp_cbrt(const Value_t& x)
486  {
487  return (x > Value_t() ? fp_exp(fp_log( x) / Value_t(3)) :
488  x < Value_t() ? -fp_exp(fp_log(-x) / Value_t(3)) :
489  Value_t());
490  }
491 #endif
492 
493 // -------------------------------------------------------------------------
494 // Synthetic functions and fallbacks for when an optimized
495 // implementation or a library function is not available
496 // -------------------------------------------------------------------------
497  template<typename Value_t> inline Value_t fp_arg(const Value_t& x);
498  template<typename Value_t> inline Value_t fp_exp2(const Value_t& x);
499  template<typename Value_t> inline Value_t fp_int(const Value_t& x);
500  template<typename Value_t> inline Value_t fp_trunc(const Value_t& x);
501  template<typename Value_t>
502  inline void fp_sinCos(Value_t& , Value_t& , const Value_t& );
503  template<typename Value_t>
504  inline void fp_sinhCosh(Value_t& , Value_t& , const Value_t& );
505 
506 #ifdef FP_SUPPORT_COMPLEX_NUMBERS
507  /* NOTE: Complex multiplication of a and b can be done with:
508  tmp = b.real * (a.real + a.imag)
509  result.real = tmp - a.imag * (b.real + b.imag)
510  result.imag = tmp + a.real * (b.imag - b.real)
511  This has fewer multiplications than the standard
512  algorithm. Take note, if you support mpfr complex one day.
513  */
514 
515  template<typename T>
516  struct FP_ProbablyHasFastLibcComplex
517  { enum { result = false }; };
518  /* The generic sqrt() etc. implementations in libstdc++
519  * are very plain and non-optimized; however, it contains
520  * callbacks to libc complex math functions where possible,
521  * and I suspect that those may actually be well optimized.
522  * So we use std:: functions when we suspect they may be fast,
523  * and otherwise we use our own optimized implementations.
524  */
525 #ifdef __GNUC__
526  template<> struct FP_ProbablyHasFastLibcComplex<float>
527  { enum { result = true }; };
528  template<> struct FP_ProbablyHasFastLibcComplex<double>
529  { enum { result = true }; };
530  template<> struct FP_ProbablyHasFastLibcComplex<long double>
531  { enum { result = true }; };
532 #endif
533 
534  template<typename T>
535  inline const std::complex<T> fp_make_imag(const std::complex<T>& v)
536  {
537  return std::complex<T> ( T(), v.real() );
538  }
539 
540  template<typename T>
541  inline std::complex<T> fp_real(const std::complex<T>& x)
542  {
543  return x.real();
544  }
545  template<typename T>
546  inline std::complex<T> fp_imag(const std::complex<T>& x)
547  {
548  return x.imag();
549  }
550  template<typename T>
551  inline std::complex<T> fp_arg(const std::complex<T>& x)
552  {
553  return std::arg(x);
554  }
555  template<typename T>
556  inline std::complex<T> fp_conj(const std::complex<T>& x)
557  {
558  return std::conj(x);
559  }
560  template<typename T, bool>
561  inline std::complex<T> fp_polar(const T& x, const T& y)
562  {
563  T si, co; fp_sinCos(si, co, y);
564  return std::complex<T> (x*co, x*si);
565  }
566  template<typename T>
567  inline std::complex<T> fp_polar(const std::complex<T>& x, const std::complex<T>& y)
568  {
569  // x * cos(y) + i * x * sin(y) -- arguments are supposed to be REAL numbers
570  return fp_polar<T,true> (x.real(), y.real());
571  //return std::polar(x.real(), y.real());
572  //return x * (fp_cos(y) + (std::complex<T>(0,1) * fp_sin(y));
573  }
574 
575  // These provide fallbacks in case there's no library function
576  template<typename T>
577  inline std::complex<T> fp_floor(const std::complex<T>& x)
578  {
579  return std::complex<T> (fp_floor(x.real()), fp_floor(x.imag()));
580  }
581  template<typename T>
582  inline std::complex<T> fp_trunc(const std::complex<T>& x)
583  {
584  return std::complex<T> (fp_trunc(x.real()), fp_trunc(x.imag()));
585  }
586  template<typename T>
587  inline std::complex<T> fp_int(const std::complex<T>& x)
588  {
589  return std::complex<T> (fp_int(x.real()), fp_int(x.imag()));
590  }
591  template<typename T>
592  inline std::complex<T> fp_ceil(const std::complex<T>& x)
593  {
594  return std::complex<T> (fp_ceil(x.real()), fp_ceil(x.imag()));
595  }
596  template<typename T>
597  inline std::complex<T> fp_abs(const std::complex<T>& x)
598  {
599  return std::abs(x);
600  //T extent = fp_max(fp_abs(x.real()), fp_abs(x.imag()));
601  //if(extent == T()) return x;
602  //return extent * fp_hypot(x.real() / extent, x.imag() / extent);
603  }
604  template<typename T>
605  inline std::complex<T> fp_exp(const std::complex<T>& x)
606  {
607  if(FP_ProbablyHasFastLibcComplex<T>::result)
608  return std::exp(x);
609  return fp_polar<T,true>(fp_exp(x.real()), x.imag());
610  }
611  template<typename T>
612  inline std::complex<T> fp_log(const std::complex<T>& x)
613  {
614  if(FP_ProbablyHasFastLibcComplex<T>::result)
615  return std::log(x);
616  // log(abs(x)) + i*arg(x)
617  // log(Xr^2+Xi^2)*0.5 + i*arg(x)
618  if(x.imag()==T())
619  return std::complex<T>( fp_log(fp_abs(x.real())),
620  fp_arg(x.real()) ); // Note: Uses real-value fp_arg() here!
621  return std::complex<T>(
622  fp_log(std::norm(x)) * T(0.5),
623  fp_arg(x).real() );
624  }
625  template<typename T>
626  inline std::complex<T> fp_sqrt(const std::complex<T>& x)
627  {
628  if(FP_ProbablyHasFastLibcComplex<T>::result)
629  return std::sqrt(x);
630  return fp_polar<T,true> (fp_sqrt(fp_abs(x).real()),
631  T(0.5)*fp_arg(x).real());
632  }
633  template<typename T>
634  inline std::complex<T> fp_acos(const std::complex<T>& x)
635  {
636  // -i * log(x + i * sqrt(1 - x^2))
637  const std::complex<T> i (T(), T(1));
638  return -i * fp_log(x + i * fp_sqrt(T(1) - x*x));
639  // Note: Real version of acos() cannot handle |x| > 1,
640  // because it would cause sqrt(negative value).
641  }
642  template<typename T>
643  inline std::complex<T> fp_asin(const std::complex<T>& x)
644  {
645  // -i * log(i*x + sqrt(1 - x^2))
646  const std::complex<T> i (T(), T(1));
647  return -i * fp_log(i*x + fp_sqrt(T(1) - x*x));
648  // Note: Real version of asin() cannot handle |x| > 1,
649  // because it would cause sqrt(negative value).
650  }
651  template<typename T>
652  inline std::complex<T> fp_atan(const std::complex<T>& x)
653  {
654  // 0.5i * (log(1-i*x) - log(1+i*x))
655  // -0.5i * log( (1+i*x) / (1-i*x) )
656  const std::complex<T> i (T(), T(1));
657  return (T(-0.5)*i) * fp_log( (T(1)+i*x) / (T(1)-i*x) );
658  // Note: x = -1i causes division by zero
659  // x = +1i causes log(0)
660  // Thus, x must not be +-1i
661  }
662  template<typename T>
663  inline std::complex<T> fp_cos(const std::complex<T>& x)
664  {
665  return std::cos(x);
666  // // (exp(i*x) + exp(-i*x)) / (2)
667  // //const std::complex<T> i (T(), T(1));
668  // //return (fp_exp(i*x) + fp_exp(-i*x)) * T(0.5);
669  // // Also: cos(Xr)*cosh(Xi) - i*sin(Xr)*sinh(Xi)
670  // return std::complex<T> (
671  // fp_cos(x.real())*fp_cosh(x.imag()),
672  // -fp_sin(x.real())*fp_sinh(x.imag()));
673  }
674  template<typename T>
675  inline std::complex<T> fp_sin(const std::complex<T>& x)
676  {
677  return std::sin(x);
678  // // (exp(i*x) - exp(-i*x)) / (2i)
679  // //const std::complex<T> i (T(), T(1));
680  // //return (fp_exp(i*x) - fp_exp(-i*x)) * (T(-0.5)*i);
681  // // Also: sin(Xr)*cosh(Xi) + cos(Xr)*sinh(Xi)
682  // return std::complex<T> (
683  // fp_sin(x.real())*fp_cosh(x.imag()),
684  // fp_cos(x.real())*fp_sinh(x.imag()));
685  }
686  template<typename T>
687  inline void fp_sinCos(
688  std::complex<T>& sinvalue,
689  std::complex<T>& cosvalue,
690  const std::complex<T>& x)
691  {
692  //const std::complex<T> i (T(), T(1)), expix(fp_exp(i*x)), expmix(fp_exp((-i)*x));
693  //cosvalue = (expix + expmix) * T(0.5);
694  //sinvalue = (expix - expmix) * (i*T(-0.5));
695  // The above expands to the following:
696  T srx, crx; fp_sinCos(srx, crx, x.real());
697  T six, cix; fp_sinhCosh(six, cix, x.imag());
698  sinvalue = std::complex<T>(srx*cix, crx*six);
699  cosvalue = std::complex<T>(crx*cix, -srx*six);
700  }
701  template<typename T>
702  inline void fp_sinhCosh(
703  std::complex<T>& sinhvalue,
704  std::complex<T>& coshvalue,
705  const std::complex<T>& x)
706  {
707  T srx, crx; fp_sinhCosh(srx, crx, x.real());
708  T six, cix; fp_sinCos(six, cix, x.imag());
709  sinhvalue = std::complex<T>(srx*cix, crx*six);
710  coshvalue = std::complex<T>(crx*cix, srx*six);
711  }
712  template<typename T>
713  inline std::complex<T> fp_tan(const std::complex<T>& x)
714  {
715  return std::tan(x);
716  //std::complex<T> si, co;
717  //fp_sinCos(si, co, x);
718  //return si/co;
719  // // (i-i*exp(2i*x)) / (exp(2i*x)+1)
720  // const std::complex<T> i (T(), T(1)), exp2ix=fp_exp((2*i)*x);
721  // return (i-i*exp2ix) / (exp2ix+T(1));
722  // // Also: sin(x)/cos(y)
723  // // return fp_sin(x)/fp_cos(x);
724  }
725  template<typename T>
726  inline std::complex<T> fp_cosh(const std::complex<T>& x)
727  {
728  return std::cosh(x);
729  // // (exp(x) + exp(-x)) * 0.5
730  // // Also: cosh(Xr)*cos(Xi) + i*sinh(Xr)*sin(Xi)
731  // return std::complex<T> (
732  // fp_cosh(x.real())*fp_cos(x.imag()),
733  // fp_sinh(x.real())*fp_sin(x.imag()));
734  }
735  template<typename T>
736  inline std::complex<T> fp_sinh(const std::complex<T>& x)
737  {
738  return std::sinh(x);
739  // // (exp(x) - exp(-x)) * 0.5
740  // // Also: sinh(Xr)*cos(Xi) + i*cosh(Xr)*sin(Xi)
741  // return std::complex<T> (
742  // fp_sinh(x.real())*fp_cos(x.imag()),
743  // fp_cosh(x.real())*fp_sin(x.imag()));
744  }
745  template<typename T>
746  inline std::complex<T> fp_tanh(const std::complex<T>& x)
747  {
748  return std::tanh(x);
749  //std::complex<T> si, co;
750  //fp_sinhCosh(si, co, x);
751  //return si/co;
752  // // (exp(2*x)-1) / (exp(2*x)+1)
753  // // Also: sinh(x)/tanh(x)
754  // const std::complex<T> exp2x=fp_exp(x+x);
755  // return (exp2x-T(1)) / (exp2x+T(1));
756  }
757 
758 #ifdef FP_SUPPORT_CPLUSPLUS11_MATH_FUNCS
759  template<typename T>
760  inline std::complex<T> fp_acosh(const std::complex<T>& x)
761  { return fp_log(x + fp_sqrt(x*x - std::complex<T>(1))); }
762  template<typename T>
763  inline std::complex<T> fp_asinh(const std::complex<T>& x)
764  { return fp_log(x + fp_sqrt(x*x + std::complex<T>(1))); }
765  template<typename T>
766  inline std::complex<T> fp_atanh(const std::complex<T>& x)
767  { return fp_log( (std::complex<T>(1)+x) / (std::complex<T>(1)-x))
768  * std::complex<T>(0.5); }
769 #endif
770  template<typename T>
771  inline std::complex<T> fp_pow(const std::complex<T>& x, const std::complex<T>& y)
772  {
773  // return std::pow(x,y);
774 
775  // With complex numbers, pow(x,y) can be solved with
776  // the general formula: exp(y*log(x)). It handles
777  // all special cases gracefully.
778  // It expands to the following:
779  // A)
780  // t1 = log(x)
781  // t2 = y * t1
782  // res = exp(t2)
783  // B)
784  // t1.r = log(x.r * x.r + x.i * x.i) * 0.5 \ fp_log()
785  // t1.i = atan2(x.i, x.r) /
786  // t2.r = y.r*t1.r - y.i*t1.i \ multiplication
787  // t2.i = y.r*t1.i + y.i*t1.r /
788  // rho = exp(t2.r) \ fp_exp()
789  // theta = t2.i /
790  // res.r = rho * cos(theta) \ fp_polar(), called from
791  // res.i = rho * sin(theta) / fp_exp(). Uses sincos().
792  // Aside from the common "norm" calculation in atan2()
793  // and in the log parameter, both of which are part of fp_log(),
794  // there does not seem to be any incentive to break this
795  // function down further; it would not help optimizing it.
796  // However, we do handle the following special cases:
797  //
798  // When x is real (positive or negative):
799  // t1.r = log(abs(x.r))
800  // t1.i = x.r<0 ? -pi : 0
801  // When y is real:
802  // t2.r = y.r * t1.r
803  // t2.i = y.r * t1.i
804  const std::complex<T> t =
805  (x.imag() != T())
806  ? fp_log(x)
807  : std::complex<T> (fp_log(fp_abs(x.real())),
808  fp_arg(x.real())); // Note: Uses real-value fp_arg() here!
809  return y.imag() != T()
810  ? fp_exp(y * t)
811  : fp_polar<T,true> (fp_exp(y.real()*t.real()), y.real()*t.imag());
812  }
813  template<typename T>
814  inline std::complex<T> fp_cbrt(const std::complex<T>& x)
815  {
816  // For real numbers, prefer giving a real solution
817  // rather than a complex solution.
818  // For example, cbrt(-3) has the following three solutions:
819  // A) 0.7211247966535 + 1.2490247864016i
820  // B) 0.7211247966535 - 1.2490247864016i
821  // C) -1.442249593307
822  // exp(log(x)/3) gives A, but we prefer to give C.
823  if(x.imag() == T()) return fp_cbrt(x.real());
824  const std::complex<T> t(fp_log(x));
825  return fp_polar<T,true> (fp_exp(t.real() / T(3)), t.imag() / T(3));
826  }
827 
828  template<typename T>
829  inline std::complex<T> fp_exp2(const std::complex<T>& x)
830  {
831  // pow(2, x)
832  // polar(2^Xr, Xi*log(2))
833  return fp_polar<T,true> (fp_exp2(x.real()), x.imag()*fp_const_log2<T>());
834  }
835  template<typename T>
836  inline std::complex<T> fp_mod(const std::complex<T>& x, const std::complex<T>& y)
837  {
838  // Modulo function is probably not defined for complex numbers.
839  // But we do our best to calculate it the same way as it is done
840  // with real numbers, so that at least it is in some way "consistent".
841  if(y.imag() == 0) return fp_mod(x.real(), y.real()); // optimization
842  std::complex<T> n = fp_trunc(x / y);
843  return x - n * y;
844  }
845 
846  /* libstdc++ already defines a streaming operator for complex values,
847  * but we redefine our own that it is compatible with the input
848  * accepted by fparser. I.e. instead of (5,3) we now get (5+3i),
849  * and instead of (-4,0) we now get -4.
850  */
851  template<typename T>
852  inline std::ostream& operator<<(std::ostream& os, const std::complex<T>& value)
853  {
854  if(value.imag() == T()) return os << value.real();
855  if(value.real() == T()) return os << value.imag() << 'i';
856  if(value.imag() < T())
857  return os << '(' << value.real() << "-" << -value.imag() << "i)";
858  else
859  return os << '(' << value.real() << "+" << value.imag() << "i)";
860  }
861 
862  /* Less-than or greater-than operators are not technically defined
863  * for Complex types. However, in fparser and its tool set, these
864  * operators are widely required to be present.
865  * Our implementation here is based on converting the complex number
866  * into a scalar and the doing a scalar comparison on the value.
867  * The means by which the number is changed into a scalar is based
868  * on the following principles:
869  * - Does not introduce unjustified amounts of extra inaccuracy
870  * - Is transparent to purely real values
871  * (this disqualifies something like x.real() + x.imag())
872  * - Does not ignore the imaginary value completely
873  * (this may be relevant especially in testbed)
874  * - Is not so complicated that it would slow down a great deal
875  *
876  * Basically our formula here is the same as std::abs(),
877  * except that it keeps the sign of the original real number,
878  * and it does not do a sqrt() calculation that is not really
879  * needed because we are only interested in the relative magnitudes.
880  *
881  * Equality and nonequality operators must not need to be overloaded.
882  * They are already implemented in standard, and we must
883  * not introduce flawed equality assumptions.
884  */
885  template<typename T>
886  inline T fp_complexScalarize(const std::complex<T>& x)
887  {
888  T res(std::norm(x));
889  if(x.real() < T()) res = -res;
890  return res;
891  }
892  template<typename T>
893  inline T fp_realComplexScalarize(const T& x)
894  {
895  T res(x*x);
896  if(x < T()) res = -res;
897  return res;
898  }
899  // { return x.real() * (T(1.0) + fp_abs(x.imag())); }
900  #define d(op) \
901  template<typename T> \
902  inline bool operator op (const std::complex<T>& x, T y) \
903  { return fp_complexScalarize(x) op fp_realComplexScalarize(y); } \
904  template<typename T> \
905  inline bool operator op (const std::complex<T>& x, const std::complex<T>& y) \
906  { return fp_complexScalarize(x) op \
907  fp_complexScalarize(y); } \
908  template<typename T> \
909  inline bool operator op (T x, const std::complex<T>& y) \
910  { return fp_realComplexScalarize(x) op fp_complexScalarize(y); }
911  d( < ) d( <= ) d( > ) d( >= )
912  #undef d
913 #endif
914 
915  template<typename Value_t>
916  inline Value_t fp_real(const Value_t& x) { return x; }
917  template<typename Value_t>
918  inline Value_t fp_imag(const Value_t& ) { return Value_t(); }
919  template<typename Value_t>
920  inline Value_t fp_arg(const Value_t& x)
921  { return x < Value_t() ? -fp_const_pi<Value_t>() : Value_t(); }
922  template<typename Value_t>
923  inline Value_t fp_conj(const Value_t& x) { return x; }
924  template<typename Value_t>
925  inline Value_t fp_polar(const Value_t& x, const Value_t& y)
926  { return x * fp_cos(y); } // This is of course a meaningless function.
927 
928  template<typename Value_t>
929  inline std::complex<Value_t> fp_atan2(const std::complex<Value_t>& y,
930  const std::complex<Value_t>& x)
931  {
932  if(y == Value_t()) return fp_arg(x);
933  if(x == Value_t()) return fp_const_pi<Value_t>() * Value_t(-0.5);
934  // 2*atan(y / (sqrt(x^2+y^2) + x) )
935  // 2*atan( (sqrt(x^2+y^2) - x) / y)
936  std::complex<Value_t> res( fp_atan(y / (fp_hypot(x,y) + x)) );
937  return res+res;
938  }
939 
940 // -------------------------------------------------------------------------
941 // Comparison
942 // -------------------------------------------------------------------------
943  template<typename Value_t>
944  inline bool fp_equal(const Value_t& x, const Value_t& y)
945  { return IsIntType<Value_t>::result
946  ? (x == y)
947  : (fp_abs(x - y) <= Epsilon<Value_t>::value); }
948 
949  template<typename Value_t>
950  inline bool fp_nequal(const Value_t& x, const Value_t& y)
951  { return IsIntType<Value_t>::result
952  ? (x != y)
953  : (fp_abs(x - y) > Epsilon<Value_t>::value); }
954 
955  template<typename Value_t>
956  inline bool fp_less(const Value_t& x, const Value_t& y)
957  { return IsIntType<Value_t>::result
958  ? (x < y)
959  : (x < y - Epsilon<Value_t>::value); }
960 
961  template<typename Value_t>
962  inline bool fp_lessOrEq(const Value_t& x, const Value_t& y)
963  { return IsIntType<Value_t>::result
964  ? (x <= y)
965  : (x <= y + Epsilon<Value_t>::value); }
966 
967 
968  template<typename Value_t>
969  inline bool fp_greater(const Value_t& x, const Value_t& y)
970  { return fp_less(y, x); }
971 
972  template<typename Value_t>
973  inline bool fp_greaterOrEq(const Value_t& x, const Value_t& y)
974  { return fp_lessOrEq(y, x); }
975 
976  template<typename Value_t>
977  inline bool fp_truth(const Value_t& d)
978  {
979  return IsIntType<Value_t>::result
980  ? d != Value_t()
981  : fp_abs(d) >= Value_t(0.5);
982  }
983 
984  template<typename Value_t>
985  inline bool fp_absTruth(const Value_t& abs_d)
986  {
987  return IsIntType<Value_t>::result
988  ? abs_d > Value_t()
989  : abs_d >= Value_t(0.5);
990  }
991 
992  template<typename Value_t>
993  inline const Value_t& fp_min(const Value_t& d1, const Value_t& d2)
994  { return d1<d2 ? d1 : d2; }
995 
996  template<typename Value_t>
997  inline const Value_t& fp_max(const Value_t& d1, const Value_t& d2)
998  { return d1>d2 ? d1 : d2; }
999 
1000  template<typename Value_t>
1001  inline const Value_t fp_not(const Value_t& b)
1002  { return Value_t(!fp_truth(b)); }
1003 
1004  template<typename Value_t>
1005  inline const Value_t fp_notNot(const Value_t& b)
1006  { return Value_t(fp_truth(b)); }
1007 
1008  template<typename Value_t>
1009  inline const Value_t fp_absNot(const Value_t& b)
1010  { return Value_t(!fp_absTruth(b)); }
1011 
1012  template<typename Value_t>
1013  inline const Value_t fp_absNotNot(const Value_t& b)
1014  { return Value_t(fp_absTruth(b)); }
1015 
1016  template<typename Value_t>
1017  inline const Value_t fp_and(const Value_t& a, const Value_t& b)
1018  { return Value_t(fp_truth(a) && fp_truth(b)); }
1019 
1020  template<typename Value_t>
1021  inline const Value_t fp_or(const Value_t& a, const Value_t& b)
1022  { return Value_t(fp_truth(a) || fp_truth(b)); }
1023 
1024  template<typename Value_t>
1025  inline const Value_t fp_absAnd(const Value_t& a, const Value_t& b)
1026  { return Value_t(fp_absTruth(a) && fp_absTruth(b)); }
1027 
1028  template<typename Value_t>
1029  inline const Value_t fp_absOr(const Value_t& a, const Value_t& b)
1030  { return Value_t(fp_absTruth(a) || fp_absTruth(b)); }
1031 
1032  template<typename Value_t>
1033  inline const Value_t fp_make_imag(const Value_t& ) // Imaginary 1. In real mode, always zero.
1034  {
1035  return Value_t();
1036  }
1037 
1039  /* Opcode analysis functions are used by fp_opcode_add.inc */
1040  /* Moved here from fparser.cc because fp_opcode_add.inc
1041  * is also now included by fpoptimizer.cc
1042  */
1043  bool IsLogicalOpcode(unsigned op);
1044  bool IsComparisonOpcode(unsigned op);
1045  unsigned OppositeComparisonOpcode(unsigned op);
1046  bool IsNeverNegativeValueOpcode(unsigned op);
1047  bool IsAlwaysIntegerOpcode(unsigned op);
1048  bool IsUnaryOpcode(unsigned op);
1049  bool IsBinaryOpcode(unsigned op);
1050  bool IsVarOpcode(unsigned op);
1051  bool IsCommutativeOrParamSwappableBinaryOpcode(unsigned op);
1052  unsigned GetParamSwappedBinaryOpcode(unsigned op);
1053 
1054  template<bool ComplexType>
1055  bool HasInvalidRangesOpcode(unsigned op);
1056 
1057  template<typename Value_t>
1058  inline Value_t DegreesToRadians(const Value_t& degrees)
1059  {
1060  return degrees * fp_const_deg_to_rad<Value_t>();
1061  }
1062 
1063  template<typename Value_t>
1064  inline Value_t RadiansToDegrees(const Value_t& radians)
1065  {
1066  return radians * fp_const_rad_to_deg<Value_t>();
1067  }
1068 
1069  template<typename Value_t>
1070  inline long makeLongInteger(const Value_t& value)
1071  {
1072  return (long) fp_int(value);
1073  }
1074 
1075 #ifdef FP_SUPPORT_COMPLEX_NUMBERS
1076  template<typename T>
1077  inline long makeLongInteger(const std::complex<T>& value)
1078  {
1079  return (long) fp_int( std::abs(value) );
1080  }
1081 #endif
1082 
1083  // Is value an integer that fits in "long" datatype?
1084  template<typename Value_t>
1085  inline bool isLongInteger(const Value_t& value)
1086  {
1087  return value == Value_t( makeLongInteger(value) );
1088  }
1089 
1090  template<typename Value_t>
1091  inline bool isOddInteger(const Value_t& value)
1092  {
1093  const Value_t halfValue = (value + Value_t(1)) * Value_t(0.5);
1094  return fp_equal(halfValue, fp_floor(halfValue));
1095  }
1096 
1097  template<typename Value_t>
1098  inline bool isEvenInteger(const Value_t& value)
1099  {
1100  const Value_t halfValue = value * Value_t(0.5);
1101  return fp_equal(halfValue, fp_floor(halfValue));
1102  }
1103 
1104  template<typename Value_t>
1105  inline bool isInteger(const Value_t& value)
1106  {
1107  return fp_equal(value, fp_floor(value));
1108  }
1109 
1110 #ifdef FP_SUPPORT_LONG_INT_TYPE
1111  template<>
1112  inline bool isEvenInteger(const long& value)
1113  {
1114  return value%2 == 0;
1115  }
1116 
1117  template<>
1118  inline bool isInteger(const long&) { return true; }
1119 
1120  template<>
1121  inline bool isLongInteger(const long&) { return true; }
1122 
1123  template<>
1124  inline long makeLongInteger(const long& value)
1125  {
1126  return value;
1127  }
1128 #endif
1129 
1130 #ifdef FP_SUPPORT_MPFR_FLOAT_TYPE
1131  template<>
1132  inline bool isInteger(const MpfrFloat& value) { return value.isInteger(); }
1133 
1134  template<>
1135  inline bool isEvenInteger(const MpfrFloat& value)
1136  {
1137  return isInteger(value) && value%2 == 0;
1138  }
1139 
1140  template<>
1141  inline long makeLongInteger(const MpfrFloat& value)
1142  {
1143  return (long) value.toInt();
1144  }
1145 #endif
1146 
1147 #ifdef FP_SUPPORT_GMP_INT_TYPE
1148  template<>
1149  inline bool isEvenInteger(const GmpInt& value)
1150  {
1151  return value%2 == 0;
1152  }
1153 
1154  template<>
1155  inline bool isInteger(const GmpInt&) { return true; }
1156 
1157  template<>
1158  inline long makeLongInteger(const GmpInt& value)
1159  {
1160  return (long) value.toInt();
1161  }
1162 #endif
1163 
1164 #ifdef FP_SUPPORT_LONG_INT_TYPE
1165  template<>
1166  inline bool isOddInteger(const long& value)
1167  {
1168  return value%2 != 0;
1169  }
1170 #endif
1171 
1172 #ifdef FP_SUPPORT_MPFR_FLOAT_TYPE
1173  template<>
1174  inline bool isOddInteger(const MpfrFloat& value)
1175  {
1176  return value.isInteger() && value%2 != 0;
1177  }
1178 #endif
1179 
1180 #ifdef FP_SUPPORT_GMP_INT_TYPE
1181  template<>
1182  inline bool isOddInteger(const GmpInt& value)
1183  {
1184  return value%2 != 0;
1185  }
1186 #endif
1187 
1188 
1189 // -------------------------------------------------------------------------
1190 // fp_pow
1191 // -------------------------------------------------------------------------
1192  // Commented versions in fparser.cc
1193  template<typename Value_t>
1194  inline Value_t fp_pow_with_exp_log(const Value_t& x, const Value_t& y)
1195  {
1196  return fp_exp(fp_log(x) * y);
1197  }
1198 
1199  template<typename Value_t>
1200  inline Value_t fp_powi(Value_t x, unsigned long y)
1201  {
1202  Value_t result(1);
1203  while(y != 0)
1204  {
1205  if(y & 1) { result *= x; y -= 1; }
1206  else { x *= x; y /= 2; }
1207  }
1208  return result;
1209  }
1210 
1211  template<typename Value_t>
1212  Value_t fp_pow(const Value_t& x, const Value_t& y)
1213  {
1214  if(x == Value_t(1)) return Value_t(1);
1215  if(isLongInteger(y))
1216  {
1217  if(y >= Value_t(0))
1218  return fp_powi(x, makeLongInteger(y));
1219  else
1220  return Value_t(1) / fp_powi(x, -makeLongInteger(y));
1221  }
1222  if(y >= Value_t(0))
1223  {
1224  if(x > Value_t(0)) return fp_pow_with_exp_log(x, y);
1225  if(x == Value_t(0)) return Value_t(0);
1226  if(!isInteger(y*Value_t(16)))
1227  return -fp_pow_with_exp_log(-x, y);
1228  }
1229  else
1230  {
1231  if(x > Value_t(0)) return fp_pow_with_exp_log(Value_t(1) / x, -y);
1232  if(x < Value_t(0))
1233  {
1234  if(!isInteger(y*Value_t(-16)))
1235  return -fp_pow_with_exp_log(Value_t(-1) / x, -y);
1236  }
1237  }
1238  return fp_pow_base(x, y);
1239  }
1240 
1241  template<typename Value_t>
1242  inline Value_t fp_exp2(const Value_t& x)
1243  {
1244  return fp_pow(Value_t(2), x);
1245  }
1246 } // namespace FUNCTIONPARSERTYPES
1247 
1248 #endif // ONCE_FPARSER_H_
1249 #endif // ONCE_FPARSER_AUX_H_
static MpfrFloat sqrt(const MpfrFloat &)
static MpfrFloat cbrt(const MpfrFloat &)
static MpfrFloat tan(const MpfrFloat &)
static MpfrFloat const_log2()
static MpfrFloat log(const MpfrFloat &)
static MpfrFloat pow(const MpfrFloat &, const MpfrFloat &)
long toInt() const
static MpfrFloat asinh(const MpfrFloat &)
static MpfrFloat round(const MpfrFloat &)
static MpfrFloat sin(const MpfrFloat &)
static MpfrFloat trunc(const MpfrFloat &)
static MpfrFloat acos(const MpfrFloat &)
static MpfrFloat atan(const MpfrFloat &)
static MpfrFloat atan2(const MpfrFloat &, const MpfrFloat &)
static void sincos(const MpfrFloat &, MpfrFloat &sin, MpfrFloat &cos)
static MpfrFloat const_pi()
static MpfrFloat asin(const MpfrFloat &)
static MpfrFloat sinh(const MpfrFloat &)
static MpfrFloat tanh(const MpfrFloat &)
static MpfrFloat cos(const MpfrFloat &)
Definition: wn.h:215
static MpfrFloat cosh(const MpfrFloat &)
void abs()
Definition: GmpInt.h:6
static MpfrFloat hypot(const MpfrFloat &, const MpfrFloat &)
static MpfrFloat log10(const MpfrFloat &)
static MpfrFloat exp2(const MpfrFloat &)
long toInt() const
static MpfrFloat atanh(const MpfrFloat &)
static MpfrFloat acosh(const MpfrFloat &)
void abs()
static MpfrFloat const_e()
static MpfrFloat log2(const MpfrFloat &)
static MpfrFloat ceil(const MpfrFloat &)
static MpfrFloat someEpsilon()
bool isInteger() const
static MpfrFloat floor(const MpfrFloat &)
static MpfrFloat exp(const MpfrFloat &)