Advertisement
sginsberg

IPOW Patch

May 13th, 2017
68
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 5.89 KB | None | 0 0
  1. --- lobject.c   Thu Dec 22 15:08:50 2016
  2. +++ lobject.c   Fri May 12 11:55:20 2017
  3. @@ -88,6 +88,7 @@
  4.      case LUA_OPMUL:return intop(*, v1, v2);
  5.      case LUA_OPMOD: return luaV_mod(L, v1, v2);
  6.      case LUA_OPIDIV: return luaV_div(L, v1, v2);
  7. +    case LUA_OPPOW: return luaV_pow(L, v1, v2);  /* [IPOW] */
  8.      case LUA_OPBAND: return intop(&, v1, v2);
  9.      case LUA_OPBOR: return intop(|, v1, v2);
  10.      case LUA_OPBXOR: return intop(^, v1, v2);
  11. @@ -133,7 +134,14 @@
  12.        }
  13.        else break;  /* go to the end */
  14.      }
  15. -    case LUA_OPDIV: case LUA_OPPOW: {  /* operate only on floats */
  16. +    case LUA_OPPOW: {  /* [IPOW] */
  17. +      if (luaV_doipow(p1, p2)) {
  18. +        setivalue(res, intarith(L, op, ivalue(p1), ivalue(p2)));
  19. +        return;
  20. +      }
  21. +      /* fall through */
  22. +    }
  23. +    case LUA_OPDIV: {  /* operate only on floats */
  24.        lua_Number n1; lua_Number n2;
  25.        if (tonumber(p1, &n1) && tonumber(p2, &n2)) {
  26.          setfltvalue(res, numarith(L, op, n1, n2));
  27. --- lvm.c   Fri Feb 05 21:59:14 2016
  28. +++ lvm.c   Fri May 12 11:57:05 2017
  29. @@ -584,6 +584,63 @@
  30.  }
  31.  
  32.  
  33. +/* [IPOW]
  34. +** Integer exponentiation; return 'b ^ n', where 'n >= 0'
  35. +** Negative 'n' is handled according to the mode defined in lvm.h
  36. +** Overflow wraps around the result consistent with repeated 'b*b'
  37. +*/
  38. +lua_Integer luaV_pow (lua_State *L, lua_Integer b, lua_Integer n) {
  39. +  lua_Integer r;
  40. +#if (LUA_IPOW_MODE == IPOW_DOERROR)
  41. +  /* throw on negative 'n' (default) */
  42. +  if (n < 0)
  43. +    luaG_runerror(L, "attempt to perform integer 'b^n' with negative 'n'");
  44. +#elif (LUA_IPOW_MODE == IPOW_DOCONVERT)
  45. +  /* should not be called for negative 'n' */
  46. +  UNUSED(L);
  47. +  lua_assert(n >= 0);
  48. +#elif (LUA_IPOW_MODE == IPOW_DOIDIV)
  49. +  /* handle negative 'n' as '1 // (b ^ abs(n))' */
  50. +  if (n < 0) {
  51. +    if (b == 0)  /* b^n == 0 */
  52. +      luaG_runerror(L, "integer 'b^n' would result in divide by zero");
  53. +    else  /* b^n != 0 */
  54. +      return 0;
  55. +  }
  56. +#else /* IPOW_DISABLE */
  57. +  /* should not be called at all */
  58. +  UNUSED(L);
  59. +  lua_assert(0);
  60. +#endif
  61. +  if (b == 0 || n == 0) {  /* special cases: 0 base and/or exponent */
  62. +    if (b == n)
  63. +      r = 1;  /* 0^0 == 1 */
  64. +    else if (b == 0)
  65. +      r = 0;  /* 0^n == 0 */
  66. +    else  /* n == 0 */
  67. +      r = 1;  /* b^0 == 1 */
  68. +  }
  69. +  else {  /* b != 0 && n > 0 */
  70. +    lua_Unsigned bu = l_castS2U(b);
  71. +    lua_Unsigned nu = l_castS2U(n);
  72. +    lua_Unsigned ru = 1u;
  73. +    if (b < 0)  /* negative base? */
  74. +      bu = 0u - bu;  /* use its magnitude */
  75. +    while (nu != 1u) {  /* do exponentiation by squaring */
  76. +      if (nu & 1u)
  77. +        ru *= bu;
  78. +      bu *= bu;
  79. +      nu >>= 1u;
  80. +    }
  81. +    ru *= bu;  /* last (or only) multiply */
  82. +    if (b < 0 && n & 1)  /* 'r' should be negative? */
  83. +      ru = 0u - ru;  /* negate the result */
  84. +    r = l_castU2S(ru);
  85. +  }
  86. +  return r;
  87. +}
  88. +
  89. +
  90.  /* number of bits in an integer */
  91.  #define NBITS  cast_int(sizeof(lua_Integer) * CHAR_BIT)
  92.  
  93. @@ -1022,7 +1079,11 @@
  94.          TValue *rb = RKB(i);
  95.          TValue *rc = RKC(i);
  96.          lua_Number nb; lua_Number nc;
  97. -        if (tonumber(rb, &nb) && tonumber(rc, &nc)) {
  98. +        if (luaV_doipow(rb, rc)) {  /* [IPOW] */
  99. +          lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc);
  100. +          setivalue(ra, luaV_pow(L, ib, ic));
  101. +        }
  102. +        else if (tonumber(rb, &nb) && tonumber(rc, &nc)) {
  103.            setfltvalue(ra, luai_numpow(L, nb, nc));
  104.          }
  105.          else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_POW)); }
  106. --- lvm.h   Thu Dec 22 15:08:50 2016
  107. +++ lvm.h   Fri May 12 11:55:52 2017
  108. @@ -92,6 +92,57 @@
  109.      luaV_finishset(L,t,k,v,slot); }
  110.  
  111.  
  112. +/* [IPOW]
  113. +** Set the "mode" for how integer exponentiation (ipow) handles a
  114. +** negative exponent. Defaults to IPOW_DOERROR (see below)
  115. +**
  116. +** IPOW_DOERROR - raise error for negative exponent
  117. +** IPOW_DOCONVERT - convert operation to float for negative exponent
  118. +** IPOW_DOIDIV - handle negative exponent as '1 // (b ^ abs(n))'
  119. +** IPOW_DISABLE - disable ipow completely
  120. +**
  121. +** Defaults to raising error for a negative exponent since this
  122. +** a) follows the rule that it is the type of numbers which determine
  123. +**    if an operation results in an integer or a float type
  124. +** b) is more consistent with integer division and modulus which raise
  125. +**    errors instead of converting result to float for a 0 dividend,
  126. +**    that is returning 'inf' for '1 // 0' and 'nan' for '1 % 0'
  127. +** c) makes integer and float arithmetic more distinct, lowering
  128. +**    the possibility of floats appearing where they are not desired
  129. +**    
  130. +*/
  131. +#define IPOW_DOERROR     1
  132. +#define IPOW_DOCONVERT   2
  133. +#define IPOW_DOIDIV      3
  134. +#define IPOW_DISABLE     0
  135. +
  136. +#if !defined(LUA_IPOW_MODE)
  137. +#define LUA_IPOW_MODE IPOW_DOERROR
  138. +#endif
  139. +
  140. +/* 'luaV_doipow' checks if ipow should be done for the given 'b^n' */
  141. +#if (LUA_IPOW_MODE == IPOW_DOERROR) || \
  142. +    (LUA_IPOW_MODE == IPOW_DOIDIV)
  143. +
  144. +/* do ipow for integers */
  145. +#define luaV_doipow(b,n) \
  146. +  (ttisinteger(b) && ttisinteger(n))
  147. +
  148. +#elif (LUA_IPOW_MODE == IPOW_DOCONVERT)
  149. +
  150. +/* only do ipow for integers when 'n >= 0' */
  151. +#define luaV_doipow(b,n) \
  152. +  ((ttisinteger(b) && ttisinteger(n)) && \
  153. +   (!luai_numlt(ivalue(n), 0)))
  154. +
  155. +#else /* IPOW_DISABLE */
  156. +
  157. +/* no ipow */
  158. +#define luaV_doipow(b,n) (0)
  159. +
  160. +#endif
  161. +
  162. +
  163.  
  164.  LUAI_FUNC int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2);
  165.  LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r);
  166. @@ -107,6 +158,7 @@
  167.  LUAI_FUNC void luaV_concat (lua_State *L, int total);
  168.  LUAI_FUNC lua_Integer luaV_div (lua_State *L, lua_Integer x, lua_Integer y);
  169.  LUAI_FUNC lua_Integer luaV_mod (lua_State *L, lua_Integer x, lua_Integer y);
  170. +LUAI_FUNC lua_Integer luaV_pow (lua_State *L, lua_Integer x, lua_Integer y); /* [IPOW] */
  171.  LUAI_FUNC lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y);
  172.  LUAI_FUNC void luaV_objlen (lua_State *L, StkId ra, const TValue *rb);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement