diff options
Diffstat (limited to 'tests/test_common/test_driver.cpp')
0 files changed, 0 insertions, 0 deletions
![]() |
index : avr/qmk/firmware | |
[no description] |
aboutsummaryrefslogtreecommitdiffstats |
--- a/src/Makefile
+++ b/src/Makefile
@@ -25,7 +25,7 @@ PLATS= aix ansi bsd freebsd generic linu
LUA_A= liblua.a
CORE_O= lapi.o lcode.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o \
lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o \
- lundump.o lvm.o lzio.o
+ lundump.o lvm.o lzio.o lnum.o
LIB_O= lauxlib.o lbaselib.o ldblib.o liolib.o lmathlib.o loslib.o ltablib.o \
lstrlib.o loadlib.o linit.o
@@ -148,6 +148,7 @@ llex.o: llex.c lua.h luaconf.h ldo.h lob
lmathlib.o: lmathlib.c lua.h luaconf.h lauxlib.h lualib.h
lmem.o: lmem.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \
ltm.h lzio.h lmem.h ldo.h
+lnum.o: lnum.c lua.h llex.h lnum.h
loadlib.o: loadlib.c lua.h luaconf.h lauxlib.h lualib.h
lobject.o: lobject.c lua.h luaconf.h ldo.h lobject.h llimits.h lstate.h \
ltm.h lzio.h lmem.h lstring.h lgc.h lvm.h
@@ -179,4 +180,18 @@ lzio.o: lzio.c lua.h luaconf.h llimits.h
print.o: print.c ldebug.h lstate.h lua.h luaconf.h lobject.h llimits.h \
ltm.h lzio.h lmem.h lopcodes.h lundump.h
+luaconf.h: lnum_config.h
+lapi.c: lnum.h
+lauxlib.c: llimits.h
+lbaselib.c: llimits.h lobject.h lapi.h
+lcode.c: lnum.h
+liolib.c: lnum.h llex.h
+llex.c: lnum.h
+lnum.h: lobject.h
+lobject.c: llex.h lnum.h
+ltable.c: lnum.h
+lua.c: llimits.h
+lvm.c: llex.h lnum.h
+print.c: lnum.h
+
# (end of Makefile)
--- a/src/lapi.c
+++ b/src/lapi.c
@@ -28,7 +28,7 @@
#include "ltm.h"
#include "lundump.h"
#include "lvm.h"
-
+#include "lnum.h"
const char lua_ident[] =
@@ -241,12 +241,13 @@ LUA_API void lua_pushvalue (lua_State *L
LUA_API int lua_type (lua_State *L, int idx) {
StkId o = index2adr(L, idx);
- return (o == luaO_nilobject) ? LUA_TNONE : ttype(o);
+ return (o == luaO_nilobject) ? LUA_TNONE : ttype_ext(o);
}
LUA_API const char *lua_typename (lua_State *L, int t) {
UNUSED(L);
+ lua_assert( t!= LUA_TINT );
return (t == LUA_TNONE) ? "no value" : luaT_typenames[t];
}
@@ -264,6 +265,14 @@ LUA_API int lua_isnumber (lua_State *L,
}
+LUA_API int lua_isinteger (lua_State *L, int idx) {
+ TValue tmp;
+ lua_Integer dum;
+ const TValue *o = index2adr(L, idx);
+ return tonumber(o,&tmp) && (ttisint(o) || tt_integer_valued(o,&dum));
+}
+
+
LUA_API int lua_isstring (lua_State *L, int idx) {
int t = lua_type(L, idx);
return (t == LUA_TSTRING || t == LUA_TNUMBER);
@@ -309,31 +318,66 @@ LUA_API int lua_lessthan (lua_State *L,
}
-
LUA_API lua_Number lua_tonumber (lua_State *L, int idx) {
TValue n;
const TValue *o = index2adr(L, idx);
- if (tonumber(o, &n))
+ if (tonumber(o, &n)) {
+#ifdef LNUM_COMPLEX
+ if (nvalue_img(o) != 0)
+ luaG_runerror(L, "expecting a real number");
+#endif
return nvalue(o);
- else
- return 0;
+ }
+ return 0;
}
LUA_API lua_Integer lua_tointeger (lua_State *L, int idx) {
TValue n;
+ /* Lua 5.1 documented behaviour is to return nonzero for non-integer:
+ * "If the number is not an integer, it is truncated in some non-specified way."
+ * I would suggest to change this, to return 0 for anything that would
+ * not fit in 'lua_Integer'.
+ */
+#ifdef LUA_COMPAT_TOINTEGER
+ /* Lua 5.1 compatible */
const TValue *o = index2adr(L, idx);
if (tonumber(o, &n)) {
- lua_Integer res;
- lua_Number num = nvalue(o);
- lua_number2integer(res, num);
- return res;
+ lua_Integer i;
+ lua_Number d;
+ if (ttisint(o)) return ivalue(o);
+ d= nvalue_fast(o);
+# ifdef LNUM_COMPLEX
+ if (nvalue_img_fast(o) != 0)
+ luaG_runerror(L, "expecting a real number");
+# endif
+ lua_number2integer(i, d);
+ return i;
}
- else
- return 0;
+#else
+ /* New suggestion */
+ const TValue *o = index2adr(L, idx);
+ if (tonumber(o, &n)) {
+ lua_Integer i;
+ if (ttisint(o)) return ivalue(o);
+ if (tt_integer_valued(o,&i)) return i;
+ }
+#endif
+ return 0;
}
+#ifdef LNUM_COMPLEX
+LUA_API lua_Complex lua_tocomplex (lua_State *L, int idx) {
+ TValue tmp;
+ const TValue *o = index2adr(L, idx);
+ if (tonumber(o, &tmp))
+ return nvalue_complex(o);
+ return 0;
+}
+#endif
+
+
LUA_API int lua_toboolean (lua_State *L, int idx) {
const TValue *o = index2adr(L, idx);
return !l_isfalse(o);
@@ -364,6 +408,7 @@ LUA_API size_t lua_objlen (lua_State *L,
case LUA_TSTRING: return tsvalue(o)->len;
case LUA_TUSERDATA: return uvalue(o)->len;
case LUA_TTABLE: return luaH_getn(hvalue(o));
+ case LUA_TINT:
case LUA_TNUMBER: {
size_t l;
lua_lock(L); /* `luaV_tostring' may create a new string */
@@ -426,6 +471,8 @@ LUA_API void lua_pushnil (lua_State *L)
}
+/* 'lua_pushnumber()' may lose accuracy on integers, 'lua_pushinteger' will not.
+ */
LUA_API void lua_pushnumber (lua_State *L, lua_Number n) {
lua_lock(L);
setnvalue(L->top, n);
@@ -434,12 +481,22 @@ LUA_API void lua_pushnumber (lua_State *
}
-LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) {
+LUA_API void lua_pushinteger (lua_State *L, lua_Integer i) {
+ lua_lock(L);
+ setivalue(L->top, i);
+ api_incr_top(L);
+ lua_unlock(L);
+}
+
+
+#ifdef LNUM_COMPLEX
+LUA_API void lua_pushcomplex (lua_State *L, lua_Complex v) {
lua_lock(L);
- setnvalue(L->top, cast_num(n));
+ setnvalue_complex( L->top, v );
api_incr_top(L);
lua_unlock(L);
}
+#endif
LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) {
@@ -569,7 +626,7 @@ LUA_API void lua_rawgeti (lua_State *L,
lua_lock(L);
o = index2adr(L, idx);
api_check(L, ttistable(o));
- setobj2s(L, L->top, luaH_getnum(hvalue(o), n));
+ setobj2s(L, L->top, luaH_getint(hvalue(o), n));
api_incr_top(L);
lua_unlock(L);
}
@@ -597,6 +654,9 @@ LUA_API int lua_getmetatable (lua_State
case LUA_TUSERDATA:
mt = uvalue(obj)->metatable;
break;
+ case LUA_TINT:
+ mt = G(L)->mt[LUA_TNUMBER];
+ break;
default:
mt = G(L)->mt[ttype(obj)];
break;
@@ -687,7 +747,7 @@ LUA_API void lua_rawseti (lua_State *L,
api_checknelems(L, 1);
o = index2adr(L, idx);
api_check(L, ttistable(o));
- setobj2t(L, luaH_setnum(L, hvalue(o), n), L->top-1);
+ setobj2t(L, luaH_setint(L, hvalue(o), n), L->top-1);
luaC_barriert(L, hvalue(o), L->top-1);
L->top--;
lua_unlock(L);
@@ -721,7 +781,7 @@ LUA_API int lua_setmetatable (lua_State
break;
}
default: {
- G(L)->mt[ttype(obj)] = mt;
+ G(L)->mt[ttype_ext(obj)] = mt;
break;
}
}
@@ -1085,3 +1145,32 @@ LUA_API const char *lua_setupvalue (lua_
return name;
}
+
+/* Help function for 'luaB_tonumber()', avoids multiple str->number
+ * conversions for Lua "tonumber()".
+ *
+ * Also pushes floating point numbers with integer value as integer, which
+ * can be used by 'tonumber()' in scripts to bring values back to integer
+ * realm.
+ *
+ * Note: The 'back to integer realm' is _not_ to affect string conversions:
+ * 'tonumber("4294967295.1")' should give a floating point value, although
+ * the value would be 4294967296 (and storable in int64 realm).
+ */
+int lua_pushvalue_as_number (lua_State *L, int idx)
+{
+ const TValue *o = index2adr(L, idx);
+ TValue tmp;
+ lua_Integer i;
+ if (ttisnumber(o)) {
+ if ( (!ttisint(o)) && tt_integer_valued(o,&i)) {
+ lua_pushinteger( L, i );
+ return 1;
+ }
+ } else if (!tonumber(o, &tmp)) {
+ return 0;
+ }
+ if (ttisint(o)) lua_pushinteger( L, ivalue(o) );
+ else lua_pushnumber( L, nvalue_fast(o) );
+ return 1;
+}
--- a/src/lapi.h
+++ b/src/lapi.h
@@ -13,4 +13,6 @@
LUAI_FUNC void luaA_pushobject (lua_State *L, const TValue *o);
+int lua_pushvalue_as_number (lua_State *L, int idx);
+
#endif
--- a/src/lauxlib.c
+++ b/src/lauxlib.c
@@ -23,7 +23,7 @@
#include "lua.h"
#include "lauxlib.h"
-
+#include "llimits.h"
#define FREELIST_REF 0 /* free list of references */
@@ -66,7 +66,7 @@ LUALIB_API int luaL_typerror (lua_State
static void tag_error (lua_State *L, int narg, int tag) {
- luaL_typerror(L, narg, lua_typename(L, tag));
+ luaL_typerror(L, narg, tag==LUA_TINT ? "integer" : lua_typename(L, tag));
}
@@ -188,8 +188,8 @@ LUALIB_API lua_Number luaL_optnumber (lu
LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) {
lua_Integer d = lua_tointeger(L, narg);
- if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */
- tag_error(L, narg, LUA_TNUMBER);
+ if (d == 0 && !lua_isinteger(L, narg)) /* avoid extra test when d is not 0 */
+ tag_error(L, narg, LUA_TINT);
return d;
}
@@ -200,6 +200,16 @@ LUALIB_API lua_Integer luaL_optinteger (
}
+#ifdef LNUM_COMPLEX
+LUALIB_API lua_Complex luaL_checkcomplex (lua_State *L, int narg) {
+ lua_Complex c = lua_tocomplex(L, narg);
+ if (c == 0 && !lua_isnumber(L, narg)) /* avoid extra test when c is not 0 */
+ tag_error(L, narg, LUA_TNUMBER);
+ return c;
+}
+#endif
+
+
LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) {
if (!lua_getmetatable(L, obj)) /* no metatable? */
return 0;
--- a/src/lauxlib.h
+++ b/src/lauxlib.h
@@ -57,6 +57,12 @@ LUALIB_API lua_Number (luaL_optnumber) (
LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg);
LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg,
lua_Integer def);
+#define luaL_checkint32(L,narg) ((int)luaL_checkinteger(L,narg))
+#define luaL_optint32(L,narg,def) ((int)luaL_optinteger(L,narg,def))
+
+#ifdef LNUM_COMPLEX
+ LUALIB_API lua_Complex (luaL_checkcomplex) (lua_State *L, int narg);
+#endif
LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg);
LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t);
--- a/src/lbaselib.c
+++ b/src/lbaselib.c
@@ -18,7 +18,9 @@
#include "lauxlib.h"
#include "lualib.h"
-
+#include "llimits.h"
+#include "lobject.h"
+#include "lapi.h"
@@ -54,20 +56,25 @@ static int luaB_tonumber (lua_State *L)
int base = luaL_optint(L, 2, 10);
if (base == 10) { /* standard conversion */
luaL_checkany(L, 1);
- if (lua_isnumber(L, 1)) {
- lua_pushnumber(L, lua_tonumber(L, 1));
+ if (lua_isnumber(L, 1)) { /* numeric string, or a number */
+ lua_pushvalue_as_number(L,1); /* API extension (not to lose accuracy here) */
return 1;
- }
+ }
}
else {
const char *s1 = luaL_checkstring(L, 1);
char *s2;
- unsigned long n;
+ unsigned LUA_INTEGER n;
luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range");
- n = strtoul(s1, &s2, base);
+ n = lua_str2ul(s1, &s2, base);
if (s1 != s2) { /* at least one valid digit? */
while (isspace((unsigned char)(*s2))) s2++; /* skip trailing spaces */
if (*s2 == '\0') { /* no invalid trailing characters? */
+
+ /* Push as number, there needs to be separate 'luaB_tointeger' for
+ * when the caller wants to preserve the bits (matters if unsigned
+ * values are used).
+ */
lua_pushnumber(L, (lua_Number)n);
return 1;
}
@@ -144,7 +151,7 @@ static int luaB_setfenv (lua_State *L) {
luaL_checktype(L, 2, LUA_TTABLE);
getfunc(L, 0);
lua_pushvalue(L, 2);
- if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0) {
+ if (lua_isnumber(L, 1) && lua_tointeger(L, 1) == 0) {
/* change environment of current thread */
lua_pushthread(L);
lua_insert(L, -2);
@@ -209,7 +216,7 @@ static int luaB_collectgarbage (lua_Stat
return 1;
}
default: {
- lua_pushnumber(L, res);
+ lua_pushinteger(L, res);
return 1;
}
}
@@ -631,6 +638,8 @@ static void base_open (lua_State *L) {
luaL_register(L, "_G", base_funcs);
lua_pushliteral(L, LUA_VERSION);
lua_setglobal(L, "_VERSION"); /* set global _VERSION */
+ lua_pushliteral(L, LUA_LNUM);
+ lua_setglobal(L, "_LNUM"); /* "[complex] double|float|ldouble int32|int64" */
/* `ipairs' and `pairs' need auxiliary functions as upvalues */
auxopen(L, "ipairs", luaB_ipairs, ipairsaux);
auxopen(L, "pairs", luaB_pairs, luaB_next);
--- a/src/lcode.c
+++ b/src/lcode.c
@@ -22,13 +22,18 @@
#include "lopcodes.h"
#include "lparser.h"
#include "ltable.h"
+#include "lnum.h"
#define hasjumps(e) ((e)->t != (e)->f)
-
static int isnumeral(expdesc *e) {
- return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP);
+ int ek=
+#ifdef LNUM_COMPLEX
+ (e->k == VKNUM2) ||
+#endif
+ (e->k == VKINT) || (e->k == VKNUM);
+ return (ek && e->t == NO_JUMP && e->f == NO_JUMP);
}
@@ -231,12 +236,16 @@ static int addk (FuncState *fs, TValue *
TValue *idx = luaH_set(L, fs->h, k);
Proto *f = fs->f;
int oldsize = f->sizek;
- if (ttisnumber(idx)) {
- lua_assert(luaO_rawequalObj(&fs->f->k[cast_int(nvalue(idx))], v));
- return cast_int(nvalue(idx));
+ if (ttype(idx)==LUA_TNUMBER) {
+ luai_normalize(idx);
+ lua_assert( ttype(idx)==LUA_TINT ); /* had no fraction */
+ }
+ if (ttisint(idx)) {
+ lua_assert(luaO_rawequalObj(&fs->f->k[ivalue(idx)], v));
+ return cast_int(ivalue(idx));
}
else { /* constant not found; create a new entry */
- setnvalue(idx, cast_num(fs->nk));
+ setivalue(idx, fs->nk);
luaM_growvector(L, f->k, fs->nk, f->sizek, TValue,
MAXARG_Bx, "constant table overflow");
while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]);
@@ -261,6 +270,21 @@ int luaK_numberK (FuncState *fs, lua_Num
}
+int luaK_integerK (FuncState *fs, lua_Integer r) {
+ TValue o;
+ setivalue(&o, r);
+ return addk(fs, &o, &o);
+}
+
+
+#ifdef LNUM_COMPLEX
+static int luaK_imagK (FuncState *fs, lua_Number r) {
+ TValue o;
+ setnvalue_complex(&o, r*I);
+ return addk(fs, &o, &o);
+}
+#endif
+
static int boolK (FuncState *fs, int b) {
TValue o;
setbvalue(&o, b);
@@ -359,6 +383,16 @@ static void discharge2reg (FuncState *fs
luaK_codeABx(fs, OP_LOADK, reg, luaK_numberK(fs, e->u.nval));
break;
}
+ case VKINT: {
+ luaK_codeABx(fs, OP_LOADK, reg, luaK_integerK(fs, e->u.ival));
+ break;
+ }
+#ifdef LNUM_COMPLEX
+ case VKNUM2: {
+ luaK_codeABx(fs, OP_LOADK, reg, luaK_imagK(fs, e->u.nval));
+ break;
+ }
+#endif
case VRELOCABLE: {
Instruction *pc = &getcode(fs, e);
SETARG_A(*pc, reg);
@@ -444,6 +478,10 @@ void luaK_exp2val (FuncState *fs, expdes
int luaK_exp2RK (FuncState *fs, expdesc *e) {
luaK_exp2val(fs, e);
switch (e->k) {
+#ifdef LNUM_COMPLEX
+ case VKNUM2:
+#endif
+ case VKINT:
case VKNUM:
case VTRUE:
case VFALSE:
@@ -451,6 +489,10 @@ int luaK_exp2RK (FuncState *fs, expdesc
if (fs->nk <= MAXINDEXRK) { /* constant fit in RK operand? */
e->u.s.info = (e->k == VNIL) ? nilK(fs) :
(e->k == VKNUM) ? luaK_numberK(fs, e->u.nval) :
+ (e->k == VKINT) ? luaK_integerK(fs, e->u.ival) :
+#ifdef LNUM_COMPLEX
+ (e->k == VKNUM2) ? luaK_imagK(fs, e->u.nval) :
+#endif
boolK(fs, (e->k == VTRUE));
e->k = VK;
return RKASK(e->u.s.info);
@@ -540,7 +582,10 @@ void luaK_goiftrue (FuncState *fs, expde
int pc; /* pc of last jump */
luaK_dischargevars(fs, e);
switch (e->k) {
- case VK: case VKNUM: case VTRUE: {
+#ifdef LNUM_COMPLEX
+ case VKNUM2:
+#endif
+ case VKINT: case VK: case VKNUM: case VTRUE: {
pc = NO_JUMP; /* always true; do nothing */
break;
}
@@ -590,7 +635,10 @@ static void codenot (FuncState *fs, expd
e->k = VTRUE;
break;
}
- case VK: case VKNUM: case VTRUE: {
+#ifdef LNUM_COMPLEX
+ case VKNUM2:
+#endif
+ case VKINT: case VK: case VKNUM: case VTRUE: {
e->k = VFALSE;
break;
}
@@ -626,25 +674,70 @@ void luaK_indexed (FuncState *fs, expdes
static int constfolding (OpCode op, expdesc *e1, expdesc *e2) {
lua_Number v1, v2, r;
+ int vkres= VKNUM;
if (!isnumeral(e1) || !isnumeral(e2)) return 0;
- v1 = e1->u.nval;
- v2 = e2->u.nval;
+
+ /* real and imaginary parts don't mix. */
+#ifdef LNUM_COMPLEX
+ if (e1->k == VKNUM2) {
+ if ((op != OP_UNM) && (e2->k != VKNUM2)) return 0;
+ vkres= VKNUM2; }
+ else if (e2->k == VKNUM2) { return 0; }
+#endif
+ if ((e1->k == VKINT) && (e2->k == VKINT)) {
+ lua_Integer i1= e1->u.ival, i2= e2->u.ival;
+ lua_Integer rr;
+ int done= 0;
+ /* Integer/integer calculations (may end up producing floating point) */
+ switch (op) {
+ case OP_ADD: done= try_addint( &rr, i1, i2 ); break;
+ case OP_SUB: done= try_subint( &rr, i1, i2 ); break;
+ case OP_MUL: done= try_mulint( &rr, i1, i2 ); break;
+ case OP_DIV: done= try_divint( &rr, i1, i2 ); break;
+ case OP_MOD: done= try_modint( &rr, i1, i2 ); break;
+ case OP_POW: done= try_powint( &rr, i1, i2 ); break;
+ case OP_UNM: done= try_unmint( &rr, i1 ); break;
+ default: done= 0; break;
+ }
+ if (done) {
+ e1->u.ival = rr; /* remained within integer range */
+ return 1;
+ }
+ }
+ v1 = (e1->k == VKINT) ? ((lua_Number)e1->u.ival) : e1->u.nval;
+ v2 = (e2->k == VKINT) ? ((lua_Number)e2->u.ival) : e2->u.nval;
+
switch (op) {
case OP_ADD: r = luai_numadd(v1, v2); break;
case OP_SUB: r = luai_numsub(v1, v2); break;
- case OP_MUL: r = luai_nummul(v1, v2); break;
+ case OP_MUL:
+#ifdef LNUM_COMPLEX
+ if (vkres==VKNUM2) return 0; /* leave to runtime (could do here, but not worth it?) */
+#endif
+ r = luai_nummul(v1, v2); break;
case OP_DIV:
if (v2 == 0) return 0; /* do not attempt to divide by 0 */
- r = luai_numdiv(v1, v2); break;
+#ifdef LNUM_COMPLEX
+ if (vkres==VKNUM2) return 0; /* leave to runtime */
+#endif
+ r = luai_numdiv(v1, v2); break;
case OP_MOD:
if (v2 == 0) return 0; /* do not attempt to divide by 0 */
+#ifdef LNUM_COMPLEX
+ if (vkres==VKNUM2) return 0; /* leave to runtime */
+#endif
r = luai_nummod(v1, v2); break;
- case OP_POW: r = luai_numpow(v1, v2); break;
+ case OP_POW:
+#ifdef LNUM_COMPLEX
+ if (vkres==VKNUM2) return 0; /* leave to runtime */
+#endif
+ r = luai_numpow(v1, v2); break;
case OP_UNM: r = luai_numunm(v1); break;
case OP_LEN: return 0; /* no constant folding for 'len' */
default: lua_assert(0); r = 0; break;
}
if (luai_numisnan(r)) return 0; /* do not attempt to produce NaN */
+ e1->k = cast(expkind,vkres);
e1->u.nval = r;
return 1;
}
@@ -688,7 +781,8 @@ static void codecomp (FuncState *fs, OpC
void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) {
expdesc e2;
- e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0;
+ e2.t = e2.f = NO_JUMP; e2.k = VKINT; e2.u.ival = 0;
+
switch (op) {
case OPR_MINUS: {
if (!isnumeral(e))
--- a/src/lcode.h
+++ b/src/lcode.h
@@ -71,6 +71,6 @@ LUAI_FUNC void luaK_prefix (FuncState *f
LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v);
LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, expdesc *v2);
LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore);
-
+LUAI_FUNC int luaK_integerK (FuncState *fs, lua_Integer r);
#endif
--- a/src/ldebug.c
+++ b/src/ldebug.c
@@ -183,7 +183,7 @@ static void collectvalidlines (lua_State
int *lineinfo = f->l.p->lineinfo;
int i;
for (i=0; i<f->l.p->sizelineinfo; i++)
- setbvalue(luaH_setnum(L, t, lineinfo[i]), 1);
+ setbvalue(luaH_setint(L, t, lineinfo[i]), 1);
sethvalue(L, L->top, t);
}
incr_top(L);
@@ -566,7 +566,7 @@ static int isinstack (CallInfo *ci, cons
void luaG_typeerror (lua_State *L, const TValue *o, const char *op) {
const char *name = NULL;
- const char *t = luaT_typenames[ttype(o)];
+ const char *t = luaT_typenames[ttype_ext(o)];
const char *kind = (isinstack(L->ci, o)) ?
getobjname(L, L->ci, cast_int(o - L->base), &name) :
NULL;
@@ -594,8 +594,8 @@ void luaG_aritherror (lua_State *L, cons
int luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) {
- const char *t1 = luaT_typenames[ttype(p1)];
- const char *t2 = luaT_typenames[ttype(p2)];
+ const char *t1 = luaT_typenames[ttype_ext(p1)];
+ const char *t2 = luaT_typenames[ttype_ext(p2)];
if (t1[2] == t2[2])
luaG_runerror(L, "attempt to compare two %s values", t1);
else
--- a/src/ldo.c
+++ b/src/ldo.c
@@ -220,9 +220,9 @@ static StkId adjust_varargs (lua_State *
luaD_checkstack(L, p->maxstacksize);
htab = luaH_new(L, nvar, 1); /* create `arg' table */
for (i=0; i<nvar; i++) /* put extra arguments into `arg' table */
- setobj2n(L, luaH_setnum(L, htab, i+1), L->top - nvar + i);
+ setobj2n(L, luaH_setint(L, htab, i+1), L->top - nvar + i);
/* store counter in field `n' */
- setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), cast_num(nvar));
+ setivalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), nvar);
}
#endif
/* move fixed parameters to final position */
--- a/src/ldump.c
+++ b/src/ldump.c
@@ -52,6 +52,11 @@ static void DumpNumber(lua_Number x, Dum
DumpVar(x,D);
}
+static void DumpInteger(lua_Integer x, DumpState* D)
+{
+ DumpVar(x,D);
+}
+
static void DumpVector(const void* b, int n, size_t size, DumpState* D)
{
DumpInt(n,D);
@@ -93,8 +98,11 @@ static void DumpConstants(const Proto* f
DumpChar(bvalue(o),D);
break;
case LUA_TNUMBER:
- DumpNumber(nvalue(o),D);
+ DumpNumber(nvalue_fast(o),D);
break;
+ case LUA_TINT:
+ DumpInteger(ivalue(o),D);
+ break;
case LUA_TSTRING:
DumpString(rawtsvalue(o),D);
break;
--- a/src/liolib.c
+++ b/src/liolib.c
@@ -9,6 +9,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <ctype.h>
#define liolib_c
#define LUA_LIB
@@ -18,7 +19,8 @@
#include "lauxlib.h"
#include "lualib.h"
-
+#include "lnum.h"
+#include "llex.h"
#define IO_INPUT 1
#define IO_OUTPUT 2
@@ -269,6 +271,13 @@ static int io_lines (lua_State *L) {
** =======================================================
*/
+/*
+* Many problems if we intend the same 'n' format specifier (see 'file:read()')
+* to work for both FP and integer numbers, without losing their accuracy. So
+* we don't. 'n' reads numbers as floating points, 'i' as integers. Old code
+* remains valid, but won't provide full integer accuracy (this only matters
+* with float FP and/or 64-bit integers).
+*/
static int read_number (lua_State *L, FILE *f) {
lua_Number d;
@@ -282,6 +291,43 @@ static int read_number (lua_State *L, FI
}
}
+static int read_integer (lua_State *L, FILE *f) {
+ lua_Integer i;
+ if (fscanf(f, LUA_INTEGER_SCAN, &i) == 1) {
+ lua_pushinteger(L, i);
+ return 1;
+ }
+ else return 0; /* read fails */
+}
+
+#ifdef LNUM_COMPLEX
+static int read_complex (lua_State *L, FILE *f) {
+ /* NNN / NNNi / NNN+MMMi / NNN-MMMi */
+ lua_Number a,b;
+ if (fscanf(f, LUA_NUMBER_SCAN, &a) == 1) {
+ int c=fgetc(f);
+ switch(c) {
+ case 'i':
+ lua_pushcomplex(L, a*I);
+ return 1;
+ case '+':
+ case '-':
+ /* "i" is consumed if at the end; just 'NNN+MMM' will most likely
+ * behave as if "i" was there? (TBD: test)
+ */
+ if (fscanf(f, LUA_NUMBER_SCAN "i", &b) == 1) {
+ lua_pushcomplex(L, a+ (c=='+' ? b:-b)*I);
+ return 1;
+ }
+ }
+ ungetc( c,f );
+ lua_pushnumber(L,a); /*real part only*/
+ return 1;
+ }
+ return 0; /* read fails */
+}
+#endif
+
static int test_eof (lua_State *L, FILE *f) {
int c = getc(f);
@@ -355,6 +401,14 @@ static int g_read (lua_State *L, FILE *f
case 'n': /* number */
success = read_number(L, f);
break;
+ case 'i': /* integer (full accuracy) */
+ success = read_integer(L, f);
+ break;
+#ifdef LNUM_COMPLEX
+ case 'c': /* complex */
+ success = read_complex(L, f);
+ break;
+#endif
case 'l': /* line */
success = read_line(L, f);
break;
@@ -415,9 +469,10 @@ static int g_write (lua_State *L, FILE *
int status = 1;
for (; nargs--; arg++) {
if (lua_type(L, arg) == LUA_TNUMBER) {
- /* optimization: could be done exactly as for strings */
- status = status &&
- fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0;
+ if (lua_isinteger(L,arg))
+ status = status && fprintf(f, LUA_INTEGER_FMT, lua_tointeger(L, arg)) > 0;
+ else
+ status = status && fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0;
}
else {
size_t l;
@@ -460,7 +515,7 @@ static int f_setvbuf (lua_State *L) {
static const char *const modenames[] = {"no", "full", "line", NULL};
FILE *f = tofile(L);
int op = luaL_checkoption(L, 2, NULL, modenames);
- lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE);
+ size_t sz = luaL_optint32(L, 3, LUAL_BUFFERSIZE);
int res = setvbuf(f, NULL, mode[op], sz);
return pushresult(L, res == 0, NULL);
}
--- a/src/llex.c
+++ b/src/llex.c
@@ -22,6 +22,7 @@
#include "lstring.h"
#include "ltable.h"
#include "lzio.h"
+#include "lnum.h"
@@ -34,13 +35,17 @@
/* ORDER RESERVED */
-const char *const luaX_tokens [] = {
+static const char *const luaX_tokens [] = {
"and", "break", "do", "else", "elseif",
"end", "false", "for", "function", "if",
"in", "local", "nil", "not", "or", "repeat",
"return", "then", "true", "until", "while",
"..", "...", "==", ">=", "<=", "~=",
"<number>", "<name>", "<string>", "<eof>",
+ "<integer>",
+#ifdef LNUM_COMPLEX
+ "<number2>",
+#endif
NULL
};
@@ -90,7 +95,11 @@ static const char *txtToken (LexState *l
switch (token) {
case TK_NAME:
case TK_STRING:
+ case TK_INT:
case TK_NUMBER:
+#ifdef LNUM_COMPLEX
+ case TK_NUMBER2:
+#endif
save(ls, '\0');
return luaZ_buffer(ls->buff);
default:
@@ -175,23 +184,27 @@ static void buffreplace (LexState *ls, c
if (p[n] == from) p[n] = to;
}
-
-static void trydecpoint (LexState *ls, SemInfo *seminfo) {
+/* TK_NUMBER (/ TK_NUMBER2) */
+static int trydecpoint (LexState *ls, SemInfo *seminfo) {
/* format error: try to update decimal point separator */
struct lconv *cv = localeconv();
char old = ls->decpoint;
+ int ret;
ls->decpoint = (cv ? cv->decimal_point[0] : '.');
buffreplace(ls, old, ls->decpoint); /* try updated decimal separator */
- if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) {
+ ret= luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r, NULL);
+ if (!ret) {
/* format error with correct decimal point: no more options */
buffreplace(ls, ls->decpoint, '.'); /* undo change (for error message) */
luaX_lexerror(ls, "malformed number", TK_NUMBER);
}
+ return ret;
}
-/* LUA_NUMBER */
-static void read_numeral (LexState *ls, SemInfo *seminfo) {
+/* TK_NUMBER / TK_INT (/TK_NUMBER2) */
+static int read_numeral (LexState *ls, SemInfo *seminfo) {
+ int ret;
lua_assert(isdigit(ls->current));
do {
save_and_next(ls);
@@ -202,8 +215,9 @@ static void read_numeral (LexState *ls,
save_and_next(ls);
save(ls, '\0');
buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */
- if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) /* format error? */
- trydecpoint(ls, seminfo); /* try to update decimal point separator */
+ ret= luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r, &seminfo->i );
+ if (!ret) return trydecpoint(ls, seminfo); /* try to update decimal point separator */
+ return ret;
}
@@ -331,6 +345,7 @@ static void read_string (LexState *ls, i
}
+/* char / TK_* */
static int llex (LexState *ls, SemInfo *seminfo) {
luaZ_resetbuffer(ls->buff);
for (;;) {
@@ -402,8 +417,7 @@ static int llex (LexState *ls, SemInfo *
}
else if (!isdigit(ls->current)) return '.';
else {
- read_numeral(ls, seminfo);
- return TK_NUMBER;
+ return read_numeral(ls, seminfo);
}
}
case EOZ: {
@@ -416,8 +430,7 @@ static int llex (LexState *ls, SemInfo *
continue;
}
else if (isdigit(ls->current)) {
- read_numeral(ls, seminfo);
- return TK_NUMBER;
+ return read_numeral(ls, seminfo);
}
else if (isalpha(ls->current) || ls->current == '_') {
/* identifier or reserved word */
--- a/src/llex.h
+++ b/src/llex.h
@@ -29,19 +29,22 @@ enum RESERVED {
TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE,
/* other terminal symbols */
TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER,
- TK_NAME, TK_STRING, TK_EOS
+ TK_NAME, TK_STRING, TK_EOS, TK_INT
+#ifdef LNUM_COMPLEX
+ , TK_NUMBER2 /* imaginary constants: Ni */
+#endif
};
/* number of reserved words */
#define NUM_RESERVED (cast(int, TK_WHILE-FIRST_RESERVED+1))
-/* array with token `names' */
-LUAI_DATA const char *const luaX_tokens [];
-
-
+/* SemInfo is a local data structure of 'llex.c', used for carrying a string
+ * or a number. A separate token (TK_*) will tell, how to interpret the data.
+ */
typedef union {
lua_Number r;
+ lua_Integer i;
TString *ts;
} SemInfo; /* semantics information */
--- a/src/llimits.h
+++ b/src/llimits.h
@@ -49,6 +49,7 @@ typedef LUAI_USER_ALIGNMENT_T L_Umaxalig
/* result of a `usual argument conversion' over lua_Number */
typedef LUAI_UACNUMBER l_uacNumber;
+typedef LUAI_UACINTEGER l_uacInteger;
/* internal assertions for in-house debugging */
@@ -80,7 +81,6 @@ typedef LUAI_UACNUMBER l_uacNumber;
#define cast_int(i) cast(int, (i))
-
/*
** type for virtual-machine instructions
** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h)
--- a/src/lmathlib.c
+++ b/src/lmathlib.c
@@ -4,7 +4,6 @@
** See Copyright Notice in lua.h
*/
-
#include <stdlib.h>
#include <math.h>
@@ -16,113 +15,210 @@
#include "lauxlib.h"
#include "lualib.h"
+/* 'luai_vectpow()' as a replacement for 'cpow()'. Defined in the header; we
+ * don't intrude the code libs internal functions.
+ */
+#ifdef LNUM_COMPLEX
+# include "lnum.h"
+#endif
#undef PI
-#define PI (3.14159265358979323846)
-#define RADIANS_PER_DEGREE (PI/180.0)
-
+#ifdef LNUM_FLOAT
+# define PI (3.14159265358979323846F)
+#elif defined(M_PI)
+# define PI M_PI
+#else
+# define PI (3.14159265358979323846264338327950288)
+#endif
+#define RADIANS_PER_DEGREE (PI/180)
+#undef HUGE
+#ifdef LNUM_FLOAT
+# define HUGE HUGE_VALF
+#elif defined(LNUM_LDOUBLE)
+# define HUGE HUGE_VALL
+#else
+# define HUGE HUGE_VAL
+#endif
static int math_abs (lua_State *L) {
- lua_pushnumber(L, fabs(luaL_checknumber(L, 1)));
+#ifdef LNUM_COMPLEX
+ lua_pushnumber(L, _LF(cabs) (luaL_checkcomplex(L,1)));
+#else
+ lua_pushnumber(L, _LF(fabs) (luaL_checknumber(L, 1)));
+#endif
return 1;
}
static int math_sin (lua_State *L) {
- lua_pushnumber(L, sin(luaL_checknumber(L, 1)));
+#ifdef LNUM_COMPLEX
+ lua_pushcomplex(L, _LF(csin) (luaL_checkcomplex(L,1)));
+#else
+ lua_pushnumber(L, _LF(sin) (luaL_checknumber(L, 1)));
+#endif
return 1;
}
static int math_sinh (lua_State *L) {
- lua_pushnumber(L, sinh(luaL_checknumber(L, 1)));
+#ifdef LNUM_COMPLEX
+ lua_pushcomplex(L, _LF(csinh) (luaL_checkcomplex(L,1)));
+#else
+ lua_pushnumber(L, _LF(sinh) (luaL_checknumber(L, 1)));
+#endif
return 1;
}
static int math_cos (lua_State *L) {
- lua_pushnumber(L, cos(luaL_checknumber(L, 1)));
+#ifdef LNUM_COMPLEX
+ lua_pushcomplex(L, _LF(ccos) (luaL_checkcomplex(L,1)));
+#else
+ lua_pushnumber(L, _LF(cos) (luaL_checknumber(L, 1)));
+#endif
return 1;
}
static int math_cosh (lua_State *L) {
- lua_pushnumber(L, cosh(luaL_checknumber(L, 1)));
+#ifdef LNUM_COMPLEX
+ lua_pushcomplex(L, _LF(ccosh) (luaL_checkcomplex(L,1)));
+#else
+ lua_pushnumber(L, _LF(cosh) (luaL_checknumber(L, 1)));
+#endif
return 1;
}
static int math_tan (lua_State *L) {
- lua_pushnumber(L, tan(luaL_checknumber(L, 1)));
+#ifdef LNUM_COMPLEX
+ lua_pushcomplex(L, _LF(ctan) (luaL_checkcomplex(L,1)));
+#else
+ lua_pushnumber(L, _LF(tan) (luaL_checknumber(L, 1)));
+#endif
return 1;
}
static int math_tanh (lua_State *L) {
- lua_pushnumber(L, tanh(luaL_checknumber(L, 1)));
+#ifdef LNUM_COMPLEX
+ lua_pushcomplex(L, _LF(ctanh) (luaL_checkcomplex(L,1)));
+#else
+ lua_pushnumber(L, _LF(tanh) (luaL_checknumber(L, 1)));
+#endif
return 1;
}
static int math_asin (lua_State *L) {
- lua_pushnumber(L, asin(luaL_checknumber(L, 1)));
+#ifdef LNUM_COMPLEX
+ lua_pushcomplex(L, _LF(casin) (luaL_checkcomplex(L,1)));
+#else
+ lua_pushnumber(L, _LF(asin) (luaL_checknumber(L, 1)));
+#endif
return 1;
}
static int math_acos (lua_State *L) {
- lua_pushnumber(L, acos(luaL_checknumber(L, 1)));
+#ifdef LNUM_COMPLEX
+ lua_pushcomplex(L, _LF(cacos) (luaL_checkcomplex(L,1)));
+#else
+ lua_pushnumber(L, _LF(acos) (luaL_checknumber(L, 1)));
+#endif
return 1;
}
static int math_atan (lua_State *L) {
- lua_pushnumber(L, atan(luaL_checknumber(L, 1)));
+#ifdef LNUM_COMPLEX
+ lua_pushcomplex(L, _LF(catan) (luaL_checkcomplex(L,1)));
+#else
+ lua_pushnumber(L, _LF(atan) (luaL_checknumber(L, 1)));
+#endif
return 1;
}
static int math_atan2 (lua_State *L) {
- lua_pushnumber(L, atan2(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
+ /* scalars only */
+ lua_pushnumber(L, _LF(atan2) (luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
return 1;
}
static int math_ceil (lua_State *L) {
- lua_pushnumber(L, ceil(luaL_checknumber(L, 1)));
+#ifdef LNUM_COMPLEX
+ lua_Complex v= luaL_checkcomplex(L, 1);
+ lua_pushcomplex(L, _LF(ceil) (_LF(creal)(v)) + _LF(ceil) (_LF(cimag)(v))*I);
+#else
+ lua_pushnumber(L, _LF(ceil) (luaL_checknumber(L, 1)));
+#endif
return 1;
}
static int math_floor (lua_State *L) {
- lua_pushnumber(L, floor(luaL_checknumber(L, 1)));
+#ifdef LNUM_COMPLEX
+ lua_Complex v= luaL_checkcomplex(L, 1);
+ lua_pushcomplex(L, _LF(floor) (_LF(creal)(v)) + _LF(floor) (_LF(cimag)(v))*I);
+#else
+ lua_pushnumber(L, _LF(floor) (luaL_checknumber(L, 1)));
+#endif
return 1;
}
-static int math_fmod (lua_State *L) {
- lua_pushnumber(L, fmod(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
+static int math_fmod (lua_State *L) {
+ /* scalars only */
+ lua_pushnumber(L, _LF(fmod) (luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
return 1;
}
static int math_modf (lua_State *L) {
- double ip;
- double fp = modf(luaL_checknumber(L, 1), &ip);
+ /* scalars only */
+ lua_Number ip;
+ lua_Number fp = _LF(modf) (luaL_checknumber(L, 1), &ip);
lua_pushnumber(L, ip);
lua_pushnumber(L, fp);
return 2;
}
static int math_sqrt (lua_State *L) {
- lua_pushnumber(L, sqrt(luaL_checknumber(L, 1)));
+#ifdef LNUM_COMPLEX
+ lua_pushcomplex(L, _LF(csqrt) (luaL_checkcomplex(L,1)));
+#else
+ lua_pushnumber(L, _LF(sqrt) (luaL_checknumber(L, 1)));
+#endif
return 1;
}
static int math_pow (lua_State *L) {
- lua_pushnumber(L, pow(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
+#ifdef LNUM_COMPLEX
+ /* C99 'cpow' gives somewhat inaccurate results (i.e. (-1)^2 = -1+1.2246467991474e-16i).
+ * 'luai_vectpow' smoothens such, reusing it is the reason we need to #include "lnum.h".
+ */
+ lua_pushcomplex(L, luai_vectpow(luaL_checkcomplex(L,1), luaL_checkcomplex(L,2)));
+#else
+ lua_pushnumber(L, _LF(pow) (luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
+#endif
return 1;
}
static int math_log (lua_State *L) {
- lua_pushnumber(L, log(luaL_checknumber(L, 1)));
+#ifdef LNUM_COMPLEX
+ lua_pushcomplex(L, _LF(clog) (luaL_checkcomplex(L,1)));
+#else
+ lua_pushnumber(L, _LF(log) (luaL_checknumber(L, 1)));
+#endif
return 1;
}
static int math_log10 (lua_State *L) {
- lua_pushnumber(L, log10(luaL_checknumber(L, 1)));
+#ifdef LNUM_COMPLEX
+ /* Not in standard <complex.h> , but easy to calculate: log_a(x) = log_b(x) / log_b(a)
+ */
+ lua_pushcomplex(L, _LF(clog) (luaL_checkcomplex(L,1)) / _LF(log) (10));
+#else
+ lua_pushnumber(L, _LF(log10) (luaL_checknumber(L, 1)));
+#endif
return 1;
}
static int math_exp (lua_State *L) {
- lua_pushnumber(L, exp(luaL_checknumber(L, 1)));
+#ifdef LNUM_COMPLEX
+ lua_pushcomplex(L, _LF(cexp) (luaL_checkcomplex(L,1)));
+#else
+ lua_pushnumber(L, _LF(exp) (luaL_checknumber(L, 1)));
+#endif
return 1;
}
@@ -138,19 +234,20 @@ static int math_rad (lua_State *L) {
static int math_frexp (lua_State *L) {
int e;
- lua_pushnumber(L, frexp(luaL_checknumber(L, 1), &e));
+ lua_pushnumber(L, _LF(frexp) (luaL_checknumber(L, 1), &e));
lua_pushinteger(L, e);
return 2;
}
static int math_ldexp (lua_State *L) {
- lua_pushnumber(L, ldexp(luaL_checknumber(L, 1), luaL_checkint(L, 2)));
+ lua_pushnumber(L, _LF(ldexp) (luaL_checknumber(L, 1), luaL_checkint(L, 2)));
return 1;
}
static int math_min (lua_State *L) {
+ /* scalars only */
int n = lua_gettop(L); /* number of arguments */
lua_Number dmin = luaL_checknumber(L, 1);
int i;
@@ -165,6 +262,7 @@ static int math_min (lua_State *L) {
static int math_max (lua_State *L) {
+ /* scalars only */
int n = lua_gettop(L); /* number of arguments */
lua_Number dmax = luaL_checknumber(L, 1);
int i;
@@ -182,25 +280,20 @@ static int math_random (lua_State *L) {
/* the `%' avoids the (rare) case of r==1, and is needed also because on
some systems (SunOS!) `rand()' may return a value larger than RAND_MAX */
lua_Number r = (lua_Number)(rand()%RAND_MAX) / (lua_Number)RAND_MAX;
- switch (lua_gettop(L)) { /* check number of arguments */
- case 0: { /* no arguments */
- lua_pushnumber(L, r); /* Number between 0 and 1 */
- break;
- }
- case 1: { /* only upper limit */
- int u = luaL_checkint(L, 1);
- luaL_argcheck(L, 1<=u, 1, "interval is empty");
- lua_pushnumber(L, floor(r*u)+1); /* int between 1 and `u' */
- break;
- }
- case 2: { /* lower and upper limits */
- int l = luaL_checkint(L, 1);
- int u = luaL_checkint(L, 2);
- luaL_argcheck(L, l<=u, 2, "interval is empty");
- lua_pushnumber(L, floor(r*(u-l+1))+l); /* int between `l' and `u' */
- break;
- }
- default: return luaL_error(L, "wrong number of arguments");
+ int n= lua_gettop(L); /* number of arguments */
+ if (n==0) { /* no arguments: range [0,1) */
+ lua_pushnumber(L, r);
+ } else if (n<=2) { /* int range [1,u] or [l,u] */
+ int l= n==1 ? 1 : luaL_checkint(L, 1);
+ int u = luaL_checkint(L, n);
+ int tmp;
+ lua_Number d;
+ luaL_argcheck(L, l<=u, n, "interval is empty");
+ d= _LF(floor)(r*(u-l+1));
+ lua_number2int(tmp,d);
+ lua_pushinteger(L, l+tmp);
+ } else {
+ return luaL_error(L, "wrong number of arguments");
}
return 1;
}
@@ -211,6 +304,66 @@ static int math_randomseed (lua_State *L
return 0;
}
+/*
+* Lua 5.1 does not have acosh, asinh, atanh for scalars (not ANSI C)
+*/
+#if __STDC_VERSION__ >= 199901L
+static int math_acosh (lua_State *L) {
+# ifdef LNUM_COMPLEX
+ lua_pushcomplex(L, _LF(cacosh) (luaL_checkcomplex(L,1)));
+# else
+ lua_pushnumber(L, _LF(acosh) (luaL_checknumber(L,1)));
+# endif
+ return 1;
+}
+static int math_asinh (lua_State *L) {
+# ifdef LNUM_COMPLEX
+ lua_pushcomplex(L, _LF(casinh) (luaL_checkcomplex(L,1)));
+# else
+ lua_pushnumber(L, _LF(asinh) (luaL_checknumber(L,1)));
+# endif
+ return 1;
+}
+static int math_atanh (lua_State *L) {
+# ifdef LNUM_COMPLEX
+ lua_pushcomplex(L, _LF(catanh) (luaL_checkcomplex(L,1)));
+# else
+ lua_pushnumber(L, _LF(atanh) (luaL_checknumber(L,1)));
+# endif
+ return 1;
+}
+#endif
+
+/*
+ * C99 complex functions, not covered above.
+*/
+#ifdef LNUM_COMPLEX
+static int math_arg (lua_State *L) {
+ lua_pushnumber(L, _LF(carg) (luaL_checkcomplex(L,1)));
+ return 1;
+}
+
+static int math_imag (lua_State *L) {
+ lua_pushnumber(L, _LF(cimag) (luaL_checkcomplex(L,1)));
+ return 1;
+}
+
+static int math_real (lua_State *L) {
+ lua_pushnumber(L, _LF(creal) (luaL_checkcomplex(L,1)));
+ return 1;
+}
+
+static int math_conj (lua_State *L) {
+ lua_pushcomplex(L, _LF(conj) (luaL_checkcomplex(L,1)));
+ return 1;
+}
+
+static int math_proj (lua_State *L) {
+ lua_pushcomplex(L, _LF(cproj) (luaL_checkcomplex(L,1)));
+ return 1;
+}
+#endif
+
static const luaL_Reg mathlib[] = {
{"abs", math_abs},
@@ -241,6 +394,18 @@ static const luaL_Reg mathlib[] = {
{"sqrt", math_sqrt},
{"tanh", math_tanh},
{"tan", math_tan},
+#if __STDC_VERSION__ >= 199901L
+ {"acosh", math_acosh},
+ {"asinh", math_asinh},
+ {"atanh", math_atanh},
+#endif
+#ifdef LNUM_COMPLEX
+ {"arg", math_arg},
+ {"imag", math_imag},
+ {"real", math_real},
+ {"conj", math_conj},
+ {"proj", math_proj},
+#endif
{NULL, NULL}
};
@@ -252,8 +417,10 @@ LUALIB_API int luaopen_math (lua_State *
luaL_register(L, LUA_MATHLIBNAME, mathlib);
lua_pushnumber(L, PI);
lua_setfield(L, -2, "pi");
- lua_pushnumber(L, HUGE_VAL);
+ lua_pushnumber(L, HUGE);
lua_setfield(L, -2, "huge");
+ lua_pushinteger(L, LUA_INTEGER_MAX );
+ lua_setfield(L, -2, "hugeint");
#if defined(LUA_COMPAT_MOD)
lua_getfield(L, -1, "fmod");
lua_setfield(L, -2, "mod");
--- /dev/null
+++ b/src/lnum.c
@@ -0,0 +1,312 @@
+/*
+** $Id: lnum.c,v ... $
+** Internal number model
+** See Copyright Notice in lua.h
+*/
+
+#include <stdlib.h>
+#include <math.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+
+#define lnum_c
+#define LUA_CORE
+
+#include "lua.h"
+#include "llex.h"
+#include "lnum.h"
+
+/*
+** lua_real2str converts a (non-complex) number to a string.
+** lua_str2real converts a string to a (non-complex) number.
+*/
+#define lua_real2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n))
+
+/*
+* Note: Only 'strtod()' is part of ANSI C; others are C99 and
+* may need '--std=c99' compiler setting (at least on Ubuntu 7.10).
+*
+* Visual C++ 2008 Express does not have 'strtof()', nor 'strtold()'.
+* References to '_strtold()' exist but don't compile. It seems best
+* to leave Windows users with DOUBLE only (or compile with MinGW).
+*
+* In practise, using '(long double)strtod' is a risky thing, since
+* it will cause accuracy loss in reading in numbers, and such losses
+* will pile up in later processing. Get a real 'strtold()' or don't
+* use that mode at all.
+*/
+#ifdef LNUM_DOUBLE
+# define lua_str2real strtod
+#elif defined(LNUM_FLOAT)
+# define lua_str2real strtof
+#elif defined(LNUM_LDOUBLE)
+# define lua_str2real strtold
+#endif
+
+#define lua_integer2str(s,v) sprintf((s), LUA_INTEGER_FMT, (v))
+
+/* 's' is expected to be LUAI_MAXNUMBER2STR long (enough for any number)
+*/
+void luaO_num2buf( char *s, const TValue *o )
+{
+ lua_Number n;
+ lua_assert( ttisnumber(o) );
+
+ /* Reason to handle integers differently is not only speed, but accuracy as
+ * well. We want to make any integer tostring() without roundings, at all.
+ */
+ if (ttisint(o)) {
+ lua_integer2str( s, ivalue(o) );
+ return;
+ }
+ n= nvalue_fast(o);
+ lua_real2str(s, n);
+
+#ifdef LNUM_COMPLEX
+ lua_Number n2= nvalue_img_fast(o);
+ if (n2!=0) { /* Postfix with +-Ni */
+ int re0= (n == 0);
+ char *s2= re0 ? s : strchr(s,'\0');
+ if ((!re0) && (n2>0)) *s2++= '+';
+ lua_real2str( s2, n2 );
+ strcat(s2,"i");
+ }
+#endif
+}
+
+/*
+* If a LUA_TNUMBER has integer value, give it.
+*/
+int /*bool*/ tt_integer_valued( const TValue *o, lua_Integer *ref ) {
+ lua_Number d;
+ lua_Integer i;
+
+ lua_assert( ttype(o)==LUA_TNUMBER );
+ lua_assert( ref );
+#ifdef LNUM_COMPLEX
+ if (nvalue_img_fast(o)!=0) return 0;
+#endif
+ d= nvalue_fast(o);
+ lua_number2integer(i, d);
+ if (cast_num(i) == d) {
+ *ref= i; return 1;
+ }
+ return 0;
+}
+
+/*
+ * Lua 5.1.3 (using 'strtod()') allows 0x+hex but not 0+octal. This is good,
+ * and we should NOT use 'autobase' 0 with 'strtoul[l]()' for this reason.
+ *
+ * Lua 5.1.3 allows '0x...' numbers to overflow and lose precision; this is not
+ * good. On Visual C++ 2008, 'strtod()' does not even take them in. Better to
+ * require hex values to fit 'lua_Integer' or give an error that they don't?
+ *
+ * Full hex range (0 .. 0xff..ff) is stored as integers, not to lose any bits.
+ * Numerical value of 0xff..ff will be -1, if used in calculations.
+ *
+ * Returns: TK_INT for a valid integer, '*endptr_ref' updated
+ * TK_NUMBER for seemingly numeric, to be parsed as floating point
+ * 0 for bad characters, not a number (or '0x' out of range)
+ */
+static int luaO_str2i (const char *s, lua_Integer *res, char **endptr_ref) {
+ char *endptr;
+ /* 'v' gets ULONG_MAX on possible overflow (which is > LUA_INTEGER_MAX);
+ * we don't have to check 'errno' here.
+ */
+ unsigned LUA_INTEGER v= lua_str2ul(s, &endptr, 10);
+ if (endptr == s) return 0; /* nothing numeric */
+ if (v==0 && *endptr=='x') {
+ errno= 0; /* needs to be set, 'strtoul[l]' does not clear it */
+ v= lua_str2ul(endptr+1, &endptr, 16); /* retry as hex, unsigned range */
+ if (errno==ERANGE) { /* clamped to 0xff..ff */
+#if (defined(LNUM_INT32) && !defined(LNUM_FLOAT)) || defined(LNUM_LDOUBLE)
+ return TK_NUMBER; /* Allow to be read as floating point (has more integer range) */
+#else
+ return 0; /* Reject the number */
+#endif
+ }
+ } else if ((v > LUA_INTEGER_MAX) || (*endptr && (!isspace(*endptr)))) {
+ return TK_NUMBER; /* not in signed range, or has '.', 'e' etc. trailing */
+ }
+ *res= (lua_Integer)v;
+ *endptr_ref= endptr;
+ return TK_INT;
+}
+
+/* 0 / TK_NUMBER / TK_INT (/ TK_NUMBER2) */
+int luaO_str2d (const char *s, lua_Number *res_n, lua_Integer *res_i) {
+ char *endptr;
+ int ret= TK_NUMBER;
+ /* Check integers first, if caller is allowing.
+ * If 'res2'==NULL, they're only looking for floating point.
+ */
+ if (res_i) {
+ ret= luaO_str2i(s,res_i,&endptr);
+ if (ret==0) return 0;
+ }
+ if (ret==TK_NUMBER) {
+ lua_assert(res_n);
+ /* Note: Visual C++ 2008 Express 'strtod()' does not read in "0x..."
+ * numbers; it will read '0' and spit 'x' as endptr.
+ * This means hex constants not fitting in 'lua_Integer' won't
+ * be read in at all. What to do?
+ */
+ *res_n = lua_str2real(s, &endptr);
+ if (endptr == s) return 0; /* conversion failed */
+ /* Visual C++ 2008 'strtod()' does not allow "0x..." input. */
+#if defined(_MSC_VER) && !defined(LNUM_FLOAT) && !defined(LNUM_INT64)
+ if (*res_n==0 && *endptr=='x') {
+ /* Hex constant too big for 'lua_Integer' but that could fit in 'lua_Number'
+ * integer bits
+ */
+ unsigned __int64 v= _strtoui64( s, &endptr, 16 );
+ /* We just let > 64 bit values be clamped to _UI64_MAX (MSDN does not say 'errno'==ERANGE would be set) */
+ *res_n= cast_num(v);
+ if (*res_n != v) return 0; /* Would have lost accuracy */
+ }
+#endif
+#ifdef LNUM_COMPLEX
+ if (*endptr == 'i') { endptr++; ret= TK_NUMBER2; }
+#endif
+ }
+ if (*endptr) {
+ while (isspace(cast(unsigned char, *endptr))) endptr++;
+ if (*endptr) return 0; /* invalid trail */
+ }
+ return ret;
+}
+
+
+/* Functions for finding out, when integer operations remain in range
+ * (and doing them).
+ */
+int try_addint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) {
+ lua_Integer v= ib+ic; /* may overflow */
+ if (ib>0 && ic>0) { if (v < 0) return 0; /*overflow, use floats*/ }
+ else if (ib<0 && ic<0) { if (v >= 0) return 0; }
+ *r= v;
+ return 1;
+}
+
+int try_subint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) {
+ lua_Integer v= ib-ic; /* may overflow */
+ if (ib>=0 && ic<0) { if (v < 0) return 0; /*overflow, use floats*/ }
+ else if (ib<0 && ic>0) { if (v >= 0) return 0; }
+ *r= v;
+ return 1;
+}
+
+int try_mulint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) {
+ if (ib!=LUA_INTEGER_MIN && ic!=LUA_INTEGER_MIN) {
+ lua_Integer b= luai_abs(ib), c= luai_abs(ic);
+ if ( (ib==0) || (LUA_INTEGER_MAX/b >= c) ) {
+ *r= ib*ic; /* no overflow */
+ return 1;
+ }
+ } else if (ib==0 || ic==0) {
+ *r= 0; return 1;
+ }
+
+ /* Result can be LUA_INTEGER_MIN; if it is, calculating it using floating
+ * point will not cause accuracy loss.
+ */
+ if ( luai_nummul( cast_num(ib), cast_num(ic) ) == LUA_INTEGER_MIN ) {
+ *r= LUA_INTEGER_MIN;
+ return 1;
+ }
+ return 0;
+}
+
+int try_divint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) {
+ /* N/0: leave to float side, to give an error
+ */
+ if (ic==0) return 0;
+
+ /* N/LUA_INTEGER_MIN: always non-integer results, or 0 or +1
+ */
+ if (ic==LUA_INTEGER_MIN) {
+ if (ib==LUA_INTEGER_MIN) { *r=1; return 1; }
+ if (ib==0) { *r=0; return 1; }
+
+ /* LUA_INTEGER_MIN (-2^31|63)/N: calculate using float side (either the division
+ * causes non-integer results, or there is no accuracy loss in int->fp->int
+ * conversions (N=2,4,8,..,256 and N=2^30,2^29,..2^23).
+ */
+ } else if (ib==LUA_INTEGER_MIN) {
+ lua_Number d= luai_numdiv( cast_num(LUA_INTEGER_MIN), cast_num(ic) );
+ lua_Integer i; lua_number2integer(i,d);
+ if (cast_num(i)==d) { *r= i; return 1; }
+
+ } else {
+ /* Note: We _can_ use ANSI C mod here, even on negative values, since
+ * we only test for == 0 (the sign would be implementation dependent).
+ */
+ if (ib%ic == 0) { *r= ib/ic; return 1; }
+ }
+
+ return 0;
+}
+
+int try_modint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) {
+ if (ic!=0) {
+ /* ANSI C can be trusted when b%c==0, or when values are non-negative.
+ * b - (floor(b/c) * c)
+ * -->
+ * + +: b - (b/c) * c (b % c can be used)
+ * - -: b - (b/c) * c (b % c could work, but not defined by ANSI C)
+ * 0 -: b - (b/c) * c (=0, b % c could work, but not defined by ANSI C)
+ * - +: b - (b/c-1) * c (when b!=-c)
+ * + -: b - (b/c-1) * c (when b!=-c)
+ *
+ * o MIN%MIN ends up 0, via overflow in calcs but that does not matter.
+ * o MIN%MAX ends up MAX-1 (and other such numbers), also after overflow,
+ * but that does not matter, results do.
+ */
+ lua_Integer v= ib % ic;
+ if ( v!=0 && (ib<0 || ic<0) ) {
+ v= ib - ((ib/ic) - ((ib<=0 && ic<0) ? 0:1)) * ic;
+ }
+ /* Result should always have same sign as 2nd argument. (PIL2) */
+ lua_assert( (v<0) ? (ic<0) : (v>0) ? (ic>0) : 1 );
+ *r= v;
+ return 1;
+ }
+ return 0; /* let float side return NaN */
+}
+
+int try_powint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) {
+
+ /* In FLOAT/INT32 or FLOAT|DOUBLE/INT64 modes, calculating integer powers
+ * via FP realm may lose accuracy (i.e. 7^11 = 1977326743, which fits int32
+ * but not 23-bit float mantissa).
+ *
+ * The current solution is dumb, but it works and uses little code. Use of
+ * integer powers is not anticipated to be very frequent (apart from 2^x,
+ * which is separately optimized).
+ */
+ if (ib==0) *r=0;
+ else if (ic<0) return 0; /* FP realm */
+ else if (ib==2 && ic < (int)sizeof(lua_Integer)*8-1) *r= ((lua_Integer)1)<<ic; /* 1,2,4,...2^30 | 2^62 optimization */
+ else if (ic==0) *r=1;
+ else if (luai_abs(ib)==1) *r= (ic%2) ? ib:1;
+ else {
+ lua_Integer x= ib;
+ while( --ic ) {
+ if (!try_mulint( &x, x, ib ))
+ return 0; /* FP realm */
+ }
+ *r= x;
+ }
+ return 1;
+}
+
+int try_unmint( lua_Integer *r, lua_Integer ib ) {
+ /* Negating LUA_INTEGER_MIN leaves the range. */
+ if ( ib != LUA_INTEGER_MIN )
+ { *r= -ib; return 1; }
+ return 0;
+}
+
--- /dev/null
+++ b/src/lnum.h
@@ -0,0 +1,116 @@
+/*
+** $Id: lnum.h,v ... $
+** Internal Number model
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lnum_h
+#define lnum_h
+
+#include <math.h>
+
+#include "lobject.h"
+
+/*
+** The luai_num* macros define the primitive operations over 'lua_Number's
+** (not 'lua_Integer's, not 'lua_Complex').
+*/
+#define luai_numadd(a,b) ((a)+(b))
+#define luai_numsub(a,b) ((a)-(b))
+#define luai_nummul(a,b) ((a)*(b))
+#define luai_numdiv(a,b) ((a)/(b))
+#define luai_nummod(a,b) ((a) - _LF(floor)((a)/(b))*(b))
+#define luai_numpow(a,b) (_LF(pow)(a,b))
+#define luai_numunm(a) (-(a))
+#define luai_numeq(a,b) ((a)==(b))
+#define luai_numlt(a,b) ((a)<(b))
+#define luai_numle(a,b) ((a)<=(b))
+#define luai_numisnan(a) (!luai_numeq((a), (a)))
+
+int try_addint( lua_Integer *r, lua_Integer ib, lua_Integer ic );
+int try_subint( lua_Integer *r, lua_Integer ib, lua_Integer ic );
+int try_mulint( lua_Integer *r, lua_Integer ib, lua_Integer ic );
+int try_divint( lua_Integer *r, lua_Integer ib, lua_Integer ic );
+int try_modint( lua_Integer *r, lua_Integer ib, lua_Integer ic );
+int try_powint( lua_Integer *r, lua_Integer ib, lua_Integer ic );
+int try_unmint( lua_Integer *r, lua_Integer ib );
+
+#ifdef LNUM_COMPLEX
+ static inline lua_Complex luai_vectunm( lua_Complex a ) { return -a; }
+ static inline lua_Complex luai_vectadd( lua_Complex a, lua_Complex b ) { return a+b; }
+ static inline lua_Complex luai_vectsub( lua_Complex a, lua_Complex b ) { return a-b; }
+ static inline lua_Complex luai_vectmul( lua_Complex a, lua_Complex b ) { return a*b; }
+ static inline lua_Complex luai_vectdiv( lua_Complex a, lua_Complex b ) { return a/b; }
+
+/*
+ * C99 does not provide modulus for complex numbers. It most likely is not
+ * meaningful at all.
+ */
+
+/*
+ * Complex power
+ *
+ * C99 'cpow' gives inaccurate results for many common cases s.a. (1i)^2 ->
+ * -1+1.2246467991474e-16i (OS X 10.4, gcc 4.0.1 build 5367)
+ *
+ * [(a+bi)^(c+di)] = (r^c) * exp(-d*t) * cos(c*t + d*ln(r)) +
+ * = (r^c) * exp(-d*t) * sin(c*t + d*ln(r)) *i
+ * r = sqrt(a^2+b^2), t = arctan( b/a )
+ *
+ * Reference: <http://home.att.net/~srschmitt/complexnumbers.html>
+ * Could also be calculated using: x^y = exp(ln(x)*y)
+ *
+ * Note: Defined here (and not in .c) so 'lmathlib.c' can share the
+ * implementation.
+ */
+ static inline
+ lua_Complex luai_vectpow( lua_Complex a, lua_Complex b )
+ {
+# if 1
+ lua_Number ar= _LF(creal)(a), ai= _LF(cimag)(a);
+ lua_Number br= _LF(creal)(b), bi= _LF(cimag)(b);
+
+ if (ai==0 && bi==0) { /* a^c (real) */
+ return luai_numpow( ar, br );
+ }
+
+ int br_int= (int)br;
+
+ if ( ai!=0 && bi==0 && br_int==br && br_int!=0 && br_int!=INT_MIN ) {
+ /* (a+bi)^N, N = { +-1,+-2, ... +-INT_MAX }
+ */
+ lua_Number k= luai_numpow( _LF(sqrt) (ar*ar + ai*ai), br );
+ lua_Number cos_z, sin_z;
+
+ /* Situation depends upon c (N) in the following manner:
+ *
+ * N%4==0 => cos(c*t)=1, sin(c*t)=0
+ * (N*sign(b))%4==1 or (N*sign(b))%4==-3 => cos(c*t)=0, sin(c*t)=1
+ * N%4==2 or N%4==-2 => cos(c*t)=-1, sin(c*t)=0
+ * (N*sign(b))%4==-1 or (N*sign(b))%4==3 => cos(c*t)=0, sin(c*t)=-1
+ */
+ int br_int_abs = br_int<0 ? -br_int:br_int;
+
+ switch( (br_int_abs%4) * (br_int<0 ? -1:1) * (ai<0 ? -1:1) ) {
+ case 0: cos_z=1, sin_z=0; break;
+ case 2: case -2: cos_z=-1, sin_z=0; break;
+ case 1: case -3: cos_z=0, sin_z=1; break;
+ case 3: case -1: cos_z=0, sin_z=-1; break;
+ default: lua_assert(0); return 0;
+ }
+ return k*cos_z + (k*sin_z)*I;
+ }
+# endif
+ return _LF(cpow) ( a, b );
+ }
+#endif
+
+LUAI_FUNC int luaO_str2d (const char *s, lua_Number *res1, lua_Integer *res2);
+LUAI_FUNC void luaO_num2buf( char *s, const TValue *o );
+
+LUAI_FUNC int /*bool*/ tt_integer_valued( const TValue *o, lua_Integer *ref );
+
+#define luai_normalize(o) \
+{ lua_Integer _i; if (tt_integer_valued(o,&_i)) setivalue(o,_i); }
+
+#endif
--- /dev/null
+++ b/src/lnum_config.h
@@ -0,0 +1,221 @@
+/*
+** $Id: lnum_config.h,v ... $
+** Internal Number model
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lnum_config_h
+#define lnum_config_h
+
+/*
+** Default number modes
+*/
+#if (!defined LNUM_DOUBLE) && (!defined LNUM_FLOAT) && (!defined LNUM_LDOUBLE)
+# define LNUM_FLOAT
+#endif
+#if (!defined LNUM_INT16) && (!defined LNUM_INT32) && (!defined LNUM_INT64)
+# define LNUM_INT32
+#endif
+
+/*
+** Require C99 mode for COMPLEX, FLOAT and LDOUBLE (only DOUBLE is ANSI C).
+*/
+#if defined(LNUM_COMPLEX) && (__STDC_VERSION__ < 199901L)
+# error "Need C99 for complex (use '--std=c99' or similar)"
+#elif defined(LNUM_LDOUBLE) && (__STDC_VERSION__ < 199901L) && !defined(_MSC_VER)
+# error "Need C99 for 'long double' (use '--std=c99' or similar)"
+#elif defined(LNUM_FLOAT) && (__STDC_VERSION__ < 199901L)
+/* LNUM_FLOAT not supported on Windows */
+# error "Need C99 for 'float' (use '--std=c99' or similar)"
+#endif
+
+/*
+** Number mode identifier to accompany the version string.
+*/
+#ifdef LNUM_COMPLEX
+# define _LNUM1 "complex "
+#else
+# define _LNUM1 ""
+#endif
+#ifdef LNUM_DOUBLE
+# define _LNUM2 "double"
+#elif defined(LNUM_FLOAT)
+# define _LNUM2 "float"
+#elif defined(LNUM_LDOUBLE)
+# define _LNUM2 "ldouble"
+#endif
+#ifdef LNUM_INT32
+# define _LNUM3 "int32"
+#elif defined(LNUM_INT64)
+# define _LNUM3 "int64"
+#elif defined(LNUM_INT16)
+# define _LNUM3 "int16"
+#endif
+#define LUA_LNUM _LNUM1 _LNUM2 " " _LNUM3
+
+/*
+** LUA_NUMBER is the type of floating point number in Lua
+** LUA_NUMBER_SCAN is the format for reading numbers.
+** LUA_NUMBER_FMT is the format for writing numbers.
+*/
+#ifdef LNUM_FLOAT
+# define LUA_NUMBER float
+# define LUA_NUMBER_SCAN "%f"
+# define LUA_NUMBER_FMT "%g"
+#elif (defined LNUM_DOUBLE)
+# define LUA_NUMBER double
+# define LUA_NUMBER_SCAN "%lf"
+# define LUA_NUMBER_FMT "%.14g"
+#elif (defined LNUM_LDOUBLE)
+# define LUA_NUMBER long double
+# define LUA_NUMBER_SCAN "%Lg"
+# define LUA_NUMBER_FMT "%.20Lg"
+#endif
+
+
+/*
+** LUAI_MAXNUMBER2STR: size of a buffer fitting any number->string result.
+**
+** double: 24 (sign, x.xxxxxxxxxxxxxxe+nnnn, and \0)
+** int64: 21 (19 digits, sign, and \0)