Mercurial > projects > dmdscript-tango
diff dmdscript_tango/dmath.d @ 0:55c2951c07be
initial, files origin, premoved tree
author | saaadel |
---|---|
date | Sun, 24 Jan 2010 12:34:47 +0200 |
parents | |
children | 8363a4bf6a8f |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dmdscript_tango/dmath.d Sun Jan 24 12:34:47 2010 +0200 @@ -0,0 +1,348 @@ + +/* Digital Mars DMDScript source code. + * Copyright (c) 2000-2002 by Chromium Communications + * D version Copyright (c) 2004-2005 by Digital Mars + * All Rights Reserved + * written by Walter Bright + * www.digitalmars.com + * Use at your own risk. There is no warranty, express or implied. + * License for redistribution is by the GNU General Public License in gpl.txt. + * + * A binary, non-exclusive license for commercial use can be + * purchased from www.digitalmars.com/dscript/buy.html. + * + * DMDScript is implemented in the D Programming Language, + * www.digitalmars.com/d/ + * + * For a C++ implementation of DMDScript, including COM support, + * see www.digitalmars.com/dscript/cppscript.html. + */ + + +module dmdscript.dmath; + +import std.math; +import std.random; + +import dmdscript.script; +import dmdscript.value; +import dmdscript.dobject; +import dmdscript.dnative; +import dmdscript.threadcontext; +import dmdscript.text; +import dmdscript.property; + +d_number math_helper(Value[] arglist) +{ + Value *v; + + v = arglist.length ? &arglist[0] : &vundefined; + return v.toNumber(); +} + +void* Dmath_abs(Dobject pthis, CallContext *cc, Dobject othis, Value* ret, Value[] arglist) +{ + // ECMA 15.8.2.1 + d_number result; + + result = fabs(math_helper(arglist)); + ret.putVnumber(result); + return null; +} + +void* Dmath_acos(Dobject pthis, CallContext *cc, Dobject othis, Value* ret, Value[] arglist) +{ + // ECMA 15.8.2.2 + d_number result; + + result = acos(math_helper(arglist)); + ret.putVnumber(result); + return null; +} + +void* Dmath_asin(Dobject pthis, CallContext *cc, Dobject othis, Value* ret, Value[] arglist) +{ + // ECMA 15.8.2.3 + d_number result; + + result = asin(math_helper(arglist)); + ret.putVnumber(result); + return null; +} + +void* Dmath_atan(Dobject pthis, CallContext *cc, Dobject othis, Value* ret, Value[] arglist) +{ + // ECMA 15.8.2.4 + d_number result; + + result = atan(math_helper(arglist)); + ret.putVnumber(result); + return null; +} + +void* Dmath_atan2(Dobject pthis, CallContext *cc, Dobject othis, Value* ret, Value[] arglist) +{ + // ECMA 15.8.2.5 + d_number n1; + Value *v2; + d_number result; + + n1 = math_helper(arglist); + v2 = (arglist.length >= 2) ? &arglist[1] : &vundefined; + result = atan2(n1, v2.toNumber()); + ret.putVnumber(result); + return null; +} + +void* Dmath_ceil(Dobject pthis, CallContext *cc, Dobject othis, Value* ret, Value[] arglist) +{ + // ECMA 15.8.2.6 + d_number result; + + result = ceil(math_helper(arglist)); + ret.putVnumber(result); + return null; +} + +void* Dmath_cos(Dobject pthis, CallContext *cc, Dobject othis, Value* ret, Value[] arglist) +{ + // ECMA 15.8.2.7 + d_number result; + + result = cos(math_helper(arglist)); + ret.putVnumber(result); + return null; +} + +void* Dmath_exp(Dobject pthis, CallContext *cc, Dobject othis, Value* ret, Value[] arglist) +{ + // ECMA 15.8.2.8 + d_number result; + + result = std.math.exp(math_helper(arglist)); + ret.putVnumber(result); + return null; +} + +void* Dmath_floor(Dobject pthis, CallContext *cc, Dobject othis, Value* ret, Value[] arglist) +{ + // ECMA 15.8.2.9 + d_number result; + + result = std.math.floor(math_helper(arglist)); + ret.putVnumber(result); + return null; +} + +void* Dmath_log(Dobject pthis, CallContext *cc, Dobject othis, Value* ret, Value[] arglist) +{ + // ECMA 15.8.2.10 + d_number result; + + result = log(math_helper(arglist)); + ret.putVnumber(result); + return null; +} + +void* Dmath_max(Dobject pthis, CallContext *cc, Dobject othis, Value* ret, Value[] arglist) +{ + // ECMA v3 15.8.2.11 + d_number n; + d_number result; + uint a; + + result = -d_number.infinity; + foreach (Value v; arglist) + { + n = v.toNumber(); + if (isnan(n)) + { result = d_number.nan; + break; + } + if (result == n) + { + // if n is +0 and result is -0, pick n + if (n == 0 && !signbit(n)) + result = n; + } + else if (n > result) + result = n; + } + ret.putVnumber(result); + return null; +} + +void* Dmath_min(Dobject pthis, CallContext *cc, Dobject othis, Value* ret, Value[] arglist) +{ + // ECMA v3 15.8.2.12 + d_number n; + d_number result; + uint a; + + result = d_number.infinity; + foreach (Value v; arglist) + { + n = v.toNumber(); + if (isnan(n)) + { result = d_number.nan; + break; + } + if (result == n) + { + // if n is -0 and result is +0, pick n + if (n == 0 && signbit(n)) + result = n; + } + else if (n < result) + result = n; + } + ret.putVnumber(result); + return null; +} + +void* Dmath_pow(Dobject pthis, CallContext *cc, Dobject othis, Value* ret, Value[] arglist) +{ + // ECMA 15.8.2.13 + d_number n1; + Value *v2; + d_number result; + + n1 = math_helper(arglist); + v2 = (arglist.length >= 2) ? &arglist[1] : &vundefined; + result = pow(n1, v2.toNumber()); + ret.putVnumber(result); + return null; +} + +void* Dmath_random(Dobject pthis, CallContext *cc, Dobject othis, Value* ret, Value[] arglist) +{ + // ECMA 15.8.2.14 + // 0.0 <= result < 1.0 + d_number result; + + ulong x; + + // Only want 53 bits of precision + x = (cast(ulong)std.random.rand() << 32) + std.random.rand(); + //PRINTF("x = x%016llx\n",x); + x &= 0xFFFFFFFFFFFFF800L; + result = x * (1 / (0x100000000L * cast(double)0x100000000L)) + + (1 / (0x200000000L * cast(double)0x100000000L)); + + // Experiments on linux show that this will never be exactly + // 1.0, so is the assert() worth it? + assert(result >= 0 && result < 1.0); + ret.putVnumber(result); + return null; +} + +void* Dmath_round(Dobject pthis, CallContext *cc, Dobject othis, Value* ret, Value[] arglist) +{ + // ECMA 15.8.2.15 + d_number result; + + result = math_helper(arglist); + if (!isnan(result)) + result = copysign(std.math.floor(result + .5), result); + ret.putVnumber(result); + return null; +} + +void* Dmath_sin(Dobject pthis, CallContext *cc, Dobject othis, Value* ret, Value[] arglist) +{ + // ECMA 15.8.2.16 + d_number result; + + result = sin(math_helper(arglist)); + ret.putVnumber(result); + return null; +} + +void* Dmath_sqrt(Dobject pthis, CallContext *cc, Dobject othis, Value* ret, Value[] arglist) +{ + // ECMA 15.8.2.17 + d_number result; + + result = sqrt(math_helper(arglist)); + ret.putVnumber(result); + return null; +} + +void* Dmath_tan(Dobject pthis, CallContext *cc, Dobject othis, Value* ret, Value[] arglist) +{ + // ECMA 15.8.2.18 + d_number result; + + result = tan(math_helper(arglist)); + ret.putVnumber(result); + return null; +} + +/* ===================== Dmath ==================== */ + +class Dmath : Dobject +{ + this(ThreadContext *tc) + { + super(tc.Dobject_prototype); + + //writef("Dmath::Dmath(%x)\n", this); + uint attributes = DontEnum | DontDelete | ReadOnly; + + struct MathConst + { d_string *name; + d_number value; + } + + static MathConst table[] = + [ + { &TEXT_E, std.math.E }, + { &TEXT_LN10, std.math.LN10 }, + { &TEXT_LN2, std.math.LN2 }, + { &TEXT_LOG2E, std.math.LOG2E }, + { &TEXT_LOG10E, std.math.LOG10E }, + { &TEXT_PI, std.math.PI }, + { &TEXT_SQRT1_2, std.math.SQRT1_2 }, + { &TEXT_SQRT2, std.math.SQRT2 }, + ]; + + for (size_t u = 0; u < table.length; u++) + { Value *v; + + v = Put(*table[u].name, table[u].value, attributes); + //writef("Put(%s,%.5g) = %x\n", *table[u].name, table[u].value, v); + } + + classname = TEXT_Math; + + static NativeFunctionData nfd[] = + [ + { &TEXT_abs, &Dmath_abs, 1 }, + { &TEXT_acos, &Dmath_acos, 1 }, + { &TEXT_asin, &Dmath_asin, 1 }, + { &TEXT_atan, &Dmath_atan, 1 }, + { &TEXT_atan2, &Dmath_atan2, 2 }, + { &TEXT_ceil, &Dmath_ceil, 1 }, + { &TEXT_cos, &Dmath_cos, 1 }, + { &TEXT_exp, &Dmath_exp, 1 }, + { &TEXT_floor, &Dmath_floor, 1 }, + { &TEXT_log, &Dmath_log, 1 }, + { &TEXT_max, &Dmath_max, 2 }, + { &TEXT_min, &Dmath_min, 2 }, + { &TEXT_pow, &Dmath_pow, 2 }, + { &TEXT_random, &Dmath_random, 0 }, + { &TEXT_round, &Dmath_round, 1 }, + { &TEXT_sin, &Dmath_sin, 1 }, + { &TEXT_sqrt, &Dmath_sqrt, 1 }, + { &TEXT_tan, &Dmath_tan, 1 }, + ]; + + DnativeFunction.init(this, nfd, attributes); + } + + static void init(ThreadContext *tc) + { + tc.Dmath_object = new Dmath(tc); + } +} +