Source

pypy / pypy / objspace / std / longtype.py

Full commit
Jean-Philippe St… c775f9d 
Armin Rigo 18f173b 
Philip Jenvey 5460b86 

Alex Gaynor d9e0f6c 

David Schneider 3c10bab 
Philip Jenvey 74d461f 
Armin Rigo 6a00154 
Benjamin Peterso… 5fe4377 
Amaury Forgeot d… f4af664 
Alex Gaynor d9e0f6c 

Maciej Fijalkows… 5a165e7 
Armin Rigo 18f173b 
Armin Rigo 9e39f59 
Armin Rigo e1edd42 



David Schneider 0bb85a4 
Armin Rigo 611fa0c 
Armin Rigo 6a00154 

Armin Rigo e1edd42 
Amaury Forgeot d… f4af664 
Armin Rigo e1edd42 

Armin Rigo d0a7bf7 
Justin Peel c5fd944 
Alex Gaynor 73f1193 
Armin Rigo e1edd42 

Antonio Cuni 5e75489 

Antonio Cuni abd04a3 
Antonio Cuni 7e217c7 
Armin Rigo 6a00154 
Amaury Forgeot d… f4af664 
Armin Rigo 72d8475 
Amaury Forgeot d… f4af664 

Armin Rigo 72d8475 

Amaury Forgeot d… dcae009 
Benjamin Peterso… ffa255e 

Armin Rigo b89fa4f 
Armin Rigo d0a7bf7 
Armin Rigo 6a00154 


Justin Peel c5fd944 
Alex Gaynor 73f1193 
Anders Chrigströ… a79d2fb 


Antonio Cuni abd04a3 
Antonio Cuni 7e217c7 
Anders Chrigströ… a79d2fb 



Armin Rigo e1edd42 








Armin Rigo d0a7bf7 
Armin Rigo 9e39f59 

Armin Rigo d0a7bf7 





Armin Rigo e1edd42 
Amaury Forgeot d… f4af664 
Armin Rigo 6a00154 
Armin Rigo d0a7bf7 
Armin Rigo e1edd42 

Armin Rigo d0a7bf7 






Armin Rigo 6a00154 
Benjamin Peterso… c2a4cfc 
Amaury Forgeot d… f4af664 
Benjamin Peterso… c2a4cfc 



Alex Gaynor d9e0f6c 
Amaury Forgeot d… f4af664 
Alex Gaynor d9e0f6c 



Amaury Forgeot d… a0a771c 
Amaury Forgeot d… 99d4a44 
Amaury Forgeot d… a0a771c 
Amaury Forgeot d… 99d4a44 
Amaury Forgeot d… a0a771c 



Philip Jenvey dcd5c7c 


Philip Jenvey 74d461f 
Philip Jenvey dcd5c7c 
Philip Jenvey 74d461f 






Philip Jenvey 2d96b05 
Philip Jenvey 74d461f 














Amaury Forgeot d… 6d32eeb 
Philip Jenvey 5460b86 




































Philip Jenvey 1fd7920 
Philip Jenvey 5460b86 












Armin Rigo 6a00154 

Amaury Forgeot d… f4af664 

lac 264f290 





Armin Rigo 18f173b 
Philip Jenvey 5460b86 
Armin Rigo 18f173b 
Benjamin Peterso… c2a4cfc 

Alex Gaynor d9e0f6c 

Armin Rigo 18f173b 
Philip Jenvey 4bf8235 
Philip Jenvey 74d461f 
Alex Gaynor d9e0f6c 
from pypy.interpreter.error import OperationError
from pypy.interpreter import typedef
from pypy.interpreter.gateway import (applevel, interp2app, unwrap_spec,
                                      WrappedDefault)
from pypy.objspace.std.register_all import register_all
from pypy.objspace.std.stdtypedef import StdTypeDef, SMM
from pypy.objspace.std.strutil import string_to_bigint, ParseStringError
from pypy.rlib.rbigint import rbigint, InvalidEndiannessError, InvalidSignednessError

def descr_conjugate(space, w_int):
    return space.int(w_int)


@unwrap_spec(w_x = WrappedDefault(0))
def descr__new__(space, w_longtype, w_x, w_base=None):
    from pypy.objspace.std.longobject import W_LongObject
    if space.config.objspace.std.withsmalllong:
        from pypy.objspace.std.smalllongobject import W_SmallLongObject
    else:
        W_SmallLongObject = None

    w_value = w_x     # 'x' is the keyword argument name in CPython
    if w_base is None:
        # check for easy cases
        if (W_SmallLongObject and type(w_value) is W_SmallLongObject
            and space.is_w(w_longtype, space.w_int)):
            return w_value
        elif type(w_value) is W_LongObject:
            return newbigint(space, w_longtype, w_value.num)
        elif space.isinstance_w(w_value, space.w_unicode):
            from pypy.objspace.std.unicodeobject import unicode_to_decimal_w
            return string_to_w_long(space, w_longtype,
                                    unicode_to_decimal_w(space, w_value))
        elif (space.isinstance_w(w_value, space.w_bytearray) or
              space.isinstance_w(w_value, space.w_bytes)):
            strvalue = space.bufferstr_w(w_value)
            return string_to_w_long(space, w_longtype, strvalue.decode('latin-1'))
        else:
            # otherwise, use the __int__() or the __trunc__ methods
            w_obj = w_value
            if space.lookup(w_obj, '__int__') is not None:
                w_obj = space.int(w_obj)
            else:
                w_obj = space.trunc(w_obj)
                w_obj = space.int(w_obj)
            if space.is_w(w_longtype, space.w_int):
                return w_obj
            bigint = space.bigint_w(w_obj)
            return newbigint(space, w_longtype, bigint)
    else:
        base = space.int_w(w_base)

        if space.isinstance_w(w_value, space.w_unicode):
            from pypy.objspace.std.unicodeobject import unicode_to_decimal_w
            s = unicode_to_decimal_w(space, w_value)
        else:
            try:
                strval = space.bufferstr_w(w_value)
                s = strval.decode('latin-1')
            except OperationError, e:
                raise OperationError(space.w_TypeError,
                                     space.wrap("long() can't convert non-string "
                                                "with explicit base"))
        return string_to_w_long(space, w_longtype, s, base)


def string_to_w_long(space, w_longtype, s, base=10):
    try:
        bigint = string_to_bigint(s, base)
    except ParseStringError, e:
        raise OperationError(space.w_ValueError,
                             space.wrap(e.msg))
    return newbigint(space, w_longtype, bigint)
string_to_w_long._dont_inline_ = True

def newbigint(space, w_longtype, bigint):
    """Turn the bigint into a W_LongObject.  If withsmalllong is enabled,
    check if the bigint would fit in a smalllong, and return a
    W_SmallLongObject instead if it does.  Similar to newlong() in
    longobject.py, but takes an explicit w_longtype argument.
    """
    if (space.config.objspace.std.withsmalllong
        and space.is_w(w_longtype, space.w_int)):
        try:
            z = bigint.tolonglong()
        except OverflowError:
            pass
        else:
            from pypy.objspace.std.smalllongobject import W_SmallLongObject
            return W_SmallLongObject(z)
    from pypy.objspace.std.longobject import W_LongObject
    w_obj = space.allocate_instance(W_LongObject, w_longtype)
    W_LongObject.__init__(w_obj, bigint)
    return w_obj

def descr_get_numerator(space, w_obj):
    return space.int(w_obj)

def descr_get_denominator(space, w_obj):
    return space.newlong(1)

def descr_get_real(space, w_obj):
    return space.int(w_obj)

def descr_get_imag(space, w_obj):
    return space.newlong(0)

def bit_length(space, w_obj):
    bigint = space.bigint_w(w_obj)
    try:
        return space.wrap(bigint.bit_length())
    except OverflowError:
        raise OperationError(space.w_OverflowError,
                             space.wrap("too many digits in integer"))

@unwrap_spec(byteorder=str, signed=bool)
def descr_from_bytes(space, w_cls, w_obj, byteorder, signed=False):
    bytes = space.bytes_w(space.call_function(space.w_bytes, w_obj))
    try:
        bigint = rbigint.frombytes(bytes, byteorder=byteorder, signed=signed)
    except InvalidEndiannessError:
        raise OperationError(
            space.w_ValueError,
            space.wrap("byteorder must be either 'little' or 'big'"))
    return newbigint(space, w_cls, bigint)

@unwrap_spec(nbytes=int, byteorder=str, signed=bool)
def descr_to_bytes(space, w_obj, nbytes, byteorder, signed=False):
    try:
        byte_string = space.bigint_w(w_obj).tobytes(nbytes, byteorder=byteorder, signed=signed)
    except InvalidEndiannessError:
        raise OperationError(
            space.w_ValueError,
            space.wrap("byteorder must be either 'little' or 'big'"))
    except InvalidSignednessError:
        raise OperationError(
            space.w_OverflowError,
            space.wrap("can't convert negative int to unsigned"))
    except OverflowError:
        raise OperationError(
            space.w_OverflowError,
            space.wrap('int too big to convert'))
    return space.wrapbytes(byte_string)

divmod_near = applevel('''
       def divmod_near(a, b):
           """Return a pair (q, r) such that a = b * q + r, and abs(r)
           <= abs(b)/2, with equality possible only if q is even.  In
           other words, q == a / b, rounded to the nearest integer using
           round-half-to-even."""
           q, r = divmod(a, b)
           # round up if either r / b > 0.5, or r / b == 0.5 and q is
           # odd.  The expression r / b > 0.5 is equivalent to 2 * r > b
           # if b is positive, 2 * r < b if b negative.
           greater_than_half = 2*r > b if b > 0 else 2*r < b
           exactly_half = 2*r == b
           if greater_than_half or exactly_half and q % 2 == 1:
               q += 1
               r -= b
           return q, r
''', filename=__file__).interphook('divmod_near')

def descr___round__(space, w_long, w_ndigits=None):
    """To round an integer m to the nearest 10**n (n positive), we make
    use of the divmod_near operation, defined by:

    divmod_near(a, b) = (q, r)

    where q is the nearest integer to the quotient a / b (the
    nearest even integer in the case of a tie) and r == a - q * b.
    Hence q * b = a - r is the nearest multiple of b to a,
    preferring even multiples in the case of a tie.

    So the nearest multiple of 10**n to m is:

    m - divmod_near(m, 10**n)[1]

    """
    from pypy.objspace.std.longobject import W_AbstractIntObject, newlong
    assert isinstance(w_long, W_AbstractIntObject)

    if w_ndigits is None:
        return space.int(w_long)

    ndigits = space.bigint_w(space.index(w_ndigits))
    # if ndigits >= 0 then no rounding is necessary; return self unchanged
    if ndigits.ge(rbigint.fromint(0)):
        return space.int(w_long)

    # result = self - divmod_near(self, 10 ** -ndigits)[1]
    right = rbigint.fromint(10).pow(ndigits.neg())
    w_temp = divmod_near(space, w_long, newlong(space, right))
    w_temp2 = space.getitem(w_temp, space.wrap(1))
    return space.sub(w_long, w_temp2)

# ____________________________________________________________

long_typedef = StdTypeDef("int",
    __doc__ = '''int(x[, base]) -> integer

Convert a string or number to a long integer, if possible.  A floating
point argument will be truncated towards zero (this does not include a
string representation of a floating point number!)  When converting a
string, use the optional base.  It is an error to supply a base when
converting a non-string.''',
    __new__ = interp2app(descr__new__),
    __round__ = interp2app(descr___round__),
    conjugate = interp2app(descr_conjugate),
    numerator = typedef.GetSetProperty(descr_get_numerator),
    denominator = typedef.GetSetProperty(descr_get_denominator),
    real = typedef.GetSetProperty(descr_get_real),
    imag = typedef.GetSetProperty(descr_get_imag),
    bit_length = interp2app(bit_length),
    from_bytes = interp2app(descr_from_bytes, as_classmethod=True),
    to_bytes = interp2app(descr_to_bytes)
)
long_typedef.registermethods(globals())