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

Documentation generated with Doxygen. Provided under the GNU Free Documentation License (see License Information).
Hosted at Get Object-oriented Scientific Computing
Lib at SourceForge.net. Fast, secure and Free Open Source software
downloads..