예제 #1
0
 def f(x):
     if x == 0:
         s = '1.0'
     else:
         s = '1e-100'
     sign, beforept, afterpt, expt = break_up_float(s)   
     return parts_to_float(sign, beforept, afterpt, expt)
예제 #2
0
def string_to_float(s):
    """
    Conversion of string to float.
    This version tries to only raise on invalid literals.
    Overflows should be converted to infinity whenever possible.
    """

    s = strip_spaces(s)

    if not s:
        raise ParseStringError("empty string for float()")

    # 1) parse the string into pieces.
    try:
        sign, before_point, after_point, exponent = break_up_float(s)
    except ValueError:
        raise ParseStringError("invalid literal for float()")
    
    if not before_point and not after_point:
        raise ParseStringError("invalid literal for float()")

    try:
        return parts_to_float(sign, before_point, after_point, exponent)
    except ValueError:
        raise ParseStringError("invalid literal for float()")
예제 #3
0
 def f(x):
     if x == 0:
         s = '1.0'
     else:
         s = '1e-100'
     sign, beforept, afterpt, expt = break_up_float(s)
     return parts_to_float(sign, beforept, afterpt, expt)
예제 #4
0
    def ll_float(ll_str):
        from pypy.rpython.annlowlevel import hlstr
        from pypy.rlib.rarithmetic import break_up_float, parts_to_float
        s = hlstr(ll_str)
        assert s is not None

        n = len(s)
        beg = 0
        while beg < n:
            if s[beg] == ' ':
                beg += 1
            else:
                break
        if beg == n:
            raise ValueError
        end = n-1
        while end >= 0:
            if s[end] == ' ':
                end -= 1
            else:
                break
        assert end >= 0
        sign, before_point, after_point, exponent = break_up_float(s[beg:end+1])
    
        if not before_point and not after_point:
            raise ValueError

        return parts_to_float(sign, before_point, after_point, exponent)
예제 #5
0
파일: rstr.py 프로젝트: xx312022850/pypy
    def ll_float(ll_str):
        from pypy.rpython.annlowlevel import hlstr
        from pypy.rlib.rarithmetic import break_up_float, parts_to_float
        s = hlstr(ll_str)
        assert s is not None

        n = len(s)
        beg = 0
        while beg < n:
            if s[beg] == ' ':
                beg += 1
            else:
                break
        if beg == n:
            raise ValueError
        end = n - 1
        while end >= 0:
            if s[end] == ' ':
                end -= 1
            else:
                break
        assert end >= 0
        sign, before_point, after_point, exponent = break_up_float(s[beg:end +
                                                                     1])

        if not before_point and not after_point:
            raise ValueError

        return parts_to_float(sign, before_point, after_point, exponent)
예제 #6
0
파일: strutil.py 프로젝트: xx312022850/pypy
def string_to_float(s):
    """
    Conversion of string to float.
    This version tries to only raise on invalid literals.
    Overflows should be converted to infinity whenever possible.
    """

    s = strip_spaces(s)

    if not s:
        raise ParseStringError("empty string for float()")

    # 1) parse the string into pieces.
    try:
        sign, before_point, after_point, exponent = break_up_float(s)
    except ValueError:
        raise ParseStringError("invalid literal for float()")

    if not before_point and not after_point:
        raise ParseStringError("invalid literal for float()")

    try:
        return parts_to_float(sign, before_point, after_point, exponent)
    except ValueError:
        raise ParseStringError("invalid literal for float()")
예제 #7
0
def test_break_up_float():
    assert break_up_float('1') == ('', '1', '', '')
    assert break_up_float('+1') == ('+', '1', '', '')
    assert break_up_float('-1') == ('-', '1', '', '')

    assert break_up_float('.5') == ('', '', '5', '')
    
    assert break_up_float('1.2e3') == ('', '1', '2', '3')
    assert break_up_float('1.2e+3') == ('', '1', '2', '+3')
    assert break_up_float('1.2e-3') == ('', '1', '2', '-3')

    # some that will get thrown out on return:
    assert break_up_float('.') == ('', '', '', '')
    assert break_up_float('+') == ('+', '', '', '')
    assert break_up_float('-') == ('-', '', '', '')
    assert break_up_float('e1') == ('', '', '', '1')

    py.test.raises(ValueError, break_up_float, 'e')
예제 #8
0
def interp_string_to_float(space, s):
    """
    Conversion of string to float.
    This version tries to only raise on invalid literals.
    Overflows should be converted to infinity whenever possible.

    Expects an unwrapped string and return an unwrapped float.
    """

    s = strip_spaces(s)

    if not s:
        raise OperationError(space.w_ValueError, space.wrap(
            "empty string for float()"))

    # 1) parse the string into pieces.
    try:
        sign, before_point, after_point, exponent = break_up_float(s)
    except ValueError:
        raise ParseStringError("invalid literal for float()")
    
    digits = before_point + after_point
    if not digits:
        raise ParseStringError("invalid literal for float()")

    # 2) pre-calculate digit exponent dexp.
    dexp = len(before_point)

    # 3) truncate and adjust dexp.
    p = 0
    plim = dexp + len(after_point)
    while p < plim and digits[p] == '0':
        p += 1
        dexp -= 1
    digits = digits[p : p + MANTISSA_DIGITS]
    p = len(digits) - 1
    while p >= 0 and digits[p] == '0':
        p -= 1
    dexp -= p + 1
    p += 1
    assert p >= 0
    digits = digits[:p]
    if len(digits) == 0:
        digits = '0'

    # a few abbreviations
    from pypy.objspace.std import longobject
    mklong = longobject.W_LongObject.fromint
    d2long = longobject.W_LongObject.fromdecimalstr
    adlong = longobject.add__Long_Long
    longup = longobject.pow__Long_Long_None
    multip = longobject.mul__Long_Long
    divide = longobject.div__Long_Long
    lshift = longobject.lshift__Long_Long
    rshift = longobject.rshift__Long_Long

    # 4) compute the exponent and truncate to +-400
    if not exponent:
        exponent = '0'
    w_le = d2long(exponent)
    w_le = adlong(space, w_le, mklong(space, dexp))
    try:
        e = w_le.toint()
    except OverflowError:
        # XXX poking at internals
        e = w_le.num.sign * 400
    if e >= 400:
        e = 400
    elif e <= -400:
        e = -400

    # 5) compute the value using long math and proper rounding.
    w_lr = d2long(digits)
    w_10 = mklong(space, 10)
    w_1 = mklong(space, 1)
    if e >= 0:
        bits = 0
        w_pten = longup(space, w_10, mklong(space, e), space.w_None)
        w_m = multip(space, w_lr, w_pten)
    else:
        # compute a sufficiently large scale
        prec = MANTISSA_DIGITS * 2 + 22 # 128, maybe
        bits = - (int(math.ceil(-e / math.log10(2.0) - 1e-10)) + prec)
        w_scale = lshift(space, w_1, mklong(space, -bits))
        w_pten = longup(space, w_10, mklong(space, -e), None)
        w_tmp = multip(space, w_lr, w_scale)
        w_m = divide(space, w_tmp, w_pten)

    # we now have a fairly large mantissa.
    # Shift it and round the last bit.

    # first estimate the bits and do a big shift
    mbits = w_m._count_bits()
    needed = MANTISSA_BITS
    if mbits > needed:
        if mbits > needed+1:
            shifted = mbits - (needed+1)
            w_m = rshift(space, w_m, mklong(space, shifted))
            bits += shifted
        # do the rounding
        bits += 1
        round = w_m.is_odd()
        w_m = rshift(space, w_m, w_1)
        w_m = adlong(space, w_m, mklong(space, round))

    try:
        r = math.ldexp(w_m.tofloat(), bits)
        # XXX I guess we do not check for overflow in ldexp as we agreed to!
        if r == 2*r and r != 0.0:
            raise OverflowError
    except OverflowError:
        r = 1e200 * 1e200 # produce inf, hopefully

    if sign == '-':
        r = -r

    return r
예제 #9
0
def applevel_string_to_float(s):
    """
    Conversion of string to float.
    This version tries to only raise on invalid literals.
    Overflows should be converted to infinity whenever possible.
    """
    # this version was triggered by Python 2.4 which adds
    # a test that breaks on overflow.
    # XXX The test still breaks for a different reason:
    # float must implement rich comparisons, where comparison
    # between infinity and a too large long does not overflow!

    # The problem:
    # there can be extreme notations of floats which are not
    # infinity.
    # For instance, this works in CPython:
    # float('1' + '0'*1000 + 'e-1000')
    # should evaluate to 1.0.
    # note: float('1' + '0'*10000 + 'e-10000')
    # does not work in CPython, but PyPy can do it, now.

    # The idea:
    # in order to compensate between very long digit strings
    # and extreme exponent numbers, we try to avoid overflows
    # by adjusting the exponent by the number of mantissa
    # digits. For simplicity, all computations are done in
    # long math.

    # The plan:
    # 1) parse the string into pieces.
    # 2) pre-calculate digit exponent dexp.
    # 3) truncate and adjust dexp.
    # 4) compute the exponent and truncate to +-400.
    # 5) compute the value using long math and proper rounding.

    # Positive results:
    # The algorithm appears appears to produce correct round-trip
    # values for the perfect input of _float_formatting.
    # Note:
    # XXX: the builtin rounding of long->float does not work, correctly.
    # Ask Tim Peters for the reasons why no correct rounding is done.
    # XXX: limitations:
    # - It is possibly not too efficient.
    # - Really optimum results need a more sophisticated algorithm
    #   like Bellerophon from William D. Clinger, cf.
    #   http://citeseer.csail.mit.edu/clinger90how.html
    
    s = strip_spaces(s)

    if not s:
        raise ParseStringError("empty string for float()")

    # 1) parse the string into pieces.
    try:
        sign, before_point, after_point, exponent = break_up_float(s)
    except ValueError:
        raise ParseStringError("invalid literal for float()")
        
    digits = before_point + after_point
    if digits:
        raise ParseStringError("invalid literal for float()")

    # 2) pre-calculate digit exponent dexp.
    dexp = len(before_point)

    # 3) truncate and adjust dexp.
    p = 0
    plim = dexp + len(after_point)
    while p < plim and digits[p] == '0':
        p += 1
        dexp -= 1
    digits = digits[p : p + MANTISSA_DIGITS]
    p = len(digits) - 1
    while p >= 0 and digits[p] == '0':
        p -= 1
    dexp -= p + 1
    digits = digits[:p+1]
    if len(digits) == 0:
        digits = '0'

    # 4) compute the exponent and truncate to +-400
    if not exponent:
        exponent = '0'
    e = long(exponent) + dexp
    if e >= 400:
        e = 400
    elif e <= -400:
        e = -400

    # 5) compute the value using long math and proper rounding.
    lr = long(digits)
    if e >= 0:
        bits = 0
        m = lr * 10L ** e
    else:
        # compute a sufficiently large scale
        prec = MANTISSA_DIGITS * 2 + 22 # 128, maybe
        bits = - (int(math.ceil(-e / math.log10(2.0) - 1e-10)) + prec)
        scale = 2L ** -bits
        pten = 10L ** -e
        m = (lr * scale) // pten

    # we now have a fairly large mantissa.
    # Shift it and round the last bit.

    # first estimate the bits and do a big shift
    if m:
        mbits = int(math.ceil(math.log(m, 2) - 1e-10))
        needed = MANTISSA_BITS
        if mbits > needed:
            if mbits > needed+1:
                shifted = mbits - (needed+1)
                m >>= shifted
                bits += shifted
            # do the rounding
            bits += 1
            m = (m >> 1) + (m & 1)

    try:
        r = math.ldexp(m, bits)
    except OverflowError:
        r = 1e200 * 1e200 # produce inf, hopefully

    if sign == '-':
        r = -r

    return r
예제 #10
0
def load_float(loader):
    if readchr(loader) != TYPE_FLOAT:
        raise ValueError("expected a float")
    length = ord(readchr(loader))
    s = readstr(loader, length)
    return parts_to_float(*break_up_float(s))
예제 #11
0
def test_break_up_float():
    assert break_up_float('1') == ('', '1', '', '')
    assert break_up_float('+1') == ('+', '1', '', '')
    assert break_up_float('-1') == ('-', '1', '', '')

    assert break_up_float('.5') == ('', '', '5', '')

    assert break_up_float('1.2e3') == ('', '1', '2', '3')
    assert break_up_float('1.2e+3') == ('', '1', '2', '+3')
    assert break_up_float('1.2e-3') == ('', '1', '2', '-3')

    # some that will get thrown out on return:
    assert break_up_float('.') == ('', '', '', '')
    assert break_up_float('+') == ('+', '', '', '')
    assert break_up_float('-') == ('-', '', '', '')
    assert break_up_float('e1') == ('', '', '', '1')

    py.test.raises(ValueError, break_up_float, 'e')
예제 #12
0
파일: rmarshal.py 프로젝트: alkorzt/pypy
def load_float(loader):
    if readchr(loader) != TYPE_FLOAT:
        raise ValueError("expected a float")
    length = ord(readchr(loader))
    s = readstr(loader, length)
    return parts_to_float(*break_up_float(s))
예제 #13
0
파일: strutil.py 프로젝트: xx312022850/pypy
def interp_string_to_float(space, s):
    """
    Conversion of string to float.
    This version tries to only raise on invalid literals.
    Overflows should be converted to infinity whenever possible.

    Expects an unwrapped string and return an unwrapped float.
    """

    s = strip_spaces(s)

    if not s:
        raise OperationError(space.w_ValueError,
                             space.wrap("empty string for float()"))

    # 1) parse the string into pieces.
    try:
        sign, before_point, after_point, exponent = break_up_float(s)
    except ValueError:
        raise ParseStringError("invalid literal for float()")

    digits = before_point + after_point
    if not digits:
        raise ParseStringError("invalid literal for float()")

    # 2) pre-calculate digit exponent dexp.
    dexp = len(before_point)

    # 3) truncate and adjust dexp.
    p = 0
    plim = dexp + len(after_point)
    while p < plim and digits[p] == '0':
        p += 1
        dexp -= 1
    digits = digits[p:p + MANTISSA_DIGITS]
    p = len(digits) - 1
    while p >= 0 and digits[p] == '0':
        p -= 1
    dexp -= p + 1
    p += 1
    assert p >= 0
    digits = digits[:p]
    if len(digits) == 0:
        digits = '0'

    # a few abbreviations
    from pypy.objspace.std import longobject
    mklong = longobject.W_LongObject.fromint
    d2long = longobject.W_LongObject.fromdecimalstr
    adlong = longobject.add__Long_Long
    longup = longobject.pow__Long_Long_None
    multip = longobject.mul__Long_Long
    divide = longobject.div__Long_Long
    lshift = longobject.lshift__Long_Long
    rshift = longobject.rshift__Long_Long

    # 4) compute the exponent and truncate to +-400
    if not exponent:
        exponent = '0'
    w_le = d2long(exponent)
    w_le = adlong(space, w_le, mklong(space, dexp))
    try:
        e = w_le.toint()
    except OverflowError:
        # XXX poking at internals
        e = w_le.num.sign * 400
    if e >= 400:
        e = 400
    elif e <= -400:
        e = -400

    # 5) compute the value using long math and proper rounding.
    w_lr = d2long(digits)
    w_10 = mklong(space, 10)
    w_1 = mklong(space, 1)
    if e >= 0:
        bits = 0
        w_pten = longup(space, w_10, mklong(space, e), space.w_None)
        w_m = multip(space, w_lr, w_pten)
    else:
        # compute a sufficiently large scale
        prec = MANTISSA_DIGITS * 2 + 22  # 128, maybe
        bits = -(int(math.ceil(-e / math.log10(2.0) - 1e-10)) + prec)
        w_scale = lshift(space, w_1, mklong(space, -bits))
        w_pten = longup(space, w_10, mklong(space, -e), None)
        w_tmp = multip(space, w_lr, w_scale)
        w_m = divide(space, w_tmp, w_pten)

    # we now have a fairly large mantissa.
    # Shift it and round the last bit.

    # first estimate the bits and do a big shift
    mbits = w_m._count_bits()
    needed = MANTISSA_BITS
    if mbits > needed:
        if mbits > needed + 1:
            shifted = mbits - (needed + 1)
            w_m = rshift(space, w_m, mklong(space, shifted))
            bits += shifted
        # do the rounding
        bits += 1
        round = w_m.is_odd()
        w_m = rshift(space, w_m, w_1)
        w_m = adlong(space, w_m, mklong(space, round))

    try:
        r = math.ldexp(w_m.tofloat(), bits)
        # XXX I guess we do not check for overflow in ldexp as we agreed to!
        if r == 2 * r and r != 0.0:
            raise OverflowError
    except OverflowError:
        r = 1e200 * 1e200  # produce inf, hopefully

    if sign == '-':
        r = -r

    return r
예제 #14
0
파일: strutil.py 프로젝트: xx312022850/pypy
def applevel_string_to_float(s):
    """
    Conversion of string to float.
    This version tries to only raise on invalid literals.
    Overflows should be converted to infinity whenever possible.
    """
    # this version was triggered by Python 2.4 which adds
    # a test that breaks on overflow.
    # XXX The test still breaks for a different reason:
    # float must implement rich comparisons, where comparison
    # between infinity and a too large long does not overflow!

    # The problem:
    # there can be extreme notations of floats which are not
    # infinity.
    # For instance, this works in CPython:
    # float('1' + '0'*1000 + 'e-1000')
    # should evaluate to 1.0.
    # note: float('1' + '0'*10000 + 'e-10000')
    # does not work in CPython, but PyPy can do it, now.

    # The idea:
    # in order to compensate between very long digit strings
    # and extreme exponent numbers, we try to avoid overflows
    # by adjusting the exponent by the number of mantissa
    # digits. For simplicity, all computations are done in
    # long math.

    # The plan:
    # 1) parse the string into pieces.
    # 2) pre-calculate digit exponent dexp.
    # 3) truncate and adjust dexp.
    # 4) compute the exponent and truncate to +-400.
    # 5) compute the value using long math and proper rounding.

    # Positive results:
    # The algorithm appears appears to produce correct round-trip
    # values for the perfect input of _float_formatting.
    # Note:
    # XXX: the builtin rounding of long->float does not work, correctly.
    # Ask Tim Peters for the reasons why no correct rounding is done.
    # XXX: limitations:
    # - It is possibly not too efficient.
    # - Really optimum results need a more sophisticated algorithm
    #   like Bellerophon from William D. Clinger, cf.
    #   http://citeseer.csail.mit.edu/clinger90how.html

    s = strip_spaces(s)

    if not s:
        raise ParseStringError("empty string for float()")

    # 1) parse the string into pieces.
    try:
        sign, before_point, after_point, exponent = break_up_float(s)
    except ValueError:
        raise ParseStringError("invalid literal for float()")

    digits = before_point + after_point
    if digits:
        raise ParseStringError("invalid literal for float()")

    # 2) pre-calculate digit exponent dexp.
    dexp = len(before_point)

    # 3) truncate and adjust dexp.
    p = 0
    plim = dexp + len(after_point)
    while p < plim and digits[p] == '0':
        p += 1
        dexp -= 1
    digits = digits[p:p + MANTISSA_DIGITS]
    p = len(digits) - 1
    while p >= 0 and digits[p] == '0':
        p -= 1
    dexp -= p + 1
    digits = digits[:p + 1]
    if len(digits) == 0:
        digits = '0'

    # 4) compute the exponent and truncate to +-400
    if not exponent:
        exponent = '0'
    e = long(exponent) + dexp
    if e >= 400:
        e = 400
    elif e <= -400:
        e = -400

    # 5) compute the value using long math and proper rounding.
    lr = long(digits)
    if e >= 0:
        bits = 0
        m = lr * 10L**e
    else:
        # compute a sufficiently large scale
        prec = MANTISSA_DIGITS * 2 + 22  # 128, maybe
        bits = -(int(math.ceil(-e / math.log10(2.0) - 1e-10)) + prec)
        scale = 2L**-bits
        pten = 10L**-e
        m = (lr * scale) // pten

    # we now have a fairly large mantissa.
    # Shift it and round the last bit.

    # first estimate the bits and do a big shift
    if m:
        mbits = int(math.ceil(math.log(m, 2) - 1e-10))
        needed = MANTISSA_BITS
        if mbits > needed:
            if mbits > needed + 1:
                shifted = mbits - (needed + 1)
                m >>= shifted
                bits += shifted
            # do the rounding
            bits += 1
            m = (m >> 1) + (m & 1)

    try:
        r = math.ldexp(m, bits)
    except OverflowError:
        r = 1e200 * 1e200  # produce inf, hopefully

    if sign == '-':
        r = -r

    return r