TTMath  0.9.4
 C++ bignum library
ttmathparser.h
Go to the documentation of this file.
1 /*
2  * This file is a part of TTMath Bignum Library
3  * and is distributed under the 3-Clause BSD Licence.
4  * Author: Tomasz Sowa <t.sowa@ttmath.org>
5  */
6 
7 /*
8  * Copyright (c) 2006-2017, Tomasz Sowa
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions are met:
13  *
14  * * Redistributions of source code must retain the above copyright notice,
15  * this list of conditions and the following disclaimer.
16  *
17  * * Redistributions in binary form must reproduce the above copyright
18  * notice, this list of conditions and the following disclaimer in the
19  * documentation and/or other materials provided with the distribution.
20  *
21  * * Neither the name Tomasz Sowa nor the names of contributors to this
22  * project may be used to endorse or promote products derived
23  * from this software without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
29  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
35  * THE POSSIBILITY OF SUCH DAMAGE.
36  */
37 
38 
39 
40 #ifndef headerfilettmathparser
41 #define headerfilettmathparser
42 
43 /*!
44  \file ttmathparser.h
45  \brief A mathematical parser
46 */
47 
48 #include <cstdio>
49 #include <vector>
50 #include <map>
51 #include <set>
52 
53 #include "ttmath.h"
54 #include "ttmathobjects.h"
55 #include "ttmathmisc.h"
56 
57 
58 
59 namespace ttmath
60 {
61 
62 /*!
63  \brief Mathematical parser
64 
65  let x will be an input string meaning an expression for converting:
66 
67  x = [+|-]Value[operator[+|-]Value][operator[+|-]Value]...
68  where:
69  an operator can be:
70  ^ (pow) (the heighest priority)
71 
72  * (mul) (or multiplication without an operator -- short mul)
73  / (div) (* and / have the same priority)
74 
75  + (add)
76  - (sub) (+ and - have the same priority)
77 
78  < (lower than)
79  > (greater than)
80  <= (lower or equal than)
81  >= (greater or equal than)
82  == (equal)
83  != (not equal) (all above logical operators have the same priority)
84 
85  && (logical and)
86 
87  || (logical or) (the lowest priority)
88 
89  short mul:
90  if the second Value (Var below) is either a variable or function there might not be
91  an operator between them, e.g.
92  "[+|-]Value Var" is treated as "[+|-]Value * Var" and the multiplication
93  has the same priority as a normal multiplication:
94  4x = 4 * x
95  2^3m = (2^3)* m
96  6h^3 = 6 * (h^3)
97  2sin(pi) = 2 * sin(pi)
98  etc.
99 
100  Value can be:
101  constant e.g. 100, can be preceded by operators for changing the base (radix): [#|&]
102  # - hex
103  & - bin
104  sample: #10 = 16
105  &10 = 2
106  variable e.g. pi
107  another expression between brackets e.g (x)
108  function e.g. sin(x)
109 
110  for example a correct input string can be:
111  "1"
112  "2.1234"
113  "2,1234" (they are the same, by default we can either use a comma or a dot)
114  "1 + 2"
115  "(1 + 2) * 3"
116  "pi"
117  "sin(pi)"
118  "(1+2)*(2+3)"
119  "log(2;1234)" there's a semicolon here (not a comma), we use it in functions
120  for separating parameters
121  "1 < 2" (the result will be: 1)
122  "4 < 3" (the result will be: 0)
123  "2+x" (of course if the variable 'x' is defined)
124  "4x+10"
125  "#20+10" = 32 + 10 = 42
126  "10 ^ -&101" = 10 ^ -5 = 0.00001
127  "8 * -&10" = 8 * -2 = -16
128  etc.
129 
130  we can also use a semicolon for separating any 'x' input strings
131  for example:
132  "1+2;4+5"
133  the result will be on the stack as follows:
134  stack[0].value=3
135  stack[1].value=9
136 */
137 template<class ValueType>
138 class Parser
139 {
140 private:
141 
142 /*!
143  there are 5 mathematical operators as follows (with their standard priorities):
144  add (+)
145  sub (-)
146  mul (*)
147  div (/)
148  pow (^)
149  and 'shortmul' used when there is no any operators between
150  a first parameter and a variable or function
151  (the 'shortmul' has the same priority as the normal multiplication )
152 */
153  class MatOperator
154  {
155  public:
156 
157  enum Type
158  {
159  none,add,sub,mul,div,pow,lt,gt,let,get,eq,neq,lor,land,shortmul
160  };
161 
162  enum Assoc
163  {
164  right, // right-associative
165  non_right // associative or left-associative
166  };
167 
168  Type GetType() const { return type; }
169  int GetPriority() const { return priority; }
170  Assoc GetAssoc() const { return assoc; }
171 
172  void SetType(Type t)
173  {
174  type = t;
175  assoc = non_right;
176 
177  switch( type )
178  {
179  case lor:
180  priority = 4;
181  break;
182 
183  case land:
184  priority = 5;
185  break;
186 
187  case eq:
188  case neq:
189  case lt:
190  case gt:
191  case let:
192  case get:
193  priority = 7;
194  break;
195 
196  case add:
197  case sub:
198  priority = 10;
199  break;
200 
201  case mul:
202  case shortmul:
203  case div:
204  priority = 12;
205  break;
206 
207  case pow:
208  priority = 14;
209  assoc = right;
210  break;
211 
212  default:
213  Error( err_internal_error );
214  break;
215  }
216  }
217 
218  MatOperator(): type(none), priority(0), assoc(non_right)
219  {
220  }
221 
222  private:
223 
224  Type type;
225  int priority;
226  Assoc assoc;
227  }; // end of MatOperator class
228 
229 
230 
231 public:
232 
233 
234 
235  /*!
236  Objects of type 'Item' we are keeping on our stack
237  */
238  struct Item
239  {
240  enum Type
241  {
242  none, numerical_value, mat_operator, first_bracket,
243  last_bracket, variable, semicolon
244  };
245 
246  // The kind of type which we're keeping
247  Type type;
248 
249  // if type == numerical_value
250  ValueType value;
251 
252  // if type == mat_operator
253  MatOperator moperator;
254 
255  /*
256  if type == first_bracket
257 
258  if 'function' is set to true it means that the first recognized bracket
259  was the bracket from function in other words we must call a function when
260  we'll find the 'last' bracket
261  */
262  bool function;
263 
264  // if function is true
265  std::string function_name;
266 
267  /*
268  the sign of value
269 
270  it can be for type==numerical_value or type==first_bracket
271  when it's true it means e.g. that value is equal -value
272  */
273  bool sign;
274 
275  Item(): type(none), function(false), sign(false)
276  {
277  }
278 
279  }; // end of Item struct
280 
281 
282 /*!
283  stack on which we're keeping the Items
284 
285  at the end of parsing we'll have the result here
286  the result don't have to be one value, it can be
287  more than one if we have used a semicolon in the global space
288  e.g. such input string "1+2;3+4" will generate a result:
289  stack[0].value=3
290  stack[1].value=7
291 
292  you should check if the stack is not empty, because if there was
293  a syntax error in the input string then we do not have any results
294  on the stack
295 */
296 std::vector<Item> stack;
297 
298 
299 private:
300 
301 
302 /*!
303  size of the stack when we're starting parsing of the string
304 
305  if it's to small while parsing the stack will be automatically resized
306 */
307 const int default_stack_size;
308 
309 
310 
311 /*!
312  index of an object in our stack
313  it's pointing on the place behind the last element
314  for example at the beginning of parsing its value is zero
315 */
316 unsigned int stack_index;
317 
318 
319 /*!
320  code of the last error
321 */
322 ErrorCode error;
323 
324 
325 /*!
326  pointer to the currently reading char
327  when an error has occured it may be used to count the index of the wrong character
328 */
329 const char * pstring;
330 
331 
332 /*!
333  the base (radix) of the mathematic system (for example it may be '10')
334 */
335 int base;
336 
337 
338 /*!
339  the unit of angles used in: sin,cos,tan,cot,asin,acos,atan,acot
340  0 - deg
341  1 - rad (default)
342  2 - grad
343 */
344 int deg_rad_grad;
345 
346 
347 
348 /*!
349  a pointer to an object which tell us whether we should stop calculating or not
350 */
351 const volatile StopCalculating * pstop_calculating;
352 
353 
354 
355 /*!
356  a pointer to the user-defined variables' table
357 */
358 const Objects * puser_variables;
359 
360 /*!
361  a pointer to the user-defined functions' table
362 */
363 const Objects * puser_functions;
364 
365 
366 typedef std::map<std::string, ValueType> FunctionLocalVariables;
367 
368 /*!
369  a pointer to the local variables of a function
370 */
371 const FunctionLocalVariables * pfunction_local_variables;
372 
373 
374 /*!
375  a temporary set using during parsing user defined variables
376 */
377 std::set<std::string> visited_variables;
378 
379 
380 /*!
381  a temporary set using during parsing user defined functions
382 */
383 std::set<std::string> visited_functions;
384 
385 
386 
387 
388 /*!
389  pfunction is the type of pointer to a mathematic function
390 
391  these mathematic functions are private members of this class,
392  they are the wrappers for standard mathematics function
393 
394  'pstack' is the pointer to the first argument on our stack
395  'amount_of_arg' tell us how many argument there are in our stack
396  'result' is the reference for result of function
397 */
398 typedef void (Parser<ValueType>::*pfunction)(int pstack, int amount_of_arg, ValueType & result);
399 
400 
401 /*!
402  pfunction is the type of pointer to a method which returns value of variable
403 */
404 typedef void (ValueType::*pfunction_var)();
405 
406 
407 /*!
408  table of mathematic functions
409 
410  this map consists of:
411  std::string - function's name
412  pfunction - pointer to specific function
413 */
414 typedef std::map<std::string, pfunction> FunctionsTable;
415 FunctionsTable functions_table;
416 
417 
418 /*!
419  table of mathematic operators
420 
421  this map consists of:
422  std::string - operators's name
423  MatOperator::Type - type of the operator
424 */
425 typedef std::map<std::string, typename MatOperator::Type> OperatorsTable;
426 OperatorsTable operators_table;
427 
428 
429 /*!
430  table of mathematic variables
431 
432  this map consists of:
433  std::string - variable's name
434  pfunction_var - pointer to specific function which returns value of variable
435 */
436 typedef std::map<std::string, pfunction_var> VariablesTable;
437 VariablesTable variables_table;
438 
439 
440 /*!
441  some coefficients used when calculating the gamma (or factorial) function
442 */
443 CGamma<ValueType> cgamma;
444 
445 
446 /*!
447  temporary object for a whole string when Parse(std::wstring) is used
448 */
449 std::string wide_to_ansi;
450 
451 
452 /*!
453  group character (used when parsing)
454  default zero (not used)
455 */
456 int group;
457 
458 
459 /*!
460  characters used as a comma
461  default: '.' and ','
462  comma2 can be zero (it means it is not used)
463 */
464 int comma, comma2;
465 
466 
467 /*!
468  an additional character used as a separator between function parameters
469  (semicolon is used always)
470 */
471 int param_sep;
472 
473 
474 /*!
475  true if something was calculated (at least one mathematical operator was used or a function or a variable)
476 */
477 bool calculated;
478 
479 
480 
481 /*!
482  we're using this method for reporting an error
483 */
484 static void Error(ErrorCode code)
485 {
486  throw code;
487 }
488 
489 
490 /*!
491  this method skips the white character from the string
492 
493  it's moving the 'pstring' to the first no-white character
494 */
495 void SkipWhiteCharacters()
496 {
497  while( (*pstring==' ' ) || (*pstring=='\t') )
498  ++pstring;
499 }
500 
501 
502 /*!
503  an auxiliary method for RecurrenceParsingVariablesOrFunction(...)
504 */
505 void RecurrenceParsingVariablesOrFunction_CheckStopCondition(bool variable, const std::string & name)
506 {
507  if( variable )
508  {
509  if( visited_variables.find(name) != visited_variables.end() )
510  Error( err_variable_loop );
511  }
512  else
513  {
514  if( visited_functions.find(name) != visited_functions.end() )
515  Error( err_functions_loop );
516  }
517 }
518 
519 
520 /*!
521  an auxiliary method for RecurrenceParsingVariablesOrFunction(...)
522 */
523 void RecurrenceParsingVariablesOrFunction_AddName(bool variable, const std::string & name)
524 {
525  if( variable )
526  visited_variables.insert( name );
527  else
528  visited_functions.insert( name );
529 }
530 
531 
532 /*!
533  an auxiliary method for RecurrenceParsingVariablesOrFunction(...)
534 */
535 void RecurrenceParsingVariablesOrFunction_DeleteName(bool variable, const std::string & name)
536 {
537  if( variable )
538  visited_variables.erase( name );
539  else
540  visited_functions.erase( name );
541 }
542 
543 
544 /*!
545  this method returns the value of a variable or function
546  by creating a new instance of the mathematical parser
547  and making the standard parsing algorithm on the given string
548 
549  this method is used only during parsing user defined variables or functions
550 
551  (there can be a recurrence here therefore we're using 'visited_variables'
552  and 'visited_functions' sets to make a stop condition)
553 */
554 ValueType RecurrenceParsingVariablesOrFunction(bool variable, const std::string & name, const char * new_string,
555  FunctionLocalVariables * local_variables = 0)
556 {
557  RecurrenceParsingVariablesOrFunction_CheckStopCondition(variable, name);
558  RecurrenceParsingVariablesOrFunction_AddName(variable, name);
559 
560  Parser<ValueType> NewParser(*this);
561  ErrorCode err;
562 
563  NewParser.pfunction_local_variables = local_variables;
564 
565  try
566  {
567  err = NewParser.Parse(new_string);
568  }
569  catch(...)
570  {
571  RecurrenceParsingVariablesOrFunction_DeleteName(variable, name);
572 
573  throw;
574  }
575 
576  RecurrenceParsingVariablesOrFunction_DeleteName(variable, name);
577 
578  if( err != err_ok )
579  Error( err );
580 
581  if( NewParser.stack.size() != 1 )
582  Error( err_must_be_only_one_value );
583 
584  if( NewParser.stack[0].type != Item::numerical_value )
585  // I think there shouldn't be this error here
586  Error( err_incorrect_value );
587 
588 return NewParser.stack[0].value;
589 }
590 
591 
592 public:
593 
594 
595 /*!
596  this method returns the user-defined value of a variable
597 */
598 bool GetValueOfUserDefinedVariable(const std::string & variable_name,ValueType & result)
599 {
600  if( !puser_variables )
601  return false;
602 
603  const char * string_value;
604 
605  if( puser_variables->GetValue(variable_name, &string_value) != err_ok )
606  return false;
607 
608  result = RecurrenceParsingVariablesOrFunction(true, variable_name, string_value);
609  calculated = true;
610 
611 return true;
612 }
613 
614 
615 /*!
616  this method returns the value of a local variable of a function
617 */
618 bool GetValueOfFunctionLocalVariable(const std::string & variable_name, ValueType & result)
619 {
620  if( !pfunction_local_variables )
621  return false;
622 
623  typename FunctionLocalVariables::const_iterator i = pfunction_local_variables->find(variable_name);
624 
625  if( i == pfunction_local_variables->end() )
626  return false;
627 
628  result = i->second;
629 
630 return true;
631 }
632 
633 
634 /*!
635  this method returns the value of a variable from variables' table
636 
637  we make an object of type ValueType then call a method which
638  sets the correct value in it and finally we'll return the object
639 */
640 ValueType GetValueOfVariable(const std::string & variable_name)
641 {
642 ValueType result;
643 
644  if( GetValueOfFunctionLocalVariable(variable_name, result) )
645  return result;
646 
647  if( GetValueOfUserDefinedVariable(variable_name, result) )
648  return result;
649 
650 
651  typename std::map<std::string, pfunction_var>::iterator i =
652  variables_table.find(variable_name);
653 
654  if( i == variables_table.end() )
655  Error( err_unknown_variable );
656 
657  (result.*(i->second))();
658  calculated = true;
659 
660 return result;
661 }
662 
663 
664 private:
665 
666 /*!
667  wrappers for mathematic functions
668 
669  'sindex' is pointing on the first argument on our stack
670  (the second argument has 'sindex+2'
671  because 'sindex+1' is guaranted for the 'semicolon' operator)
672  the third artument has of course 'sindex+4' etc.
673 
674  'result' will be the result of the function
675 
676  (we're using exceptions here for example when function gets an improper argument)
677 */
678 
679 
680 /*!
681  used by: sin,cos,tan,cot
682 */
683 ValueType ConvertAngleToRad(const ValueType & input)
684 {
685  if( deg_rad_grad == 1 ) // rad
686  return input;
687 
688  ValueType result;
689  ErrorCode err;
690 
691  if( deg_rad_grad == 0 ) // deg
692  result = ttmath::DegToRad(input, &err);
693  else // grad
694  result = ttmath::GradToRad(input, &err);
695 
696  if( err != err_ok )
697  Error( err );
698 
699 return result;
700 }
701 
702 
703 /*!
704  used by: asin,acos,atan,acot
705 */
706 ValueType ConvertRadToAngle(const ValueType & input)
707 {
708  if( deg_rad_grad == 1 ) // rad
709  return input;
710 
711  ValueType result;
712  ErrorCode err;
713 
714  if( deg_rad_grad == 0 ) // deg
715  result = ttmath::RadToDeg(input, &err);
716  else // grad
717  result = ttmath::RadToGrad(input, &err);
718 
719  if( err != err_ok )
720  Error( err );
721 
722 return result;
723 }
724 
725 
726 void Gamma(int sindex, int amount_of_args, ValueType & result)
727 {
728  if( amount_of_args != 1 )
729  Error( err_improper_amount_of_arguments );
730 
731  ErrorCode err;
732 
733  result = ttmath::Gamma(stack[sindex].value, cgamma, &err, pstop_calculating);
734 
735  if(err != err_ok)
736  Error( err );
737 }
738 
739 
740 /*!
741  factorial
742  result = 1 * 2 * 3 * 4 * .... * x
743 */
744 void Factorial(int sindex, int amount_of_args, ValueType & result)
745 {
746  if( amount_of_args != 1 )
747  Error( err_improper_amount_of_arguments );
748 
749  ErrorCode err;
750 
751  result = ttmath::Factorial(stack[sindex].value, cgamma, &err, pstop_calculating);
752 
753  if(err != err_ok)
754  Error( err );
755 }
756 
757 
758 void Abs(int sindex, int amount_of_args, ValueType & result)
759 {
760  if( amount_of_args != 1 )
761  Error( err_improper_amount_of_arguments );
762 
763  result = ttmath::Abs(stack[sindex].value);
764 }
765 
766 void Sin(int sindex, int amount_of_args, ValueType & result)
767 {
768  if( amount_of_args != 1 )
769  Error( err_improper_amount_of_arguments );
770 
771  ErrorCode err;
772  result = ttmath::Sin( ConvertAngleToRad(stack[sindex].value), &err );
773 
774  if(err != err_ok)
775  Error( err );
776 }
777 
778 void Cos(int sindex, int amount_of_args, ValueType & result)
779 {
780  if( amount_of_args != 1 )
781  Error( err_improper_amount_of_arguments );
782 
783  ErrorCode err;
784  result = ttmath::Cos( ConvertAngleToRad(stack[sindex].value), &err );
785 
786  if(err != err_ok)
787  Error( err );
788 }
789 
790 void Tan(int sindex, int amount_of_args, ValueType & result)
791 {
792  if( amount_of_args != 1 )
793  Error( err_improper_amount_of_arguments );
794 
795  ErrorCode err;
796  result = ttmath::Tan(ConvertAngleToRad(stack[sindex].value), &err);
797 
798  if(err != err_ok)
799  Error( err );
800 }
801 
802 void Cot(int sindex, int amount_of_args, ValueType & result)
803 {
804  if( amount_of_args != 1 )
805  Error( err_improper_amount_of_arguments );
806 
807  ErrorCode err;
808  result = ttmath::Cot(ConvertAngleToRad(stack[sindex].value), &err);
809 
810  if(err != err_ok)
811  Error( err );
812 }
813 
814 void Int(int sindex, int amount_of_args, ValueType & result)
815 {
816  if( amount_of_args != 1 )
817  Error( err_improper_amount_of_arguments );
818 
819  result = ttmath::SkipFraction(stack[sindex].value);
820 }
821 
822 
823 void Round(int sindex, int amount_of_args, ValueType & result)
824 {
825  if( amount_of_args != 1 )
826  Error( err_improper_amount_of_arguments );
827 
828  result = stack[sindex].value;
829 
830  if( result.Round() )
831  Error( err_overflow );
832 }
833 
834 
835 void Ln(int sindex, int amount_of_args, ValueType & result)
836 {
837  if( amount_of_args != 1 )
838  Error( err_improper_amount_of_arguments );
839 
840  ErrorCode err;
841  result = ttmath::Ln(stack[sindex].value, &err);
842 
843  if(err != err_ok)
844  Error( err );
845 }
846 
847 void Log(int sindex, int amount_of_args, ValueType & result)
848 {
849  if( amount_of_args != 2 )
850  Error( err_improper_amount_of_arguments );
851 
852  ErrorCode err;
853  result = ttmath::Log(stack[sindex].value, stack[sindex+2].value, &err);
854 
855  if(err != err_ok)
856  Error( err );
857 }
858 
859 void Exp(int sindex, int amount_of_args, ValueType & result)
860 {
861  if( amount_of_args != 1 )
862  Error( err_improper_amount_of_arguments );
863 
864  ErrorCode err;
865  result = ttmath::Exp(stack[sindex].value, &err);
866 
867  if(err != err_ok)
868  Error( err );
869 }
870 
871 
872 void Max(int sindex, int amount_of_args, ValueType & result)
873 {
874  if( amount_of_args == 0 )
875  {
876  result.SetMax();
877 
878  return;
879  }
880 
881  result = stack[sindex].value;
882 
883  for(int i=1 ; i<amount_of_args ; ++i)
884  {
885  if( result < stack[sindex + i*2].value )
886  result = stack[sindex + i*2].value;
887  }
888 }
889 
890 
891 void Min(int sindex, int amount_of_args, ValueType & result)
892 {
893  if( amount_of_args == 0 )
894  {
895  result.SetMin();
896 
897  return;
898  }
899 
900  result = stack[sindex].value;
901 
902  for(int i=1 ; i<amount_of_args ; ++i)
903  {
904  if( result > stack[sindex + i*2].value )
905  result = stack[sindex + i*2].value;
906  }
907 }
908 
909 
910 void ASin(int sindex, int amount_of_args, ValueType & result)
911 {
912  if( amount_of_args != 1 )
913  Error( err_improper_amount_of_arguments );
914 
915  ErrorCode err;
916  ValueType temp = ttmath::ASin(stack[sindex].value, &err);
917 
918  if(err != err_ok)
919  Error( err );
920 
921  result = ConvertRadToAngle(temp);
922 }
923 
924 
925 void ACos(int sindex, int amount_of_args, ValueType & result)
926 {
927  if( amount_of_args != 1 )
928  Error( err_improper_amount_of_arguments );
929 
930  ErrorCode err;
931  ValueType temp = ttmath::ACos(stack[sindex].value, &err);
932 
933  if(err != err_ok)
934  Error( err );
935 
936  result = ConvertRadToAngle(temp);
937 }
938 
939 
940 void ATan(int sindex, int amount_of_args, ValueType & result)
941 {
942  if( amount_of_args != 1 )
943  Error( err_improper_amount_of_arguments );
944 
945  result = ConvertRadToAngle(ttmath::ATan(stack[sindex].value));
946 }
947 
948 
949 void ACot(int sindex, int amount_of_args, ValueType & result)
950 {
951  if( amount_of_args != 1 )
952  Error( err_improper_amount_of_arguments );
953 
954  result = ConvertRadToAngle(ttmath::ACot(stack[sindex].value));
955 }
956 
957 
958 void Sgn(int sindex, int amount_of_args, ValueType & result)
959 {
960  if( amount_of_args != 1 )
961  Error( err_improper_amount_of_arguments );
962 
963  result = ttmath::Sgn(stack[sindex].value);
964 }
965 
966 
967 void Mod(int sindex, int amount_of_args, ValueType & result)
968 {
969  if( amount_of_args != 2 )
970  Error( err_improper_amount_of_arguments );
971 
972  if( stack[sindex+2].value.IsZero() )
973  Error( err_improper_argument );
974 
975  result = stack[sindex].value;
976  uint c = result.Mod(stack[sindex+2].value);
977 
978  if( c )
979  Error( err_overflow );
980 }
981 
982 
983 void If(int sindex, int amount_of_args, ValueType & result)
984 {
985  if( amount_of_args != 3 )
986  Error( err_improper_amount_of_arguments );
987 
988 
989  if( !stack[sindex].value.IsZero() )
990  result = stack[sindex+2].value;
991  else
992  result = stack[sindex+4].value;
993 }
994 
995 
996 void Or(int sindex, int amount_of_args, ValueType & result)
997 {
998  if( amount_of_args < 2 )
999  Error( err_improper_amount_of_arguments );
1000 
1001  for(int i=0 ; i<amount_of_args ; ++i)
1002  {
1003  if( !stack[sindex+i*2].value.IsZero() )
1004  {
1005  result.SetOne();
1006  return;
1007  }
1008  }
1009 
1010  result.SetZero();
1011 }
1012 
1013 
1014 void And(int sindex, int amount_of_args, ValueType & result)
1015 {
1016  if( amount_of_args < 2 )
1017  Error( err_improper_amount_of_arguments );
1018 
1019  for(int i=0 ; i<amount_of_args ; ++i)
1020  {
1021  if( stack[sindex+i*2].value.IsZero() )
1022  {
1023  result.SetZero();
1024  return;
1025  }
1026  }
1027 
1028  result.SetOne();
1029 }
1030 
1031 
1032 void Not(int sindex, int amount_of_args, ValueType & result)
1033 {
1034  if( amount_of_args != 1 )
1035  Error( err_improper_amount_of_arguments );
1036 
1037 
1038  if( stack[sindex].value.IsZero() )
1039  result.SetOne();
1040  else
1041  result.SetZero();
1042 }
1043 
1044 
1045 void DegToRad(int sindex, int amount_of_args, ValueType & result)
1046 {
1047  ErrorCode err = err_ok;
1048 
1049  if( amount_of_args == 1 )
1050  {
1051  result = ttmath::DegToRad(stack[sindex].value, &err);
1052  }
1053  else
1054  if( amount_of_args == 3 )
1055  {
1056  result = ttmath::DegToRad( stack[sindex].value, stack[sindex+2].value,
1057  stack[sindex+4].value, &err);
1058  }
1059  else
1060  Error( err_improper_amount_of_arguments );
1061 
1062 
1063  if( err != err_ok )
1064  Error( err );
1065 }
1066 
1067 
1068 void RadToDeg(int sindex, int amount_of_args, ValueType & result)
1069 {
1070  ErrorCode err;
1071 
1072  if( amount_of_args != 1 )
1073  Error( err_improper_amount_of_arguments );
1074 
1075  result = ttmath::RadToDeg(stack[sindex].value, &err);
1076 
1077  if( err != err_ok )
1078  Error( err );
1079 }
1080 
1081 
1082 void DegToDeg(int sindex, int amount_of_args, ValueType & result)
1083 {
1084  if( amount_of_args != 3 )
1085  Error( err_improper_amount_of_arguments );
1086 
1087  ErrorCode err;
1088  result = ttmath::DegToDeg( stack[sindex].value, stack[sindex+2].value,
1089  stack[sindex+4].value, &err);
1090 
1091  if( err != err_ok )
1092  Error( err );
1093 }
1094 
1095 
1096 void GradToRad(int sindex, int amount_of_args, ValueType & result)
1097 {
1098  ErrorCode err;
1099 
1100  if( amount_of_args != 1 )
1101  Error( err_improper_amount_of_arguments );
1102 
1103  result = ttmath::GradToRad(stack[sindex].value, &err);
1104 
1105  if( err != err_ok )
1106  Error( err );
1107 }
1108 
1109 
1110 void RadToGrad(int sindex, int amount_of_args, ValueType & result)
1111 {
1112  ErrorCode err;
1113 
1114  if( amount_of_args != 1 )
1115  Error( err_improper_amount_of_arguments );
1116 
1117  result = ttmath::RadToGrad(stack[sindex].value, &err);
1118 
1119  if( err != err_ok )
1120  Error( err );
1121 }
1122 
1123 
1124 void DegToGrad(int sindex, int amount_of_args, ValueType & result)
1125 {
1126  ErrorCode err = err_ok;
1127 
1128  if( amount_of_args == 1 )
1129  {
1130  result = ttmath::DegToGrad(stack[sindex].value, &err);
1131  }
1132  else
1133  if( amount_of_args == 3 )
1134  {
1135  result = ttmath::DegToGrad( stack[sindex].value, stack[sindex+2].value,
1136  stack[sindex+4].value, &err);
1137  }
1138  else
1139  Error( err_improper_amount_of_arguments );
1140 
1141 
1142  if( err != err_ok )
1143  Error( err );
1144 }
1145 
1146 
1147 void GradToDeg(int sindex, int amount_of_args, ValueType & result)
1148 {
1149  ErrorCode err;
1150 
1151  if( amount_of_args != 1 )
1152  Error( err_improper_amount_of_arguments );
1153 
1154  result = ttmath::GradToDeg(stack[sindex].value, &err);
1155 
1156  if( err != err_ok )
1157  Error( err );
1158 }
1159 
1160 
1161 void Ceil(int sindex, int amount_of_args, ValueType & result)
1162 {
1163  if( amount_of_args != 1 )
1164  Error( err_improper_amount_of_arguments );
1165 
1166  ErrorCode err;
1167  result = ttmath::Ceil(stack[sindex].value, &err);
1168 
1169  if( err != err_ok )
1170  Error( err );
1171 }
1172 
1173 
1174 void Floor(int sindex, int amount_of_args, ValueType & result)
1175 {
1176  if( amount_of_args != 1 )
1177  Error( err_improper_amount_of_arguments );
1178 
1179  ErrorCode err;
1180  result = ttmath::Floor(stack[sindex].value, &err);
1181 
1182  if( err != err_ok )
1183  Error( err );
1184 }
1185 
1186 void Sqrt(int sindex, int amount_of_args, ValueType & result)
1187 {
1188  if( amount_of_args != 1 )
1189  Error( err_improper_amount_of_arguments );
1190 
1191  ErrorCode err;
1192  result = ttmath::Sqrt(stack[sindex].value, &err);
1193 
1194  if( err != err_ok )
1195  Error( err );
1196 }
1197 
1198 
1199 void Sinh(int sindex, int amount_of_args, ValueType & result)
1200 {
1201  if( amount_of_args != 1 )
1202  Error( err_improper_amount_of_arguments );
1203 
1204  ErrorCode err;
1205  result = ttmath::Sinh(stack[sindex].value, &err);
1206 
1207  if( err != err_ok )
1208  Error( err );
1209 }
1210 
1211 
1212 void Cosh(int sindex, int amount_of_args, ValueType & result)
1213 {
1214  if( amount_of_args != 1 )
1215  Error( err_improper_amount_of_arguments );
1216 
1217  ErrorCode err;
1218  result = ttmath::Cosh(stack[sindex].value, &err);
1219 
1220  if( err != err_ok )
1221  Error( err );
1222 }
1223 
1224 
1225 void Tanh(int sindex, int amount_of_args, ValueType & result)
1226 {
1227  if( amount_of_args != 1 )
1228  Error( err_improper_amount_of_arguments );
1229 
1230  ErrorCode err;
1231  result = ttmath::Tanh(stack[sindex].value, &err);
1232 
1233  if( err != err_ok )
1234  Error( err );
1235 }
1236 
1237 
1238 void Coth(int sindex, int amount_of_args, ValueType & result)
1239 {
1240  if( amount_of_args != 1 )
1241  Error( err_improper_amount_of_arguments );
1242 
1243  ErrorCode err;
1244  result = ttmath::Coth(stack[sindex].value, &err);
1245 
1246  if( err != err_ok )
1247  Error( err );
1248 }
1249 
1250 
1251 void Root(int sindex, int amount_of_args, ValueType & result)
1252 {
1253  if( amount_of_args != 2 )
1254  Error( err_improper_amount_of_arguments );
1255 
1256  ErrorCode err;
1257  result = ttmath::Root(stack[sindex].value, stack[sindex+2].value, &err);
1258 
1259  if( err != err_ok )
1260  Error( err );
1261 }
1262 
1263 
1264 
1265 void ASinh(int sindex, int amount_of_args, ValueType & result)
1266 {
1267  if( amount_of_args != 1 )
1268  Error( err_improper_amount_of_arguments );
1269 
1270  ErrorCode err;
1271  result = ttmath::ASinh(stack[sindex].value, &err);
1272 
1273  if( err != err_ok )
1274  Error( err );
1275 }
1276 
1277 
1278 void ACosh(int sindex, int amount_of_args, ValueType & result)
1279 {
1280  if( amount_of_args != 1 )
1281  Error( err_improper_amount_of_arguments );
1282 
1283  ErrorCode err;
1284  result = ttmath::ACosh(stack[sindex].value, &err);
1285 
1286  if( err != err_ok )
1287  Error( err );
1288 }
1289 
1290 
1291 void ATanh(int sindex, int amount_of_args, ValueType & result)
1292 {
1293  if( amount_of_args != 1 )
1294  Error( err_improper_amount_of_arguments );
1295 
1296  ErrorCode err;
1297  result = ttmath::ATanh(stack[sindex].value, &err);
1298 
1299  if( err != err_ok )
1300  Error( err );
1301 }
1302 
1303 
1304 void ACoth(int sindex, int amount_of_args, ValueType & result)
1305 {
1306  if( amount_of_args != 1 )
1307  Error( err_improper_amount_of_arguments );
1308 
1309  ErrorCode err;
1310  result = ttmath::ACoth(stack[sindex].value, &err);
1311 
1312  if( err != err_ok )
1313  Error( err );
1314 }
1315 
1316 
1317 void BitAnd(int sindex, int amount_of_args, ValueType & result)
1318 {
1319  if( amount_of_args != 2 )
1320  Error( err_improper_amount_of_arguments );
1321 
1322  uint err;
1323  result = stack[sindex].value;
1324  err = result.BitAnd(stack[sindex+2].value);
1325 
1326  switch(err)
1327  {
1328  case 1:
1329  Error( err_overflow );
1330  break;
1331  case 2:
1332  Error( err_improper_argument );
1333  break;
1334  }
1335 }
1336 
1337 void BitOr(int sindex, int amount_of_args, ValueType & result)
1338 {
1339  if( amount_of_args != 2 )
1340  Error( err_improper_amount_of_arguments );
1341 
1342  uint err;
1343  result = stack[sindex].value;
1344  err = result.BitOr(stack[sindex+2].value);
1345 
1346  switch(err)
1347  {
1348  case 1:
1349  Error( err_overflow );
1350  break;
1351  case 2:
1352  Error( err_improper_argument );
1353  break;
1354  }
1355 }
1356 
1357 
1358 void BitXor(int sindex, int amount_of_args, ValueType & result)
1359 {
1360  if( amount_of_args != 2 )
1361  Error( err_improper_amount_of_arguments );
1362 
1363  uint err;
1364  result = stack[sindex].value;
1365  err = result.BitXor(stack[sindex+2].value);
1366 
1367  switch(err)
1368  {
1369  case 1:
1370  Error( err_overflow );
1371  break;
1372  case 2:
1373  Error( err_improper_argument );
1374  break;
1375  }
1376 }
1377 
1378 
1379 void Sum(int sindex, int amount_of_args, ValueType & result)
1380 {
1381  if( amount_of_args == 0 )
1382  Error( err_improper_amount_of_arguments );
1383 
1384  result = stack[sindex].value;
1385 
1386  for(int i=1 ; i<amount_of_args ; ++i )
1387  if( result.Add( stack[ sindex + i*2 ].value ) )
1388  Error( err_overflow );
1389 }
1390 
1391 void Avg(int sindex, int amount_of_args, ValueType & result)
1392 {
1393  if( amount_of_args == 0 )
1394  Error( err_improper_amount_of_arguments );
1395 
1396  result = stack[sindex].value;
1397 
1398  for(int i=1 ; i<amount_of_args ; ++i )
1399  if( result.Add( stack[ sindex + i*2 ].value ) )
1400  Error( err_overflow );
1401 
1402  if( result.Div( amount_of_args ) )
1403  Error( err_overflow );
1404 }
1405 
1406 
1407 void Frac(int sindex, int amount_of_args, ValueType & result)
1408 {
1409  if( amount_of_args != 1 )
1410  Error( err_improper_amount_of_arguments );
1411 
1412  result = stack[sindex].value;
1413  result.RemainFraction();
1414 }
1415 
1416 
1417 
1418 
1419 /*!
1420  we use such a method because 'wvsprintf' is not everywhere defined
1421 */
1422 void Sprintf(char * buffer, int par)
1423 {
1424 char buf[30]; // char, not wchar_t
1425 int i;
1426 
1427  #ifdef _MSC_VER
1428  #pragma warning( disable: 4996 )
1429  //warning C4996: 'sprintf': This function or variable may be unsafe.
1430  #endif
1431 
1432  sprintf(buf, "%d", par);
1433  for(i=0 ; buf[i] != 0 ; ++i)
1434  buffer[i] = buf[i];
1435 
1436  buffer[i] = 0;
1437 
1438  #ifdef _MSC_VER
1439  #pragma warning( default: 4996 )
1440  #endif
1441 }
1442 
1443 
1444 
1445 
1446 /*!
1447  this method returns the value from a user-defined function
1448 
1449  (look at the description in 'CallFunction(...)')
1450 */
1451 bool GetValueOfUserDefinedFunction(const std::string & function_name, int amount_of_args, int sindex)
1452 {
1453  if( !puser_functions )
1454  return false;
1455 
1456  const char * string_value;
1457  int param;
1458 
1459  if( puser_functions->GetValueAndParam(function_name, &string_value, &param) != err_ok )
1460  return false;
1461 
1462  if( param != amount_of_args )
1463  Error( err_improper_amount_of_arguments );
1464 
1465 
1466  FunctionLocalVariables local_variables;
1467 
1468  if( amount_of_args > 0 )
1469  {
1470  char buffer[30];
1471 
1472  // x = x1
1473  buffer[0] = 'x';
1474  buffer[1] = 0;
1475  local_variables.insert( std::make_pair(buffer, stack[sindex].value) );
1476 
1477  for(int i=0 ; i<amount_of_args ; ++i)
1478  {
1479  buffer[0] = 'x';
1480  Sprintf(buffer+1, i+1);
1481  local_variables.insert( std::make_pair(buffer, stack[sindex + i*2].value) );
1482  }
1483  }
1484 
1485  stack[sindex-1].value = RecurrenceParsingVariablesOrFunction(false, function_name, string_value, &local_variables);
1486  calculated = true;
1487 
1488 return true;
1489 }
1490 
1491 
1492 /*
1493  we're calling a specific function
1494 
1495  function_name - name of the function
1496  amount_of_args - how many arguments there are on our stack
1497  (function must check whether this is a correct value or not)
1498  sindex - index of the first argument on the stack (sindex is greater than zero)
1499  if there aren't any arguments on the stack 'sindex' pointing on
1500  a non existend element (after the first bracket)
1501 
1502  result will be stored in 'stack[sindex-1].value'
1503  (we don't have to set the correct type of this element, it'll be set later)
1504 */
1505 void CallFunction(const std::string & function_name, int amount_of_args, int sindex)
1506 {
1507  if( GetValueOfUserDefinedFunction(function_name, amount_of_args, sindex) )
1508  return;
1509 
1510  typename FunctionsTable::iterator i = functions_table.find( function_name );
1511 
1512  if( i == functions_table.end() )
1513  Error( err_unknown_function );
1514 
1515  /*
1516  calling the specify function
1517  */
1518  (this->*(i->second))(sindex, amount_of_args, stack[sindex-1].value);
1519  calculated = true;
1520 }
1521 
1522 
1523 
1524 
1525 
1526 /*!
1527  inserting a function to the functions' table
1528 
1529  function_name - name of the function
1530  pf - pointer to the function (to the wrapper)
1531 */
1532 void InsertFunctionToTable(const char * function_name, pfunction pf)
1533 {
1534  std::string str;
1535  Misc::AssignString(str, function_name);
1536 
1537  functions_table.insert( std::make_pair(str, pf) );
1538 }
1539 
1540 
1541 
1542 /*!
1543  inserting a function to the variables' table
1544  (this function returns value of variable)
1545 
1546  variable_name - name of the function
1547  pf - pointer to the function
1548 */
1549 void InsertVariableToTable(const char * variable_name, pfunction_var pf)
1550 {
1551  std::string str;
1552  Misc::AssignString(str, variable_name);
1553 
1554  variables_table.insert( std::make_pair(str, pf) );
1555 }
1556 
1557 
1558 /*!
1559  this method creates the table of functions
1560 */
1561 void CreateFunctionsTable()
1562 {
1563  InsertFunctionToTable("gamma", &Parser<ValueType>::Gamma);
1564  InsertFunctionToTable("factorial", &Parser<ValueType>::Factorial);
1565  InsertFunctionToTable("abs", &Parser<ValueType>::Abs);
1566  InsertFunctionToTable("sin", &Parser<ValueType>::Sin);
1567  InsertFunctionToTable("cos", &Parser<ValueType>::Cos);
1568  InsertFunctionToTable("tan", &Parser<ValueType>::Tan);
1569  InsertFunctionToTable("tg", &Parser<ValueType>::Tan);
1570  InsertFunctionToTable("cot", &Parser<ValueType>::Cot);
1571  InsertFunctionToTable("ctg", &Parser<ValueType>::Cot);
1572  InsertFunctionToTable("int", &Parser<ValueType>::Int);
1573  InsertFunctionToTable("round", &Parser<ValueType>::Round);
1574  InsertFunctionToTable("ln", &Parser<ValueType>::Ln);
1575  InsertFunctionToTable("log", &Parser<ValueType>::Log);
1576  InsertFunctionToTable("exp", &Parser<ValueType>::Exp);
1577  InsertFunctionToTable("max", &Parser<ValueType>::Max);
1578  InsertFunctionToTable("min", &Parser<ValueType>::Min);
1579  InsertFunctionToTable("asin", &Parser<ValueType>::ASin);
1580  InsertFunctionToTable("acos", &Parser<ValueType>::ACos);
1581  InsertFunctionToTable("atan", &Parser<ValueType>::ATan);
1582  InsertFunctionToTable("atg", &Parser<ValueType>::ATan);
1583  InsertFunctionToTable("acot", &Parser<ValueType>::ACot);
1584  InsertFunctionToTable("actg", &Parser<ValueType>::ACot);
1585  InsertFunctionToTable("sgn", &Parser<ValueType>::Sgn);
1586  InsertFunctionToTable("mod", &Parser<ValueType>::Mod);
1587  InsertFunctionToTable("if", &Parser<ValueType>::If);
1588  InsertFunctionToTable("or", &Parser<ValueType>::Or);
1589  InsertFunctionToTable("and", &Parser<ValueType>::And);
1590  InsertFunctionToTable("not", &Parser<ValueType>::Not);
1591  InsertFunctionToTable("degtorad", &Parser<ValueType>::DegToRad);
1592  InsertFunctionToTable("radtodeg", &Parser<ValueType>::RadToDeg);
1593  InsertFunctionToTable("degtodeg", &Parser<ValueType>::DegToDeg);
1594  InsertFunctionToTable("gradtorad", &Parser<ValueType>::GradToRad);
1595  InsertFunctionToTable("radtograd", &Parser<ValueType>::RadToGrad);
1596  InsertFunctionToTable("degtograd", &Parser<ValueType>::DegToGrad);
1597  InsertFunctionToTable("gradtodeg", &Parser<ValueType>::GradToDeg);
1598  InsertFunctionToTable("ceil", &Parser<ValueType>::Ceil);
1599  InsertFunctionToTable("floor", &Parser<ValueType>::Floor);
1600  InsertFunctionToTable("sqrt", &Parser<ValueType>::Sqrt);
1601  InsertFunctionToTable("sinh", &Parser<ValueType>::Sinh);
1602  InsertFunctionToTable("cosh", &Parser<ValueType>::Cosh);
1603  InsertFunctionToTable("tanh", &Parser<ValueType>::Tanh);
1604  InsertFunctionToTable("tgh", &Parser<ValueType>::Tanh);
1605  InsertFunctionToTable("coth", &Parser<ValueType>::Coth);
1606  InsertFunctionToTable("ctgh", &Parser<ValueType>::Coth);
1607  InsertFunctionToTable("root", &Parser<ValueType>::Root);
1608  InsertFunctionToTable("asinh", &Parser<ValueType>::ASinh);
1609  InsertFunctionToTable("acosh", &Parser<ValueType>::ACosh);
1610  InsertFunctionToTable("atanh", &Parser<ValueType>::ATanh);
1611  InsertFunctionToTable("atgh", &Parser<ValueType>::ATanh);
1612  InsertFunctionToTable("acoth", &Parser<ValueType>::ACoth);
1613  InsertFunctionToTable("actgh", &Parser<ValueType>::ACoth);
1614  InsertFunctionToTable("bitand", &Parser<ValueType>::BitAnd);
1615  InsertFunctionToTable("bitor", &Parser<ValueType>::BitOr);
1616  InsertFunctionToTable("bitxor", &Parser<ValueType>::BitXor);
1617  InsertFunctionToTable("band", &Parser<ValueType>::BitAnd);
1618  InsertFunctionToTable("bor", &Parser<ValueType>::BitOr);
1619  InsertFunctionToTable("bxor", &Parser<ValueType>::BitXor);
1620  InsertFunctionToTable("sum", &Parser<ValueType>::Sum);
1621  InsertFunctionToTable("avg", &Parser<ValueType>::Avg);
1622  InsertFunctionToTable("frac", &Parser<ValueType>::Frac);
1623 }
1624 
1625 
1626 /*!
1627  this method creates the table of variables
1628 */
1629 void CreateVariablesTable()
1630 {
1631  InsertVariableToTable("pi", &ValueType::SetPi);
1632  InsertVariableToTable("e", &ValueType::SetE);
1633 }
1634 
1635 
1636 /*!
1637  converting from a big letter to a small one
1638 */
1639 int ToLowerCase(int c)
1640 {
1641  if( c>='A' && c<='Z' )
1642  return c - 'A' + 'a';
1643 
1644 return c;
1645 }
1646 
1647 
1648 /*!
1649  this method read the name of a variable or a function
1650 
1651  'result' will be the name of a variable or a function
1652  function return 'false' if this name is the name of a variable
1653  or function return 'true' if this name is the name of a function
1654 
1655  what should be returned is tested just by a '(' character that means if there's
1656  a '(' character after a name that function returns 'true'
1657 */
1658 bool ReadName(std::string & result)
1659 {
1660 int character;
1661 
1662 
1663  result.erase();
1664  character = *pstring;
1665 
1666  /*
1667  the first letter must be from range 'a' - 'z' or 'A' - 'Z'
1668  */
1669  if( ! (( character>='a' && character<='z' ) || ( character>='A' && character<='Z' )) )
1670  Error( err_unknown_character );
1671 
1672 
1673  do
1674  {
1675  result += static_cast<char>( character );
1676  character = * ++pstring;
1677  }
1678  while( (character>='a' && character<='z') ||
1679  (character>='A' && character<='Z') ||
1680  (character>='0' && character<='9') ||
1681  character=='_' );
1682 
1683 
1684  SkipWhiteCharacters();
1685 
1686 
1687  /*
1688  if there's a character '(' that means this name is a name of a function
1689  */
1690  if( *pstring == '(' )
1691  {
1692  ++pstring;
1693  return true;
1694  }
1695 
1696 
1697 return false;
1698 }
1699 
1700 
1701 /*!
1702  we're checking whether the first character is '-' or '+'
1703  if it is we'll return 'true' and if it is equally '-' we'll set the 'sign' member of 'result'
1704 */
1705 bool TestSign(Item & result)
1706 {
1707  SkipWhiteCharacters();
1708  result.sign = false;
1709 
1710  if( *pstring == '-' || *pstring == '+' )
1711  {
1712  if( *pstring == '-' )
1713  result.sign = true;
1714 
1715  ++pstring;
1716 
1717  return true;
1718  }
1719 
1720 return false;
1721 }
1722 
1723 
1724 /*!
1725  we're reading the name of a variable or a function
1726  if is there a function we'll return 'true'
1727 */
1728 bool ReadVariableOrFunction(Item & result)
1729 {
1730 std::string name;
1731 bool is_it_name_of_function = ReadName(name);
1732 
1733  if( is_it_name_of_function )
1734  {
1735  /*
1736  we've read the name of a function
1737  */
1738  result.function_name = name;
1739  result.type = Item::first_bracket;
1740  result.function = true;
1741  }
1742  else
1743  {
1744  /*
1745  we've read the name of a variable and we're getting its value now
1746  */
1747  result.value = GetValueOfVariable( name );
1748  }
1749 
1750 return is_it_name_of_function;
1751 }
1752 
1753 
1754 
1755 
1756 /*!
1757  we're reading a numerical value directly from the string
1758 */
1759 void ReadValue(Item & result, int reading_base)
1760 {
1761 const char * new_stack_pointer;
1762 bool value_read;
1763 Conv conv;
1764 
1765  conv.base = reading_base;
1766  conv.comma = comma;
1767  conv.comma2 = comma2;
1768  conv.group = group;
1769 
1770  uint carry = result.value.FromString(pstring, conv, &new_stack_pointer, &value_read);
1771  pstring = new_stack_pointer;
1772 
1773  if( carry )
1774  Error( err_overflow );
1775 
1776  if( !value_read )
1777  Error( err_unknown_character );
1778 }
1779 
1780 
1781 /*!
1782  this method returns true if 'character' is a proper first digit for the value (or a comma -- can be first too)
1783 */
1784 bool ValueStarts(int character, int character_base)
1785 {
1786  if( character == comma )
1787  return true;
1788 
1789  if( comma2!=0 && character==comma2 )
1790  return true;
1791 
1792  if( Misc::CharToDigit(character, character_base) != -1 )
1793  return true;
1794 
1795 return false;
1796 }
1797 
1798 
1799 /*!
1800  we're reading the item
1801 
1802  return values:
1803  0 - all ok, the item is successfully read
1804  1 - the end of the string (the item is not read)
1805  2 - the final bracket ')'
1806 */
1807 int ReadValueVariableOrFunction(Item & result)
1808 {
1809 bool it_was_sign = false;
1810 int character;
1811 
1812 
1813  if( TestSign(result) )
1814  // 'result.sign' was set as well
1815  it_was_sign = true;
1816 
1817  SkipWhiteCharacters();
1818  character = ToLowerCase( *pstring );
1819 
1820 
1821  if( character == 0 )
1822  {
1823  if( it_was_sign )
1824  // at the end of the string a character like '-' or '+' has left
1825  Error( err_unexpected_end );
1826 
1827  // there's the end of the string here
1828  return 1;
1829  }
1830  else
1831  if( character == '(' )
1832  {
1833  // we've got a normal bracket (not a function)
1834  result.type = Item::first_bracket;
1835  result.function = false;
1836  ++pstring;
1837 
1838  return 0;
1839  }
1840  else
1841  if( character == ')' )
1842  {
1843  // we've got a final bracket
1844  // (in this place we can find a final bracket only when there are empty brackets
1845  // without any values inside or with a sign '-' or '+' inside)
1846 
1847  if( it_was_sign )
1848  Error( err_unexpected_final_bracket );
1849 
1850  result.type = Item::last_bracket;
1851 
1852  // we don't increment 'pstring', this final bracket will be read next by the
1853  // 'ReadOperatorAndCheckFinalBracket(...)' method
1854 
1855  return 2;
1856  }
1857  else
1858  if( character == '#' )
1859  {
1860  ++pstring;
1861  SkipWhiteCharacters();
1862 
1863  // after '#' character we do not allow '-' or '+' (can be white characters)
1864  if( ValueStarts(*pstring, 16) )
1865  ReadValue( result, 16 );
1866  else
1867  Error( err_unknown_character );
1868  }
1869  else
1870  if( character == '&' )
1871  {
1872  ++pstring;
1873  SkipWhiteCharacters();
1874 
1875  // after '&' character we do not allow '-' or '+' (can be white characters)
1876  if( ValueStarts(*pstring, 2) )
1877  ReadValue( result, 2 );
1878  else
1879  Error( err_unknown_character );
1880  }
1881  else
1882  if( ValueStarts(character, base) )
1883  {
1884  ReadValue( result, base );
1885  }
1886  else
1887  if( character>='a' && character<='z' )
1888  {
1889  if( ReadVariableOrFunction(result) )
1890  // we've read the name of a function
1891  return 0;
1892  }
1893  else
1894  Error( err_unknown_character );
1895 
1896 
1897 
1898  /*
1899  we've got a value in the 'result'
1900  this value is from a variable or directly from the string
1901  */
1902  result.type = Item::numerical_value;
1903 
1904  if( result.sign )
1905  {
1906  result.value.ChangeSign();
1907  result.sign = false;
1908  }
1909 
1910 
1911 return 0;
1912 }
1913 
1914 
1915 void InsertOperatorToTable(const char * name, typename MatOperator::Type type)
1916 {
1917  operators_table.insert( std::make_pair(std::string(name), type) );
1918 }
1919 
1920 
1921 /*!
1922  this method creates the table of operators
1923 */
1924 void CreateMathematicalOperatorsTable()
1925 {
1926  InsertOperatorToTable("||", MatOperator::lor);
1927  InsertOperatorToTable("&&", MatOperator::land);
1928  InsertOperatorToTable("!=", MatOperator::neq);
1929  InsertOperatorToTable("==", MatOperator::eq);
1930  InsertOperatorToTable(">=", MatOperator::get);
1931  InsertOperatorToTable("<=", MatOperator::let);
1932  InsertOperatorToTable(">", MatOperator::gt);
1933  InsertOperatorToTable("<", MatOperator::lt);
1934  InsertOperatorToTable("-", MatOperator::sub);
1935  InsertOperatorToTable("+", MatOperator::add);
1936  InsertOperatorToTable("/", MatOperator::div);
1937  InsertOperatorToTable("*", MatOperator::mul);
1938  InsertOperatorToTable("^", MatOperator::pow);
1939 }
1940 
1941 
1942 /*!
1943  returns true if 'str2' is the substring of str1
1944 
1945  e.g.
1946  true when str1="test" and str2="te"
1947 */
1948 bool IsSubstring(const std::string & str1, const std::string & str2)
1949 {
1950  if( str2.length() > str1.length() )
1951  return false;
1952 
1953  for(typename std::string::size_type i=0 ; i<str2.length() ; ++i)
1954  if( str1[i] != str2[i] )
1955  return false;
1956 
1957 return true;
1958 }
1959 
1960 
1961 /*!
1962  this method reads a mathematical (or logical) operator
1963 */
1964 void ReadMathematicalOperator(Item & result)
1965 {
1966 std::string oper;
1967 typename OperatorsTable::iterator iter_old, iter_new;
1968 
1969  iter_old = operators_table.end();
1970 
1971  for( ; true ; ++pstring )
1972  {
1973  oper += *pstring;
1974  iter_new = operators_table.lower_bound(oper);
1975 
1976  if( iter_new == operators_table.end() || !IsSubstring(iter_new->first, oper) )
1977  {
1978  oper.erase(oper.begin() + oper.size() - 1); // we've got mininum one element
1979 
1980  if( iter_old != operators_table.end() && iter_old->first == oper )
1981  {
1982  result.type = Item::mat_operator;
1983  result.moperator.SetType( iter_old->second );
1984  break;
1985  }
1986 
1987  Error( err_unknown_operator );
1988  }
1989 
1990  iter_old = iter_new;
1991  }
1992 }
1993 
1994 
1995 /*!
1996  this method makes a calculation for the percentage operator
1997  e.g.
1998  1000-50% = 1000-(1000*0,5) = 500
1999 */
2000 void OperatorPercentage()
2001 {
2002  if( stack_index < 3 ||
2003  stack[stack_index-1].type != Item::numerical_value ||
2004  stack[stack_index-2].type != Item::mat_operator ||
2005  stack[stack_index-3].type != Item::numerical_value )
2006  Error(err_percent_from);
2007 
2008  ++pstring;
2009  SkipWhiteCharacters();
2010 
2011  uint c = 0;
2012  c += stack[stack_index-1].value.Div(100);
2013  c += stack[stack_index-1].value.Mul(stack[stack_index-3].value);
2014 
2015  if( c )
2016  Error(err_overflow);
2017 }
2018 
2019 
2020 /*!
2021  this method reads a mathematic operators
2022  or the final bracket or the semicolon operator
2023 
2024  return values:
2025  0 - ok
2026  1 - the string is finished
2027 */
2028 int ReadOperator(Item & result)
2029 {
2030  SkipWhiteCharacters();
2031 
2032  if( *pstring == '%' )
2033  OperatorPercentage();
2034 
2035 
2036  if( *pstring == 0 )
2037  return 1;
2038  else
2039  if( *pstring == ')' )
2040  {
2041  result.type = Item::last_bracket;
2042  ++pstring;
2043  }
2044  else
2045  if( *pstring == ';' || (param_sep!=0 && *pstring==param_sep) )
2046  {
2047  result.type = Item::semicolon;
2048  ++pstring;
2049  }
2050  else
2051  if( (*pstring>='a' && *pstring<='z') || (*pstring>='A' && *pstring<='Z') )
2052  {
2053  // short mul (without any operators)
2054 
2055  result.type = Item::mat_operator;
2056  result.moperator.SetType( MatOperator::shortmul );
2057  }
2058  else
2059  ReadMathematicalOperator(result);
2060 
2061 return 0;
2062 }
2063 
2064 
2065 
2066 /*!
2067  this method is making the standard mathematic operation like '-' '+' '*' '/' and '^'
2068 
2069  the operation is made between 'value1' and 'value2'
2070  the result of this operation is stored in the 'value1'
2071 */
2072 void MakeStandardMathematicOperation(ValueType & value1, typename MatOperator::Type mat_operator,
2073  const ValueType & value2)
2074 {
2075 uint res;
2076 
2077  calculated = true;
2078 
2079  switch( mat_operator )
2080  {
2081  case MatOperator::land:
2082  (!value1.IsZero() && !value2.IsZero()) ? value1.SetOne() : value1.SetZero();
2083  break;
2084 
2085  case MatOperator::lor:
2086  (!value1.IsZero() || !value2.IsZero()) ? value1.SetOne() : value1.SetZero();
2087  break;
2088 
2089  case MatOperator::eq:
2090  (value1 == value2) ? value1.SetOne() : value1.SetZero();
2091  break;
2092 
2093  case MatOperator::neq:
2094  (value1 != value2) ? value1.SetOne() : value1.SetZero();
2095  break;
2096 
2097  case MatOperator::lt:
2098  (value1 < value2) ? value1.SetOne() : value1.SetZero();
2099  break;
2100 
2101  case MatOperator::gt:
2102  (value1 > value2) ? value1.SetOne() : value1.SetZero();
2103  break;
2104 
2105  case MatOperator::let:
2106  (value1 <= value2) ? value1.SetOne() : value1.SetZero();
2107  break;
2108 
2109  case MatOperator::get:
2110  (value1 >= value2) ? value1.SetOne() : value1.SetZero();
2111  break;
2112 
2113  case MatOperator::sub:
2114  if( value1.Sub(value2) ) Error( err_overflow );
2115  break;
2116 
2117  case MatOperator::add:
2118  if( value1.Add(value2) ) Error( err_overflow );
2119  break;
2120 
2121  case MatOperator::mul:
2122  case MatOperator::shortmul:
2123  if( value1.Mul(value2) ) Error( err_overflow );
2124  break;
2125 
2126  case MatOperator::div:
2127  if( value2.IsZero() ) Error( err_division_by_zero );
2128  if( value1.Div(value2) ) Error( err_overflow );
2129  break;
2130 
2131  case MatOperator::pow:
2132  res = value1.Pow( value2 );
2133 
2134  if( res == 1 ) Error( err_overflow );
2135  else
2136  if( res == 2 ) Error( err_improper_argument );
2137 
2138  break;
2139 
2140  default:
2141  /*
2142  on the stack left an unknown operator but we had to recognize its before
2143  that means there's an error in our algorithm
2144  */
2145  Error( err_internal_error );
2146  }
2147 }
2148 
2149 
2150 
2151 
2152 /*!
2153  this method is trying to roll the stack up with the operator's priority
2154 
2155  for example if there are:
2156  "1 - 2 +"
2157  we can subtract "1-2" and the result store on the place where is '1' and copy the last
2158  operator '+', that means there'll be '-1+' on our stack
2159 
2160  but if there are:
2161  "1 - 2 *"
2162  we can't roll the stack up because the operator '*' has greater priority than '-'
2163 */
2164 void TryRollingUpStackWithOperatorPriority()
2165 {
2166  while( stack_index>=4 &&
2167  stack[stack_index-4].type == Item::numerical_value &&
2168  stack[stack_index-3].type == Item::mat_operator &&
2169  stack[stack_index-2].type == Item::numerical_value &&
2170  stack[stack_index-1].type == Item::mat_operator &&
2171  (
2172  (
2173  // the first operator has greater priority
2174  stack[stack_index-3].moperator.GetPriority() > stack[stack_index-1].moperator.GetPriority()
2175  ) ||
2176  (
2177  // or both operators have the same priority and the first operator is not right associative
2178  stack[stack_index-3].moperator.GetPriority() == stack[stack_index-1].moperator.GetPriority() &&
2179  stack[stack_index-3].moperator.GetAssoc() == MatOperator::non_right
2180  )
2181  )
2182  )
2183  {
2184  MakeStandardMathematicOperation(stack[stack_index-4].value,
2185  stack[stack_index-3].moperator.GetType(),
2186  stack[stack_index-2].value);
2187 
2188 
2189  /*
2190  copying the last operator and setting the stack pointer to the correct value
2191  */
2192  stack[stack_index-3] = stack[stack_index-1];
2193  stack_index -= 2;
2194  }
2195 }
2196 
2197 
2198 /*!
2199  this method is trying to roll the stack up without testing any operators
2200 
2201  for example if there are:
2202  "1 - 2"
2203  there'll be "-1" on our stack
2204 */
2205 void TryRollingUpStack()
2206 {
2207  while( stack_index >= 3 &&
2208  stack[stack_index-3].type == Item::numerical_value &&
2209  stack[stack_index-2].type == Item::mat_operator &&
2210  stack[stack_index-1].type == Item::numerical_value )
2211  {
2212  MakeStandardMathematicOperation( stack[stack_index-3].value,
2213  stack[stack_index-2].moperator.GetType(),
2214  stack[stack_index-1].value );
2215 
2216  stack_index -= 2;
2217  }
2218 }
2219 
2220 
2221 /*!
2222  this method is reading a value or a variable or a function
2223  (the normal first bracket as well) and push it into the stack
2224 */
2225 int ReadValueVariableOrFunctionAndPushItIntoStack(Item & temp)
2226 {
2227 int code = ReadValueVariableOrFunction( temp );
2228 
2229  if( code == 0 )
2230  {
2231  if( stack_index < stack.size() )
2232  stack[stack_index] = temp;
2233  else
2234  stack.push_back( temp );
2235 
2236  ++stack_index;
2237  }
2238 
2239  if( code == 2 )
2240  // there was a final bracket, we didn't push it into the stack
2241  // (it'll be read by the 'ReadOperatorAndCheckFinalBracket' method next)
2242  code = 0;
2243 
2244 
2245 return code;
2246 }
2247 
2248 
2249 
2250 /*!
2251  this method calculate how many parameters there are on the stack
2252  and the index of the first parameter
2253 
2254  if there aren't any parameters on the stack this method returns
2255  'size' equals zero and 'index' pointing after the first bracket
2256  (on non-existend element)
2257 */
2258 void HowManyParameters(int & size, int & index)
2259 {
2260  size = 0;
2261  index = stack_index;
2262 
2263  if( index == 0 )
2264  // we haven't put a first bracket on the stack
2265  Error( err_unexpected_final_bracket );
2266 
2267 
2268  if( stack[index-1].type == Item::first_bracket )
2269  // empty brackets
2270  return;
2271 
2272  for( --index ; index>=1 ; index-=2 )
2273  {
2274  if( stack[index].type != Item::numerical_value )
2275  {
2276  /*
2277  this element must be 'numerical_value', if not that means
2278  there's an error in our algorithm
2279  */
2280  Error( err_internal_error );
2281  }
2282 
2283  ++size;
2284 
2285  if( stack[index-1].type != Item::semicolon )
2286  break;
2287  }
2288 
2289  if( index<1 || stack[index-1].type != Item::first_bracket )
2290  {
2291  /*
2292  we haven't put a first bracket on the stack
2293  */
2294  Error( err_unexpected_final_bracket );
2295  }
2296 }
2297 
2298 
2299 /*!
2300  this method is being called when the final bracket ')' is being found
2301 
2302  this method's rolling the stack up, counting how many parameters there are
2303  on the stack and if there was a function it's calling the function
2304 */
2305 void RollingUpFinalBracket()
2306 {
2307 int amount_of_parameters;
2308 int index;
2309 
2310 
2311  if( stack_index<1 ||
2312  (stack[stack_index-1].type != Item::numerical_value &&
2313  stack[stack_index-1].type != Item::first_bracket)
2314  )
2315  Error( err_unexpected_final_bracket );
2316 
2317 
2318  TryRollingUpStack();
2319  HowManyParameters(amount_of_parameters, index);
2320 
2321  // 'index' will be greater than zero
2322  // 'amount_of_parameters' can be zero
2323 
2324 
2325  if( amount_of_parameters==0 && !stack[index-1].function )
2326  Error( err_unexpected_final_bracket );
2327 
2328 
2329  bool was_sign = stack[index-1].sign;
2330 
2331 
2332  if( stack[index-1].function )
2333  {
2334  // the result of a function will be on 'stack[index-1]'
2335  // and then at the end we'll set the correct type (numerical value) of this element
2336  CallFunction(stack[index-1].function_name, amount_of_parameters, index);
2337  }
2338  else
2339  {
2340  /*
2341  there was a normal bracket (not a funcion)
2342  */
2343  if( amount_of_parameters != 1 )
2344  Error( err_unexpected_semicolon_operator );
2345 
2346 
2347  /*
2348  in the place where is the bracket we put the result
2349  */
2350  stack[index-1] = stack[index];
2351  }
2352 
2353 
2354  /*
2355  if there was a '-' character before the first bracket
2356  we change the sign of the expression
2357  */
2358  stack[index-1].sign = false;
2359 
2360  if( was_sign )
2361  stack[index-1].value.ChangeSign();
2362 
2363  stack[index-1].type = Item::numerical_value;
2364 
2365 
2366  /*
2367  the pointer of the stack will be pointing on the next (non-existing now) element
2368  */
2369  stack_index = index;
2370 }
2371 
2372 
2373 /*!
2374  this method is putting the operator on the stack
2375 */
2376 
2377 void PushOperatorIntoStack(Item & temp)
2378 {
2379  if( stack_index < stack.size() )
2380  stack[stack_index] = temp;
2381  else
2382  stack.push_back( temp );
2383 
2384  ++stack_index;
2385 }
2386 
2387 
2388 
2389 /*!
2390  this method is reading a operator and if it's a final bracket
2391  it's calling RollingUpFinalBracket() and reading a operator again
2392 */
2393 int ReadOperatorAndCheckFinalBracket(Item & temp)
2394 {
2395  do
2396  {
2397  if( ReadOperator(temp) == 1 )
2398  {
2399  /*
2400  the string is finished
2401  */
2402  return 1;
2403  }
2404 
2405  if( temp.type == Item::last_bracket )
2406  RollingUpFinalBracket();
2407 
2408  }
2409  while( temp.type == Item::last_bracket );
2410 
2411 return 0;
2412 }
2413 
2414 
2415 /*!
2416  we check wheter there are only numerical value's or 'semicolon' operators on the stack
2417 */
2418 void CheckIntegrityOfStack()
2419 {
2420  for(unsigned int i=0 ; i<stack_index; ++i)
2421  {
2422  if( stack[i].type != Item::numerical_value &&
2423  stack[i].type != Item::semicolon)
2424  {
2425  /*
2426  on the stack we must only have 'numerical_value' or 'semicolon' operator
2427  if there is something another that means
2428  we probably didn't close any of the 'first' bracket
2429  */
2430  Error( err_stack_not_clear );
2431  }
2432  }
2433 }
2434 
2435 
2436 
2437 /*!
2438  the main loop of parsing
2439 */
2440 void Parse()
2441 {
2442 Item item;
2443 int result_code;
2444 
2445 
2446  while( true )
2447  {
2448  if( pstop_calculating && pstop_calculating->WasStopSignal() )
2449  Error( err_interrupt );
2450 
2451  result_code = ReadValueVariableOrFunctionAndPushItIntoStack( item );
2452 
2453  if( result_code == 0 )
2454  {
2455  if( item.type == Item::first_bracket )
2456  continue;
2457 
2458  result_code = ReadOperatorAndCheckFinalBracket( item );
2459  }
2460 
2461 
2462  if( result_code==1 || item.type==Item::semicolon )
2463  {
2464  /*
2465  the string is finished or the 'semicolon' operator has appeared
2466  */
2467 
2468  if( stack_index == 0 )
2469  Error( err_nothing_has_read );
2470 
2471  TryRollingUpStack();
2472 
2473  if( result_code == 1 )
2474  {
2475  CheckIntegrityOfStack();
2476 
2477  return;
2478  }
2479  }
2480 
2481 
2482  PushOperatorIntoStack( item );
2483  TryRollingUpStackWithOperatorPriority();
2484  }
2485 }
2486 
2487 /*!
2488  this method is called at the end of the parsing process
2489 
2490  on our stack we can have another value than 'numerical_values' for example
2491  when someone use the operator ';' in the global scope or there was an error during
2492  parsing and the parser hasn't finished its job
2493 
2494  if there was an error the stack is cleaned up now
2495  otherwise we resize stack and leave on it only 'numerical_value' items
2496 */
2497 void NormalizeStack()
2498 {
2499  if( error!=err_ok || stack_index==0 )
2500  {
2501  stack.clear();
2502  return;
2503  }
2504 
2505 
2506  /*
2507  'stack_index' tell us how many elements there are on the stack,
2508  we must resize the stack now because 'stack_index' is using only for parsing
2509  and stack has more (or equal) elements than value of 'stack_index'
2510  */
2511  stack.resize( stack_index );
2512 
2513  for(uint i=stack_index-1 ; i!=uint(-1) ; --i)
2514  {
2515  if( stack[i].type != Item::numerical_value )
2516  stack.erase( stack.begin() + i );
2517  }
2518 }
2519 
2520 
2521 public:
2522 
2523 
2524 /*!
2525  the default constructor
2526 */
2527 Parser(): default_stack_size(100)
2528 {
2529  pstop_calculating = 0;
2530  puser_variables = 0;
2531  puser_functions = 0;
2532  pfunction_local_variables = 0;
2533  base = 10;
2534  deg_rad_grad = 1;
2535  error = err_ok;
2536  group = 0;
2537  comma = '.';
2538  comma2 = ',';
2539  param_sep = 0;
2540 
2541  CreateFunctionsTable();
2542  CreateVariablesTable();
2543  CreateMathematicalOperatorsTable();
2544 }
2545 
2546 
2547 /*!
2548  the assignment operator
2549 */
2551 {
2552  pstop_calculating = p.pstop_calculating;
2553  puser_variables = p.puser_variables;
2554  puser_functions = p.puser_functions;
2555  pfunction_local_variables = 0;
2556  base = p.base;
2557  deg_rad_grad = p.deg_rad_grad;
2558  error = p.error;
2559  group = p.group;
2560  comma = p.comma;
2561  comma2 = p.comma2;
2562  param_sep = p.param_sep;
2563 
2564  /*
2565  we don't have to call 'CreateFunctionsTable()' etc.
2566  we can only copy these tables
2567  */
2568  functions_table = p.functions_table;
2569  variables_table = p.variables_table;
2570  operators_table = p.operators_table;
2571 
2572  visited_variables = p.visited_variables;
2573  visited_functions = p.visited_functions;
2574 
2575 return *this;
2576 }
2577 
2578 
2579 /*!
2580  the copying constructor
2581 */
2582 Parser(const Parser<ValueType> & p): default_stack_size(p.default_stack_size)
2583 {
2584  operator=(p);
2585 }
2586 
2587 
2588 /*!
2589  the new base of mathematic system
2590  default is 10
2591 */
2592 void SetBase(int b)
2593 {
2594  if( b>=2 && b<=16 )
2595  base = b;
2596 }
2597 
2598 
2599 /*!
2600  the unit of angles used in: sin,cos,tan,cot,asin,acos,atan,acot
2601  0 - deg
2602  1 - rad (default)
2603  2 - grad
2604 */
2605 void SetDegRadGrad(int angle)
2606 {
2607  if( angle >= 0 && angle <= 2 )
2608  deg_rad_grad = angle;
2609 }
2610 
2611 /*!
2612  this method sets a pointer to the object which tell us whether we should stop
2613  calculations
2614 */
2615 void SetStopObject(const volatile StopCalculating * ps)
2616 {
2617  pstop_calculating = ps;
2618 }
2619 
2620 
2621 /*!
2622  this method sets the new table of user-defined variables
2623  if you don't want any other variables just put zero value into the 'puser_variables' variable
2624 
2625  (you can have only one table at the same time)
2626 */
2627 void SetVariables(const Objects * pv)
2628 {
2629  puser_variables = pv;
2630 }
2631 
2632 
2633 /*!
2634  this method sets the new table of user-defined functions
2635  if you don't want any other functions just put zero value into the 'puser_functions' variable
2636 
2637  (you can have only one table at the same time)
2638 */
2639 void SetFunctions(const Objects * pf)
2640 {
2641  puser_functions = pf;
2642 }
2643 
2644 
2645 /*!
2646  setting the group character
2647  default zero (not used)
2648 */
2649 void SetGroup(int g)
2650 {
2651  group = g;
2652 }
2653 
2654 
2655 /*!
2656  setting the main comma operator and the additional comma operator
2657  the additional operator can be zero (which means it is not used)
2658  default are: '.' and ','
2659 */
2660 void SetComma(int c, int c2 = 0)
2661 {
2662  comma = c;
2663  comma2 = c2;
2664 }
2665 
2666 
2667 /*!
2668  setting an additional character which is used as a parameters separator
2669  the main parameters separator is a semicolon (is used always)
2670 
2671  this character is used also as a global separator
2672 */
2673 void SetParamSep(int s)
2674 {
2675  param_sep = s;
2676 }
2677 
2678 
2679 /*!
2680  the main method using for parsing string
2681 */
2682 ErrorCode Parse(const char * str)
2683 {
2684  stack_index = 0;
2685  pstring = str;
2686  error = err_ok;
2687  calculated = false;
2688 
2689  stack.resize( default_stack_size );
2690 
2691  try
2692  {
2693  Parse();
2694  }
2695  catch(ErrorCode c)
2696  {
2697  error = c;
2698  calculated = false;
2699  }
2700 
2701  NormalizeStack();
2702 
2703 return error;
2704 }
2705 
2706 
2707 /*!
2708  the main method using for parsing string
2709 */
2710 ErrorCode Parse(const std::string & str)
2711 {
2712  return Parse(str.c_str());
2713 }
2714 
2715 
2716 #ifndef TTMATH_DONT_USE_WCHAR
2717 
2718 /*!
2719  the main method using for parsing string
2720 */
2721 ErrorCode Parse(const wchar_t * str)
2722 {
2723  Misc::AssignString(wide_to_ansi, str);
2724 
2725 return Parse(wide_to_ansi.c_str());
2726 
2727  // !! wide_to_ansi clearing can be added here
2728 }
2729 
2730 
2731 /*!
2732  the main method using for parsing string
2733 */
2734 ErrorCode Parse(const std::wstring & str)
2735 {
2736  return Parse(str.c_str());
2737 }
2738 
2739 #endif
2740 
2741 
2742 /*!
2743  this method returns true is something was calculated
2744  (at least one mathematical operator was used or a function or variable)
2745  e.g. true if the string to Parse() looked like this:
2746  "1+1"
2747  "2*3"
2748  "sin(5)"
2749 
2750  if the string was e.g. "678" the result is false
2751 */
2753 {
2754  return calculated;
2755 }
2756 
2757 
2758 /*!
2759  initializing coefficients used when calculating the gamma (or factorial) function
2760  this speed up the next calculations
2761  you don't have to call this method explicitly
2762  these coefficients will be calculated when needed
2763 */
2765 {
2766  cgamma.InitAll();
2767 }
2768 
2769 
2770 };
2771 
2772 
2773 
2774 } // namespace
2775 
2776 
2777 #endif
ValueType Sgn(ValueType x)
Definition: ttmath.h:2155
ValueType ACot(const ValueType &x)
Definition: ttmath.h:1136
ValueType ACoth(const ValueType &x, ErrorCode *err=0)
Definition: ttmath.h:1489
Int implements a big integer value with a sign.
Definition: ttmathint.h:63
ValueType Tan(const ValueType &x, ErrorCode *err=0)
Definition: ttmath.h:619
ValueType Log(const ValueType &x, const ValueType &base, ErrorCode *err=0)
Definition: ttmath.h:278
ValueType Sin(ValueType x, ErrorCode *err=0)
Definition: ttmath.h:525
void SetParamSep(int s)
static uint CharToDigit(uint c)
Definition: ttmathmisc.h:181
ErrorCode Parse(const std::wstring &str)
void SetComma(int c, int c2=0)
some helpful functions
std::vector< Item > stack
Definition: ttmathparser.h:296
ValueType Exp(const ValueType &x, ErrorCode *err=0)
Definition: ttmath.h:323
ErrorCode Parse(const char *str)
Mathematical parser.
Definition: ttmathparser.h:138
ValueType ACosh(const ValueType &x, ErrorCode *err=0)
Definition: ttmath.h:1387
ValueType RadToDeg(const ValueType &x, ErrorCode *err=0)
Definition: ttmath.h:1588
ValueType ASin(ValueType x, ErrorCode *err=0)
Definition: ttmath.h:855
void InitAll()
Definition: ttmath.h:2840
ValueType ASinh(const ValueType &x, ErrorCode *err=0)
Definition: ttmath.h:1351
ValueType SkipFraction(const ValueType &x)
Definition: ttmath.h:90
ValueType Cos(ValueType x, ErrorCode *err=0)
Definition: ttmath.h:581
void SetVariables(const Objects *pv)
ValueType ATanh(const ValueType &x, ErrorCode *err=0)
Definition: ttmath.h:1436
ErrorCode Parse(const wchar_t *str)
ValueType Ln(const ValueType &x, ErrorCode *err=0)
Definition: ttmath.h:237
Parser< ValueType > & operator=(const Parser< ValueType > &p)
ErrorCode GetValueAndParam(const std::string &name, std::string &value, int *param) const
ValueType RadToGrad(const ValueType &x, ErrorCode *err=0)
Definition: ttmath.h:1726
ValueType Abs(const ValueType &x)
Definition: ttmath.h:2137
void SetDegRadGrad(int angle)
ValueType GradToDeg(const ValueType &x, ErrorCode *err=0)
Definition: ttmath.h:1808
static void AssignString(std::string &result, const char *str)
Definition: ttmathmisc.h:72
void SetBase(int b)
a namespace for the TTMath library
Definition: ttmath.h:62
ErrorCode Parse(const std::string &str)
ValueType Root(ValueType x, const ValueType &index, ErrorCode *err=0)
Definition: ttmath.h:2076
ValueType DegToRad(const ValueType &x, ErrorCode *err=0)
Definition: ttmath.h:1552
ValueType GradToRad(const ValueType &x, ErrorCode *err=0)
Definition: ttmath.h:1690
void SetFunctions(const Objects *pf)
ValueType Mod(ValueType a, const ValueType &b, ErrorCode *err=0)
Definition: ttmath.h:2173
void SetStopObject(const volatile StopCalculating *ps)
ValueType ATan(ValueType x)
Definition: ttmath.h:1085
Parser(const Parser< ValueType > &p)
ValueType Coth(const ValueType &x, ErrorCode *err=0)
Definition: ttmath.h:1286
ValueType Factorial(const ValueType &x, CGamma< ValueType > &cgamma, ErrorCode *err=0, const volatile StopCalculating *stop=0)
Definition: ttmath.h:2809
ValueType Floor(const ValueType &x, ErrorCode *err=0)
Definition: ttmath.h:189
ValueType Tanh(const ValueType &x, ErrorCode *err=0)
Definition: ttmath.h:1238
ValueType Sinh(const ValueType &x, ErrorCode *err=0)
Definition: ttmath.h:1174
ValueType Cot(const ValueType &x, ErrorCode *err=0)
Definition: ttmath.h:661
ValueType DegToGrad(const ValueType &x, ErrorCode *err=0)
Definition: ttmath.h:1758
ValueType Gamma(const ValueType &n, CGamma< ValueType > &cgamma, ErrorCode *err=0, const volatile StopCalculating *stop=0)
Definition: ttmath.h:2679
Mathematic functions.
ValueType Cosh(const ValueType &x, ErrorCode *err=0)
Definition: ttmath.h:1206
ErrorCode GetValue(const std::string &name, std::string &value) const
Mathematics functions.
unsigned long uint
Definition: ttmathtypes.h:238
ValueType Round(const ValueType &x, ErrorCode *err=0)
Definition: ttmath.h:109
ValueType DegToDeg(const ValueType &d, const ValueType &m, const ValueType &s, ErrorCode *err=0)
Definition: ttmath.h:1633
ValueType GetValueOfVariable(const std::string &variable_name)
Definition: ttmathparser.h:640
bool GetValueOfFunctionLocalVariable(const std::string &variable_name, ValueType &result)
Definition: ttmathparser.h:618
void SetGroup(int g)
ValueType Ceil(const ValueType &x, ErrorCode *err=0)
Definition: ttmath.h:142
ValueType Sqrt(ValueType x, ErrorCode *err=0)
Definition: ttmath.h:1852
ValueType ACos(const ValueType &x, ErrorCode *err=0)
Definition: ttmath.h:910
bool GetValueOfUserDefinedVariable(const std::string &variable_name, ValueType &result)
Definition: ttmathparser.h:598