Refactor math library
This commit is contained in:
@@ -27,6 +27,9 @@ import org.luaj.vm2.LuaDouble;
|
|||||||
import org.luaj.vm2.LuaTable;
|
import org.luaj.vm2.LuaTable;
|
||||||
import org.luaj.vm2.LuaValue;
|
import org.luaj.vm2.LuaValue;
|
||||||
import org.luaj.vm2.Varargs;
|
import org.luaj.vm2.Varargs;
|
||||||
|
import org.luaj.vm2.lib.jme.JmePlatform;
|
||||||
|
import org.luaj.vm2.lib.jse.JseMathLib;
|
||||||
|
import org.luaj.vm2.lib.jse.JsePlatform;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subclass of {@link LibFunction} which implements the lua standard {@code math}
|
* Subclass of {@link LibFunction} which implements the lua standard {@code math}
|
||||||
@@ -77,75 +80,161 @@ public class MathLib extends OneArgFunction {
|
|||||||
|
|
||||||
public static MathLib MATHLIB = null;
|
public static MathLib MATHLIB = null;
|
||||||
|
|
||||||
private Random random;
|
|
||||||
|
|
||||||
public MathLib() {
|
public MathLib() {
|
||||||
MATHLIB = this;
|
MATHLIB = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LuaValue call(LuaValue env) {
|
public LuaValue call(LuaValue env) {
|
||||||
LuaTable t = new LuaTable(0,30);
|
LuaTable math = new LuaTable(0,30);
|
||||||
t.set( "pi", Math.PI );
|
math.set("abs", new abs());
|
||||||
t.set( "huge", LuaDouble.POSINF );
|
math.set("ceil", new ceil());
|
||||||
bind( t, MathLib1.class, new String[] {
|
math.set("cos", new cos());
|
||||||
"abs", "ceil", "cos", "deg",
|
math.set("deg", new deg());
|
||||||
"exp", "floor", "rad", "sin",
|
math.set("exp", new exp(this));
|
||||||
"sqrt", "tan" } );
|
math.set("floor", new floor());
|
||||||
bind( t, MathLib2.class, new String[] {
|
math.set("fmod", new fmod());
|
||||||
"fmod", "ldexp", "pow", } );
|
math.set("frexp", new frexp());
|
||||||
bind( t, MathLibV.class, new String[] {
|
math.set("huge", LuaDouble.POSINF );
|
||||||
"frexp", "max", "min", "modf",
|
math.set("ldexp", new ldexp());
|
||||||
"randomseed", "random", } );
|
math.set("max", new max());
|
||||||
((MathLibV) t.get("randomseed")).mathlib = this;
|
math.set("min", new min());
|
||||||
((MathLibV) t.get("random" )).mathlib = this;
|
math.set("modf", new modf());
|
||||||
env.set("math", t);
|
math.set("pi", Math.PI );
|
||||||
PackageLib.instance.LOADED.set("math", t);
|
math.set("pow", new pow());
|
||||||
return t;
|
random r;
|
||||||
|
math.set("random", r = new random());
|
||||||
|
math.set("randomseed", new randomseed(r));
|
||||||
|
math.set("rad", new rad());
|
||||||
|
math.set("sin", new sin());
|
||||||
|
math.set("sqrt", new sqrt());
|
||||||
|
math.set("tan", new tan());
|
||||||
|
env.set("math", math);
|
||||||
|
PackageLib.instance.LOADED.set("math", math);
|
||||||
|
return math;
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract protected static class UnaryOp extends OneArgFunction {
|
||||||
|
public LuaValue call(LuaValue arg) {
|
||||||
|
return valueOf(call(arg.checkdouble()));
|
||||||
|
}
|
||||||
|
abstract protected double call(double d);
|
||||||
}
|
}
|
||||||
|
|
||||||
static final class MathLib1 extends OneArgFunction {
|
abstract protected static class BinaryOp extends TwoArgFunction {
|
||||||
public LuaValue call(LuaValue arg) {
|
public LuaValue call(LuaValue x, LuaValue y) {
|
||||||
switch ( opcode ) {
|
return valueOf(call(x.checkdouble(), y.checkdouble()));
|
||||||
case 0: return valueOf(Math.abs(arg.checkdouble()));
|
}
|
||||||
case 1: return valueOf(Math.ceil(arg.checkdouble()));
|
abstract protected double call(double x, double y);
|
||||||
case 2: return valueOf(Math.cos(arg.checkdouble()));
|
}
|
||||||
case 3: return valueOf(Math.toDegrees(arg.checkdouble()));
|
|
||||||
case 4: return dpow(Math.E,arg.checkdouble());
|
static final class abs extends UnaryOp { protected double call(double d) { return Math.abs(d); } }
|
||||||
case 5: return valueOf(Math.floor(arg.checkdouble()));
|
static final class ceil extends UnaryOp { protected double call(double d) { return Math.ceil(d); } }
|
||||||
case 6: return valueOf(Math.toRadians(arg.checkdouble()));
|
static final class cos extends UnaryOp { protected double call(double d) { return Math.cos(d); } }
|
||||||
case 7: return valueOf(Math.sin(arg.checkdouble()));
|
static final class deg extends UnaryOp { protected double call(double d) { return Math.toDegrees(d); } }
|
||||||
case 8: return valueOf(Math.sqrt(arg.checkdouble()));
|
static final class floor extends UnaryOp { protected double call(double d) { return Math.floor(d); } }
|
||||||
case 9: return valueOf(Math.tan(arg.checkdouble()));
|
static final class rad extends UnaryOp { protected double call(double d) { return Math.toRadians(d); } }
|
||||||
}
|
static final class sin extends UnaryOp { protected double call(double d) { return Math.sin(d); } }
|
||||||
return NIL;
|
static final class sqrt extends UnaryOp { protected double call(double d) { return Math.sqrt(d); } }
|
||||||
|
static final class tan extends UnaryOp { protected double call(double d) { return Math.tan(d); } }
|
||||||
|
|
||||||
|
static final class exp extends UnaryOp {
|
||||||
|
final MathLib mathlib;
|
||||||
|
exp(MathLib mathlib) {
|
||||||
|
this.mathlib = mathlib;
|
||||||
|
}
|
||||||
|
protected double call(double d) {
|
||||||
|
return mathlib.dpow_lib(Math.E,d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static final class fmod extends BinaryOp {
|
||||||
|
protected double call(double x, double y) {
|
||||||
|
double q = x/y;
|
||||||
|
return x - y * (q>=0? Math.floor(q): Math.ceil(q));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static final class ldexp extends BinaryOp {
|
||||||
|
protected double call(double x, double y) {
|
||||||
|
y += 1023.5;
|
||||||
|
long e = (long) ((0!=(1&((int)y)))? Math.floor(y): Math.ceil(y-1));
|
||||||
|
return x * Double.longBitsToDouble(e << 52);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static final class pow extends BinaryOp {
|
||||||
|
protected double call(double x, double y) {
|
||||||
|
return MathLib.dpow_default(x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class frexp extends VarArgFunction {
|
||||||
|
public Varargs invoke(Varargs args) {
|
||||||
|
double x = args.checkdouble(1);
|
||||||
|
if ( x == 0 ) return varargsOf(ZERO,ZERO);
|
||||||
|
long bits = Double.doubleToLongBits( x );
|
||||||
|
double m = ((bits & (~(-1L<<52))) + (1L<<52)) * ((bits >= 0)? (.5 / (1L<<52)): (-.5 / (1L<<52)));
|
||||||
|
double e = (((int) (bits >> 52)) & 0x7ff) - 1022;
|
||||||
|
return varargsOf( valueOf(m), valueOf(e) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class max extends VarArgFunction {
|
||||||
|
public Varargs invoke(Varargs args) {
|
||||||
|
double m = args.checkdouble(1);
|
||||||
|
for ( int i=2,n=args.narg(); i<=n; ++i )
|
||||||
|
m = Math.max(m,args.checkdouble(i));
|
||||||
|
return valueOf(m);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static final class MathLib2 extends TwoArgFunction {
|
static class min extends VarArgFunction {
|
||||||
protected MathLib mathlib;
|
public Varargs invoke(Varargs args) {
|
||||||
public LuaValue call(LuaValue arg1, LuaValue arg2) {
|
double m = args.checkdouble(1);
|
||||||
switch ( opcode ) {
|
for ( int i=2,n=args.narg(); i<=n; ++i )
|
||||||
case 0: { // fmod
|
m = Math.min(m,args.checkdouble(i));
|
||||||
double x = arg1.checkdouble();
|
return valueOf(m);
|
||||||
double y = arg2.checkdouble();
|
|
||||||
double q = x/y;
|
|
||||||
double f = x - y * (q>=0? Math.floor(q): Math.ceil(q));
|
|
||||||
return valueOf( f );
|
|
||||||
}
|
|
||||||
case 1: { // ldexp
|
|
||||||
double x = arg1.checkdouble();
|
|
||||||
double y = arg2.checkdouble()+1023.5;
|
|
||||||
long e = (long) ((0!=(1&((int)y)))? Math.floor(y): Math.ceil(y-1));
|
|
||||||
return valueOf(x * Double.longBitsToDouble(e << 52));
|
|
||||||
}
|
|
||||||
case 2: { // pow
|
|
||||||
return dpow(arg1.checkdouble(), arg2.checkdouble());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NIL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static class modf extends VarArgFunction {
|
||||||
|
public Varargs invoke(Varargs args) {
|
||||||
|
double x = args.checkdouble(1);
|
||||||
|
double intPart = ( x > 0 ) ? Math.floor( x ) : Math.ceil( x );
|
||||||
|
double fracPart = x - intPart;
|
||||||
|
return varargsOf( valueOf(intPart), valueOf(fracPart) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class random extends LibFunction {
|
||||||
|
Random random = new Random();
|
||||||
|
public LuaValue call() {
|
||||||
|
return valueOf( random.nextDouble() );
|
||||||
|
}
|
||||||
|
public LuaValue call(LuaValue a) {
|
||||||
|
int m = a.checkint();
|
||||||
|
if (m<1) argerror(1, "interval is empty");
|
||||||
|
return valueOf( 1 + random.nextInt(m) );
|
||||||
|
}
|
||||||
|
public LuaValue call(LuaValue a, LuaValue b) {
|
||||||
|
int m = a.checkint();
|
||||||
|
int n = b.checkint();
|
||||||
|
if (n<m) argerror(2, "interval is empty");
|
||||||
|
return valueOf( m + random.nextInt(n+1-m) );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static class randomseed extends OneArgFunction {
|
||||||
|
final random random;
|
||||||
|
randomseed(random random) {
|
||||||
|
this.random = random;
|
||||||
|
}
|
||||||
|
public LuaValue call(LuaValue arg) {
|
||||||
|
long seed = arg.checklong();
|
||||||
|
random.random = new Random(seed);
|
||||||
|
return NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** compute power using installed math library, or default if there is no math library installed */
|
/** compute power using installed math library, or default if there is no math library installed */
|
||||||
public static LuaValue dpow(double a, double b) {
|
public static LuaValue dpow(double a, double b) {
|
||||||
return LuaDouble.valueOf(
|
return LuaDouble.valueOf(
|
||||||
@@ -188,63 +277,4 @@ public class MathLib extends OneArgFunction {
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
static final class MathLibV extends VarArgFunction {
|
|
||||||
protected MathLib mathlib;
|
|
||||||
public Varargs invoke(Varargs args) {
|
|
||||||
switch ( opcode ) {
|
|
||||||
case 0: { // frexp
|
|
||||||
double x = args.checkdouble(1);
|
|
||||||
if ( x == 0 ) return varargsOf(ZERO,ZERO);
|
|
||||||
long bits = Double.doubleToLongBits( x );
|
|
||||||
double m = ((bits & (~(-1L<<52))) + (1L<<52)) * ((bits >= 0)? (.5 / (1L<<52)): (-.5 / (1L<<52)));
|
|
||||||
double e = (((int) (bits >> 52)) & 0x7ff) - 1022;
|
|
||||||
return varargsOf( valueOf(m), valueOf(e) );
|
|
||||||
}
|
|
||||||
case 1: { // max
|
|
||||||
double m = args.checkdouble(1);
|
|
||||||
for ( int i=2,n=args.narg(); i<=n; ++i )
|
|
||||||
m = Math.max(m,args.checkdouble(i));
|
|
||||||
return valueOf(m);
|
|
||||||
}
|
|
||||||
case 2: { // min
|
|
||||||
double m = args.checkdouble(1);
|
|
||||||
for ( int i=2,n=args.narg(); i<=n; ++i )
|
|
||||||
m = Math.min(m,args.checkdouble(i));
|
|
||||||
return valueOf(m);
|
|
||||||
}
|
|
||||||
case 3: { // modf
|
|
||||||
double x = args.checkdouble(1);
|
|
||||||
double intPart = ( x > 0 ) ? Math.floor( x ) : Math.ceil( x );
|
|
||||||
double fracPart = x - intPart;
|
|
||||||
return varargsOf( valueOf(intPart), valueOf(fracPart) );
|
|
||||||
}
|
|
||||||
case 4: { // randomseed
|
|
||||||
long seed = args.checklong(1);
|
|
||||||
mathlib.random = new Random(seed);
|
|
||||||
return NONE;
|
|
||||||
}
|
|
||||||
case 5: { // random
|
|
||||||
if ( mathlib.random == null )
|
|
||||||
mathlib.random = new Random();
|
|
||||||
|
|
||||||
switch ( args.narg() ) {
|
|
||||||
case 0:
|
|
||||||
return valueOf( mathlib.random.nextDouble() );
|
|
||||||
case 1: {
|
|
||||||
int m = args.checkint(1);
|
|
||||||
if (m<1) argerror(1, "interval is empty");
|
|
||||||
return valueOf( 1 + mathlib.random.nextInt(m) );
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
int m = args.checkint(1);
|
|
||||||
int n = args.checkint(2);
|
|
||||||
if (n<m) argerror(2, "interval is empty");
|
|
||||||
return valueOf( m + mathlib.random.nextInt(n+1-m) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NONE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,8 +23,6 @@ package org.luaj.vm2.lib.jse;
|
|||||||
|
|
||||||
import org.luaj.vm2.LuaValue;
|
import org.luaj.vm2.LuaValue;
|
||||||
import org.luaj.vm2.lib.LibFunction;
|
import org.luaj.vm2.lib.LibFunction;
|
||||||
import org.luaj.vm2.lib.OneArgFunction;
|
|
||||||
import org.luaj.vm2.lib.TwoArgFunction;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subclass of {@link LibFunction} which implements the lua standard {@code math}
|
* Subclass of {@link LibFunction} which implements the lua standard {@code math}
|
||||||
@@ -60,42 +58,32 @@ public class JseMathLib extends org.luaj.vm2.lib.MathLib {
|
|||||||
|
|
||||||
public JseMathLib() {}
|
public JseMathLib() {}
|
||||||
|
|
||||||
public LuaValue call(LuaValue arg) {
|
public LuaValue call(LuaValue env) {
|
||||||
LuaValue t = super.call(arg);
|
super.call(env);
|
||||||
bind( t, JseMathLib1.class, new String[] {
|
LuaValue math = env.get("math");
|
||||||
"acos", "asin", "atan", "cosh",
|
math.set("acos", new acos());
|
||||||
"exp", "log", "sinh",
|
math.set("asin", new asin());
|
||||||
"tanh" } );
|
math.set("atan", new atan());
|
||||||
bind( t, JseMathLib2.class, new String[] {
|
math.set("atan2", new atan2());
|
||||||
"atan2", "pow", } );
|
math.set("cosh", new cosh());
|
||||||
return t;
|
math.set("exp", new exp());
|
||||||
|
math.set("log", new log());
|
||||||
|
math.set("pow", new pow());
|
||||||
|
math.set("sinh", new sinh());
|
||||||
|
math.set("tanh", new tanh());
|
||||||
|
return math;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class JseMathLib1 extends OneArgFunction {
|
static final class acos extends UnaryOp { protected double call(double d) { return Math.acos(d); } }
|
||||||
public LuaValue call(LuaValue arg) {
|
static final class asin extends UnaryOp { protected double call(double d) { return Math.asin(d); } }
|
||||||
switch ( opcode ) {
|
static final class atan extends UnaryOp { protected double call(double d) { return Math.atan(d); } }
|
||||||
case 0: return valueOf(Math.acos(arg.checkdouble()));
|
static final class atan2 extends BinaryOp { protected double call(double y, double x) { return Math.atan2(y, x); } }
|
||||||
case 1: return valueOf(Math.asin(arg.checkdouble()));
|
static final class cosh extends UnaryOp { protected double call(double d) { return Math.cosh(d); } }
|
||||||
case 2: return valueOf(Math.atan(arg.checkdouble()));
|
static final class exp extends UnaryOp { protected double call(double d) { return Math.exp(d); } }
|
||||||
case 3: return valueOf(Math.cosh(arg.checkdouble()));
|
static final class log extends UnaryOp { protected double call(double d) { return Math.log(d); } }
|
||||||
case 4: return valueOf(Math.exp(arg.checkdouble()));
|
static final class pow extends BinaryOp { protected double call(double x, double y) { return Math.pow(x, y); } }
|
||||||
case 5: return valueOf(Math.log(arg.checkdouble()));
|
static final class sinh extends UnaryOp { protected double call(double d) { return Math.sinh(d); } }
|
||||||
case 6: return valueOf(Math.sinh(arg.checkdouble()));
|
static final class tanh extends UnaryOp { protected double call(double d) { return Math.tanh(d); } }
|
||||||
case 7: return valueOf(Math.tanh(arg.checkdouble()));
|
|
||||||
}
|
|
||||||
return NIL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final class JseMathLib2 extends TwoArgFunction {
|
|
||||||
public LuaValue call(LuaValue arg1, LuaValue arg2) {
|
|
||||||
switch ( opcode ) {
|
|
||||||
case 0: return valueOf(Math.atan2(arg1.checkdouble(), arg2.checkdouble()));
|
|
||||||
case 1: return valueOf(Math.pow(arg1.checkdouble(), arg2.checkdouble()));
|
|
||||||
}
|
|
||||||
return NIL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Faster, better version of pow() used by arithmetic operator ^ */
|
/** Faster, better version of pow() used by arithmetic operator ^ */
|
||||||
public double dpow_lib(double a, double b) {
|
public double dpow_lib(double a, double b) {
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ local singleargfunctions = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
local singleargposdomain = {
|
local singleargposdomain = {
|
||||||
'log', 'log10', 'sqrt', 'ceil',
|
'log', 'sqrt', 'ceil',
|
||||||
}
|
}
|
||||||
|
|
||||||
local twoargfunctions = {
|
local twoargfunctions = {
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ local ONEARG_JME = {
|
|||||||
}
|
}
|
||||||
local ONEARG_JSE = {
|
local ONEARG_JSE = {
|
||||||
"acos", "asin", "atan", "cosh",
|
"acos", "asin", "atan", "cosh",
|
||||||
"log", "log10", "sinh", "tanh",
|
"log", "sinh", "tanh",
|
||||||
}
|
}
|
||||||
local TWOARGS_JME = {
|
local TWOARGS_JME = {
|
||||||
"fmod", "ldexp", "pow",
|
"fmod", "ldexp", "pow",
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ for DIR in "errors" "perf" "."; do
|
|||||||
FILES=`ls -1 *.lua | awk 'BEGIN { FS="." } ; { print $1 }'`
|
FILES=`ls -1 *.lua | awk 'BEGIN { FS="." } ; { print $1 }'`
|
||||||
for FILE in $FILES ; do
|
for FILE in $FILES ; do
|
||||||
echo 'executing' `pwd` $FILE
|
echo 'executing' `pwd` $FILE
|
||||||
lua ${FILE}.lua > ${FILE}.out
|
lua ${FILE}.lua JSE > ${FILE}.out
|
||||||
done
|
done
|
||||||
cd ..
|
cd ..
|
||||||
done
|
done
|
||||||
|
|||||||
Reference in New Issue
Block a user