Library for big numbers from http://www.ttmath.org/

Dependents:   PIDHeater82 Conceptcontroller_v_1_0 AlarmClockApp COG4050_adxl355_tilt ... more

TTMath is a small library which allows one to perform arithmetic operations with big unsigned integer, big signed integer and big floating point numbers. It provides standard mathematical operations like adding, subtracting, multiplying, dividing.

TTMath is BSD Licensed (new/modified BSD)

For more information about ttmath see http://www.ttmath.org/

Committer:
stevep
Date:
Tue Jul 30 18:43:48 2013 +0000
Revision:
0:04a9f72bbca7
v0.9.3 of ttmath

Who changed what in which revision?

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