diff --git a/src/core/org/luaj/lib/MathLib.java b/src/core/org/luaj/lib/MathLib.java
index 173811c7..a029ee3a 100644
--- a/src/core/org/luaj/lib/MathLib.java
+++ b/src/core/org/luaj/lib/MathLib.java
@@ -88,37 +88,64 @@ public class MathLib extends LFunction {
vm.pushlvalue( value );
}
+ private static void setResult( LuaState vm, double d ) {
+ vm.resettop();
+ vm.pushlvalue( LDouble.valueOf(d) );
+ }
+
+ private static void setResult( LuaState vm, int i ) {
+ vm.resettop();
+ vm.pushlvalue( LInteger.valueOf(i) );
+ }
+
public boolean luaStackCall( LuaState vm ) {
+ double x;
switch ( id ) {
case INSTALL:
install( vm._G );
break;
case ABS:
- setResult( vm, abs( vm.topointer( 2 ) ) );
+ setResult( vm, Math.abs ( vm.checkdouble(2) ) );
break;
case COS:
- setResult( vm, new LDouble( Math.cos ( vm.tonumber(2) ) ) );
+ setResult( vm, Math.cos ( vm.checkdouble(2) ) );
break;
- case MAX:
- setResult( vm, max( vm.topointer(2), vm.topointer(3) ) );
+ case MAX: {
+ int n = vm.gettop();
+ x = vm.checkdouble(2);
+ for ( int i=3; i<=n; i++ )
+ x = Math.max(x, vm.checkdouble(i));
+ setResult( vm, x );
break;
- case MIN:
- setResult( vm, min( vm.topointer(2), vm.topointer(3) ) );
+ }
+ case MIN: {
+ int n = vm.gettop();
+ x = vm.checkdouble(2);
+ for ( int i=3; i<=n; i++ )
+ x = Math.min(x, vm.checkdouble(i));
+ setResult(vm,x);
break;
- case MODF:
- modf( vm );
+ }
+ case MODF: {
+ double v = vm.checkdouble(2);
+ double intPart = ( v > 0 ) ? Math.floor( v ) : Math.ceil( v );
+ double fracPart = v - intPart;
+ vm.resettop();
+ vm.pushnumber( intPart );
+ vm.pushnumber( fracPart );
break;
+ }
case SIN:
- setResult( vm, new LDouble( Math.sin( vm.tonumber(2) ) ) );
+ setResult( vm, Math.sin( vm.checkdouble(2) ) );
break;
case SQRT:
- setResult( vm, new LDouble( Math.sqrt( vm.tonumber(2) ) ) );
+ setResult( vm, Math.sqrt( vm.checkdouble(2) ) );
break;
case CEIL:
- setResult( vm, LInteger.valueOf( (int) Math.ceil( vm.tonumber(2) ) ) );
+ setResult( vm, (int) Math.ceil( vm.checkdouble(2) ) );
break;
case FLOOR:
- setResult( vm, LInteger.valueOf( (int) Math.floor( vm.tonumber(2) ) ) );
+ setResult( vm, (int) Math.floor( vm.checkdouble(2) ) );
break;
case RANDOM: {
if ( random == null )
@@ -129,14 +156,16 @@ public class MathLib extends LFunction {
vm.pushnumber(random.nextDouble());
break;
case 2: {
- int m = vm.tointeger(2);
+ int m = vm.checkint(2);
+ vm.argcheck(1<=m, 1, "interval is empty");
vm.resettop();
vm.pushinteger(1+random.nextInt(m));
break;
}
default: {
- int m = vm.tointeger(2);
- int n = vm.tointeger(3);
+ int m = vm.checkint(2);
+ int n = vm.checkint(3);
+ vm.argcheck(m<=n, 2, "interval is empty");
vm.resettop();
vm.pushinteger(m+random.nextInt(n+1-m));
break;
@@ -145,7 +174,7 @@ public class MathLib extends LFunction {
break;
}
case RANDOMSEED:
- random = new Random( vm.tointeger(2) );
+ random = new Random( vm.checkint(2) );
vm.resettop();
break;
default:
@@ -153,27 +182,5 @@ public class MathLib extends LFunction {
}
return false;
}
- private LValue abs( final LValue v ) {
- LValue nv = v.luaUnaryMinus();
- return max( v, nv );
- }
-
- private LValue max( LValue lhs, LValue rhs ) {
- return rhs.luaBinCmpUnknown( Lua.OP_LT, lhs ) ? rhs: lhs;
- }
-
- private LValue min( LValue lhs, LValue rhs ) {
- return rhs.luaBinCmpUnknown( Lua.OP_LT, lhs ) ? lhs: rhs;
- }
-
- private void modf( LuaState vm ) {
- LValue arg = vm.topointer(2);
- double v = arg.toJavaDouble();
- double intPart = ( v > 0 ) ? Math.floor( v ) : Math.ceil( v );
- double fracPart = v - intPart;
- vm.resettop();
- vm.pushnumber( intPart );
- vm.pushnumber( fracPart );
- }
}
diff --git a/src/core/org/luaj/vm/LuaState.java b/src/core/org/luaj/vm/LuaState.java
index 2f4eaa10..02023e6b 100644
--- a/src/core/org/luaj/vm/LuaState.java
+++ b/src/core/org/luaj/vm/LuaState.java
@@ -2617,23 +2617,30 @@ public class LuaState extends Lua {
/**
* Report an error with an argument.
*
- * @param narg
- * Stack index of the bad argument
- * @param extramsg
- * String to include in error message
+ * @param narg Stack index of the bad argument
+ * @param extramsg String to include in error message
*/
public void argerror(int narg, String extramsg) {
- // TODO: port ldebug.c and provide mode useful error messages.
error("bad argument #" + (narg - 1) + " (" + extramsg + ")");
}
- /**
+ /**
+ * Conditionally report an error with an argument.
+ *
+ * @param cond boolean condition that generates an error when false
+ * @param narg Stack index of the bad argument
+ * @param extramsg String to include in error message
+ */
+ public void argcheck(boolean cond, int narg, String extramsg) {
+ if ( ! cond )
+ argerror(narg,extramsg);
+ }
+
+ /**
* Report a type error.
*
- * @param narg
- * Stack index of the bad argument
- * @param typename
- * Name of the type that was expected
+ * @param narg Stack index of the bad argument
+ * @param typename Name of the type that was expected, such as "string"
*/
public void typerror(int narg, String typename) {
argerror(narg, typename + " expected, got " + typename(narg));
@@ -2642,11 +2649,8 @@ public class LuaState extends Lua {
/**
* Report a type error.
*
- * @param narg
- * Stack index of the bad argument
- * @param typenum
- * Constant value specifying the type of argument that was
- * expected (i.e. LUA_TSTRING).
+ * @param narg Stack index of the bad argument
+ * @param typenum Constant value specifying the type of argument that was expected (i.e. LUA_TSTRING).
*/
public void typerror(int narg, int typenum) {
typerror(narg, TYPE_NAMES[typenum]);
@@ -2712,7 +2716,18 @@ public class LuaState extends Lua {
public long checklong(int narg) {
return checknumber(narg).toJavaLong();
}
-
+
+ /**
+ * Checks whether the function argument narg is a number and
+ * returns this number cast to a double.
+ * @param narg the argument number
+ * @throws LuaErrorException if the value cannot be converted to a double
+ * @return long value if the argument is a number or can be converted to double
+ */
+ public double checkdouble(int narg) {
+ return checknumber(narg).toJavaDouble();
+ }
+
/**
* Checks whether the function argument narg is a number and
* returns this number.