Skip to content

Commit

Permalink
actually normalize rbigints when the image asks us (addresses overflo…
Browse files Browse the repository at this point in the history
…ws in #131)
  • Loading branch information
timfel committed Dec 21, 2016
1 parent 5e3965b commit fa09553
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 7 deletions.
6 changes: 0 additions & 6 deletions rsqueakvm/model/numeric.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,12 +204,6 @@ def calculate_exposed_size_for_big_int(value):
bytelenval = value.abs()
# XXX +0.05: heuristic hack float rounding errors
return int(math.floor(bytelenval.log(256) + 0.05)) + 1
# TODO: check if this might be better
# try:
# bytes = val.tobytes(bytelen, 'little', False)
# except OverflowError:
# # round-off errors in math.log, might need an extra byte
# bytes = val.tobytes(bytelen + 1, 'little', False)


class W_LargeIntegerBig(W_LargeInteger):
Expand Down
18 changes: 17 additions & 1 deletion rsqueakvm/plugins/large_integers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@
from rsqueakvm.plugins.plugin import Plugin
from rsqueakvm.primitives import prim_table
from rsqueakvm.primitives.constants import *
from rsqueakvm.model.numeric import W_LargeInteger
from rsqueakvm.model.numeric import W_LargeInteger, W_LargeIntegerBig, calculate_exposed_size_for_big_int
from rsqueakvm.model.variable import W_BytesObject

from rpython.rlib.rbigint import rbigint, NULLRBIGINT, _divrem
from rpython.rlib import jit

LargeIntegers = Plugin()

Expand Down Expand Up @@ -73,16 +74,31 @@ def primDigitCompare(interp, s_frame, rcvr, arg):
res = 0
return interp.space.wrap_int(res)

@jit.elidable
def minimum_bytelen_for(val):
bytelen = calculate_exposed_size_for_big_int(val) - 1
while True:
try:
# see if we have enough room
val.tobytes(bytelen, 'little', False)
return bytelen
except OverflowError:
bytelen += 1

@LargeIntegers.expose_primitive(unwrap_spec=[object])
def primNormalizePositive(interp, s_frame, w_rcvr):
if isinstance(w_rcvr, W_BytesObject):
# only bytes object may be denormalized
return interp.space.wrap_rbigint(w_rcvr.unwrap_rbigint(interp.space))
elif isinstance(w_rcvr, W_LargeIntegerBig):
w_rcvr._exposed_size = minimum_bytelen_for(w_rcvr.value)
return w_rcvr

@LargeIntegers.expose_primitive(unwrap_spec=[object])
def primNormalizeNegative(interp, s_frame, w_rcvr):
if isinstance(w_rcvr, W_BytesObject):
# only bytes object may be denormalized
return interp.space.wrap_rbigint(w_rcvr.unwrap_rbigint(interp.space))
elif isinstance(w_rcvr, W_LargeIntegerBig):
w_rcvr._exposed_size = minimum_bytelen_for(w_rcvr.value.abs())
return w_rcvr

0 comments on commit fa09553

Please sign in to comment.