# [pypy-svn] pypy real-rffi.INT: hg merge default

Wed Mar 2 20:23:00 CET 2011

```Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: real-rffi.INT
Changeset: r42389:8cc22ca5785c
Date: 2011-03-02 13:58 +0100
http://bitbucket.org/pypy/pypy/changeset/8cc22ca5785c/

Log:	hg merge default

diff --git a/pypy/rlib/rarithmetic.py b/pypy/rlib/rarithmetic.py
--- a/pypy/rlib/rarithmetic.py
+++ b/pypy/rlib/rarithmetic.py
@@ -33,12 +33,10 @@

"""
-import sys, math
+import sys
from pypy.rpython import extregistry
from pypy.rlib import objectmodel

-USE_SHORT_FLOAT_REPR = True # XXX make it a translation option?
-
# set up of machine internals
_bits = 0
_itest = 1
@@ -60,117 +58,6 @@
LONG_BIT_SHIFT += 1

-INFINITY = 1e200 * 1e200
-NAN = INFINITY / INFINITY
-
-try:
-    # Try to get math functions added in 2.6.
-    from math import isinf, isnan, copysign, acosh, asinh, atanh, log1p
-except ImportError:
-    def isinf(x):
-        "NOT_RPYTHON"
-        return x == INFINITY or x == -INFINITY
-
-    def isnan(v):
-        "NOT_RPYTHON"
-        return v != v
-
-    def copysign(x, y):
-        """NOT_RPYTHON. Return x with the sign of y"""
-        if x < 0.:
-            x = -x
-        if y > 0. or (y == 0. and math.atan2(y, -1.) > 0.):
-            return x
-        else:
-            return -x
-
-    _2_to_m28 = 3.7252902984619141E-09; # 2**-28
-    _2_to_p28 = 268435456.0; # 2**28
-    _ln2 = 6.93147180559945286227E-01
-
-    def acosh(x):
-        "NOT_RPYTHON"
-        if isnan(x):
-            return NAN
-        if x < 1.:
-            raise ValueError("math domain error")
-        if x >= _2_to_p28:
-            if isinf(x):
-                return x
-            else:
-                return math.log(x) + _ln2
-        if x == 1.:
-            return 0.
-        if x >= 2.:
-            t = x * x
-            return math.log(2. * x - 1. / (x + math.sqrt(t - 1.0)))
-        t = x - 1.0
-        return log1p(t + math.sqrt(2. * t + t * t))
-
-    def asinh(x):
-        "NOT_RPYTHON"
-        absx = abs(x)
-        if isnan(x) or isinf(x):
-            return x
-        if absx < _2_to_m28:
-            return x
-        if absx > _2_to_p28:
-            w = math.log(absx) + _ln2
-        elif absx > 2.:
-            w = math.log(2. * absx + 1. / (math.sqrt(x * x + 1.) + absx))
-        else:
-            t = x * x
-            w = log1p(absx + t / (1. + math.sqrt(1. + t)))
-        return copysign(w, x)
-
-    def atanh(x):
-        "NOT_RPYTHON"
-        if isnan(x):
-            return x
-        absx = abs(x)
-        if absx >= 1.:
-            raise ValueError("math domain error")
-        if absx < _2_to_m28:
-            return x
-        if absx < .5:
-            t = absx + absx
-            t = .5 * log1p(t + t * absx / (1. - absx))
-        else:
-            t = .5 * log1p((absx + absx) / (1. - absx))
-        return copysign(t, x)
-
-    def log1p(x):
-        "NOT_RPYTHON"
-        from pypy.rlib import rfloat
-        if abs(x) < rfloat.DBL_EPSILON // 2.:
-            return x
-        elif -.5 <= x <= 1.:
-            y = 1. + x
-            return math.log(y) - ((y - 1.) - x) / y
-        else:
-            return math.log(1. + x)
-
-try:
-    from math import expm1 # Added in Python 2.7.
-except ImportError:
-    def expm1(x):
-        "NOT_RPYTHON"
-        if abs(x) < .7:
-            u = math.exp(x)
-            if u == 1.:
-                return x
-            return (u - 1.) * x / math.log(u)
-        return math.exp(x) - 1.
-
-def round_away(x):
-    # round() from libm, which is not available on all platforms!
-    absx = abs(x)
-    if absx - math.floor(absx) >= .5:
-        r = math.ceil(absx)
-    else:
-        r = math.floor(absx)
-    return copysign(r, x)
-
if isinstance(n, int):
return int(n)   # possibly bool->int
@@ -243,6 +130,7 @@
# successfully be casted to an int.
if sys.maxint == 2147483647:
def ovfcheck_float_to_int(x):
+        from pypy.rlib.rfloat import isnan
if isnan(x):
raise OverflowError
if -2147483649.0 < x < 2147483648.0:
@@ -253,6 +141,7 @@
# Note the "<= x <" here, as opposed to "< x <" above.
# This is justified by test_typed in translator/c/test.
def ovfcheck_float_to_int(x):
+        from pypy.rlib.rfloat import isnan
if isnan(x):
raise OverflowError
if -9223372036854776832.0 <= x < 9223372036854775296.0:
@@ -550,259 +439,6 @@
(False, 64): r_ulonglong,
}

-def rstring_to_float(s):
-    if USE_SHORT_FLOAT_REPR:
-        from pypy.rlib.rdtoa import strtod
-        return strtod(s)
-
-    sign, before_point, after_point, exponent = break_up_float(s)
-
-    if not before_point and not after_point:
-        raise ValueError
-
-    return parts_to_float(sign, before_point, after_point, exponent)
-
-# float as string  -> sign, beforept, afterpt, exponent
-def break_up_float(s):
-    i = 0
-
-    sign = ''
-    before_point = ''
-    after_point = ''
-    exponent = ''
-
-    if s[i] in '+-':
-        sign = s[i]
-        i += 1
-
-    while i < len(s) and s[i] in '0123456789':
-        before_point += s[i]
-        i += 1
-
-    if i == len(s):
-        return sign, before_point, after_point, exponent
-
-    if s[i] == '.':
-        i += 1
-        while i < len(s) and s[i] in '0123456789':
-            after_point += s[i]
-            i += 1
-
-        if i == len(s):
-            return sign, before_point, after_point, exponent
-
-    if s[i] not in  'eE':
-        raise ValueError
-
-    i += 1
-    if i == len(s):
-        raise ValueError
-
-    if s[i] in '-+':
-        exponent += s[i]
-        i += 1
-
-    if i == len(s):
-        raise ValueError
-
-    while i < len(s) and s[i] in '0123456789':
-        exponent += s[i]
-        i += 1
-
-    if i != len(s):
-        raise ValueError
-
-    return sign, before_point, after_point, exponent
-
-# string -> float helper
-
-def parts_to_float(sign, beforept, afterpt, exponent):
-    "NOT_RPYTHON"
-    if not exponent:
-        exponent = '0'
-    return float("%s%s.%se%s" % (sign, beforept, afterpt, exponent))
-
-# float -> string
-
-DTSF_STR_PRECISION = 12
-
-DTSF_SIGN      = 0x1
-DTSF_ALT       = 0x4
-
-DIST_FINITE   = 1
-DIST_NAN      = 2
-DIST_INFINITY = 3
-
-# Equivalent to CPython's PyOS_double_to_string
-def _formatd(x, code, precision, flags):
-    "NOT_RPYTHON"
-    if flags & DTSF_ALT:
-        alt = '#'
-    else:
-        alt = ''
-
-    if code == 'r':
-        fmt = "%r"
-    else:
-        fmt = "%%%s.%d%s" % (alt, precision, code)
-    s = fmt % (x,)
-
-        # We want float numbers to be recognizable as such,
-        # i.e., they should contain a decimal point or an exponent.
-        # However, %g may print the number as an integer;
-        # in such cases, we append ".0" to the string.
-        for c in s:
-            if c in '.eE':
-                break
-        else:
-            s += '.0'
-    elif code == 'r' and s.endswith('.0'):
-        s = s[:-2]
-
-    return s
-
-def formatd(x, code, precision, flags=0):
-    if USE_SHORT_FLOAT_REPR:
-        from pypy.rlib.rdtoa import dtoa_formatd
-        return dtoa_formatd(x, code, precision, flags)
-    else:
-        return _formatd(x, code, precision, flags)
-
-def double_to_string(value, tp, precision, flags):
-    if isnan(value):
-        special = DIST_NAN
-    elif isinf(value):
-        special = DIST_INFINITY
-    else:
-        special = DIST_FINITE
-    result = formatd(value, tp, precision, flags)
-    return result, special
-
-if USE_SHORT_FLOAT_REPR:
-    def round_double(value, ndigits):
-        # The basic idea is very simple: convert and round the double to
-        # a decimal string using _Py_dg_dtoa, then convert that decimal
-        # string back to a double with _Py_dg_strtod.  There's one minor
-        # difficulty: Python 2.x expects round to do
-        # round-half-away-from-zero, while _Py_dg_dtoa does
-        # round-half-to-even.  So we need some way to detect and correct
-        # the halfway cases.
-
-        # a halfway value has the form k * 0.5 * 10**-ndigits for some
-        # odd integer k.  Or in other words, a rational number x is
-        # exactly halfway between two multiples of 10**-ndigits if its
-        # 2-valuation is exactly -ndigits-1 and its 5-valuation is at
-        # least -ndigits.  For ndigits >= 0 the latter condition is
-        # automatically satisfied for a binary float x, since any such
-        # float has nonnegative 5-valuation.  For 0 > ndigits >= -22, x
-        # needs to be an integral multiple of 5**-ndigits; we can check
-        # this using fmod.  For -22 > ndigits, there are no halfway
-        # cases: 5**23 takes 54 bits to represent exactly, so any odd
-        # multiple of 0.5 * 10**n for n >= 23 takes at least 54 bits of
-        # precision to represent exactly.
-
-        sign = copysign(1.0, value)
-        value = abs(value)
-
-        # find 2-valuation value
-        m, expo = math.frexp(value)
-        while m != math.floor(m):
-            m *= 2.0
-            expo -= 1
-
-        # determine whether this is a halfway case.
-        halfway_case = 0
-        if expo == -ndigits - 1:
-            if ndigits >= 0:
-                halfway_case = 1
-            elif ndigits >= -22:
-                # 22 is the largest k such that 5**k is exactly
-                # representable as a double
-                five_pow = 1.0
-                for i in range(-ndigits):
-                    five_pow *= 5.0
-                if math.fmod(value, five_pow) == 0.0:
-                    halfway_case = 1
-
-        # round to a decimal string; use an extra place for halfway case
-        strvalue = formatd(value, 'f', ndigits + halfway_case)
-
-        if halfway_case:
-            buf = [c for c in strvalue]
-            if ndigits >= 0:
-                endpos = len(buf) - 1
-            else:
-                endpos = len(buf) + ndigits
-            # Sanity checks: there should be exactly ndigits+1 places
-            # following the decimal point, and the last digit in the
-            # buffer should be a '5'
-            if not objectmodel.we_are_translated():
-                assert buf[endpos] == '5'
-                if '.' in buf:
-                    assert endpos == len(buf) - 1
-                    assert buf.index('.') == len(buf) - ndigits - 2
-
-            # increment and shift right at the same time
-            i = endpos - 1
-            carry = 1
-            while i >= 0:
-                digit = ord(buf[i])
-                if digit == ord('.'):
-                    buf[i+1] = chr(digit)
-                    i -= 1
-                    digit = ord(buf[i])
-
-                carry += digit - ord('0')
-                buf[i+1] = chr(carry % 10 + ord('0'))
-                carry /= 10
-                i -= 1
-            buf[0] = chr(carry + ord('0'))
-            if ndigits < 0:
-                buf.append('0')
-
-            strvalue = ''.join(buf)
-
-        return sign * rstring_to_float(strvalue)
-
-else:
-    # fallback version, to be used when correctly rounded
-    # binary<->decimal conversions aren't available
-    def round_double(value, ndigits):
-        if ndigits >= 0:
-            if ndigits > 22:
-                # pow1 and pow2 are each safe from overflow, but
-                # pow1*pow2 ~= pow(10.0, ndigits) might overflow
-                pow1 = math.pow(10.0, ndigits - 22)
-                pow2 = 1e22
-            else:
-                pow1 = math.pow(10.0, ndigits)
-                pow2 = 1.0
-
-            y = (value * pow1) * pow2
-            # if y overflows, then rounded value is exactly x
-            if isinf(y):
-                return value
-
-        else:
-            pow1 = math.pow(10.0, -ndigits);
-            pow2 = 1.0 # unused; for translation
-            y = value / pow1
-
-        if y >= 0.0:
-            z = math.floor(y + 0.5)
-        else:
-            z = math.ceil(y - 0.5)
-        if math.fabs(y-z) == 1.0:   # obscure case, see the test
-            z = y
-
-        if ndigits >= 0:
-            z = (z / pow2) / pow1
-        else:
-            z *= pow1
-        return z
-
# the 'float' C type

class r_singlefloat(object):

diff --git a/pypy/translator/c/primitive.py b/pypy/translator/c/primitive.py
--- a/pypy/translator/c/primitive.py
+++ b/pypy/translator/c/primitive.py
@@ -1,7 +1,8 @@
import sys
from pypy.rlib.objectmodel import Symbolic, ComputedIntSymbolic
from pypy.rlib.objectmodel import CDefinedIntSymbolic
-from pypy.rlib.rarithmetic import r_longlong, isinf, isnan
+from pypy.rlib.rarithmetic import r_longlong
+from pypy.rlib.rfloat import isinf, isnan
from pypy.rpython.lltypesystem.lltype import *
from pypy.rpython.lltypesystem import rffi, llgroup