b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame] | 1 | --- a/Makefile |
| 2 | +++ b/Makefile |
| 3 | @@ -42,7 +42,7 @@ PLATS= aix ansi bsd freebsd generic linu |
| 4 | |
| 5 | # What to install. |
| 6 | TO_BIN= lua$V luac$V |
| 7 | -TO_INC= lua.h luaconf.h lualib.h lauxlib.h ../etc/lua.hpp |
| 8 | +TO_INC= lua.h luaconf.h lualib.h lauxlib.h lnum_config.h ../etc/lua.hpp |
| 9 | TO_LIB= liblua.a |
| 10 | TO_MAN= lua$V.1 luac$V.1 |
| 11 | |
| 12 | --- a/src/Makefile |
| 13 | +++ b/src/Makefile |
| 14 | @@ -25,7 +25,7 @@ PLATS= aix ansi bsd freebsd generic linu |
| 15 | LUA_A= liblua.a |
| 16 | CORE_O= lapi.o lcode.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o \ |
| 17 | lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o \ |
| 18 | - lundump.o lvm.o lzio.o |
| 19 | + lundump.o lvm.o lzio.o lnum.o |
| 20 | LIB_O= lauxlib.o lbaselib.o ldblib.o liolib.o lmathlib.o loslib.o ltablib.o \ |
| 21 | lstrlib.o loadlib.o linit.o |
| 22 | |
| 23 | @@ -148,6 +148,7 @@ llex.o: llex.c lua.h luaconf.h ldo.h lob |
| 24 | lmathlib.o: lmathlib.c lua.h luaconf.h lauxlib.h lualib.h |
| 25 | lmem.o: lmem.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \ |
| 26 | ltm.h lzio.h lmem.h ldo.h |
| 27 | +lnum.o: lnum.c lua.h llex.h lnum.h |
| 28 | loadlib.o: loadlib.c lua.h luaconf.h lauxlib.h lualib.h |
| 29 | lobject.o: lobject.c lua.h luaconf.h ldo.h lobject.h llimits.h lstate.h \ |
| 30 | ltm.h lzio.h lmem.h lstring.h lgc.h lvm.h |
| 31 | @@ -179,4 +180,18 @@ lzio.o: lzio.c lua.h luaconf.h llimits.h |
| 32 | print.o: print.c ldebug.h lstate.h lua.h luaconf.h lobject.h llimits.h \ |
| 33 | ltm.h lzio.h lmem.h lopcodes.h lundump.h |
| 34 | |
| 35 | +luaconf.h: lnum_config.h |
| 36 | +lapi.c: lnum.h |
| 37 | +lauxlib.c: llimits.h |
| 38 | +lbaselib.c: llimits.h lobject.h lapi.h |
| 39 | +lcode.c: lnum.h |
| 40 | +liolib.c: lnum.h llex.h |
| 41 | +llex.c: lnum.h |
| 42 | +lnum.h: lobject.h |
| 43 | +lobject.c: llex.h lnum.h |
| 44 | +ltable.c: lnum.h |
| 45 | +lua.c: llimits.h |
| 46 | +lvm.c: llex.h lnum.h |
| 47 | +print.c: lnum.h |
| 48 | + |
| 49 | # (end of Makefile) |
| 50 | --- a/src/lapi.c |
| 51 | +++ b/src/lapi.c |
| 52 | @@ -28,7 +28,7 @@ |
| 53 | #include "ltm.h" |
| 54 | #include "lundump.h" |
| 55 | #include "lvm.h" |
| 56 | - |
| 57 | +#include "lnum.h" |
| 58 | |
| 59 | |
| 60 | const char lua_ident[] = |
| 61 | @@ -241,12 +241,13 @@ LUA_API void lua_pushvalue (lua_State *L |
| 62 | |
| 63 | LUA_API int lua_type (lua_State *L, int idx) { |
| 64 | StkId o = index2adr(L, idx); |
| 65 | - return (o == luaO_nilobject) ? LUA_TNONE : ttype(o); |
| 66 | + return (o == luaO_nilobject) ? LUA_TNONE : ttype_ext(o); |
| 67 | } |
| 68 | |
| 69 | |
| 70 | LUA_API const char *lua_typename (lua_State *L, int t) { |
| 71 | UNUSED(L); |
| 72 | + lua_assert( t!= LUA_TINT ); |
| 73 | return (t == LUA_TNONE) ? "no value" : luaT_typenames[t]; |
| 74 | } |
| 75 | |
| 76 | @@ -264,6 +265,14 @@ LUA_API int lua_isnumber (lua_State *L, |
| 77 | } |
| 78 | |
| 79 | |
| 80 | +LUA_API int lua_isinteger (lua_State *L, int idx) { |
| 81 | + TValue tmp; |
| 82 | + lua_Integer dum; |
| 83 | + const TValue *o = index2adr(L, idx); |
| 84 | + return tonumber(o,&tmp) && (ttisint(o) || tt_integer_valued(o,&dum)); |
| 85 | +} |
| 86 | + |
| 87 | + |
| 88 | LUA_API int lua_isstring (lua_State *L, int idx) { |
| 89 | int t = lua_type(L, idx); |
| 90 | return (t == LUA_TSTRING || t == LUA_TNUMBER); |
| 91 | @@ -309,31 +318,66 @@ LUA_API int lua_lessthan (lua_State *L, |
| 92 | } |
| 93 | |
| 94 | |
| 95 | - |
| 96 | LUA_API lua_Number lua_tonumber (lua_State *L, int idx) { |
| 97 | TValue n; |
| 98 | const TValue *o = index2adr(L, idx); |
| 99 | - if (tonumber(o, &n)) |
| 100 | + if (tonumber(o, &n)) { |
| 101 | +#ifdef LNUM_COMPLEX |
| 102 | + if (nvalue_img(o) != 0) |
| 103 | + luaG_runerror(L, "expecting a real number"); |
| 104 | +#endif |
| 105 | return nvalue(o); |
| 106 | - else |
| 107 | - return 0; |
| 108 | + } |
| 109 | + return 0; |
| 110 | } |
| 111 | |
| 112 | |
| 113 | LUA_API lua_Integer lua_tointeger (lua_State *L, int idx) { |
| 114 | TValue n; |
| 115 | + /* Lua 5.1 documented behaviour is to return nonzero for non-integer: |
| 116 | + * "If the number is not an integer, it is truncated in some non-specified way." |
| 117 | + * I would suggest to change this, to return 0 for anything that would |
| 118 | + * not fit in 'lua_Integer'. |
| 119 | + */ |
| 120 | +#ifdef LUA_COMPAT_TOINTEGER |
| 121 | + /* Lua 5.1 compatible */ |
| 122 | const TValue *o = index2adr(L, idx); |
| 123 | if (tonumber(o, &n)) { |
| 124 | - lua_Integer res; |
| 125 | - lua_Number num = nvalue(o); |
| 126 | - lua_number2integer(res, num); |
| 127 | - return res; |
| 128 | + lua_Integer i; |
| 129 | + lua_Number d; |
| 130 | + if (ttisint(o)) return ivalue(o); |
| 131 | + d= nvalue_fast(o); |
| 132 | +# ifdef LNUM_COMPLEX |
| 133 | + if (nvalue_img_fast(o) != 0) |
| 134 | + luaG_runerror(L, "expecting a real number"); |
| 135 | +# endif |
| 136 | + lua_number2integer(i, d); |
| 137 | + return i; |
| 138 | } |
| 139 | - else |
| 140 | - return 0; |
| 141 | +#else |
| 142 | + /* New suggestion */ |
| 143 | + const TValue *o = index2adr(L, idx); |
| 144 | + if (tonumber(o, &n)) { |
| 145 | + lua_Integer i; |
| 146 | + if (ttisint(o)) return ivalue(o); |
| 147 | + if (tt_integer_valued(o,&i)) return i; |
| 148 | + } |
| 149 | +#endif |
| 150 | + return 0; |
| 151 | } |
| 152 | |
| 153 | |
| 154 | +#ifdef LNUM_COMPLEX |
| 155 | +LUA_API lua_Complex lua_tocomplex (lua_State *L, int idx) { |
| 156 | + TValue tmp; |
| 157 | + const TValue *o = index2adr(L, idx); |
| 158 | + if (tonumber(o, &tmp)) |
| 159 | + return nvalue_complex(o); |
| 160 | + return 0; |
| 161 | +} |
| 162 | +#endif |
| 163 | + |
| 164 | + |
| 165 | LUA_API int lua_toboolean (lua_State *L, int idx) { |
| 166 | const TValue *o = index2adr(L, idx); |
| 167 | return !l_isfalse(o); |
| 168 | @@ -364,6 +408,7 @@ LUA_API size_t lua_objlen (lua_State *L, |
| 169 | case LUA_TSTRING: return tsvalue(o)->len; |
| 170 | case LUA_TUSERDATA: return uvalue(o)->len; |
| 171 | case LUA_TTABLE: return luaH_getn(hvalue(o)); |
| 172 | + case LUA_TINT: |
| 173 | case LUA_TNUMBER: { |
| 174 | size_t l; |
| 175 | lua_lock(L); /* `luaV_tostring' may create a new string */ |
| 176 | @@ -426,6 +471,8 @@ LUA_API void lua_pushnil (lua_State *L) |
| 177 | } |
| 178 | |
| 179 | |
| 180 | +/* 'lua_pushnumber()' may lose accuracy on integers, 'lua_pushinteger' will not. |
| 181 | + */ |
| 182 | LUA_API void lua_pushnumber (lua_State *L, lua_Number n) { |
| 183 | lua_lock(L); |
| 184 | setnvalue(L->top, n); |
| 185 | @@ -434,12 +481,22 @@ LUA_API void lua_pushnumber (lua_State * |
| 186 | } |
| 187 | |
| 188 | |
| 189 | -LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) { |
| 190 | +LUA_API void lua_pushinteger (lua_State *L, lua_Integer i) { |
| 191 | + lua_lock(L); |
| 192 | + setivalue(L->top, i); |
| 193 | + api_incr_top(L); |
| 194 | + lua_unlock(L); |
| 195 | +} |
| 196 | + |
| 197 | + |
| 198 | +#ifdef LNUM_COMPLEX |
| 199 | +LUA_API void lua_pushcomplex (lua_State *L, lua_Complex v) { |
| 200 | lua_lock(L); |
| 201 | - setnvalue(L->top, cast_num(n)); |
| 202 | + setnvalue_complex( L->top, v ); |
| 203 | api_incr_top(L); |
| 204 | lua_unlock(L); |
| 205 | } |
| 206 | +#endif |
| 207 | |
| 208 | |
| 209 | LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) { |
| 210 | @@ -569,7 +626,7 @@ LUA_API void lua_rawgeti (lua_State *L, |
| 211 | lua_lock(L); |
| 212 | o = index2adr(L, idx); |
| 213 | api_check(L, ttistable(o)); |
| 214 | - setobj2s(L, L->top, luaH_getnum(hvalue(o), n)); |
| 215 | + setobj2s(L, L->top, luaH_getint(hvalue(o), n)); |
| 216 | api_incr_top(L); |
| 217 | lua_unlock(L); |
| 218 | } |
| 219 | @@ -597,6 +654,9 @@ LUA_API int lua_getmetatable (lua_State |
| 220 | case LUA_TUSERDATA: |
| 221 | mt = uvalue(obj)->metatable; |
| 222 | break; |
| 223 | + case LUA_TINT: |
| 224 | + mt = G(L)->mt[LUA_TNUMBER]; |
| 225 | + break; |
| 226 | default: |
| 227 | mt = G(L)->mt[ttype(obj)]; |
| 228 | break; |
| 229 | @@ -687,7 +747,7 @@ LUA_API void lua_rawseti (lua_State *L, |
| 230 | api_checknelems(L, 1); |
| 231 | o = index2adr(L, idx); |
| 232 | api_check(L, ttistable(o)); |
| 233 | - setobj2t(L, luaH_setnum(L, hvalue(o), n), L->top-1); |
| 234 | + setobj2t(L, luaH_setint(L, hvalue(o), n), L->top-1); |
| 235 | luaC_barriert(L, hvalue(o), L->top-1); |
| 236 | L->top--; |
| 237 | lua_unlock(L); |
| 238 | @@ -721,7 +781,7 @@ LUA_API int lua_setmetatable (lua_State |
| 239 | break; |
| 240 | } |
| 241 | default: { |
| 242 | - G(L)->mt[ttype(obj)] = mt; |
| 243 | + G(L)->mt[ttype_ext(obj)] = mt; |
| 244 | break; |
| 245 | } |
| 246 | } |
| 247 | @@ -1085,3 +1145,32 @@ LUA_API const char *lua_setupvalue (lua_ |
| 248 | return name; |
| 249 | } |
| 250 | |
| 251 | + |
| 252 | +/* Help function for 'luaB_tonumber()', avoids multiple str->number |
| 253 | + * conversions for Lua "tonumber()". |
| 254 | + * |
| 255 | + * Also pushes floating point numbers with integer value as integer, which |
| 256 | + * can be used by 'tonumber()' in scripts to bring values back to integer |
| 257 | + * realm. |
| 258 | + * |
| 259 | + * Note: The 'back to integer realm' is _not_ to affect string conversions: |
| 260 | + * 'tonumber("4294967295.1")' should give a floating point value, although |
| 261 | + * the value would be 4294967296 (and storable in int64 realm). |
| 262 | + */ |
| 263 | +int lua_pushvalue_as_number (lua_State *L, int idx) |
| 264 | +{ |
| 265 | + const TValue *o = index2adr(L, idx); |
| 266 | + TValue tmp; |
| 267 | + lua_Integer i; |
| 268 | + if (ttisnumber(o)) { |
| 269 | + if ( (!ttisint(o)) && tt_integer_valued(o,&i)) { |
| 270 | + lua_pushinteger( L, i ); |
| 271 | + return 1; |
| 272 | + } |
| 273 | + } else if (!tonumber(o, &tmp)) { |
| 274 | + return 0; |
| 275 | + } |
| 276 | + if (ttisint(o)) lua_pushinteger( L, ivalue(o) ); |
| 277 | + else lua_pushnumber( L, nvalue_fast(o) ); |
| 278 | + return 1; |
| 279 | +} |
| 280 | --- a/src/lapi.h |
| 281 | +++ b/src/lapi.h |
| 282 | @@ -13,4 +13,6 @@ |
| 283 | |
| 284 | LUAI_FUNC void luaA_pushobject (lua_State *L, const TValue *o); |
| 285 | |
| 286 | +int lua_pushvalue_as_number (lua_State *L, int idx); |
| 287 | + |
| 288 | #endif |
| 289 | --- a/src/lauxlib.c |
| 290 | +++ b/src/lauxlib.c |
| 291 | @@ -23,7 +23,7 @@ |
| 292 | #include "lua.h" |
| 293 | |
| 294 | #include "lauxlib.h" |
| 295 | - |
| 296 | +#include "llimits.h" |
| 297 | |
| 298 | #define FREELIST_REF 0 /* free list of references */ |
| 299 | |
| 300 | @@ -66,7 +66,7 @@ LUALIB_API int luaL_typerror (lua_State |
| 301 | |
| 302 | |
| 303 | static void tag_error (lua_State *L, int narg, int tag) { |
| 304 | - luaL_typerror(L, narg, lua_typename(L, tag)); |
| 305 | + luaL_typerror(L, narg, tag==LUA_TINT ? "integer" : lua_typename(L, tag)); |
| 306 | } |
| 307 | |
| 308 | |
| 309 | @@ -188,8 +188,8 @@ LUALIB_API lua_Number luaL_optnumber (lu |
| 310 | |
| 311 | LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) { |
| 312 | lua_Integer d = lua_tointeger(L, narg); |
| 313 | - if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */ |
| 314 | - tag_error(L, narg, LUA_TNUMBER); |
| 315 | + if (d == 0 && !lua_isinteger(L, narg)) /* avoid extra test when d is not 0 */ |
| 316 | + tag_error(L, narg, LUA_TINT); |
| 317 | return d; |
| 318 | } |
| 319 | |
| 320 | @@ -200,6 +200,16 @@ LUALIB_API lua_Integer luaL_optinteger ( |
| 321 | } |
| 322 | |
| 323 | |
| 324 | +#ifdef LNUM_COMPLEX |
| 325 | +LUALIB_API lua_Complex luaL_checkcomplex (lua_State *L, int narg) { |
| 326 | + lua_Complex c = lua_tocomplex(L, narg); |
| 327 | + if (c == 0 && !lua_isnumber(L, narg)) /* avoid extra test when c is not 0 */ |
| 328 | + tag_error(L, narg, LUA_TNUMBER); |
| 329 | + return c; |
| 330 | +} |
| 331 | +#endif |
| 332 | + |
| 333 | + |
| 334 | LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) { |
| 335 | if (!lua_getmetatable(L, obj)) /* no metatable? */ |
| 336 | return 0; |
| 337 | --- a/src/lauxlib.h |
| 338 | +++ b/src/lauxlib.h |
| 339 | @@ -57,6 +57,12 @@ LUALIB_API lua_Number (luaL_optnumber) ( |
| 340 | LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg); |
| 341 | LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg, |
| 342 | lua_Integer def); |
| 343 | +#define luaL_checkint32(L,narg) ((int)luaL_checkinteger(L,narg)) |
| 344 | +#define luaL_optint32(L,narg,def) ((int)luaL_optinteger(L,narg,def)) |
| 345 | + |
| 346 | +#ifdef LNUM_COMPLEX |
| 347 | + LUALIB_API lua_Complex (luaL_checkcomplex) (lua_State *L, int narg); |
| 348 | +#endif |
| 349 | |
| 350 | LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg); |
| 351 | LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t); |
| 352 | --- a/src/lbaselib.c |
| 353 | +++ b/src/lbaselib.c |
| 354 | @@ -18,7 +18,9 @@ |
| 355 | |
| 356 | #include "lauxlib.h" |
| 357 | #include "lualib.h" |
| 358 | - |
| 359 | +#include "llimits.h" |
| 360 | +#include "lobject.h" |
| 361 | +#include "lapi.h" |
| 362 | |
| 363 | |
| 364 | |
| 365 | @@ -54,20 +56,25 @@ static int luaB_tonumber (lua_State *L) |
| 366 | int base = luaL_optint(L, 2, 10); |
| 367 | if (base == 10) { /* standard conversion */ |
| 368 | luaL_checkany(L, 1); |
| 369 | - if (lua_isnumber(L, 1)) { |
| 370 | - lua_pushnumber(L, lua_tonumber(L, 1)); |
| 371 | + if (lua_isnumber(L, 1)) { /* numeric string, or a number */ |
| 372 | + lua_pushvalue_as_number(L,1); /* API extension (not to lose accuracy here) */ |
| 373 | return 1; |
| 374 | - } |
| 375 | + } |
| 376 | } |
| 377 | else { |
| 378 | const char *s1 = luaL_checkstring(L, 1); |
| 379 | char *s2; |
| 380 | - unsigned long n; |
| 381 | + unsigned LUA_INTEGER n; |
| 382 | luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); |
| 383 | - n = strtoul(s1, &s2, base); |
| 384 | + n = lua_str2ul(s1, &s2, base); |
| 385 | if (s1 != s2) { /* at least one valid digit? */ |
| 386 | while (isspace((unsigned char)(*s2))) s2++; /* skip trailing spaces */ |
| 387 | if (*s2 == '\0') { /* no invalid trailing characters? */ |
| 388 | + |
| 389 | + /* Push as number, there needs to be separate 'luaB_tointeger' for |
| 390 | + * when the caller wants to preserve the bits (matters if unsigned |
| 391 | + * values are used). |
| 392 | + */ |
| 393 | lua_pushnumber(L, (lua_Number)n); |
| 394 | return 1; |
| 395 | } |
| 396 | @@ -144,7 +151,7 @@ static int luaB_setfenv (lua_State *L) { |
| 397 | luaL_checktype(L, 2, LUA_TTABLE); |
| 398 | getfunc(L, 0); |
| 399 | lua_pushvalue(L, 2); |
| 400 | - if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0) { |
| 401 | + if (lua_isnumber(L, 1) && lua_tointeger(L, 1) == 0) { |
| 402 | /* change environment of current thread */ |
| 403 | lua_pushthread(L); |
| 404 | lua_insert(L, -2); |
| 405 | @@ -209,7 +216,7 @@ static int luaB_collectgarbage (lua_Stat |
| 406 | return 1; |
| 407 | } |
| 408 | default: { |
| 409 | - lua_pushnumber(L, res); |
| 410 | + lua_pushinteger(L, res); |
| 411 | return 1; |
| 412 | } |
| 413 | } |
| 414 | @@ -631,6 +638,8 @@ static void base_open (lua_State *L) { |
| 415 | luaL_register(L, "_G", base_funcs); |
| 416 | lua_pushliteral(L, LUA_VERSION); |
| 417 | lua_setglobal(L, "_VERSION"); /* set global _VERSION */ |
| 418 | + lua_pushliteral(L, LUA_LNUM); |
| 419 | + lua_setglobal(L, "_LNUM"); /* "[complex] double|float|ldouble int32|int64" */ |
| 420 | /* `ipairs' and `pairs' need auxiliary functions as upvalues */ |
| 421 | auxopen(L, "ipairs", luaB_ipairs, ipairsaux); |
| 422 | auxopen(L, "pairs", luaB_pairs, luaB_next); |
| 423 | --- a/src/lcode.c |
| 424 | +++ b/src/lcode.c |
| 425 | @@ -22,13 +22,18 @@ |
| 426 | #include "lopcodes.h" |
| 427 | #include "lparser.h" |
| 428 | #include "ltable.h" |
| 429 | +#include "lnum.h" |
| 430 | |
| 431 | |
| 432 | #define hasjumps(e) ((e)->t != (e)->f) |
| 433 | |
| 434 | - |
| 435 | static int isnumeral(expdesc *e) { |
| 436 | - return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP); |
| 437 | + int ek= |
| 438 | +#ifdef LNUM_COMPLEX |
| 439 | + (e->k == VKNUM2) || |
| 440 | +#endif |
| 441 | + (e->k == VKINT) || (e->k == VKNUM); |
| 442 | + return (ek && e->t == NO_JUMP && e->f == NO_JUMP); |
| 443 | } |
| 444 | |
| 445 | |
| 446 | @@ -231,12 +236,16 @@ static int addk (FuncState *fs, TValue * |
| 447 | TValue *idx = luaH_set(L, fs->h, k); |
| 448 | Proto *f = fs->f; |
| 449 | int oldsize = f->sizek; |
| 450 | - if (ttisnumber(idx)) { |
| 451 | - lua_assert(luaO_rawequalObj(&fs->f->k[cast_int(nvalue(idx))], v)); |
| 452 | - return cast_int(nvalue(idx)); |
| 453 | + if (ttype(idx)==LUA_TNUMBER) { |
| 454 | + luai_normalize(idx); |
| 455 | + lua_assert( ttype(idx)==LUA_TINT ); /* had no fraction */ |
| 456 | + } |
| 457 | + if (ttisint(idx)) { |
| 458 | + lua_assert(luaO_rawequalObj(&fs->f->k[ivalue(idx)], v)); |
| 459 | + return cast_int(ivalue(idx)); |
| 460 | } |
| 461 | else { /* constant not found; create a new entry */ |
| 462 | - setnvalue(idx, cast_num(fs->nk)); |
| 463 | + setivalue(idx, fs->nk); |
| 464 | luaM_growvector(L, f->k, fs->nk, f->sizek, TValue, |
| 465 | MAXARG_Bx, "constant table overflow"); |
| 466 | while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); |
| 467 | @@ -261,6 +270,21 @@ int luaK_numberK (FuncState *fs, lua_Num |
| 468 | } |
| 469 | |
| 470 | |
| 471 | +int luaK_integerK (FuncState *fs, lua_Integer r) { |
| 472 | + TValue o; |
| 473 | + setivalue(&o, r); |
| 474 | + return addk(fs, &o, &o); |
| 475 | +} |
| 476 | + |
| 477 | + |
| 478 | +#ifdef LNUM_COMPLEX |
| 479 | +static int luaK_imagK (FuncState *fs, lua_Number r) { |
| 480 | + TValue o; |
| 481 | + setnvalue_complex(&o, r*I); |
| 482 | + return addk(fs, &o, &o); |
| 483 | +} |
| 484 | +#endif |
| 485 | + |
| 486 | static int boolK (FuncState *fs, int b) { |
| 487 | TValue o; |
| 488 | setbvalue(&o, b); |
| 489 | @@ -359,6 +383,16 @@ static void discharge2reg (FuncState *fs |
| 490 | luaK_codeABx(fs, OP_LOADK, reg, luaK_numberK(fs, e->u.nval)); |
| 491 | break; |
| 492 | } |
| 493 | + case VKINT: { |
| 494 | + luaK_codeABx(fs, OP_LOADK, reg, luaK_integerK(fs, e->u.ival)); |
| 495 | + break; |
| 496 | + } |
| 497 | +#ifdef LNUM_COMPLEX |
| 498 | + case VKNUM2: { |
| 499 | + luaK_codeABx(fs, OP_LOADK, reg, luaK_imagK(fs, e->u.nval)); |
| 500 | + break; |
| 501 | + } |
| 502 | +#endif |
| 503 | case VRELOCABLE: { |
| 504 | Instruction *pc = &getcode(fs, e); |
| 505 | SETARG_A(*pc, reg); |
| 506 | @@ -444,6 +478,10 @@ void luaK_exp2val (FuncState *fs, expdes |
| 507 | int luaK_exp2RK (FuncState *fs, expdesc *e) { |
| 508 | luaK_exp2val(fs, e); |
| 509 | switch (e->k) { |
| 510 | +#ifdef LNUM_COMPLEX |
| 511 | + case VKNUM2: |
| 512 | +#endif |
| 513 | + case VKINT: |
| 514 | case VKNUM: |
| 515 | case VTRUE: |
| 516 | case VFALSE: |
| 517 | @@ -451,6 +489,10 @@ int luaK_exp2RK (FuncState *fs, expdesc |
| 518 | if (fs->nk <= MAXINDEXRK) { /* constant fit in RK operand? */ |
| 519 | e->u.s.info = (e->k == VNIL) ? nilK(fs) : |
| 520 | (e->k == VKNUM) ? luaK_numberK(fs, e->u.nval) : |
| 521 | + (e->k == VKINT) ? luaK_integerK(fs, e->u.ival) : |
| 522 | +#ifdef LNUM_COMPLEX |
| 523 | + (e->k == VKNUM2) ? luaK_imagK(fs, e->u.nval) : |
| 524 | +#endif |
| 525 | boolK(fs, (e->k == VTRUE)); |
| 526 | e->k = VK; |
| 527 | return RKASK(e->u.s.info); |
| 528 | @@ -540,7 +582,10 @@ void luaK_goiftrue (FuncState *fs, expde |
| 529 | int pc; /* pc of last jump */ |
| 530 | luaK_dischargevars(fs, e); |
| 531 | switch (e->k) { |
| 532 | - case VK: case VKNUM: case VTRUE: { |
| 533 | +#ifdef LNUM_COMPLEX |
| 534 | + case VKNUM2: |
| 535 | +#endif |
| 536 | + case VKINT: case VK: case VKNUM: case VTRUE: { |
| 537 | pc = NO_JUMP; /* always true; do nothing */ |
| 538 | break; |
| 539 | } |
| 540 | @@ -590,7 +635,10 @@ static void codenot (FuncState *fs, expd |
| 541 | e->k = VTRUE; |
| 542 | break; |
| 543 | } |
| 544 | - case VK: case VKNUM: case VTRUE: { |
| 545 | +#ifdef LNUM_COMPLEX |
| 546 | + case VKNUM2: |
| 547 | +#endif |
| 548 | + case VKINT: case VK: case VKNUM: case VTRUE: { |
| 549 | e->k = VFALSE; |
| 550 | break; |
| 551 | } |
| 552 | @@ -626,25 +674,70 @@ void luaK_indexed (FuncState *fs, expdes |
| 553 | |
| 554 | static int constfolding (OpCode op, expdesc *e1, expdesc *e2) { |
| 555 | lua_Number v1, v2, r; |
| 556 | + int vkres= VKNUM; |
| 557 | if (!isnumeral(e1) || !isnumeral(e2)) return 0; |
| 558 | - v1 = e1->u.nval; |
| 559 | - v2 = e2->u.nval; |
| 560 | + |
| 561 | + /* real and imaginary parts don't mix. */ |
| 562 | +#ifdef LNUM_COMPLEX |
| 563 | + if (e1->k == VKNUM2) { |
| 564 | + if ((op != OP_UNM) && (e2->k != VKNUM2)) return 0; |
| 565 | + vkres= VKNUM2; } |
| 566 | + else if (e2->k == VKNUM2) { return 0; } |
| 567 | +#endif |
| 568 | + if ((e1->k == VKINT) && (e2->k == VKINT)) { |
| 569 | + lua_Integer i1= e1->u.ival, i2= e2->u.ival; |
| 570 | + lua_Integer rr; |
| 571 | + int done= 0; |
| 572 | + /* Integer/integer calculations (may end up producing floating point) */ |
| 573 | + switch (op) { |
| 574 | + case OP_ADD: done= try_addint( &rr, i1, i2 ); break; |
| 575 | + case OP_SUB: done= try_subint( &rr, i1, i2 ); break; |
| 576 | + case OP_MUL: done= try_mulint( &rr, i1, i2 ); break; |
| 577 | + case OP_DIV: done= try_divint( &rr, i1, i2 ); break; |
| 578 | + case OP_MOD: done= try_modint( &rr, i1, i2 ); break; |
| 579 | + case OP_POW: done= try_powint( &rr, i1, i2 ); break; |
| 580 | + case OP_UNM: done= try_unmint( &rr, i1 ); break; |
| 581 | + default: done= 0; break; |
| 582 | + } |
| 583 | + if (done) { |
| 584 | + e1->u.ival = rr; /* remained within integer range */ |
| 585 | + return 1; |
| 586 | + } |
| 587 | + } |
| 588 | + v1 = (e1->k == VKINT) ? ((lua_Number)e1->u.ival) : e1->u.nval; |
| 589 | + v2 = (e2->k == VKINT) ? ((lua_Number)e2->u.ival) : e2->u.nval; |
| 590 | + |
| 591 | switch (op) { |
| 592 | case OP_ADD: r = luai_numadd(v1, v2); break; |
| 593 | case OP_SUB: r = luai_numsub(v1, v2); break; |
| 594 | - case OP_MUL: r = luai_nummul(v1, v2); break; |
| 595 | + case OP_MUL: |
| 596 | +#ifdef LNUM_COMPLEX |
| 597 | + if (vkres==VKNUM2) return 0; /* leave to runtime (could do here, but not worth it?) */ |
| 598 | +#endif |
| 599 | + r = luai_nummul(v1, v2); break; |
| 600 | case OP_DIV: |
| 601 | if (v2 == 0) return 0; /* do not attempt to divide by 0 */ |
| 602 | - r = luai_numdiv(v1, v2); break; |
| 603 | +#ifdef LNUM_COMPLEX |
| 604 | + if (vkres==VKNUM2) return 0; /* leave to runtime */ |
| 605 | +#endif |
| 606 | + r = luai_numdiv(v1, v2); break; |
| 607 | case OP_MOD: |
| 608 | if (v2 == 0) return 0; /* do not attempt to divide by 0 */ |
| 609 | +#ifdef LNUM_COMPLEX |
| 610 | + if (vkres==VKNUM2) return 0; /* leave to runtime */ |
| 611 | +#endif |
| 612 | r = luai_nummod(v1, v2); break; |
| 613 | - case OP_POW: r = luai_numpow(v1, v2); break; |
| 614 | + case OP_POW: |
| 615 | +#ifdef LNUM_COMPLEX |
| 616 | + if (vkres==VKNUM2) return 0; /* leave to runtime */ |
| 617 | +#endif |
| 618 | + r = luai_numpow(v1, v2); break; |
| 619 | case OP_UNM: r = luai_numunm(v1); break; |
| 620 | case OP_LEN: return 0; /* no constant folding for 'len' */ |
| 621 | default: lua_assert(0); r = 0; break; |
| 622 | } |
| 623 | if (luai_numisnan(r)) return 0; /* do not attempt to produce NaN */ |
| 624 | + e1->k = cast(expkind,vkres); |
| 625 | e1->u.nval = r; |
| 626 | return 1; |
| 627 | } |
| 628 | @@ -688,7 +781,8 @@ static void codecomp (FuncState *fs, OpC |
| 629 | |
| 630 | void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) { |
| 631 | expdesc e2; |
| 632 | - e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0; |
| 633 | + e2.t = e2.f = NO_JUMP; e2.k = VKINT; e2.u.ival = 0; |
| 634 | + |
| 635 | switch (op) { |
| 636 | case OPR_MINUS: { |
| 637 | if (!isnumeral(e)) |
| 638 | --- a/src/lcode.h |
| 639 | +++ b/src/lcode.h |
| 640 | @@ -71,6 +71,6 @@ LUAI_FUNC void luaK_prefix (FuncState *f |
| 641 | LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v); |
| 642 | LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, expdesc *v2); |
| 643 | LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore); |
| 644 | - |
| 645 | +LUAI_FUNC int luaK_integerK (FuncState *fs, lua_Integer r); |
| 646 | |
| 647 | #endif |
| 648 | --- a/src/ldebug.c |
| 649 | +++ b/src/ldebug.c |
| 650 | @@ -183,7 +183,7 @@ static void collectvalidlines (lua_State |
| 651 | int *lineinfo = f->l.p->lineinfo; |
| 652 | int i; |
| 653 | for (i=0; i<f->l.p->sizelineinfo; i++) |
| 654 | - setbvalue(luaH_setnum(L, t, lineinfo[i]), 1); |
| 655 | + setbvalue(luaH_setint(L, t, lineinfo[i]), 1); |
| 656 | sethvalue(L, L->top, t); |
| 657 | } |
| 658 | incr_top(L); |
| 659 | @@ -566,7 +566,7 @@ static int isinstack (CallInfo *ci, cons |
| 660 | |
| 661 | void luaG_typeerror (lua_State *L, const TValue *o, const char *op) { |
| 662 | const char *name = NULL; |
| 663 | - const char *t = luaT_typenames[ttype(o)]; |
| 664 | + const char *t = luaT_typenames[ttype_ext(o)]; |
| 665 | const char *kind = (isinstack(L->ci, o)) ? |
| 666 | getobjname(L, L->ci, cast_int(o - L->base), &name) : |
| 667 | NULL; |
| 668 | @@ -594,8 +594,8 @@ void luaG_aritherror (lua_State *L, cons |
| 669 | |
| 670 | |
| 671 | int luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) { |
| 672 | - const char *t1 = luaT_typenames[ttype(p1)]; |
| 673 | - const char *t2 = luaT_typenames[ttype(p2)]; |
| 674 | + const char *t1 = luaT_typenames[ttype_ext(p1)]; |
| 675 | + const char *t2 = luaT_typenames[ttype_ext(p2)]; |
| 676 | if (t1[2] == t2[2]) |
| 677 | luaG_runerror(L, "attempt to compare two %s values", t1); |
| 678 | else |
| 679 | --- a/src/ldo.c |
| 680 | +++ b/src/ldo.c |
| 681 | @@ -220,9 +220,9 @@ static StkId adjust_varargs (lua_State * |
| 682 | luaD_checkstack(L, p->maxstacksize); |
| 683 | htab = luaH_new(L, nvar, 1); /* create `arg' table */ |
| 684 | for (i=0; i<nvar; i++) /* put extra arguments into `arg' table */ |
| 685 | - setobj2n(L, luaH_setnum(L, htab, i+1), L->top - nvar + i); |
| 686 | + setobj2n(L, luaH_setint(L, htab, i+1), L->top - nvar + i); |
| 687 | /* store counter in field `n' */ |
| 688 | - setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), cast_num(nvar)); |
| 689 | + setivalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), nvar); |
| 690 | } |
| 691 | #endif |
| 692 | /* move fixed parameters to final position */ |
| 693 | --- a/src/ldump.c |
| 694 | +++ b/src/ldump.c |
| 695 | @@ -52,6 +52,11 @@ static void DumpNumber(lua_Number x, Dum |
| 696 | DumpVar(x,D); |
| 697 | } |
| 698 | |
| 699 | +static void DumpInteger(lua_Integer x, DumpState* D) |
| 700 | +{ |
| 701 | + DumpVar(x,D); |
| 702 | +} |
| 703 | + |
| 704 | static void DumpVector(const void* b, int n, size_t size, DumpState* D) |
| 705 | { |
| 706 | DumpInt(n,D); |
| 707 | @@ -93,8 +98,11 @@ static void DumpConstants(const Proto* f |
| 708 | DumpChar(bvalue(o),D); |
| 709 | break; |
| 710 | case LUA_TNUMBER: |
| 711 | - DumpNumber(nvalue(o),D); |
| 712 | + DumpNumber(nvalue_fast(o),D); |
| 713 | break; |
| 714 | + case LUA_TINT: |
| 715 | + DumpInteger(ivalue(o),D); |
| 716 | + break; |
| 717 | case LUA_TSTRING: |
| 718 | DumpString(rawtsvalue(o),D); |
| 719 | break; |
| 720 | --- a/src/liolib.c |
| 721 | +++ b/src/liolib.c |
| 722 | @@ -9,6 +9,7 @@ |
| 723 | #include <stdio.h> |
| 724 | #include <stdlib.h> |
| 725 | #include <string.h> |
| 726 | +#include <ctype.h> |
| 727 | |
| 728 | #define liolib_c |
| 729 | #define LUA_LIB |
| 730 | @@ -18,7 +19,8 @@ |
| 731 | #include "lauxlib.h" |
| 732 | #include "lualib.h" |
| 733 | |
| 734 | - |
| 735 | +#include "lnum.h" |
| 736 | +#include "llex.h" |
| 737 | |
| 738 | #define IO_INPUT 1 |
| 739 | #define IO_OUTPUT 2 |
| 740 | @@ -269,6 +271,13 @@ static int io_lines (lua_State *L) { |
| 741 | ** ======================================================= |
| 742 | */ |
| 743 | |
| 744 | +/* |
| 745 | +* Many problems if we intend the same 'n' format specifier (see 'file:read()') |
| 746 | +* to work for both FP and integer numbers, without losing their accuracy. So |
| 747 | +* we don't. 'n' reads numbers as floating points, 'i' as integers. Old code |
| 748 | +* remains valid, but won't provide full integer accuracy (this only matters |
| 749 | +* with float FP and/or 64-bit integers). |
| 750 | +*/ |
| 751 | |
| 752 | static int read_number (lua_State *L, FILE *f) { |
| 753 | lua_Number d; |
| 754 | @@ -282,6 +291,43 @@ static int read_number (lua_State *L, FI |
| 755 | } |
| 756 | } |
| 757 | |
| 758 | +static int read_integer (lua_State *L, FILE *f) { |
| 759 | + lua_Integer i; |
| 760 | + if (fscanf(f, LUA_INTEGER_SCAN, &i) == 1) { |
| 761 | + lua_pushinteger(L, i); |
| 762 | + return 1; |
| 763 | + } |
| 764 | + else return 0; /* read fails */ |
| 765 | +} |
| 766 | + |
| 767 | +#ifdef LNUM_COMPLEX |
| 768 | +static int read_complex (lua_State *L, FILE *f) { |
| 769 | + /* NNN / NNNi / NNN+MMMi / NNN-MMMi */ |
| 770 | + lua_Number a,b; |
| 771 | + if (fscanf(f, LUA_NUMBER_SCAN, &a) == 1) { |
| 772 | + int c=fgetc(f); |
| 773 | + switch(c) { |
| 774 | + case 'i': |
| 775 | + lua_pushcomplex(L, a*I); |
| 776 | + return 1; |
| 777 | + case '+': |
| 778 | + case '-': |
| 779 | + /* "i" is consumed if at the end; just 'NNN+MMM' will most likely |
| 780 | + * behave as if "i" was there? (TBD: test) |
| 781 | + */ |
| 782 | + if (fscanf(f, LUA_NUMBER_SCAN "i", &b) == 1) { |
| 783 | + lua_pushcomplex(L, a+ (c=='+' ? b:-b)*I); |
| 784 | + return 1; |
| 785 | + } |
| 786 | + } |
| 787 | + ungetc( c,f ); |
| 788 | + lua_pushnumber(L,a); /*real part only*/ |
| 789 | + return 1; |
| 790 | + } |
| 791 | + return 0; /* read fails */ |
| 792 | +} |
| 793 | +#endif |
| 794 | + |
| 795 | |
| 796 | static int test_eof (lua_State *L, FILE *f) { |
| 797 | int c = getc(f); |
| 798 | @@ -355,6 +401,14 @@ static int g_read (lua_State *L, FILE *f |
| 799 | case 'n': /* number */ |
| 800 | success = read_number(L, f); |
| 801 | break; |
| 802 | + case 'i': /* integer (full accuracy) */ |
| 803 | + success = read_integer(L, f); |
| 804 | + break; |
| 805 | +#ifdef LNUM_COMPLEX |
| 806 | + case 'c': /* complex */ |
| 807 | + success = read_complex(L, f); |
| 808 | + break; |
| 809 | +#endif |
| 810 | case 'l': /* line */ |
| 811 | success = read_line(L, f); |
| 812 | break; |
| 813 | @@ -415,9 +469,10 @@ static int g_write (lua_State *L, FILE * |
| 814 | int status = 1; |
| 815 | for (; nargs--; arg++) { |
| 816 | if (lua_type(L, arg) == LUA_TNUMBER) { |
| 817 | - /* optimization: could be done exactly as for strings */ |
| 818 | - status = status && |
| 819 | - fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0; |
| 820 | + if (lua_isinteger(L,arg)) |
| 821 | + status = status && fprintf(f, LUA_INTEGER_FMT, lua_tointeger(L, arg)) > 0; |
| 822 | + else |
| 823 | + status = status && fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0; |
| 824 | } |
| 825 | else { |
| 826 | size_t l; |
| 827 | @@ -460,7 +515,7 @@ static int f_setvbuf (lua_State *L) { |
| 828 | static const char *const modenames[] = {"no", "full", "line", NULL}; |
| 829 | FILE *f = tofile(L); |
| 830 | int op = luaL_checkoption(L, 2, NULL, modenames); |
| 831 | - lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE); |
| 832 | + size_t sz = luaL_optint32(L, 3, LUAL_BUFFERSIZE); |
| 833 | int res = setvbuf(f, NULL, mode[op], sz); |
| 834 | return pushresult(L, res == 0, NULL); |
| 835 | } |
| 836 | --- a/src/llex.c |
| 837 | +++ b/src/llex.c |
| 838 | @@ -22,6 +22,7 @@ |
| 839 | #include "lstring.h" |
| 840 | #include "ltable.h" |
| 841 | #include "lzio.h" |
| 842 | +#include "lnum.h" |
| 843 | |
| 844 | |
| 845 | |
| 846 | @@ -34,13 +35,17 @@ |
| 847 | |
| 848 | |
| 849 | /* ORDER RESERVED */ |
| 850 | -const char *const luaX_tokens [] = { |
| 851 | +static const char *const luaX_tokens [] = { |
| 852 | "and", "break", "do", "else", "elseif", |
| 853 | "end", "false", "for", "function", "if", |
| 854 | "in", "local", "nil", "not", "or", "repeat", |
| 855 | "return", "then", "true", "until", "while", |
| 856 | "..", "...", "==", ">=", "<=", "~=", |
| 857 | "<number>", "<name>", "<string>", "<eof>", |
| 858 | + "<integer>", |
| 859 | +#ifdef LNUM_COMPLEX |
| 860 | + "<number2>", |
| 861 | +#endif |
| 862 | NULL |
| 863 | }; |
| 864 | |
| 865 | @@ -90,7 +95,11 @@ static const char *txtToken (LexState *l |
| 866 | switch (token) { |
| 867 | case TK_NAME: |
| 868 | case TK_STRING: |
| 869 | + case TK_INT: |
| 870 | case TK_NUMBER: |
| 871 | +#ifdef LNUM_COMPLEX |
| 872 | + case TK_NUMBER2: |
| 873 | +#endif |
| 874 | save(ls, '\0'); |
| 875 | return luaZ_buffer(ls->buff); |
| 876 | default: |
| 877 | @@ -175,23 +184,27 @@ static void buffreplace (LexState *ls, c |
| 878 | if (p[n] == from) p[n] = to; |
| 879 | } |
| 880 | |
| 881 | - |
| 882 | -static void trydecpoint (LexState *ls, SemInfo *seminfo) { |
| 883 | +/* TK_NUMBER (/ TK_NUMBER2) */ |
| 884 | +static int trydecpoint (LexState *ls, SemInfo *seminfo) { |
| 885 | /* format error: try to update decimal point separator */ |
| 886 | struct lconv *cv = localeconv(); |
| 887 | char old = ls->decpoint; |
| 888 | + int ret; |
| 889 | ls->decpoint = (cv ? cv->decimal_point[0] : '.'); |
| 890 | buffreplace(ls, old, ls->decpoint); /* try updated decimal separator */ |
| 891 | - if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) { |
| 892 | + ret= luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r, NULL); |
| 893 | + if (!ret) { |
| 894 | /* format error with correct decimal point: no more options */ |
| 895 | buffreplace(ls, ls->decpoint, '.'); /* undo change (for error message) */ |
| 896 | luaX_lexerror(ls, "malformed number", TK_NUMBER); |
| 897 | } |
| 898 | + return ret; |
| 899 | } |
| 900 | |
| 901 | |
| 902 | -/* LUA_NUMBER */ |
| 903 | -static void read_numeral (LexState *ls, SemInfo *seminfo) { |
| 904 | +/* TK_NUMBER / TK_INT (/TK_NUMBER2) */ |
| 905 | +static int read_numeral (LexState *ls, SemInfo *seminfo) { |
| 906 | + int ret; |
| 907 | lua_assert(isdigit(ls->current)); |
| 908 | do { |
| 909 | save_and_next(ls); |
| 910 | @@ -202,8 +215,9 @@ static void read_numeral (LexState *ls, |
| 911 | save_and_next(ls); |
| 912 | save(ls, '\0'); |
| 913 | buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */ |
| 914 | - if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) /* format error? */ |
| 915 | - trydecpoint(ls, seminfo); /* try to update decimal point separator */ |
| 916 | + ret= luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r, &seminfo->i ); |
| 917 | + if (!ret) return trydecpoint(ls, seminfo); /* try to update decimal point separator */ |
| 918 | + return ret; |
| 919 | } |
| 920 | |
| 921 | |
| 922 | @@ -331,6 +345,7 @@ static void read_string (LexState *ls, i |
| 923 | } |
| 924 | |
| 925 | |
| 926 | +/* char / TK_* */ |
| 927 | static int llex (LexState *ls, SemInfo *seminfo) { |
| 928 | luaZ_resetbuffer(ls->buff); |
| 929 | for (;;) { |
| 930 | @@ -402,8 +417,7 @@ static int llex (LexState *ls, SemInfo * |
| 931 | } |
| 932 | else if (!isdigit(ls->current)) return '.'; |
| 933 | else { |
| 934 | - read_numeral(ls, seminfo); |
| 935 | - return TK_NUMBER; |
| 936 | + return read_numeral(ls, seminfo); |
| 937 | } |
| 938 | } |
| 939 | case EOZ: { |
| 940 | @@ -416,8 +430,7 @@ static int llex (LexState *ls, SemInfo * |
| 941 | continue; |
| 942 | } |
| 943 | else if (isdigit(ls->current)) { |
| 944 | - read_numeral(ls, seminfo); |
| 945 | - return TK_NUMBER; |
| 946 | + return read_numeral(ls, seminfo); |
| 947 | } |
| 948 | else if (isalpha(ls->current) || ls->current == '_') { |
| 949 | /* identifier or reserved word */ |
| 950 | --- a/src/llex.h |
| 951 | +++ b/src/llex.h |
| 952 | @@ -29,19 +29,22 @@ enum RESERVED { |
| 953 | TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE, |
| 954 | /* other terminal symbols */ |
| 955 | TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER, |
| 956 | - TK_NAME, TK_STRING, TK_EOS |
| 957 | + TK_NAME, TK_STRING, TK_EOS, TK_INT |
| 958 | +#ifdef LNUM_COMPLEX |
| 959 | + , TK_NUMBER2 /* imaginary constants: Ni */ |
| 960 | +#endif |
| 961 | }; |
| 962 | |
| 963 | /* number of reserved words */ |
| 964 | #define NUM_RESERVED (cast(int, TK_WHILE-FIRST_RESERVED+1)) |
| 965 | |
| 966 | |
| 967 | -/* array with token `names' */ |
| 968 | -LUAI_DATA const char *const luaX_tokens []; |
| 969 | - |
| 970 | - |
| 971 | +/* SemInfo is a local data structure of 'llex.c', used for carrying a string |
| 972 | + * or a number. A separate token (TK_*) will tell, how to interpret the data. |
| 973 | + */ |
| 974 | typedef union { |
| 975 | lua_Number r; |
| 976 | + lua_Integer i; |
| 977 | TString *ts; |
| 978 | } SemInfo; /* semantics information */ |
| 979 | |
| 980 | --- a/src/llimits.h |
| 981 | +++ b/src/llimits.h |
| 982 | @@ -49,6 +49,7 @@ typedef LUAI_USER_ALIGNMENT_T L_Umaxalig |
| 983 | |
| 984 | /* result of a `usual argument conversion' over lua_Number */ |
| 985 | typedef LUAI_UACNUMBER l_uacNumber; |
| 986 | +typedef LUAI_UACINTEGER l_uacInteger; |
| 987 | |
| 988 | |
| 989 | /* internal assertions for in-house debugging */ |
| 990 | @@ -80,7 +81,6 @@ typedef LUAI_UACNUMBER l_uacNumber; |
| 991 | #define cast_int(i) cast(int, (i)) |
| 992 | |
| 993 | |
| 994 | - |
| 995 | /* |
| 996 | ** type for virtual-machine instructions |
| 997 | ** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h) |
| 998 | --- a/src/lmathlib.c |
| 999 | +++ b/src/lmathlib.c |
| 1000 | @@ -4,7 +4,6 @@ |
| 1001 | ** See Copyright Notice in lua.h |
| 1002 | */ |
| 1003 | |
| 1004 | - |
| 1005 | #include <stdlib.h> |
| 1006 | #include <math.h> |
| 1007 | |
| 1008 | @@ -16,113 +15,210 @@ |
| 1009 | #include "lauxlib.h" |
| 1010 | #include "lualib.h" |
| 1011 | |
| 1012 | +/* 'luai_vectpow()' as a replacement for 'cpow()'. Defined in the header; we |
| 1013 | + * don't intrude the code libs internal functions. |
| 1014 | + */ |
| 1015 | +#ifdef LNUM_COMPLEX |
| 1016 | +# include "lnum.h" |
| 1017 | +#endif |
| 1018 | |
| 1019 | #undef PI |
| 1020 | -#define PI (3.14159265358979323846) |
| 1021 | -#define RADIANS_PER_DEGREE (PI/180.0) |
| 1022 | - |
| 1023 | - |
| 1024 | +#ifdef LNUM_FLOAT |
| 1025 | +# define PI (3.14159265358979323846F) |
| 1026 | +#elif defined(M_PI) |
| 1027 | +# define PI M_PI |
| 1028 | +#else |
| 1029 | +# define PI (3.14159265358979323846264338327950288) |
| 1030 | +#endif |
| 1031 | +#define RADIANS_PER_DEGREE (PI/180) |
| 1032 | + |
| 1033 | +#undef HUGE |
| 1034 | +#ifdef LNUM_FLOAT |
| 1035 | +# define HUGE HUGE_VALF |
| 1036 | +#elif defined(LNUM_LDOUBLE) |
| 1037 | +# define HUGE HUGE_VALL |
| 1038 | +#else |
| 1039 | +# define HUGE HUGE_VAL |
| 1040 | +#endif |
| 1041 | |
| 1042 | static int math_abs (lua_State *L) { |
| 1043 | - lua_pushnumber(L, fabs(luaL_checknumber(L, 1))); |
| 1044 | +#ifdef LNUM_COMPLEX |
| 1045 | + lua_pushnumber(L, _LF(cabs) (luaL_checkcomplex(L,1))); |
| 1046 | +#else |
| 1047 | + lua_pushnumber(L, _LF(fabs) (luaL_checknumber(L, 1))); |
| 1048 | +#endif |
| 1049 | return 1; |
| 1050 | } |
| 1051 | |
| 1052 | static int math_sin (lua_State *L) { |
| 1053 | - lua_pushnumber(L, sin(luaL_checknumber(L, 1))); |
| 1054 | +#ifdef LNUM_COMPLEX |
| 1055 | + lua_pushcomplex(L, _LF(csin) (luaL_checkcomplex(L,1))); |
| 1056 | +#else |
| 1057 | + lua_pushnumber(L, _LF(sin) (luaL_checknumber(L, 1))); |
| 1058 | +#endif |
| 1059 | return 1; |
| 1060 | } |
| 1061 | |
| 1062 | static int math_sinh (lua_State *L) { |
| 1063 | - lua_pushnumber(L, sinh(luaL_checknumber(L, 1))); |
| 1064 | +#ifdef LNUM_COMPLEX |
| 1065 | + lua_pushcomplex(L, _LF(csinh) (luaL_checkcomplex(L,1))); |
| 1066 | +#else |
| 1067 | + lua_pushnumber(L, _LF(sinh) (luaL_checknumber(L, 1))); |
| 1068 | +#endif |
| 1069 | return 1; |
| 1070 | } |
| 1071 | |
| 1072 | static int math_cos (lua_State *L) { |
| 1073 | - lua_pushnumber(L, cos(luaL_checknumber(L, 1))); |
| 1074 | +#ifdef LNUM_COMPLEX |
| 1075 | + lua_pushcomplex(L, _LF(ccos) (luaL_checkcomplex(L,1))); |
| 1076 | +#else |
| 1077 | + lua_pushnumber(L, _LF(cos) (luaL_checknumber(L, 1))); |
| 1078 | +#endif |
| 1079 | return 1; |
| 1080 | } |
| 1081 | |
| 1082 | static int math_cosh (lua_State *L) { |
| 1083 | - lua_pushnumber(L, cosh(luaL_checknumber(L, 1))); |
| 1084 | +#ifdef LNUM_COMPLEX |
| 1085 | + lua_pushcomplex(L, _LF(ccosh) (luaL_checkcomplex(L,1))); |
| 1086 | +#else |
| 1087 | + lua_pushnumber(L, _LF(cosh) (luaL_checknumber(L, 1))); |
| 1088 | +#endif |
| 1089 | return 1; |
| 1090 | } |
| 1091 | |
| 1092 | static int math_tan (lua_State *L) { |
| 1093 | - lua_pushnumber(L, tan(luaL_checknumber(L, 1))); |
| 1094 | +#ifdef LNUM_COMPLEX |
| 1095 | + lua_pushcomplex(L, _LF(ctan) (luaL_checkcomplex(L,1))); |
| 1096 | +#else |
| 1097 | + lua_pushnumber(L, _LF(tan) (luaL_checknumber(L, 1))); |
| 1098 | +#endif |
| 1099 | return 1; |
| 1100 | } |
| 1101 | |
| 1102 | static int math_tanh (lua_State *L) { |
| 1103 | - lua_pushnumber(L, tanh(luaL_checknumber(L, 1))); |
| 1104 | +#ifdef LNUM_COMPLEX |
| 1105 | + lua_pushcomplex(L, _LF(ctanh) (luaL_checkcomplex(L,1))); |
| 1106 | +#else |
| 1107 | + lua_pushnumber(L, _LF(tanh) (luaL_checknumber(L, 1))); |
| 1108 | +#endif |
| 1109 | return 1; |
| 1110 | } |
| 1111 | |
| 1112 | static int math_asin (lua_State *L) { |
| 1113 | - lua_pushnumber(L, asin(luaL_checknumber(L, 1))); |
| 1114 | +#ifdef LNUM_COMPLEX |
| 1115 | + lua_pushcomplex(L, _LF(casin) (luaL_checkcomplex(L,1))); |
| 1116 | +#else |
| 1117 | + lua_pushnumber(L, _LF(asin) (luaL_checknumber(L, 1))); |
| 1118 | +#endif |
| 1119 | return 1; |
| 1120 | } |
| 1121 | |
| 1122 | static int math_acos (lua_State *L) { |
| 1123 | - lua_pushnumber(L, acos(luaL_checknumber(L, 1))); |
| 1124 | +#ifdef LNUM_COMPLEX |
| 1125 | + lua_pushcomplex(L, _LF(cacos) (luaL_checkcomplex(L,1))); |
| 1126 | +#else |
| 1127 | + lua_pushnumber(L, _LF(acos) (luaL_checknumber(L, 1))); |
| 1128 | +#endif |
| 1129 | return 1; |
| 1130 | } |
| 1131 | |
| 1132 | static int math_atan (lua_State *L) { |
| 1133 | - lua_pushnumber(L, atan(luaL_checknumber(L, 1))); |
| 1134 | +#ifdef LNUM_COMPLEX |
| 1135 | + lua_pushcomplex(L, _LF(catan) (luaL_checkcomplex(L,1))); |
| 1136 | +#else |
| 1137 | + lua_pushnumber(L, _LF(atan) (luaL_checknumber(L, 1))); |
| 1138 | +#endif |
| 1139 | return 1; |
| 1140 | } |
| 1141 | |
| 1142 | static int math_atan2 (lua_State *L) { |
| 1143 | - lua_pushnumber(L, atan2(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); |
| 1144 | + /* scalars only */ |
| 1145 | + lua_pushnumber(L, _LF(atan2) (luaL_checknumber(L, 1), luaL_checknumber(L, 2))); |
| 1146 | return 1; |
| 1147 | } |
| 1148 | |
| 1149 | static int math_ceil (lua_State *L) { |
| 1150 | - lua_pushnumber(L, ceil(luaL_checknumber(L, 1))); |
| 1151 | +#ifdef LNUM_COMPLEX |
| 1152 | + lua_Complex v= luaL_checkcomplex(L, 1); |
| 1153 | + lua_pushcomplex(L, _LF(ceil) (_LF(creal)(v)) + _LF(ceil) (_LF(cimag)(v))*I); |
| 1154 | +#else |
| 1155 | + lua_pushnumber(L, _LF(ceil) (luaL_checknumber(L, 1))); |
| 1156 | +#endif |
| 1157 | return 1; |
| 1158 | } |
| 1159 | |
| 1160 | static int math_floor (lua_State *L) { |
| 1161 | - lua_pushnumber(L, floor(luaL_checknumber(L, 1))); |
| 1162 | +#ifdef LNUM_COMPLEX |
| 1163 | + lua_Complex v= luaL_checkcomplex(L, 1); |
| 1164 | + lua_pushcomplex(L, _LF(floor) (_LF(creal)(v)) + _LF(floor) (_LF(cimag)(v))*I); |
| 1165 | +#else |
| 1166 | + lua_pushnumber(L, _LF(floor) (luaL_checknumber(L, 1))); |
| 1167 | +#endif |
| 1168 | return 1; |
| 1169 | } |
| 1170 | |
| 1171 | -static int math_fmod (lua_State *L) { |
| 1172 | - lua_pushnumber(L, fmod(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); |
| 1173 | +static int math_fmod (lua_State *L) { |
| 1174 | + /* scalars only */ |
| 1175 | + lua_pushnumber(L, _LF(fmod) (luaL_checknumber(L, 1), luaL_checknumber(L, 2))); |
| 1176 | return 1; |
| 1177 | } |
| 1178 | |
| 1179 | static int math_modf (lua_State *L) { |
| 1180 | - double ip; |
| 1181 | - double fp = modf(luaL_checknumber(L, 1), &ip); |
| 1182 | + /* scalars only */ |
| 1183 | + lua_Number ip; |
| 1184 | + lua_Number fp = _LF(modf) (luaL_checknumber(L, 1), &ip); |
| 1185 | lua_pushnumber(L, ip); |
| 1186 | lua_pushnumber(L, fp); |
| 1187 | return 2; |
| 1188 | } |
| 1189 | |
| 1190 | static int math_sqrt (lua_State *L) { |
| 1191 | - lua_pushnumber(L, sqrt(luaL_checknumber(L, 1))); |
| 1192 | +#ifdef LNUM_COMPLEX |
| 1193 | + lua_pushcomplex(L, _LF(csqrt) (luaL_checkcomplex(L,1))); |
| 1194 | +#else |
| 1195 | + lua_pushnumber(L, _LF(sqrt) (luaL_checknumber(L, 1))); |
| 1196 | +#endif |
| 1197 | return 1; |
| 1198 | } |
| 1199 | |
| 1200 | static int math_pow (lua_State *L) { |
| 1201 | - lua_pushnumber(L, pow(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); |
| 1202 | +#ifdef LNUM_COMPLEX |
| 1203 | + /* C99 'cpow' gives somewhat inaccurate results (i.e. (-1)^2 = -1+1.2246467991474e-16i). |
| 1204 | + * 'luai_vectpow' smoothens such, reusing it is the reason we need to #include "lnum.h". |
| 1205 | + */ |
| 1206 | + lua_pushcomplex(L, luai_vectpow(luaL_checkcomplex(L,1), luaL_checkcomplex(L,2))); |
| 1207 | +#else |
| 1208 | + lua_pushnumber(L, _LF(pow) (luaL_checknumber(L, 1), luaL_checknumber(L, 2))); |
| 1209 | +#endif |
| 1210 | return 1; |
| 1211 | } |
| 1212 | |
| 1213 | static int math_log (lua_State *L) { |
| 1214 | - lua_pushnumber(L, log(luaL_checknumber(L, 1))); |
| 1215 | +#ifdef LNUM_COMPLEX |
| 1216 | + lua_pushcomplex(L, _LF(clog) (luaL_checkcomplex(L,1))); |
| 1217 | +#else |
| 1218 | + lua_pushnumber(L, _LF(log) (luaL_checknumber(L, 1))); |
| 1219 | +#endif |
| 1220 | return 1; |
| 1221 | } |
| 1222 | |
| 1223 | static int math_log10 (lua_State *L) { |
| 1224 | - lua_pushnumber(L, log10(luaL_checknumber(L, 1))); |
| 1225 | +#ifdef LNUM_COMPLEX |
| 1226 | + /* Not in standard <complex.h> , but easy to calculate: log_a(x) = log_b(x) / log_b(a) |
| 1227 | + */ |
| 1228 | + lua_pushcomplex(L, _LF(clog) (luaL_checkcomplex(L,1)) / _LF(log) (10)); |
| 1229 | +#else |
| 1230 | + lua_pushnumber(L, _LF(log10) (luaL_checknumber(L, 1))); |
| 1231 | +#endif |
| 1232 | return 1; |
| 1233 | } |
| 1234 | |
| 1235 | static int math_exp (lua_State *L) { |
| 1236 | - lua_pushnumber(L, exp(luaL_checknumber(L, 1))); |
| 1237 | +#ifdef LNUM_COMPLEX |
| 1238 | + lua_pushcomplex(L, _LF(cexp) (luaL_checkcomplex(L,1))); |
| 1239 | +#else |
| 1240 | + lua_pushnumber(L, _LF(exp) (luaL_checknumber(L, 1))); |
| 1241 | +#endif |
| 1242 | return 1; |
| 1243 | } |
| 1244 | |
| 1245 | @@ -138,19 +234,20 @@ static int math_rad (lua_State *L) { |
| 1246 | |
| 1247 | static int math_frexp (lua_State *L) { |
| 1248 | int e; |
| 1249 | - lua_pushnumber(L, frexp(luaL_checknumber(L, 1), &e)); |
| 1250 | + lua_pushnumber(L, _LF(frexp) (luaL_checknumber(L, 1), &e)); |
| 1251 | lua_pushinteger(L, e); |
| 1252 | return 2; |
| 1253 | } |
| 1254 | |
| 1255 | static int math_ldexp (lua_State *L) { |
| 1256 | - lua_pushnumber(L, ldexp(luaL_checknumber(L, 1), luaL_checkint(L, 2))); |
| 1257 | + lua_pushnumber(L, _LF(ldexp) (luaL_checknumber(L, 1), luaL_checkint(L, 2))); |
| 1258 | return 1; |
| 1259 | } |
| 1260 | |
| 1261 | |
| 1262 | |
| 1263 | static int math_min (lua_State *L) { |
| 1264 | + /* scalars only */ |
| 1265 | int n = lua_gettop(L); /* number of arguments */ |
| 1266 | lua_Number dmin = luaL_checknumber(L, 1); |
| 1267 | int i; |
| 1268 | @@ -165,6 +262,7 @@ static int math_min (lua_State *L) { |
| 1269 | |
| 1270 | |
| 1271 | static int math_max (lua_State *L) { |
| 1272 | + /* scalars only */ |
| 1273 | int n = lua_gettop(L); /* number of arguments */ |
| 1274 | lua_Number dmax = luaL_checknumber(L, 1); |
| 1275 | int i; |
| 1276 | @@ -182,25 +280,20 @@ static int math_random (lua_State *L) { |
| 1277 | /* the `%' avoids the (rare) case of r==1, and is needed also because on |
| 1278 | some systems (SunOS!) `rand()' may return a value larger than RAND_MAX */ |
| 1279 | lua_Number r = (lua_Number)(rand()%RAND_MAX) / (lua_Number)RAND_MAX; |
| 1280 | - switch (lua_gettop(L)) { /* check number of arguments */ |
| 1281 | - case 0: { /* no arguments */ |
| 1282 | - lua_pushnumber(L, r); /* Number between 0 and 1 */ |
| 1283 | - break; |
| 1284 | - } |
| 1285 | - case 1: { /* only upper limit */ |
| 1286 | - int u = luaL_checkint(L, 1); |
| 1287 | - luaL_argcheck(L, 1<=u, 1, "interval is empty"); |
| 1288 | - lua_pushnumber(L, floor(r*u)+1); /* int between 1 and `u' */ |
| 1289 | - break; |
| 1290 | - } |
| 1291 | - case 2: { /* lower and upper limits */ |
| 1292 | - int l = luaL_checkint(L, 1); |
| 1293 | - int u = luaL_checkint(L, 2); |
| 1294 | - luaL_argcheck(L, l<=u, 2, "interval is empty"); |
| 1295 | - lua_pushnumber(L, floor(r*(u-l+1))+l); /* int between `l' and `u' */ |
| 1296 | - break; |
| 1297 | - } |
| 1298 | - default: return luaL_error(L, "wrong number of arguments"); |
| 1299 | + int n= lua_gettop(L); /* number of arguments */ |
| 1300 | + if (n==0) { /* no arguments: range [0,1) */ |
| 1301 | + lua_pushnumber(L, r); |
| 1302 | + } else if (n<=2) { /* int range [1,u] or [l,u] */ |
| 1303 | + int l= n==1 ? 1 : luaL_checkint(L, 1); |
| 1304 | + int u = luaL_checkint(L, n); |
| 1305 | + int tmp; |
| 1306 | + lua_Number d; |
| 1307 | + luaL_argcheck(L, l<=u, n, "interval is empty"); |
| 1308 | + d= _LF(floor)(r*(u-l+1)); |
| 1309 | + lua_number2int(tmp,d); |
| 1310 | + lua_pushinteger(L, l+tmp); |
| 1311 | + } else { |
| 1312 | + return luaL_error(L, "wrong number of arguments"); |
| 1313 | } |
| 1314 | return 1; |
| 1315 | } |
| 1316 | @@ -211,6 +304,66 @@ static int math_randomseed (lua_State *L |
| 1317 | return 0; |
| 1318 | } |
| 1319 | |
| 1320 | +/* |
| 1321 | +* Lua 5.1 does not have acosh, asinh, atanh for scalars (not ANSI C) |
| 1322 | +*/ |
| 1323 | +#if __STDC_VERSION__ >= 199901L |
| 1324 | +static int math_acosh (lua_State *L) { |
| 1325 | +# ifdef LNUM_COMPLEX |
| 1326 | + lua_pushcomplex(L, _LF(cacosh) (luaL_checkcomplex(L,1))); |
| 1327 | +# else |
| 1328 | + lua_pushnumber(L, _LF(acosh) (luaL_checknumber(L,1))); |
| 1329 | +# endif |
| 1330 | + return 1; |
| 1331 | +} |
| 1332 | +static int math_asinh (lua_State *L) { |
| 1333 | +# ifdef LNUM_COMPLEX |
| 1334 | + lua_pushcomplex(L, _LF(casinh) (luaL_checkcomplex(L,1))); |
| 1335 | +# else |
| 1336 | + lua_pushnumber(L, _LF(asinh) (luaL_checknumber(L,1))); |
| 1337 | +# endif |
| 1338 | + return 1; |
| 1339 | +} |
| 1340 | +static int math_atanh (lua_State *L) { |
| 1341 | +# ifdef LNUM_COMPLEX |
| 1342 | + lua_pushcomplex(L, _LF(catanh) (luaL_checkcomplex(L,1))); |
| 1343 | +# else |
| 1344 | + lua_pushnumber(L, _LF(atanh) (luaL_checknumber(L,1))); |
| 1345 | +# endif |
| 1346 | + return 1; |
| 1347 | +} |
| 1348 | +#endif |
| 1349 | + |
| 1350 | +/* |
| 1351 | + * C99 complex functions, not covered above. |
| 1352 | +*/ |
| 1353 | +#ifdef LNUM_COMPLEX |
| 1354 | +static int math_arg (lua_State *L) { |
| 1355 | + lua_pushnumber(L, _LF(carg) (luaL_checkcomplex(L,1))); |
| 1356 | + return 1; |
| 1357 | +} |
| 1358 | + |
| 1359 | +static int math_imag (lua_State *L) { |
| 1360 | + lua_pushnumber(L, _LF(cimag) (luaL_checkcomplex(L,1))); |
| 1361 | + return 1; |
| 1362 | +} |
| 1363 | + |
| 1364 | +static int math_real (lua_State *L) { |
| 1365 | + lua_pushnumber(L, _LF(creal) (luaL_checkcomplex(L,1))); |
| 1366 | + return 1; |
| 1367 | +} |
| 1368 | + |
| 1369 | +static int math_conj (lua_State *L) { |
| 1370 | + lua_pushcomplex(L, _LF(conj) (luaL_checkcomplex(L,1))); |
| 1371 | + return 1; |
| 1372 | +} |
| 1373 | + |
| 1374 | +static int math_proj (lua_State *L) { |
| 1375 | + lua_pushcomplex(L, _LF(cproj) (luaL_checkcomplex(L,1))); |
| 1376 | + return 1; |
| 1377 | +} |
| 1378 | +#endif |
| 1379 | + |
| 1380 | |
| 1381 | static const luaL_Reg mathlib[] = { |
| 1382 | {"abs", math_abs}, |
| 1383 | @@ -241,6 +394,18 @@ static const luaL_Reg mathlib[] = { |
| 1384 | {"sqrt", math_sqrt}, |
| 1385 | {"tanh", math_tanh}, |
| 1386 | {"tan", math_tan}, |
| 1387 | +#if __STDC_VERSION__ >= 199901L |
| 1388 | + {"acosh", math_acosh}, |
| 1389 | + {"asinh", math_asinh}, |
| 1390 | + {"atanh", math_atanh}, |
| 1391 | +#endif |
| 1392 | +#ifdef LNUM_COMPLEX |
| 1393 | + {"arg", math_arg}, |
| 1394 | + {"imag", math_imag}, |
| 1395 | + {"real", math_real}, |
| 1396 | + {"conj", math_conj}, |
| 1397 | + {"proj", math_proj}, |
| 1398 | +#endif |
| 1399 | {NULL, NULL} |
| 1400 | }; |
| 1401 | |
| 1402 | @@ -252,8 +417,10 @@ LUALIB_API int luaopen_math (lua_State * |
| 1403 | luaL_register(L, LUA_MATHLIBNAME, mathlib); |
| 1404 | lua_pushnumber(L, PI); |
| 1405 | lua_setfield(L, -2, "pi"); |
| 1406 | - lua_pushnumber(L, HUGE_VAL); |
| 1407 | + lua_pushnumber(L, HUGE); |
| 1408 | lua_setfield(L, -2, "huge"); |
| 1409 | + lua_pushinteger(L, LUA_INTEGER_MAX ); |
| 1410 | + lua_setfield(L, -2, "hugeint"); |
| 1411 | #if defined(LUA_COMPAT_MOD) |
| 1412 | lua_getfield(L, -1, "fmod"); |
| 1413 | lua_setfield(L, -2, "mod"); |
| 1414 | --- /dev/null |
| 1415 | +++ b/src/lnum.c |
| 1416 | @@ -0,0 +1,312 @@ |
| 1417 | +/* |
| 1418 | +** $Id: lnum.c,v ... $ |
| 1419 | +** Internal number model |
| 1420 | +** See Copyright Notice in lua.h |
| 1421 | +*/ |
| 1422 | + |
| 1423 | +#include <stdlib.h> |
| 1424 | +#include <math.h> |
| 1425 | +#include <ctype.h> |
| 1426 | +#include <string.h> |
| 1427 | +#include <stdio.h> |
| 1428 | +#include <errno.h> |
| 1429 | + |
| 1430 | +#define lnum_c |
| 1431 | +#define LUA_CORE |
| 1432 | + |
| 1433 | +#include "lua.h" |
| 1434 | +#include "llex.h" |
| 1435 | +#include "lnum.h" |
| 1436 | + |
| 1437 | +/* |
| 1438 | +** lua_real2str converts a (non-complex) number to a string. |
| 1439 | +** lua_str2real converts a string to a (non-complex) number. |
| 1440 | +*/ |
| 1441 | +#define lua_real2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n)) |
| 1442 | + |
| 1443 | +/* |
| 1444 | +* Note: Only 'strtod()' is part of ANSI C; others are C99 and |
| 1445 | +* may need '--std=c99' compiler setting (at least on Ubuntu 7.10). |
| 1446 | +* |
| 1447 | +* Visual C++ 2008 Express does not have 'strtof()', nor 'strtold()'. |
| 1448 | +* References to '_strtold()' exist but don't compile. It seems best |
| 1449 | +* to leave Windows users with DOUBLE only (or compile with MinGW). |
| 1450 | +* |
| 1451 | +* In practise, using '(long double)strtod' is a risky thing, since |
| 1452 | +* it will cause accuracy loss in reading in numbers, and such losses |
| 1453 | +* will pile up in later processing. Get a real 'strtold()' or don't |
| 1454 | +* use that mode at all. |
| 1455 | +*/ |
| 1456 | +#ifdef LNUM_DOUBLE |
| 1457 | +# define lua_str2real strtod |
| 1458 | +#elif defined(LNUM_FLOAT) |
| 1459 | +# define lua_str2real strtof |
| 1460 | +#elif defined(LNUM_LDOUBLE) |
| 1461 | +# define lua_str2real strtold |
| 1462 | +#endif |
| 1463 | + |
| 1464 | +#define lua_integer2str(s,v) sprintf((s), LUA_INTEGER_FMT, (v)) |
| 1465 | + |
| 1466 | +/* 's' is expected to be LUAI_MAXNUMBER2STR long (enough for any number) |
| 1467 | +*/ |
| 1468 | +void luaO_num2buf( char *s, const TValue *o ) |
| 1469 | +{ |
| 1470 | + lua_Number n; |
| 1471 | + lua_assert( ttisnumber(o) ); |
| 1472 | + |
| 1473 | + /* Reason to handle integers differently is not only speed, but accuracy as |
| 1474 | + * well. We want to make any integer tostring() without roundings, at all. |
| 1475 | + */ |
| 1476 | + if (ttisint(o)) { |
| 1477 | + lua_integer2str( s, ivalue(o) ); |
| 1478 | + return; |
| 1479 | + } |
| 1480 | + n= nvalue_fast(o); |
| 1481 | + lua_real2str(s, n); |
| 1482 | + |
| 1483 | +#ifdef LNUM_COMPLEX |
| 1484 | + lua_Number n2= nvalue_img_fast(o); |
| 1485 | + if (n2!=0) { /* Postfix with +-Ni */ |
| 1486 | + int re0= (n == 0); |
| 1487 | + char *s2= re0 ? s : strchr(s,'\0'); |
| 1488 | + if ((!re0) && (n2>0)) *s2++= '+'; |
| 1489 | + lua_real2str( s2, n2 ); |
| 1490 | + strcat(s2,"i"); |
| 1491 | + } |
| 1492 | +#endif |
| 1493 | +} |
| 1494 | + |
| 1495 | +/* |
| 1496 | +* If a LUA_TNUMBER has integer value, give it. |
| 1497 | +*/ |
| 1498 | +int /*bool*/ tt_integer_valued( const TValue *o, lua_Integer *ref ) { |
| 1499 | + lua_Number d; |
| 1500 | + lua_Integer i; |
| 1501 | + |
| 1502 | + lua_assert( ttype(o)==LUA_TNUMBER ); |
| 1503 | + lua_assert( ref ); |
| 1504 | +#ifdef LNUM_COMPLEX |
| 1505 | + if (nvalue_img_fast(o)!=0) return 0; |
| 1506 | +#endif |
| 1507 | + d= nvalue_fast(o); |
| 1508 | + lua_number2integer(i, d); |
| 1509 | + if (cast_num(i) == d) { |
| 1510 | + *ref= i; return 1; |
| 1511 | + } |
| 1512 | + return 0; |
| 1513 | +} |
| 1514 | + |
| 1515 | +/* |
| 1516 | + * Lua 5.1.3 (using 'strtod()') allows 0x+hex but not 0+octal. This is good, |
| 1517 | + * and we should NOT use 'autobase' 0 with 'strtoul[l]()' for this reason. |
| 1518 | + * |
| 1519 | + * Lua 5.1.3 allows '0x...' numbers to overflow and lose precision; this is not |
| 1520 | + * good. On Visual C++ 2008, 'strtod()' does not even take them in. Better to |
| 1521 | + * require hex values to fit 'lua_Integer' or give an error that they don't? |
| 1522 | + * |
| 1523 | + * Full hex range (0 .. 0xff..ff) is stored as integers, not to lose any bits. |
| 1524 | + * Numerical value of 0xff..ff will be -1, if used in calculations. |
| 1525 | + * |
| 1526 | + * Returns: TK_INT for a valid integer, '*endptr_ref' updated |
| 1527 | + * TK_NUMBER for seemingly numeric, to be parsed as floating point |
| 1528 | + * 0 for bad characters, not a number (or '0x' out of range) |
| 1529 | + */ |
| 1530 | +static int luaO_str2i (const char *s, lua_Integer *res, char **endptr_ref) { |
| 1531 | + char *endptr; |
| 1532 | + /* 'v' gets ULONG_MAX on possible overflow (which is > LUA_INTEGER_MAX); |
| 1533 | + * we don't have to check 'errno' here. |
| 1534 | + */ |
| 1535 | + unsigned LUA_INTEGER v= lua_str2ul(s, &endptr, 10); |
| 1536 | + if (endptr == s) return 0; /* nothing numeric */ |
| 1537 | + if (v==0 && *endptr=='x') { |
| 1538 | + errno= 0; /* needs to be set, 'strtoul[l]' does not clear it */ |
| 1539 | + v= lua_str2ul(endptr+1, &endptr, 16); /* retry as hex, unsigned range */ |
| 1540 | + if (errno==ERANGE) { /* clamped to 0xff..ff */ |
| 1541 | +#if (defined(LNUM_INT32) && !defined(LNUM_FLOAT)) || defined(LNUM_LDOUBLE) |
| 1542 | + return TK_NUMBER; /* Allow to be read as floating point (has more integer range) */ |
| 1543 | +#else |
| 1544 | + return 0; /* Reject the number */ |
| 1545 | +#endif |
| 1546 | + } |
| 1547 | + } else if ((v > LUA_INTEGER_MAX) || (*endptr && (!isspace(*endptr)))) { |
| 1548 | + return TK_NUMBER; /* not in signed range, or has '.', 'e' etc. trailing */ |
| 1549 | + } |
| 1550 | + *res= (lua_Integer)v; |
| 1551 | + *endptr_ref= endptr; |
| 1552 | + return TK_INT; |
| 1553 | +} |
| 1554 | + |
| 1555 | +/* 0 / TK_NUMBER / TK_INT (/ TK_NUMBER2) */ |
| 1556 | +int luaO_str2d (const char *s, lua_Number *res_n, lua_Integer *res_i) { |
| 1557 | + char *endptr; |
| 1558 | + int ret= TK_NUMBER; |
| 1559 | + /* Check integers first, if caller is allowing. |
| 1560 | + * If 'res2'==NULL, they're only looking for floating point. |
| 1561 | + */ |
| 1562 | + if (res_i) { |
| 1563 | + ret= luaO_str2i(s,res_i,&endptr); |
| 1564 | + if (ret==0) return 0; |
| 1565 | + } |
| 1566 | + if (ret==TK_NUMBER) { |
| 1567 | + lua_assert(res_n); |
| 1568 | + /* Note: Visual C++ 2008 Express 'strtod()' does not read in "0x..." |
| 1569 | + * numbers; it will read '0' and spit 'x' as endptr. |
| 1570 | + * This means hex constants not fitting in 'lua_Integer' won't |
| 1571 | + * be read in at all. What to do? |
| 1572 | + */ |
| 1573 | + *res_n = lua_str2real(s, &endptr); |
| 1574 | + if (endptr == s) return 0; /* conversion failed */ |
| 1575 | + /* Visual C++ 2008 'strtod()' does not allow "0x..." input. */ |
| 1576 | +#if defined(_MSC_VER) && !defined(LNUM_FLOAT) && !defined(LNUM_INT64) |
| 1577 | + if (*res_n==0 && *endptr=='x') { |
| 1578 | + /* Hex constant too big for 'lua_Integer' but that could fit in 'lua_Number' |
| 1579 | + * integer bits |
| 1580 | + */ |
| 1581 | + unsigned __int64 v= _strtoui64( s, &endptr, 16 ); |
| 1582 | + /* We just let > 64 bit values be clamped to _UI64_MAX (MSDN does not say 'errno'==ERANGE would be set) */ |
| 1583 | + *res_n= cast_num(v); |
| 1584 | + if (*res_n != v) return 0; /* Would have lost accuracy */ |
| 1585 | + } |
| 1586 | +#endif |
| 1587 | +#ifdef LNUM_COMPLEX |
| 1588 | + if (*endptr == 'i') { endptr++; ret= TK_NUMBER2; } |
| 1589 | +#endif |
| 1590 | + } |
| 1591 | + if (*endptr) { |
| 1592 | + while (isspace(cast(unsigned char, *endptr))) endptr++; |
| 1593 | + if (*endptr) return 0; /* invalid trail */ |
| 1594 | + } |
| 1595 | + return ret; |
| 1596 | +} |
| 1597 | + |
| 1598 | + |
| 1599 | +/* Functions for finding out, when integer operations remain in range |
| 1600 | + * (and doing them). |
| 1601 | + */ |
| 1602 | +int try_addint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) { |
| 1603 | + /* Signed int overflow is undefined behavior, so catch it without causing it. */ |
| 1604 | + if (ic>0) { if (ib > LUA_INTEGER_MAX - ic) return 0; /*overflow, use floats*/ } |
| 1605 | + else { if (ib < LUA_INTEGER_MIN - ic) return 0; } |
| 1606 | + *r = ib + ic; |
| 1607 | + return 1; |
| 1608 | +} |
| 1609 | + |
| 1610 | +int try_subint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) { |
| 1611 | + /* Signed int overflow is undefined behavior, so catch it without causing it. */ |
| 1612 | + if (ic>0) { if (ib < LUA_INTEGER_MIN + ic) return 0; /*overflow, use floats*/ } |
| 1613 | + else { if (ib > LUA_INTEGER_MAX + ic) return 0; } |
| 1614 | + *r = ib - ic; |
| 1615 | + return 1; |
| 1616 | +} |
| 1617 | + |
| 1618 | +int try_mulint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) { |
| 1619 | + if (ib!=LUA_INTEGER_MIN && ic!=LUA_INTEGER_MIN) { |
| 1620 | + lua_Integer b= luai_abs(ib), c= luai_abs(ic); |
| 1621 | + if ( (ib==0) || (LUA_INTEGER_MAX/b >= c) ) { |
| 1622 | + *r= ib*ic; /* no overflow */ |
| 1623 | + return 1; |
| 1624 | + } |
| 1625 | + } else if (ib==0 || ic==0) { |
| 1626 | + *r= 0; return 1; |
| 1627 | + } |
| 1628 | + |
| 1629 | + /* Result can be LUA_INTEGER_MIN; if it is, calculating it using floating |
| 1630 | + * point will not cause accuracy loss. |
| 1631 | + */ |
| 1632 | + if ( luai_nummul( cast_num(ib), cast_num(ic) ) == LUA_INTEGER_MIN ) { |
| 1633 | + *r= LUA_INTEGER_MIN; |
| 1634 | + return 1; |
| 1635 | + } |
| 1636 | + return 0; |
| 1637 | +} |
| 1638 | + |
| 1639 | +int try_divint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) { |
| 1640 | + /* N/0: leave to float side, to give an error |
| 1641 | + */ |
| 1642 | + if (ic==0) return 0; |
| 1643 | + |
| 1644 | + /* N/LUA_INTEGER_MIN: always non-integer results, or 0 or +1 |
| 1645 | + */ |
| 1646 | + if (ic==LUA_INTEGER_MIN) { |
| 1647 | + if (ib==LUA_INTEGER_MIN) { *r=1; return 1; } |
| 1648 | + if (ib==0) { *r=0; return 1; } |
| 1649 | + |
| 1650 | + /* LUA_INTEGER_MIN (-2^31|63)/N: calculate using float side (either the division |
| 1651 | + * causes non-integer results, or there is no accuracy loss in int->fp->int |
| 1652 | + * conversions (N=2,4,8,..,256 and N=2^30,2^29,..2^23). |
| 1653 | + */ |
| 1654 | + } else if (ib==LUA_INTEGER_MIN) { |
| 1655 | + lua_Number d= luai_numdiv( cast_num(LUA_INTEGER_MIN), cast_num(ic) ); |
| 1656 | + lua_Integer i; lua_number2integer(i,d); |
| 1657 | + if (cast_num(i)==d) { *r= i; return 1; } |
| 1658 | + |
| 1659 | + } else { |
| 1660 | + /* Note: We _can_ use ANSI C mod here, even on negative values, since |
| 1661 | + * we only test for == 0 (the sign would be implementation dependent). |
| 1662 | + */ |
| 1663 | + if (ib%ic == 0) { *r= ib/ic; return 1; } |
| 1664 | + } |
| 1665 | + |
| 1666 | + return 0; |
| 1667 | +} |
| 1668 | + |
| 1669 | +int try_modint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) { |
| 1670 | + if (ic!=0) { |
| 1671 | + /* ANSI C can be trusted when b%c==0, or when values are non-negative. |
| 1672 | + * b - (floor(b/c) * c) |
| 1673 | + * --> |
| 1674 | + * + +: b - (b/c) * c (b % c can be used) |
| 1675 | + * - -: b - (b/c) * c (b % c could work, but not defined by ANSI C) |
| 1676 | + * 0 -: b - (b/c) * c (=0, b % c could work, but not defined by ANSI C) |
| 1677 | + * - +: b - (b/c-1) * c (when b!=-c) |
| 1678 | + * + -: b - (b/c-1) * c (when b!=-c) |
| 1679 | + * |
| 1680 | + * o MIN%MIN ends up 0, via overflow in calcs but that does not matter. |
| 1681 | + * o MIN%MAX ends up MAX-1 (and other such numbers), also after overflow, |
| 1682 | + * but that does not matter, results do. |
| 1683 | + */ |
| 1684 | + lua_Integer v= ib % ic; |
| 1685 | + if ( v!=0 && (ib<0 || ic<0) ) { |
| 1686 | + v= ib - ((ib/ic) - ((ib<=0 && ic<0) ? 0:1)) * ic; |
| 1687 | + } |
| 1688 | + /* Result should always have same sign as 2nd argument. (PIL2) */ |
| 1689 | + lua_assert( (v<0) ? (ic<0) : (v>0) ? (ic>0) : 1 ); |
| 1690 | + *r= v; |
| 1691 | + return 1; |
| 1692 | + } |
| 1693 | + return 0; /* let float side return NaN */ |
| 1694 | +} |
| 1695 | + |
| 1696 | +int try_powint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) { |
| 1697 | + |
| 1698 | + /* In FLOAT/INT32 or FLOAT|DOUBLE/INT64 modes, calculating integer powers |
| 1699 | + * via FP realm may lose accuracy (i.e. 7^11 = 1977326743, which fits int32 |
| 1700 | + * but not 23-bit float mantissa). |
| 1701 | + * |
| 1702 | + * The current solution is dumb, but it works and uses little code. Use of |
| 1703 | + * integer powers is not anticipated to be very frequent (apart from 2^x, |
| 1704 | + * which is separately optimized). |
| 1705 | + */ |
| 1706 | + if (ib==0) *r=0; |
| 1707 | + else if (ic<0) return 0; /* FP realm */ |
| 1708 | + else if (ib==2 && ic < (int)sizeof(lua_Integer)*8-1) *r= ((lua_Integer)1)<<ic; /* 1,2,4,...2^30 | 2^62 optimization */ |
| 1709 | + else if (ic==0) *r=1; |
| 1710 | + else if (luai_abs(ib)==1) *r= (ic%2) ? ib:1; |
| 1711 | + else { |
| 1712 | + lua_Integer x= ib; |
| 1713 | + while( --ic ) { |
| 1714 | + if (!try_mulint( &x, x, ib )) |
| 1715 | + return 0; /* FP realm */ |
| 1716 | + } |
| 1717 | + *r= x; |
| 1718 | + } |
| 1719 | + return 1; |
| 1720 | +} |
| 1721 | + |
| 1722 | +int try_unmint( lua_Integer *r, lua_Integer ib ) { |
| 1723 | + /* Negating LUA_INTEGER_MIN leaves the range. */ |
| 1724 | + if ( ib != LUA_INTEGER_MIN ) |
| 1725 | + { *r= -ib; return 1; } |
| 1726 | + return 0; |
| 1727 | +} |
| 1728 | + |
| 1729 | --- /dev/null |
| 1730 | +++ b/src/lnum.h |
| 1731 | @@ -0,0 +1,116 @@ |
| 1732 | +/* |
| 1733 | +** $Id: lnum.h,v ... $ |
| 1734 | +** Internal Number model |
| 1735 | +** See Copyright Notice in lua.h |
| 1736 | +*/ |
| 1737 | + |
| 1738 | +#ifndef lnum_h |
| 1739 | +#define lnum_h |
| 1740 | + |
| 1741 | +#include <math.h> |
| 1742 | + |
| 1743 | +#include "lobject.h" |
| 1744 | + |
| 1745 | +/* |
| 1746 | +** The luai_num* macros define the primitive operations over 'lua_Number's |
| 1747 | +** (not 'lua_Integer's, not 'lua_Complex'). |
| 1748 | +*/ |
| 1749 | +#define luai_numadd(a,b) ((a)+(b)) |
| 1750 | +#define luai_numsub(a,b) ((a)-(b)) |
| 1751 | +#define luai_nummul(a,b) ((a)*(b)) |
| 1752 | +#define luai_numdiv(a,b) ((a)/(b)) |
| 1753 | +#define luai_nummod(a,b) ((a) - _LF(floor)((a)/(b))*(b)) |
| 1754 | +#define luai_numpow(a,b) (_LF(pow)(a,b)) |
| 1755 | +#define luai_numunm(a) (-(a)) |
| 1756 | +#define luai_numeq(a,b) ((a)==(b)) |
| 1757 | +#define luai_numlt(a,b) ((a)<(b)) |
| 1758 | +#define luai_numle(a,b) ((a)<=(b)) |
| 1759 | +#define luai_numisnan(a) (!luai_numeq((a), (a))) |
| 1760 | + |
| 1761 | +int try_addint( lua_Integer *r, lua_Integer ib, lua_Integer ic ); |
| 1762 | +int try_subint( lua_Integer *r, lua_Integer ib, lua_Integer ic ); |
| 1763 | +int try_mulint( lua_Integer *r, lua_Integer ib, lua_Integer ic ); |
| 1764 | +int try_divint( lua_Integer *r, lua_Integer ib, lua_Integer ic ); |
| 1765 | +int try_modint( lua_Integer *r, lua_Integer ib, lua_Integer ic ); |
| 1766 | +int try_powint( lua_Integer *r, lua_Integer ib, lua_Integer ic ); |
| 1767 | +int try_unmint( lua_Integer *r, lua_Integer ib ); |
| 1768 | + |
| 1769 | +#ifdef LNUM_COMPLEX |
| 1770 | + static inline lua_Complex luai_vectunm( lua_Complex a ) { return -a; } |
| 1771 | + static inline lua_Complex luai_vectadd( lua_Complex a, lua_Complex b ) { return a+b; } |
| 1772 | + static inline lua_Complex luai_vectsub( lua_Complex a, lua_Complex b ) { return a-b; } |
| 1773 | + static inline lua_Complex luai_vectmul( lua_Complex a, lua_Complex b ) { return a*b; } |
| 1774 | + static inline lua_Complex luai_vectdiv( lua_Complex a, lua_Complex b ) { return a/b; } |
| 1775 | + |
| 1776 | +/* |
| 1777 | + * C99 does not provide modulus for complex numbers. It most likely is not |
| 1778 | + * meaningful at all. |
| 1779 | + */ |
| 1780 | + |
| 1781 | +/* |
| 1782 | + * Complex power |
| 1783 | + * |
| 1784 | + * C99 'cpow' gives inaccurate results for many common cases s.a. (1i)^2 -> |
| 1785 | + * -1+1.2246467991474e-16i (OS X 10.4, gcc 4.0.1 build 5367) |
| 1786 | + * |
| 1787 | + * [(a+bi)^(c+di)] = (r^c) * exp(-d*t) * cos(c*t + d*ln(r)) + |
| 1788 | + * = (r^c) * exp(-d*t) * sin(c*t + d*ln(r)) *i |
| 1789 | + * r = sqrt(a^2+b^2), t = arctan( b/a ) |
| 1790 | + * |
| 1791 | + * Reference: <http://home.att.net/~srschmitt/complexnumbers.html> |
| 1792 | + * Could also be calculated using: x^y = exp(ln(x)*y) |
| 1793 | + * |
| 1794 | + * Note: Defined here (and not in .c) so 'lmathlib.c' can share the |
| 1795 | + * implementation. |
| 1796 | + */ |
| 1797 | + static inline |
| 1798 | + lua_Complex luai_vectpow( lua_Complex a, lua_Complex b ) |
| 1799 | + { |
| 1800 | +# if 1 |
| 1801 | + lua_Number ar= _LF(creal)(a), ai= _LF(cimag)(a); |
| 1802 | + lua_Number br= _LF(creal)(b), bi= _LF(cimag)(b); |
| 1803 | + |
| 1804 | + if (ai==0 && bi==0) { /* a^c (real) */ |
| 1805 | + return luai_numpow( ar, br ); |
| 1806 | + } |
| 1807 | + |
| 1808 | + int br_int= (int)br; |
| 1809 | + |
| 1810 | + if ( ai!=0 && bi==0 && br_int==br && br_int!=0 && br_int!=INT_MIN ) { |
| 1811 | + /* (a+bi)^N, N = { +-1,+-2, ... +-INT_MAX } |
| 1812 | + */ |
| 1813 | + lua_Number k= luai_numpow( _LF(sqrt) (ar*ar + ai*ai), br ); |
| 1814 | + lua_Number cos_z, sin_z; |
| 1815 | + |
| 1816 | + /* Situation depends upon c (N) in the following manner: |
| 1817 | + * |
| 1818 | + * N%4==0 => cos(c*t)=1, sin(c*t)=0 |
| 1819 | + * (N*sign(b))%4==1 or (N*sign(b))%4==-3 => cos(c*t)=0, sin(c*t)=1 |
| 1820 | + * N%4==2 or N%4==-2 => cos(c*t)=-1, sin(c*t)=0 |
| 1821 | + * (N*sign(b))%4==-1 or (N*sign(b))%4==3 => cos(c*t)=0, sin(c*t)=-1 |
| 1822 | + */ |
| 1823 | + int br_int_abs = br_int<0 ? -br_int:br_int; |
| 1824 | + |
| 1825 | + switch( (br_int_abs%4) * (br_int<0 ? -1:1) * (ai<0 ? -1:1) ) { |
| 1826 | + case 0: cos_z=1, sin_z=0; break; |
| 1827 | + case 2: case -2: cos_z=-1, sin_z=0; break; |
| 1828 | + case 1: case -3: cos_z=0, sin_z=1; break; |
| 1829 | + case 3: case -1: cos_z=0, sin_z=-1; break; |
| 1830 | + default: lua_assert(0); return 0; |
| 1831 | + } |
| 1832 | + return k*cos_z + (k*sin_z)*I; |
| 1833 | + } |
| 1834 | +# endif |
| 1835 | + return _LF(cpow) ( a, b ); |
| 1836 | + } |
| 1837 | +#endif |
| 1838 | + |
| 1839 | +LUAI_FUNC int luaO_str2d (const char *s, lua_Number *res1, lua_Integer *res2); |
| 1840 | +LUAI_FUNC void luaO_num2buf( char *s, const TValue *o ); |
| 1841 | + |
| 1842 | +LUAI_FUNC int /*bool*/ tt_integer_valued( const TValue *o, lua_Integer *ref ); |
| 1843 | + |
| 1844 | +#define luai_normalize(o) \ |
| 1845 | +{ lua_Integer _i; if (tt_integer_valued(o,&_i)) setivalue(o,_i); } |
| 1846 | + |
| 1847 | +#endif |
| 1848 | --- /dev/null |
| 1849 | +++ b/src/lnum_config.h |
| 1850 | @@ -0,0 +1,221 @@ |
| 1851 | +/* |
| 1852 | +** $Id: lnum_config.h,v ... $ |
| 1853 | +** Internal Number model |
| 1854 | +** See Copyright Notice in lua.h |
| 1855 | +*/ |
| 1856 | + |
| 1857 | +#ifndef lnum_config_h |
| 1858 | +#define lnum_config_h |
| 1859 | + |
| 1860 | +/* |
| 1861 | +** Default number modes |
| 1862 | +*/ |
| 1863 | +#if (!defined LNUM_DOUBLE) && (!defined LNUM_FLOAT) && (!defined LNUM_LDOUBLE) |
| 1864 | +# define LNUM_FLOAT |
| 1865 | +#endif |
| 1866 | +#if (!defined LNUM_INT16) && (!defined LNUM_INT32) && (!defined LNUM_INT64) |
| 1867 | +# define LNUM_INT32 |
| 1868 | +#endif |
| 1869 | + |
| 1870 | +/* |
| 1871 | +** Require C99 mode for COMPLEX, FLOAT and LDOUBLE (only DOUBLE is ANSI C). |
| 1872 | +*/ |
| 1873 | +#if defined(LNUM_COMPLEX) && (__STDC_VERSION__ < 199901L) |
| 1874 | +# error "Need C99 for complex (use '--std=c99' or similar)" |
| 1875 | +#elif defined(LNUM_LDOUBLE) && (__STDC_VERSION__ < 199901L) && !defined(_MSC_VER) |
| 1876 | +# error "Need C99 for 'long double' (use '--std=c99' or similar)" |
| 1877 | +#elif defined(LNUM_FLOAT) && (__STDC_VERSION__ < 199901L) |
| 1878 | +/* LNUM_FLOAT not supported on Windows */ |
| 1879 | +# error "Need C99 for 'float' (use '--std=c99' or similar)" |
| 1880 | +#endif |
| 1881 | + |
| 1882 | +/* |
| 1883 | +** Number mode identifier to accompany the version string. |
| 1884 | +*/ |
| 1885 | +#ifdef LNUM_COMPLEX |
| 1886 | +# define _LNUM1 "complex " |
| 1887 | +#else |
| 1888 | +# define _LNUM1 "" |
| 1889 | +#endif |
| 1890 | +#ifdef LNUM_DOUBLE |
| 1891 | +# define _LNUM2 "double" |
| 1892 | +#elif defined(LNUM_FLOAT) |
| 1893 | +# define _LNUM2 "float" |
| 1894 | +#elif defined(LNUM_LDOUBLE) |
| 1895 | +# define _LNUM2 "ldouble" |
| 1896 | +#endif |
| 1897 | +#ifdef LNUM_INT32 |
| 1898 | +# define _LNUM3 "int32" |
| 1899 | +#elif defined(LNUM_INT64) |
| 1900 | +# define _LNUM3 "int64" |
| 1901 | +#elif defined(LNUM_INT16) |
| 1902 | +# define _LNUM3 "int16" |
| 1903 | +#endif |
| 1904 | +#define LUA_LNUM _LNUM1 _LNUM2 " " _LNUM3 |
| 1905 | + |
| 1906 | +/* |
| 1907 | +** LUA_NUMBER is the type of floating point number in Lua |
| 1908 | +** LUA_NUMBER_SCAN is the format for reading numbers. |
| 1909 | +** LUA_NUMBER_FMT is the format for writing numbers. |
| 1910 | +*/ |
| 1911 | +#ifdef LNUM_FLOAT |
| 1912 | +# define LUA_NUMBER float |
| 1913 | +# define LUA_NUMBER_SCAN "%f" |
| 1914 | +# define LUA_NUMBER_FMT "%g" |
| 1915 | +#elif (defined LNUM_DOUBLE) |
| 1916 | +# define LUA_NUMBER double |
| 1917 | +# define LUA_NUMBER_SCAN "%lf" |
| 1918 | +# define LUA_NUMBER_FMT "%.14g" |
| 1919 | +#elif (defined LNUM_LDOUBLE) |
| 1920 | +# define LUA_NUMBER long double |
| 1921 | +# define LUA_NUMBER_SCAN "%Lg" |
| 1922 | +# define LUA_NUMBER_FMT "%.20Lg" |
| 1923 | +#endif |
| 1924 | + |
| 1925 | + |
| 1926 | +/* |
| 1927 | +** LUAI_MAXNUMBER2STR: size of a buffer fitting any number->string result. |
| 1928 | +** |
| 1929 | +** double: 24 (sign, x.xxxxxxxxxxxxxxe+nnnn, and \0) |
| 1930 | +** int64: 21 (19 digits, sign, and \0) |
| 1931 | +** long double: 43 for 128-bit (sign, x.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxe+nnnn, and \0) |
| 1932 | +** 30 for 80-bit (sign, x.xxxxxxxxxxxxxxxxxxxxe+nnnn, and \0) |
| 1933 | +*/ |
| 1934 | +#ifdef LNUM_LDOUBLE |
| 1935 | +# define _LUAI_MN2S 44 |
| 1936 | +#else |
| 1937 | +# define _LUAI_MN2S 24 |
| 1938 | +#endif |
| 1939 | + |
| 1940 | +#ifdef LNUM_COMPLEX |
| 1941 | +# define LUAI_MAXNUMBER2STR (2*_LUAI_MN2S) |
| 1942 | +#else |
| 1943 | +# define LUAI_MAXNUMBER2STR _LUAI_MN2S |
| 1944 | +#endif |
| 1945 | + |
| 1946 | +/* |
| 1947 | +** LUA_INTEGER is the integer type used by lua_pushinteger/lua_tointeger/lua_isinteger. |
| 1948 | +** LUA_INTEGER_SCAN is the format for reading integers |
| 1949 | +** LUA_INTEGER_FMT is the format for writing integers |
| 1950 | +** |
| 1951 | +** Note: Visual C++ 2005 does not have 'strtoull()', use '_strtoui64()' instead. |
| 1952 | +*/ |
| 1953 | +#ifdef LNUM_INT32 |
| 1954 | +# if LUAI_BITSINT > 16 |
| 1955 | +# define LUA_INTEGER int |
| 1956 | +# define LUA_INTEGER_SCAN "%d" |
| 1957 | +# define LUA_INTEGER_FMT "%d" |
| 1958 | +# else |
| 1959 | +/* Note: 'LUA_INTEGER' being 'ptrdiff_t' (as in Lua 5.1) causes problems with |
| 1960 | + * 'printf()' operations. Also 'unsigned ptrdiff_t' is invalid. |
| 1961 | + */ |
| 1962 | +# define LUA_INTEGER long |
| 1963 | +# define LUA_INTEGER_SCAN "%ld" |
| 1964 | +# define LUA_INTEGER_FMT "%ld" |
| 1965 | +# endif |
| 1966 | +# define LUA_INTEGER_MAX 0x7FFFFFFF /* 2^31-1 */ |
| 1967 | +/* */ |
| 1968 | +#elif defined(LNUM_INT64) |
| 1969 | +# define LUA_INTEGER long long |
| 1970 | +# ifdef _MSC_VER |
| 1971 | +# define lua_str2ul _strtoui64 |
| 1972 | +# else |
| 1973 | +# define lua_str2ul strtoull |
| 1974 | +# endif |
| 1975 | +# define LUA_INTEGER_SCAN "%lld" |
| 1976 | +# define LUA_INTEGER_FMT "%lld" |
| 1977 | +# define LUA_INTEGER_MAX 0x7fffffffffffffffLL /* 2^63-1 */ |
| 1978 | +# define LUA_INTEGER_MIN (-LUA_INTEGER_MAX - 1LL) /* -2^63 */ |
| 1979 | +/* */ |
| 1980 | +#elif defined(LNUM_INT16) |
| 1981 | +# if LUAI_BITSINT > 16 |
| 1982 | +# define LUA_INTEGER short |
| 1983 | +# define LUA_INTEGER_SCAN "%hd" |
| 1984 | +# define LUA_INTEGER_FMT "%hd" |
| 1985 | +# else |
| 1986 | +# define LUA_INTEGER int |
| 1987 | +# define LUA_INTEGER_SCAN "%d" |
| 1988 | +# define LUA_INTEGER_FMT "%d" |
| 1989 | +# endif |
| 1990 | +# define LUA_INTEGER_MAX 0x7FFF /* 2^16-1 */ |
| 1991 | +#endif |
| 1992 | + |
| 1993 | +#ifndef lua_str2ul |
| 1994 | +# define lua_str2ul (unsigned LUA_INTEGER)strtoul |
| 1995 | +#endif |
| 1996 | +#ifndef LUA_INTEGER_MIN |
| 1997 | +# define LUA_INTEGER_MIN (-LUA_INTEGER_MAX -1) /* -2^16|32 */ |
| 1998 | +#endif |
| 1999 | + |
| 2000 | +/* |
| 2001 | +@@ lua_number2int is a macro to convert lua_Number to int. |
| 2002 | +@@ lua_number2integer is a macro to convert lua_Number to lua_Integer. |
| 2003 | +** CHANGE them if you know a faster way to convert a lua_Number to |
| 2004 | +** int (with any rounding method and without throwing errors) in your |
| 2005 | +** system. In Pentium machines, a naive typecast from double to int |
| 2006 | +** in C is extremely slow, so any alternative is worth trying. |
| 2007 | +*/ |
| 2008 | + |
| 2009 | +/* On a Pentium, resort to a trick */ |
| 2010 | +#if defined(LNUM_DOUBLE) && !defined(LUA_ANSI) && !defined(__SSE2__) && \ |
| 2011 | + (defined(__i386) || defined (_M_IX86) || defined(__i386__)) |
| 2012 | + |
| 2013 | +/* On a Microsoft compiler, use assembler */ |
| 2014 | +# if defined(_MSC_VER) |
| 2015 | +# define lua_number2int(i,d) __asm fld d __asm fistp i |
| 2016 | +# else |
| 2017 | + |
| 2018 | +/* the next trick should work on any Pentium, but sometimes clashes |
| 2019 | + with a DirectX idiosyncrasy */ |
| 2020 | +union luai_Cast { double l_d; long l_l; }; |
| 2021 | +# define lua_number2int(i,d) \ |
| 2022 | + { volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; } |
| 2023 | +# endif |
| 2024 | + |
| 2025 | +# ifndef LNUM_INT64 |
| 2026 | +# define lua_number2integer lua_number2int |
| 2027 | +# endif |
| 2028 | + |
| 2029 | +/* this option always works, but may be slow */ |
| 2030 | +#else |
| 2031 | +# define lua_number2int(i,d) ((i)=(int)(d)) |
| 2032 | +#endif |
| 2033 | + |
| 2034 | +/* Note: Some compilers (OS X gcc 4.0?) may choke on double->long long conversion |
| 2035 | + * since it can lose precision. Others do require 'long long' there. |
| 2036 | + */ |
| 2037 | +#ifndef lua_number2integer |
| 2038 | +# define lua_number2integer(i,d) ((i)=(lua_Integer)(d)) |
| 2039 | +#endif |
| 2040 | + |
| 2041 | +/* |
| 2042 | +** 'luai_abs()' to give absolute value of 'lua_Integer' |
| 2043 | +*/ |
| 2044 | +#ifdef LNUM_INT32 |
| 2045 | +# define luai_abs abs |
| 2046 | +#elif defined(LNUM_INT64) && (__STDC_VERSION__ >= 199901L) |
| 2047 | +# define luai_abs llabs |
| 2048 | +#else |
| 2049 | +# define luai_abs(v) ((v) >= 0 ? (v) : -(v)) |
| 2050 | +#endif |
| 2051 | + |
| 2052 | +/* |
| 2053 | +** LUAI_UACNUMBER is the result of an 'usual argument conversion' over a number. |
| 2054 | +** LUAI_UACINTEGER the same, over an integer. |
| 2055 | +*/ |
| 2056 | +#define LUAI_UACNUMBER double |
| 2057 | +#define LUAI_UACINTEGER long |
| 2058 | + |
| 2059 | +/* ANSI C only has math funcs for 'double. C99 required for float and long double |
| 2060 | + * variants. |
| 2061 | + */ |
| 2062 | +#ifdef LNUM_DOUBLE |
| 2063 | +# define _LF(name) name |
| 2064 | +#elif defined(LNUM_FLOAT) |
| 2065 | +# define _LF(name) name ## f |
| 2066 | +#elif defined(LNUM_LDOUBLE) |
| 2067 | +# define _LF(name) name ## l |
| 2068 | +#endif |
| 2069 | + |
| 2070 | +#endif |
| 2071 | + |
| 2072 | --- a/src/lobject.c |
| 2073 | +++ b/src/lobject.c |
| 2074 | @@ -21,7 +21,8 @@ |
| 2075 | #include "lstate.h" |
| 2076 | #include "lstring.h" |
| 2077 | #include "lvm.h" |
| 2078 | - |
| 2079 | +#include "llex.h" |
| 2080 | +#include "lnum.h" |
| 2081 | |
| 2082 | |
| 2083 | const TValue luaO_nilobject_ = {{NULL}, LUA_TNIL}; |
| 2084 | @@ -70,12 +71,31 @@ int luaO_log2 (unsigned int x) { |
| 2085 | |
| 2086 | |
| 2087 | int luaO_rawequalObj (const TValue *t1, const TValue *t2) { |
| 2088 | - if (ttype(t1) != ttype(t2)) return 0; |
| 2089 | + if (!ttype_ext_same(t1,t2)) return 0; |
| 2090 | else switch (ttype(t1)) { |
| 2091 | case LUA_TNIL: |
| 2092 | return 1; |
| 2093 | + case LUA_TINT: |
| 2094 | + if (ttype(t2)==LUA_TINT) |
| 2095 | + return ivalue(t1) == ivalue(t2); |
| 2096 | + else { /* t1:int, t2:num */ |
| 2097 | +#ifdef LNUM_COMPLEX |
| 2098 | + if (nvalue_img_fast(t2) != 0) return 0; |
| 2099 | +#endif |
| 2100 | + /* Avoid doing accuracy losing cast, if possible. */ |
| 2101 | + lua_Integer tmp; |
| 2102 | + if (tt_integer_valued(t2,&tmp)) |
| 2103 | + return ivalue(t1) == tmp; |
| 2104 | + else |
| 2105 | + return luai_numeq( cast_num(ivalue(t1)), nvalue_fast(t2) ); |
| 2106 | + } |
| 2107 | case LUA_TNUMBER: |
| 2108 | - return luai_numeq(nvalue(t1), nvalue(t2)); |
| 2109 | + if (ttype(t2)==LUA_TINT) |
| 2110 | + return luaO_rawequalObj(t2, t1); /* swap LUA_TINT to left */ |
| 2111 | +#ifdef LNUM_COMPLEX |
| 2112 | + if (!luai_numeq(nvalue_img_fast(t1), nvalue_img_fast(t2))) return 0; |
| 2113 | +#endif |
| 2114 | + return luai_numeq(nvalue_fast(t1), nvalue_fast(t2)); |
| 2115 | case LUA_TBOOLEAN: |
| 2116 | return bvalue(t1) == bvalue(t2); /* boolean true must be 1 !! */ |
| 2117 | case LUA_TLIGHTUSERDATA: |
| 2118 | @@ -86,21 +106,6 @@ int luaO_rawequalObj (const TValue *t1, |
| 2119 | } |
| 2120 | } |
| 2121 | |
| 2122 | - |
| 2123 | -int luaO_str2d (const char *s, lua_Number *result) { |
| 2124 | - char *endptr; |
| 2125 | - *result = lua_str2number(s, &endptr); |
| 2126 | - if (endptr == s) return 0; /* conversion failed */ |
| 2127 | - if (*endptr == 'x' || *endptr == 'X') /* maybe an hexadecimal constant? */ |
| 2128 | - *result = cast_num(strtoul(s, &endptr, 16)); |
| 2129 | - if (*endptr == '\0') return 1; /* most common case */ |
| 2130 | - while (isspace(cast(unsigned char, *endptr))) endptr++; |
| 2131 | - if (*endptr != '\0') return 0; /* invalid trailing characters? */ |
| 2132 | - return 1; |
| 2133 | -} |
| 2134 | - |
| 2135 | - |
| 2136 | - |
| 2137 | static void pushstr (lua_State *L, const char *str) { |
| 2138 | setsvalue2s(L, L->top, luaS_new(L, str)); |
| 2139 | incr_top(L); |
| 2140 | @@ -131,7 +136,11 @@ const char *luaO_pushvfstring (lua_State |
| 2141 | break; |
| 2142 | } |
| 2143 | case 'd': { |
| 2144 | - setnvalue(L->top, cast_num(va_arg(argp, int))); |
| 2145 | + /* This is tricky for 64-bit integers; maybe they even cannot be |
| 2146 | + * supported on all compilers; depends on the conversions applied to |
| 2147 | + * variable argument lists. TBD: test! |
| 2148 | + */ |
| 2149 | + setivalue(L->top, (lua_Integer) va_arg(argp, l_uacInteger)); |
| 2150 | incr_top(L); |
| 2151 | break; |
| 2152 | } |
| 2153 | @@ -212,3 +221,4 @@ void luaO_chunkid (char *out, const char |
| 2154 | } |
| 2155 | } |
| 2156 | } |
| 2157 | + |
| 2158 | --- a/src/lobject.h |
| 2159 | +++ b/src/lobject.h |
| 2160 | @@ -17,7 +17,11 @@ |
| 2161 | |
| 2162 | |
| 2163 | /* tags for values visible from Lua */ |
| 2164 | -#define LAST_TAG LUA_TTHREAD |
| 2165 | +#if LUA_TINT > LUA_TTHREAD |
| 2166 | +# define LAST_TAG LUA_TINT |
| 2167 | +#else |
| 2168 | +# define LAST_TAG LUA_TTHREAD |
| 2169 | +#endif |
| 2170 | |
| 2171 | #define NUM_TAGS (LAST_TAG+1) |
| 2172 | |
| 2173 | @@ -59,7 +63,12 @@ typedef struct GCheader { |
| 2174 | typedef union { |
| 2175 | GCObject *gc; |
| 2176 | void *p; |
| 2177 | +#ifdef LNUM_COMPLEX |
| 2178 | + lua_Complex n; |
| 2179 | +#else |
| 2180 | lua_Number n; |
| 2181 | +#endif |
| 2182 | + lua_Integer i; |
| 2183 | int b; |
| 2184 | } Value; |
| 2185 | |
| 2186 | @@ -77,7 +86,11 @@ typedef struct lua_TValue { |
| 2187 | |
| 2188 | /* Macros to test type */ |
| 2189 | #define ttisnil(o) (ttype(o) == LUA_TNIL) |
| 2190 | -#define ttisnumber(o) (ttype(o) == LUA_TNUMBER) |
| 2191 | +#define ttisint(o) (ttype(o) == LUA_TINT) |
| 2192 | +#define ttisnumber(o) ((ttype(o) == LUA_TINT) || (ttype(o) == LUA_TNUMBER)) |
| 2193 | +#ifdef LNUM_COMPLEX |
| 2194 | +# define ttiscomplex(o) ((ttype(o) == LUA_TNUMBER) && (nvalue_img_fast(o)!=0)) |
| 2195 | +#endif |
| 2196 | #define ttisstring(o) (ttype(o) == LUA_TSTRING) |
| 2197 | #define ttistable(o) (ttype(o) == LUA_TTABLE) |
| 2198 | #define ttisfunction(o) (ttype(o) == LUA_TFUNCTION) |
| 2199 | @@ -90,7 +103,25 @@ typedef struct lua_TValue { |
| 2200 | #define ttype(o) ((o)->tt) |
| 2201 | #define gcvalue(o) check_exp(iscollectable(o), (o)->value.gc) |
| 2202 | #define pvalue(o) check_exp(ttislightuserdata(o), (o)->value.p) |
| 2203 | -#define nvalue(o) check_exp(ttisnumber(o), (o)->value.n) |
| 2204 | + |
| 2205 | +#define ttype_ext(o) ( ttype(o) == LUA_TINT ? LUA_TNUMBER : ttype(o) ) |
| 2206 | +#define ttype_ext_same(o1,o2) ( (ttype(o1)==ttype(o2)) || (ttisnumber(o1) && ttisnumber(o2)) ) |
| 2207 | + |
| 2208 | +/* '_fast' variants are for cases where 'ttype(o)' is known to be LUA_TNUMBER. |
| 2209 | + */ |
| 2210 | +#ifdef LNUM_COMPLEX |
| 2211 | +# define nvalue_complex_fast(o) check_exp( ttype(o)==LUA_TNUMBER, (o)->value.n ) |
| 2212 | +# define nvalue_fast(o) ( _LF(creal) ( nvalue_complex_fast(o) ) ) |
| 2213 | +# define nvalue_img_fast(o) ( _LF(cimag) ( nvalue_complex_fast(o) ) ) |
| 2214 | +# define nvalue_complex(o) check_exp( ttisnumber(o), (ttype(o)==LUA_TINT) ? (o)->value.i : (o)->value.n ) |
| 2215 | +# define nvalue_img(o) check_exp( ttisnumber(o), (ttype(o)==LUA_TINT) ? 0 : _LF(cimag)( (o)->value.n ) ) |
| 2216 | +# define nvalue(o) check_exp( ttisnumber(o), (ttype(o)==LUA_TINT) ? cast_num((o)->value.i) : _LF(creal)((o)->value.n) ) |
| 2217 | +#else |
| 2218 | +# define nvalue(o) check_exp( ttisnumber(o), (ttype(o)==LUA_TINT) ? cast_num((o)->value.i) : (o)->value.n ) |
| 2219 | +# define nvalue_fast(o) check_exp( ttype(o)==LUA_TNUMBER, (o)->value.n ) |
| 2220 | +#endif |
| 2221 | +#define ivalue(o) check_exp( ttype(o)==LUA_TINT, (o)->value.i ) |
| 2222 | + |
| 2223 | #define rawtsvalue(o) check_exp(ttisstring(o), &(o)->value.gc->ts) |
| 2224 | #define tsvalue(o) (&rawtsvalue(o)->tsv) |
| 2225 | #define rawuvalue(o) check_exp(ttisuserdata(o), &(o)->value.gc->u) |
| 2226 | @@ -116,8 +147,27 @@ typedef struct lua_TValue { |
| 2227 | /* Macros to set values */ |
| 2228 | #define setnilvalue(obj) ((obj)->tt=LUA_TNIL) |
| 2229 | |
| 2230 | -#define setnvalue(obj,x) \ |
| 2231 | - { TValue *i_o=(obj); i_o->value.n=(x); i_o->tt=LUA_TNUMBER; } |
| 2232 | +/* Must not have side effects, 'x' may be expression. |
| 2233 | +*/ |
| 2234 | +#define setivalue(obj,x) \ |
| 2235 | + { TValue *i_o=(obj); i_o->value.i=(x); i_o->tt=LUA_TINT; } |
| 2236 | + |
| 2237 | +# define setnvalue(obj,x) \ |
| 2238 | + { TValue *i_o=(obj); i_o->value.n= (x); i_o->tt=LUA_TNUMBER; } |
| 2239 | + |
| 2240 | +/* Note: Complex always has "inline", both are C99. |
| 2241 | +*/ |
| 2242 | +#ifdef LNUM_COMPLEX |
| 2243 | + static inline void setnvalue_complex_fast( TValue *obj, lua_Complex x ) { |
| 2244 | + lua_assert( _LF(cimag)(x) != 0 ); |
| 2245 | + obj->value.n= x; obj->tt= LUA_TNUMBER; |
| 2246 | + } |
| 2247 | + static inline void setnvalue_complex( TValue *obj, lua_Complex x ) { |
| 2248 | + if (_LF(cimag)(x) == 0) { setnvalue(obj, _LF(creal)(x)); } |
| 2249 | + else { obj->value.n= x; obj->tt= LUA_TNUMBER; } |
| 2250 | + } |
| 2251 | +#endif |
| 2252 | + |
| 2253 | |
| 2254 | #define setpvalue(obj,x) \ |
| 2255 | { TValue *i_o=(obj); i_o->value.p=(x); i_o->tt=LUA_TLIGHTUSERDATA; } |
| 2256 | @@ -155,9 +205,6 @@ typedef struct lua_TValue { |
| 2257 | i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TPROTO; \ |
| 2258 | checkliveness(G(L),i_o); } |
| 2259 | |
| 2260 | - |
| 2261 | - |
| 2262 | - |
| 2263 | #define setobj(L,obj1,obj2) \ |
| 2264 | { const TValue *o2=(obj2); TValue *o1=(obj1); \ |
| 2265 | o1->value = o2->value; o1->tt=o2->tt; \ |
| 2266 | @@ -185,8 +232,11 @@ typedef struct lua_TValue { |
| 2267 | |
| 2268 | #define setttype(obj, tt) (ttype(obj) = (tt)) |
| 2269 | |
| 2270 | - |
| 2271 | -#define iscollectable(o) (ttype(o) >= LUA_TSTRING) |
| 2272 | +#if LUA_TINT >= LUA_TSTRING |
| 2273 | +# define iscollectable(o) ((ttype(o) >= LUA_TSTRING) && (ttype(o) != LUA_TINT)) |
| 2274 | +#else |
| 2275 | +# define iscollectable(o) (ttype(o) >= LUA_TSTRING) |
| 2276 | +#endif |
| 2277 | |
| 2278 | |
| 2279 | |
| 2280 | @@ -370,12 +420,10 @@ LUAI_FUNC int luaO_log2 (unsigned int x) |
| 2281 | LUAI_FUNC int luaO_int2fb (unsigned int x); |
| 2282 | LUAI_FUNC int luaO_fb2int (int x); |
| 2283 | LUAI_FUNC int luaO_rawequalObj (const TValue *t1, const TValue *t2); |
| 2284 | -LUAI_FUNC int luaO_str2d (const char *s, lua_Number *result); |
| 2285 | LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt, |
| 2286 | va_list argp); |
| 2287 | LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...); |
| 2288 | LUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t len); |
| 2289 | |
| 2290 | - |
| 2291 | #endif |
| 2292 | |
| 2293 | --- a/src/loslib.c |
| 2294 | +++ b/src/loslib.c |
| 2295 | @@ -186,15 +186,30 @@ static int os_time (lua_State *L) { |
| 2296 | } |
| 2297 | if (t == (time_t)(-1)) |
| 2298 | lua_pushnil(L); |
| 2299 | - else |
| 2300 | - lua_pushnumber(L, (lua_Number)t); |
| 2301 | + else { |
| 2302 | + /* On float systems the pushed value must be an integer, NOT a number. |
| 2303 | + * Otherwise, accuracy is lost in the time_t->float conversion. |
| 2304 | + */ |
| 2305 | +#ifdef LNUM_FLOAT |
| 2306 | + lua_pushinteger(L, (lua_Integer) t); |
| 2307 | +#else |
| 2308 | + lua_pushnumber(L, (lua_Number) t); |
| 2309 | +#endif |
| 2310 | + } |
| 2311 | return 1; |
| 2312 | } |
| 2313 | |
| 2314 | |
| 2315 | static int os_difftime (lua_State *L) { |
| 2316 | +#ifdef LNUM_FLOAT |
| 2317 | + lua_Integer i= (lua_Integer) |
| 2318 | + difftime( (time_t)(luaL_checkinteger(L, 1)), |
| 2319 | + (time_t)(luaL_optinteger(L, 2, 0))); |
| 2320 | + lua_pushinteger(L, i); |
| 2321 | +#else |
| 2322 | lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)), |
| 2323 | (time_t)(luaL_optnumber(L, 2, 0)))); |
| 2324 | +#endif |
| 2325 | return 1; |
| 2326 | } |
| 2327 | |
| 2328 | --- a/src/lparser.c |
| 2329 | +++ b/src/lparser.c |
| 2330 | @@ -33,7 +33,6 @@ |
| 2331 | |
| 2332 | #define luaY_checklimit(fs,v,l,m) if ((v)>(l)) errorlimit(fs,l,m) |
| 2333 | |
| 2334 | - |
| 2335 | /* |
| 2336 | ** nodes for block list (list of active blocks) |
| 2337 | */ |
| 2338 | @@ -72,7 +71,7 @@ static void errorlimit (FuncState *fs, i |
| 2339 | const char *msg = (fs->f->linedefined == 0) ? |
| 2340 | luaO_pushfstring(fs->L, "main function has more than %d %s", limit, what) : |
| 2341 | luaO_pushfstring(fs->L, "function at line %d has more than %d %s", |
| 2342 | - fs->f->linedefined, limit, what); |
| 2343 | + (fs->f->linedefined), limit, what); |
| 2344 | luaX_lexerror(fs->ls, msg, 0); |
| 2345 | } |
| 2346 | |
| 2347 | @@ -733,6 +732,18 @@ static void simpleexp (LexState *ls, exp |
| 2348 | v->u.nval = ls->t.seminfo.r; |
| 2349 | break; |
| 2350 | } |
| 2351 | + case TK_INT: { |
| 2352 | + init_exp(v, VKINT, 0); |
| 2353 | + v->u.ival = ls->t.seminfo.i; |
| 2354 | + break; |
| 2355 | + } |
| 2356 | +#ifdef LNUM_COMPLEX |
| 2357 | + case TK_NUMBER2: { |
| 2358 | + init_exp(v, VKNUM2, 0); |
| 2359 | + v->u.nval = ls->t.seminfo.r; |
| 2360 | + break; |
| 2361 | + } |
| 2362 | +#endif |
| 2363 | case TK_STRING: { |
| 2364 | codestring(ls, v, ls->t.seminfo.ts); |
| 2365 | break; |
| 2366 | @@ -1079,7 +1090,7 @@ static void fornum (LexState *ls, TStrin |
| 2367 | if (testnext(ls, ',')) |
| 2368 | exp1(ls); /* optional step */ |
| 2369 | else { /* default step = 1 */ |
| 2370 | - luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1)); |
| 2371 | + luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_integerK(fs, 1)); |
| 2372 | luaK_reserveregs(fs, 1); |
| 2373 | } |
| 2374 | forbody(ls, base, line, 1, 1); |
| 2375 | --- a/src/lparser.h |
| 2376 | +++ b/src/lparser.h |
| 2377 | @@ -31,7 +31,11 @@ typedef enum { |
| 2378 | VRELOCABLE, /* info = instruction pc */ |
| 2379 | VNONRELOC, /* info = result register */ |
| 2380 | VCALL, /* info = instruction pc */ |
| 2381 | - VVARARG /* info = instruction pc */ |
| 2382 | + VVARARG, /* info = instruction pc */ |
| 2383 | + VKINT /* ival = integer value */ |
| 2384 | +#ifdef LNUM_COMPLEX |
| 2385 | + ,VKNUM2 /* nval = imaginary value */ |
| 2386 | +#endif |
| 2387 | } expkind; |
| 2388 | |
| 2389 | typedef struct expdesc { |
| 2390 | @@ -39,6 +43,7 @@ typedef struct expdesc { |
| 2391 | union { |
| 2392 | struct { int info, aux; } s; |
| 2393 | lua_Number nval; |
| 2394 | + lua_Integer ival; |
| 2395 | } u; |
| 2396 | int t; /* patch list of `exit when true' */ |
| 2397 | int f; /* patch list of `exit when false' */ |
| 2398 | --- a/src/lstrlib.c |
| 2399 | +++ b/src/lstrlib.c |
| 2400 | @@ -43,8 +43,8 @@ static ptrdiff_t posrelat (ptrdiff_t pos |
| 2401 | static int str_sub (lua_State *L) { |
| 2402 | size_t l; |
| 2403 | const char *s = luaL_checklstring(L, 1, &l); |
| 2404 | - ptrdiff_t start = posrelat(luaL_checkinteger(L, 2), l); |
| 2405 | - ptrdiff_t end = posrelat(luaL_optinteger(L, 3, -1), l); |
| 2406 | + ptrdiff_t start = posrelat(luaL_checkint32(L, 2), l); |
| 2407 | + ptrdiff_t end = posrelat(luaL_optint32(L, 3, -1), l); |
| 2408 | if (start < 1) start = 1; |
| 2409 | if (end > (ptrdiff_t)l) end = (ptrdiff_t)l; |
| 2410 | if (start <= end) |
| 2411 | @@ -106,8 +106,8 @@ static int str_rep (lua_State *L) { |
| 2412 | static int str_byte (lua_State *L) { |
| 2413 | size_t l; |
| 2414 | const char *s = luaL_checklstring(L, 1, &l); |
| 2415 | - ptrdiff_t posi = posrelat(luaL_optinteger(L, 2, 1), l); |
| 2416 | - ptrdiff_t pose = posrelat(luaL_optinteger(L, 3, posi), l); |
| 2417 | + ptrdiff_t posi = posrelat(luaL_optint32(L, 2, 1), l); |
| 2418 | + ptrdiff_t pose = posrelat(luaL_optint32(L, 3, posi), l); |
| 2419 | int n, i; |
| 2420 | if (posi <= 0) posi = 1; |
| 2421 | if ((size_t)pose > l) pose = l; |
| 2422 | @@ -496,7 +496,7 @@ static int str_find_aux (lua_State *L, i |
| 2423 | size_t l1, l2; |
| 2424 | const char *s = luaL_checklstring(L, 1, &l1); |
| 2425 | const char *p = luaL_checklstring(L, 2, &l2); |
| 2426 | - ptrdiff_t init = posrelat(luaL_optinteger(L, 3, 1), l1) - 1; |
| 2427 | + ptrdiff_t init = posrelat(luaL_optint32(L, 3, 1), l1) - 1; |
| 2428 | if (init < 0) init = 0; |
| 2429 | else if ((size_t)(init) > l1) init = (ptrdiff_t)l1; |
| 2430 | if (find && (lua_toboolean(L, 4) || /* explicit request? */ |
| 2431 | @@ -690,7 +690,7 @@ static int str_gsub (lua_State *L) { |
| 2432 | ** maximum size of each format specification (such as '%-099.99d') |
| 2433 | ** (+10 accounts for %99.99x plus margin of error) |
| 2434 | */ |
| 2435 | -#define MAX_FORMAT (sizeof(FLAGS) + sizeof(LUA_INTFRMLEN) + 10) |
| 2436 | +#define MAX_FORMAT (sizeof(FLAGS) + sizeof(LUA_INTEGER_FMT)-2 + 10) |
| 2437 | |
| 2438 | |
| 2439 | static void addquoted (lua_State *L, luaL_Buffer *b, int arg) { |
| 2440 | @@ -747,9 +747,9 @@ static const char *scanformat (lua_State |
| 2441 | static void addintlen (char *form) { |
| 2442 | size_t l = strlen(form); |
| 2443 | char spec = form[l - 1]; |
| 2444 | - strcpy(form + l - 1, LUA_INTFRMLEN); |
| 2445 | - form[l + sizeof(LUA_INTFRMLEN) - 2] = spec; |
| 2446 | - form[l + sizeof(LUA_INTFRMLEN) - 1] = '\0'; |
| 2447 | + const char *tmp= LUA_INTEGER_FMT; /* "%lld" or "%ld" */ |
| 2448 | + strcpy(form + l - 1, tmp+1); |
| 2449 | + form[l + sizeof(LUA_INTEGER_FMT)-4] = spec; |
| 2450 | } |
| 2451 | |
| 2452 | |
| 2453 | @@ -779,12 +779,12 @@ static int str_format (lua_State *L) { |
| 2454 | } |
| 2455 | case 'd': case 'i': { |
| 2456 | addintlen(form); |
| 2457 | - sprintf(buff, form, (LUA_INTFRM_T)luaL_checknumber(L, arg)); |
| 2458 | + sprintf(buff, form, luaL_checkinteger(L, arg)); |
| 2459 | break; |
| 2460 | } |
| 2461 | case 'o': case 'u': case 'x': case 'X': { |
| 2462 | addintlen(form); |
| 2463 | - sprintf(buff, form, (unsigned LUA_INTFRM_T)luaL_checknumber(L, arg)); |
| 2464 | + sprintf(buff, form, (unsigned LUA_INTEGER)luaL_checkinteger(L, arg)); |
| 2465 | break; |
| 2466 | } |
| 2467 | case 'e': case 'E': case 'f': |
| 2468 | --- a/src/ltable.c |
| 2469 | +++ b/src/ltable.c |
| 2470 | @@ -33,6 +33,7 @@ |
| 2471 | #include "lobject.h" |
| 2472 | #include "lstate.h" |
| 2473 | #include "ltable.h" |
| 2474 | +#include "lnum.h" |
| 2475 | |
| 2476 | |
| 2477 | /* |
| 2478 | @@ -51,25 +52,15 @@ |
| 2479 | |
| 2480 | #define hashstr(t,str) hashpow2(t, (str)->tsv.hash) |
| 2481 | #define hashboolean(t,p) hashpow2(t, p) |
| 2482 | - |
| 2483 | +#define hashint(t,i) hashpow2(t,i) |
| 2484 | |
| 2485 | /* |
| 2486 | ** for some types, it is better to avoid modulus by power of 2, as |
| 2487 | ** they tend to have many 2 factors. |
| 2488 | */ |
| 2489 | #define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1)|1)))) |
| 2490 | - |
| 2491 | - |
| 2492 | #define hashpointer(t,p) hashmod(t, IntPoint(p)) |
| 2493 | |
| 2494 | - |
| 2495 | -/* |
| 2496 | -** number of ints inside a lua_Number |
| 2497 | -*/ |
| 2498 | -#define numints cast_int(sizeof(lua_Number)/sizeof(int)) |
| 2499 | - |
| 2500 | - |
| 2501 | - |
| 2502 | #define dummynode (&dummynode_) |
| 2503 | |
| 2504 | static const Node dummynode_ = { |
| 2505 | @@ -80,27 +71,46 @@ static const Node dummynode_ = { |
| 2506 | |
| 2507 | /* |
| 2508 | ** hash for lua_Numbers |
| 2509 | +** |
| 2510 | +** for non-complex modes, never called with 'lua_Integer' value range (s.a. 0) |
| 2511 | */ |
| 2512 | static Node *hashnum (const Table *t, lua_Number n) { |
| 2513 | - unsigned int a[numints]; |
| 2514 | - int i; |
| 2515 | - if (luai_numeq(n, 0)) /* avoid problems with -0 */ |
| 2516 | - return gnode(t, 0); |
| 2517 | - memcpy(a, &n, sizeof(a)); |
| 2518 | - for (i = 1; i < numints; i++) a[0] += a[i]; |
| 2519 | - return hashmod(t, a[0]); |
| 2520 | + const unsigned int *p= cast(const unsigned int *,&n); |
| 2521 | + unsigned int sum= *p; |
| 2522 | + unsigned int m= sizeof(lua_Number)/sizeof(int); |
| 2523 | + unsigned int i; |
| 2524 | + /* OS X Intel has 'm'==4 and gives "Bus error" if the last integer of |
| 2525 | + * 'n' is read; the actual size of long double is only 80 bits = 10 bytes. |
| 2526 | + * Linux x86 has 'm'==3, and does not require reduction. |
| 2527 | + */ |
| 2528 | +#if defined(LNUM_LDOUBLE) && defined(__i386__) |
| 2529 | + if (m>3) m--; |
| 2530 | +#endif |
| 2531 | + for (i = 1; i < m; i++) sum += p[i]; |
| 2532 | + return hashmod(t, sum); |
| 2533 | } |
| 2534 | |
| 2535 | |
| 2536 | - |
| 2537 | /* |
| 2538 | ** returns the `main' position of an element in a table (that is, the index |
| 2539 | ** of its hash value) |
| 2540 | +** |
| 2541 | +** Floating point numbers with integer value give the hash position of the |
| 2542 | +** integer (so they use the same table position). |
| 2543 | */ |
| 2544 | static Node *mainposition (const Table *t, const TValue *key) { |
| 2545 | + lua_Integer i; |
| 2546 | switch (ttype(key)) { |
| 2547 | case LUA_TNUMBER: |
| 2548 | - return hashnum(t, nvalue(key)); |
| 2549 | + if (tt_integer_valued(key,&i)) |
| 2550 | + return hashint(t, i); |
| 2551 | +#ifdef LNUM_COMPLEX |
| 2552 | + if (nvalue_img_fast(key)!=0 && luai_numeq(nvalue_fast(key),0)) |
| 2553 | + return gnode(t, 0); /* 0 and -0 to give same hash */ |
| 2554 | +#endif |
| 2555 | + return hashnum(t, nvalue_fast(key)); |
| 2556 | + case LUA_TINT: |
| 2557 | + return hashint(t, ivalue(key)); |
| 2558 | case LUA_TSTRING: |
| 2559 | return hashstr(t, rawtsvalue(key)); |
| 2560 | case LUA_TBOOLEAN: |
| 2561 | @@ -116,16 +126,20 @@ static Node *mainposition (const Table * |
| 2562 | /* |
| 2563 | ** returns the index for `key' if `key' is an appropriate key to live in |
| 2564 | ** the array part of the table, -1 otherwise. |
| 2565 | +** |
| 2566 | +** Anything <=0 is taken as not being in the array part. |
| 2567 | */ |
| 2568 | -static int arrayindex (const TValue *key) { |
| 2569 | - if (ttisnumber(key)) { |
| 2570 | - lua_Number n = nvalue(key); |
| 2571 | - int k; |
| 2572 | - lua_number2int(k, n); |
| 2573 | - if (luai_numeq(cast_num(k), n)) |
| 2574 | - return k; |
| 2575 | +static int arrayindex (const TValue *key, int max) { |
| 2576 | + lua_Integer k; |
| 2577 | + switch( ttype(key) ) { |
| 2578 | + case LUA_TINT: |
| 2579 | + k= ivalue(key); break; |
| 2580 | + case LUA_TNUMBER: |
| 2581 | + if (tt_integer_valued(key,&k)) break; |
| 2582 | + default: |
| 2583 | + return -1; /* not to be used as array index */ |
| 2584 | } |
| 2585 | - return -1; /* `key' did not match some condition */ |
| 2586 | + return ((k>0) && (k <= max)) ? cast_int(k) : -1; |
| 2587 | } |
| 2588 | |
| 2589 | |
| 2590 | @@ -137,8 +151,8 @@ static int arrayindex (const TValue *key |
| 2591 | static int findindex (lua_State *L, Table *t, StkId key) { |
| 2592 | int i; |
| 2593 | if (ttisnil(key)) return -1; /* first iteration */ |
| 2594 | - i = arrayindex(key); |
| 2595 | - if (0 < i && i <= t->sizearray) /* is `key' inside array part? */ |
| 2596 | + i = arrayindex(key, t->sizearray); |
| 2597 | + if (i>0) /* inside array part? */ |
| 2598 | return i-1; /* yes; that's the index (corrected to C) */ |
| 2599 | else { |
| 2600 | Node *n = mainposition(t, key); |
| 2601 | @@ -163,7 +177,7 @@ int luaH_next (lua_State *L, Table *t, S |
| 2602 | int i = findindex(L, t, key); /* find original element */ |
| 2603 | for (i++; i < t->sizearray; i++) { /* try first array part */ |
| 2604 | if (!ttisnil(&t->array[i])) { /* a non-nil value? */ |
| 2605 | - setnvalue(key, cast_num(i+1)); |
| 2606 | + setivalue(key, i+1); |
| 2607 | setobj2s(L, key+1, &t->array[i]); |
| 2608 | return 1; |
| 2609 | } |
| 2610 | @@ -209,8 +223,8 @@ static int computesizes (int nums[], int |
| 2611 | |
| 2612 | |
| 2613 | static int countint (const TValue *key, int *nums) { |
| 2614 | - int k = arrayindex(key); |
| 2615 | - if (0 < k && k <= MAXASIZE) { /* is `key' an appropriate array index? */ |
| 2616 | + int k = arrayindex(key,MAXASIZE); |
| 2617 | + if (k>0) { /* appropriate array index? */ |
| 2618 | nums[ceillog2(k)]++; /* count as such */ |
| 2619 | return 1; |
| 2620 | } |
| 2621 | @@ -308,7 +322,7 @@ static void resize (lua_State *L, Table |
| 2622 | /* re-insert elements from vanishing slice */ |
| 2623 | for (i=nasize; i<oldasize; i++) { |
| 2624 | if (!ttisnil(&t->array[i])) |
| 2625 | - setobjt2t(L, luaH_setnum(L, t, i+1), &t->array[i]); |
| 2626 | + setobjt2t(L, luaH_setint(L, t, i+1), &t->array[i]); |
| 2627 | } |
| 2628 | /* shrink array */ |
| 2629 | luaM_reallocvector(L, t->array, oldasize, nasize, TValue); |
| 2630 | @@ -409,7 +423,9 @@ static TValue *newkey (lua_State *L, Tab |
| 2631 | othern = mainposition(t, key2tval(mp)); |
| 2632 | if (othern != mp) { /* is colliding node out of its main position? */ |
| 2633 | /* yes; move colliding node into free position */ |
| 2634 | - while (gnext(othern) != mp) othern = gnext(othern); /* find previous */ |
| 2635 | + while (gnext(othern) != mp) { |
| 2636 | + othern = gnext(othern); /* find previous */ |
| 2637 | + } |
| 2638 | gnext(othern) = n; /* redo the chain with `n' in place of `mp' */ |
| 2639 | *n = *mp; /* copy colliding node into free pos. (mp->next also goes) */ |
| 2640 | gnext(mp) = NULL; /* now `mp' is free */ |
| 2641 | @@ -432,17 +448,18 @@ static TValue *newkey (lua_State *L, Tab |
| 2642 | /* |
| 2643 | ** search function for integers |
| 2644 | */ |
| 2645 | -const TValue *luaH_getnum (Table *t, int key) { |
| 2646 | +const TValue *luaH_getint (Table *t, lua_Integer key) { |
| 2647 | /* (1 <= key && key <= t->sizearray) */ |
| 2648 | if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray)) |
| 2649 | return &t->array[key-1]; |
| 2650 | else { |
| 2651 | - lua_Number nk = cast_num(key); |
| 2652 | - Node *n = hashnum(t, nk); |
| 2653 | + Node *n = hashint(t, key); |
| 2654 | do { /* check whether `key' is somewhere in the chain */ |
| 2655 | - if (ttisnumber(gkey(n)) && luai_numeq(nvalue(gkey(n)), nk)) |
| 2656 | + if (ttisint(gkey(n)) && (ivalue(gkey(n)) == key)) { |
| 2657 | return gval(n); /* that's it */ |
| 2658 | - else n = gnext(n); |
| 2659 | + } else { |
| 2660 | + n = gnext(n); |
| 2661 | + } |
| 2662 | } while (n); |
| 2663 | return luaO_nilobject; |
| 2664 | } |
| 2665 | @@ -470,14 +487,12 @@ const TValue *luaH_get (Table *t, const |
| 2666 | switch (ttype(key)) { |
| 2667 | case LUA_TNIL: return luaO_nilobject; |
| 2668 | case LUA_TSTRING: return luaH_getstr(t, rawtsvalue(key)); |
| 2669 | + case LUA_TINT: return luaH_getint(t, ivalue(key)); |
| 2670 | case LUA_TNUMBER: { |
| 2671 | - int k; |
| 2672 | - lua_Number n = nvalue(key); |
| 2673 | - lua_number2int(k, n); |
| 2674 | - if (luai_numeq(cast_num(k), nvalue(key))) /* index is int? */ |
| 2675 | - return luaH_getnum(t, k); /* use specialized version */ |
| 2676 | - /* else go through */ |
| 2677 | - } |
| 2678 | + lua_Integer i; |
| 2679 | + if (tt_integer_valued(key,&i)) |
| 2680 | + return luaH_getint(t,i); |
| 2681 | + } /* pass through */ |
| 2682 | default: { |
| 2683 | Node *n = mainposition(t, key); |
| 2684 | do { /* check whether `key' is somewhere in the chain */ |
| 2685 | @@ -498,20 +513,25 @@ TValue *luaH_set (lua_State *L, Table *t |
| 2686 | return cast(TValue *, p); |
| 2687 | else { |
| 2688 | if (ttisnil(key)) luaG_runerror(L, "table index is nil"); |
| 2689 | - else if (ttisnumber(key) && luai_numisnan(nvalue(key))) |
| 2690 | - luaG_runerror(L, "table index is NaN"); |
| 2691 | + else if (ttype(key)==LUA_TNUMBER) { |
| 2692 | + lua_Integer k; |
| 2693 | + if (luai_numisnan(nvalue_fast(key))) |
| 2694 | + luaG_runerror(L, "table index is NaN"); |
| 2695 | + if (tt_integer_valued(key,&k)) |
| 2696 | + return luaH_setint(L, t, k); |
| 2697 | + } |
| 2698 | return newkey(L, t, key); |
| 2699 | } |
| 2700 | } |
| 2701 | |
| 2702 | |
| 2703 | -TValue *luaH_setnum (lua_State *L, Table *t, int key) { |
| 2704 | - const TValue *p = luaH_getnum(t, key); |
| 2705 | +TValue *luaH_setint (lua_State *L, Table *t, lua_Integer key) { |
| 2706 | + const TValue *p = luaH_getint(t, key); |
| 2707 | if (p != luaO_nilobject) |
| 2708 | return cast(TValue *, p); |
| 2709 | else { |
| 2710 | TValue k; |
| 2711 | - setnvalue(&k, cast_num(key)); |
| 2712 | + setivalue(&k, key); |
| 2713 | return newkey(L, t, &k); |
| 2714 | } |
| 2715 | } |
| 2716 | @@ -533,20 +553,21 @@ static int unbound_search (Table *t, uns |
| 2717 | unsigned int i = j; /* i is zero or a present index */ |
| 2718 | j++; |
| 2719 | /* find `i' and `j' such that i is present and j is not */ |
| 2720 | - while (!ttisnil(luaH_getnum(t, j))) { |
| 2721 | + while (!ttisnil(luaH_getint(t, j))) { |
| 2722 | i = j; |
| 2723 | j *= 2; |
| 2724 | if (j > cast(unsigned int, MAX_INT)) { /* overflow? */ |
| 2725 | /* table was built with bad purposes: resort to linear search */ |
| 2726 | - i = 1; |
| 2727 | - while (!ttisnil(luaH_getnum(t, i))) i++; |
| 2728 | - return i - 1; |
| 2729 | + for( i = 1; i<MAX_INT+1; i++ ) { |
| 2730 | + if (ttisnil(luaH_getint(t, i))) break; |
| 2731 | + } |
| 2732 | + return i - 1; /* up to MAX_INT */ |
| 2733 | } |
| 2734 | } |
| 2735 | /* now do a binary search between them */ |
| 2736 | while (j - i > 1) { |
| 2737 | unsigned int m = (i+j)/2; |
| 2738 | - if (ttisnil(luaH_getnum(t, m))) j = m; |
| 2739 | + if (ttisnil(luaH_getint(t, m))) j = m; |
| 2740 | else i = m; |
| 2741 | } |
| 2742 | return i; |
| 2743 | --- a/src/ltable.h |
| 2744 | +++ b/src/ltable.h |
| 2745 | @@ -18,8 +18,8 @@ |
| 2746 | #define key2tval(n) (&(n)->i_key.tvk) |
| 2747 | |
| 2748 | |
| 2749 | -LUAI_FUNC const TValue *luaH_getnum (Table *t, int key); |
| 2750 | -LUAI_FUNC TValue *luaH_setnum (lua_State *L, Table *t, int key); |
| 2751 | +LUAI_FUNC const TValue *luaH_getint (Table *t, lua_Integer key); |
| 2752 | +LUAI_FUNC TValue *luaH_setint (lua_State *L, Table *t, lua_Integer key); |
| 2753 | LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key); |
| 2754 | LUAI_FUNC TValue *luaH_setstr (lua_State *L, Table *t, TString *key); |
| 2755 | LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key); |
| 2756 | --- a/src/ltm.c |
| 2757 | +++ b/src/ltm.c |
| 2758 | @@ -19,7 +19,6 @@ |
| 2759 | #include "ltm.h" |
| 2760 | |
| 2761 | |
| 2762 | - |
| 2763 | const char *const luaT_typenames[] = { |
| 2764 | "nil", "boolean", "userdata", "number", |
| 2765 | "string", "table", "function", "userdata", "thread", |
| 2766 | @@ -67,6 +66,9 @@ const TValue *luaT_gettmbyobj (lua_State |
| 2767 | case LUA_TUSERDATA: |
| 2768 | mt = uvalue(o)->metatable; |
| 2769 | break; |
| 2770 | + case LUA_TINT: |
| 2771 | + mt = G(L)->mt[LUA_TNUMBER]; |
| 2772 | + break; |
| 2773 | default: |
| 2774 | mt = G(L)->mt[ttype(o)]; |
| 2775 | } |
| 2776 | --- a/src/lua.c |
| 2777 | +++ b/src/lua.c |
| 2778 | @@ -16,7 +16,7 @@ |
| 2779 | |
| 2780 | #include "lauxlib.h" |
| 2781 | #include "lualib.h" |
| 2782 | - |
| 2783 | +#include "llimits.h" |
| 2784 | |
| 2785 | |
| 2786 | static lua_State *globalL = NULL; |
| 2787 | @@ -382,6 +382,15 @@ int main (int argc, char **argv) { |
| 2788 | l_message(argv[0], "cannot create state: not enough memory"); |
| 2789 | return EXIT_FAILURE; |
| 2790 | } |
| 2791 | + /* Checking 'sizeof(lua_Integer)' cannot be made in preprocessor on all compilers. |
| 2792 | + */ |
| 2793 | +#ifdef LNUM_INT16 |
| 2794 | + lua_assert( sizeof(lua_Integer) == 2 ); |
| 2795 | +#elif defined(LNUM_INT32) |
| 2796 | + lua_assert( sizeof(lua_Integer) == 4 ); |
| 2797 | +#elif defined(LNUM_INT64) |
| 2798 | + lua_assert( sizeof(lua_Integer) == 8 ); |
| 2799 | +#endif |
| 2800 | s.argc = argc; |
| 2801 | s.argv = argv; |
| 2802 | status = lua_cpcall(L, &pmain, &s); |
| 2803 | --- a/src/lua.h |
| 2804 | +++ b/src/lua.h |
| 2805 | @@ -19,7 +19,7 @@ |
| 2806 | #define LUA_VERSION "Lua 5.1" |
| 2807 | #define LUA_RELEASE "Lua 5.1.5" |
| 2808 | #define LUA_VERSION_NUM 501 |
| 2809 | -#define LUA_COPYRIGHT "Copyright (C) 1994-2012 Lua.org, PUC-Rio" |
| 2810 | +#define LUA_COPYRIGHT "Copyright (C) 1994-2012 Lua.org, PUC-Rio" " (" LUA_LNUM ")" |
| 2811 | #define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes" |
| 2812 | |
| 2813 | |
| 2814 | @@ -71,6 +71,16 @@ typedef void * (*lua_Alloc) (void *ud, v |
| 2815 | */ |
| 2816 | #define LUA_TNONE (-1) |
| 2817 | |
| 2818 | +/* LUA_TINT is an internal type, not visible to applications. There are three |
| 2819 | + * potential values where it can be tweaked to (code autoadjusts to these): |
| 2820 | + * |
| 2821 | + * -2: not 'usual' type value; good since 'LUA_TINT' is not part of the API |
| 2822 | + * LUA_TNUMBER+1: shifts other type values upwards, breaking binary compatibility |
| 2823 | + * not acceptable for 5.1, maybe 5.2 onwards? |
| 2824 | + * 9: greater than existing (5.1) type values. |
| 2825 | +*/ |
| 2826 | +#define LUA_TINT (-2) |
| 2827 | + |
| 2828 | #define LUA_TNIL 0 |
| 2829 | #define LUA_TBOOLEAN 1 |
| 2830 | #define LUA_TLIGHTUSERDATA 2 |
| 2831 | @@ -139,6 +149,8 @@ LUA_API int (lua_isuserdata) |
| 2832 | LUA_API int (lua_type) (lua_State *L, int idx); |
| 2833 | LUA_API const char *(lua_typename) (lua_State *L, int tp); |
| 2834 | |
| 2835 | +LUA_API int (lua_isinteger) (lua_State *L, int idx); |
| 2836 | + |
| 2837 | LUA_API int (lua_equal) (lua_State *L, int idx1, int idx2); |
| 2838 | LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2); |
| 2839 | LUA_API int (lua_lessthan) (lua_State *L, int idx1, int idx2); |
| 2840 | @@ -244,6 +256,19 @@ LUA_API lua_Alloc (lua_getallocf) (lua_S |
| 2841 | LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud); |
| 2842 | |
| 2843 | |
| 2844 | +/* |
| 2845 | +* It is unnecessary to break Lua C API 'lua_tonumber()' compatibility, just |
| 2846 | +* because the Lua number type is complex. Most C modules would use scalars |
| 2847 | +* only. We'll introduce new 'lua_tocomplex' and 'lua_pushcomplex' for when |
| 2848 | +* the module really wants to use them. |
| 2849 | +*/ |
| 2850 | +#ifdef LNUM_COMPLEX |
| 2851 | + #include <complex.h> |
| 2852 | + typedef LUA_NUMBER complex lua_Complex; |
| 2853 | + LUA_API lua_Complex (lua_tocomplex) (lua_State *L, int idx); |
| 2854 | + LUA_API void (lua_pushcomplex) (lua_State *L, lua_Complex v); |
| 2855 | +#endif |
| 2856 | + |
| 2857 | |
| 2858 | /* |
| 2859 | ** =============================================================== |
| 2860 | @@ -268,7 +293,12 @@ LUA_API void lua_setallocf (lua_State *L |
| 2861 | #define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN) |
| 2862 | #define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD) |
| 2863 | #define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE) |
| 2864 | -#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0) |
| 2865 | + |
| 2866 | +#if LUA_TINT < 0 |
| 2867 | +# define lua_isnoneornil(L, n) ( (lua_type(L,(n)) <= 0) && (lua_type(L,(n)) != LUA_TINT) ) |
| 2868 | +#else |
| 2869 | +# define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0) |
| 2870 | +#endif |
| 2871 | |
| 2872 | #define lua_pushliteral(L, s) \ |
| 2873 | lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1) |
| 2874 | @@ -386,3 +416,4 @@ struct lua_Debug { |
| 2875 | |
| 2876 | |
| 2877 | #endif |
| 2878 | + |
| 2879 | --- a/src/luaconf.h |
| 2880 | +++ b/src/luaconf.h |
| 2881 | @@ -10,7 +10,9 @@ |
| 2882 | |
| 2883 | #include <limits.h> |
| 2884 | #include <stddef.h> |
| 2885 | - |
| 2886 | +#ifdef lua_assert |
| 2887 | +# include <assert.h> |
| 2888 | +#endif |
| 2889 | |
| 2890 | /* |
| 2891 | ** ================================================================== |
| 2892 | @@ -136,14 +138,38 @@ |
| 2893 | |
| 2894 | |
| 2895 | /* |
| 2896 | -@@ LUA_INTEGER is the integral type used by lua_pushinteger/lua_tointeger. |
| 2897 | -** CHANGE that if ptrdiff_t is not adequate on your machine. (On most |
| 2898 | -** machines, ptrdiff_t gives a good choice between int or long.) |
| 2899 | +@@ LUAI_BITSINT defines the number of bits in an int. |
| 2900 | +** CHANGE here if Lua cannot automatically detect the number of bits of |
| 2901 | +** your machine. Probably you do not need to change this. |
| 2902 | */ |
| 2903 | -#define LUA_INTEGER ptrdiff_t |
| 2904 | +/* avoid overflows in comparison */ |
| 2905 | +#if INT_MAX-20 < 32760 |
| 2906 | +#define LUAI_BITSINT 16 |
| 2907 | +#elif INT_MAX > 2147483640L |
| 2908 | +/* int has at least 32 bits */ |
| 2909 | +#define LUAI_BITSINT 32 |
| 2910 | +#else |
| 2911 | +#error "you must define LUA_BITSINT with number of bits in an integer" |
| 2912 | +#endif |
| 2913 | |
| 2914 | |
| 2915 | /* |
| 2916 | +@@ LNUM_DOUBLE |Â LNUM_FLOAT |Â LNUM_LDOUBLE: Generic Lua number mode |
| 2917 | +@@ LNUM_INT32 | LNUM_INT64: Integer type |
| 2918 | +@@ LNUM_COMPLEX: Define for using 'a+bi' numbers |
| 2919 | +@@ |
| 2920 | +@@ You can combine LNUM_xxx but only one of each group. I.e. '-DLNUM_FLOAT |
| 2921 | +@@ -DLNUM_INT32 -DLNUM_COMPLEX' gives float range complex numbers, with |
| 2922 | +@@ 32-bit scalar integer range optimized. |
| 2923 | +** |
| 2924 | +** These are kept in a separate configuration file mainly for ease of patching |
| 2925 | +** (can be changed if integerated to Lua proper). |
| 2926 | +*/ |
| 2927 | +/*#define LNUM_DOUBLE*/ |
| 2928 | +/*#define LNUM_INT32*/ |
| 2929 | +#include "lnum_config.h" |
| 2930 | + |
| 2931 | +/* |
| 2932 | @@ LUA_API is a mark for all core API functions. |
| 2933 | @@ LUALIB_API is a mark for all standard library functions. |
| 2934 | ** CHANGE them if you need to define those functions in some special way. |
| 2935 | @@ -383,22 +409,6 @@ |
| 2936 | |
| 2937 | |
| 2938 | /* |
| 2939 | -@@ LUAI_BITSINT defines the number of bits in an int. |
| 2940 | -** CHANGE here if Lua cannot automatically detect the number of bits of |
| 2941 | -** your machine. Probably you do not need to change this. |
| 2942 | -*/ |
| 2943 | -/* avoid overflows in comparison */ |
| 2944 | -#if INT_MAX-20 < 32760 |
| 2945 | -#define LUAI_BITSINT 16 |
| 2946 | -#elif INT_MAX > 2147483640L |
| 2947 | -/* int has at least 32 bits */ |
| 2948 | -#define LUAI_BITSINT 32 |
| 2949 | -#else |
| 2950 | -#error "you must define LUA_BITSINT with number of bits in an integer" |
| 2951 | -#endif |
| 2952 | - |
| 2953 | - |
| 2954 | -/* |
| 2955 | @@ LUAI_UINT32 is an unsigned integer with at least 32 bits. |
| 2956 | @@ LUAI_INT32 is an signed integer with at least 32 bits. |
| 2957 | @@ LUAI_UMEM is an unsigned integer big enough to count the total |
| 2958 | @@ -425,6 +435,15 @@ |
| 2959 | #define LUAI_MEM long |
| 2960 | #endif |
| 2961 | |
| 2962 | +/* |
| 2963 | +@@ LUAI_BOOL carries 0 and nonzero (normally 1). It may be defined as 'char' |
| 2964 | +** (to save memory), 'int' (for speed), 'bool' (for C++) or '_Bool' (C99) |
| 2965 | +*/ |
| 2966 | +#ifdef __cplusplus |
| 2967 | +# define LUAI_BOOL bool |
| 2968 | +#else |
| 2969 | +# define LUAI_BOOL int |
| 2970 | +#endif |
| 2971 | |
| 2972 | /* |
| 2973 | @@ LUAI_MAXCALLS limits the number of nested calls. |
| 2974 | @@ -490,101 +509,6 @@ |
| 2975 | /* }================================================================== */ |
| 2976 | |
| 2977 | |
| 2978 | - |
| 2979 | - |
| 2980 | -/* |
| 2981 | -** {================================================================== |
| 2982 | -@@ LUA_NUMBER is the type of numbers in Lua. |
| 2983 | -** CHANGE the following definitions only if you want to build Lua |
| 2984 | -** with a number type different from double. You may also need to |
| 2985 | -** change lua_number2int & lua_number2integer. |
| 2986 | -** =================================================================== |
| 2987 | -*/ |
| 2988 | - |
| 2989 | -#define LUA_NUMBER_DOUBLE |
| 2990 | -#define LUA_NUMBER double |
| 2991 | - |
| 2992 | -/* |
| 2993 | -@@ LUAI_UACNUMBER is the result of an 'usual argument conversion' |
| 2994 | -@* over a number. |
| 2995 | -*/ |
| 2996 | -#define LUAI_UACNUMBER double |
| 2997 | - |
| 2998 | - |
| 2999 | -/* |
| 3000 | -@@ LUA_NUMBER_SCAN is the format for reading numbers. |
| 3001 | -@@ LUA_NUMBER_FMT is the format for writing numbers. |
| 3002 | -@@ lua_number2str converts a number to a string. |
| 3003 | -@@ LUAI_MAXNUMBER2STR is maximum size of previous conversion. |
| 3004 | -@@ lua_str2number converts a string to a number. |
| 3005 | -*/ |
| 3006 | -#define LUA_NUMBER_SCAN "%lf" |
| 3007 | -#define LUA_NUMBER_FMT "%.14g" |
| 3008 | -#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n)) |
| 3009 | -#define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */ |
| 3010 | -#define lua_str2number(s,p) strtod((s), (p)) |
| 3011 | - |
| 3012 | - |
| 3013 | -/* |
| 3014 | -@@ The luai_num* macros define the primitive operations over numbers. |
| 3015 | -*/ |
| 3016 | -#if defined(LUA_CORE) |
| 3017 | -#include <math.h> |
| 3018 | -#define luai_numadd(a,b) ((a)+(b)) |
| 3019 | -#define luai_numsub(a,b) ((a)-(b)) |
| 3020 | -#define luai_nummul(a,b) ((a)*(b)) |
| 3021 | -#define luai_numdiv(a,b) ((a)/(b)) |
| 3022 | -#define luai_nummod(a,b) ((a) - floor((a)/(b))*(b)) |
| 3023 | -#define luai_numpow(a,b) (pow(a,b)) |
| 3024 | -#define luai_numunm(a) (-(a)) |
| 3025 | -#define luai_numeq(a,b) ((a)==(b)) |
| 3026 | -#define luai_numlt(a,b) ((a)<(b)) |
| 3027 | -#define luai_numle(a,b) ((a)<=(b)) |
| 3028 | -#define luai_numisnan(a) (!luai_numeq((a), (a))) |
| 3029 | -#endif |
| 3030 | - |
| 3031 | - |
| 3032 | -/* |
| 3033 | -@@ lua_number2int is a macro to convert lua_Number to int. |
| 3034 | -@@ lua_number2integer is a macro to convert lua_Number to lua_Integer. |
| 3035 | -** CHANGE them if you know a faster way to convert a lua_Number to |
| 3036 | -** int (with any rounding method and without throwing errors) in your |
| 3037 | -** system. In Pentium machines, a naive typecast from double to int |
| 3038 | -** in C is extremely slow, so any alternative is worth trying. |
| 3039 | -*/ |
| 3040 | - |
| 3041 | -/* On a Pentium, resort to a trick */ |
| 3042 | -#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) && !defined(__SSE2__) && \ |
| 3043 | - (defined(__i386) || defined (_M_IX86) || defined(__i386__)) |
| 3044 | - |
| 3045 | -/* On a Microsoft compiler, use assembler */ |
| 3046 | -#if defined(_MSC_VER) |
| 3047 | - |
| 3048 | -#define lua_number2int(i,d) __asm fld d __asm fistp i |
| 3049 | -#define lua_number2integer(i,n) lua_number2int(i, n) |
| 3050 | - |
| 3051 | -/* the next trick should work on any Pentium, but sometimes clashes |
| 3052 | - with a DirectX idiosyncrasy */ |
| 3053 | -#else |
| 3054 | - |
| 3055 | -union luai_Cast { double l_d; long l_l; }; |
| 3056 | -#define lua_number2int(i,d) \ |
| 3057 | - { volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; } |
| 3058 | -#define lua_number2integer(i,n) lua_number2int(i, n) |
| 3059 | - |
| 3060 | -#endif |
| 3061 | - |
| 3062 | - |
| 3063 | -/* this option always works, but may be slow */ |
| 3064 | -#else |
| 3065 | -#define lua_number2int(i,d) ((i)=(int)(d)) |
| 3066 | -#define lua_number2integer(i,d) ((i)=(lua_Integer)(d)) |
| 3067 | - |
| 3068 | -#endif |
| 3069 | - |
| 3070 | -/* }================================================================== */ |
| 3071 | - |
| 3072 | - |
| 3073 | /* |
| 3074 | @@ LUAI_USER_ALIGNMENT_T is a type that requires maximum alignment. |
| 3075 | ** CHANGE it if your system requires alignments larger than double. (For |
| 3076 | @@ -728,28 +652,6 @@ union luai_Cast { double l_d; long l_l; |
| 3077 | #define luai_userstateyield(L,n) ((void)L) |
| 3078 | |
| 3079 | |
| 3080 | -/* |
| 3081 | -@@ LUA_INTFRMLEN is the length modifier for integer conversions |
| 3082 | -@* in 'string.format'. |
| 3083 | -@@ LUA_INTFRM_T is the integer type correspoding to the previous length |
| 3084 | -@* modifier. |
| 3085 | -** CHANGE them if your system supports long long or does not support long. |
| 3086 | -*/ |
| 3087 | - |
| 3088 | -#if defined(LUA_USELONGLONG) |
| 3089 | - |
| 3090 | -#define LUA_INTFRMLEN "ll" |
| 3091 | -#define LUA_INTFRM_T long long |
| 3092 | - |
| 3093 | -#else |
| 3094 | - |
| 3095 | -#define LUA_INTFRMLEN "l" |
| 3096 | -#define LUA_INTFRM_T long |
| 3097 | - |
| 3098 | -#endif |
| 3099 | - |
| 3100 | - |
| 3101 | - |
| 3102 | /* =================================================================== */ |
| 3103 | |
| 3104 | /* |
| 3105 | --- a/src/lundump.c |
| 3106 | +++ b/src/lundump.c |
| 3107 | @@ -73,6 +73,13 @@ static lua_Number LoadNumber(LoadState* |
| 3108 | return x; |
| 3109 | } |
| 3110 | |
| 3111 | +static lua_Integer LoadInteger(LoadState* S) |
| 3112 | +{ |
| 3113 | + lua_Integer x; |
| 3114 | + LoadVar(S,x); |
| 3115 | + return x; |
| 3116 | +} |
| 3117 | + |
| 3118 | static TString* LoadString(LoadState* S) |
| 3119 | { |
| 3120 | size_t size; |
| 3121 | @@ -119,6 +126,9 @@ static void LoadConstants(LoadState* S, |
| 3122 | case LUA_TNUMBER: |
| 3123 | setnvalue(o,LoadNumber(S)); |
| 3124 | break; |
| 3125 | + case LUA_TINT: /* Integer type saved in bytecode (see lcode.c) */ |
| 3126 | + setivalue(o,LoadInteger(S)); |
| 3127 | + break; |
| 3128 | case LUA_TSTRING: |
| 3129 | setsvalue2n(S->L,o,LoadString(S)); |
| 3130 | break; |
| 3131 | @@ -223,5 +233,22 @@ void luaU_header (char* h) |
| 3132 | *h++=(char)sizeof(size_t); |
| 3133 | *h++=(char)sizeof(Instruction); |
| 3134 | *h++=(char)sizeof(lua_Number); |
| 3135 | - *h++=(char)(((lua_Number)0.5)==0); /* is lua_Number integral? */ |
| 3136 | + |
| 3137 | + /* |
| 3138 | + * Last byte of header (0/1 in unpatched Lua 5.1.3): |
| 3139 | + * |
| 3140 | + * 0: lua_Number is float or double, lua_Integer not used. (nonpatched only) |
| 3141 | + * 1: lua_Number is integer (nonpatched only) |
| 3142 | + * |
| 3143 | + * +2: LNUM_INT16: sizeof(lua_Integer) |
| 3144 | + * +4: LNUM_INT32: sizeof(lua_Integer) |
| 3145 | + * +8: LNUM_INT64: sizeof(lua_Integer) |
| 3146 | + * |
| 3147 | + * +0x80: LNUM_COMPLEX |
| 3148 | + */ |
| 3149 | + *h++ = (char)(sizeof(lua_Integer) |
| 3150 | +#ifdef LNUM_COMPLEX |
| 3151 | + | 0x80 |
| 3152 | +#endif |
| 3153 | + ); |
| 3154 | } |
| 3155 | --- a/src/lvm.c |
| 3156 | +++ b/src/lvm.c |
| 3157 | @@ -25,22 +25,35 @@ |
| 3158 | #include "ltable.h" |
| 3159 | #include "ltm.h" |
| 3160 | #include "lvm.h" |
| 3161 | - |
| 3162 | - |
| 3163 | +#include "llex.h" |
| 3164 | +#include "lnum.h" |
| 3165 | |
| 3166 | /* limit for table tag-method chains (to avoid loops) */ |
| 3167 | #define MAXTAGLOOP 100 |
| 3168 | |
| 3169 | |
| 3170 | -const TValue *luaV_tonumber (const TValue *obj, TValue *n) { |
| 3171 | - lua_Number num; |
| 3172 | +/* |
| 3173 | + * If 'obj' is a string, it is tried to be interpreted as a number. |
| 3174 | + */ |
| 3175 | +const TValue *luaV_tonumber ( const TValue *obj, TValue *n) { |
| 3176 | + lua_Number d; |
| 3177 | + lua_Integer i; |
| 3178 | + |
| 3179 | if (ttisnumber(obj)) return obj; |
| 3180 | - if (ttisstring(obj) && luaO_str2d(svalue(obj), &num)) { |
| 3181 | - setnvalue(n, num); |
| 3182 | - return n; |
| 3183 | - } |
| 3184 | - else |
| 3185 | - return NULL; |
| 3186 | + |
| 3187 | + if (ttisstring(obj)) { |
| 3188 | + switch( luaO_str2d( svalue(obj), &d, &i ) ) { |
| 3189 | + case TK_INT: |
| 3190 | + setivalue(n,i); return n; |
| 3191 | + case TK_NUMBER: |
| 3192 | + setnvalue(n,d); return n; |
| 3193 | +#ifdef LNUM_COMPLEX |
| 3194 | + case TK_NUMBER2: /* "N.NNNi", != 0 */ |
| 3195 | + setnvalue_complex_fast(n, d*I); return n; |
| 3196 | +#endif |
| 3197 | + } |
| 3198 | + } |
| 3199 | + return NULL; |
| 3200 | } |
| 3201 | |
| 3202 | |
| 3203 | @@ -49,8 +62,7 @@ int luaV_tostring (lua_State *L, StkId o |
| 3204 | return 0; |
| 3205 | else { |
| 3206 | char s[LUAI_MAXNUMBER2STR]; |
| 3207 | - lua_Number n = nvalue(obj); |
| 3208 | - lua_number2str(s, n); |
| 3209 | + luaO_num2buf(s,obj); |
| 3210 | setsvalue2s(L, obj, luaS_new(L, s)); |
| 3211 | return 1; |
| 3212 | } |
| 3213 | @@ -222,59 +234,127 @@ static int l_strcmp (const TString *ls, |
| 3214 | } |
| 3215 | |
| 3216 | |
| 3217 | +#ifdef LNUM_COMPLEX |
| 3218 | +void error_complex( lua_State *L, const TValue *l, const TValue *r ) |
| 3219 | +{ |
| 3220 | + char buf1[ LUAI_MAXNUMBER2STR ]; |
| 3221 | + char buf2[ LUAI_MAXNUMBER2STR ]; |
| 3222 | + luaO_num2buf( buf1, l ); |
| 3223 | + luaO_num2buf( buf2, r ); |
| 3224 | + luaG_runerror( L, "unable to compare: %s with %s", buf1, buf2 ); |
| 3225 | + /* no return */ |
| 3226 | +} |
| 3227 | +#endif |
| 3228 | + |
| 3229 | + |
| 3230 | int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { |
| 3231 | int res; |
| 3232 | - if (ttype(l) != ttype(r)) |
| 3233 | + int tl,tr; |
| 3234 | + lua_Integer tmp; |
| 3235 | + |
| 3236 | + if (!ttype_ext_same(l,r)) |
| 3237 | return luaG_ordererror(L, l, r); |
| 3238 | - else if (ttisnumber(l)) |
| 3239 | - return luai_numlt(nvalue(l), nvalue(r)); |
| 3240 | - else if (ttisstring(l)) |
| 3241 | - return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0; |
| 3242 | - else if ((res = call_orderTM(L, l, r, TM_LT)) != -1) |
| 3243 | +#ifdef LNUM_COMPLEX |
| 3244 | + if ( (nvalue_img(l)!=0) || (nvalue_img(r)!=0) ) |
| 3245 | + error_complex( L, l, r ); |
| 3246 | +#endif |
| 3247 | + tl= ttype(l); tr= ttype(r); |
| 3248 | + if (tl==tr) { /* clear arithmetics */ |
| 3249 | + switch(tl) { |
| 3250 | + case LUA_TINT: return ivalue(l) < ivalue(r); |
| 3251 | + case LUA_TNUMBER: return luai_numlt(nvalue_fast(l), nvalue_fast(r)); |
| 3252 | + case LUA_TSTRING: return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0; |
| 3253 | + } |
| 3254 | + } else if (tl==LUA_TINT) { /* l:int, r:num */ |
| 3255 | + /* Avoid accuracy losing casts: if 'r' is integer by value, do comparisons |
| 3256 | + * in integer realm. Only otherwise cast 'l' to FP (which might change its |
| 3257 | + * value). |
| 3258 | + */ |
| 3259 | + if (tt_integer_valued(r,&tmp)) |
| 3260 | + return ivalue(l) < tmp; |
| 3261 | + else |
| 3262 | + return luai_numlt( cast_num(ivalue(l)), nvalue_fast(r) ); |
| 3263 | + |
| 3264 | + } else if (tl==LUA_TNUMBER) { /* l:num, r:int */ |
| 3265 | + if (tt_integer_valued(l,&tmp)) |
| 3266 | + return tmp < ivalue(r); |
| 3267 | + else |
| 3268 | + return luai_numlt( nvalue_fast(l), cast_num(ivalue(r)) ); |
| 3269 | + |
| 3270 | + } else if ((res = call_orderTM(L, l, r, TM_LT)) != -1) |
| 3271 | return res; |
| 3272 | + |
| 3273 | return luaG_ordererror(L, l, r); |
| 3274 | } |
| 3275 | |
| 3276 | |
| 3277 | static int lessequal (lua_State *L, const TValue *l, const TValue *r) { |
| 3278 | int res; |
| 3279 | - if (ttype(l) != ttype(r)) |
| 3280 | + int tl, tr; |
| 3281 | + lua_Integer tmp; |
| 3282 | + |
| 3283 | + if (!ttype_ext_same(l,r)) |
| 3284 | return luaG_ordererror(L, l, r); |
| 3285 | - else if (ttisnumber(l)) |
| 3286 | - return luai_numle(nvalue(l), nvalue(r)); |
| 3287 | - else if (ttisstring(l)) |
| 3288 | - return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0; |
| 3289 | - else if ((res = call_orderTM(L, l, r, TM_LE)) != -1) /* first try `le' */ |
| 3290 | +#ifdef LNUM_COMPLEX |
| 3291 | + if ( (nvalue_img(l)!=0) || (nvalue_img(r)!=0) ) |
| 3292 | + error_complex( L, l, r ); |
| 3293 | +#endif |
| 3294 | + tl= ttype(l); tr= ttype(r); |
| 3295 | + if (tl==tr) { /* clear arithmetics */ |
| 3296 | + switch(tl) { |
| 3297 | + case LUA_TINT: return ivalue(l) <= ivalue(r); |
| 3298 | + case LUA_TNUMBER: return luai_numle(nvalue_fast(l), nvalue_fast(r)); |
| 3299 | + case LUA_TSTRING: return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0; |
| 3300 | + } |
| 3301 | + } |
| 3302 | + if (tl==LUA_TINT) { /* l:int, r:num */ |
| 3303 | + if (tt_integer_valued(r,&tmp)) |
| 3304 | + return ivalue(l) <= tmp; |
| 3305 | + else |
| 3306 | + return luai_numle( cast_num(ivalue(l)), nvalue_fast(r) ); |
| 3307 | + |
| 3308 | + } else if (tl==LUA_TNUMBER) { /* l:num, r:int */ |
| 3309 | + if (tt_integer_valued(l,&tmp)) |
| 3310 | + return tmp <= ivalue(r); |
| 3311 | + else |
| 3312 | + return luai_numle( nvalue_fast(l), cast_num(ivalue(r)) ); |
| 3313 | + |
| 3314 | + } else if ((res = call_orderTM(L, l, r, TM_LE)) != -1) /* first try `le' */ |
| 3315 | return res; |
| 3316 | else if ((res = call_orderTM(L, r, l, TM_LT)) != -1) /* else try `lt' */ |
| 3317 | return !res; |
| 3318 | + |
| 3319 | return luaG_ordererror(L, l, r); |
| 3320 | } |
| 3321 | |
| 3322 | |
| 3323 | -int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2) { |
| 3324 | +/* Note: 'luaV_equalval()' and 'luaO_rawequalObj()' have largely overlapping |
| 3325 | + * implementation. LUA_TNIL..LUA_TLIGHTUSERDATA cases could be handled |
| 3326 | + * simply by the 'default' case here. |
| 3327 | + */ |
| 3328 | +int luaV_equalval (lua_State *L, const TValue *l, const TValue *r) { |
| 3329 | const TValue *tm; |
| 3330 | - lua_assert(ttype(t1) == ttype(t2)); |
| 3331 | - switch (ttype(t1)) { |
| 3332 | + lua_assert(ttype_ext_same(l,r)); |
| 3333 | + switch (ttype(l)) { |
| 3334 | case LUA_TNIL: return 1; |
| 3335 | - case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2)); |
| 3336 | - case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */ |
| 3337 | - case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2); |
| 3338 | + case LUA_TINT: |
| 3339 | + case LUA_TNUMBER: return luaO_rawequalObj(l,r); |
| 3340 | + case LUA_TBOOLEAN: return bvalue(l) == bvalue(r); /* true must be 1 !! */ |
| 3341 | + case LUA_TLIGHTUSERDATA: return pvalue(l) == pvalue(r); |
| 3342 | case LUA_TUSERDATA: { |
| 3343 | - if (uvalue(t1) == uvalue(t2)) return 1; |
| 3344 | - tm = get_compTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable, |
| 3345 | - TM_EQ); |
| 3346 | + if (uvalue(l) == uvalue(r)) return 1; |
| 3347 | + tm = get_compTM(L, uvalue(l)->metatable, uvalue(r)->metatable, TM_EQ); |
| 3348 | break; /* will try TM */ |
| 3349 | } |
| 3350 | case LUA_TTABLE: { |
| 3351 | - if (hvalue(t1) == hvalue(t2)) return 1; |
| 3352 | - tm = get_compTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ); |
| 3353 | + if (hvalue(l) == hvalue(r)) return 1; |
| 3354 | + tm = get_compTM(L, hvalue(l)->metatable, hvalue(r)->metatable, TM_EQ); |
| 3355 | break; /* will try TM */ |
| 3356 | } |
| 3357 | - default: return gcvalue(t1) == gcvalue(t2); |
| 3358 | + default: return gcvalue(l) == gcvalue(r); |
| 3359 | } |
| 3360 | if (tm == NULL) return 0; /* no TM? */ |
| 3361 | - callTMres(L, L->top, tm, t1, t2); /* call TM */ |
| 3362 | + callTMres(L, L->top, tm, l, r); /* call TM */ |
| 3363 | return !l_isfalse(L->top); |
| 3364 | } |
| 3365 | |
| 3366 | @@ -314,30 +394,6 @@ void luaV_concat (lua_State *L, int tota |
| 3367 | } |
| 3368 | |
| 3369 | |
| 3370 | -static void Arith (lua_State *L, StkId ra, const TValue *rb, |
| 3371 | - const TValue *rc, TMS op) { |
| 3372 | - TValue tempb, tempc; |
| 3373 | - const TValue *b, *c; |
| 3374 | - if ((b = luaV_tonumber(rb, &tempb)) != NULL && |
| 3375 | - (c = luaV_tonumber(rc, &tempc)) != NULL) { |
| 3376 | - lua_Number nb = nvalue(b), nc = nvalue(c); |
| 3377 | - switch (op) { |
| 3378 | - case TM_ADD: setnvalue(ra, luai_numadd(nb, nc)); break; |
| 3379 | - case TM_SUB: setnvalue(ra, luai_numsub(nb, nc)); break; |
| 3380 | - case TM_MUL: setnvalue(ra, luai_nummul(nb, nc)); break; |
| 3381 | - case TM_DIV: setnvalue(ra, luai_numdiv(nb, nc)); break; |
| 3382 | - case TM_MOD: setnvalue(ra, luai_nummod(nb, nc)); break; |
| 3383 | - case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); break; |
| 3384 | - case TM_UNM: setnvalue(ra, luai_numunm(nb)); break; |
| 3385 | - default: lua_assert(0); break; |
| 3386 | - } |
| 3387 | - } |
| 3388 | - else if (!call_binTM(L, rb, rc, ra, op)) |
| 3389 | - luaG_aritherror(L, rb, rc); |
| 3390 | -} |
| 3391 | - |
| 3392 | - |
| 3393 | - |
| 3394 | /* |
| 3395 | ** some macros for common tasks in `luaV_execute' |
| 3396 | */ |
| 3397 | @@ -361,17 +417,154 @@ static void Arith (lua_State *L, StkId r |
| 3398 | #define Protect(x) { L->savedpc = pc; {x;}; base = L->base; } |
| 3399 | |
| 3400 | |
| 3401 | -#define arith_op(op,tm) { \ |
| 3402 | - TValue *rb = RKB(i); \ |
| 3403 | - TValue *rc = RKC(i); \ |
| 3404 | - if (ttisnumber(rb) && ttisnumber(rc)) { \ |
| 3405 | - lua_Number nb = nvalue(rb), nc = nvalue(rc); \ |
| 3406 | - setnvalue(ra, op(nb, nc)); \ |
| 3407 | - } \ |
| 3408 | - else \ |
| 3409 | - Protect(Arith(L, ra, rb, rc, tm)); \ |
| 3410 | +/* Note: if called for unary operations, 'rc'=='rb'. |
| 3411 | + */ |
| 3412 | +static void Arith (lua_State *L, StkId ra, const TValue *rb, |
| 3413 | + const TValue *rc, TMS op) { |
| 3414 | + TValue tempb, tempc; |
| 3415 | + const TValue *b, *c; |
| 3416 | + lua_Number nb,nc; |
| 3417 | + |
| 3418 | + if ((b = luaV_tonumber(rb, &tempb)) != NULL && |
| 3419 | + (c = luaV_tonumber(rc, &tempc)) != NULL) { |
| 3420 | + |
| 3421 | + /* Keep integer arithmetics in the integer realm, if possible. |
| 3422 | + */ |
| 3423 | + if (ttisint(b) && ttisint(c)) { |
| 3424 | + lua_Integer ib = ivalue(b), ic = ivalue(c); |
| 3425 | + lua_Integer *ri = &ra->value.i; |
| 3426 | + ra->tt= LUA_TINT; /* part of 'setivalue(ra)' */ |
| 3427 | + switch (op) { |
| 3428 | + case TM_ADD: if (try_addint( ri, ib, ic)) return; break; |
| 3429 | + case TM_SUB: if (try_subint( ri, ib, ic)) return; break; |
| 3430 | + case TM_MUL: if (try_mulint( ri, ib, ic)) return; break; |
| 3431 | + case TM_DIV: if (try_divint( ri, ib, ic)) return; break; |
| 3432 | + case TM_MOD: if (try_modint( ri, ib, ic)) return; break; |
| 3433 | + case TM_POW: if (try_powint( ri, ib, ic)) return; break; |
| 3434 | + case TM_UNM: if (try_unmint( ri, ib)) return; break; |
| 3435 | + default: lua_assert(0); |
| 3436 | } |
| 3437 | + } |
| 3438 | + /* Fallback to floating point, when leaving range. */ |
| 3439 | |
| 3440 | +#ifdef LNUM_COMPLEX |
| 3441 | + if ((nvalue_img(b)!=0) || (nvalue_img(c)!=0)) { |
| 3442 | + lua_Complex r; |
| 3443 | + if (op==TM_UNM) { |
| 3444 | + r= -nvalue_complex_fast(b); /* never an integer (or scalar) */ |
| 3445 | + setnvalue_complex_fast( ra, r ); |
| 3446 | + } else { |
| 3447 | + lua_Complex bb= nvalue_complex(b), cc= nvalue_complex(c); |
| 3448 | + switch (op) { |
| 3449 | + case TM_ADD: r= bb + cc; break; |
| 3450 | + case TM_SUB: r= bb - cc; break; |
| 3451 | + case TM_MUL: r= bb * cc; break; |
| 3452 | + case TM_DIV: r= bb / cc; break; |
| 3453 | + case TM_MOD: |
| 3454 | + luaG_runerror(L, "attempt to use %% on complex numbers"); /* no return */ |
| 3455 | + case TM_POW: r= luai_vectpow( bb, cc ); break; |
| 3456 | + default: lua_assert(0); r=0; |
| 3457 | + } |
| 3458 | + setnvalue_complex( ra, r ); |
| 3459 | + } |
| 3460 | + return; |
| 3461 | + } |
| 3462 | +#endif |
| 3463 | + nb = nvalue(b); nc = nvalue(c); |
| 3464 | + switch (op) { |
| 3465 | + case TM_ADD: setnvalue(ra, luai_numadd(nb, nc)); return; |
| 3466 | + case TM_SUB: setnvalue(ra, luai_numsub(nb, nc)); return; |
| 3467 | + case TM_MUL: setnvalue(ra, luai_nummul(nb, nc)); return; |
| 3468 | + case TM_DIV: setnvalue(ra, luai_numdiv(nb, nc)); return; |
| 3469 | + case TM_MOD: setnvalue(ra, luai_nummod(nb, nc)); return; |
| 3470 | + case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); return; |
| 3471 | + case TM_UNM: setnvalue(ra, luai_numunm(nb)); return; |
| 3472 | + default: lua_assert(0); |
| 3473 | + } |
| 3474 | + } |
| 3475 | + |
| 3476 | + /* Either operand not a number */ |
| 3477 | + if (!call_binTM(L, rb, rc, ra, op)) |
| 3478 | + luaG_aritherror(L, rb, rc); |
| 3479 | +} |
| 3480 | + |
| 3481 | +/* Helper macro to sort arithmetic operations into four categories: |
| 3482 | + * TK_INT: integer - integer operands |
| 3483 | + * TK_NUMBER: number - number (non complex, either may be integer) |
| 3484 | + * TK_NUMBER2: complex numbers (at least the other) |
| 3485 | + * 0: non-numeric (at least the other) |
| 3486 | +*/ |
| 3487 | +#ifdef LNUM_COMPLEX |
| 3488 | +static inline int arith_mode( const TValue *rb, const TValue *rc ) { |
| 3489 | + if (ttisint(rb) && ttisint(rc)) return TK_INT; |
| 3490 | + if (ttiscomplex(rb) || ttiscomplex(rc)) return TK_NUMBER2; |
| 3491 | + if (ttisnumber(rb) && ttisnumber(rc)) return TK_NUMBER; |
| 3492 | + return 0; |
| 3493 | +} |
| 3494 | +#else |
| 3495 | +# define arith_mode(rb,rc) \ |
| 3496 | + ( (ttisint(rb) && ttisint(rc)) ? TK_INT : \ |
| 3497 | + (ttisnumber(rb) && ttisnumber(rc)) ? TK_NUMBER : 0 ) |
| 3498 | +#endif |
| 3499 | + |
| 3500 | +/* arith_op macro for two operators: |
| 3501 | + * automatically chooses, which function (number, integer, complex) to use |
| 3502 | + */ |
| 3503 | +#define ARITH_OP2_START( op_num, op_int ) \ |
| 3504 | + int failed= 0; \ |
| 3505 | + switch( arith_mode(rb,rc) ) { \ |
| 3506 | + case TK_INT: \ |
| 3507 | + if (op_int ( &(ra)->value.i, ivalue(rb), ivalue(rc) )) \ |
| 3508 | + { ra->tt= LUA_TINT; break; } /* else flow through */ \ |
| 3509 | + case TK_NUMBER: \ |
| 3510 | + setnvalue(ra, op_num ( nvalue(rb), nvalue(rc) )); break; |
| 3511 | + |
| 3512 | +#define ARITH_OP2_END \ |
| 3513 | + default: \ |
| 3514 | + failed= 1; break; \ |
| 3515 | + } if (!failed) continue; |
| 3516 | + |
| 3517 | +#define arith_op_continue_scalar( op_num, op_int ) \ |
| 3518 | + ARITH_OP2_START( op_num, op_int ) \ |
| 3519 | + ARITH_OP2_END |
| 3520 | + |
| 3521 | +#ifdef LNUM_COMPLEX |
| 3522 | +# define arith_op_continue( op_num, op_int, op_complex ) \ |
| 3523 | + ARITH_OP2_START( op_num, op_int ) \ |
| 3524 | + case TK_NUMBER2: \ |
| 3525 | + setnvalue_complex( ra, op_complex ( nvalue_complex(rb), nvalue_complex(rc) ) ); break; \ |
| 3526 | + ARITH_OP2_END |
| 3527 | +#else |
| 3528 | +# define arith_op_continue(op_num,op_int,_) arith_op_continue_scalar(op_num,op_int) |
| 3529 | +#endif |
| 3530 | + |
| 3531 | +/* arith_op macro for one operator: |
| 3532 | + */ |
| 3533 | +#define ARITH_OP1_START( op_num, op_int ) \ |
| 3534 | + int failed= 0; \ |
| 3535 | + switch( arith_mode(rb,rb) ) { \ |
| 3536 | + case TK_INT: \ |
| 3537 | + if (op_int ( &(ra)->value.i, ivalue(rb) )) \ |
| 3538 | + { ra->tt= LUA_TINT; break; } /* else flow through */ \ |
| 3539 | + case TK_NUMBER: \ |
| 3540 | + setnvalue(ra, op_num (nvalue(rb))); break; \ |
| 3541 | + |
| 3542 | +#define ARITH_OP1_END \ |
| 3543 | + default: \ |
| 3544 | + failed= 1; break; \ |
| 3545 | + } if (!failed) continue; |
| 3546 | + |
| 3547 | +#ifdef LNUM_COMPLEX |
| 3548 | +# define arith_op1_continue( op_num, op_int, op_complex ) \ |
| 3549 | + ARITH_OP1_START( op_num, op_int ) \ |
| 3550 | + case TK_NUMBER2: \ |
| 3551 | + setnvalue_complex( ra, op_complex ( nvalue_complex_fast(rb) )); break; \ |
| 3552 | + ARITH_OP1_END |
| 3553 | +#else |
| 3554 | +# define arith_op1_continue( op_num, op_int, _ ) \ |
| 3555 | + ARITH_OP1_START( op_num, op_int ) \ |
| 3556 | + ARITH_OP1_END |
| 3557 | +#endif |
| 3558 | |
| 3559 | |
| 3560 | void luaV_execute (lua_State *L, int nexeccalls) { |
| 3561 | @@ -472,38 +665,45 @@ void luaV_execute (lua_State *L, int nex |
| 3562 | continue; |
| 3563 | } |
| 3564 | case OP_ADD: { |
| 3565 | - arith_op(luai_numadd, TM_ADD); |
| 3566 | + TValue *rb = RKB(i), *rc= RKC(i); |
| 3567 | + arith_op_continue( luai_numadd, try_addint, luai_vectadd ); |
| 3568 | + Protect(Arith(L, ra, rb, rc, TM_ADD)); \ |
| 3569 | continue; |
| 3570 | } |
| 3571 | case OP_SUB: { |
| 3572 | - arith_op(luai_numsub, TM_SUB); |
| 3573 | + TValue *rb = RKB(i), *rc= RKC(i); |
| 3574 | + arith_op_continue( luai_numsub, try_subint, luai_vectsub ); |
| 3575 | + Protect(Arith(L, ra, rb, rc, TM_SUB)); |
| 3576 | continue; |
| 3577 | } |
| 3578 | case OP_MUL: { |
| 3579 | - arith_op(luai_nummul, TM_MUL); |
| 3580 | + TValue *rb = RKB(i), *rc= RKC(i); |
| 3581 | + arith_op_continue(luai_nummul, try_mulint, luai_vectmul); |
| 3582 | + Protect(Arith(L, ra, rb, rc, TM_MUL)); |
| 3583 | continue; |
| 3584 | } |
| 3585 | case OP_DIV: { |
| 3586 | - arith_op(luai_numdiv, TM_DIV); |
| 3587 | + TValue *rb = RKB(i), *rc= RKC(i); |
| 3588 | + arith_op_continue(luai_numdiv, try_divint, luai_vectdiv); |
| 3589 | + Protect(Arith(L, ra, rb, rc, TM_DIV)); |
| 3590 | continue; |
| 3591 | } |
| 3592 | case OP_MOD: { |
| 3593 | - arith_op(luai_nummod, TM_MOD); |
| 3594 | + TValue *rb = RKB(i), *rc= RKC(i); |
| 3595 | + arith_op_continue_scalar(luai_nummod, try_modint); /* scalars only */ |
| 3596 | + Protect(Arith(L, ra, rb, rc, TM_MOD)); |
| 3597 | continue; |
| 3598 | } |
| 3599 | case OP_POW: { |
| 3600 | - arith_op(luai_numpow, TM_POW); |
| 3601 | + TValue *rb = RKB(i), *rc= RKC(i); |
| 3602 | + arith_op_continue(luai_numpow, try_powint, luai_vectpow); |
| 3603 | + Protect(Arith(L, ra, rb, rc, TM_POW)); |
| 3604 | continue; |
| 3605 | } |
| 3606 | case OP_UNM: { |
| 3607 | TValue *rb = RB(i); |
| 3608 | - if (ttisnumber(rb)) { |
| 3609 | - lua_Number nb = nvalue(rb); |
| 3610 | - setnvalue(ra, luai_numunm(nb)); |
| 3611 | - } |
| 3612 | - else { |
| 3613 | - Protect(Arith(L, ra, rb, rb, TM_UNM)); |
| 3614 | - } |
| 3615 | + arith_op1_continue(luai_numunm, try_unmint, luai_vectunm); |
| 3616 | + Protect(Arith(L, ra, rb, rb, TM_UNM)); |
| 3617 | continue; |
| 3618 | } |
| 3619 | case OP_NOT: { |
| 3620 | @@ -515,11 +715,11 @@ void luaV_execute (lua_State *L, int nex |
| 3621 | const TValue *rb = RB(i); |
| 3622 | switch (ttype(rb)) { |
| 3623 | case LUA_TTABLE: { |
| 3624 | - setnvalue(ra, cast_num(luaH_getn(hvalue(rb)))); |
| 3625 | + setivalue(ra, luaH_getn(hvalue(rb))); |
| 3626 | break; |
| 3627 | } |
| 3628 | case LUA_TSTRING: { |
| 3629 | - setnvalue(ra, cast_num(tsvalue(rb)->len)); |
| 3630 | + setivalue(ra, tsvalue(rb)->len); |
| 3631 | break; |
| 3632 | } |
| 3633 | default: { /* try metamethod */ |
| 3634 | @@ -652,14 +852,30 @@ void luaV_execute (lua_State *L, int nex |
| 3635 | } |
| 3636 | } |
| 3637 | case OP_FORLOOP: { |
| 3638 | - lua_Number step = nvalue(ra+2); |
| 3639 | - lua_Number idx = luai_numadd(nvalue(ra), step); /* increment index */ |
| 3640 | - lua_Number limit = nvalue(ra+1); |
| 3641 | - if (luai_numlt(0, step) ? luai_numle(idx, limit) |
| 3642 | - : luai_numle(limit, idx)) { |
| 3643 | - dojump(L, pc, GETARG_sBx(i)); /* jump back */ |
| 3644 | - setnvalue(ra, idx); /* update internal index... */ |
| 3645 | - setnvalue(ra+3, idx); /* ...and external index */ |
| 3646 | + /* If start,step and limit are all integers, we don't need to check |
| 3647 | + * against overflow in the looping. |
| 3648 | + */ |
| 3649 | + if (ttisint(ra) && ttisint(ra+1) && ttisint(ra+2)) { |
| 3650 | + lua_Integer step = ivalue(ra+2); |
| 3651 | + lua_Integer idx = ivalue(ra) + step; /* increment index */ |
| 3652 | + lua_Integer limit = ivalue(ra+1); |
| 3653 | + if (step > 0 ? (idx <= limit) : (limit <= idx)) { |
| 3654 | + dojump(L, pc, GETARG_sBx(i)); /* jump back */ |
| 3655 | + setivalue(ra, idx); /* update internal index... */ |
| 3656 | + setivalue(ra+3, idx); /* ...and external index */ |
| 3657 | + } |
| 3658 | + } else { |
| 3659 | + /* non-integer looping (don't use 'nvalue_fast', some may be integer!) |
| 3660 | + */ |
| 3661 | + lua_Number step = nvalue(ra+2); |
| 3662 | + lua_Number idx = luai_numadd(nvalue(ra), step); /* increment index */ |
| 3663 | + lua_Number limit = nvalue(ra+1); |
| 3664 | + if (luai_numlt(0, step) ? luai_numle(idx, limit) |
| 3665 | + : luai_numle(limit, idx)) { |
| 3666 | + dojump(L, pc, GETARG_sBx(i)); /* jump back */ |
| 3667 | + setnvalue(ra, idx); /* update internal index... */ |
| 3668 | + setnvalue(ra+3, idx); /* ...and external index */ |
| 3669 | + } |
| 3670 | } |
| 3671 | continue; |
| 3672 | } |
| 3673 | @@ -668,13 +884,21 @@ void luaV_execute (lua_State *L, int nex |
| 3674 | const TValue *plimit = ra+1; |
| 3675 | const TValue *pstep = ra+2; |
| 3676 | L->savedpc = pc; /* next steps may throw errors */ |
| 3677 | + /* Using same location for tonumber's both arguments, effectively does |
| 3678 | + * in-place modification (string->number). */ |
| 3679 | if (!tonumber(init, ra)) |
| 3680 | luaG_runerror(L, LUA_QL("for") " initial value must be a number"); |
| 3681 | else if (!tonumber(plimit, ra+1)) |
| 3682 | luaG_runerror(L, LUA_QL("for") " limit must be a number"); |
| 3683 | else if (!tonumber(pstep, ra+2)) |
| 3684 | luaG_runerror(L, LUA_QL("for") " step must be a number"); |
| 3685 | - setnvalue(ra, luai_numsub(nvalue(ra), nvalue(pstep))); |
| 3686 | + /* Step back one value (keep within integers if we can) |
| 3687 | + */ |
| 3688 | + if (!( ttisint(ra) && ttisint(pstep) && |
| 3689 | + try_subint( &ra->value.i, ivalue(ra), ivalue(pstep) ) )) { |
| 3690 | + /* don't use 'nvalue_fast()', values may be integer */ |
| 3691 | + setnvalue(ra, luai_numsub(nvalue(ra), nvalue(pstep))); |
| 3692 | + } |
| 3693 | dojump(L, pc, GETARG_sBx(i)); |
| 3694 | continue; |
| 3695 | } |
| 3696 | @@ -711,7 +935,7 @@ void luaV_execute (lua_State *L, int nex |
| 3697 | luaH_resizearray(L, h, last); /* pre-alloc it at once */ |
| 3698 | for (; n > 0; n--) { |
| 3699 | TValue *val = ra+n; |
| 3700 | - setobj2t(L, luaH_setnum(L, h, last--), val); |
| 3701 | + setobj2t(L, luaH_setint(L, h, last--), val); |
| 3702 | luaC_barriert(L, h, val); |
| 3703 | } |
| 3704 | continue; |
| 3705 | --- a/src/lvm.h |
| 3706 | +++ b/src/lvm.h |
| 3707 | @@ -15,11 +15,9 @@ |
| 3708 | |
| 3709 | #define tostring(L,o) ((ttype(o) == LUA_TSTRING) || (luaV_tostring(L, o))) |
| 3710 | |
| 3711 | -#define tonumber(o,n) (ttype(o) == LUA_TNUMBER || \ |
| 3712 | - (((o) = luaV_tonumber(o,n)) != NULL)) |
| 3713 | +#define tonumber(o,n) (ttisnumber(o) || (((o) = luaV_tonumber(o,n)) != NULL)) |
| 3714 | |
| 3715 | -#define equalobj(L,o1,o2) \ |
| 3716 | - (ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2)) |
| 3717 | +#define equalobj(L,o1,o2) (ttype_ext_same(o1,o2) && luaV_equalval(L, o1, o2)) |
| 3718 | |
| 3719 | |
| 3720 | LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r); |
| 3721 | --- a/src/print.c |
| 3722 | +++ b/src/print.c |
| 3723 | @@ -14,6 +14,7 @@ |
| 3724 | #include "lobject.h" |
| 3725 | #include "lopcodes.h" |
| 3726 | #include "lundump.h" |
| 3727 | +#include "lnum.h" |
| 3728 | |
| 3729 | #define PrintFunction luaU_print |
| 3730 | |
| 3731 | @@ -59,8 +60,16 @@ static void PrintConstant(const Proto* f |
| 3732 | case LUA_TBOOLEAN: |
| 3733 | printf(bvalue(o) ? "true" : "false"); |
| 3734 | break; |
| 3735 | + case LUA_TINT: |
| 3736 | + printf(LUA_INTEGER_FMT,ivalue(o)); |
| 3737 | + break; |
| 3738 | case LUA_TNUMBER: |
| 3739 | - printf(LUA_NUMBER_FMT,nvalue(o)); |
| 3740 | +#ifdef LNUM_COMPLEX |
| 3741 | + // TBD: Do we get complex values here? |
| 3742 | + { lua_Number b= nvalue_img_fast(o); |
| 3743 | + printf( LUA_NUMBER_FMT "%s" LUA_NUMBER_FMT "i", nvalue_fast(o), b>=0 ? "+":"", b ); } |
| 3744 | +#endif |
| 3745 | + printf(LUA_NUMBER_FMT,nvalue_fast(o)); |
| 3746 | break; |
| 3747 | case LUA_TSTRING: |
| 3748 | PrintString(rawtsvalue(o)); |