Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --- lobject.c Thu Dec 22 15:08:50 2016
- +++ lobject.c Fri May 12 11:55:20 2017
- @@ -88,6 +88,7 @@
- case LUA_OPMUL:return intop(*, v1, v2);
- case LUA_OPMOD: return luaV_mod(L, v1, v2);
- case LUA_OPIDIV: return luaV_div(L, v1, v2);
- + case LUA_OPPOW: return luaV_pow(L, v1, v2); /* [IPOW] */
- case LUA_OPBAND: return intop(&, v1, v2);
- case LUA_OPBOR: return intop(|, v1, v2);
- case LUA_OPBXOR: return intop(^, v1, v2);
- @@ -133,7 +134,14 @@
- }
- else break; /* go to the end */
- }
- - case LUA_OPDIV: case LUA_OPPOW: { /* operate only on floats */
- + case LUA_OPPOW: { /* [IPOW] */
- + if (luaV_doipow(p1, p2)) {
- + setivalue(res, intarith(L, op, ivalue(p1), ivalue(p2)));
- + return;
- + }
- + /* fall through */
- + }
- + case LUA_OPDIV: { /* operate only on floats */
- lua_Number n1; lua_Number n2;
- if (tonumber(p1, &n1) && tonumber(p2, &n2)) {
- setfltvalue(res, numarith(L, op, n1, n2));
- --- lvm.c Fri Feb 05 21:59:14 2016
- +++ lvm.c Fri May 12 11:57:05 2017
- @@ -584,6 +584,63 @@
- }
- +/* [IPOW]
- +** Integer exponentiation; return 'b ^ n', where 'n >= 0'
- +** Negative 'n' is handled according to the mode defined in lvm.h
- +** Overflow wraps around the result consistent with repeated 'b*b'
- +*/
- +lua_Integer luaV_pow (lua_State *L, lua_Integer b, lua_Integer n) {
- + lua_Integer r;
- +#if (LUA_IPOW_MODE == IPOW_DOERROR)
- + /* throw on negative 'n' (default) */
- + if (n < 0)
- + luaG_runerror(L, "attempt to perform integer 'b^n' with negative 'n'");
- +#elif (LUA_IPOW_MODE == IPOW_DOCONVERT)
- + /* should not be called for negative 'n' */
- + UNUSED(L);
- + lua_assert(n >= 0);
- +#elif (LUA_IPOW_MODE == IPOW_DOIDIV)
- + /* handle negative 'n' as '1 // (b ^ abs(n))' */
- + if (n < 0) {
- + if (b == 0) /* b^n == 0 */
- + luaG_runerror(L, "integer 'b^n' would result in divide by zero");
- + else /* b^n != 0 */
- + return 0;
- + }
- +#else /* IPOW_DISABLE */
- + /* should not be called at all */
- + UNUSED(L);
- + lua_assert(0);
- +#endif
- + if (b == 0 || n == 0) { /* special cases: 0 base and/or exponent */
- + if (b == n)
- + r = 1; /* 0^0 == 1 */
- + else if (b == 0)
- + r = 0; /* 0^n == 0 */
- + else /* n == 0 */
- + r = 1; /* b^0 == 1 */
- + }
- + else { /* b != 0 && n > 0 */
- + lua_Unsigned bu = l_castS2U(b);
- + lua_Unsigned nu = l_castS2U(n);
- + lua_Unsigned ru = 1u;
- + if (b < 0) /* negative base? */
- + bu = 0u - bu; /* use its magnitude */
- + while (nu != 1u) { /* do exponentiation by squaring */
- + if (nu & 1u)
- + ru *= bu;
- + bu *= bu;
- + nu >>= 1u;
- + }
- + ru *= bu; /* last (or only) multiply */
- + if (b < 0 && n & 1) /* 'r' should be negative? */
- + ru = 0u - ru; /* negate the result */
- + r = l_castU2S(ru);
- + }
- + return r;
- +}
- +
- +
- /* number of bits in an integer */
- #define NBITS cast_int(sizeof(lua_Integer) * CHAR_BIT)
- @@ -1022,7 +1079,11 @@
- TValue *rb = RKB(i);
- TValue *rc = RKC(i);
- lua_Number nb; lua_Number nc;
- - if (tonumber(rb, &nb) && tonumber(rc, &nc)) {
- + if (luaV_doipow(rb, rc)) { /* [IPOW] */
- + lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc);
- + setivalue(ra, luaV_pow(L, ib, ic));
- + }
- + else if (tonumber(rb, &nb) && tonumber(rc, &nc)) {
- setfltvalue(ra, luai_numpow(L, nb, nc));
- }
- else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_POW)); }
- --- lvm.h Thu Dec 22 15:08:50 2016
- +++ lvm.h Fri May 12 11:55:52 2017
- @@ -92,6 +92,57 @@
- luaV_finishset(L,t,k,v,slot); }
- +/* [IPOW]
- +** Set the "mode" for how integer exponentiation (ipow) handles a
- +** negative exponent. Defaults to IPOW_DOERROR (see below)
- +**
- +** IPOW_DOERROR - raise error for negative exponent
- +** IPOW_DOCONVERT - convert operation to float for negative exponent
- +** IPOW_DOIDIV - handle negative exponent as '1 // (b ^ abs(n))'
- +** IPOW_DISABLE - disable ipow completely
- +**
- +** Defaults to raising error for a negative exponent since this
- +** a) follows the rule that it is the type of numbers which determine
- +** if an operation results in an integer or a float type
- +** b) is more consistent with integer division and modulus which raise
- +** errors instead of converting result to float for a 0 dividend,
- +** that is returning 'inf' for '1 // 0' and 'nan' for '1 % 0'
- +** c) makes integer and float arithmetic more distinct, lowering
- +** the possibility of floats appearing where they are not desired
- +**
- +*/
- +#define IPOW_DOERROR 1
- +#define IPOW_DOCONVERT 2
- +#define IPOW_DOIDIV 3
- +#define IPOW_DISABLE 0
- +
- +#if !defined(LUA_IPOW_MODE)
- +#define LUA_IPOW_MODE IPOW_DOERROR
- +#endif
- +
- +/* 'luaV_doipow' checks if ipow should be done for the given 'b^n' */
- +#if (LUA_IPOW_MODE == IPOW_DOERROR) || \
- + (LUA_IPOW_MODE == IPOW_DOIDIV)
- +
- +/* do ipow for integers */
- +#define luaV_doipow(b,n) \
- + (ttisinteger(b) && ttisinteger(n))
- +
- +#elif (LUA_IPOW_MODE == IPOW_DOCONVERT)
- +
- +/* only do ipow for integers when 'n >= 0' */
- +#define luaV_doipow(b,n) \
- + ((ttisinteger(b) && ttisinteger(n)) && \
- + (!luai_numlt(ivalue(n), 0)))
- +
- +#else /* IPOW_DISABLE */
- +
- +/* no ipow */
- +#define luaV_doipow(b,n) (0)
- +
- +#endif
- +
- +
- LUAI_FUNC int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2);
- LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r);
- @@ -107,6 +158,7 @@
- LUAI_FUNC void luaV_concat (lua_State *L, int total);
- LUAI_FUNC lua_Integer luaV_div (lua_State *L, lua_Integer x, lua_Integer y);
- LUAI_FUNC lua_Integer luaV_mod (lua_State *L, lua_Integer x, lua_Integer y);
- +LUAI_FUNC lua_Integer luaV_pow (lua_State *L, lua_Integer x, lua_Integer y); /* [IPOW] */
- LUAI_FUNC lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y);
- LUAI_FUNC void luaV_objlen (lua_State *L, StkId ra, const TValue *rb);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement