Skip to content

Commit fa09553

Browse files
committed
actually normalize rbigints when the image asks us (addresses overflows in #131)
1 parent 5e3965b commit fa09553

File tree

2 files changed

+17
-7
lines changed

2 files changed

+17
-7
lines changed

rsqueakvm/model/numeric.py

-6
Original file line numberDiff line numberDiff line change
@@ -204,12 +204,6 @@ def calculate_exposed_size_for_big_int(value):
204204
bytelenval = value.abs()
205205
# XXX +0.05: heuristic hack float rounding errors
206206
return int(math.floor(bytelenval.log(256) + 0.05)) + 1
207-
# TODO: check if this might be better
208-
# try:
209-
# bytes = val.tobytes(bytelen, 'little', False)
210-
# except OverflowError:
211-
# # round-off errors in math.log, might need an extra byte
212-
# bytes = val.tobytes(bytelen + 1, 'little', False)
213207

214208

215209
class W_LargeIntegerBig(W_LargeInteger):

rsqueakvm/plugins/large_integers.py

+17-1
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@
22
from rsqueakvm.plugins.plugin import Plugin
33
from rsqueakvm.primitives import prim_table
44
from rsqueakvm.primitives.constants import *
5-
from rsqueakvm.model.numeric import W_LargeInteger
5+
from rsqueakvm.model.numeric import W_LargeInteger, W_LargeIntegerBig, calculate_exposed_size_for_big_int
66
from rsqueakvm.model.variable import W_BytesObject
77

88
from rpython.rlib.rbigint import rbigint, NULLRBIGINT, _divrem
9+
from rpython.rlib import jit
910

1011
LargeIntegers = Plugin()
1112

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

77+
@jit.elidable
78+
def minimum_bytelen_for(val):
79+
bytelen = calculate_exposed_size_for_big_int(val) - 1
80+
while True:
81+
try:
82+
# see if we have enough room
83+
val.tobytes(bytelen, 'little', False)
84+
return bytelen
85+
except OverflowError:
86+
bytelen += 1
87+
7688
@LargeIntegers.expose_primitive(unwrap_spec=[object])
7789
def primNormalizePositive(interp, s_frame, w_rcvr):
7890
if isinstance(w_rcvr, W_BytesObject):
7991
# only bytes object may be denormalized
8092
return interp.space.wrap_rbigint(w_rcvr.unwrap_rbigint(interp.space))
93+
elif isinstance(w_rcvr, W_LargeIntegerBig):
94+
w_rcvr._exposed_size = minimum_bytelen_for(w_rcvr.value)
8195
return w_rcvr
8296

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

0 commit comments

Comments
 (0)