| [906] | 1 | /* | 
|---|
|  | 2 | * TinyJS | 
|---|
|  | 3 | * | 
|---|
|  | 4 | * A single-file Javascript-alike engine | 
|---|
|  | 5 | * | 
|---|
|  | 6 | * -  Math and Trigonometry functions | 
|---|
|  | 7 | * | 
|---|
|  | 8 | * Authored By O.Z.L.B. <ozlbinfo@gmail.com> | 
|---|
|  | 9 | * | 
|---|
|  | 10 | * Copyright (C) 2011 O.Z.L.B. | 
|---|
|  | 11 | * | 
|---|
|  | 12 |  | 
|---|
|  | 13 | * 42TinyJS | 
|---|
|  | 14 | * | 
|---|
|  | 15 | * A fork of TinyJS with the goal to makes a more JavaScript/ECMA compliant engine | 
|---|
|  | 16 | * | 
|---|
|  | 17 | * Authored / Changed By Armin Diedering <armin@diedering.de> | 
|---|
|  | 18 | * | 
|---|
|  | 19 | * Copyright (C) 2010-2013 ardisoft | 
|---|
|  | 20 | * | 
|---|
|  | 21 | * | 
|---|
|  | 22 | * Permission is hereby granted, free of charge, to any person obtaining a copy of | 
|---|
|  | 23 | * this software and associated documentation files (the "Software"), to deal in | 
|---|
|  | 24 | * the Software without restriction, including without limitation the rights to | 
|---|
|  | 25 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies | 
|---|
|  | 26 | * of the Software, and to permit persons to whom the Software is furnished to do | 
|---|
|  | 27 | * so, subject to the following conditions: | 
|---|
|  | 28 |  | 
|---|
|  | 29 | * The above copyright notice and this permission notice shall be included in all | 
|---|
|  | 30 | * copies or substantial portions of the Software. | 
|---|
|  | 31 |  | 
|---|
|  | 32 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | 
|---|
|  | 33 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | 
|---|
|  | 34 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | 
|---|
|  | 35 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | 
|---|
|  | 36 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | 
|---|
|  | 37 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | 
|---|
|  | 38 | * SOFTWARE. | 
|---|
|  | 39 | */ | 
|---|
|  | 40 |  | 
|---|
|  | 41 | #include <cmath> | 
|---|
|  | 42 | #include <cstdlib> | 
|---|
|  | 43 | #include <sstream> | 
|---|
|  | 44 | #include <ctime> | 
|---|
|  | 45 | #include "TinyJS.h" | 
|---|
|  | 46 |  | 
|---|
|  | 47 | using namespace std; | 
|---|
|  | 48 |  | 
|---|
|  | 49 | #define k_E                 exp(1.0) | 
|---|
|  | 50 | #define k_PI                3.1415926535897932384626433832795 | 
|---|
|  | 51 | #define k_LN2               log((double)2) | 
|---|
|  | 52 | #define k_LN10              log((double)10) | 
|---|
|  | 53 | #define k_LOG2E             (log(k_E)/log((double)2)) | 
|---|
|  | 54 | #define k_LOG10E            log10(k_E) | 
|---|
|  | 55 | #define k_SQRT1_2           sqrt((double)0.5) | 
|---|
|  | 56 | #define k_SQRT2             sqrt((double)2) | 
|---|
|  | 57 |  | 
|---|
|  | 58 | #define F_ABS(a)            ((a)>=0 ? (a) : (-(a))) | 
|---|
|  | 59 | #define F_MIN(a,b)          ((a)>(b) ? (b) : (a)) | 
|---|
|  | 60 | #define F_MAX(a,b)          ((a)>(b) ? (a) : (b)) | 
|---|
|  | 61 | #define F_SGN(a)            ((a)>0 ? 1 : ((a)<0 ? -1 : 0 )) | 
|---|
|  | 62 | #define F_RNG(a,min,max)    ((a)<(min) ? min : ((a)>(max) ? max : a )) | 
|---|
|  | 63 |  | 
|---|
|  | 64 | #ifdef _MSC_VER | 
|---|
|  | 65 | namespace | 
|---|
|  | 66 | { | 
|---|
|  | 67 | double asinh( const double &value ) { | 
|---|
|  | 68 | double returned; | 
|---|
|  | 69 |  | 
|---|
|  | 70 | if(value>0) | 
|---|
|  | 71 | returned = log(value + sqrt(value * value + 1)); | 
|---|
|  | 72 | else | 
|---|
|  | 73 | returned = -log(-value + sqrt(value * value + 1)); | 
|---|
|  | 74 |  | 
|---|
|  | 75 | return(returned); | 
|---|
|  | 76 | } | 
|---|
|  | 77 |  | 
|---|
|  | 78 | double acosh( const double &value ) { | 
|---|
|  | 79 | double returned; | 
|---|
|  | 80 |  | 
|---|
|  | 81 | if(value>0) | 
|---|
|  | 82 | returned = log(value + sqrt(value * value - 1)); | 
|---|
|  | 83 | else | 
|---|
|  | 84 | returned = -log(-value + sqrt(value * value - 1)); | 
|---|
|  | 85 |  | 
|---|
|  | 86 | return(returned); | 
|---|
|  | 87 | } | 
|---|
|  | 88 |  | 
|---|
|  | 89 | double atanh( double value ) { | 
|---|
|  | 90 | bool neg = value<0; | 
|---|
|  | 91 | if(neg) value=-value; | 
|---|
|  | 92 | double value_x2 = 2.0*value; | 
|---|
|  | 93 | if(value>=0.5) | 
|---|
|  | 94 | value = log(1.0+value_x2/(1.0-value))/2.0; | 
|---|
|  | 95 | else | 
|---|
|  | 96 | value = log(1.0+value_x2+value_x2*value/(1.0-value))/2.0; | 
|---|
|  | 97 | return(neg ? -value : value); | 
|---|
|  | 98 | } | 
|---|
|  | 99 | } | 
|---|
|  | 100 | #endif | 
|---|
|  | 101 |  | 
|---|
|  | 102 | #define PARAMETER_TO_NUMBER(v,n) CNumber v = c->getArgument(n)->toNumber() | 
|---|
|  | 103 | #define RETURN_NAN_IS_NAN(v) do{ if(v.isNaN()) { c->setReturnVar(c->newScriptVar(v)); return; } }while(0) | 
|---|
|  | 104 | #define RETURN_NAN_IS_NAN_OR_INFINITY(v) do{ if(v.isNaN() || v.isInfinity()) { c->setReturnVar(c->newScriptVar(v)); return; } }while(0) | 
|---|
|  | 105 | #define RETURN_INFINITY_IS_INFINITY(v) do{ if(v.isInfinity()) { c->setReturnVar(c->newScriptVar(v)); return; } }while(0) | 
|---|
|  | 106 | #define RETURN_ZERO_IS_ZERO(v) do{ if(v.isZero()) { c->setReturnVar(c->newScriptVar(v)); return; } }while(0) | 
|---|
|  | 107 | #define RETURN(a)       do{ c->setReturnVar(c->newScriptVar(a)); return; }while(0) | 
|---|
|  | 108 | #define RETURNconst(a)  c->setReturnVar(c->constScriptVar(a)) | 
|---|
|  | 109 |  | 
|---|
|  | 110 | //Math.abs(x) - returns absolute of given value | 
|---|
|  | 111 | static void scMathAbs(const CFunctionsScopePtr &c, void *userdata) { | 
|---|
|  | 112 | PARAMETER_TO_NUMBER(a,"a"); | 
|---|
|  | 113 | RETURN(a.sign()<0?-a:a); | 
|---|
|  | 114 | } | 
|---|
|  | 115 |  | 
|---|
|  | 116 | //Math.round(a) - returns nearest round of given value | 
|---|
|  | 117 | static void scMathRound(const CFunctionsScopePtr &c, void *userdata) { | 
|---|
|  | 118 | PARAMETER_TO_NUMBER(a,"a"); | 
|---|
|  | 119 | RETURN(a.round()); | 
|---|
|  | 120 | } | 
|---|
|  | 121 |  | 
|---|
|  | 122 | //Math.ceil(a) - returns nearest round of given value | 
|---|
|  | 123 | static void scMathCeil(const CFunctionsScopePtr &c, void *userdata) { | 
|---|
|  | 124 | PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); RETURN_INFINITY_IS_INFINITY(a); | 
|---|
|  | 125 | RETURN(a.ceil()); | 
|---|
|  | 126 | } | 
|---|
|  | 127 |  | 
|---|
|  | 128 | //Math.floor(a) - returns nearest round of given value | 
|---|
|  | 129 | static void scMathFloor(const CFunctionsScopePtr &c, void *userdata) { | 
|---|
|  | 130 | PARAMETER_TO_NUMBER(a,"a"); | 
|---|
|  | 131 | RETURN(a.floor()); | 
|---|
|  | 132 | } | 
|---|
|  | 133 |  | 
|---|
|  | 134 | //Math.min(a,b) - returns minimum of two given values | 
|---|
|  | 135 | static void scMathMin(const CFunctionsScopePtr &c, void *userdata) { | 
|---|
|  | 136 | int length = c->getArgumentsLength(); | 
|---|
|  | 137 | CNumber ret(InfinityPositive); | 
|---|
|  | 138 | for(int i=0; i<length; i++) | 
|---|
|  | 139 | { | 
|---|
|  | 140 | PARAMETER_TO_NUMBER(a,i); RETURN_NAN_IS_NAN(a); | 
|---|
|  | 141 | if(ret>a) ret=a; | 
|---|
|  | 142 | } | 
|---|
|  | 143 | RETURN(ret); | 
|---|
|  | 144 | } | 
|---|
|  | 145 |  | 
|---|
|  | 146 | //Math.max(a,b) - returns maximum of two given values | 
|---|
|  | 147 | static void scMathMax(const CFunctionsScopePtr &c, void *userdata) { | 
|---|
|  | 148 | int length = c->getArgumentsLength(); | 
|---|
|  | 149 | CNumber ret(InfinityNegative); | 
|---|
|  | 150 | for(int i=0; i<length; i++) | 
|---|
|  | 151 | { | 
|---|
|  | 152 | PARAMETER_TO_NUMBER(a,i); RETURN_NAN_IS_NAN(a); | 
|---|
|  | 153 | if(ret<a) ret=a; | 
|---|
|  | 154 | } | 
|---|
|  | 155 | RETURN(ret); | 
|---|
|  | 156 | } | 
|---|
|  | 157 |  | 
|---|
|  | 158 | //Math.range(x,a,b) - returns value limited between two given values | 
|---|
|  | 159 | static void scMathRange(const CFunctionsScopePtr &c, void *userdata) { | 
|---|
|  | 160 | PARAMETER_TO_NUMBER(x,"x"); RETURN_NAN_IS_NAN(x); | 
|---|
|  | 161 | PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); | 
|---|
|  | 162 | PARAMETER_TO_NUMBER(b,"b"); RETURN_NAN_IS_NAN(b); | 
|---|
|  | 163 |  | 
|---|
|  | 164 | if(a>b) RETURNconst(NaN); | 
|---|
|  | 165 | if(x<a) RETURN(a); | 
|---|
|  | 166 | if(x>b) RETURN(b); | 
|---|
|  | 167 | RETURN(x); | 
|---|
|  | 168 | } | 
|---|
|  | 169 |  | 
|---|
|  | 170 | //Math.sign(a) - returns sign of given value (-1==negative,0=zero,1=positive) | 
|---|
|  | 171 | static void scMathSign(const CFunctionsScopePtr &c, void *userdata) { | 
|---|
|  | 172 | PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); | 
|---|
|  | 173 | RETURN(a.isZero() ? 0 : a.sign()); | 
|---|
|  | 174 | } | 
|---|
|  | 175 | static void scMathRandom(const CFunctionsScopePtr &c, void *) { | 
|---|
|  | 176 | static int inited=0; | 
|---|
|  | 177 | if(!inited) { | 
|---|
|  | 178 | inited = 1; | 
|---|
|  | 179 | srand((unsigned int)time(NULL)); | 
|---|
|  | 180 | } | 
|---|
|  | 181 | RETURN(double(rand())/RAND_MAX); | 
|---|
|  | 182 | } | 
|---|
|  | 183 |  | 
|---|
|  | 184 | //Math.toDegrees(a) - returns degree value of a given angle in radians | 
|---|
|  | 185 | static void scMathToDegrees(const CFunctionsScopePtr &c, void *userdata) { | 
|---|
|  | 186 | PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); RETURN_INFINITY_IS_INFINITY(a); | 
|---|
|  | 187 | RETURN( (180.0/k_PI)*a ); | 
|---|
|  | 188 | } | 
|---|
|  | 189 |  | 
|---|
|  | 190 | //Math.toRadians(a) - returns radians value of a given angle in degrees | 
|---|
|  | 191 | static void scMathToRadians(const CFunctionsScopePtr &c, void *userdata) { | 
|---|
|  | 192 | PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); RETURN_INFINITY_IS_INFINITY(a); | 
|---|
|  | 193 | RETURN( (k_PI/180.0)*a ); | 
|---|
|  | 194 | } | 
|---|
|  | 195 |  | 
|---|
|  | 196 | //Math.sin(a) - returns trig. sine of given angle in radians | 
|---|
|  | 197 | static void scMathSin(const CFunctionsScopePtr &c, void *userdata) { | 
|---|
|  | 198 | PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN_OR_INFINITY(a); RETURN_ZERO_IS_ZERO(a); | 
|---|
|  | 199 | RETURN( sin(a.toDouble()) ); | 
|---|
|  | 200 | } | 
|---|
|  | 201 |  | 
|---|
|  | 202 | //Math.asin(a) - returns trig. arcsine of given angle in radians | 
|---|
|  | 203 | static void scMathASin(const CFunctionsScopePtr &c, void *userdata) { | 
|---|
|  | 204 | PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); RETURN_ZERO_IS_ZERO(a); | 
|---|
|  | 205 | if(abs(a)>1) RETURNconst(NaN); | 
|---|
|  | 206 | RETURN( asin(a.toDouble()) ); | 
|---|
|  | 207 | } | 
|---|
|  | 208 |  | 
|---|
|  | 209 | //Math.cos(a) - returns trig. cosine of given angle in radians | 
|---|
|  | 210 | static void scMathCos(const CFunctionsScopePtr &c, void *userdata) { | 
|---|
|  | 211 | PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN_OR_INFINITY(a); | 
|---|
|  | 212 | if(a.isZero()) RETURN(1); | 
|---|
|  | 213 | RETURN( cos(a.toDouble()) ); | 
|---|
|  | 214 | } | 
|---|
|  | 215 |  | 
|---|
|  | 216 | //Math.acos(a) - returns trig. arccosine of given angle in radians | 
|---|
|  | 217 | static void scMathACos(const CFunctionsScopePtr &c, void *userdata) { | 
|---|
|  | 218 | PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN_OR_INFINITY(a); | 
|---|
|  | 219 | if(abs(a)>1) RETURNconst(NaN); | 
|---|
|  | 220 | else if(a==1) RETURN(0); | 
|---|
|  | 221 | RETURN( acos(a.toDouble()) ); | 
|---|
|  | 222 | } | 
|---|
|  | 223 |  | 
|---|
|  | 224 | //Math.tan(a) - returns trig. tangent of given angle in radians | 
|---|
|  | 225 | static void scMathTan(const CFunctionsScopePtr &c, void *userdata) { | 
|---|
|  | 226 | PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN_OR_INFINITY(a); RETURN_ZERO_IS_ZERO(a); | 
|---|
|  | 227 | RETURN( tan(a.toDouble()) ); | 
|---|
|  | 228 | } | 
|---|
|  | 229 |  | 
|---|
|  | 230 | //Math.atan(a) - returns trig. arctangent of given angle in radians | 
|---|
|  | 231 | static void scMathATan(const CFunctionsScopePtr &c, void *userdata) { | 
|---|
|  | 232 | PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); RETURN_ZERO_IS_ZERO(a); | 
|---|
|  | 233 | int infinity=a.isInfinity(); | 
|---|
|  | 234 | if(infinity) RETURN(k_PI/(infinity*2)); | 
|---|
|  | 235 | RETURN( atan(a.toDouble()) ); | 
|---|
|  | 236 | } | 
|---|
|  | 237 |  | 
|---|
|  | 238 | //Math.atan2(a,b) - returns trig. arctangent of given angle in radians | 
|---|
|  | 239 | static void scMathATan2(const CFunctionsScopePtr &c, void *userdata) { | 
|---|
|  | 240 | PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); | 
|---|
|  | 241 | PARAMETER_TO_NUMBER(b,"b"); RETURN_NAN_IS_NAN(b); | 
|---|
|  | 242 | int sign_a = a.sign(); | 
|---|
|  | 243 | int sign_b = b.sign(); | 
|---|
|  | 244 | if(a.isZero()) | 
|---|
|  | 245 | RETURN(sign_a>0 ? (sign_b>0 ? 0.0 : k_PI) : (sign_b>0 ? -0.0 : -k_PI)); | 
|---|
|  | 246 | else if(b.isZero()) | 
|---|
|  | 247 | RETURN((sign_a>0 ? k_PI : -k_PI)/2.0); | 
|---|
|  | 248 | int infinity_a=a.isInfinity(); | 
|---|
|  | 249 | int infinity_b=b.isInfinity(); | 
|---|
|  | 250 | if(infinity_a) { | 
|---|
|  | 251 | if(infinity_b>0) RETURN(k_PI/(infinity_a*4)); | 
|---|
|  | 252 | else if(infinity_b<0) RETURN(3.0*k_PI/(infinity_a*4)); | 
|---|
|  | 253 | else RETURN(k_PI/(infinity_a*2)); | 
|---|
|  | 254 | } else if(infinity_b>0) | 
|---|
|  | 255 | RETURN(sign_a>0 ? 0.0 : -0.0); | 
|---|
|  | 256 | else if(infinity_b<0) | 
|---|
|  | 257 | RETURN(sign_a>0 ? k_PI : -k_PI); | 
|---|
|  | 258 | RETURN( atan2(a.toDouble(), b.toDouble()) ); | 
|---|
|  | 259 | } | 
|---|
|  | 260 |  | 
|---|
|  | 261 |  | 
|---|
|  | 262 | //Math.sinh(a) - returns trig. hyperbolic sine of given angle in radians | 
|---|
|  | 263 | static void scMathSinh(const CFunctionsScopePtr &c, void *userdata) { | 
|---|
|  | 264 | PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); | 
|---|
|  | 265 | RETURN_ZERO_IS_ZERO(a); | 
|---|
|  | 266 | if(abs(a)>1) RETURNconst(NaN); | 
|---|
|  | 267 | RETURN( sinh(a.toDouble()) ); | 
|---|
|  | 268 | } | 
|---|
|  | 269 |  | 
|---|
|  | 270 | //Math.asinh(a) - returns trig. hyperbolic arcsine of given angle in radians | 
|---|
|  | 271 | static void scMathASinh(const CFunctionsScopePtr &c, void *userdata) { | 
|---|
|  | 272 | PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); | 
|---|
|  | 273 | RETURN_INFINITY_IS_INFINITY(a); | 
|---|
|  | 274 | RETURN_ZERO_IS_ZERO(a); | 
|---|
|  | 275 | RETURN( asinh(a.toDouble()) ); | 
|---|
|  | 276 | } | 
|---|
|  | 277 |  | 
|---|
|  | 278 | //Math.cosh(a) - returns trig. hyperbolic cosine of given angle in radians | 
|---|
|  | 279 | static void scMathCosh(const CFunctionsScopePtr &c, void *userdata) { | 
|---|
|  | 280 | PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); | 
|---|
|  | 281 | if(a.isInfinity()) RETURNconst(InfinityPositive); | 
|---|
|  | 282 | RETURN( cosh(a.toDouble()) ); | 
|---|
|  | 283 | } | 
|---|
|  | 284 |  | 
|---|
|  | 285 | //Math.acosh(a) - returns trig. hyperbolic arccosine of given angle in radians | 
|---|
|  | 286 | static void scMathACosh(const CFunctionsScopePtr &c, void *userdata) { | 
|---|
|  | 287 | PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); | 
|---|
|  | 288 | RETURN_INFINITY_IS_INFINITY(a); | 
|---|
|  | 289 | if(abs(a)<1) RETURNconst(NaN); | 
|---|
|  | 290 | RETURN( acosh(a.toDouble()) ); | 
|---|
|  | 291 | } | 
|---|
|  | 292 |  | 
|---|
|  | 293 | //Math.tanh(a) - returns trig. hyperbolic tangent of given angle in radians | 
|---|
|  | 294 | static void scMathTanh(const CFunctionsScopePtr &c, void *userdata) { | 
|---|
|  | 295 | PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); | 
|---|
|  | 296 | RETURN_ZERO_IS_ZERO(a); | 
|---|
|  | 297 | if(a.isInfinity()) RETURN(a.sign()); | 
|---|
|  | 298 | RETURN( tanh(a.toDouble()) ); | 
|---|
|  | 299 | } | 
|---|
|  | 300 |  | 
|---|
|  | 301 | //Math.atanh(a) - returns trig. hyperbolic arctangent of given angle in radians | 
|---|
|  | 302 | static void scMathATanh(const CFunctionsScopePtr &c, void *userdata) { | 
|---|
|  | 303 | PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); | 
|---|
|  | 304 | RETURN_ZERO_IS_ZERO(a); | 
|---|
|  | 305 | CNumber abs_a = abs(a); | 
|---|
|  | 306 | if(abs_a > 1) RETURNconst(NaN); | 
|---|
|  | 307 | if(abs_a == 1) RETURNconst(Infinity(a.sign())); | 
|---|
|  | 308 | RETURN( atanh(a.toDouble()) ); | 
|---|
|  | 309 | } | 
|---|
|  | 310 |  | 
|---|
|  | 311 | //Math.log(a) - returns natural logaritm (base E) of given value | 
|---|
|  | 312 | static void scMathLog(const CFunctionsScopePtr &c, void *userdata) { | 
|---|
|  | 313 | PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); | 
|---|
|  | 314 | if(a.isZero()) RETURNconst(InfinityNegative); | 
|---|
|  | 315 | if(a.sign()<0) RETURNconst(NaN); | 
|---|
|  | 316 | if(a.isInfinity()) RETURNconst(InfinityPositive); | 
|---|
|  | 317 | RETURN( log( a.toDouble()) ); | 
|---|
|  | 318 | } | 
|---|
|  | 319 |  | 
|---|
|  | 320 | //Math.log10(a) - returns logaritm(base 10) of given value | 
|---|
|  | 321 | static void scMathLog10(const CFunctionsScopePtr &c, void *userdata) { | 
|---|
|  | 322 | PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); | 
|---|
|  | 323 | if(a.isZero()) RETURNconst(InfinityNegative); | 
|---|
|  | 324 | if(a.sign()<0) RETURNconst(NaN); | 
|---|
|  | 325 | if(a.isInfinity()) RETURNconst(InfinityPositive); | 
|---|
|  | 326 | RETURN( log10( a.toDouble()) ); | 
|---|
|  | 327 | } | 
|---|
|  | 328 |  | 
|---|
|  | 329 | //Math.exp(a) - returns e raised to the power of a given number | 
|---|
|  | 330 | static void scMathExp(const CFunctionsScopePtr &c, void *userdata) { | 
|---|
|  | 331 | PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); | 
|---|
|  | 332 | if(a.isZero()) RETURN(1); | 
|---|
|  | 333 | int a_i = a.isInfinity(); | 
|---|
|  | 334 | if(a_i>0) RETURNconst(InfinityPositive); | 
|---|
|  | 335 | else if(a_i<0) RETURN(0); | 
|---|
|  | 336 | RETURN( exp(a.toDouble()) ); | 
|---|
|  | 337 | } | 
|---|
|  | 338 |  | 
|---|
|  | 339 | //Math.pow(a,b) - returns the result of a number raised to a power (a)^(b) | 
|---|
|  | 340 | static void scMathPow(const CFunctionsScopePtr &c, void *userdata) { | 
|---|
|  | 341 | PARAMETER_TO_NUMBER(a,"a"); | 
|---|
|  | 342 | PARAMETER_TO_NUMBER(b,"b"); RETURN_NAN_IS_NAN(b); | 
|---|
|  | 343 | if(b.isZero()) RETURN(1); | 
|---|
|  | 344 | RETURN_NAN_IS_NAN(a); | 
|---|
|  | 345 | if(b==1) RETURN(a); | 
|---|
|  | 346 |  | 
|---|
|  | 347 | int sign; | 
|---|
|  | 348 | CNumber a_abs = abs(a); | 
|---|
|  | 349 | if((sign = b.isInfinity())) { | 
|---|
|  | 350 | if( a_abs==1 ) RETURNconst(NaN); | 
|---|
|  | 351 | else if( (a_abs>1) ^ (sign<0) ) RETURN(b); else RETURN(0); | 
|---|
|  | 352 | } else if((sign = a.isInfinity())) { | 
|---|
|  | 353 | if(sign>0) { | 
|---|
|  | 354 | if(b.sign()>0) RETURN(a); else RETURN(0); | 
|---|
|  | 355 | } else { | 
|---|
|  | 356 | bool b_is_odd_int = ((b+1)/2).isInteger(); | 
|---|
|  | 357 | if(b.sign()>0) RETURNconst(b_is_odd_int?InfinityNegative:InfinityPositive); | 
|---|
|  | 358 | else RETURN(b_is_odd_int?CNumber(NegativeZero):CNumber(0)); | 
|---|
|  | 359 | } | 
|---|
|  | 360 | } else if(a.isZero()) { | 
|---|
|  | 361 | if(a.isNegativeZero()) { | 
|---|
|  | 362 | bool b_is_odd_int = ((b+1)/2).isInteger(); | 
|---|
|  | 363 | if(b.sign()>0) RETURN(b_is_odd_int?CNumber(NegativeZero):CNumber(0)); | 
|---|
|  | 364 | else RETURNconst(b_is_odd_int?InfinityNegative:InfinityPositive); | 
|---|
|  | 365 | } else | 
|---|
|  | 366 | if(b.sign()>0) RETURN(a); else RETURNconst(InfinityPositive); | 
|---|
|  | 367 | } | 
|---|
|  | 368 | if(a.sign()<0 && !b.isInteger()) RETURNconst(NaN); | 
|---|
|  | 369 |  | 
|---|
|  | 370 | RETURN( pow(a.toDouble(), b.toDouble()) ); | 
|---|
|  | 371 | } | 
|---|
|  | 372 |  | 
|---|
|  | 373 | //Math.sqr(a) - returns square of given value | 
|---|
|  | 374 | static void scMathSqr(const CFunctionsScopePtr &c, void *userdata) { | 
|---|
|  | 375 | PARAMETER_TO_NUMBER(a,"a"); | 
|---|
|  | 376 | RETURN( a*a ); | 
|---|
|  | 377 | } | 
|---|
|  | 378 |  | 
|---|
|  | 379 | //Math.sqrt(a) - returns square root of given value | 
|---|
|  | 380 | static void scMathSqrt(const CFunctionsScopePtr &c, void *userdata) { | 
|---|
|  | 381 | PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); | 
|---|
|  | 382 | RETURN_ZERO_IS_ZERO(a); | 
|---|
|  | 383 | if(a.sign()<0) RETURNconst(NaN); | 
|---|
|  | 384 | RETURN_INFINITY_IS_INFINITY(a); | 
|---|
|  | 385 | RETURN( sqrt(a.toDouble()) ); | 
|---|
|  | 386 | } | 
|---|
|  | 387 |  | 
|---|
|  | 388 | // ----------------------------------------------- Register Functions | 
|---|
|  | 389 | void registerMathFunctions(CTinyJS *tinyJS) {} | 
|---|
|  | 390 | extern "C" void _registerMathFunctions(CTinyJS *tinyJS) { | 
|---|
|  | 391 |  | 
|---|
|  | 392 | CScriptVarPtr Math = tinyJS->getRoot()->addChild("Math", tinyJS->newScriptVar(Object), SCRIPTVARLINK_CONSTANT); | 
|---|
|  | 393 |  | 
|---|
|  | 394 | // --- Math and Trigonometry functions --- | 
|---|
|  | 395 | tinyJS->addNative("function Math.abs(a)", scMathAbs, 0, SCRIPTVARLINK_BUILDINDEFAULT); | 
|---|
|  | 396 | tinyJS->addNative("function Math.round(a)", scMathRound, 0, SCRIPTVARLINK_BUILDINDEFAULT); | 
|---|
|  | 397 | tinyJS->addNative("function Math.ceil(a)", scMathCeil, 0, SCRIPTVARLINK_BUILDINDEFAULT); | 
|---|
|  | 398 | tinyJS->addNative("function Math.floor(a)", scMathFloor, 0, SCRIPTVARLINK_BUILDINDEFAULT); | 
|---|
|  | 399 | tinyJS->addNative("function Math.min()", scMathMin, 0, SCRIPTVARLINK_BUILDINDEFAULT); | 
|---|
|  | 400 | tinyJS->addNative("function Math.max()", scMathMax, 0, SCRIPTVARLINK_BUILDINDEFAULT); | 
|---|
|  | 401 | tinyJS->addNative("function Math.range(x,a,b)", scMathRange, 0, SCRIPTVARLINK_BUILDINDEFAULT); | 
|---|
|  | 402 | tinyJS->addNative("function Math.sign(a)", scMathSign, 0, SCRIPTVARLINK_BUILDINDEFAULT); | 
|---|
|  | 403 | tinyJS->addNative("function Math.random(a)", scMathRandom, 0, SCRIPTVARLINK_BUILDINDEFAULT); | 
|---|
|  | 404 |  | 
|---|
|  | 405 |  | 
|---|
|  | 406 | // atan2, ceil, floor, random, round, | 
|---|
|  | 407 |  | 
|---|
|  | 408 | Math->addChild("LN2", tinyJS->newScriptVar(k_LN2), SCRIPTVARLINK_READONLY); | 
|---|
|  | 409 | Math->addChild("LN10", tinyJS->newScriptVar(k_LN10), SCRIPTVARLINK_READONLY); | 
|---|
|  | 410 | Math->addChild("LOG2E", tinyJS->newScriptVar(k_LOG2E), SCRIPTVARLINK_READONLY); | 
|---|
|  | 411 | Math->addChild("LOG10E", tinyJS->newScriptVar(k_LOG10E), SCRIPTVARLINK_READONLY); | 
|---|
|  | 412 | Math->addChild("SQRT1_2", tinyJS->newScriptVar(k_SQRT1_2), SCRIPTVARLINK_READONLY); | 
|---|
|  | 413 | Math->addChild("SQRT2", tinyJS->newScriptVar(k_SQRT2), SCRIPTVARLINK_READONLY); | 
|---|
|  | 414 | Math->addChild("PI", tinyJS->newScriptVar(k_PI), SCRIPTVARLINK_READONLY); | 
|---|
|  | 415 | //    tinyJS->addNative("function Math.PI()", scMathPI, 0); | 
|---|
|  | 416 | tinyJS->addNative("function Math.toDegrees(a)", scMathToDegrees, 0, SCRIPTVARLINK_BUILDINDEFAULT); | 
|---|
|  | 417 | tinyJS->addNative("function Math.toRadians(a)", scMathToRadians, 0, SCRIPTVARLINK_BUILDINDEFAULT); | 
|---|
|  | 418 | tinyJS->addNative("function Math.sin(a)", scMathSin, 0, SCRIPTVARLINK_BUILDINDEFAULT); | 
|---|
|  | 419 | tinyJS->addNative("function Math.asin(a)", scMathASin, 0, SCRIPTVARLINK_BUILDINDEFAULT); | 
|---|
|  | 420 | tinyJS->addNative("function Math.cos(a)", scMathCos, 0, SCRIPTVARLINK_BUILDINDEFAULT); | 
|---|
|  | 421 | tinyJS->addNative("function Math.acos(a)", scMathACos, 0, SCRIPTVARLINK_BUILDINDEFAULT); | 
|---|
|  | 422 | tinyJS->addNative("function Math.tan(a)", scMathTan, 0, SCRIPTVARLINK_BUILDINDEFAULT); | 
|---|
|  | 423 | tinyJS->addNative("function Math.atan(a)", scMathATan, 0, SCRIPTVARLINK_BUILDINDEFAULT); | 
|---|
|  | 424 | tinyJS->addNative("function Math.atan2(a,b)", scMathATan2, 0, SCRIPTVARLINK_BUILDINDEFAULT); | 
|---|
|  | 425 | tinyJS->addNative("function Math.sinh(a)", scMathSinh, 0, SCRIPTVARLINK_BUILDINDEFAULT); | 
|---|
|  | 426 | tinyJS->addNative("function Math.asinh(a)", scMathASinh, 0, SCRIPTVARLINK_BUILDINDEFAULT); | 
|---|
|  | 427 | tinyJS->addNative("function Math.cosh(a)", scMathCosh, 0, SCRIPTVARLINK_BUILDINDEFAULT); | 
|---|
|  | 428 | tinyJS->addNative("function Math.acosh(a)", scMathACosh, 0, SCRIPTVARLINK_BUILDINDEFAULT); | 
|---|
|  | 429 | tinyJS->addNative("function Math.tanh(a)", scMathTanh, 0, SCRIPTVARLINK_BUILDINDEFAULT); | 
|---|
|  | 430 | tinyJS->addNative("function Math.atanh(a)", scMathATanh, 0, SCRIPTVARLINK_BUILDINDEFAULT); | 
|---|
|  | 431 |  | 
|---|
|  | 432 | Math->addChild("E", tinyJS->newScriptVar(k_E), SCRIPTVARLINK_READONLY); | 
|---|
|  | 433 | tinyJS->addNative("function Math.log(a)", scMathLog, 0, SCRIPTVARLINK_BUILDINDEFAULT); | 
|---|
|  | 434 | tinyJS->addNative("function Math.log10(a)", scMathLog10, 0, SCRIPTVARLINK_BUILDINDEFAULT); | 
|---|
|  | 435 | tinyJS->addNative("function Math.exp(a)", scMathExp, 0, SCRIPTVARLINK_BUILDINDEFAULT); | 
|---|
|  | 436 | tinyJS->addNative("function Math.pow(a,b)", scMathPow, 0, SCRIPTVARLINK_BUILDINDEFAULT); | 
|---|
|  | 437 |  | 
|---|
|  | 438 | tinyJS->addNative("function Math.sqr(a)", scMathSqr, 0, SCRIPTVARLINK_BUILDINDEFAULT); | 
|---|
|  | 439 | tinyJS->addNative("function Math.sqrt(a)", scMathSqrt, 0, SCRIPTVARLINK_BUILDINDEFAULT); | 
|---|
|  | 440 |  | 
|---|
|  | 441 | } | 
|---|