diff options
Diffstat (limited to 'src/lj_carith.c')
-rw-r--r-- | src/lj_carith.c | 43 |
1 files changed, 27 insertions, 16 deletions
diff --git a/src/lj_carith.c b/src/lj_carith.c index a7d92983..46f07be7 100644 --- a/src/lj_carith.c +++ b/src/lj_carith.c | |||
@@ -184,7 +184,12 @@ static int carith_int64(lua_State *L, CTState *cts, CDArith *ca, MMS mm) | |||
184 | else | 184 | else |
185 | *up = u0 % u1; | 185 | *up = u0 % u1; |
186 | break; | 186 | break; |
187 | case MM_pow: *up = lj_carith_powi64(u0, u1, (id == CTID_UINT64)); break; | 187 | case MM_pow: |
188 | if (id == CTID_INT64) | ||
189 | *up = (uint64_t)lj_carith_powi64((int64_t)u0, (int64_t)u1); | ||
190 | else | ||
191 | *up = lj_carith_powu64(u0, u1); | ||
192 | break; | ||
188 | case MM_unm: *up = (uint64_t)-(int64_t)u0; break; | 193 | case MM_unm: *up = (uint64_t)-(int64_t)u0; break; |
189 | default: lua_assert(0); break; | 194 | default: lua_assert(0); break; |
190 | } | 195 | } |
@@ -225,24 +230,12 @@ int lj_carith_op(lua_State *L, MMS mm) | |||
225 | 230 | ||
226 | /* -- 64 bit integer arithmetic helpers ----------------------------------- */ | 231 | /* -- 64 bit integer arithmetic helpers ----------------------------------- */ |
227 | 232 | ||
228 | /* 64 bit integer x^k. */ | 233 | /* Unsigned 64 bit x^k. */ |
229 | uint64_t lj_carith_powi64(uint64_t x, uint64_t k, int isunsigned) | 234 | uint64_t lj_carith_powu64(uint64_t x, uint64_t k) |
230 | { | 235 | { |
231 | uint64_t y = 0; | 236 | uint64_t y; |
232 | if (k == 0) | 237 | if (k == 0) |
233 | return 1; | 238 | return 1; |
234 | if (!isunsigned) { | ||
235 | if ((int64_t)k < 0) { | ||
236 | if (x == 0) | ||
237 | return U64x(7fffffff,ffffffff); | ||
238 | else if (x == 1) | ||
239 | return 1; | ||
240 | else if ((int64_t)x == -1) | ||
241 | return (k & 1) ? -1 : 1; | ||
242 | else | ||
243 | return 0; | ||
244 | } | ||
245 | } | ||
246 | for (; (k & 1) == 0; k >>= 1) x *= x; | 239 | for (; (k & 1) == 0; k >>= 1) x *= x; |
247 | y = x; | 240 | y = x; |
248 | if ((k >>= 1) != 0) { | 241 | if ((k >>= 1) != 0) { |
@@ -257,4 +250,22 @@ uint64_t lj_carith_powi64(uint64_t x, uint64_t k, int isunsigned) | |||
257 | return y; | 250 | return y; |
258 | } | 251 | } |
259 | 252 | ||
253 | /* Signed 64 bit x^k. */ | ||
254 | int64_t lj_carith_powi64(int64_t x, int64_t k) | ||
255 | { | ||
256 | if (k == 0) | ||
257 | return 1; | ||
258 | if (k < 0) { | ||
259 | if (x == 0) | ||
260 | return U64x(7fffffff,ffffffff); | ||
261 | else if (x == 1) | ||
262 | return 1; | ||
263 | else if (x == -1) | ||
264 | return (k & 1) ? -1 : 1; | ||
265 | else | ||
266 | return 0; | ||
267 | } | ||
268 | return (int64_t)lj_carith_powu64((uint64_t)x, (uint64_t)k); | ||
269 | } | ||
270 | |||
260 | #endif | 271 | #endif |