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 #include "fpconfig.hh"
12 #include "fparser.hh"
13 #include <set>
14 #include <cstdlib>
15 #include <cstring>
16 #include <cctype>
17 #include <cmath>
18 #include <cassert>
19 #include <limits>
20 #include "extrasrc/fptypes.hh"
21 #include "extrasrc/fpaux.hh"
22 using namespace FUNCTIONPARSERTYPES;
23
24 #ifdef FP_USE_THREAD_SAFE_EVAL_WITH_ALLOCA
25 #ifndef FP_USE_THREAD_SAFE_EVAL
26 #define FP_USE_THREAD_SAFE_EVAL
27 #endif
28 #endif
29
30 #ifdef __GNUC__
31 # define likely(x) __builtin_expect(!!(x), 1)
32 # define unlikely(x) __builtin_expect(!!(x), 0)
33 #else
34 # define likely(x) (x)
35 # define unlikely(x) (x)
36 #endif
37
38 //=========================================================================
39 // Opcode analysis functions
40 //=========================================================================
41 // These functions are used by the Parse() bytecode optimizer (mostly from
42 // code in fp_opcode_add.inc).
43
IsLogicalOpcode(unsigned op)44 bool FUNCTIONPARSERTYPES::IsLogicalOpcode(unsigned op)
45 {
46 switch(op)
47 {
48 case cAnd: case cAbsAnd:
49 case cOr: case cAbsOr:
50 case cNot: case cAbsNot:
51 case cNotNot: case cAbsNotNot:
52 case cEqual: case cNEqual:
53 case cLess: case cLessOrEq:
54 case cGreater: case cGreaterOrEq:
55 return true;
56 default: break;
57 }
58 return false;
59 }
60
IsComparisonOpcode(unsigned op)61 bool FUNCTIONPARSERTYPES::IsComparisonOpcode(unsigned op)
62 {
63 switch(op)
64 {
65 case cEqual: case cNEqual:
66 case cLess: case cLessOrEq:
67 case cGreater: case cGreaterOrEq:
68 return true;
69 default: break;
70 }
71 return false;
72 }
73
OppositeComparisonOpcode(unsigned op)74 unsigned FUNCTIONPARSERTYPES::OppositeComparisonOpcode(unsigned op)
75 {
76 switch(op)
77 {
78 case cLess: return cGreater;
79 case cGreater: return cLess;
80 case cLessOrEq: return cGreaterOrEq;
81 case cGreaterOrEq: return cLessOrEq;
82 }
83 return op;
84 }
85
IsNeverNegativeValueOpcode(unsigned op)86 bool FUNCTIONPARSERTYPES::IsNeverNegativeValueOpcode(unsigned op)
87 {
88 switch(op)
89 {
90 case cAnd: case cAbsAnd:
91 case cOr: case cAbsOr:
92 case cNot: case cAbsNot:
93 case cNotNot: case cAbsNotNot:
94 case cEqual: case cNEqual:
95 case cLess: case cLessOrEq:
96 case cGreater: case cGreaterOrEq:
97 case cSqrt: case cRSqrt: case cSqr:
98 case cHypot:
99 case cAbs:
100 case cAcos: case cCosh:
101 return true;
102 default: break;
103 }
104 return false;
105 }
106
IsAlwaysIntegerOpcode(unsigned op)107 bool FUNCTIONPARSERTYPES::IsAlwaysIntegerOpcode(unsigned op)
108 {
109 switch(op)
110 {
111 case cAnd: case cAbsAnd:
112 case cOr: case cAbsOr:
113 case cNot: case cAbsNot:
114 case cNotNot: case cAbsNotNot:
115 case cEqual: case cNEqual:
116 case cLess: case cLessOrEq:
117 case cGreater: case cGreaterOrEq:
118 case cInt: case cFloor: case cCeil: case cTrunc:
119 return true;
120 default: break;
121 }
122 return false;
123 }
124
IsUnaryOpcode(unsigned op)125 bool FUNCTIONPARSERTYPES::IsUnaryOpcode(unsigned op)
126 {
127 switch(op)
128 {
129 case cInv: case cNeg:
130 case cNot: case cAbsNot:
131 case cNotNot: case cAbsNotNot:
132 case cSqr: case cRSqrt:
133 case cDeg: case cRad:
134 return true;
135 }
136 return (op < FUNC_AMOUNT && Functions[op].params == 1);
137 }
138
IsBinaryOpcode(unsigned op)139 bool FUNCTIONPARSERTYPES::IsBinaryOpcode(unsigned op)
140 {
141 switch(op)
142 {
143 case cAdd: case cSub: case cRSub:
144 case cMul: case cDiv: case cRDiv:
145 case cMod:
146 case cEqual: case cNEqual: case cLess:
147 case cLessOrEq: case cGreater: case cGreaterOrEq:
148 case cAnd: case cAbsAnd:
149 case cOr: case cAbsOr:
150 return true;
151 }
152 return (op < FUNC_AMOUNT && Functions[op].params == 2);
153 }
154
IsVarOpcode(unsigned op)155 bool FUNCTIONPARSERTYPES::IsVarOpcode(unsigned op)
156 {
157 // See comment in declaration of FP_ParamGuardMask
158 return int(op) >= VarBegin;
159 }
160
IsCommutativeOrParamSwappableBinaryOpcode(unsigned op)161 bool FUNCTIONPARSERTYPES::IsCommutativeOrParamSwappableBinaryOpcode(unsigned op)
162 {
163 switch(op)
164 {
165 case cAdd:
166 case cMul:
167 case cEqual: case cNEqual:
168 case cAnd: case cAbsAnd:
169 case cOr: case cAbsOr:
170 case cMin: case cMax: case cHypot:
171 return true;
172 case cDiv: case cSub: case cRDiv: case cRSub:
173 return true;
174 case cLess: case cGreater:
175 case cLessOrEq: case cGreaterOrEq: return true;
176 }
177 return false;
178 }
179
GetParamSwappedBinaryOpcode(unsigned op)180 unsigned FUNCTIONPARSERTYPES::GetParamSwappedBinaryOpcode(unsigned op)
181 {
182 switch(op)
183 {
184 case cAdd:
185 case cMul:
186 case cEqual: case cNEqual:
187 case cAnd: case cAbsAnd:
188 case cOr: case cAbsOr:
189 case cMin: case cMax: case cHypot:
190 return op;
191 case cDiv: return cRDiv;
192 case cSub: return cRSub;
193 case cRDiv: return cDiv;
194 case cRSub: return cSub;
195 case cLess: return cGreater;
196 case cGreater: return cLess;
197 case cLessOrEq: return cGreaterOrEq;
198 case cGreaterOrEq: return cLessOrEq;
199 }
200 return op; // Error
201 }
202
203 template<bool ComplexType>
HasInvalidRangesOpcode(unsigned op)204 bool FUNCTIONPARSERTYPES::HasInvalidRangesOpcode(unsigned op)
205 {
206 // Returns true, if the given opcode has a range of
207 // input values that gives an error.
208 if(ComplexType)
209 {
210 // COMPLEX:
211 switch(op)
212 {
213 case cAtan: // allowed range: x != +-1i
214 case cAtanh: // allowed range: x != +-1
215 //case cCot: // allowed range: tan(x) != 0
216 //case cCsc: // allowed range: sin(x) != 0
217 case cLog: // allowed range: x != 0
218 case cLog2: // allowed range: x != 0
219 case cLog10: // allowed range: x != 0
220 #ifdef FP_SUPPORT_OPTIMIZER
221 case cLog2by:// allowed range: x != 0
222 #endif
223 //case cPow: // allowed when: x != 0 or y != 0
224 //case cSec: // allowed range: cos(x) != 0
225 //case cTan: // allowed range: cos(x) != 0 --> x != +-(pi/2)
226 //case cTanh: // allowed range: log(x) != -1 --> x != +-(pi/2)i
227 case cRSqrt: // allowed range: x != 0
228 //case cDiv: // allowed range: y != 0
229 //case cRDiv: // allowed range: x != 0
230 //case cInv: // allowed range: x != 0
231 return true;
232 }
233 }
234 else
235 {
236 // REAL:
237 switch(op)
238 {
239 case cAcos: // allowed range: |x| <= 1
240 case cAsin: // allowed range: |x| <= 1
241 case cAcosh: // allowed range: x >= 1
242 case cAtanh: // allowed range: |x| < 1
243 //case cCot: // allowed range: tan(x) != 0
244 //case cCsc: // allowed range: sin(x) != 0
245 case cLog: // allowed range: x > 0
246 case cLog2: // allowed range: x > 0
247 case cLog10: // allowed range: x > 0
248 #ifdef FP_SUPPORT_OPTIMIZER
249 case cLog2by:// allowed range: x > 0
250 #endif
251 //case cPow: // allowed when: x > 0 or (x = 0 and y != 0) or (x<0)
252 // Technically, when (x<0 and y is not integer),
253 // it is not allowed, but we allow it anyway
254 // in order to make nontrivial roots work.
255 //case cSec: // allowed range: cos(x) != 0
256 case cSqrt: // allowed range: x >= 0
257 case cRSqrt: // allowed range: x > 0
258 //case cTan: // allowed range: cos(x) != 0 --> x != +-(pi/2)
259 //case cDiv: // allowed range: y != 0
260 //case cRDiv: // allowed range: x != 0
261 //case cInv: // allowed range: x != 0
262 return true;
263 }
264 }
265 return false;
266 }
267
268 template bool FUNCTIONPARSERTYPES::HasInvalidRangesOpcode<false>(unsigned op);
269 template bool FUNCTIONPARSERTYPES::HasInvalidRangesOpcode<true>(unsigned op);
270
271
272 #if(0) // Implementation moved to fpaux.hh due to linker problems
273 //=========================================================================
274 // Mathematical template functions
275 //=========================================================================
276 /* fp_pow() is a wrapper for std::pow()
277 * that produces an identical value for
278 * exp(1) ^ 2.0 (0x4000000000000000)
279 * as exp(2.0) (0x4000000000000000)
280 * - std::pow() on x86_64
281 * produces 2.0 (0x3FFFFFFFFFFFFFFF) instead!
282 * See comments below for other special traits.
283 */
284 namespace
285 {
286 template<typename ValueT>
fp_pow_with_exp_log(const ValueT & x,const ValueT & y)287 inline ValueT fp_pow_with_exp_log(const ValueT& x, const ValueT& y)
288 {
289 // Exponentiation using exp(log(x)*y).
290 // See http://en.wikipedia.org/wiki/Exponentiation#Real_powers
291 // Requirements: x > 0.
292 return fp_exp(fp_log(x) * y);
293 }
294
295 template<typename ValueT>
fp_powi(ValueT x,unsigned long y)296 inline ValueT fp_powi(ValueT x, unsigned long y)
297 {
298 // Fast binary exponentiation algorithm
299 // See http://en.wikipedia.org/wiki/Exponentiation_by_squaring
300 // Requirements: y is non-negative integer.
301 ValueT result(1);
302 while(y != 0)
303 {
304 if(y & 1) { result *= x; y -= 1; }
305 else { x *= x; y /= 2; }
306 }
307 return result;
308 }
309 }
310
311 template<typename ValueT>
fp_pow(const ValueT & x,const ValueT & y)312 ValueT FUNCTIONPARSERTYPES::fp_pow(const ValueT& x, const ValueT& y)
313 {
314 if(x == ValueT(1)) return ValueT(1);
315 // y is now zero or positive
316 if(isLongInteger(y))
317 {
318 // Use fast binary exponentiation algorithm
319 if(y >= ValueT(0))
320 return fp_powi(x, makeLongInteger(y));
321 else
322 return ValueT(1) / fp_powi(x, -makeLongInteger(y));
323 }
324 if(y >= ValueT(0))
325 {
326 // y is now positive. Calculate using exp(log(x)*y).
327 if(x > ValueT(0)) return fp_pow_with_exp_log(x, y);
328 if(x == ValueT(0)) return ValueT(0);
329 // At this point, y > 0.0 and x is known to be < 0.0,
330 // because positive and zero cases are already handled.
331 if(!isInteger(y*ValueT(16)))
332 return -fp_pow_with_exp_log(-x, y);
333 // ^This is not technically correct, but it allows
334 // functions such as cbrt(x^5), that is, x^(5/3),
335 // to be evaluated when x is negative.
336 // It is too complicated (and slow) to test whether y
337 // is a formed from a ratio of an integer to an odd integer.
338 // (And due to floating point inaccuracy, pointless too.)
339 // For example, x^1.30769230769... is
340 // actually x^(17/13), i.e. (x^17) ^ (1/13).
341 // (-5)^(17/13) gives us now -8.204227562330453.
342 // To see whether the result is right, we can test the given
343 // root: (-8.204227562330453)^13 gives us the value of (-5)^17,
344 // which proves that the expression was correct.
345 //
346 // The y*16 check prevents e.g. (-4)^(3/2) from being calculated,
347 // as it would confuse functioninfo when pow() returns no error
348 // but sqrt() does when the formula is converted into sqrt(x)*x.
349 //
350 // The errors in this approach are:
351 // (-2)^sqrt(2) should produce NaN
352 // or actually sqrt(2)I + 2^sqrt(2),
353 // produces -(2^sqrt(2)) instead.
354 // (Impact: Neglible)
355 // Thus, at worst, we're changing a NaN (or complex)
356 // result into a negative real number result.
357 }
358 else
359 {
360 // y is negative. Utilize the x^y = 1/(x^-y) identity.
361 if(x > ValueT(0)) return fp_pow_with_exp_log(ValueT(1) / x, -y);
362 if(x < ValueT(0))
363 {
364 if(!isInteger(y*ValueT(-16)))
365 return -fp_pow_with_exp_log(ValueT(-1) / x, -y);
366 // ^ See comment above.
367 }
368 // Remaining case: 0.0 ^ negative number
369 }
370 // This is reached when:
371 // x=0, and y<0
372 // x<0, and y*16 is either positive or negative integer
373 // It is used for producing error values and as a safe fallback.
374 return fp_pow_base(x, y);
375 }
376 #endif
377
378
379 //=========================================================================
380 // Elementary (atom) parsing functions
381 //=========================================================================
382 namespace
383 {
384 const unsigned FP_ParamGuardMask = 1U << (sizeof(unsigned) * 8u - 1u);
385 // ^ This mask is used to prevent cFetch/other opcode's parameters
386 // from being confused into opcodes or variable indices within the
387 // bytecode optimizer. Because the way it is tested in bytecoderules.dat
388 // for speed reasons, it must also be the sign-bit of the "int" datatype.
389 // Perhaps an "assert(IsVarOpcode(X | FP_ParamGuardMask) == false)"
390 // might be justified to put somewhere in the code, just in case?
391
392
393 /* Reads an UTF8-encoded sequence which forms a valid identifier name from
394 the given input string and returns its length. If bit 31 is set, the
395 return value also contains the internal function opcode (defined in
396 fptypes.hh) that matches the name.
397 */
readIdentifierCommon(const char * input)398 unsigned readIdentifierCommon(const char* input)
399 {
400 /* Assuming unsigned = 32 bits:
401 76543210 76543210 76543210 76543210
402 Return value if built-in function:
403 1PPPPPPP PPPPPPPP LLLLLLLL LLLLLLLL
404 P = function opcode (15 bits)
405 L = function name length (16 bits)
406 Return value if not built-in function:
407 0LLLLLLL LLLLLLLL LLLLLLLL LLLLLLLL
408 L = identifier length (31 bits)
409 If unsigned has more than 32 bits, the other
410 higher order bits are to be assumed zero.
411 */
412 #include "extrasrc/fp_identifier_parser.inc"
413 return 0;
414 }
415
416 template<typename Value_t>
readIdentifier(const char * input)417 inline unsigned readIdentifier(const char* input)
418 {
419 const unsigned value = readIdentifierCommon(input);
420 if( (value & 0x80000000U) != 0) // Function?
421 {
422 // Verify that the function actually exists for this datatype
423 if(IsIntType<Value_t>::result
424 && !Functions[(value >> 16) & 0x7FFF].okForInt())
425 {
426 // If it does not exist, return it as an identifier instead
427 return value & 0xFFFFu;
428 }
429 if(!IsComplexType<Value_t>::result
430 && Functions[(value >> 16) & 0x7FFF].complexOnly())
431 {
432 // If it does not exist, return it as an identifier instead
433 return value & 0xFFFFu;
434 }
435 }
436 return value;
437 }
438
439 // Returns true if the entire string is a valid identifier
440 template<typename Value_t>
containsOnlyValidIdentifierChars(const std::string & name)441 bool containsOnlyValidIdentifierChars(const std::string& name)
442 {
443 if(name.empty()) return false;
444 return readIdentifier<Value_t>(name.c_str()) == unsigned(name.size());
445 }
446
447
448 // -----------------------------------------------------------------------
449 // Wrappers for strto... functions
450 // -----------------------------------------------------------------------
451 template<typename Value_t>
fp_parseLiteral(const char * str,char ** endptr)452 inline Value_t fp_parseLiteral(const char* str, char** endptr)
453 {
454 return std::strtod(str, endptr);
455 }
456
457 #if defined(FP_USE_STRTOLD) || defined(FP_SUPPORT_CPLUSPLUS11_MATH_FUNCS)
458 template<>
fp_parseLiteral(const char * str,char ** endptr)459 inline long double fp_parseLiteral<long double>(const char* str,
460 char** endptr)
461 {
462 using namespace std; // Just in case strtold() is not inside std::
463 return strtold(str, endptr);
464 }
465 #endif
466
467 #ifdef FP_SUPPORT_LONG_INT_TYPE
468 template<>
fp_parseLiteral(const char * str,char ** endptr)469 inline long fp_parseLiteral<long>(const char* str, char** endptr)
470 {
471 return std::strtol(str, endptr, 10);
472 }
473 #endif
474
475 #ifdef FP_SUPPORT_COMPLEX_NUMBERS
476 template<typename T>
fp_parseComplexLiteral(const char * str,char ** endptr)477 inline std::complex<T> fp_parseComplexLiteral(const char* str,
478 char** endptr)
479 {
480 T result = fp_parseLiteral<T> (str,endptr);
481 const char* end = *endptr;
482 if( (*end == 'i' || *end == 'I')
483 && !std::isalnum(end[1]) )
484 {
485 ++*endptr;
486 return std::complex<T> (T(), result);
487 }
488 return std::complex<T> (result, T());
489 }
490 #endif
491
492 #ifdef FP_SUPPORT_COMPLEX_DOUBLE_TYPE
493 template<>
fp_parseLiteral(const char * str,char ** endptr)494 inline std::complex<double> fp_parseLiteral<std::complex<double> >
495 (const char* str, char** endptr)
496 {
497 return fp_parseComplexLiteral<double> (str,endptr);
498 }
499 #endif
500
501 #ifdef FP_SUPPORT_COMPLEX_FLOAT_TYPE
502 template<>
fp_parseLiteral(const char * str,char ** endptr)503 inline std::complex<float> fp_parseLiteral<std::complex<float> >
504 (const char* str, char** endptr)
505 {
506 return fp_parseComplexLiteral<float> (str,endptr);
507 }
508 #endif
509
510 #ifdef FP_SUPPORT_COMPLEX_LONG_DOUBLE_TYPE
511 template<>
fp_parseLiteral(const char * str,char ** endptr)512 inline std::complex<long double> fp_parseLiteral<std::complex<long double> >
513 (const char* str, char** endptr)
514 {
515 return fp_parseComplexLiteral<long double> (str,endptr);
516 }
517 #endif
518
519 // -----------------------------------------------------------------------
520 // Hexadecimal floating point literal parsing
521 // -----------------------------------------------------------------------
testXdigit(unsigned c)522 inline int testXdigit(unsigned c)
523 {
524 if((c-'0') < 10u) return c&15; // 0..9
525 if(((c|0x20)-'a') < 6u) return 9+(c&15); // A..F or a..f
526 return -1; // Not a hex digit
527 }
528
529 template<typename elem_t, unsigned n_limbs, unsigned limb_bits>
addXdigit(elem_t * buffer,unsigned nibble)530 inline void addXdigit(elem_t* buffer, unsigned nibble)
531 {
532 for(unsigned p=0; p<n_limbs; ++p)
533 {
534 unsigned carry = unsigned( buffer[p] >> elem_t(limb_bits-4) );
535 buffer[p] = (buffer[p] << 4) | nibble;
536 nibble = carry;
537 }
538 }
539
540 template<typename Value_t>
parseHexLiteral(const char * str,char ** endptr)541 Value_t parseHexLiteral(const char* str, char** endptr)
542 {
543 const unsigned bits_per_char = 8;
544
545 const int MantissaBits =
546 std::numeric_limits<Value_t>::radix == 2
547 ? std::numeric_limits<Value_t>::digits
548 : (((sizeof(Value_t) * bits_per_char) &~ 3) - 4);
549
550 typedef unsigned long elem_t;
551 const int ExtraMantissaBits = 4 + ((MantissaBits+3)&~3); // Store one digit more for correct rounding
552 const unsigned limb_bits = sizeof(elem_t) * bits_per_char;
553 const unsigned n_limbs = (ExtraMantissaBits + limb_bits-1) / limb_bits;
554 elem_t mantissa_buffer[n_limbs] = { 0 };
555
556 int n_mantissa_bits = 0; // Track the number of bits
557 int exponent = 0; // The exponent that will be used to multiply the mantissa
558 // Read integer portion
559 while(true)
560 {
561 int xdigit = testXdigit(*str);
562 if(xdigit < 0) break;
563 addXdigit<elem_t,n_limbs,limb_bits> (mantissa_buffer, xdigit);
564 ++str;
565
566 n_mantissa_bits += 4;
567 if(n_mantissa_bits >= ExtraMantissaBits)
568 {
569 // Exhausted the precision. Parse the rest (until exponent)
570 // normally but ignore the actual digits.
571 for(; testXdigit(*str) >= 0; ++str)
572 exponent += 4;
573 // Read but ignore decimals
574 if(*str == '.')
575 for(++str; testXdigit(*str) >= 0; ++str)
576 {}
577 goto read_exponent;
578 }
579 }
580 // Read decimals
581 if(*str == '.')
582 for(++str; ; )
583 {
584 int xdigit = testXdigit(*str);
585 if(xdigit < 0) break;
586 addXdigit<elem_t,n_limbs,limb_bits> (mantissa_buffer, xdigit);
587 ++str;
588
589 exponent -= 4;
590 n_mantissa_bits += 4;
591 if(n_mantissa_bits >= ExtraMantissaBits)
592 {
593 // Exhausted the precision. Skip the rest
594 // of the decimals, until the exponent.
595 while(testXdigit(*str) >= 0)
596 ++str;
597 break;
598 }
599 }
600
601 // Read exponent
602 read_exponent:
603 if(*str == 'p' || *str == 'P')
604 {
605 const char* str2 = str+1;
606 long p_exponent = strtol(str2, const_cast<char**> (&str2), 10);
607 if(str2 != str+1 && p_exponent == (long)(int)p_exponent)
608 {
609 exponent += (int)p_exponent;
610 str = str2;
611 }
612 }
613
614 if(endptr) *endptr = const_cast<char*> (str);
615
616 Value_t result = std::ldexp(Value_t(mantissa_buffer[0]), exponent);
617 for(unsigned p=1; p<n_limbs; ++p)
618 {
619 exponent += limb_bits;
620 result += ldexp(Value_t(mantissa_buffer[p]), exponent);
621 }
622 return result;
623 }
624
625 #ifdef FP_SUPPORT_LONG_INT_TYPE
626 template<>
parseHexLiteral(const char * str,char ** endptr)627 long parseHexLiteral<long>(const char* str, char** endptr)
628 {
629 return std::strtol(str, endptr, 16);
630 }
631 #endif
632
633 #ifdef FP_SUPPORT_COMPLEX_DOUBLE_TYPE
634 template<>
635 std::complex<double>
parseHexLiteral(const char * str,char ** endptr)636 parseHexLiteral<std::complex<double> >(const char* str, char** endptr)
637 {
638 return parseHexLiteral<double> (str, endptr);
639 }
640 #endif
641
642 #ifdef FP_SUPPORT_COMPLEX_FLOAT_TYPE
643 template<>
644 std::complex<float>
parseHexLiteral(const char * str,char ** endptr)645 parseHexLiteral<std::complex<float> >(const char* str, char** endptr)
646 {
647 return parseHexLiteral<float> (str, endptr);
648 }
649 #endif
650
651 #ifdef FP_SUPPORT_COMPLEX_LONG_DOUBLE_TYPE
652 template<>
653 std::complex<long double>
parseHexLiteral(const char * str,char ** endptr)654 parseHexLiteral<std::complex<long double> >(const char* str, char** endptr)
655 {
656 return parseHexLiteral<long double> (str, endptr);
657 }
658 #endif
659 }
660
661 //=========================================================================
662 // Utility functions
663 //=========================================================================
664 namespace
665 {
666 // -----------------------------------------------------------------------
667 // Add a new identifier to the specified identifier map
668 // -----------------------------------------------------------------------
669 // Return value will be false if the name already existed
670 template<typename Value_t>
addNewNameData(NamePtrsMap<Value_t> & namePtrs,std::pair<NamePtr,NameData<Value_t>> & newName,bool isVar)671 bool addNewNameData(NamePtrsMap<Value_t>& namePtrs,
672 std::pair<NamePtr, NameData<Value_t> >& newName,
673 bool isVar)
674 {
675 typename NamePtrsMap<Value_t>::iterator nameIter =
676 namePtrs.lower_bound(newName.first);
677
678 if(nameIter != namePtrs.end() && newName.first == nameIter->first)
679 {
680 // redefining a var is not allowed.
681 if(isVar) return false;
682
683 // redefining other tokens is allowed, if the type stays the same.
684 if(nameIter->second.type != newName.second.type)
685 return false;
686
687 // update the data
688 nameIter->second = newName.second;
689 return true;
690 }
691
692 if(!isVar)
693 {
694 // Allocate a copy of the name (pointer stored in the map key)
695 // However, for VARIABLEs, the pointer points to VariableString,
696 // which is managed separately. Thusly, only done when !IsVar.
697 char* namebuf = new char[newName.first.nameLength];
698 memcpy(namebuf, newName.first.name, newName.first.nameLength);
699 newName.first.name = namebuf;
700 }
701
702 namePtrs.insert(nameIter, newName);
703 return true;
704 }
705 }
706
707
708 //=========================================================================
709 // Data struct implementation
710 //=========================================================================
711 template<typename Value_t>
Data()712 FunctionParserBase<Value_t>::Data::Data():
713 mReferenceCounter(1),
714 mDelimiterChar(0),
715 mParseErrorType(NO_FUNCTION_PARSED_YET),
716 mEvalErrorType(0),
717 mUseDegreeConversion(false),
718 mErrorLocation(0),
719 mVariablesAmount(0),
720 mStackSize(0)
721 {}
722
723 template<typename Value_t>
Data(const Data & rhs)724 FunctionParserBase<Value_t>::Data::Data(const Data& rhs):
725 mReferenceCounter(0),
726 mDelimiterChar(rhs.mDelimiterChar),
727 mParseErrorType(rhs.mParseErrorType),
728 mEvalErrorType(rhs.mEvalErrorType),
729 mUseDegreeConversion(rhs.mUseDegreeConversion),
730 mErrorLocation(rhs.mErrorLocation),
731 mVariablesAmount(rhs.mVariablesAmount),
732 mVariablesString(rhs.mVariablesString),
733 mNamePtrs(),
734 mFuncPtrs(rhs.mFuncPtrs),
735 mFuncParsers(rhs.mFuncParsers),
736 mByteCode(rhs.mByteCode),
737 mImmed(rhs.mImmed),
738 #ifndef FP_USE_THREAD_SAFE_EVAL
739 mStack(rhs.mStackSize),
740 #endif
741 mStackSize(rhs.mStackSize)
742 {
743 for(typename NamePtrsMap<Value_t>::const_iterator i = rhs.mNamePtrs.begin();
744 i != rhs.mNamePtrs.end();
745 ++i)
746 {
747 if(i->second.type == NameData<Value_t>::VARIABLE)
748 {
749 const std::size_t variableStringOffset =
750 i->first.name - rhs.mVariablesString.c_str();
751 std::pair<NamePtr, NameData<Value_t> > tmp
752 (NamePtr(&mVariablesString[variableStringOffset],
753 i->first.nameLength),
754 i->second);
755 mNamePtrs.insert(mNamePtrs.end(), tmp);
756 }
757 else
758 {
759 std::pair<NamePtr, NameData<Value_t> > tmp
760 (NamePtr(new char[i->first.nameLength], i->first.nameLength),
761 i->second );
762 memcpy(const_cast<char*>(tmp.first.name), i->first.name,
763 tmp.first.nameLength);
764 mNamePtrs.insert(mNamePtrs.end(), tmp);
765 }
766 }
767 }
768
769 template<typename Value_t>
~Data()770 FunctionParserBase<Value_t>::Data::~Data()
771 {
772 for(typename NamePtrsMap<Value_t>::iterator i = mNamePtrs.begin();
773 i != mNamePtrs.end();
774 ++i)
775 {
776 if(i->second.type != NameData<Value_t>::VARIABLE)
777 delete[] i->first.name;
778 }
779 }
780
781 template<typename Value_t>
incFuncWrapperRefCount(FunctionWrapper * wrapper)782 void FunctionParserBase<Value_t>::incFuncWrapperRefCount
783 (FunctionWrapper* wrapper)
784 {
785 ++wrapper->mReferenceCount;
786 }
787
788 template<typename Value_t>
decFuncWrapperRefCount(FunctionWrapper * wrapper)789 unsigned FunctionParserBase<Value_t>::decFuncWrapperRefCount
790 (FunctionWrapper* wrapper)
791 {
792 return --wrapper->mReferenceCount;
793 }
794
795 template<typename Value_t>
FuncWrapperPtrData()796 FunctionParserBase<Value_t>::Data::FuncWrapperPtrData::FuncWrapperPtrData():
797 mRawFuncPtr(0), mFuncWrapperPtr(0), mParams(0)
798 {}
799
800 template<typename Value_t>
~FuncWrapperPtrData()801 FunctionParserBase<Value_t>::Data::FuncWrapperPtrData::~FuncWrapperPtrData()
802 {
803 if(mFuncWrapperPtr &&
804 FunctionParserBase::decFuncWrapperRefCount(mFuncWrapperPtr) == 0)
805 delete mFuncWrapperPtr;
806 }
807
808 template<typename Value_t>
FuncWrapperPtrData(const FuncWrapperPtrData & rhs)809 FunctionParserBase<Value_t>::Data::FuncWrapperPtrData::FuncWrapperPtrData
810 (const FuncWrapperPtrData& rhs):
811 mRawFuncPtr(rhs.mRawFuncPtr),
812 mFuncWrapperPtr(rhs.mFuncWrapperPtr),
813 mParams(rhs.mParams)
814 {
815 if(mFuncWrapperPtr)
816 FunctionParserBase::incFuncWrapperRefCount(mFuncWrapperPtr);
817 }
818
819 template<typename Value_t>
820 typename FunctionParserBase<Value_t>::Data::FuncWrapperPtrData&
operator =(const FuncWrapperPtrData & rhs)821 FunctionParserBase<Value_t>::Data::FuncWrapperPtrData::operator=
822 (const FuncWrapperPtrData& rhs)
823 {
824 if(&rhs != this)
825 {
826 if(mFuncWrapperPtr &&
827 FunctionParserBase::decFuncWrapperRefCount(mFuncWrapperPtr) == 0)
828 delete mFuncWrapperPtr;
829 mRawFuncPtr = rhs.mRawFuncPtr;
830 mFuncWrapperPtr = rhs.mFuncWrapperPtr;
831 mParams = rhs.mParams;
832 if(mFuncWrapperPtr)
833 FunctionParserBase::incFuncWrapperRefCount(mFuncWrapperPtr);
834 }
835 return *this;
836 }
837
838
839 //=========================================================================
840 // FunctionParser constructors, destructor and assignment
841 //=========================================================================
842 template<typename Value_t>
FunctionParserBase()843 FunctionParserBase<Value_t>::FunctionParserBase():
844 mData(new Data),
845 mStackPtr(0)
846 {
847 }
848
849 template<typename Value_t>
~FunctionParserBase()850 FunctionParserBase<Value_t>::~FunctionParserBase()
851 {
852 if(--(mData->mReferenceCounter) == 0)
853 delete mData;
854 }
855
856 template<typename Value_t>
FunctionParserBase(const FunctionParserBase & cpy)857 FunctionParserBase<Value_t>::FunctionParserBase(const FunctionParserBase& cpy):
858 mData(cpy.mData),
859 mStackPtr(0)
860 {
861 ++(mData->mReferenceCounter);
862 }
863
864 template<typename Value_t>
865 FunctionParserBase<Value_t>&
operator =(const FunctionParserBase & cpy)866 FunctionParserBase<Value_t>::operator=(const FunctionParserBase& cpy)
867 {
868 if(mData != cpy.mData)
869 {
870 if(--(mData->mReferenceCounter) == 0) delete mData;
871
872 mData = cpy.mData;
873 ++(mData->mReferenceCounter);
874 }
875 return *this;
876 }
877
878 template<typename Value_t>
879 typename FunctionParserBase<Value_t>::Data*
getParserData()880 FunctionParserBase<Value_t>::getParserData()
881 {
882 return mData;
883 }
884
885 template<typename Value_t>
setDelimiterChar(char c)886 void FunctionParserBase<Value_t>::setDelimiterChar(char c)
887 {
888 mData->mDelimiterChar = c;
889 }
890
891
892 //---------------------------------------------------------------------------
893 // Copy-on-write method
894 //---------------------------------------------------------------------------
895 template<typename Value_t>
CopyOnWrite()896 void FunctionParserBase<Value_t>::CopyOnWrite()
897 {
898 if(mData->mReferenceCounter > 1)
899 {
900 Data* oldData = mData;
901 mData = new Data(*oldData);
902 --(oldData->mReferenceCounter);
903 mData->mReferenceCounter = 1;
904 }
905 }
906
907 template<typename Value_t>
CopyOnWrite2()908 void FunctionParserBase<Value_t>::CopyOnWrite2()
909 {
910 if(mData->mReferenceCounter > 1)
911 {
912 Data* oldData = mData;
913 mData = new Data(*oldData);
914 //--(oldData->mReferenceCounter);
915 //mData->mReferenceCounter = 1;
916 for (unsigned i=0; i<oldData->mFuncParsers.size(); i++)
917 {
918 mData->mFuncParsers[i].mParserPtr = new FunctionParserBase(*(oldData->mFuncParsers[i].mParserPtr));
919 mData->mFuncParsers[i].mParams = oldData->mFuncParsers[i].mParams;
920 }
921 mData->mByteCode = oldData->mByteCode;
922
923 }
924 }
925
926 template<typename Value_t>
ForceDeepCopy()927 void FunctionParserBase<Value_t>::ForceDeepCopy()
928 {
929 CopyOnWrite2();
930 }
931
932 //=========================================================================
933 // Epsilon
934 //=========================================================================
935 template<typename Value_t>
epsilon()936 Value_t FunctionParserBase<Value_t>::epsilon()
937 {
938 return Epsilon<Value_t>::value;
939 }
940
941 template<typename Value_t>
setEpsilon(Value_t value)942 void FunctionParserBase<Value_t>::setEpsilon(Value_t value)
943 {
944 Epsilon<Value_t>::value = value;
945 }
946
947 //=========================================================================
948 // User-defined identifier addition functions
949 //=========================================================================
950 template<typename Value_t>
AddConstant(const std::string & name,Value_t value)951 bool FunctionParserBase<Value_t>::AddConstant(const std::string& name, Value_t value)
952 {
953 if(!containsOnlyValidIdentifierChars<Value_t>(name)) return false;
954
955 CopyOnWrite();
956 std::pair<NamePtr, NameData<Value_t> > newName
957 (NamePtr(name.data(), unsigned(name.size())),
958 NameData<Value_t>(NameData<Value_t>::CONSTANT, value));
959
960 return addNewNameData(mData->mNamePtrs, newName, false);
961 }
962
963 template<typename Value_t>
AddUnit(const std::string & name,Value_t value)964 bool FunctionParserBase<Value_t>::AddUnit(const std::string& name,
965 Value_t value)
966 {
967 if(!containsOnlyValidIdentifierChars<Value_t>(name)) return false;
968
969 CopyOnWrite();
970 std::pair<NamePtr, NameData<Value_t> > newName
971 (NamePtr(name.data(), unsigned(name.size())),
972 NameData<Value_t>(NameData<Value_t>::UNIT, value));
973 return addNewNameData(mData->mNamePtrs, newName, false);
974 }
975
976 template<typename Value_t>
AddFunction(const std::string & name,FunctionPtr ptr,unsigned paramsAmount)977 bool FunctionParserBase<Value_t>::AddFunction
978 (const std::string& name, FunctionPtr ptr, unsigned paramsAmount)
979 {
980 if(!containsOnlyValidIdentifierChars<Value_t>(name)) return false;
981
982 CopyOnWrite();
983 std::pair<NamePtr, NameData<Value_t> > newName
984 (NamePtr(name.data(), unsigned(name.size())),
985 NameData<Value_t>(NameData<Value_t>::FUNC_PTR,
986 unsigned(mData->mFuncPtrs.size())));
987
988 const bool success = addNewNameData(mData->mNamePtrs, newName, false);
989 if(success)
990 {
991 mData->mFuncPtrs.push_back(typename Data::FuncWrapperPtrData());
992 mData->mFuncPtrs.back().mRawFuncPtr = ptr;
993 mData->mFuncPtrs.back().mParams = paramsAmount;
994 }
995 return success;
996 }
997
998 template<typename Value_t>
addFunctionWrapperPtr(const std::string & name,FunctionWrapper * wrapper,unsigned paramsAmount)999 bool FunctionParserBase<Value_t>::addFunctionWrapperPtr
1000 (const std::string& name, FunctionWrapper* wrapper, unsigned paramsAmount)
1001 {
1002 if(!AddFunction(name, FunctionPtr(0), paramsAmount)) return false;
1003 mData->mFuncPtrs.back().mFuncWrapperPtr = wrapper;
1004 return true;
1005 }
1006
1007 template<typename Value_t>
1008 typename FunctionParserBase<Value_t>::FunctionWrapper*
GetFunctionWrapper(const std::string & name)1009 FunctionParserBase<Value_t>::GetFunctionWrapper(const std::string& name)
1010 {
1011 CopyOnWrite();
1012 NamePtr namePtr(name.data(), unsigned(name.size()));
1013
1014 typename NamePtrsMap<Value_t>::iterator nameIter =
1015 mData->mNamePtrs.find(namePtr);
1016
1017 if(nameIter != mData->mNamePtrs.end() &&
1018 nameIter->second.type == NameData<Value_t>::FUNC_PTR)
1019 {
1020 return mData->mFuncPtrs[nameIter->second.index].mFuncWrapperPtr;
1021 }
1022 return 0;
1023 }
1024
1025 template<typename Value_t>
CheckRecursiveLinking(const FunctionParserBase * fp) const1026 bool FunctionParserBase<Value_t>::CheckRecursiveLinking
1027 (const FunctionParserBase* fp) const
1028 {
1029 if(fp == this) return true;
1030 for(unsigned i = 0; i < fp->mData->mFuncParsers.size(); ++i)
1031 if(CheckRecursiveLinking(fp->mData->mFuncParsers[i].mParserPtr))
1032 return true;
1033 return false;
1034 }
1035
1036 template<typename Value_t>
AddFunction(const std::string & name,FunctionParserBase & fp)1037 bool FunctionParserBase<Value_t>::AddFunction(const std::string& name,
1038 FunctionParserBase& fp)
1039 {
1040 if(!containsOnlyValidIdentifierChars<Value_t>(name) ||
1041 CheckRecursiveLinking(&fp))
1042 return false;
1043
1044 CopyOnWrite();
1045 std::pair<NamePtr, NameData<Value_t> > newName
1046 (NamePtr(name.data(), unsigned(name.size())),
1047 NameData<Value_t>(NameData<Value_t>::PARSER_PTR,
1048 unsigned(mData->mFuncParsers.size())));
1049
1050 const bool success = addNewNameData(mData->mNamePtrs, newName, false);
1051 if(success)
1052 {
1053 mData->mFuncParsers.push_back(typename Data::FuncParserPtrData());
1054 mData->mFuncParsers.back().mParserPtr = &fp;
1055 mData->mFuncParsers.back().mParams = fp.mData->mVariablesAmount;
1056 }
1057 return success;
1058 }
1059
1060 template<typename Value_t>
RemoveIdentifier(const std::string & name)1061 bool FunctionParserBase<Value_t>::RemoveIdentifier(const std::string& name)
1062 {
1063 CopyOnWrite();
1064
1065 NamePtr namePtr(name.data(), unsigned(name.size()));
1066
1067 typename NamePtrsMap<Value_t>::iterator nameIter =
1068 mData->mNamePtrs.find(namePtr);
1069
1070 if(nameIter != mData->mNamePtrs.end())
1071 {
1072 if(nameIter->second.type == NameData<Value_t>::VARIABLE)
1073 {
1074 // Illegal attempt to delete variables
1075 return false;
1076 }
1077 delete[] nameIter->first.name;
1078 mData->mNamePtrs.erase(nameIter);
1079 return true;
1080 }
1081 return false;
1082 }
1083
1084 //=========================================================================
1085 // Function parsing
1086 //=========================================================================
1087 namespace
1088 {
1089 // Error messages returned by ErrorMsg():
1090 const char* const ParseErrorMessage[]=
1091 {
1092 "Syntax error", // 0
1093 "Mismatched parenthesis", // 1
1094 "Missing ')'", // 2
1095 "Empty parentheses", // 3
1096 "Syntax error: Operator expected", // 4
1097 "Not enough memory", // 5
1098 "An unexpected error occurred. Please make a full bug report "
1099 "to the author", // 6
1100 "Syntax error in parameter 'Vars' given to "
1101 "FunctionParser::Parse()", // 7
1102 "Illegal number of parameters to function", // 8
1103 "Syntax error: Premature end of string", // 9
1104 "Syntax error: Expecting ( after function", // 10
1105 "Syntax error: Unknown identifier", // 11
1106 "(No function has been parsed yet)",
1107 ""
1108 };
1109
1110 template<typename Value_t>
1111 inline typename FunctionParserBase<Value_t>::ParseErrorType
noCommaError(char c)1112 noCommaError(char c)
1113 {
1114 return c == ')' ?
1115 FunctionParserBase<Value_t>::ILL_PARAMS_AMOUNT :
1116 FunctionParserBase<Value_t>::SYNTAX_ERROR;
1117 }
1118
1119 template<typename Value_t>
1120 inline typename FunctionParserBase<Value_t>::ParseErrorType
noParenthError(char c)1121 noParenthError(char c)
1122 {
1123 return c == ',' ?
1124 FunctionParserBase<Value_t>::ILL_PARAMS_AMOUNT :
1125 FunctionParserBase<Value_t>::MISSING_PARENTH;
1126 }
1127
1128 template<unsigned offset>
1129 struct IntLiteralMask
1130 {
1131 enum { mask =
1132 // ( 1UL << ('-'-offset)) |
1133 (0x3FFUL << ('0'-offset)) }; /* 0x3FF = 10 bits worth "1" */
1134 // Note: If you change fparser to support negative numbers parsing
1135 // (as opposed to parsing them as cNeg followed by literal),
1136 // enable the '-' line above, and change the offset value
1137 // in BeginsLiteral() to '-' instead of '.'.
1138 };
1139
1140 template<typename Value_t, unsigned offset>
1141 struct LiteralMask
1142 {
1143 enum { mask =
1144 ( 1UL << ('.'-offset)) |
1145 IntLiteralMask<offset>::mask };
1146 };
1147 #ifdef FP_SUPPORT_LONG_INT_TYPE
1148 template<unsigned offset>
1149 struct LiteralMask<long, offset>: public IntLiteralMask<offset>
1150 {
1151 };
1152 #endif
1153 #ifdef FP_SUPPORT_GMP_INT_TYPE
1154 template<unsigned offset>
1155 struct LiteralMask<GmpInt, offset>: public IntLiteralMask<offset>
1156 {
1157 };
1158 #endif
1159
1160 template<unsigned offset>
1161 struct SimpleSpaceMask
1162 {
1163 enum { mask =
1164 (1UL << ('\r'-offset)) |
1165 (1UL << ('\n'-offset)) |
1166 (1UL << ('\v'-offset)) |
1167 (1UL << ('\t'-offset)) |
1168 (1UL << (' ' -offset)) };
1169 };
1170
1171 template<typename Value_t>
BeginsLiteral(unsigned byte)1172 inline bool BeginsLiteral(unsigned byte)
1173 {
1174 enum { n = sizeof(unsigned long)>=8 ? 0 : '.' };
1175 byte -= n;
1176 if(byte > (unsigned char)('9'-n)) return false;
1177 unsigned long shifted = 1UL << byte;
1178 const unsigned long mask = LiteralMask<Value_t, n>::mask;
1179 return (mask & shifted) != 0;
1180 }
1181
1182 template<typename CharPtr>
SkipSpace(CharPtr & function)1183 inline void SkipSpace(CharPtr& function)
1184 {
1185 /*
1186 Space characters in unicode:
1187 U+0020 SPACE Depends on font, often adjusted (see below)
1188 U+00A0 NO-BREAK SPACE As a space, but often not adjusted
1189 U+2000 EN QUAD 1 en (= 1/2 em)
1190 U+2001 EM QUAD 1 em (nominally, the height of the font)
1191 U+2002 EN SPACE 1 en (= 1/2 em)
1192 U+2003 EM SPACE 1 em
1193 U+2004 THREE-PER-EM SPACE 1/3 em
1194 U+2005 FOUR-PER-EM SPACE 1/4 em
1195 U+2006 SIX-PER-EM SPACE 1/6 em
1196 U+2007 FIGURE SPACE Tabular width, the width of digits
1197 U+2008 PUNCTUATION SPACE The width of a period .
1198 U+2009 THIN SPACE 1/5 em (or sometimes 1/6 em)
1199 U+200A HAIR SPACE Narrower than THIN SPACE
1200 U+200B ZERO WIDTH SPACE Nominally no width, but may expand
1201 U+202F NARROW NO-BREAK SPACE Narrower than NO-BREAK SPACE (or SPACE)
1202 U+205F MEDIUM MATHEMATICAL SPACE 4/18 em
1203 U+3000 IDEOGRAPHIC SPACE The width of ideographic (CJK) characters.
1204 Also:
1205 U+000A \n
1206 U+000D \r
1207 U+0009 \t
1208 U+000B \v
1209 As UTF-8 sequences:
1210 09
1211 0A
1212 0B
1213 0D
1214 20
1215 C2 A0
1216 E2 80 80-8B
1217 E2 80 AF
1218 E2 81 9F
1219 E3 80 80
1220 */
1221 while(true)
1222 {
1223 enum { n = sizeof(unsigned long)>=8 ? 0 : '\t' };
1224 typedef signed char schar;
1225 unsigned byte = (unsigned char)*function;
1226 byte -= n;
1227 // ^Note: values smaller than n intentionally become
1228 // big values here due to integer wrap. The
1229 // comparison below thus excludes them, making
1230 // the effective range 0x09..0x20 (32-bit)
1231 // or 0x00..0x20 (64-bit) within the if-clause.
1232 if(byte <= (unsigned char)(' '-n))
1233 {
1234 unsigned long shifted = 1UL << byte;
1235 const unsigned long mask = SimpleSpaceMask<n>::mask;
1236 if(mask & shifted)
1237 { ++function; continue; } // \r, \n, \t, \v and space
1238 break;
1239 }
1240 if(likely(byte < 0xC2-n)) break;
1241
1242 if(byte == 0xC2-n && function[1] == char(0xA0))
1243 { function += 2; continue; } // U+00A0
1244 if(byte == 0xE3-n &&
1245 function[1] == char(0x80) && function[2] == char(0x80))
1246 { function += 3; continue; } // U+3000
1247 if(byte == 0xE2-n)
1248 {
1249 if(function[1] == char(0x81))
1250 {
1251 if(function[2] != char(0x9F)) break;
1252 function += 3; // U+205F
1253 continue;
1254 }
1255 if(function[1] == char(0x80))
1256 if(function[2] == char(0xAF) || // U+202F
1257 schar(function[2]) <= schar(0x8B) // U+2000..U+200B
1258 )
1259 {
1260 function += 3;
1261 continue;
1262 }
1263 }
1264 break;
1265 } // while(true)
1266 } // SkipSpace(CharPtr& function)
1267 }
1268
1269 // ---------------------------------------------------------------------------
1270 // Return parse error message
1271 // ---------------------------------------------------------------------------
1272 template<typename Value_t>
ErrorMsg() const1273 const char* FunctionParserBase<Value_t>::ErrorMsg() const
1274 {
1275 return ParseErrorMessage[mData->mParseErrorType];
1276 }
1277
1278 template<typename Value_t>
1279 typename FunctionParserBase<Value_t>::ParseErrorType
GetParseErrorType() const1280 FunctionParserBase<Value_t>::GetParseErrorType() const
1281 {
1282 return mData->mParseErrorType;
1283 }
1284
1285 template<typename Value_t>
EvalError() const1286 int FunctionParserBase<Value_t>::EvalError() const
1287 {
1288 return mData->mEvalErrorType;
1289 }
1290
1291 // ---------------------------------------------------------------------------
1292 // Parse variables
1293 // ---------------------------------------------------------------------------
1294 template<typename Value_t>
ParseVariables(const std::string & inputVarString)1295 bool FunctionParserBase<Value_t>::ParseVariables
1296 (const std::string& inputVarString)
1297 {
1298 if(mData->mVariablesString == inputVarString) return true;
1299
1300 /* Delete existing variables from mNamePtrs */
1301 for(typename NamePtrsMap<Value_t>::iterator i =
1302 mData->mNamePtrs.begin();
1303 i != mData->mNamePtrs.end(); )
1304 {
1305 if(i->second.type == NameData<Value_t>::VARIABLE)
1306 {
1307 typename NamePtrsMap<Value_t>::iterator j (i);
1308 ++i;
1309 mData->mNamePtrs.erase(j);
1310 }
1311 else ++i;
1312 }
1313 mData->mVariablesString = inputVarString;
1314 const std::string& vars = mData->mVariablesString;
1315 const unsigned len = unsigned(vars.size());
1316 unsigned varNumber = VarBegin;
1317 const char* beginPtr = vars.c_str();
1318 const char* finalPtr = beginPtr + len;
1319 while(beginPtr < finalPtr)
1320 {
1321 SkipSpace(beginPtr);
1322 unsigned nameLength = readIdentifier<Value_t>(beginPtr);
1323 if(nameLength == 0 || (nameLength & 0x80000000U)) return false;
1324 const char* endPtr = beginPtr + nameLength;
1325 SkipSpace(endPtr);
1326 if(endPtr != finalPtr && *endPtr != ',') return false;
1327 std::pair<NamePtr, NameData<Value_t> > newName
1328 (NamePtr(beginPtr, nameLength),
1329 NameData<Value_t>(NameData<Value_t>::VARIABLE, varNumber++));
1330 if(!addNewNameData(mData->mNamePtrs, newName, true))
1331 {
1332 return false;
1333 }
1334 beginPtr = endPtr + 1;
1335 }
1336 mData->mVariablesAmount = varNumber - VarBegin;
1337 return true;
1338 }
1339
1340 // ---------------------------------------------------------------------------
1341 // Parse() public interface functions
1342 // ---------------------------------------------------------------------------
1343 template<typename Value_t>
Parse(const char * Function,const std::string & Vars,bool useDegrees)1344 int FunctionParserBase<Value_t>::Parse(const char* Function,
1345 const std::string& Vars,
1346 bool useDegrees)
1347 {
1348 CopyOnWrite();
1349
1350 if(!ParseVariables(Vars))
1351 {
1352 mData->mParseErrorType = INVALID_VARS;
1353 return int(strlen(Function));
1354 }
1355
1356 return ParseFunction(Function, useDegrees);
1357 }
1358
1359 template<typename Value_t>
Parse(const std::string & Function,const std::string & Vars,bool useDegrees)1360 int FunctionParserBase<Value_t>::Parse(const std::string& Function,
1361 const std::string& Vars,
1362 bool useDegrees)
1363 {
1364 CopyOnWrite();
1365
1366 if(!ParseVariables(Vars))
1367 {
1368 mData->mParseErrorType = INVALID_VARS;
1369 return int(Function.size());
1370 }
1371
1372 return ParseFunction(Function.c_str(), useDegrees);
1373 }
1374
1375
1376 // ---------------------------------------------------------------------------
1377 // Main parsing function
1378 // ---------------------------------------------------------------------------
1379 template<typename Value_t>
ParseFunction(const char * function,bool useDegrees)1380 int FunctionParserBase<Value_t>::ParseFunction(const char* function,
1381 bool useDegrees)
1382 {
1383 mData->mUseDegreeConversion = useDegrees;
1384 mData->mParseErrorType = FP_NO_ERROR;
1385
1386 mData->mInlineVarNames.clear();
1387 mData->mByteCode.clear(); mData->mByteCode.reserve(128);
1388 mData->mImmed.clear(); mData->mImmed.reserve(128);
1389 mData->mStackSize = mStackPtr = 0;
1390
1391 mData->mHasByteCodeFlags = false;
1392
1393 const char* ptr = Compile(function);
1394 mData->mInlineVarNames.clear();
1395
1396 if(mData->mHasByteCodeFlags)
1397 {
1398 for(unsigned i = unsigned(mData->mByteCode.size()); i-- > 0; )
1399 mData->mByteCode[i] &= ~FP_ParamGuardMask;
1400 }
1401
1402 if(mData->mParseErrorType != FP_NO_ERROR)
1403 return int(mData->mErrorLocation - function);
1404
1405 assert(ptr); // Should never be null at this point. It's a bug otherwise.
1406 if(*ptr)
1407 {
1408 if(mData->mDelimiterChar == 0 || *ptr != mData->mDelimiterChar)
1409 mData->mParseErrorType = EXPECT_OPERATOR;
1410 return int(ptr - function);
1411 }
1412
1413 #ifndef FP_USE_THREAD_SAFE_EVAL
1414 mData->mStack.resize(mData->mStackSize);
1415 //mData->mStacki.resize(64*mData->mStackSize);
1416 #endif
1417
1418 return -1;
1419 }
1420
1421
1422 //=========================================================================
1423 // Parsing and bytecode compiling functions
1424 //=========================================================================
1425 template<typename Value_t>
SetErrorType(ParseErrorType t,const char * pos)1426 inline const char* FunctionParserBase<Value_t>::SetErrorType(ParseErrorType t,
1427 const char* pos)
1428 {
1429 mData->mParseErrorType = t;
1430 mData->mErrorLocation = pos;
1431 return 0;
1432 }
1433
1434 template<typename Value_t>
incStackPtr()1435 inline void FunctionParserBase<Value_t>::incStackPtr()
1436 {
1437 if(++mStackPtr > mData->mStackSize) ++(mData->mStackSize);
1438 }
1439
1440 namespace
1441 {
1442 const unsigned char powi_factor_table[128] =
1443 {
1444 0,1,0,0,0,0,0,0, 0, 0,0,0,0,0,0,3,/* 0 - 15 */
1445 0,0,0,0,0,0,0,0, 0, 5,0,3,0,0,3,0,/* 16 - 31 */
1446 0,0,0,0,0,0,0,3, 0, 0,0,0,0,5,0,0,/* 32 - 47 */
1447 0,0,5,3,0,0,3,5, 0, 3,0,0,3,0,0,3,/* 48 - 63 */
1448 0,0,0,0,0,0,0,0, 0, 0,0,3,0,0,3,0,/* 64 - 79 */
1449 0,9,0,0,0,5,0,3, 0, 0,5,7,0,0,0,5,/* 80 - 95 */
1450 0,0,0,3,5,0,3,0, 0, 3,0,0,3,0,5,3,/* 96 - 111 */
1451 0,0,3,5,0,9,0,7, 3,11,0,3,0,5,3,0,/* 112 - 127 */
1452 };
1453
get_powi_factor(long abs_int_exponent)1454 inline int get_powi_factor(long abs_int_exponent)
1455 {
1456 if(abs_int_exponent >= int(sizeof(powi_factor_table))) return 0;
1457 return powi_factor_table[abs_int_exponent];
1458 }
1459
1460 #if 0
1461 int EstimatePowiComplexity(int abs_int_exponent)
1462 {
1463 int cost = 0;
1464 while(abs_int_exponent > 1)
1465 {
1466 int factor = get_powi_factor(abs_int_exponent);
1467 if(factor)
1468 {
1469 cost += EstimatePowiComplexity(factor);
1470 abs_int_exponent /= factor;
1471 continue;
1472 }
1473 if(!(abs_int_exponent & 1))
1474 {
1475 abs_int_exponent /= 2;
1476 cost += 3; // sqr
1477 }
1478 else
1479 {
1480 cost += 4; // dup+mul
1481 abs_int_exponent -= 1;
1482 }
1483 }
1484 return cost;
1485 }
1486 #endif
1487
IsEligibleIntPowiExponent(long int_exponent)1488 bool IsEligibleIntPowiExponent(long int_exponent)
1489 {
1490 if(int_exponent == 0) return false;
1491 long abs_int_exponent = int_exponent;
1492 #if 0
1493 int cost = 0;
1494
1495 if(abs_int_exponent < 0)
1496 {
1497 cost += 11;
1498 abs_int_exponent = -abs_int_exponent;
1499 }
1500
1501 cost += EstimatePowiComplexity(abs_int_exponent);
1502
1503 return cost < (10*3 + 4*4);
1504 #else
1505 if(abs_int_exponent < 0) abs_int_exponent = -abs_int_exponent;
1506
1507 return (abs_int_exponent >= 1)
1508 && (abs_int_exponent <= 46 ||
1509 (abs_int_exponent <= 1024 &&
1510 (abs_int_exponent & (abs_int_exponent - 1)) == 0));
1511 #endif
1512 }
1513
1514 /* Needed by fp_opcode_add.inc if tracing is enabled */
1515 template<typename Value_t>
findName(const NamePtrsMap<Value_t> & nameMap,unsigned index,typename NameData<Value_t>::DataType type)1516 std::string findName(const NamePtrsMap<Value_t>& nameMap,
1517 unsigned index,
1518 typename NameData<Value_t>::DataType type)
1519 {
1520 for(typename NamePtrsMap<Value_t>::const_iterator
1521 iter = nameMap.begin();
1522 iter != nameMap.end();
1523 ++iter)
1524 {
1525 if(iter->second.type == type && iter->second.index == index)
1526 return std::string(iter->first.name,
1527 iter->first.name + iter->first.nameLength);
1528 }
1529 return "?";
1530 }
1531 }
1532
1533 template<typename Value_t>
AddImmedOpcode(Value_t value)1534 inline void FunctionParserBase<Value_t>::AddImmedOpcode(Value_t value)
1535 {
1536 mData->mImmed.push_back(value);
1537 mData->mByteCode.push_back(cImmed);
1538 }
1539
1540 template<typename Value_t>
CompilePowi(long abs_int_exponent)1541 inline void FunctionParserBase<Value_t>::CompilePowi(long abs_int_exponent)
1542 {
1543 int num_muls=0;
1544 while(abs_int_exponent > 1)
1545 {
1546 long factor = get_powi_factor(abs_int_exponent);
1547 if(factor)
1548 {
1549 CompilePowi(factor);
1550 abs_int_exponent /= factor;
1551 continue;
1552 }
1553 if(!(abs_int_exponent & 1))
1554 {
1555 abs_int_exponent /= 2;
1556 mData->mByteCode.push_back(cSqr);
1557 // ^ Don't put AddFunctionOpcode here,
1558 // it would slow down a great deal.
1559 }
1560 else
1561 {
1562 mData->mByteCode.push_back(cDup);
1563 incStackPtr();
1564 abs_int_exponent -= 1;
1565 ++num_muls;
1566 }
1567 }
1568 if(num_muls > 0)
1569 {
1570 mData->mByteCode.resize(mData->mByteCode.size()+num_muls, cMul);
1571 mStackPtr -= num_muls;
1572 }
1573 }
1574
1575 template<typename Value_t>
TryCompilePowi(Value_t original_immed)1576 inline bool FunctionParserBase<Value_t>::TryCompilePowi(Value_t original_immed)
1577 {
1578 Value_t changed_immed = original_immed;
1579 for(int sqrt_count=0; /**/; ++sqrt_count)
1580 {
1581 long int_exponent = makeLongInteger(changed_immed);
1582 if(isLongInteger(changed_immed) &&
1583 IsEligibleIntPowiExponent(int_exponent))
1584 {
1585 long abs_int_exponent = int_exponent;
1586 if(abs_int_exponent < 0)
1587 abs_int_exponent = -abs_int_exponent;
1588
1589 mData->mImmed.pop_back(); mData->mByteCode.pop_back();
1590 --mStackPtr;
1591 // ^Though the above is accounted for by the procedure
1592 // that generates cPow, we need it for correct cFetch
1593 // indexes in CompilePowi().
1594
1595 while(sqrt_count > 0)
1596 {
1597 int opcode = cSqrt;
1598 if(sqrt_count == 1 && int_exponent < 0)
1599 {
1600 opcode = cRSqrt;
1601 int_exponent = -int_exponent;
1602 }
1603 mData->mByteCode.push_back(opcode);
1604 --sqrt_count;
1605 }
1606 if((abs_int_exponent & 1) == 0)
1607 {
1608 // This special rule fixes the optimization
1609 // shortcoming of (-x)^2 with minimal overhead.
1610 AddFunctionOpcode(cSqr);
1611 abs_int_exponent >>= 1;
1612 }
1613 CompilePowi(abs_int_exponent);
1614 if(int_exponent < 0) mData->mByteCode.push_back(cInv);
1615 ++mStackPtr; // Needed because cPow adding will assume this.
1616 return true;
1617 }
1618 if(sqrt_count >= 4) break;
1619 changed_immed += changed_immed;
1620 }
1621
1622 // When we don't know whether x >= 0, we still know that
1623 // x^y can be safely converted into exp(y * log(x))
1624 // when y is _not_ integer, because we know that x >= 0.
1625 // Otherwise either expression will give a NaN.
1626 if(/*!isInteger(original_immed) ||*/
1627 IsNeverNegativeValueOpcode(mData->mByteCode[mData->mByteCode.size()-2]))
1628 {
1629 mData->mImmed.pop_back();
1630 mData->mByteCode.pop_back();
1631 //--mStackPtr; - accounted for by the procedure that generates cPow
1632 AddFunctionOpcode(cLog);
1633 AddImmedOpcode(original_immed);
1634 //incStackPtr(); - this and the next are redundant because...
1635 AddFunctionOpcode(cMul);
1636 //--mStackPtr; - ...because the cImmed was popped earlier.
1637 AddFunctionOpcode(cExp);
1638 return true;
1639 }
1640 return false;
1641 }
1642
1643 //#include "fpoptimizer/opcodename.hh"
1644 // ^ needed only if FP_TRACE_BYTECODE_OPTIMIZATION() is used
1645
1646 template<typename Value_t>
AddFunctionOpcode(unsigned opcode)1647 inline void FunctionParserBase<Value_t>::AddFunctionOpcode(unsigned opcode)
1648 {
1649 #define FP_FLOAT_VERSION 1
1650 #define FP_COMPLEX_VERSION 0
1651 #include "extrasrc/fp_opcode_add.inc"
1652 #undef FP_COMPLEX_VERSION
1653 #undef FP_FLOAT_VERSION
1654 }
1655
1656 #ifdef FP_SUPPORT_LONG_INT_TYPE
1657 template<>
AddFunctionOpcode(unsigned opcode)1658 inline void FunctionParserBase<long>::AddFunctionOpcode(unsigned opcode)
1659 {
1660 typedef long Value_t;
1661 #define FP_FLOAT_VERSION 0
1662 #define FP_COMPLEX_VERSION 0
1663 #include "extrasrc/fp_opcode_add.inc"
1664 #undef FP_COMPLEX_VERSION
1665 #undef FP_FLOAT_VERSION
1666 }
1667 #endif
1668
1669 #ifdef FP_SUPPORT_GMP_INT_TYPE
1670 template<>
AddFunctionOpcode(unsigned opcode)1671 inline void FunctionParserBase<GmpInt>::AddFunctionOpcode(unsigned opcode)
1672 {
1673 typedef GmpInt Value_t;
1674 #define FP_FLOAT_VERSION 0
1675 #define FP_COMPLEX_VERSION 0
1676 #include "extrasrc/fp_opcode_add.inc"
1677 #undef FP_COMPLEX_VERSION
1678 #undef FP_FLOAT_VERSION
1679 }
1680 #endif
1681
1682 #ifdef FP_SUPPORT_COMPLEX_DOUBLE_TYPE
1683 template<>
AddFunctionOpcode(unsigned opcode)1684 inline void FunctionParserBase<std::complex<double> >::AddFunctionOpcode(unsigned opcode)
1685 {
1686 typedef std::complex<double> Value_t;
1687 #define FP_FLOAT_VERSION 1
1688 #define FP_COMPLEX_VERSION 1
1689 #include "extrasrc/fp_opcode_add.inc"
1690 #undef FP_COMPLEX_VERSION
1691 #undef FP_FLOAT_VERSION
1692 }
1693 #endif
1694
1695 #ifdef FP_SUPPORT_COMPLEX_FLOAT_TYPE
1696 template<>
AddFunctionOpcode(unsigned opcode)1697 inline void FunctionParserBase<std::complex<float> >::AddFunctionOpcode(unsigned opcode)
1698 {
1699 typedef std::complex<float> Value_t;
1700 #define FP_FLOAT_VERSION 1
1701 #define FP_COMPLEX_VERSION 1
1702 #include "extrasrc/fp_opcode_add.inc"
1703 #undef FP_COMPLEX_VERSION
1704 #undef FP_FLOAT_VERSION
1705 }
1706 #endif
1707
1708 #ifdef FP_SUPPORT_COMPLEX_LONG_DOUBLE_TYPE
1709 template<>
AddFunctionOpcode(unsigned opcode)1710 inline void FunctionParserBase<std::complex<long double> >::AddFunctionOpcode(unsigned opcode)
1711 {
1712 typedef std::complex<long double> Value_t;
1713 #define FP_FLOAT_VERSION 1
1714 #define FP_COMPLEX_VERSION 1
1715 #include "extrasrc/fp_opcode_add.inc"
1716 #undef FP_COMPLEX_VERSION
1717 #undef FP_FLOAT_VERSION
1718 }
1719 #endif
1720
1721 template<typename Value_t>
1722 unsigned
ParseIdentifier(const char * function)1723 FunctionParserBase<Value_t>::ParseIdentifier(const char* function)
1724 {
1725 return readIdentifier<Value_t>(function);
1726 }
1727
1728 template<typename Value_t>
1729 std::pair<const char*, Value_t>
ParseLiteral(const char * function)1730 FunctionParserBase<Value_t>::ParseLiteral(const char* function)
1731 {
1732 char* endptr;
1733 #if 0 /* Profile the hex literal parser */
1734 if(function[0]=='0' && function[1]=='x')
1735 {
1736 // Parse hexadecimal literal if fp_parseLiteral didn't already
1737 Value_t val = parseHexLiteral<Value_t>(function+2, &endptr);
1738 if(endptr == function+2)
1739 return std::pair<const char*,Value_t> (function, Value_t());
1740 return std::pair<const char*, Value_t> (endptr, val);
1741 }
1742 #endif
1743 Value_t val = fp_parseLiteral<Value_t>(function, &endptr);
1744
1745 if(endptr == function+1 && function[0] == '0' && function[1] == 'x')
1746 {
1747 // Parse hexadecimal literal if fp_parseLiteral didn't already
1748 val = parseHexLiteral<Value_t>(function+2, &endptr);
1749 if(endptr == function+2)
1750 return std::pair<const char*,Value_t> (function, Value_t());
1751 }
1752 else if(endptr == function)
1753 return std::pair<const char*,Value_t> (function, Value_t());
1754
1755 return std::pair<const char*,Value_t> (endptr, val);
1756 }
1757
1758 #ifdef FP_SUPPORT_MPFR_FLOAT_TYPE
1759 template<>
1760 std::pair<const char*, MpfrFloat>
ParseLiteral(const char * function)1761 FunctionParserBase<MpfrFloat>::ParseLiteral(const char* function)
1762 {
1763 char* endPtr;
1764 const MpfrFloat val = MpfrFloat::parseString(function, &endPtr);
1765 if(endPtr == function)
1766 return std::pair<const char*,MpfrFloat> (function, MpfrFloat());
1767 return std::pair<const char*,MpfrFloat> (endPtr, val);
1768 }
1769 #endif
1770
1771 #ifdef FP_SUPPORT_GMP_INT_TYPE
1772 template<>
1773 std::pair<const char*, GmpInt>
ParseLiteral(const char * function)1774 FunctionParserBase<GmpInt>::ParseLiteral(const char* function)
1775 {
1776 char* endPtr;
1777 const GmpInt val = GmpInt::parseString(function, &endPtr);
1778 if(endPtr == function)
1779 return std::pair<const char*,GmpInt> (function, GmpInt());
1780 return std::pair<const char*,GmpInt> (endPtr, val);
1781 }
1782 #endif
1783
1784
1785 template<typename Value_t>
1786 inline const char*
CompileLiteral(const char * function)1787 FunctionParserBase<Value_t>::CompileLiteral(const char* function)
1788 {
1789 std::pair<const char*, Value_t> result = ParseLiteral(function);
1790
1791 if(result.first == function)
1792 return SetErrorType(SYNTAX_ERROR, result.first);
1793
1794 AddImmedOpcode(result.second);
1795 incStackPtr();
1796 SkipSpace(result.first);
1797 return result.first;
1798 }
1799
1800 template<typename Value_t>
CompileIf(const char * function)1801 const char* FunctionParserBase<Value_t>::CompileIf(const char* function)
1802 {
1803 if(*function != '(') return SetErrorType(EXPECT_PARENTH_FUNC, function);
1804
1805 function = CompileExpression(function+1);
1806 if(!function) return 0;
1807 if(*function != ',')
1808 return SetErrorType(noCommaError<Value_t>(*function), function);
1809
1810 OPCODE opcode = cIf;
1811 if(mData->mByteCode.back() == cNotNot) mData->mByteCode.pop_back();
1812 if(IsNeverNegativeValueOpcode(mData->mByteCode.back()))
1813 {
1814 // If we know that the condition to be tested is always
1815 // a positive value (such as when produced by "x<y"),
1816 // we can use the faster opcode to evaluate it.
1817 // cIf tests whether fabs(cond) >= 0.5,
1818 // cAbsIf simply tests whether cond >= 0.5.
1819 opcode = cAbsIf;
1820 }
1821
1822 mData->mByteCode.push_back(opcode);
1823 const unsigned curByteCodeSize = unsigned(mData->mByteCode.size());
1824 PushOpcodeParam<false>(0); // Jump index; to be set later
1825 PushOpcodeParam<true> (0); // Immed jump index; to be set later
1826
1827 --mStackPtr;
1828
1829 function = CompileExpression(function + 1);
1830 if(!function) return 0;
1831 if(*function != ',')
1832 return SetErrorType(noCommaError<Value_t>(*function), function);
1833
1834 mData->mByteCode.push_back(cJump);
1835 const unsigned curByteCodeSize2 = unsigned(mData->mByteCode.size());
1836 const unsigned curImmedSize2 = unsigned(mData->mImmed.size());
1837 PushOpcodeParam<false>(0); // Jump index; to be set later
1838 PushOpcodeParam<true> (0); // Immed jump index; to be set later
1839
1840 --mStackPtr;
1841
1842 function = CompileExpression(function + 1);
1843 if(!function) return 0;
1844 if(*function != ')')
1845 return SetErrorType(noParenthError<Value_t>(*function), function);
1846
1847 PutOpcodeParamAt<true> ( mData->mByteCode.back(), unsigned(mData->mByteCode.size()-1) );
1848 // ^Necessary for guarding against if(x,1,2)+1 being changed
1849 // into if(x,1,3) by fp_opcode_add.inc
1850
1851 // Set jump indices
1852 PutOpcodeParamAt<false>( curByteCodeSize2+1, curByteCodeSize );
1853 PutOpcodeParamAt<false>( curImmedSize2, curByteCodeSize+1 );
1854 PutOpcodeParamAt<false>( unsigned(mData->mByteCode.size())-1, curByteCodeSize2);
1855 PutOpcodeParamAt<false>( unsigned(mData->mImmed.size()), curByteCodeSize2+1);
1856
1857 ++function;
1858 SkipSpace(function);
1859 return function;
1860 }
1861
1862 template<typename Value_t>
CompileFunctionParams(const char * function,unsigned requiredParams)1863 const char* FunctionParserBase<Value_t>::CompileFunctionParams
1864 (const char* function, unsigned requiredParams)
1865 {
1866 if(*function != '(') return SetErrorType(EXPECT_PARENTH_FUNC, function);
1867
1868 if(requiredParams > 0)
1869 {
1870 const char* function_end = CompileExpression(function+1);
1871 if(!function_end)
1872 {
1873 // If an error occurred, verify whether it was caused by ()
1874 ++function;
1875 SkipSpace(function);
1876 if(*function == ')')
1877 return SetErrorType(ILL_PARAMS_AMOUNT, function);
1878 // Not caused by (), use the error message given by CompileExpression()
1879 return 0;
1880 }
1881 function = function_end;
1882
1883 for(unsigned i = 1; i < requiredParams; ++i)
1884 {
1885 if(*function != ',')
1886 return SetErrorType(noCommaError<Value_t>(*function), function);
1887
1888 function = CompileExpression(function+1);
1889 if(!function) return 0;
1890 }
1891 // No need for incStackPtr() because each parse parameter calls it
1892 mStackPtr -= requiredParams-1;
1893 }
1894 else
1895 {
1896 incStackPtr(); // return value of function is pushed onto the stack
1897 ++function;
1898 SkipSpace(function);
1899 }
1900
1901 if(*function != ')')
1902 return SetErrorType(noParenthError<Value_t>(*function), function);
1903 ++function;
1904 SkipSpace(function);
1905 return function;
1906 }
1907
1908 template<typename Value_t>
CompileElement(const char * function)1909 const char* FunctionParserBase<Value_t>::CompileElement(const char* function)
1910 {
1911 if(BeginsLiteral<Value_t>( (unsigned char) *function))
1912 return CompileLiteral(function);
1913
1914 unsigned nameLength = readIdentifier<Value_t>(function);
1915 if(nameLength == 0)
1916 {
1917 // No identifier found
1918 if(*function == '(') return CompileParenthesis(function);
1919 if(*function == ')') return SetErrorType(MISM_PARENTH, function);
1920 return SetErrorType(SYNTAX_ERROR, function);
1921 }
1922
1923 // Function, variable or constant
1924 if(nameLength & 0x80000000U) // Function
1925 {
1926 OPCODE func_opcode = OPCODE( (nameLength >> 16) & 0x7FFF );
1927 return CompileFunction(function + (nameLength & 0xFFFF), func_opcode);
1928 }
1929
1930 NamePtr name(function, nameLength);
1931 const char* endPtr = function + nameLength;
1932 SkipSpace(endPtr);
1933
1934 typename NamePtrsMap<Value_t>::iterator nameIter =
1935 mData->mNamePtrs.find(name);
1936 if(nameIter == mData->mNamePtrs.end())
1937 {
1938 // Check if it's an inline variable:
1939 for(typename Data::InlineVarNamesContainer::reverse_iterator iter =
1940 mData->mInlineVarNames.rbegin();
1941 iter != mData->mInlineVarNames.rend();
1942 ++iter)
1943 {
1944 if(name == iter->mName)
1945 {
1946 if( iter->mFetchIndex+1 == mStackPtr)
1947 {
1948 mData->mByteCode.push_back(cDup);
1949 }
1950 else
1951 {
1952 mData->mByteCode.push_back(cFetch);
1953 PushOpcodeParam<true>(iter->mFetchIndex);
1954 }
1955 incStackPtr();
1956 return endPtr;
1957 }
1958 }
1959
1960 return SetErrorType(UNKNOWN_IDENTIFIER, function);
1961 }
1962
1963 const NameData<Value_t>* nameData = &nameIter->second;
1964 switch(nameData->type)
1965 {
1966 case NameData<Value_t>::VARIABLE: // is variable
1967 if(unlikely(!mData->mByteCode.empty() &&
1968 mData->mByteCode.back() == nameData->index))
1969 mData->mByteCode.push_back(cDup);
1970 else
1971 mData->mByteCode.push_back(nameData->index);
1972 incStackPtr();
1973 return endPtr;
1974
1975 case NameData<Value_t>::CONSTANT: // is constant
1976 AddImmedOpcode(nameData->value);
1977 incStackPtr();
1978 return endPtr;
1979
1980 case NameData<Value_t>::UNIT: // is unit (error if appears here)
1981 break;
1982
1983 case NameData<Value_t>::FUNC_PTR: // is C++ function
1984 function = CompileFunctionParams
1985 (endPtr, mData->mFuncPtrs[nameData->index].mParams);
1986 //if(!function) return 0;
1987 mData->mByteCode.push_back(cFCall);
1988 PushOpcodeParam<true>(nameData->index);
1989 return function;
1990
1991 case NameData<Value_t>::PARSER_PTR: // is FunctionParser
1992 function = CompileFunctionParams
1993 (endPtr, mData->mFuncParsers[nameData->index].mParams);
1994 //if(!function) return 0;
1995 mData->mByteCode.push_back(cPCall);
1996 PushOpcodeParam<true>(nameData->index);
1997 return function;
1998 }
1999
2000 // When it's an unit (or unrecognized type):
2001 return SetErrorType(SYNTAX_ERROR, function);
2002 }
2003
2004 template<typename Value_t>
CompileFunction(const char * function,unsigned func_opcode)2005 inline const char* FunctionParserBase<Value_t>::CompileFunction
2006 (const char* function, unsigned func_opcode)
2007 {
2008 SkipSpace(function);
2009 const FuncDefinition& funcDef = Functions[func_opcode];
2010
2011 if(func_opcode == cIf) // "if" is a special case
2012 return CompileIf(function);
2013
2014 unsigned requiredParams = funcDef.params;
2015
2016 function = CompileFunctionParams(function, requiredParams);
2017 if(!function) return 0;
2018
2019 if(mData->mUseDegreeConversion)
2020 {
2021 if(funcDef.flags & FuncDefinition::AngleIn)
2022 AddFunctionOpcode(cRad);
2023
2024 AddFunctionOpcode(func_opcode);
2025
2026 if(funcDef.flags & FuncDefinition::AngleOut)
2027 AddFunctionOpcode(cDeg);
2028 }
2029 else
2030 {
2031 AddFunctionOpcode(func_opcode);
2032 }
2033 return function;
2034 }
2035
2036 template<typename Value_t>
2037 inline const char*
CompileParenthesis(const char * function)2038 FunctionParserBase<Value_t>::CompileParenthesis(const char* function)
2039 {
2040 ++function; // Skip '('
2041
2042 SkipSpace(function);
2043 if(*function == ')') return SetErrorType(EMPTY_PARENTH, function);
2044 function = CompileExpression(function);
2045 if(!function) return 0;
2046
2047 if(*function != ')') return SetErrorType(MISSING_PARENTH, function);
2048 ++function; // Skip ')'
2049
2050 SkipSpace(function);
2051 return function;
2052 }
2053
2054 template<typename Value_t>
2055 const char*
CompilePossibleUnit(const char * function)2056 FunctionParserBase<Value_t>::CompilePossibleUnit(const char* function)
2057 {
2058 unsigned nameLength = readIdentifier<Value_t>(function);
2059 if(nameLength & 0x80000000U) return function; // built-in function name
2060 if(nameLength != 0)
2061 {
2062 NamePtr name(function, nameLength);
2063
2064 typename NamePtrsMap<Value_t>::iterator nameIter =
2065 mData->mNamePtrs.find(name);
2066 if(nameIter != mData->mNamePtrs.end())
2067 {
2068 const NameData<Value_t>* nameData = &nameIter->second;
2069 if(nameData->type == NameData<Value_t>::UNIT)
2070 {
2071 AddImmedOpcode(nameData->value);
2072 incStackPtr();
2073 AddFunctionOpcode(cMul);
2074 --mStackPtr;
2075
2076 const char* endPtr = function + nameLength;
2077 SkipSpace(endPtr);
2078 return endPtr;
2079 }
2080 }
2081 }
2082
2083 return function;
2084 }
2085
2086 template<typename Value_t>
2087 inline const char*
CompilePow(const char * function)2088 FunctionParserBase<Value_t>::CompilePow(const char* function)
2089 {
2090 function = CompileElement(function);
2091 if(!function) return 0;
2092 function = CompilePossibleUnit(function);
2093
2094 if(*function == '^')
2095 {
2096 ++function;
2097 SkipSpace(function);
2098
2099 unsigned op = cPow;
2100 if(mData->mByteCode.back() == cImmed)
2101 {
2102 if(mData->mImmed.back() == fp_const_e<Value_t>())
2103 { op = cExp; mData->mByteCode.pop_back();
2104 mData->mImmed.pop_back(); --mStackPtr; }
2105 else if(mData->mImmed.back() == Value_t(2))
2106 { op = cExp2; mData->mByteCode.pop_back();
2107 mData->mImmed.pop_back(); --mStackPtr; }
2108 }
2109
2110 function = CompileUnaryMinus(function);
2111 if(!function) return 0;
2112
2113 // add opcode
2114 AddFunctionOpcode(op);
2115
2116 if(op == cPow) --mStackPtr;
2117 }
2118 return function;
2119 }
2120
2121 /* Currently the power operator is skipped for integral types because its
2122 usefulness with them is questionable, and in the case of GmpInt, for safety
2123 reasons:
2124 - With long int almost any power, except for very small ones, would
2125 overflow the result, so the usefulness of this is rather questionable.
2126 - With GmpInt the power operator could be easily abused to make the program
2127 run out of memory (think of a function like "10^10^10^10^1000000").
2128 */
2129 #ifdef FP_SUPPORT_LONG_INT_TYPE
2130 template<>
2131 inline const char*
CompilePow(const char * function)2132 FunctionParserBase<long>::CompilePow(const char* function)
2133 {
2134 function = CompileElement(function);
2135 if(!function) return 0;
2136 return CompilePossibleUnit(function);
2137 }
2138 #endif
2139
2140 #ifdef FP_SUPPORT_GMP_INT_TYPE
2141 template<>
2142 inline const char*
CompilePow(const char * function)2143 FunctionParserBase<GmpInt>::CompilePow(const char* function)
2144 {
2145 function = CompileElement(function);
2146 if(!function) return 0;
2147 return CompilePossibleUnit(function);
2148 }
2149 #endif
2150
2151 template<typename Value_t>
2152 inline const char*
CompileUnaryMinus(const char * function)2153 FunctionParserBase<Value_t>::CompileUnaryMinus(const char* function)
2154 {
2155 char op = *function;
2156 switch(op)
2157 {
2158 case '-':
2159 case '!':
2160 ++function;
2161 SkipSpace(function);
2162
2163 function = CompileUnaryMinus(function);
2164 if(!function) return 0;
2165
2166 AddFunctionOpcode(op=='-' ? cNeg : cNot);
2167
2168 return function;
2169 default: break;
2170 }
2171 return CompilePow(function);
2172 }
2173
2174 template<typename Value_t>
2175 inline const char*
CompileMult(const char * function)2176 FunctionParserBase<Value_t>::CompileMult(const char* function)
2177 {
2178 function = CompileUnaryMinus(function);
2179 if(!function) return 0;
2180
2181 Value_t pending_immed(1);
2182 #define FP_FlushImmed(do_reset) \
2183 if(pending_immed != Value_t(1)) \
2184 { \
2185 unsigned op = cMul; \
2186 if(!IsIntType<Value_t>::result && mData->mByteCode.back() == cInv) \
2187 { \
2188 /* (...) cInv 5 cMul -> (...) 5 cRDiv */ \
2189 /* ^ ^ | */ \
2190 mData->mByteCode.pop_back(); \
2191 op = cRDiv; \
2192 } \
2193 AddImmedOpcode(pending_immed); \
2194 incStackPtr(); \
2195 AddFunctionOpcode(op); \
2196 --mStackPtr; \
2197 if(do_reset) pending_immed = Value_t(1); \
2198 }
2199 while(true)
2200 {
2201 char c = *function;
2202 if(c == '%')
2203 {
2204 FP_FlushImmed(true);
2205 ++function;
2206 SkipSpace(function);
2207 function = CompileUnaryMinus(function);
2208 if(!function) return 0;
2209 AddFunctionOpcode(cMod);
2210 --mStackPtr;
2211 continue;
2212 }
2213 if(c != '*' && c != '/') break;
2214
2215 bool safe_cumulation = (c == '*' || !IsIntType<Value_t>::result);
2216 if(!safe_cumulation)
2217 {
2218 FP_FlushImmed(true);
2219 }
2220
2221 ++function;
2222 SkipSpace(function);
2223 if(mData->mByteCode.back() == cImmed
2224 && (safe_cumulation
2225 || mData->mImmed.back() == Value_t(1)))
2226 {
2227 // 5 (...) cMul --> (...) ||| 5 cMul
2228 // 5 (...) cDiv --> (...) cInv ||| 5 cMul
2229 // ^ | ^
2230 pending_immed *= mData->mImmed.back();
2231 mData->mImmed.pop_back();
2232 mData->mByteCode.pop_back();
2233 --mStackPtr;
2234 function = CompileUnaryMinus(function);
2235 if(!function) return 0;
2236 if(c == '/')
2237 AddFunctionOpcode(cInv);
2238 continue;
2239 }
2240 if(safe_cumulation
2241 && mData->mByteCode.back() == cMul
2242 && mData->mByteCode[mData->mByteCode.size()-2] == cImmed)
2243 {
2244 // (:::) 5 cMul (...) cMul -> (:::) (...) cMul ||| 5 cMul
2245 // (:::) 5 cMul (...) cDiv -> (:::) (...) cDiv ||| 5 cMul
2246 // ^ ^
2247 pending_immed *= mData->mImmed.back();
2248 mData->mImmed.pop_back();
2249 mData->mByteCode.pop_back();
2250 mData->mByteCode.pop_back();
2251 }
2252 // cDiv is not tested here because the bytecode
2253 // optimizer will convert this kind of cDivs into cMuls.
2254 bool lhs_inverted = false;
2255 if(!IsIntType<Value_t>::result && c == '*'
2256 && mData->mByteCode.back() == cInv)
2257 {
2258 // (:::) cInv (...) cMul -> (:::) (...) cRDiv
2259 // (:::) cInv (...) cDiv -> (:::) (...) cMul cInv
2260 // ^ ^ |
2261 mData->mByteCode.pop_back();
2262 lhs_inverted = true;
2263 }
2264 function = CompileUnaryMinus(function);
2265 if(!function) return 0;
2266 if(safe_cumulation
2267 && mData->mByteCode.back() == cMul
2268 && mData->mByteCode[mData->mByteCode.size()-2] == cImmed)
2269 {
2270 // (:::) (...) 5 cMul cMul -> (:::) (...) cMul ||| 5 Mul
2271 // (:::) (...) 5 cMul cDiv -> (:::) (...) cDiv ||| /5 Mul
2272 // ^ ^
2273 if(c == '*')
2274 pending_immed *= mData->mImmed.back();
2275 else
2276 pending_immed /= mData->mImmed.back();
2277 mData->mImmed.pop_back();
2278 mData->mByteCode.pop_back();
2279 mData->mByteCode.pop_back();
2280 }
2281 else
2282 if(safe_cumulation
2283 && mData->mByteCode.back() == cRDiv
2284 && mData->mByteCode[mData->mByteCode.size()-2] == cImmed)
2285 {
2286 // (:::) (...) 5 cRDiv cMul -> (:::) (...) cDiv ||| 5 cMul
2287 // (:::) (...) 5 cRDiv cDiv -> (:::) (...) cMul ||| /5 cMul
2288 // ^ ^
2289 if(c == '*')
2290 { c = '/'; pending_immed *= mData->mImmed.back(); }
2291 else
2292 { c = '*'; pending_immed /= mData->mImmed.back(); }
2293 mData->mImmed.pop_back();
2294 mData->mByteCode.pop_back();
2295 mData->mByteCode.pop_back();
2296 }
2297 if(!lhs_inverted) // if (/x/y) was changed to /(x*y), add missing cInv
2298 {
2299 AddFunctionOpcode(c == '*' ? cMul : cDiv);
2300 --mStackPtr;
2301 }
2302 else if(c == '*') // (/x)*y -> rdiv(x,y)
2303 {
2304 AddFunctionOpcode(cRDiv);
2305 --mStackPtr;
2306 }
2307 else // (/x)/y -> /(x*y)
2308 {
2309 AddFunctionOpcode(cMul);
2310 --mStackPtr;
2311 AddFunctionOpcode(cInv);
2312 }
2313 }
2314 FP_FlushImmed(false);
2315 #undef FP_FlushImmed
2316 return function;
2317 }
2318
2319 template<typename Value_t>
2320 inline const char*
CompileAddition(const char * function)2321 FunctionParserBase<Value_t>::CompileAddition(const char* function)
2322 {
2323 function = CompileMult(function);
2324 if(!function) return 0;
2325
2326 Value_t pending_immed(0);
2327 #define FP_FlushImmed(do_reset) \
2328 if(pending_immed != Value_t(0)) \
2329 { \
2330 unsigned op = cAdd; \
2331 if(mData->mByteCode.back() == cNeg) \
2332 { \
2333 /* (...) cNeg 5 cAdd -> (...) 5 cRSub */ \
2334 /* ^ ^ | */ \
2335 mData->mByteCode.pop_back(); \
2336 op = cRSub; \
2337 } \
2338 AddImmedOpcode(pending_immed); \
2339 incStackPtr(); \
2340 AddFunctionOpcode(op); \
2341 --mStackPtr; \
2342 if(do_reset) pending_immed = Value_t(0); \
2343 }
2344 while(true)
2345 {
2346 char c = *function;
2347 if(c != '+' && c != '-') break;
2348 ++function;
2349 SkipSpace(function);
2350 if(mData->mByteCode.back() == cImmed)
2351 {
2352 // 5 (...) cAdd --> (...) ||| 5 cAdd
2353 // 5 (...) cSub --> (...) cNeg ||| 5 cAdd
2354 // ^ | ^
2355 pending_immed += mData->mImmed.back();
2356 mData->mImmed.pop_back();
2357 mData->mByteCode.pop_back();
2358 --mStackPtr;
2359 function = CompileMult(function);
2360 if(!function) return 0;
2361 if(c == '-')
2362 AddFunctionOpcode(cNeg);
2363 continue;
2364 }
2365 if(mData->mByteCode.back() == cAdd
2366 && mData->mByteCode[mData->mByteCode.size()-2] == cImmed)
2367 {
2368 // (:::) 5 cAdd (...) cAdd -> (:::) (...) cAdd ||| 5 cAdd
2369 // (:::) 5 cAdd (...) cSub -> (:::) (...) cSub ||| 5 cAdd
2370 // ^ ^
2371 pending_immed += mData->mImmed.back();
2372 mData->mImmed.pop_back();
2373 mData->mByteCode.pop_back();
2374 mData->mByteCode.pop_back();
2375 }
2376 // cSub is not tested here because the bytecode
2377 // optimizer will convert this kind of cSubs into cAdds.
2378 bool lhs_negated = false;
2379 if(mData->mByteCode.back() == cNeg)
2380 {
2381 // (:::) cNeg (...) cAdd -> (:::) (...) cRSub
2382 // (:::) cNeg (...) cSub -> (:::) (...) cAdd cNeg
2383 // ^ ^ |
2384 mData->mByteCode.pop_back();
2385 lhs_negated = true;
2386 }
2387 function = CompileMult(function);
2388 if(!function) return 0;
2389 if(mData->mByteCode.back() == cAdd
2390 && mData->mByteCode[mData->mByteCode.size()-2] == cImmed)
2391 {
2392 // (:::) (...) 5 cAdd cAdd -> (:::) (...) cAdd ||| 5 Add
2393 // (:::) (...) 5 cAdd cSub -> (:::) (...) cSub ||| -5 Add
2394 // ^ ^
2395 if(c == '+')
2396 pending_immed += mData->mImmed.back();
2397 else
2398 pending_immed -= mData->mImmed.back();
2399 mData->mImmed.pop_back();
2400 mData->mByteCode.pop_back();
2401 mData->mByteCode.pop_back();
2402 }
2403 else
2404 if(mData->mByteCode.back() == cRSub
2405 && mData->mByteCode[mData->mByteCode.size()-2] == cImmed)
2406 {
2407 // (:::) (...) 5 cRSub cAdd -> (:::) (...) cSub ||| 5 cAdd
2408 // (:::) (...) 5 cRSub cSub -> (:::) (...) cAdd ||| -5 cAdd
2409 // ^ ^
2410 if(c == '+')
2411 { c = '-'; pending_immed += mData->mImmed.back(); }
2412 else
2413 { c = '+'; pending_immed -= mData->mImmed.back(); }
2414 mData->mImmed.pop_back();
2415 mData->mByteCode.pop_back();
2416 mData->mByteCode.pop_back();
2417 }
2418 if(!lhs_negated) // if (-x-y) was changed to -(x+y), add missing cNeg
2419 {
2420 AddFunctionOpcode(c == '+' ? cAdd : cSub);
2421 --mStackPtr;
2422 }
2423 else if(c == '+') // (-x)+y -> rsub(x,y)
2424 {
2425 AddFunctionOpcode(cRSub);
2426 --mStackPtr;
2427 }
2428 else // (-x)-y -> -(x+y)
2429 {
2430 AddFunctionOpcode(cAdd);
2431 --mStackPtr;
2432 AddFunctionOpcode(cNeg);
2433 }
2434 }
2435 FP_FlushImmed(false);
2436 #undef FP_FlushImmed
2437 return function;
2438 }
2439
2440 template<typename Value_t>
2441 inline const char*
CompileComparison(const char * function)2442 FunctionParserBase<Value_t>::CompileComparison(const char* function)
2443 {
2444 unsigned op=0;
2445 while(true)
2446 {
2447 function = CompileAddition(function);
2448 if(!function) return 0;
2449
2450 if(op)
2451 {
2452 AddFunctionOpcode(op);
2453 --mStackPtr;
2454 }
2455 switch(*function)
2456 {
2457 case '=':
2458 ++function; op = cEqual; break;
2459 case '!':
2460 if(function[1] == '=')
2461 { function += 2; op = cNEqual; break; }
2462 // If '=' does not follow '!', a syntax error will
2463 // be generated at the outermost parsing level
2464 return function;
2465 case '<':
2466 if(function[1] == '=')
2467 { function += 2; op = cLessOrEq; break; }
2468 ++function; op = cLess; break;
2469 case '>':
2470 if(function[1] == '=')
2471 { function += 2; op = cGreaterOrEq; break; }
2472 ++function; op = cGreater; break;
2473 default: return function;
2474 }
2475 SkipSpace(function);
2476 }
2477 return function;
2478 }
2479
2480 template<typename Value_t>
CompileAnd(const char * function)2481 inline const char* FunctionParserBase<Value_t>::CompileAnd(const char* function)
2482 {
2483 std::size_t param0end=0;
2484 while(true)
2485 {
2486 function = CompileComparison(function);
2487 if(!function) return 0;
2488
2489 if(param0end)
2490 {
2491 if(mData->mByteCode.back() == cNotNot) mData->mByteCode.pop_back();
2492
2493 AddFunctionOpcode(cAnd);
2494 --mStackPtr;
2495 }
2496 if(*function != '&') break;
2497 ++function;
2498 SkipSpace(function);
2499 param0end = mData->mByteCode.size();
2500 }
2501 return function;
2502 }
2503
2504 template<typename Value_t>
CompileExpression(const char * function)2505 const char* FunctionParserBase<Value_t>::CompileExpression(const char* function)
2506 {
2507 std::size_t param0end=0;
2508 while(true)
2509 {
2510 SkipSpace(function);
2511 function = CompileAnd(function);
2512 if(!function) return 0;
2513
2514 if(param0end)
2515 {
2516 if(mData->mByteCode.back() == cNotNot) mData->mByteCode.pop_back();
2517
2518 AddFunctionOpcode(cOr);
2519 --mStackPtr;
2520 }
2521 if(*function != '|') break;
2522 ++function;
2523 param0end = mData->mByteCode.size();
2524 }
2525 return function;
2526 }
2527
2528 template<typename Value_t>
Compile(const char * function)2529 const char* FunctionParserBase<Value_t>::Compile(const char* function)
2530 {
2531 while(true)
2532 {
2533 // Check if an identifier appears as first token:
2534 SkipSpace(function);
2535 unsigned nameLength = readIdentifier<Value_t>(function);
2536 if(nameLength > 0 && !(nameLength & 0x80000000U))
2537 {
2538 typename Data::InlineVariable inlineVar =
2539 { NamePtr(function, nameLength), 0 };
2540
2541 // Check if it's an unknown identifier:
2542 typename NamePtrsMap<Value_t>::iterator nameIter =
2543 mData->mNamePtrs.find(inlineVar.mName);
2544 if(nameIter == mData->mNamePtrs.end())
2545 {
2546 const char* function2 = function + nameLength;
2547 SkipSpace(function2);
2548
2549 // Check if ":=" follows the unknown identifier:
2550 if(function2[0] == ':' && function2[1] == '=')
2551 {
2552 // Parse the expression that follows and create the
2553 // inline variable:
2554 function2 = CompileExpression(function2 + 2);
2555 if(!function2) return 0;
2556 if(*function2 != ';') return function2;
2557
2558 inlineVar.mFetchIndex = mStackPtr - 1;
2559 mData->mInlineVarNames.push_back(inlineVar);
2560
2561 // Continue with the expression after the ';':
2562 function = function2 + 1;
2563 continue;
2564 }
2565 }
2566 }
2567 break;
2568 }
2569
2570 return CompileExpression(function);
2571 }
2572
2573 template<typename Value_t> template<bool PutFlag>
PushOpcodeParam(unsigned value)2574 inline void FunctionParserBase<Value_t>::PushOpcodeParam
2575 (unsigned value)
2576 {
2577 mData->mByteCode.push_back(value | (PutFlag ? FP_ParamGuardMask : 0u));
2578 if(PutFlag) mData->mHasByteCodeFlags = true;
2579 }
2580
2581 template<typename Value_t> template<bool PutFlag>
PutOpcodeParamAt(unsigned value,unsigned offset)2582 inline void FunctionParserBase<Value_t>::PutOpcodeParamAt
2583 (unsigned value, unsigned offset)
2584 {
2585 mData->mByteCode[offset] = value | (PutFlag ? FP_ParamGuardMask : 0u);
2586 if(PutFlag) mData->mHasByteCodeFlags = true;
2587 }
2588
2589 //===========================================================================
2590 // Function evaluation
2591 //===========================================================================
2592 template<typename Value_t>
Eval(const Value_t * Vars)2593 Value_t FunctionParserBase<Value_t>::Eval(const Value_t* Vars)
2594 {
2595 if(mData->mParseErrorType != FP_NO_ERROR) return Value_t(0);
2596
2597 const unsigned* const byteCode = &(mData->mByteCode[0]);
2598 const Value_t* const immed = mData->mImmed.empty() ? 0 : &(mData->mImmed[0]);
2599 const unsigned byteCodeSize = unsigned(mData->mByteCode.size());
2600 unsigned IP, DP=0;
2601 int SP=-1;
2602 //int stt =0;
2603 std::vector<Value_t>& StackSave = mData->mStackSave;
2604 int VarSize = StackSave.size();
2605
2606 #ifdef FP_USE_THREAD_SAFE_EVAL
2607 /* If Eval() may be called by multiple threads simultaneously,
2608 * then Eval() must allocate its own stack.
2609 */
2610 #ifdef FP_USE_THREAD_SAFE_EVAL_WITH_ALLOCA
2611 /* alloca() allocates room from the hardware stack.
2612 * It is automatically freed when the function returns.
2613 */
2614 Value_t* const Stack = (Value_t*)alloca(mData->mStackSize*sizeof(Value_t));
2615 #else
2616 /* Allocate from the heap. Ensure that it is freed
2617 * automatically no matter which exit path is taken.
2618 */
2619 struct AutoDealloc
2620 {
2621 Value_t* ptr;
2622 ~AutoDealloc() { delete[] ptr; }
2623 } AutoDeallocStack = { new Value_t[mData->mStackSize] };
2624 Value_t*& Stack = AutoDeallocStack.ptr;
2625 #endif
2626 #else
2627 /* No thread safety, so use a global stack. */
2628 std::vector<Value_t>& Stack = mData->mStack;
2629 #endif
2630
2631 for(IP=0; IP<byteCodeSize; ++IP)
2632 {
2633 switch(byteCode[IP])
2634 {
2635 // Functions:
2636 case cAbs: Stack[SP] = fp_abs(Stack[SP]); break;
2637
2638 case cAcos:
2639 if(IsComplexType<Value_t>::result == false
2640 && (Stack[SP] < Value_t(-1) || Stack[SP] > Value_t(1)))
2641 {
2642 mData->mEvalErrorType=4;
2643 return Value_t(0);
2644 }
2645 Stack[SP] = fp_acos(Stack[SP]);
2646 break;
2647
2648 case cAcosh:
2649 if(IsComplexType<Value_t>::result == false
2650 && Stack[SP] < Value_t(1))
2651 {
2652 mData->mEvalErrorType=4;
2653 return Value_t(0);
2654 }
2655 Stack[SP] = fp_acosh(Stack[SP]);
2656 break;
2657
2658 case cAsin:
2659 if(IsComplexType<Value_t>::result == false
2660 && (Stack[SP] < Value_t(-1) || Stack[SP] > Value_t(1)))
2661 {
2662 mData->mEvalErrorType=4;
2663 return Value_t(0);
2664 }
2665 Stack[SP] = fp_asin(Stack[SP]);
2666 break;
2667
2668 case cAsinh:
2669 Stack[SP] = fp_asinh(Stack[SP]);
2670 break;
2671
2672 case cAtan: Stack[SP] = fp_atan(Stack[SP]); break;
2673
2674 case cAtan2: Stack[SP-1] = fp_atan2(Stack[SP-1], Stack[SP]);
2675 --SP; break;
2676
2677 case cAtanh:
2678 if(IsComplexType<Value_t>::result
2679 ? (Stack[SP] == Value_t(-1) || Stack[SP] == Value_t(1))
2680 : (Stack[SP] <= Value_t(-1) || Stack[SP] >= Value_t(1)))
2681 { mData->mEvalErrorType=4; return Value_t(0); }
2682 Stack[SP] = fp_atanh(Stack[SP]); break;
2683
2684 case cCbrt: Stack[SP] = fp_cbrt(Stack[SP]); break;
2685
2686 case cCeil: Stack[SP] = fp_ceil(Stack[SP]); break;
2687
2688 case cCos: Stack[SP] = fp_cos(Stack[SP]); break;
2689
2690 case cCosh: Stack[SP] = fp_cosh(Stack[SP]); break;
2691
2692 case cCot:
2693 {
2694 const Value_t t = fp_tan(Stack[SP]);
2695 if(t == Value_t(0))
2696 { mData->mEvalErrorType=1; return Value_t(0); }
2697 Stack[SP] = Value_t(1)/t; break;
2698 }
2699
2700 case cCsc:
2701 {
2702 const Value_t s = fp_sin(Stack[SP]);
2703 if(s == Value_t(0))
2704 { mData->mEvalErrorType=1; return Value_t(0); }
2705 Stack[SP] = Value_t(1)/s; break;
2706 }
2707
2708
2709 case cExp: Stack[SP] = fp_exp(Stack[SP]); break;
2710
2711 case cExp2: Stack[SP] = fp_exp2(Stack[SP]); break;
2712
2713 case cFloor: Stack[SP] = fp_floor(Stack[SP]); break;
2714
2715 case cHypot:
2716 Stack[SP-1] = fp_hypot(Stack[SP-1], Stack[SP]);
2717 --SP; break;
2718
2719 case cIf:
2720 if(fp_truth(Stack[SP--]))
2721 IP += 2;
2722 else
2723 {
2724 const unsigned* buf = &byteCode[IP+1];
2725 IP = buf[0];
2726 DP = buf[1];
2727 }
2728 break;
2729
2730 case cInt: Stack[SP] = fp_int(Stack[SP]); break;
2731
2732 case cLog:
2733 if(IsComplexType<Value_t>::result
2734 ? Stack[SP] == Value_t(0)
2735 : !(Stack[SP] > Value_t(0)))
2736 { mData->mEvalErrorType=3; return Value_t(0); }
2737 Stack[SP] = fp_log(Stack[SP]); break;
2738
2739 case cLog10:
2740 if(IsComplexType<Value_t>::result
2741 ? Stack[SP] == Value_t(0)
2742 : !(Stack[SP] > Value_t(0)))
2743 { mData->mEvalErrorType=3; return Value_t(0); }
2744 Stack[SP] = fp_log10(Stack[SP]);
2745 break;
2746
2747 case cLog2:
2748 if(IsComplexType<Value_t>::result
2749 ? Stack[SP] == Value_t(0)
2750 : !(Stack[SP] > Value_t(0)))
2751 { mData->mEvalErrorType=3; return Value_t(0); }
2752 Stack[SP] = fp_log2(Stack[SP]);
2753 break;
2754
2755 case cMax: Stack[SP-1] = fp_max(Stack[SP-1], Stack[SP]);
2756 --SP; break;
2757
2758 case cMin: Stack[SP-1] = fp_min(Stack[SP-1], Stack[SP]);
2759 --SP; break;
2760
2761 case cPow:
2762 // x:Negative ^ y:NonInteger is failure,
2763 // except when the reciprocal of y forms an integer
2764 /*if(IsComplexType<Value_t>::result == false
2765 && Stack[SP-1] < Value_t(0) &&
2766 !isInteger(Stack[SP]) &&
2767 !isInteger(1.0 / Stack[SP]))
2768 { mEvalErrorType=3; return Value_t(0); }*/
2769 // x:0 ^ y:negative is failure
2770 if(Stack[SP-1] == Value_t(0) && Stack[SP] < Value_t(0))
2771 {
2772 mData->mEvalErrorType=3;
2773 return Value_t(0);
2774 }
2775 Stack[SP-1] = fp_pow(Stack[SP-1], Stack[SP]);
2776 --SP;
2777 break;
2778
2779 case cPsh:
2780 if((Stack[SP-1]) >= Value_t(VarSize) || Stack[SP-1] <Value_t(0))
2781 {
2782 mData->mEvalErrorType=VAR_OVERFLOW;
2783 return Value_t(7);
2784 }
2785 StackSave[abs(Stack[SP-1])] = Stack[SP];
2786 Stack[SP-1] = 1.0;
2787 --SP;
2788 break;
2789
2790 case cCsd:
2791 if(Stack[SP] >= Value_t(VarSize) || Stack[SP] <Value_t(0))
2792 {
2793 mData->mEvalErrorType=VAR_OVERFLOW;
2794 return Value_t(7);
2795 }
2796 Stack[SP] = StackSave[abs(Stack[SP])];
2797 break;
2798
2799 case cTrunc:
2800 Stack[SP] = fp_trunc(Stack[SP]);
2801 break;
2802
2803 case cSec:
2804 {
2805 const Value_t c = fp_cos(Stack[SP]);
2806 if(c == Value_t(0))
2807 {
2808 mData->mEvalErrorType=1;
2809 return Value_t(0);
2810 }
2811 Stack[SP] = Value_t(1)/c;
2812 break;
2813 }
2814
2815 case cSin:
2816 Stack[SP] = fp_sin(Stack[SP]);
2817 break;
2818
2819 case cSinh:
2820 Stack[SP] = fp_sinh(Stack[SP]);
2821 break;
2822
2823 case cSqrt:
2824 if(IsComplexType<Value_t>::result == false &&
2825 Stack[SP] < Value_t(0))
2826 {
2827 mData->mEvalErrorType=2;
2828 return Value_t(0);
2829 }
2830 Stack[SP] = fp_sqrt(Stack[SP]);
2831 break;
2832
2833 case cTan:
2834 Stack[SP] = fp_tan(Stack[SP]);
2835 break;
2836
2837 case cTanh:
2838 Stack[SP] = fp_tanh(Stack[SP]);
2839 break;
2840
2841 // Misc:
2842 case cImmed:
2843 Stack[++SP] = immed[DP++];
2844 break;
2845
2846 case cJump:
2847 {
2848 const unsigned* buf = &byteCode[IP+1];
2849 IP = buf[0];
2850 DP = buf[1];
2851 break;
2852 }
2853
2854 // Operators:
2855 case cNeg:
2856 Stack[SP] = -Stack[SP];
2857 break;
2858 case cAdd:
2859 Stack[SP-1] += Stack[SP];
2860 --SP;
2861 break;
2862 case cSub: Stack[SP-1] -= Stack[SP]; --SP; break;
2863 case cMul: Stack[SP-1] *= Stack[SP]; --SP; break;
2864 case cDiv:
2865 if(Stack[SP] == Value_t(0))
2866 { mData->mEvalErrorType=1; return Value_t(0); }
2867 Stack[SP-1] /= Stack[SP]; --SP; break;
2868 case cMod:
2869 if(Stack[SP] == Value_t(0))
2870 { mData->mEvalErrorType=1; return Value_t(0); }
2871 Stack[SP-1] = fp_mod(Stack[SP-1], Stack[SP]);
2872 --SP; break;
2873 case cEqual:
2874 Stack[SP-1] = fp_equal(Stack[SP-1], Stack[SP]);
2875 --SP; break;
2876 case cNEqual:
2877 Stack[SP-1] = fp_nequal(Stack[SP-1], Stack[SP]);
2878 --SP; break;
2879 case cLess:
2880 Stack[SP-1] = fp_less(Stack[SP-1], Stack[SP]);
2881 --SP; break;
2882 case cLessOrEq:
2883 Stack[SP-1] = fp_lessOrEq(Stack[SP-1], Stack[SP]);
2884 --SP; break;
2885
2886 case cGreater:
2887 Stack[SP-1] = fp_less(Stack[SP], Stack[SP-1]);
2888 --SP; break;
2889
2890 case cGreaterOrEq:
2891 Stack[SP-1] = fp_lessOrEq(Stack[SP], Stack[SP-1]);
2892 --SP; break;
2893 case cNot: Stack[SP] = fp_not(Stack[SP]); break;
2894 case cNotNot: Stack[SP] = fp_notNot(Stack[SP]); break;
2895 case cAnd:
2896 Stack[SP-1] = fp_and(Stack[SP-1], Stack[SP]);
2897 --SP; break;
2898 case cOr:
2899 Stack[SP-1] = fp_or(Stack[SP-1], Stack[SP]);
2900 --SP; break;
2901 // Degrees-radians conversion:
2902 case cDeg: Stack[SP] = RadiansToDegrees(Stack[SP]); break;
2903 case cRad: Stack[SP] = DegreesToRadians(Stack[SP]); break;
2904
2905 // User-defined function calls:
2906 case cFCall:
2907 {
2908 const unsigned index = byteCode[++IP];
2909 const unsigned params = mData->mFuncPtrs[index].mParams;
2910 const Value_t retVal =
2911 mData->mFuncPtrs[index].mRawFuncPtr ?
2912 mData->mFuncPtrs[index].mRawFuncPtr(&Stack[SP-params+1]) :
2913 mData->mFuncPtrs[index].mFuncWrapperPtr->callFunction
2914 (&Stack[SP-params+1]);
2915 SP -= int(params)-1;
2916 Stack[SP] = retVal;
2917 break;
2918 }
2919 case cPCall:
2920 {
2921 unsigned index = byteCode[++IP];
2922 unsigned params = mData->mFuncParsers[index].mParams;
2923 Value_t retVal =
2924 mData->mFuncParsers[index].mParserPtr->Eval
2925 (&Stack[SP-params+1]);
2926 SP -= int(params)-1;
2927 Stack[SP] = retVal;
2928 const int error =
2929 mData->mFuncParsers[index].mParserPtr->EvalError();
2930 if(error)
2931 {
2932 mData->mEvalErrorType = error;
2933 return 0;
2934 }
2935 break;
2936 }
2937 case cFetch:
2938 {
2939 unsigned stackOffs = byteCode[++IP];
2940 Stack[SP+1] = Stack[stackOffs]; ++SP;
2941 break;
2942 }
2943 #ifdef FP_SUPPORT_OPTIMIZER
2944 case cPopNMov:
2945 {
2946 unsigned stackOffs_target = byteCode[++IP];
2947 unsigned stackOffs_source = byteCode[++IP];
2948 Stack[stackOffs_target] = Stack[stackOffs_source];
2949 SP = stackOffs_target;
2950 break;
2951 }
2952
2953 case cLog2by:
2954 if(IsComplexType<Value_t>::result
2955 ? Stack[SP-1] == Value_t(0)
2956 : !(Stack[SP-1] > Value_t(0)))
2957 { mData->mEvalErrorType=3; return Value_t(0); }
2958 Stack[SP-1] = fp_log2(Stack[SP-1]) * Stack[SP];
2959 --SP;
2960 break;
2961
2962 case cNop: break;
2963 #endif // FP_SUPPORT_OPTIMIZER
2964
2965 case cSinCos:
2966 fp_sinCos(Stack[SP], Stack[SP+1], Stack[SP]);
2967 ++SP;
2968 break;
2969 case cSinhCosh:
2970 fp_sinhCosh(Stack[SP], Stack[SP+1], Stack[SP]);
2971 ++SP;
2972 break;
2973
2974 case cAbsNot:
2975 Stack[SP] = fp_absNot(Stack[SP]); break;
2976 case cAbsNotNot:
2977 Stack[SP] = fp_absNotNot(Stack[SP]); break;
2978 case cAbsAnd:
2979 Stack[SP-1] = fp_absAnd(Stack[SP-1], Stack[SP]);
2980 --SP; break;
2981 case cAbsOr:
2982 Stack[SP-1] = fp_absOr(Stack[SP-1], Stack[SP]);
2983 --SP; break;
2984 case cAbsIf:
2985 if(fp_absTruth(Stack[SP--]))
2986 IP += 2;
2987 else
2988 {
2989 const unsigned* buf = &byteCode[IP+1];
2990 IP = buf[0];
2991 DP = buf[1];
2992 }
2993 break;
2994 case cDup: Stack[SP+1] = Stack[SP]; ++SP; break;
2995 case cInv:
2996 if(Stack[SP] == Value_t(0))
2997 { mData->mEvalErrorType=1; return Value_t(0); }
2998 Stack[SP] = Value_t(1)/Stack[SP];
2999 break;
3000 case cSqr:
3001 Stack[SP] = Stack[SP]*Stack[SP];
3002 break;
3003 case cRDiv:
3004 if(Stack[SP-1] == Value_t(0))
3005 { mData->mEvalErrorType=1; return Value_t(0); }
3006 Stack[SP-1] = Stack[SP] / Stack[SP-1]; --SP; break;
3007 case cRSub: Stack[SP-1] = Stack[SP] - Stack[SP-1]; --SP; break;
3008 case cRSqrt:
3009 if(Stack[SP] == Value_t(0))
3010 { mData->mEvalErrorType=1; return Value_t(0); }
3011 Stack[SP] = Value_t(1) / fp_sqrt(Stack[SP]); break;
3012 #ifdef FP_SUPPORT_COMPLEX_NUMBERS
3013 case cReal: Stack[SP] = fp_real(Stack[SP]); break;
3014 case cImag: Stack[SP] = fp_imag(Stack[SP]); break;
3015 case cArg: Stack[SP] = fp_arg(Stack[SP]); break;
3016 case cConj: Stack[SP] = fp_conj(Stack[SP]); break;
3017 case cPolar:
3018 Stack[SP-1] = fp_polar(Stack[SP-1], Stack[SP]);
3019 --SP; break;
3020 #endif
3021
3022 // Variables:
3023 default:
3024 Stack[++SP] = Vars[byteCode[IP]-VarBegin];
3025 }
3026 }
3027 mData->mEvalErrorType=0;
3028 return Stack[SP];
3029 }
3030
3031 //===========================================================================
3032 // Function evaluation
3033 //===========================================================================
3034 template<typename Value_t>
EvalC(const std::complex<double> * Vars)3035 std::complex<double> FunctionParserBase<Value_t>::EvalC(const std::complex<double>* Vars)
3036 {
3037 if(mData->mParseErrorType != FP_NO_ERROR) return Value_t(0);
3038
3039 const unsigned* const byteCode = &(mData->mByteCode[0]);
3040 const Value_t* const immed = mData->mImmed.empty() ? 0 : &(mData->mImmed[0]);
3041 const unsigned byteCodeSize = unsigned(mData->mByteCode.size());
3042 unsigned IP, DP=0;
3043 int SP=-1;
3044 std::vector<Value_t>& StackSave = mData->mStackSave;
3045 unsigned int VarSize = StackSave.size();
3046
3047 #ifdef FP_USE_THREAD_SAFE_EVAL
3048 /* If Eval() may be called by multiple threads simultaneously,
3049 * then Eval() must allocate its own stack.
3050 */
3051 #ifdef FP_USE_THREAD_SAFE_EVAL_WITH_ALLOCA
3052 /* alloca() allocates room from the hardware stack.
3053 * It is automatically freed when the function returns.
3054 */
3055 Value_t* const Stack = (Value_t*)alloca(mData->mStackSize*sizeof(Value_t));
3056 #else
3057 /* Allocate from the heap. Ensure that it is freed
3058 * automatically no matter which exit path is taken.
3059 */
3060 struct AutoDealloc
3061 {
3062 Value_t* ptr;
3063 ~AutoDealloc() { delete[] ptr; }
3064 } AutoDeallocStack = { new Value_t[mData->mStackSize] };
3065 Value_t*& Stack = AutoDeallocStack.ptr;
3066 #endif
3067 #else
3068 /* No thread safety, so use a global stack. */
3069 //std::vector<Value_t>& Stack = mData->mStack;
3070 #endif
3071
3072 std::complex<double>* const Stack = (std::complex<double>*)alloca(mData->mStackSize*sizeof(std::complex<double>));
3073
3074 for(IP=0; IP<byteCodeSize; ++IP)
3075 {
3076 switch(byteCode[IP])
3077 {
3078 // Functions:
3079 case cAbs: Stack[SP] = fp_abs(Stack[SP]); break;
3080
3081 case cAcos:
3082 Stack[SP] = fp_acos(Stack[SP]); break;
3083
3084 case cAcosh:
3085 Stack[SP] = fp_acosh(Stack[SP]); break;
3086
3087 case cAsin:
3088 Stack[SP] = fp_asin(Stack[SP]); break;
3089
3090 case cAsinh: Stack[SP] = fp_asinh(Stack[SP]); break;
3091
3092 case cAtan: Stack[SP] = fp_atan(Stack[SP]); break;
3093
3094 case cAtan2: Stack[SP-1] = fp_atan2(Stack[SP-1], Stack[SP]);
3095 --SP; break;
3096
3097 case cAtanh:
3098 Stack[SP] = fp_atanh(Stack[SP]); break;
3099
3100 case cCbrt: Stack[SP] = fp_cbrt(Stack[SP]); break;
3101
3102 case cCeil: Stack[SP] = fp_ceil(Stack[SP]); break;
3103
3104 case cCos: Stack[SP] = fp_cos(Stack[SP]); break;
3105
3106 case cCosh: Stack[SP] = fp_cosh(Stack[SP]); break;
3107
3108 case cCot:
3109 {
3110 const std::complex<double> t = fp_tan(Stack[SP]);
3111 Stack[SP] = (1.0)/t; break;
3112 }
3113
3114 case cCsc:
3115 {
3116 const std::complex<double> s = fp_sin(Stack[SP]);
3117 Stack[SP] = (1.0)/s; break;
3118 }
3119
3120
3121 case cExp: Stack[SP] = fp_exp(Stack[SP]); break;
3122
3123 case cExp2: Stack[SP] = fp_exp2(Stack[SP]); break;
3124
3125 case cFloor: Stack[SP] = fp_floor(Stack[SP]); break;
3126
3127 case cHypot:
3128 Stack[SP-1] = fp_hypot(Stack[SP-1], Stack[SP]);
3129 --SP; break;
3130
3131 case cIf:
3132 if(fp_truth(Stack[SP--]))
3133 IP += 2;
3134 else
3135 {
3136 const unsigned* buf = &byteCode[IP+1];
3137 IP = buf[0];
3138 DP = buf[1];
3139 }
3140 break;
3141
3142 case cInt: Stack[SP] = fp_int(Stack[SP]); break;
3143
3144 case cLog:
3145 Stack[SP] = fp_log(Stack[SP]); break;
3146
3147 case cLog10:
3148 Stack[SP] = fp_log10(Stack[SP]);
3149 break;
3150
3151 case cLog2:
3152 Stack[SP] = fp_log2(Stack[SP]);
3153 break;
3154
3155 case cMax: Stack[SP-1] = fp_max(Stack[SP-1], Stack[SP]);
3156 --SP; break;
3157
3158 case cMin: Stack[SP-1] = fp_min(Stack[SP-1], Stack[SP]);
3159 --SP; break;
3160
3161 case cPow:
3162 // x:Negative ^ y:NonInteger is failure,
3163 // except when the reciprocal of y forms an integer
3164 /*if(IsComplexType<Value_t>::result == false
3165 && Stack[SP-1] < Value_t(0) &&
3166 !isInteger(Stack[SP]) &&
3167 !isInteger(1.0 / Stack[SP]))
3168 { mEvalErrorType=3; return Value_t(0); }*/
3169 // x:0 ^ y:negative is failure
3170 /*
3171 if(Stack[SP-1] == Value_t(0) &&
3172 Stack[SP] < Value_t(0))
3173 { mData->mEvalErrorType=3; return Value_t(0); }*/
3174 Stack[SP-1] = fp_pow(Stack[SP-1], Stack[SP]);
3175 --SP; break;
3176 case cPsh:
3177
3178 if((Stack[SP-1]).real() >= VarSize || Stack[SP-1].real() < 0)
3179 {
3180 mData->mEvalErrorType=VAR_OVERFLOW;
3181 return Value_t(7);
3182 }
3183 StackSave[abs(Stack[SP-1])] = (Stack[SP]).real();
3184 Stack[SP-1] = 1.0;
3185 --SP;
3186 break;
3187 case cCsd:
3188
3189 if(Stack[SP].real() >= VarSize || Stack[SP].real() < 0)
3190 {
3191 mData->mEvalErrorType=VAR_OVERFLOW;
3192 return Value_t(7);
3193 }
3194 Stack[SP] = StackSave[abs(Stack[SP])];
3195 break;
3196 case cTrunc: Stack[SP] = fp_trunc(Stack[SP]); break;
3197
3198 case cSec:
3199 {
3200 const std::complex<double> c = fp_cos(Stack[SP]);
3201 if(abs(c) == 0)
3202 { mData->mEvalErrorType=1; return Value_t(0); }
3203 Stack[SP] = (1.0)/c; break;
3204 }
3205
3206 case cSin: Stack[SP] = fp_sin(Stack[SP]); break;
3207
3208 case cSinh: Stack[SP] = fp_sinh(Stack[SP]); break;
3209
3210 case cSqrt:
3211 /*
3212 if(IsComplexType<Value_t>::result == false &&
3213 Stack[SP] < Value_t(0))
3214 { mData->mEvalErrorType=2; return Value_t(0); }
3215 */
3216 Stack[SP] = fp_sqrt(Stack[SP]); break;
3217
3218 case cTan: Stack[SP] = fp_tan(Stack[SP]); break;
3219
3220 case cTanh: Stack[SP] = fp_tanh(Stack[SP]); break;
3221
3222 // Misc:
3223 case cImmed: Stack[++SP] = immed[DP++]; break;
3224
3225 case cJump:
3226 {
3227 const unsigned* buf = &byteCode[IP+1];
3228 IP = buf[0];
3229 DP = buf[1];
3230 break;
3231 }
3232
3233 // Operators:
3234 case cNeg: Stack[SP] = -Stack[SP]; break;
3235 case cAdd: Stack[SP-1] += Stack[SP]; --SP; break;
3236 case cSub: Stack[SP-1] -= Stack[SP]; --SP; break;
3237 case cMul: Stack[SP-1] *= Stack[SP]; --SP; break;
3238
3239 case cDiv:
3240 if(abs(Stack[SP]) == 0)
3241 { mData->mEvalErrorType=1; return Value_t(0); }
3242 Stack[SP-1] /= Stack[SP];
3243 --SP; break;
3244
3245 case cMod:
3246 if(abs(Stack[SP]) == 0)
3247 { mData->mEvalErrorType=1; return Value_t(0); }
3248 Stack[SP-1] = fp_mod(Stack[SP-1], Stack[SP]);
3249 --SP; break;
3250
3251 case cEqual:
3252 Stack[SP-1] = fp_equal(Stack[SP-1], Stack[SP]);
3253 --SP; break;
3254
3255 case cNEqual:
3256 Stack[SP-1] = fp_nequal(Stack[SP-1], Stack[SP]);
3257 --SP; break;
3258
3259 case cLess:
3260 Stack[SP-1] = fp_less(Stack[SP-1], Stack[SP]);
3261 --SP; break;
3262
3263 case cLessOrEq:
3264 Stack[SP-1] = fp_lessOrEq(Stack[SP-1], Stack[SP]);
3265 --SP; break;
3266
3267 case cGreater:
3268 Stack[SP-1] = fp_less(Stack[SP], Stack[SP-1]);
3269 --SP; break;
3270
3271 case cGreaterOrEq:
3272 Stack[SP-1] = fp_lessOrEq(Stack[SP], Stack[SP-1]);
3273 --SP; break;
3274
3275 case cNot: Stack[SP] = fp_not(Stack[SP]); break;
3276
3277 case cNotNot: Stack[SP] = fp_notNot(Stack[SP]); break;
3278
3279 case cAnd:
3280 Stack[SP-1] = fp_and(Stack[SP-1], Stack[SP]);
3281 --SP; break;
3282
3283 case cOr:
3284 Stack[SP-1] = fp_or(Stack[SP-1], Stack[SP]);
3285 --SP; break;
3286
3287 // Degrees-radians conversion:
3288 case cDeg: Stack[SP] = RadiansToDegrees(Stack[SP]); break;
3289 case cRad: Stack[SP] = DegreesToRadians(Stack[SP]); break;
3290
3291 // User-defined function calls:
3292
3293 case cFCall:
3294 {
3295 const unsigned index = byteCode[++IP];
3296 const unsigned params = mData->mFuncPtrs[index].mParams;
3297 const Value_t hy = Stack[SP-params+1].real();
3298 std::complex<double> retVal =
3299 mData->mFuncPtrs[index].mRawFuncPtr ?
3300 mData->mFuncPtrs[index].mRawFuncPtr(&hy) :
3301 mData->mFuncPtrs[index].mFuncWrapperPtr->callFunction
3302 (&hy);
3303 SP -= int(params)-1;
3304 Stack[SP] = retVal;
3305 break;
3306 }
3307
3308 case cPCall:
3309 {
3310 unsigned index = byteCode[++IP];
3311 unsigned params = mData->mFuncParsers[index].mParams;
3312 std::complex<double> retVal =
3313 mData->mFuncParsers[index].mParserPtr->EvalC
3314 (&Stack[SP-params+1]);
3315 SP -= int(params)-1;
3316 Stack[SP] = retVal;
3317 const int error =
3318 mData->mFuncParsers[index].mParserPtr->EvalError();
3319 if(error)
3320 {
3321 mData->mEvalErrorType = error;
3322 return 0;
3323 }
3324 break;
3325 }
3326
3327
3328 case cFetch:
3329 {
3330 unsigned stackOffs = byteCode[++IP];
3331 Stack[SP+1] = Stack[stackOffs]; ++SP;
3332 break;
3333 }
3334
3335 #ifdef FP_SUPPORT_OPTIMIZER
3336 case cPopNMov:
3337 {
3338 unsigned stackOffs_target = byteCode[++IP];
3339 unsigned stackOffs_source = byteCode[++IP];
3340 Stack[stackOffs_target] = Stack[stackOffs_source];
3341 SP = stackOffs_target;
3342 break;
3343 }
3344
3345 case cLog2by:/*
3346 if(IsComplexType<Value_t>::result
3347 ? Stack[SP-1] == Value_t(0)
3348 : !(Stack[SP-1] > Value_t(0)))
3349 { mData->mEvalErrorType=3; return Value_t(0); }*/
3350 Stack[SP-1] = fp_log2(Stack[SP-1]) * Stack[SP];
3351 --SP;
3352 break;
3353
3354 case cNop: break;
3355 #endif // FP_SUPPORT_OPTIMIZER
3356
3357 case cSinCos:
3358 fp_sinCos(Stack[SP], Stack[SP+1], Stack[SP]);
3359 ++SP;
3360 break;
3361 case cSinhCosh:
3362 fp_sinhCosh(Stack[SP], Stack[SP+1], Stack[SP]);
3363 ++SP;
3364 break;
3365
3366 case cAbsNot:
3367 Stack[SP] = fp_absNot(Stack[SP]); break;
3368 case cAbsNotNot:
3369 Stack[SP] = fp_absNotNot(Stack[SP]); break;
3370 case cAbsAnd:
3371 Stack[SP-1] = fp_absAnd(Stack[SP-1], Stack[SP]);
3372 --SP; break;
3373 case cAbsOr:
3374 Stack[SP-1] = fp_absOr(Stack[SP-1], Stack[SP]);
3375 --SP; break;
3376 case cAbsIf:
3377 if(fp_absTruth(Stack[SP--]))
3378 IP += 2;
3379 else
3380 {
3381 const unsigned* buf = &byteCode[IP+1];
3382 IP = buf[0];
3383 DP = buf[1];
3384 }
3385 break;
3386
3387 case cDup: Stack[SP+1] = Stack[SP]; ++SP; break;
3388
3389 case cInv:/*
3390 if(Stack[SP] == Value_t(0))
3391 { mData->mEvalErrorType=1; return Value_t(0); }*/
3392 Stack[SP] = (1.0)/Stack[SP];
3393 break;
3394
3395 case cSqr:
3396 Stack[SP] = Stack[SP]*Stack[SP];
3397 break;
3398
3399 case cRDiv:/*
3400 if(Stack[SP-1] == Value_t(0))
3401 { mData->mEvalErrorType=1; return Value_t(0); }*/
3402 Stack[SP-1] = Stack[SP] / Stack[SP-1]; --SP; break;
3403
3404 case cRSub: Stack[SP-1] = Stack[SP] - Stack[SP-1]; --SP; break;
3405
3406 case cRSqrt:/*
3407 if(Stack[SP] == Value_t(0))
3408 { mData->mEvalErrorType=1; return Value_t(0); }*/
3409 Stack[SP] = (1.0) / fp_sqrt(Stack[SP]); break;
3410
3411 #ifdef FP_SUPPORT_COMPLEX_NUMBERS
3412 case cReal: Stack[SP] = fp_real(Stack[SP]); break;
3413 case cImag: Stack[SP] = fp_imag(Stack[SP]); break;
3414 case cArg: Stack[SP] = fp_arg(Stack[SP]); break;
3415 case cConj: Stack[SP] = fp_conj(Stack[SP]); break;
3416 case cPolar:
3417 Stack[SP-1] = fp_polar(Stack[SP-1], Stack[SP]);
3418 --SP; break;
3419 #endif
3420
3421
3422 // Variables:
3423 default:
3424 Stack[++SP] = Vars[byteCode[IP]-VarBegin];
3425 }
3426 }
3427
3428 mData->mEvalErrorType=0;
3429 return (Stack[SP]);
3430 }
3431
3432
3433
3434 template<typename Value_t>
AllocateStackMemory(unsigned int nbStack,int nbvar)3435 void FunctionParserBase<Value_t>::AllocateStackMemory(unsigned int nbStack, int nbvar)
3436 {
3437 mData->mStacki.resize(nbStack*(mData->mStack).size());
3438 mData->mStackSave.resize(nbvar*nbStack); // Should be done earlier
3439 }
3440
3441 template<typename Value_t>
Eval2(const Value_t * Vars,unsigned NbVar,Value_t * results,unsigned NbStack,int SP)3442 Value_t FunctionParserBase<Value_t>::Eval2(const Value_t* Vars, unsigned NbVar, Value_t* results, unsigned NbStack, int SP)
3443 {
3444 if(mData->mParseErrorType != FP_NO_ERROR) return Value_t(0);
3445
3446 const unsigned* const byteCode = &(mData->mByteCode[0]);
3447 const Value_t* const immed = mData->mImmed.empty() ? 0 : &(mData->mImmed[0]);
3448 const unsigned byteCodeSize = unsigned(mData->mByteCode.size());
3449 unsigned IP, DP=0, Nbval;
3450 /* No thread safety, so use a global stack. */
3451 std::vector<Value_t>& Stack = mData->mStack;
3452 std::vector<Value_t>& Stacki = mData->mStacki;
3453 std::vector<Value_t>& StackSave = mData->mStackSave;
3454 int Size = Stack.size();
3455 int VarSize = StackSave.size();
3456 Value_t stt;
3457
3458 for(IP=0; IP<byteCodeSize; ++IP)
3459 {
3460 switch(byteCode[IP])
3461 {
3462 // Functions:
3463 case cCos:
3464 for(Nbval=0; Nbval<NbStack; Nbval++)
3465 Stacki[Nbval*Size+SP] = fp_cos(Stacki[Nbval*Size+SP]);
3466 break;
3467 case cAbs:
3468 for(Nbval=0; Nbval<NbStack; Nbval++)
3469 Stacki[Nbval*Size+SP] = fp_abs(Stacki[Nbval*Size+SP]);
3470 break;
3471 case cAcos:
3472 for(Nbval=0; Nbval<NbStack; Nbval++)
3473 {
3474 if(IsComplexType<Value_t>::result == false
3475 && (Stacki[Nbval*Size+SP] < Value_t(-1) || Stacki[Nbval*Size+SP] > Value_t(1)))
3476 { mData->mEvalErrorType=4; return Value_t(0); }
3477 Stacki[Nbval*Size+SP] = fp_acos(Stacki[Nbval*Size+SP]);
3478 }
3479 break;
3480
3481 case cAcosh:
3482 for(Nbval=0; Nbval<NbStack; Nbval++)
3483 {
3484 if(IsComplexType<Value_t>::result == false
3485 && Stacki[Nbval*Size+SP] < Value_t(1))
3486 { mData->mEvalErrorType=4; return Value_t(0); }
3487 Stacki[Nbval*Size+SP] = fp_acosh(Stacki[Nbval*Size+SP]);
3488 }
3489 break;
3490
3491 case cAsin:
3492 for(Nbval=0; Nbval<NbStack; Nbval++)
3493 {
3494 if(IsComplexType<Value_t>::result == false
3495 && (Stacki[Nbval*Size+SP] < Value_t(-1) || Stacki[Nbval*Size+SP] > Value_t(1)))
3496 { mData->mEvalErrorType=4; return Value_t(0); }
3497 Stacki[Nbval*Size+SP] = fp_asin(Stacki[Nbval*Size+SP]);
3498 }
3499 break;
3500
3501 case cAsinh:
3502 for(Nbval=0; Nbval<NbStack; Nbval++)
3503 Stacki[Nbval*Size+SP] = fp_asinh(Stacki[Nbval*Size+SP]);
3504 break;
3505
3506 case cAtan:
3507 for(Nbval=0; Nbval<NbStack; Nbval++)
3508 Stacki[Nbval*Size+SP] = fp_atan(Stacki[Nbval*Size+SP]);
3509 break;
3510
3511 case cAtan2:
3512 for(Nbval=0; Nbval<NbStack; Nbval++)
3513 Stacki[Nbval*Size+SP-1] = fp_atan2(Stacki[Nbval*Size+SP-1], Stacki[Nbval*Size+SP]);
3514 --SP; break;
3515
3516 case cAtanh:
3517 for(Nbval=0; Nbval<NbStack; Nbval++)
3518 {
3519 if(IsComplexType<Value_t>::result
3520 ? (Stacki[Nbval*Size+SP] == Value_t(-1) || Stacki[Nbval*Size+SP] == Value_t(1))
3521 : (Stacki[Nbval*Size+SP] <= Value_t(-1) || Stacki[Nbval*Size+SP] >= Value_t(1)))
3522 { mData->mEvalErrorType=4; return Value_t(0); }
3523 Stacki[Nbval*Size+SP] = fp_atanh(Stacki[Nbval*Size+SP]);
3524 }
3525 break;
3526
3527 case cCbrt:
3528 for(Nbval=0; Nbval<NbStack; Nbval++)
3529 Stacki[Nbval*Size+SP] = fp_cbrt(Stacki[Nbval*Size+SP]);
3530 break;
3531
3532 case cCeil:
3533 for(Nbval=0; Nbval<NbStack; Nbval++)
3534 Stacki[Nbval*Size+SP] = fp_ceil(Stacki[Nbval*Size+SP]);
3535 break;
3536
3537 case cCosh:
3538 for(Nbval=0; Nbval<NbStack; Nbval++)
3539 Stacki[Nbval*Size+SP] = fp_cosh(Stacki[Nbval*Size+SP]);
3540 break;
3541
3542 case cCot:
3543 for(Nbval=0; Nbval<NbStack; Nbval++)
3544 {
3545 const Value_t t = fp_tan(Stacki[Nbval*Size+SP]);
3546 if(t == Value_t(0))
3547 { mData->mEvalErrorType=DIVISION_BY_ZERO; return Value_t(1); }
3548 Stacki[Nbval*Size+SP] = Value_t(1)/t;
3549 }
3550 break;
3551
3552 case cCsc:
3553 for(Nbval=0; Nbval<NbStack; Nbval++)
3554 {
3555 const Value_t s = fp_sin(Stacki[Nbval*Size+SP]);
3556 if(s == Value_t(0))
3557 { mData->mEvalErrorType=DIVISION_BY_ZERO; return Value_t(1); }
3558 Stacki[Nbval*Size+SP] = Value_t(1)/s;
3559 }
3560 break;
3561
3562 case cExp:
3563 for(Nbval=0; Nbval<NbStack; Nbval++)
3564 Stacki[Nbval*Size+SP] = fp_exp(Stacki[Nbval*Size+SP]);
3565 break;
3566
3567 case cExp2:
3568 for(Nbval=0; Nbval<NbStack; Nbval++)
3569 Stacki[Nbval*Size+SP] = fp_exp2(Stacki[Nbval*Size+SP]);
3570 break;
3571
3572 case cFloor:
3573 for(Nbval=0; Nbval<NbStack; Nbval++)
3574 Stacki[Nbval*Size+SP] = fp_floor(Stacki[Nbval*Size+SP]);
3575 break;
3576
3577 case cHypot:
3578 for(Nbval=0; Nbval<NbStack; Nbval++)
3579 Stacki[Nbval*Size+SP-1] = fp_hypot(Stacki[Nbval*Size+SP-1], Stacki[Nbval*Size+SP]);
3580 --SP;
3581 break;
3582
3583 case cIf:
3584 {
3585 bool valid = fp_truth(Stacki[SP]);
3586
3587 for(Nbval=1; Nbval<NbStack; Nbval++)
3588 if(valid != fp_truth(Stacki[Nbval*Size+SP]))
3589 {
3590 mData->mEvalErrorType=IF_FUNCT_ERROR; return Value_t(5);
3591 }
3592 if(valid)
3593 IP += 2;
3594 else
3595 {
3596 const unsigned* buf = &byteCode[IP+1];
3597 IP = buf[0];
3598 DP = buf[1];
3599 }
3600 }
3601 SP--;
3602 break;
3603 case cInt:
3604 for(Nbval=0; Nbval<NbStack; Nbval++)
3605 Stacki[Nbval*Size+SP] = fp_int(Stacki[Nbval*Size+SP]);
3606 break;
3607
3608 case cLog:
3609 for(Nbval=0; Nbval<NbStack; Nbval++)
3610 {
3611 if(IsComplexType<Value_t>::result
3612 ? Stacki[Nbval*Size+SP] == Value_t(0)
3613 : !(Stacki[Nbval*Size+SP] > Value_t(0)))
3614 { mData->mEvalErrorType=3; return Value_t(0); }
3615 Stacki[Nbval*Size+SP] = fp_log(Stacki[Nbval*Size+SP]);
3616 }
3617 break;
3618
3619 case cLog10:
3620 for(Nbval=0; Nbval<NbStack; Nbval++)
3621 {
3622 if(IsComplexType<Value_t>::result
3623 ? Stacki[Nbval*Size+SP] == Value_t(0)
3624 : !(Stacki[Nbval*Size+SP] > Value_t(0)))
3625 { mData->mEvalErrorType=3; return Value_t(0); }
3626 Stacki[Nbval*Size+SP] = fp_log10(Stacki[Nbval*Size+SP]);
3627 }
3628 break;
3629
3630 case cLog2:
3631 for(Nbval=0; Nbval<NbStack; Nbval++)
3632 {
3633 if(IsComplexType<Value_t>::result
3634 ? Stacki[Nbval*Size+SP] == Value_t(0)
3635 : !(Stacki[Nbval*Size+SP] > Value_t(0)))
3636 { mData->mEvalErrorType=3; return Value_t(0); }
3637 Stacki[Nbval*Size+SP] = fp_log2(Stacki[Nbval*Size+SP]);
3638 }
3639 break;
3640
3641 case cMax:
3642 for(Nbval=0; Nbval<NbStack; Nbval++)
3643 Stacki[Nbval*Size+SP-1] = fp_max(Stacki[Nbval*Size+SP-1], Stacki[Nbval*Size+SP]);
3644 --SP; break;
3645
3646 case cMin:
3647 for(Nbval=0; Nbval<NbStack; Nbval++)
3648 Stacki[Nbval*Size+SP-1] = fp_min(Stacki[Nbval*Size+SP-1], Stacki[Nbval*Size+SP]);
3649 --SP; break;
3650
3651 case cPow:
3652 // x:Negative ^ y:NonInteger is failure,
3653 // except when the reciprocal of y forms an integer
3654 /*if(IsComplexType<Value_t>::result == false
3655 && Stack[SP-1] < Value_t(0) &&
3656 !isInteger(Stack[SP]) &&
3657 !isInteger(1.0 / Stack[SP]))
3658 { mEvalErrorType=3; return Value_t(0); }*/
3659 // x:0 ^ y:negative is failure
3660
3661 for(Nbval=0; Nbval<NbStack; Nbval++)
3662 {
3663 if(Stacki[Nbval*Size+SP-1] == Value_t(0) &&
3664 Stacki[Nbval*Size+SP] < Value_t(0))
3665 { mData->mEvalErrorType=3; return Value_t(0); }
3666 Stacki[Nbval*Size+SP-1] = fp_pow(Stacki[Nbval*Size+SP-1], Stacki[Nbval*Size+SP]);
3667 }
3668 --SP; break;
3669 case cPsh:
3670 for(Nbval=0; Nbval<NbStack; Nbval++)
3671 {
3672 stt = (Value_t(NbStack)*(Stacki[Nbval*Size+SP-1])+Value_t(Nbval));
3673 if(stt >= Value_t(VarSize) || stt < Value_t(0))
3674 {
3675 mData->mEvalErrorType=VAR_OVERFLOW;
3676 return Value_t(7);
3677 }
3678 StackSave[abs(stt)] = Stacki[Nbval*Size+SP];
3679 Stacki[Nbval*Size+SP-1] = 1.0;
3680 }
3681 --SP;
3682 break;
3683 case cCsd:
3684 for(Nbval=0; Nbval<NbStack; Nbval++)
3685 {
3686 stt = (Value_t(NbStack)*(Stacki[Nbval*Size+SP])+Value_t(Nbval));
3687 if(stt >= Value_t(VarSize) || stt < Value_t(0))
3688 {
3689 mData->mEvalErrorType=VAR_OVERFLOW;
3690 return Value_t(7);
3691 }
3692 Stacki[Nbval*Size+SP] = StackSave[abs(stt)];
3693 }
3694 break;
3695 case cTrunc:
3696 for(Nbval=0; Nbval<NbStack; Nbval++)
3697 Stacki[Nbval*Size+SP] = fp_trunc(Stacki[Nbval*Size+SP]);
3698 break;
3699
3700 case cSec:
3701 for(Nbval=0; Nbval<NbStack; Nbval++)
3702 {
3703 const Value_t c = fp_cos(Stacki[Nbval*Size+SP]);
3704 if(c == Value_t(0))
3705 {
3706 mData->mEvalErrorType=DIVISION_BY_ZERO;
3707 return Value_t(1);
3708 }
3709 Stacki[Nbval*Size+SP] = Value_t(1)/c;
3710 }
3711 break;
3712 case cSin:
3713 for(Nbval=0; Nbval<NbStack; Nbval++)
3714 Stacki[Nbval*Size+SP] = fp_sin(Stacki[Nbval*Size+SP]);
3715 break;
3716
3717 case cSinh:
3718 for(Nbval=0; Nbval<NbStack; Nbval++)
3719 Stacki[Nbval*Size+SP] = fp_sinh(Stacki[Nbval*Size+SP]);
3720 break;
3721
3722 case cSqrt:
3723 for(Nbval=0; Nbval<NbStack; Nbval++)
3724 {
3725 if(IsComplexType<Value_t>::result == false &&
3726 Stacki[Nbval*Size+SP] < Value_t(0))
3727 {
3728 mData->mEvalErrorType=2;
3729 return Value_t(0);
3730 }
3731 Stacki[Nbval*Size+SP] = fp_sqrt(Stacki[Nbval*Size+SP]);
3732 }
3733 break;
3734
3735 case cTan:
3736 for(Nbval=0; Nbval<NbStack; Nbval++)
3737 Stacki[Nbval*Size+SP] = fp_tan(Stacki[Nbval*Size+SP]);
3738 break;
3739
3740 case cTanh:
3741 for(Nbval=0; Nbval<NbStack; Nbval++)
3742 Stacki[Nbval*Size+SP] = fp_tanh(Stacki[Nbval*Size+SP]);
3743 break;
3744
3745
3746 // Misc:
3747 case cImmed:
3748 ++SP;
3749 for(Nbval=0; Nbval<NbStack; Nbval++)
3750 Stacki[Nbval*Size+SP] = immed[DP];
3751 DP++;
3752 break;
3753 case cJump:
3754 {
3755 const unsigned* buf = &byteCode[IP+1];
3756 IP = buf[0];
3757 DP = buf[1];
3758 break;
3759 }
3760 // Operators:
3761 case cNeg:
3762 for(Nbval=0; Nbval<NbStack; Nbval++)
3763 Stacki[Nbval*Size+SP] = -Stacki[Nbval*Size+SP];
3764 break;
3765 case cAdd:
3766 for(Nbval=0; Nbval<NbStack; Nbval++)
3767 Stacki[Nbval*Size+SP-1] += Stacki[Nbval*Size+SP];
3768 --SP;
3769 break;
3770 case cSub:
3771 for(Nbval=0; Nbval<NbStack; Nbval++)
3772 Stacki[Nbval*Size+SP-1] -= Stacki[Nbval*Size+SP];
3773 --SP;
3774 break;
3775 case cMul:
3776 for(Nbval=0; Nbval<NbStack; Nbval++)
3777 Stacki[Nbval*Size+SP-1] *= Stacki[Nbval*Size+SP];
3778 --SP;
3779 break;
3780 case cDiv:
3781 for(Nbval=0; Nbval<NbStack; Nbval++)
3782 {
3783 if(Stacki[Nbval*Size+SP] == Value_t(0))
3784 {
3785 mData->mEvalErrorType=DIVISION_BY_ZERO;
3786 return Value_t(1);
3787 }
3788 Stacki[Nbval*Size+SP-1] /= Stacki[Nbval*Size+SP];
3789 }
3790 --SP; break;
3791 case cMod:
3792 for(Nbval=0; Nbval<NbStack; Nbval++)
3793 {
3794 if(Stacki[Nbval*Size+SP] == Value_t(0))
3795 {
3796 mData->mEvalErrorType=DIVISION_BY_ZERO;
3797 return Value_t(0);
3798 }
3799 Stacki[Nbval*Size+SP-1] = fp_mod(Stacki[Nbval*Size+SP-1], Stacki[Nbval*Size+SP]);
3800 }
3801 --SP;
3802 break;
3803 case cEqual:
3804 for(Nbval=0; Nbval<NbStack; Nbval++)
3805 Stacki[Nbval*Size+SP-1] = fp_equal(Stacki[Nbval*Size+SP-1], Stacki[Nbval*Size+SP]);
3806 --SP;
3807 break;
3808 case cNEqual:
3809 for(Nbval=0; Nbval<NbStack; Nbval++)
3810 Stacki[Nbval*Size+SP-1] = fp_nequal(Stacki[Nbval*Size+SP-1], Stacki[Nbval*Size+SP]);
3811 --SP;
3812 break;
3813 case cLess:
3814 for(Nbval=0; Nbval<NbStack; Nbval++)
3815 Stacki[Nbval*Size+SP-1] = fp_less(Stacki[Nbval*Size+SP-1], Stacki[Nbval*Size+SP]);
3816 --SP;
3817 break;
3818
3819 case cLessOrEq:
3820 for(Nbval=0; Nbval<NbStack; Nbval++)
3821 Stacki[Nbval*Size+SP-1] = fp_lessOrEq(Stacki[Nbval*Size+SP-1], Stacki[Nbval*Size+SP]);
3822 --SP;
3823 break;
3824
3825 case cGreater:
3826 for(Nbval=0; Nbval<NbStack; Nbval++)
3827 Stacki[Nbval*Size+SP-1] = fp_less(Stacki[Nbval*Size+SP], Stacki[Nbval*Size+SP-1]);
3828 --SP;
3829 break;
3830
3831 case cGreaterOrEq:
3832 for(Nbval=0; Nbval<NbStack; Nbval++)
3833 Stacki[Nbval*Size+SP-1] = fp_lessOrEq(Stacki[Nbval*Size+SP], Stacki[Nbval*Size+SP-1]);
3834 --SP;
3835 break;
3836
3837 case cNot:
3838 for(Nbval=0; Nbval<NbStack; Nbval++)
3839 Stacki[Nbval*Size+SP] = fp_not(Stacki[Nbval*Size+SP]);
3840 break;
3841
3842 case cNotNot:
3843 for(Nbval=0; Nbval<NbStack; Nbval++)
3844 Stacki[Nbval*Size+SP] = fp_notNot(Stacki[Nbval*Size+SP]);
3845 break;
3846
3847 case cAnd:
3848 for(Nbval=0; Nbval<NbStack; Nbval++)
3849 Stacki[Nbval*Size+SP-1] = fp_and(Stacki[Nbval*Size+SP-1], Stacki[Nbval*Size+SP]);
3850 --SP;
3851 break;
3852
3853 case cOr:
3854 for(Nbval=0; Nbval<NbStack; Nbval++)
3855 Stacki[Nbval*Size+SP-1] = fp_or(Stacki[Nbval*Size+SP-1], Stacki[Nbval*Size+SP]);
3856 --SP;
3857 break;
3858
3859 // Degrees-radians conversion:
3860 case cDeg:
3861 for(Nbval=0; Nbval<NbStack; Nbval++)
3862 Stacki[Nbval*Size+SP] = RadiansToDegrees(Stacki[Nbval*Size+SP]);
3863 break;
3864 case cRad:
3865 for(Nbval=0; Nbval<NbStack; Nbval++)
3866 Stacki[Nbval*Size+SP] = DegreesToRadians(Stacki[Nbval*Size+SP]);
3867 break;
3868
3869 // User-defined function calls:
3870 case cFCall:
3871 {
3872 const unsigned index = byteCode[++IP];
3873 const unsigned params = mData->mFuncPtrs[index].mParams;
3874 for(Nbval=0; Nbval<NbStack; Nbval++)
3875 {
3876 const Value_t retVal =
3877 mData->mFuncPtrs[index].mRawFuncPtr ?
3878 mData->mFuncPtrs[index].mRawFuncPtr(&(Stacki[Nbval*Size+SP-params+1])) :
3879 mData->mFuncPtrs[index].mFuncWrapperPtr->callFunction
3880 (&Stacki[Nbval*Size+SP-params+1]);
3881 Stacki[Nbval*Size+SP-(int(params)-1)] = retVal;
3882 }
3883 SP -= int(params)-1;
3884 break;
3885 }
3886
3887 case cFetch:
3888 {
3889 unsigned stackOffs = byteCode[++IP];
3890 for(Nbval=0; Nbval<NbStack; Nbval++)
3891 Stacki[Nbval*Size+SP+1] = Stacki[Nbval*Size+stackOffs];
3892 ++SP;
3893 break;
3894 }
3895
3896 #ifdef FP_SUPPORT_OPTIMIZER
3897 case cPopNMov:
3898 {
3899 unsigned stackOffs_target = byteCode[++IP];
3900 unsigned stackOffs_source = byteCode[++IP];
3901 for(Nbval=0; Nbval<NbStack; Nbval++)
3902 Stacki[Nbval*Size+stackOffs_target] = Stacki[Nbval*Size+stackOffs_source];
3903 SP = stackOffs_target;
3904 break;
3905 }
3906
3907 case cLog2by:
3908 for(Nbval=0; Nbval<NbStack; Nbval++)
3909 {
3910 if(IsComplexType<Value_t>::result
3911 ? Stacki[Nbval*Size+SP-1] == Value_t(0)
3912 : !(Stacki[Nbval*Size+SP-1] > Value_t(0)))
3913 { mData->mEvalErrorType=3; return Value_t(0); }
3914 Stacki[Nbval*Size+SP-1] = fp_log2(Stacki[Nbval*Size+SP-1]) * Stacki[Nbval*Size+SP];
3915 }
3916 --SP;
3917 break;
3918
3919 case cNop: break;
3920 #endif // FP_SUPPORT_OPTIMIZER
3921
3922 case cSinCos:
3923 for(Nbval=0; Nbval<NbStack; Nbval++)
3924 fp_sinCos(Stacki[Nbval*Size+SP], Stacki[Nbval*Size+SP+1], Stacki[Nbval*Size+SP]);
3925 ++SP;
3926 break;
3927 case cSinhCosh:
3928 for(Nbval=0; Nbval<NbStack; Nbval++)
3929 fp_sinhCosh(Stacki[Nbval*Size+SP], Stacki[Nbval*Size+SP+1], Stacki[Nbval*Size+SP]);
3930 ++SP;
3931 break;
3932
3933 case cAbsNot:
3934 for(Nbval=0; Nbval<NbStack; Nbval++)
3935 Stacki[Nbval*Size+SP] = fp_absNot(Stacki[Nbval*Size+SP]);
3936 break;
3937 case cAbsNotNot:
3938 for(Nbval=0; Nbval<NbStack; Nbval++)
3939 Stacki[Nbval*Size+SP] = fp_absNotNot(Stacki[Nbval*Size+SP]);
3940 break;
3941 case cAbsAnd:
3942 for(Nbval=0; Nbval<NbStack; Nbval++)
3943 Stacki[Nbval*Size+SP-1] = fp_absAnd(Stacki[Nbval*Size+SP-1], Stacki[Nbval*Size+SP]);
3944 --SP; break;
3945 case cAbsOr:
3946 for(Nbval=0; Nbval<NbStack; Nbval++)
3947 Stacki[Nbval*Size+SP-1] = fp_absOr(Stacki[Nbval*Size+SP-1], Stacki[Nbval*Size+SP]);
3948 --SP; break;
3949 case cAbsIf:
3950 {
3951 bool valid = fp_absTruth(Stacki[SP]);
3952
3953 for(Nbval=1; Nbval<NbStack; Nbval++)
3954 if(valid != fp_absTruth(Stacki[Nbval*Size+SP]))
3955 { mData->mEvalErrorType=IF_FUNCT_ERROR; return Value_t(5); }
3956
3957 if(valid)
3958 IP += 2;
3959 else
3960 {
3961 const unsigned* buf = &byteCode[IP+1];
3962 IP = buf[0];
3963 DP = buf[1];
3964 }
3965 }
3966 SP--;
3967 break;
3968 case cDup:
3969 for(Nbval=0; Nbval<NbStack; Nbval++)
3970 Stacki[Nbval*Size+SP+1] = Stacki[Nbval*Size+SP];
3971 ++SP; break;
3972
3973 case cInv:
3974 for(Nbval=0; Nbval<NbStack; Nbval++)
3975 {
3976 if(Stacki[Nbval*Size+SP] == Value_t(0))
3977 { mData->mEvalErrorType=DIVISION_BY_ZERO; return Value_t(1); }
3978 Stacki[Nbval*Size+SP] = Value_t(1)/Stacki[Nbval*Size+SP];
3979 }
3980 break;
3981
3982 case cSqr:
3983 for(Nbval=0; Nbval<NbStack; Nbval++)
3984 Stacki[Nbval*Size+SP] = Stacki[Nbval*Size+SP]*Stacki[Nbval*Size+SP];
3985 break;
3986
3987 case cRDiv:
3988 for(Nbval=0; Nbval<NbStack; Nbval++)
3989 {
3990 if(Stacki[Nbval*Size+SP-1] == Value_t(0))
3991 { mData->mEvalErrorType=DIVISION_BY_ZERO; return Value_t(1); }
3992 Stacki[Nbval*Size+SP-1] = Stacki[Nbval*Size+SP] / Stacki[Nbval*Size+SP-1];
3993 }
3994 --SP; break;
3995
3996 case cRSub:
3997 for(Nbval=0; Nbval<NbStack; Nbval++)
3998 Stacki[Nbval*Size+SP-1] = Stacki[Nbval*Size+SP] - Stacki[Nbval*Size+SP-1];
3999 --SP; break;
4000
4001 case cRSqrt:
4002 for(Nbval=0; Nbval<NbStack; Nbval++)
4003 {
4004 if(Stacki[Nbval*Size+SP] == Value_t(0))
4005 { mData->mEvalErrorType=DIVISION_BY_ZERO; return Value_t(1); }
4006 Stacki[Nbval*Size+SP] = Value_t(1) / fp_sqrt(Stacki[Nbval*Size+SP]);
4007 }
4008 break;
4009
4010 #ifdef FP_SUPPORT_COMPLEX_NUMBERS
4011 case cReal:
4012 for(Nbval=0; Nbval<NbStack; Nbval++)
4013 Stacki[Nbval*Size+SP] = fp_real(Stacki[Nbval*Size+SP]);
4014 break;
4015 case cImag:
4016 for(Nbval=0; Nbval<NbStack; Nbval++)
4017 Stacki[Nbval*Size+SP] = fp_imag(Stacki[Nbval*Size+SP]);
4018 break;
4019 case cArg:
4020 for(Nbval=0; Nbval<NbStack; Nbval++)
4021 Stacki[Nbval*Size+SP] = fp_arg(Stacki[Nbval*Size+SP]);
4022 break;
4023 case cConj:
4024 for(Nbval=0; Nbval<NbStack; Nbval++)
4025 Stacki[Nbval*Size+SP] = fp_conj(Stacki[Nbval*Size+SP]);
4026 break;
4027 case cPolar:
4028 for(Nbval=0; Nbval<NbStack; Nbval++)
4029 Stacki[Nbval*Size+SP-1] = fp_polar(Stacki[Nbval*Size+SP-1], Stacki[Nbval*Size+SP]);
4030 --SP;
4031 break;
4032 #endif
4033
4034 case cPCall:
4035 {
4036 unsigned index = byteCode[++IP];
4037 unsigned params = mData->mFuncParsers[index].mParams;
4038 Value_t res[NbStack];
4039 Value_t rest=mData->mFuncParsers[index].mParserPtr->Eval2
4040 (&(Stacki[SP-params+1]), Size, res, NbStack);
4041 if (rest == Value_t(5))
4042 {
4043 mData->mEvalErrorType = IF_FUNCT_ERROR;
4044 return Value_t(mData->mEvalErrorType);
4045 }
4046 if (rest == Value_t(7))
4047 {
4048 mData->mEvalErrorType = VAR_OVERFLOW;
4049 return Value_t(7);
4050 }
4051 for(Nbval=0; Nbval<NbStack; Nbval++)
4052 {
4053 Stacki[Nbval*Size+SP - (int(params)-1)] = res[Nbval];
4054 }
4055 SP -= int(params)-1;
4056 break;
4057 }
4058 // Variables:
4059 default:
4060 ++SP;
4061 for(Nbval=0; Nbval<NbStack; Nbval++)
4062 Stacki[Nbval*Size+SP] = Vars[byteCode[IP]+ NbVar*Nbval-VarBegin];
4063 }
4064 }
4065
4066 mData->mEvalErrorType=EVAL_NO_ERROR;
4067 for(Nbval=0; Nbval<NbStack; Nbval++)
4068 results[Nbval] = Stacki[Nbval*Size+SP];
4069 return Value_t(Value_t(6));
4070 }
4071
4072
4073 //===========================================================================
4074 // Variable deduction
4075 //===========================================================================
4076 namespace
4077 {
4078 template<typename Value_t>
deduceVariables(FunctionParserBase<Value_t> & fParser,const char * funcStr,std::string & destVarString,int * amountOfVariablesFound,std::vector<std::string> * destVarNames,bool useDegrees)4079 int deduceVariables(FunctionParserBase<Value_t>& fParser,
4080 const char* funcStr,
4081 std::string& destVarString,
4082 int* amountOfVariablesFound,
4083 std::vector<std::string>* destVarNames,
4084 bool useDegrees)
4085 {
4086 typedef std::set<std::string> StrSet;
4087 StrSet varNames;
4088
4089 int oldIndex = -1;
4090
4091 while(true)
4092 {
4093 destVarString.clear();
4094 for(StrSet::iterator iter = varNames.begin();
4095 iter != varNames.end();
4096 ++iter)
4097 {
4098 if(iter != varNames.begin()) destVarString += ",";
4099 destVarString += *iter;
4100 }
4101
4102 const int index =
4103 fParser.Parse(funcStr, destVarString, useDegrees);
4104 if(index < 0) break;
4105 if(index == oldIndex) return index;
4106
4107 unsigned nameLength = readIdentifier<Value_t>(funcStr + index);
4108 if(nameLength & 0x80000000U) return index;
4109 if(nameLength == 0) return index;
4110
4111 varNames.insert(std::string(funcStr + index, nameLength));
4112 oldIndex = index;
4113 }
4114
4115 if(amountOfVariablesFound)
4116 *amountOfVariablesFound = int(varNames.size());
4117
4118 if(destVarNames)
4119 destVarNames->assign(varNames.begin(), varNames.end());
4120
4121 return -1;
4122 }
4123 }
4124
4125 template<typename Value_t>
ParseAndDeduceVariables(const std::string & function,int * amountOfVariablesFound,bool useDegrees)4126 int FunctionParserBase<Value_t>::ParseAndDeduceVariables
4127 (const std::string& function,
4128 int* amountOfVariablesFound,
4129 bool useDegrees)
4130 {
4131 std::string varString;
4132 return deduceVariables(*this, function.c_str(), varString,
4133 amountOfVariablesFound, 0, useDegrees);
4134 }
4135
4136 template<typename Value_t>
ParseAndDeduceVariables(const std::string & function,std::string & resultVarString,int * amountOfVariablesFound,bool useDegrees)4137 int FunctionParserBase<Value_t>::ParseAndDeduceVariables
4138 (const std::string& function,
4139 std::string& resultVarString,
4140 int* amountOfVariablesFound,
4141 bool useDegrees)
4142 {
4143 std::string varString;
4144 const int index =
4145 deduceVariables(*this, function.c_str(), varString,
4146 amountOfVariablesFound, 0, useDegrees);
4147 if(index < 0) resultVarString = varString;
4148 return index;
4149 }
4150
4151 template<typename Value_t>
ParseAndDeduceVariables(const std::string & function,std::vector<std::string> & resultVars,bool useDegrees)4152 int FunctionParserBase<Value_t>::ParseAndDeduceVariables
4153 (const std::string& function,
4154 std::vector<std::string>& resultVars,
4155 bool useDegrees)
4156 {
4157 std::string varString;
4158 std::vector<std::string> vars;
4159 const int index =
4160 deduceVariables(*this, function.c_str(), varString,
4161 0, &vars, useDegrees);
4162 if(index < 0) resultVars.swap(vars);
4163 return index;
4164 }
4165
4166
4167 #ifdef FUNCTIONPARSER_SUPPORT_DEBUGGING
4168 //===========================================================================
4169 // Bytecode injection
4170 //===========================================================================
4171 template<typename Value_t>
InjectRawByteCode(const unsigned * bytecode,unsigned bytecodeAmount,const Value_t * immed,unsigned immedAmount,unsigned stackSize)4172 void FunctionParserBase<Value_t>::InjectRawByteCode
4173 (const unsigned* bytecode, unsigned bytecodeAmount,
4174 const Value_t* immed, unsigned immedAmount, unsigned stackSize)
4175 {
4176 CopyOnWrite();
4177
4178 mData->mByteCode.assign(bytecode, bytecode + bytecodeAmount);
4179 mData->mImmed.assign(immed, immed + immedAmount);
4180 mData->mStackSize = stackSize;
4181
4182 #ifndef FP_USE_THREAD_SAFE_EVAL
4183 mData->mStack.resize(stackSize);
4184 //mData->mStacki.resize(64*mData->mStackSize);
4185 #endif
4186 }
4187
4188 //===========================================================================
4189 // Debug output
4190 //===========================================================================
4191 #include <iomanip>
4192 #include <sstream>
4193 namespace
4194 {
printHex(std::ostream & dest,unsigned n)4195 inline void printHex(std::ostream& dest, unsigned n)
4196 {
4197 std::ios::fmtflags flags = dest.flags();
4198 dest.width(4); dest.fill('0'); std::hex(dest); //uppercase(dest);
4199 dest << n;
4200 dest.flags(flags);
4201 }
4202
padLine(std::ostringstream & dest,unsigned destLength)4203 void padLine(std::ostringstream& dest, unsigned destLength)
4204 {
4205 for(std::size_t currentLength = dest.str().length();
4206 currentLength < destLength;
4207 ++currentLength)
4208 {
4209 dest << ' ';
4210 }
4211 }
4212
4213 const struct PowiMuliType
4214 {
4215 unsigned opcode_square;
4216 unsigned opcode_cumulate;
4217 unsigned opcode_invert;
4218 unsigned opcode_half;
4219 unsigned opcode_invhalf;
4220 } iseq_powi = {cSqr,cMul,cInv,cSqrt,cRSqrt},
4221 iseq_muli = {~unsigned(0), cAdd,cNeg, ~unsigned(0),~unsigned(0) };
4222
4223 template<typename Value_t>
ParsePowiMuli(const PowiMuliType & opcodes,const std::vector<unsigned> & ByteCode,unsigned & IP,unsigned limit,std::size_t factor_stack_base,std::vector<Value_t> & stack,bool IgnoreExcess)4224 Value_t ParsePowiMuli(
4225 const PowiMuliType& opcodes,
4226 const std::vector<unsigned>& ByteCode, unsigned& IP,
4227 unsigned limit,
4228 std::size_t factor_stack_base,
4229 std::vector<Value_t>& stack,
4230 bool IgnoreExcess)
4231 {
4232 Value_t result = Value_t(1);
4233 while(IP < limit)
4234 {
4235 if(ByteCode[IP] == opcodes.opcode_square)
4236 {
4237 if(!isInteger(result)) break;
4238 result *= Value_t(2);
4239 ++IP;
4240 continue;
4241 }
4242 if(ByteCode[IP] == opcodes.opcode_invert)
4243 {
4244 if(result < Value_t(0)) break;
4245 result = -result;
4246 ++IP;
4247 continue;
4248 }
4249 if(ByteCode[IP] == opcodes.opcode_half)
4250 {
4251 if(result > Value_t(0) && isEvenInteger(result))
4252 break;
4253 if(isInteger(result * Value_t(0.5))) break;
4254 result *= Value_t(0.5);
4255 ++IP;
4256 continue;
4257 }
4258 if(ByteCode[IP] == opcodes.opcode_invhalf)
4259 {
4260 if(result > Value_t(0) && isEvenInteger(result))
4261 break;
4262 if(isInteger(result * Value_t(-0.5))) break;
4263 result *= Value_t(-0.5);
4264 ++IP;
4265 continue;
4266 }
4267
4268 unsigned dup_fetch_pos = IP;
4269 Value_t lhs = Value_t(1);
4270
4271 if(ByteCode[IP] == cFetch)
4272 {
4273 unsigned index = ByteCode[++IP];
4274 if(index < factor_stack_base
4275 || std::size_t(index-factor_stack_base) >= stack.size())
4276 {
4277 // It wasn't a powi-fetch after all
4278 IP = dup_fetch_pos;
4279 break;
4280 }
4281 lhs = stack[index - factor_stack_base];
4282 // Note: ^This assumes that cFetch of recentmost
4283 // is always converted into cDup.
4284 goto dup_or_fetch;
4285 }
4286
4287 if(ByteCode[IP] == cDup)
4288 {
4289 lhs = result;
4290 goto dup_or_fetch;
4291
4292 dup_or_fetch:
4293 stack.push_back(result);
4294 ++IP;
4295 Value_t subexponent = ParsePowiMuli
4296 (opcodes,
4297 ByteCode, IP, limit,
4298 factor_stack_base, stack,
4299 IgnoreExcess);
4300 if(IP >= limit && IgnoreExcess)
4301 return lhs*subexponent;
4302 if(IP >= limit || ByteCode[IP] != opcodes.opcode_cumulate)
4303 {
4304 // It wasn't a powi-dup after all
4305 IP = dup_fetch_pos;
4306 break;
4307 }
4308 ++IP; // skip opcode_cumulate
4309 stack.pop_back();
4310 result += lhs*subexponent;
4311 continue;
4312 }
4313 break;
4314 }
4315 return result;
4316 }
4317
4318 template<typename Value_t>
ParsePowiSequence(const std::vector<unsigned> & ByteCode,unsigned & IP,unsigned limit,std::size_t factor_stack_base,bool IgnoreExcess=false)4319 Value_t ParsePowiSequence(const std::vector<unsigned>& ByteCode,
4320 unsigned& IP, unsigned limit,
4321 std::size_t factor_stack_base,
4322 bool IgnoreExcess = false)
4323 {
4324 std::vector<Value_t> stack;
4325 stack.push_back(Value_t(1));
4326 return ParsePowiMuli(iseq_powi, ByteCode, IP, limit,
4327 factor_stack_base, stack,
4328 IgnoreExcess);
4329 }
4330
4331 template<typename Value_t>
ParseMuliSequence(const std::vector<unsigned> & ByteCode,unsigned & IP,unsigned limit,std::size_t factor_stack_base,bool IgnoreExcess=false)4332 Value_t ParseMuliSequence(const std::vector<unsigned>& ByteCode,
4333 unsigned& IP, unsigned limit,
4334 std::size_t factor_stack_base,
4335 bool IgnoreExcess = false)
4336 {
4337 std::vector<Value_t> stack;
4338 stack.push_back(Value_t(1));
4339 return ParsePowiMuli(iseq_muli, ByteCode, IP, limit,
4340 factor_stack_base, stack,
4341 IgnoreExcess);
4342 }
4343
4344 struct IfInfo
4345 {
4346 std::pair<int,std::string> condition;
4347 std::pair<int,std::string> thenbranch;
4348 unsigned endif_location;
4349
IfInfo__anon65dca5ac0c11::IfInfo4350 IfInfo() : condition(), thenbranch(), endif_location() { }
4351 };
4352 }
4353
4354 template<typename Value_t>
PrintByteCode(std::ostream & dest,bool showExpression) const4355 void FunctionParserBase<Value_t>::PrintByteCode(std::ostream& dest,
4356 bool showExpression) const
4357 {
4358 dest << "Size of stack: " << mData->mStackSize << "\n";
4359
4360 std::ostringstream outputBuffer;
4361 std::ostream& output = (showExpression ? outputBuffer : dest);
4362
4363 const std::vector<unsigned>& ByteCode = mData->mByteCode;
4364 const std::vector<Value_t>& Immed = mData->mImmed;
4365
4366 std::vector<std::pair<int,std::string> > stack;
4367 std::vector<IfInfo> if_stack;
4368
4369 for(unsigned IP = 0, DP = 0; IP <= ByteCode.size(); ++IP)
4370 {
4371 after_powi_or_muli:;
4372 std::string n;
4373 bool out_params = false;
4374 unsigned params = 2, produces = 1, opcode = 0;
4375
4376 if(showExpression && !if_stack.empty() &&
4377 ( // Normal If termination rule:
4378 if_stack.back().endif_location == IP
4379 // This rule matches when cJumps are threaded:
4380 || (IP < ByteCode.size() && ByteCode[IP] == cJump
4381 && !if_stack.back().thenbranch.second.empty())
4382 ))
4383 {
4384 printHex(output, IP);
4385 if(if_stack.back().endif_location == IP)
4386 output << ": ----- (phi)";
4387 else
4388 output << ": ----- (phi+)";
4389
4390 stack.resize(stack.size()+2);
4391 std::swap(stack[stack.size()-3], stack[stack.size()-1]);
4392 std::swap(if_stack.back().condition, stack[stack.size()-3]);
4393 std::swap(if_stack.back().thenbranch, stack[stack.size()-2]);
4394 opcode = cIf;
4395 params = 3;
4396 --IP;
4397 if_stack.pop_back();
4398 }
4399 else
4400 {
4401 if(IP >= ByteCode.size()) break;
4402 opcode = ByteCode[IP];
4403
4404 if(showExpression && (
4405 opcode == cSqr || opcode == cDup
4406 || opcode == cInv
4407 || opcode == cSqrt || opcode == cRSqrt
4408 || opcode == cFetch
4409 ))
4410 {
4411 unsigned changed_ip = IP;
4412 Value_t exponent =
4413 ParsePowiSequence<Value_t>
4414 (ByteCode, changed_ip,
4415 if_stack.empty()
4416 ? (unsigned)ByteCode.size()
4417 : if_stack.back().endif_location,
4418 stack.size()-1);
4419 std::string operation_prefix;
4420 std::ostringstream operation_value;
4421 int prio = 0;
4422 if(exponent == Value_t(1.0))
4423 {
4424 if(opcode != cDup) goto not_powi_or_muli;
4425 Value_t factor =
4426 ParseMuliSequence<Value_t>
4427 (ByteCode, changed_ip,
4428 if_stack.empty()
4429 ? (unsigned)ByteCode.size()
4430 : if_stack.back().endif_location,
4431 stack.size()-1);
4432 if(factor == Value_t(1) || factor == Value_t(-1))
4433 goto not_powi_or_muli;
4434 operation_prefix = "*";
4435 operation_value << factor;
4436 prio = 3;
4437 }
4438 else
4439 {
4440 prio = 2;
4441 operation_prefix = "^";
4442 operation_value << exponent;
4443 }
4444
4445 //unsigned explanation_before = changed_ip-2;
4446 unsigned explanation_before = changed_ip-1;
4447
4448 const char* explanation_prefix = "_";
4449 for(const unsigned first_ip = IP; IP < changed_ip; ++IP)
4450 {
4451 printHex(output, IP);
4452 output << ": ";
4453
4454 const char* sep = "|";
4455 if(first_ip+1 == changed_ip)
4456 { sep = "="; explanation_prefix = " "; }
4457 else if(IP == first_ip) sep = "\\";
4458 else if(IP+1 == changed_ip) sep = "/";
4459 else explanation_prefix = "=";
4460
4461 switch(ByteCode[IP])
4462 {
4463 case cInv: output << "inv"; break;
4464 case cNeg: output << "neg"; break;
4465 case cDup: output << "dup"; break;
4466 case cSqr: output << "sqr"; break;
4467 case cMul: output << "mul"; break;
4468 case cAdd: output << "add"; break;
4469 case cCbrt: output << "cbrt"; break;
4470 case cSqrt: output << "sqrt"; break;
4471 case cRSqrt: output << "rsqrt"; break;
4472 case cFetch:
4473 {
4474 unsigned index = ByteCode[++IP];
4475 output << "cFetch(" << index << ")";
4476 break;
4477 }
4478 default: break;
4479 }
4480 padLine(outputBuffer, 20);
4481 output << sep;
4482 if(IP >= explanation_before)
4483 {
4484 explanation_before = (unsigned)ByteCode.size();
4485 output << explanation_prefix
4486 << '[' << (stack.size()-1) << ']';
4487 std::string last = stack.back().second;
4488 if(stack.back().first >= prio)
4489 last = "(" + last + ")";
4490 output << last;
4491 output << operation_prefix;
4492 output << operation_value.str();
4493 }
4494 else
4495 {
4496 unsigned p = first_ip;
4497 Value_t exp = operation_prefix=="^" ?
4498 ParsePowiSequence<Value_t>
4499 (ByteCode, p, IP+1, stack.size()-1, true) :
4500 ParseMuliSequence<Value_t>
4501 (ByteCode, p, IP+1, stack.size()-1, true);
4502 std::string last = stack.back().second;
4503 if(stack.back().first >= prio)
4504 last = "(" + last + ")";
4505 output << " ..." << last;
4506 output << operation_prefix;
4507 output << exp;
4508 }
4509 dest << outputBuffer.str() << std::endl;
4510 outputBuffer.str("");
4511 }
4512
4513 std::string& last = stack.back().second;
4514 if(stack.back().first >= prio)
4515 last = "(" + last + ")";
4516 last += operation_prefix;
4517 last += operation_value.str();
4518 stack.back().first = prio;
4519
4520 goto after_powi_or_muli;
4521 }
4522 not_powi_or_muli:;
4523 printHex(output, IP);
4524 output << ": ";
4525
4526 switch(opcode)
4527 {
4528 case cIf:
4529 {
4530 unsigned label = ByteCode[IP+1]+1;
4531 output << "jz ";
4532 printHex(output, label);
4533 params = 1;
4534 produces = 0;
4535 IP += 2;
4536
4537 if_stack.resize(if_stack.size() + 1);
4538 std::swap( if_stack.back().condition, stack.back() );
4539 if_stack.back().endif_location = (unsigned) ByteCode.size();
4540 stack.pop_back();
4541 break;
4542 }
4543 case cAbsIf:
4544 {
4545 unsigned dp = ByteCode[IP+2];
4546 unsigned label = ByteCode[IP+1]+1;
4547 output << "jz_abs " << dp << ",";
4548 printHex(output, label);
4549 params = 1;
4550 produces = 0;
4551 IP += 2;
4552
4553 if_stack.resize(if_stack.size() + 1);
4554 std::swap( if_stack.back().condition, stack.back() );
4555 if_stack.back().endif_location = (unsigned) ByteCode.size();
4556 stack.pop_back();
4557 break;
4558 }
4559
4560 case cJump:
4561 {
4562 unsigned dp = ByteCode[IP+2];
4563 unsigned label = ByteCode[IP+1]+1;
4564
4565 if(!if_stack.empty() && !stack.empty())
4566 {
4567 std::swap(if_stack.back().thenbranch, stack.back());
4568 if_stack.back().endif_location = label;
4569 stack.pop_back();
4570 }
4571
4572 output << "jump " << dp << ",";
4573 printHex(output, label);
4574 params = 0;
4575 produces = 0;
4576 IP += 2;
4577 break;
4578 }
4579 case cImmed:
4580 {
4581 if(showExpression)
4582 {
4583 std::ostringstream buf;
4584 buf.precision(8);
4585 buf << Immed[DP];
4586 stack.push_back( std::make_pair(0, buf.str()) );
4587 }
4588 output.precision(8);
4589 output << "push " << Immed[DP];
4590 ++DP;
4591 produces = 0;
4592 break;
4593 }
4594
4595 case cFCall:
4596 {
4597 const unsigned index = ByteCode[++IP];
4598 params = mData->mFuncPtrs[index].mParams;
4599 static std::string name;
4600 name = "f:" + findName(mData->mNamePtrs, index,
4601 NameData<Value_t>::FUNC_PTR);
4602 n = name.c_str();
4603 out_params = true;
4604 break;
4605 }
4606
4607 case cPCall:
4608 {
4609 const unsigned index = ByteCode[++IP];
4610 params = mData->mFuncParsers[index].mParams;
4611 static std::string name;
4612 name = "p:" + findName(mData->mNamePtrs, index,
4613 NameData<Value_t>::PARSER_PTR);
4614 n = name.c_str();
4615 out_params = true;
4616 break;
4617 }
4618
4619 default:
4620 if(IsVarOpcode(opcode))
4621 {
4622 if(showExpression)
4623 {
4624 stack.push_back(std::make_pair(0,
4625 (findName(mData->mNamePtrs, opcode,
4626 NameData<Value_t>::VARIABLE))));
4627 }
4628 output << "push Var" << opcode-VarBegin;
4629 produces = 0;
4630 }
4631 else
4632 {
4633 switch(OPCODE(opcode))
4634 {
4635 case cNeg: n = "neg"; params = 1; break;
4636 case cAdd: n = "add"; break;
4637 case cSub: n = "sub"; break;
4638 case cMul: n = "mul"; break;
4639 case cDiv: n = "div"; break;
4640 case cMod: n = "mod"; break;
4641 case cPow: n = "pow"; break;
4642 case cEqual: n = "eq"; break;
4643 case cNEqual: n = "neq"; break;
4644 case cLess: n = "lt"; break;
4645 case cLessOrEq: n = "le"; break;
4646 case cGreater: n = "gt"; break;
4647 case cGreaterOrEq: n = "ge"; break;
4648 case cAnd: n = "and"; break;
4649 case cOr: n = "or"; break;
4650 case cNot: n = "not"; params = 1; break;
4651 case cNotNot: n = "notnot"; params = 1; break;
4652 case cDeg: n = "deg"; params = 1; break;
4653 case cRad: n = "rad"; params = 1; break;
4654
4655 case cFetch:
4656 {
4657 unsigned index = ByteCode[++IP];
4658 if(showExpression && index < stack.size())
4659 stack.push_back(stack[index]);
4660 output << "cFetch(" << index << ")";
4661 produces = 0;
4662 break;
4663 }
4664 #ifdef FP_SUPPORT_OPTIMIZER
4665 case cLog2by: n = "log2by"; params = 2; out_params = 1; break;
4666 case cPopNMov:
4667 {
4668 std::size_t a = ByteCode[++IP];
4669 std::size_t b = ByteCode[++IP];
4670 if(showExpression && b < stack.size())
4671 {
4672 std::pair<int, std::string> stacktop(0, "?");
4673 if(b < stack.size()) stacktop = stack[b];
4674 stack.resize(a);
4675 stack.push_back(stacktop);
4676 }
4677 output << "cPopNMov(" << a << ", " << b << ")";
4678 produces = 0;
4679 break;
4680 }
4681 case cNop:
4682 output << "nop"; params = 0; produces = 0;
4683 break;
4684 #endif
4685 case cSinCos:
4686 {
4687 if(showExpression)
4688 {
4689 std::pair<int, std::string> sin = stack.back();
4690 std::pair<int, std::string> cos(
4691 0, "cos(" + sin.second + ")");
4692 sin.first = 0;
4693 sin.second = "sin(" + sin.second + ")";
4694 stack.back() = sin;
4695 stack.push_back(cos);
4696 }
4697 output << "sincos";
4698 produces = 0;
4699 break;
4700 }
4701 case cSinhCosh:
4702 {
4703 if(showExpression)
4704 {
4705 std::pair<int, std::string> sinh = stack.back();
4706 std::pair<int, std::string> cosh(
4707 0, "cosh(" + sinh.second + ")");
4708 sinh.first = 0;
4709 sinh.second = "sinh(" + sinh.second + ")";
4710 stack.back() = sinh;
4711 stack.push_back(cosh);
4712 }
4713 output << "sinhcosh";
4714 produces = 0;
4715 break;
4716 }
4717 case cAbsAnd: n = "abs_and"; break;
4718 case cAbsOr: n = "abs_or"; break;
4719 case cAbsNot: n = "abs_not"; params = 1; break;
4720 case cAbsNotNot: n = "abs_notnot"; params = 1; break;
4721 case cDup:
4722 {
4723 if(showExpression)
4724 stack.push_back(stack.back());
4725 output << "dup";
4726 produces = 0;
4727 break;
4728 }
4729 case cInv: n = "inv"; params = 1; break;
4730 case cSqr: n = "sqr"; params = 1; break;
4731 case cRDiv: n = "rdiv"; break;
4732 case cRSub: n = "rsub"; break;
4733 case cRSqrt: n = "rsqrt"; params = 1; break;
4734
4735 default:
4736 n = Functions[opcode-cAbs].name;
4737 params = Functions[opcode-cAbs].params;
4738 out_params = params != 1;
4739 }
4740 }
4741 }
4742 }
4743 if(produces) output << n;
4744 if(out_params) output << " (" << params << ")";
4745 if(showExpression)
4746 {
4747 padLine(outputBuffer, 20);
4748
4749 if(produces > 0)
4750 {
4751 std::ostringstream buf;
4752 const char *paramsep = ",", *suff = "";
4753 int prio = 0; bool commutative = false;
4754 switch(opcode)
4755 {
4756 case cIf: buf << "if("; suff = ")";
4757 break;
4758 case cAbsIf: buf << "if("; suff = ")";
4759 break;
4760 case cOr: prio = 6; paramsep = "|"; commutative = true;
4761 break;
4762 case cAnd: prio = 5; paramsep = "&"; commutative = true;
4763 break;
4764 case cAdd: prio = 4; paramsep = "+"; commutative = true;
4765 break;
4766 case cSub: prio = 4; paramsep = "-";
4767 break;
4768 case cMul: prio = 3; paramsep = "*"; commutative = true;
4769 break;
4770 case cDiv: prio = 3; paramsep = "/";
4771 break;
4772 case cPow: prio = 2; paramsep = "^";
4773 break;
4774 case cAbsOr: prio = 6; paramsep = "|"; commutative = true;
4775 break;
4776 case cAbsAnd: prio = 5; paramsep = "&"; commutative = true;
4777 break;
4778 case cSqr: prio = 2; suff = "^2";
4779 break;
4780 case cNeg: buf << "(-("; suff = "))";
4781 break;
4782 case cNot: buf << "(!("; suff = "))";
4783 break;
4784 default: buf << n << '('; suff = ")";
4785 }
4786
4787 const char* sep = "";
4788 for(unsigned a=0; a<params; ++a)
4789 {
4790 buf << sep;
4791 if(stack.size() + a < params)
4792 buf << "?";
4793 else
4794 {
4795 const std::pair<int,std::string>& prev =
4796 stack[stack.size() - params + a];
4797 if(prio > 0 && (prev.first > prio ||
4798 (prev.first==prio && !commutative)))
4799 buf << '(' << prev.second << ')';
4800 else
4801 buf << prev.second;
4802 }
4803 sep = paramsep;
4804 }
4805 if(stack.size() >= params)
4806 stack.resize(stack.size() - params);
4807 else
4808 stack.clear();
4809 buf << suff;
4810 stack.push_back(std::make_pair(prio, buf.str()));
4811 //if(n.size() <= 4 && !out_params) padLine(outputBuffer, 20);
4812 }
4813 //padLine(outputBuffer, 20);
4814 output << "= ";
4815 if(((opcode == cIf || opcode == cAbsIf) && params != 3)
4816 || opcode == cJump
4817 #ifdef FP_SUPPORT_OPTIMIZER
4818 || opcode == cNop
4819 #endif
4820 )
4821 output << "(void)";
4822 else if(stack.empty())
4823 output << "[?] ?";
4824 else
4825 output << '[' << (stack.size()-1) << ']'
4826 << stack.back().second;
4827 }
4828
4829 if(showExpression)
4830 {
4831 dest << outputBuffer.str() << std::endl;
4832 outputBuffer.str("");
4833 }
4834 else
4835 output << std::endl;
4836 }
4837 dest << std::flush;
4838 }
4839 #endif
4840
4841
4842 #ifndef FP_SUPPORT_OPTIMIZER
4843 template<typename Value_t>
Optimize()4844 void FunctionParserBase<Value_t>::Optimize()
4845 {
4846 // Do nothing if no optimizations are supported.
4847 }
4848 #endif
4849
4850
4851 #define FUNCTIONPARSER_INSTANTIATE_CLASS(type) \
4852 template class FunctionParserBase< type >;
4853
4854 #ifndef FP_DISABLE_DOUBLE_TYPE
4855 FUNCTIONPARSER_INSTANTIATE_CLASS(double)
4856 #endif
4857
4858 #ifdef FP_SUPPORT_FLOAT_TYPE
4859 FUNCTIONPARSER_INSTANTIATE_CLASS(float)
4860 #endif
4861
4862 #ifdef FP_SUPPORT_LONG_DOUBLE_TYPE
4863 FUNCTIONPARSER_INSTANTIATE_CLASS(long double)
4864 #endif
4865
4866 #ifdef FP_SUPPORT_LONG_INT_TYPE
4867 FUNCTIONPARSER_INSTANTIATE_CLASS(long)
4868 #endif
4869
4870 #ifdef FP_SUPPORT_MPFR_FLOAT_TYPE
4871 FUNCTIONPARSER_INSTANTIATE_CLASS(MpfrFloat)
4872 #endif
4873
4874 #ifdef FP_SUPPORT_GMP_INT_TYPE
4875 FUNCTIONPARSER_INSTANTIATE_CLASS(GmpInt)
4876 #endif
4877
4878 #ifdef FP_SUPPORT_COMPLEX_DOUBLE_TYPE
4879 FUNCTIONPARSER_INSTANTIATE_CLASS(std::complex<double>)
4880 #endif
4881
4882 #ifdef FP_SUPPORT_COMPLEX_FLOAT_TYPE
4883 FUNCTIONPARSER_INSTANTIATE_CLASS(std::complex<float>)
4884 #endif
4885
4886 #ifdef FP_SUPPORT_COMPLEX_LONG_DOUBLE_TYPE
4887 FUNCTIONPARSER_INSTANTIATE_CLASS(std::complex<long double>)
4888 #endif
4889