Exemple #1
0
def c_cosh(x, y):
    if not isfinite(x) or not isfinite(y):
        if isinf(x) and isfinite(y) and y != 0.:
            if x > 0:
                real = copysign(INF, math.cos(y))
                imag = copysign(INF, math.sin(y))
            else:
                real = copysign(INF, math.cos(y))
                imag = -copysign(INF, math.sin(y))
            r = (real, imag)
        else:
            r = cosh_special_values[special_type(x)][special_type(y)]

        # need to raise ValueError if y is +/- infinity and x is not
        # a NaN
        if isinf(y) and not isnan(x):
            raise ValueError("math domain error")
        return r

    if fabs(x) > CM_LOG_LARGE_DOUBLE:
        # deal correctly with cases where cosh(x) overflows but
        # cosh(z) does not.
        x_minus_one = x - copysign(1., x)
        real = math.cos(y) * math.cosh(x_minus_one) * math.e
        imag = math.sin(y) * math.sinh(x_minus_one) * math.e
    else:
        real = math.cos(y) * math.cosh(x)
        imag = math.sin(y) * math.sinh(x)
    if isinf(real) or isinf(imag):
        raise OverflowError("math range error")
    return real, imag
Exemple #2
0
def c_rect(r, phi):
    if not isfinite(r) or not isfinite(phi):
        # if r is +/-infinity and phi is finite but nonzero then
        # result is (+-INF +-INF i), but we need to compute cos(phi)
        # and sin(phi) to figure out the signs.
        if isinf(r) and isfinite(phi) and phi != 0.:
            if r > 0:
                real = copysign(INF, math.cos(phi))
                imag = copysign(INF, math.sin(phi))
            else:
                real = -copysign(INF, math.cos(phi))
                imag = -copysign(INF, math.sin(phi))
            z = (real, imag)
        else:
            z = rect_special_values[special_type(r)][special_type(phi)]

        # need to raise ValueError if r is a nonzero number and phi
        # is infinite
        if r != 0. and not isnan(r) and isinf(phi):
            raise ValueError("math domain error")
        return z

    real = r * math.cos(phi)
    imag = r * math.sin(phi)
    return real, imag
Exemple #3
0
def c_sinh(x, y):
    # special treatment for sinh(+/-inf + iy) if y is finite and nonzero
    if not isfinite(x) or not isfinite(y):
        if isinf(x) and isfinite(y) and y != 0.:
            if x > 0:
                real = copysign(INF, math.cos(y))
                imag = copysign(INF, math.sin(y))
            else:
                real = -copysign(INF, math.cos(y))
                imag = copysign(INF, math.sin(y))
            r = (real, imag)
        else:
            r = sinh_special_values[special_type(x)][special_type(y)]

        # need to raise ValueError if y is +/- infinity and x is not
        # a NaN
        if isinf(y) and not isnan(x):
            raise ValueError("math domain error")
        return r

    if fabs(x) > CM_LOG_LARGE_DOUBLE:
        x_minus_one = x - copysign(1., x)
        real = math.cos(y) * math.sinh(x_minus_one) * math.e
        imag = math.sin(y) * math.cosh(x_minus_one) * math.e
    else:
        real = math.cos(y) * math.sinh(x)
        imag = math.sin(y) * math.cosh(x)
    if isinf(real) or isinf(imag):
        raise OverflowError("math range error")
    return real, imag
Exemple #4
0
def c_atanh(x, y):
    if not isfinite(x) or not isfinite(y):
        return atanh_special_values[special_type(x)][special_type(y)]

    # Reduce to case where x >= 0., using atanh(z) = -atanh(-z).
    if x < 0.:
        return c_neg(*c_atanh(*c_neg(x, y)))

    ay = fabs(y)
    if x > CM_SQRT_LARGE_DOUBLE or ay > CM_SQRT_LARGE_DOUBLE:
        # if abs(z) is large then we use the approximation
        # atanh(z) ~ 1/z +/- i*pi/2 (+/- depending on the sign
        # of y
        h = math.hypot(x/2., y/2.)   # safe from overflow
        real = x/4./h/h
        # the two negations in the next line cancel each other out
        # except when working with unsigned zeros: they're there to
        # ensure that the branch cut has the correct continuity on
        # systems that don't support signed zeros
        imag = -copysign(math.pi/2., -y)
    elif x == 1. and ay < CM_SQRT_DBL_MIN:
        # C99 standard says:  atanh(1+/-0.) should be inf +/- 0i
        if ay == 0.:
            raise ValueError("math domain error")
            #real = INF
            #imag = y
        else:
            real = -math.log(math.sqrt(ay)/math.sqrt(math.hypot(ay, 2.)))
            imag = copysign(math.atan2(2., -ay) / 2, y)
    else:
        real = log1p(4.*x/((1-x)*(1-x) + ay*ay))/4.
        imag = -math.atan2(-2.*y, (1-x)*(1+x) - ay*ay) / 2.
    return (real, imag)
Exemple #5
0
def c_exp(x, y):
    if not isfinite(x) or not isfinite(y):
        if isinf(x) and isfinite(y) and y != 0.:
            if x > 0:
                real = copysign(INF, math.cos(y))
                imag = copysign(INF, math.sin(y))
            else:
                real = copysign(0., math.cos(y))
                imag = copysign(0., math.sin(y))
            r = (real, imag)
        else:
            r = exp_special_values[special_type(x)][special_type(y)]

        # need to raise ValueError if y is +/- infinity and x is not
        # a NaN and not -infinity
        if isinf(y) and (isfinite(x) or (isinf(x) and x > 0)):
            raise ValueError("math domain error")
        return r

    if x > CM_LOG_LARGE_DOUBLE:
        l = math.exp(x-1.)
        real = l * math.cos(y) * math.e
        imag = l * math.sin(y) * math.e
    else:
        l = math.exp(x)
        real = l * math.cos(y)
        imag = l * math.sin(y)
    if isinf(real) or isinf(imag):
        raise OverflowError("math range error")
    return real, imag
Exemple #6
0
 def _make_key(self, obj):
     # see the tests 'test_zeros_not_mixed*' in ../test/test_compiler.py
     space = self.space
     w_type = space.type(obj)
     if space.is_w(w_type, space.w_float):
         val = space.float_w(obj)
         if val == 0.0 and rfloat.copysign(1.0, val) < 0:
             w_key = space.newtuple([obj, space.w_float, space.w_None])
         else:
             w_key = space.newtuple([obj, space.w_float])
     elif space.is_w(w_type, space.w_complex):
         w_real = space.getattr(obj, space.wrap("real"))
         w_imag = space.getattr(obj, space.wrap("imag"))
         real = space.float_w(w_real)
         imag = space.float_w(w_imag)
         real_negzero = real == 0.0 and rfloat.copysign(1.0, real) < 0
         imag_negzero = imag == 0.0 and rfloat.copysign(1.0, imag) < 0
         if real_negzero and imag_negzero:
             tup = [obj, space.w_complex, space.w_None, space.w_None, space.w_None]
         elif imag_negzero:
             tup = [obj, space.w_complex, space.w_None, space.w_None]
         elif real_negzero:
             tup = [obj, space.w_complex, space.w_None]
         else:
             tup = [obj, space.w_complex]
         w_key = space.newtuple(tup)
     elif space.is_w(w_type, space.w_tuple):
         result_w = [obj, w_type]
         for w_item in space.fixedview(obj):
             result_w.append(self._make_key(w_item))
         w_key = space.newtuple(result_w[:])
     else:
         w_key = space.newtuple([obj, w_type])
     return w_key
Exemple #7
0
def test_nan_and_special_values():
    from rpython.rlib.rfloat import isnan, isinf, isfinite, copysign
    inf = 1e300 * 1e300
    assert isinf(inf)
    nan = inf/inf
    assert isnan(nan)

    for value, checker in [
            (inf,   lambda x: isinf(x) and x > 0.0),
            (-inf,  lambda x: isinf(x) and x < 0.0),
            (nan,   isnan),
            (42.0,  isfinite),
            (0.0,   lambda x: not x and copysign(1., x) == 1.),
            (-0.0,  lambda x: not x and copysign(1., x) == -1.),
            ]:
        def f():
            return value
        f1 = compile(f, [])
        res = f1()
        assert checker(res)

        l = [value]
        def g(x):
            return l[x]
        g2 = compile(g, [int])
        res = g2(0)
        assert checker(res)

        l2 = [(-value, -value), (value, value)]
        def h(x):
            return l2[x][1]
        h3 = compile(h, [int])
        res = h3(1)
        assert checker(res)
Exemple #8
0
 def descr_str(self, space):
     if self.realval == 0 and copysign(1., self.realval) == 1.:
         return space.wrap(str_format(self.imagval) + 'j')
     sign = (copysign(1., self.imagval) == 1. or
             isnan(self.imagval)) and '+' or ''
     return space.wrap('(' + str_format(self.realval)
                       + sign + str_format(self.imagval) + 'j)')
Exemple #9
0
 def __eq__(self, other):
     if (type(self) is SomeFloat and type(other) is SomeFloat and
         self.is_constant() and other.is_constant()):
         from rpython.rlib.rfloat import isnan, copysign
         # NaN unpleasantness.
         if isnan(self.const) and isnan(other.const):
             return True
         # 0.0 vs -0.0 unpleasantness.
         if not self.const and not other.const:
             return copysign(1., self.const) == copysign(1., other.const)
         #
     return super(SomeFloat, self).__eq__(other)
Exemple #10
0
def c_sqrt(x, y):
    '''
    Method: use symmetries to reduce to the case when x = z.real and y
    = z.imag are nonnegative.  Then the real part of the result is
    given by
    
      s = sqrt((x + hypot(x, y))/2)
    
    and the imaginary part is
    
      d = (y/2)/s
    
    If either x or y is very large then there's a risk of overflow in
    computation of the expression x + hypot(x, y).  We can avoid this
    by rewriting the formula for s as:
    
      s = 2*sqrt(x/8 + hypot(x/8, y/8))
    
    This costs us two extra multiplications/divisions, but avoids the
    overhead of checking for x and y large.
    
    If both x and y are subnormal then hypot(x, y) may also be
    subnormal, so will lack full precision.  We solve this by rescaling
    x and y by a sufficiently large power of 2 to ensure that x and y
    are normal.
    '''
    if not isfinite(x) or not isfinite(y):
        return sqrt_special_values[special_type(x)][special_type(y)]

    if x == 0. and y == 0.:
        return (0., y)

    ax = fabs(x)
    ay = fabs(y)

    if ax < DBL_MIN and ay < DBL_MIN and (ax > 0. or ay > 0.):
        # here we catch cases where hypot(ax, ay) is subnormal
        ax = math.ldexp(ax, CM_SCALE_UP)
        ay1= math.ldexp(ay, CM_SCALE_UP)
        s = math.ldexp(math.sqrt(ax + math.hypot(ax, ay1)),
                       CM_SCALE_DOWN)
    else:
        ax /= 8.
        s = 2.*math.sqrt(ax + math.hypot(ax, ay/8.))

    d = ay/(2.*s)

    if x >= 0.:
        return (s, copysign(d, y))
    else:
        return (d, copysign(s, y))
Exemple #11
0
def rAlmostEqual(a, b, rel_err=2e-15, abs_err=5e-323, msg=''):
    """Fail if the two floating-point numbers are not almost equal.

    Determine whether floating-point values a and b are equal to within
    a (small) rounding error.  The default values for rel_err and
    abs_err are chosen to be suitable for platforms where a float is
    represented by an IEEE 754 double.  They allow an error of between
    9 and 19 ulps.
    """

    # special values testing
    if isnan(a):
        if isnan(b):
            return True,''
        raise AssertionError(msg + '%r should be nan' % (b,))

    if isinf(a):
        if a == b:
            return True,''
        raise AssertionError(msg + 'finite result where infinity expected: '+ \
                          'expected %r, got %r' % (a, b))

    # if both a and b are zero, check whether they have the same sign
    # (in theory there are examples where it would be legitimate for a
    # and b to have opposite signs; in practice these hardly ever
    # occur).
    if not a and not b:
        # only check it if we are running on top of CPython >= 2.6
        if sys.version_info >= (2, 6) and copysign(1., a) != copysign(1., b):
            raise AssertionError( msg + \
                    'zero has wrong sign: expected %r, got %r' % (a, b))

    # if a-b overflows, or b is infinite, return False.  Again, in
    # theory there are examples where a is within a few ulps of the
    # max representable float, and then b could legitimately be
    # infinite.  In practice these examples are rare.
    try:
        absolute_error = abs(b-a)
    except OverflowError:
        pass
    else:
        # test passes if either the absolute error or the relative
        # error is sufficiently small.  The defaults amount to an
        # error of between 9 ulps and 19 ulps on an IEEE-754 compliant
        # machine.
        if absolute_error <= max(abs_err, rel_err * abs(a)):
            return True,''
    raise AssertionError(msg + \
            '%r and %r are not sufficiently close, %g > %g' %\
            (a, b, absolute_error, max(abs_err, rel_err*abs(a))))
Exemple #12
0
def rAlmostEqual(a, b, rel_err=2e-15, abs_err=5e-323, msg=''):
    """Fail if the two floating-point numbers are not almost equal.

    Determine whether floating-point values a and b are equal to within
    a (small) rounding error.  The default values for rel_err and
    abs_err are chosen to be suitable for platforms where a float is
    represented by an IEEE 754 double.  They allow an error of between
    9 and 19 ulps.
    """

    # special values testing
    if isnan(a):
        if isnan(b):
            return True, ''
        raise AssertionError(msg + '%r should be nan' % (b, ))

    if isinf(a):
        if a == b:
            return True, ''
        raise AssertionError(msg + 'finite result where infinity expected: '+ \
                          'expected %r, got %r' % (a, b))

    # if both a and b are zero, check whether they have the same sign
    # (in theory there are examples where it would be legitimate for a
    # and b to have opposite signs; in practice these hardly ever
    # occur).
    if not a and not b:
        # only check it if we are running on top of CPython >= 2.6
        if sys.version_info >= (2, 6) and copysign(1., a) != copysign(1., b):
            raise AssertionError( msg + \
                    'zero has wrong sign: expected %r, got %r' % (a, b))

    # if a-b overflows, or b is infinite, return False.  Again, in
    # theory there are examples where a is within a few ulps of the
    # max representable float, and then b could legitimately be
    # infinite.  In practice these examples are rare.
    try:
        absolute_error = abs(b - a)
    except OverflowError:
        pass
    else:
        # test passes if either the absolute error or the relative
        # error is sufficiently small.  The defaults amount to an
        # error of between 9 ulps and 19 ulps on an IEEE-754 compliant
        # machine.
        if absolute_error <= max(abs_err, rel_err * abs(a)):
            return True, ''
    raise AssertionError(msg + \
            '%r and %r are not sufficiently close, %g > %g' %\
            (a, b, absolute_error, max(abs_err, rel_err*abs(a))))
Exemple #13
0
def c_sqrt(x, y):
    '''
    Method: use symmetries to reduce to the case when x = z.real and y
    = z.imag are nonnegative.  Then the real part of the result is
    given by
    
      s = sqrt((x + hypot(x, y))/2)
    
    and the imaginary part is
    
      d = (y/2)/s
    
    If either x or y is very large then there's a risk of overflow in
    computation of the expression x + hypot(x, y).  We can avoid this
    by rewriting the formula for s as:
    
      s = 2*sqrt(x/8 + hypot(x/8, y/8))
    
    This costs us two extra multiplications/divisions, but avoids the
    overhead of checking for x and y large.
    
    If both x and y are subnormal then hypot(x, y) may also be
    subnormal, so will lack full precision.  We solve this by rescaling
    x and y by a sufficiently large power of 2 to ensure that x and y
    are normal.
    '''
    if not isfinite(x) or not isfinite(y):
        return sqrt_special_values[special_type(x)][special_type(y)]

    if x == 0. and y == 0.:
        return (0., y)

    ax = fabs(x)
    ay = fabs(y)

    if ax < DBL_MIN and ay < DBL_MIN and (ax > 0. or ay > 0.):
        # here we catch cases where hypot(ax, ay) is subnormal
        ax = math.ldexp(ax, CM_SCALE_UP)
        ay1 = math.ldexp(ay, CM_SCALE_UP)
        s = math.ldexp(math.sqrt(ax + math.hypot(ax, ay1)), CM_SCALE_DOWN)
    else:
        ax /= 8.
        s = 2. * math.sqrt(ax + math.hypot(ax, ay / 8.))

    d = ay / (2. * s)

    if x >= 0.:
        return (s, copysign(d, y))
    else:
        return (d, copysign(s, y))
Exemple #14
0
def float_pack80(x, size):
    """Convert a Python float or longfloat x into two 64-bit unsigned integers
    with 80 bit extended representation."""
    x = float(x)  # longfloat not really supported
    if size == 10 or size == 12 or size == 16:
        MIN_EXP = -16381
        MAX_EXP = 16384
        MANT_DIG = 64
        BITS = 80
    else:
        raise ValueError("invalid size value")

    sign = rfloat.copysign(1.0, x) < 0.0
    if rfloat.isinf(x):
        mant = r_ulonglong(0)
        exp = MAX_EXP - MIN_EXP + 2
    elif rfloat.isnan(x):  # rfloat.isnan(x):
        asint = cast(ULONGLONG, float2longlong(x))
        mant = asint & ((r_ulonglong(1) << 51) - 1)
        if mant == 0:
            mant = r_ulonglong(1) << (MANT_DIG - 1) - 1
        sign = asint < 0
        exp = MAX_EXP - MIN_EXP + 2
    elif x == 0.0:
        mant = r_ulonglong(0)
        exp = 0
    else:
        m, e = math.frexp(abs(x))  # abs(x) == m * 2**e
        exp = e - (MIN_EXP - 1)
        if exp > 0:
            # Normal case. Avoid uint64 overflow by using MANT_DIG-1
            mant = round_to_nearest(m * (r_ulonglong(1) << MANT_DIG - 1))
        else:
            # Subnormal case.
            if exp + MANT_DIG - 1 >= 0:
                mant = round_to_nearest(m *
                                        (r_ulonglong(1) << exp + MANT_DIG - 1))
            else:
                mant = r_ulonglong(0)
            exp = 0

        # Special case: rounding produced a MANT_DIG-bit mantissa.
        if mant == r_ulonglong(1) << MANT_DIG - 1:
            mant = r_ulonglong(0)
            exp += 1

        # Raise on overflow (in some circumstances, may want to return
        # infinity instead).
        if exp >= MAX_EXP - MIN_EXP + 2:
            raise OverflowError("float too large to pack in this format")

        mant = mant << 1
    # check constraints
    if not objectmodel.we_are_translated():
        assert 0 <= mant <= (1 << MANT_DIG) - 1
        assert 0 <= exp <= MAX_EXP - MIN_EXP + 2
        assert 0 <= sign <= 1
    exp = r_ulonglong(exp)
    sign = r_ulonglong(sign)
    return (mant, (sign << BITS - MANT_DIG - 1) | exp)
Exemple #15
0
 def descr_hex(self, space):
     TOHEX_NBITS = rfloat.DBL_MANT_DIG + 3 - (rfloat.DBL_MANT_DIG + 2) % 4
     value = self.floatval
     if not isfinite(value):
         return self.descr_str(space)
     if value == 0.0:
         if copysign(1., value) == -1.:
             return space.wrap("-0x0.0p+0")
         else:
             return space.wrap("0x0.0p+0")
     mant, exp = math.frexp(value)
     shift = 1 - max(rfloat.DBL_MIN_EXP - exp, 0)
     mant = math.ldexp(mant, shift)
     mant = abs(mant)
     exp -= shift
     result = ['\0'] * ((TOHEX_NBITS - 1) // 4 + 2)
     result[0] = _char_from_hex(int(mant))
     mant -= int(mant)
     result[1] = "."
     for i in range((TOHEX_NBITS - 1) // 4):
         mant *= 16.0
         result[i + 2] = _char_from_hex(int(mant))
         mant -= int(mant)
     if exp < 0:
         sign = "-"
     else:
         sign = "+"
     exp = abs(exp)
     s = ''.join(result)
     if value < 0.0:
         return space.wrap("-0x%sp%s%d" % (s, sign, exp))
     else:
         return space.wrap("0x%sp%s%d" % (s, sign, exp))
Exemple #16
0
def float_pack80(x, size):
    """Convert a Python float or longfloat x into two 64-bit unsigned integers
    with 80 bit extended representation."""
    x = float(x)  # longfloat not really supported
    if size == 10 or size == 12 or size == 16:
        MIN_EXP = -16381
        MAX_EXP = 16384
        MANT_DIG = 64
        BITS = 80
    else:
        raise ValueError("invalid size value")

    sign = rfloat.copysign(1.0, x) < 0.0
    if rfloat.isinf(x):
        mant = r_ulonglong(0)
        exp = MAX_EXP - MIN_EXP + 2
    elif rfloat.isnan(x):  # rfloat.isnan(x):
        asint = cast(ULONGLONG, float2longlong(x))
        mant = asint & ((r_ulonglong(1) << 51) - 1)
        if mant == 0:
            mant = r_ulonglong(1) << (MANT_DIG - 1) - 1
        sign = asint < 0
        exp = MAX_EXP - MIN_EXP + 2
    elif x == 0.0:
        mant = r_ulonglong(0)
        exp = 0
    else:
        m, e = math.frexp(abs(x))  # abs(x) == m * 2**e
        exp = e - (MIN_EXP - 1)
        if exp > 0:
            # Normal case. Avoid uint64 overflow by using MANT_DIG-1
            mant = round_to_nearest(m * (r_ulonglong(1) << MANT_DIG - 1))
        else:
            # Subnormal case.
            if exp + MANT_DIG - 1 >= 0:
                mant = round_to_nearest(m * (r_ulonglong(1) << exp + MANT_DIG - 1))
            else:
                mant = r_ulonglong(0)
            exp = 0

        # Special case: rounding produced a MANT_DIG-bit mantissa.
        if mant == r_ulonglong(1) << MANT_DIG - 1:
            mant = r_ulonglong(0)
            exp += 1

        # Raise on overflow (in some circumstances, may want to return
        # infinity instead).
        if exp >= MAX_EXP - MIN_EXP + 2:
            raise OverflowError("float too large to pack in this format")

        mant = mant << 1
    # check constraints
    if not objectmodel.we_are_translated():
        assert 0 <= mant <= (1 << MANT_DIG) - 1
        assert 0 <= exp <= MAX_EXP - MIN_EXP + 2
        assert 0 <= sign <= 1
    exp = r_ulonglong(exp)
    sign = r_ulonglong(sign)
    return (mant, (sign << BITS - MANT_DIG - 1) | exp)
Exemple #17
0
def test_special_values():
    from rpython.rlib.special_value import sqrt_special_values
    assert len(sqrt_special_values) == 7
    assert len(sqrt_special_values[4]) == 7
    assert isinstance(sqrt_special_values[5][1], tuple)
    assert sqrt_special_values[5][1][0] == 1e200 * 1e200
    assert sqrt_special_values[5][1][1] == -0.
    assert copysign(1., sqrt_special_values[5][1][1]) == -1.
Exemple #18
0
def float_mod(a, b):
    y = b.number
    mod = math_fmod(a.number, y)  # Follows pypy implementation.
    if mod:  # I'm not sure why remainder and denominator
        if (y < 0.0) != (mod < 0.0):  # must have the same sign.
            mod += y
    else:
        mod = copysign(0.0, y)
    return Float(mod)
Exemple #19
0
def c_asinh(x, y):
    if not isfinite(x) or not isfinite(y):
        return asinh_special_values[special_type(x)][special_type(y)]

    if fabs(x) > CM_LARGE_DOUBLE or fabs(y) > CM_LARGE_DOUBLE:
        if y >= 0.:
            real = copysign(math.log(math.hypot(x/2., y/2.)) +
                            M_LN2*2., x)
        else:
            real = -copysign(math.log(math.hypot(x/2., y/2.)) +
                             M_LN2*2., -x)
        imag = math.atan2(y, fabs(x))
    else:
        s1x, s1y = c_sqrt(1.+y, -x)
        s2x, s2y = c_sqrt(1.-y, x)
        real = asinh(s1x*s2y - s2x*s1y)
        imag = math.atan2(y, s1x*s2x - s1y*s2y)
    return (real, imag)
Exemple #20
0
def c_asinh(x, y):
    if not isfinite(x) or not isfinite(y):
        return asinh_special_values[special_type(x)][special_type(y)]

    if fabs(x) > CM_LARGE_DOUBLE or fabs(y) > CM_LARGE_DOUBLE:
        if y >= 0.:
            real = copysign(
                math.log(math.hypot(x / 2., y / 2.)) + M_LN2 * 2., x)
        else:
            real = -copysign(
                math.log(math.hypot(x / 2., y / 2.)) + M_LN2 * 2., -x)
        imag = math.atan2(y, fabs(x))
    else:
        s1x, s1y = c_sqrt(1. + y, -x)
        s2x, s2y = c_sqrt(1. - y, x)
        real = asinh(s1x * s2y - s2x * s1y)
        imag = math.atan2(y, s1x * s2x - s1y * s2y)
    return (real, imag)
Exemple #21
0
 def method_atanh(self, space, value):
     try:
         res = math.atanh(value)
     except ValueError:
         if value == 1.0 or value == -1.0:
             # produce an infinity with the right sign
             res = rfloat.copysign(rfloat.INFINITY, value)
         else:
             raise space.error(space.getclassfor(W_DomainError), 'Numerical argument is out of domain - "atanh"')
     return space.newfloat(res)
Exemple #22
0
def c_acos(x, y):
    if not isfinite(x) or not isfinite(y):
        return acos_special_values[special_type(x)][special_type(y)]

    if fabs(x) > CM_LARGE_DOUBLE or fabs(y) > CM_LARGE_DOUBLE:
        # avoid unnecessary overflow for large arguments
        real = math.atan2(fabs(y), x)
        # split into cases to make sure that the branch cut has the
        # correct continuity on systems with unsigned zeros
        if x < 0.:
            imag = -copysign(math.log(math.hypot(x/2., y/2.)) +
                             M_LN2*2., y)
        else:
            imag = copysign(math.log(math.hypot(x/2., y/2.)) +
                            M_LN2*2., -y)
    else:
        s1x, s1y = c_sqrt(1.-x, -y)
        s2x, s2y = c_sqrt(1.+x, y)
        real = 2.*math.atan2(s1x, s2x)
        imag = asinh(s2x*s1y - s2y*s1x)
    return (real, imag)
Exemple #23
0
 def method_fdiv(self, space, w_other):
     if space.is_kind_of(w_other, space.w_fixnum):
         other = space.int_w(w_other)
         try:
             res = float(self.intvalue) / float(other)
         except ZeroDivisionError:
             return space.newfloat(rfloat.copysign(rfloat.INFINITY, float(self.intvalue)))
         else:
             return space.newfloat(res)
     elif space.is_kind_of(w_other, space.w_bignum):
         return space.send(space.newbigint_fromint(self.intvalue), "fdiv", [w_other])
     elif space.is_kind_of(w_other, space.w_float):
         other = space.float_w(w_other)
         try:
             res = float(self.intvalue) / other
         except ZeroDivisionError:
             return space.newfloat(rfloat.copysign(rfloat.INFINITY, float(self.intvalue)))
         else:
             return space.newfloat(res)
     else:
         return W_NumericObject.retry_binop_coercing(space, self, w_other, "fdiv")
Exemple #24
0
 def method_atanh(self, space, value):
     try:
         res = math.atanh(value)
     except ValueError:
         if value == 1.0 or value == -1.0:
             # produce an infinity with the right sign
             res = rfloat.copysign(rfloat.INFINITY, value)
         else:
             raise space.error(
                 space.getclassfor(W_DomainError),
                 'Numerical argument is out of domain - "atanh"')
     return space.newfloat(res)
Exemple #25
0
 def method_fdiv(self, space, w_other):
     if space.is_kind_of(w_other, space.w_fixnum):
         other = space.int_w(w_other)
         try:
             res = float(self.intvalue) / float(other)
         except ZeroDivisionError:
             return space.newfloat(rfloat.copysign(rfloat.INFINITY, float(self.intvalue)))
         else:
             return space.newfloat(res)
     elif space.is_kind_of(w_other, space.w_bignum):
         return space.send(space.newbigint_fromint(self.intvalue), "fdiv", [w_other])
     elif space.is_kind_of(w_other, space.w_float):
         other = space.float_w(w_other)
         try:
             res = float(self.intvalue) / other
         except ZeroDivisionError:
             return space.newfloat(rfloat.copysign(rfloat.INFINITY, float(self.intvalue)))
         else:
             return space.newfloat(res)
     else:
         return W_NumericObject.retry_binop_coercing(space, self, w_other, "fdiv")
Exemple #26
0
def c_acos(x, y):
    if not isfinite(x) or not isfinite(y):
        return acos_special_values[special_type(x)][special_type(y)]

    if fabs(x) > CM_LARGE_DOUBLE or fabs(y) > CM_LARGE_DOUBLE:
        # avoid unnecessary overflow for large arguments
        real = math.atan2(fabs(y), x)
        # split into cases to make sure that the branch cut has the
        # correct continuity on systems with unsigned zeros
        if x < 0.:
            imag = -copysign(
                math.log(math.hypot(x / 2., y / 2.)) + M_LN2 * 2., y)
        else:
            imag = copysign(
                math.log(math.hypot(x / 2., y / 2.)) + M_LN2 * 2., -y)
    else:
        s1x, s1y = c_sqrt(1. - x, -y)
        s2x, s2y = c_sqrt(1. + x, y)
        real = 2. * math.atan2(s1x, s2x)
        imag = asinh(s2x * s1y - s2y * s1x)
    return (real, imag)
Exemple #27
0
 def method_gamma(self, space, value):
     try:
         res = rfloat.gamma(value)
     except ValueError:
         if value == 0.0:
             # produce an infinity with the right sign
             res = rfloat.copysign(rfloat.INFINITY, value)
         else:
             raise space.error(space.getclassfor(W_DomainError), 'Numerical argument is out of domain - "gamma"')
     except OverflowError:
         res = rfloat.INFINITY
     return space.newfloat(res)
Exemple #28
0
def c_tanh(x, y):
    # Formula:
    #
    #   tanh(x+iy) = (tanh(x)(1+tan(y)^2) + i tan(y)(1-tanh(x))^2) /
    #   (1+tan(y)^2 tanh(x)^2)
    #
    #   To avoid excessive roundoff error, 1-tanh(x)^2 is better computed
    #   as 1/cosh(x)^2.  When abs(x) is large, we approximate 1-tanh(x)^2
    #   by 4 exp(-2*x) instead, to avoid possible overflow in the
    #   computation of cosh(x).

    if not isfinite(x) or not isfinite(y):
        if isinf(x) and isfinite(y) and y != 0.:
            if x > 0:
                real = 1.0        # vv XXX why is the 2. there?
                imag = copysign(0., 2. * math.sin(y) * math.cos(y))
            else:
                real = -1.0
                imag = copysign(0., 2. * math.sin(y) * math.cos(y))
            r = (real, imag)
        else:
            r = tanh_special_values[special_type(x)][special_type(y)]

        # need to raise ValueError if y is +/-infinity and x is finite
        if isinf(y) and isfinite(x):
            raise ValueError("math domain error")
        return r

    if fabs(x) > CM_LOG_LARGE_DOUBLE:
        real = copysign(1., x)
        imag = 4. * math.sin(y) * math.cos(y) * math.exp(-2.*fabs(x))
    else:
        tx = math.tanh(x)
        ty = math.tan(y)
        cx = 1. / math.cosh(x)
        txty = tx * ty
        denom = 1. + txty * txty
        real = tx * (1. + ty*ty) / denom
        imag = ((ty / denom) * cx) * cx
    return real, imag
Exemple #29
0
def test_nan_and_special_values():
    from rpython.rlib.rfloat import isnan, isinf, isfinite, copysign
    inf = 1e300 * 1e300
    assert isinf(inf)
    nan = inf / inf
    assert isnan(nan)

    for value, checker in [
        (inf, lambda x: isinf(x) and x > 0.0),
        (-inf, lambda x: isinf(x) and x < 0.0),
        (nan, isnan),
        (42.0, isfinite),
        (0.0, lambda x: not x and copysign(1., x) == 1.),
        (-0.0, lambda x: not x and copysign(1., x) == -1.),
    ]:

        def f():
            return value

        f1 = compile(f, [])
        res = f1()
        assert checker(res)

        l = [value]

        def g(x):
            return l[x]

        g2 = compile(g, [int])
        res = g2(0)
        assert checker(res)

        l2 = [(-value, -value), (value, value)]

        def h(x):
            return l2[x][1]

        h3 = compile(h, [int])
        res = h3(1)
        assert checker(res)
Exemple #30
0
def c_tanh(x, y):
    # Formula:
    #
    #   tanh(x+iy) = (tanh(x)(1+tan(y)^2) + i tan(y)(1-tanh(x))^2) /
    #   (1+tan(y)^2 tanh(x)^2)
    #
    #   To avoid excessive roundoff error, 1-tanh(x)^2 is better computed
    #   as 1/cosh(x)^2.  When abs(x) is large, we approximate 1-tanh(x)^2
    #   by 4 exp(-2*x) instead, to avoid possible overflow in the
    #   computation of cosh(x).

    if not isfinite(x) or not isfinite(y):
        if isinf(x) and isfinite(y) and y != 0.:
            if x > 0:
                real = 1.0  # vv XXX why is the 2. there?
                imag = copysign(0., 2. * math.sin(y) * math.cos(y))
            else:
                real = -1.0
                imag = copysign(0., 2. * math.sin(y) * math.cos(y))
            r = (real, imag)
        else:
            r = tanh_special_values[special_type(x)][special_type(y)]

        # need to raise ValueError if y is +/-infinity and x is finite
        if isinf(y) and isfinite(x):
            raise ValueError("math domain error")
        return r

    if fabs(x) > CM_LOG_LARGE_DOUBLE:
        real = copysign(1., x)
        imag = 4. * math.sin(y) * math.cos(y) * math.exp(-2. * fabs(x))
    else:
        tx = math.tanh(x)
        ty = math.tan(y)
        cx = 1. / math.cosh(x)
        txty = tx * ty
        denom = 1. + txty * txty
        real = tx * (1. + ty * ty) / denom
        imag = ((ty / denom) * cx) * cx
    return real, imag
Exemple #31
0
 def _make_key(self, obj):
     # see the tests 'test_zeros_not_mixed*' in ../test/test_compiler.py
     space = self.space
     w_type = space.type(obj)
     if space.is_w(w_type, space.w_float):
         val = space.float_w(obj)
         if val == 0.0 and rfloat.copysign(1., val) < 0:
             w_key = space.newtuple([obj, space.w_float, space.w_None])
         else:
             w_key = space.newtuple([obj, space.w_float])
     elif space.is_w(w_type, space.w_complex):
         w_real = space.getattr(obj, space.newtext("real"))
         w_imag = space.getattr(obj, space.newtext("imag"))
         real = space.float_w(w_real)
         imag = space.float_w(w_imag)
         real_negzero = (real == 0.0 and rfloat.copysign(1., real) < 0)
         imag_negzero = (imag == 0.0 and rfloat.copysign(1., imag) < 0)
         if real_negzero and imag_negzero:
             tup = [
                 obj, space.w_complex, space.w_None, space.w_None,
                 space.w_None
             ]
         elif imag_negzero:
             tup = [obj, space.w_complex, space.w_None, space.w_None]
         elif real_negzero:
             tup = [obj, space.w_complex, space.w_None]
         else:
             tup = [obj, space.w_complex]
         w_key = space.newtuple(tup)
     elif space.is_w(w_type, space.w_tuple):
         result_w = [obj, w_type]
         for w_item in space.fixedview(obj):
             result_w.append(self._make_key(w_item))
         w_key = space.newtuple(result_w[:])
     elif isinstance(obj, PyCode):
         w_key = space.newtuple([obj, w_type, space.id(obj)])
     else:
         w_key = space.newtuple([obj, w_type])
     return w_key
Exemple #32
0
 def method_gamma(self, space, value):
     try:
         res = rfloat.gamma(value)
     except ValueError:
         if value == 0.0:
             # produce an infinity with the right sign
             res = rfloat.copysign(rfloat.INFINITY, value)
         else:
             raise space.error(
                 space.getclassfor(W_DomainError),
                 'Numerical argument is out of domain - "gamma"')
     except OverflowError:
         res = rfloat.INFINITY
     return space.newfloat(res)
Exemple #33
0
 def __init__(self, value):
     self.value = value  # a concrete value
     # try to be smart about constant mutable or immutable values
     key = type(self.value), self.value  # to avoid confusing e.g. 0 and 0.0
     #
     # we also have to avoid confusing 0.0 and -0.0 (needed e.g. for
     # translating the cmath module)
     if key[0] is float and not self.value:
         from rpython.rlib.rfloat import copysign
         if copysign(1., self.value) == -1.:  # -0.0
             key = (float, "-0.0")
     #
     try:
         hash(key)
     except TypeError:
         key = id(self.value)
     self.key = key
Exemple #34
0
 def __init__(self, value):
     self.value = value     # a concrete value
     # try to be smart about constant mutable or immutable values
     key = type(self.value), self.value  # to avoid confusing e.g. 0 and 0.0
     #
     # we also have to avoid confusing 0.0 and -0.0 (needed e.g. for
     # translating the cmath module)
     if key[0] is float and not self.value:
         from rpython.rlib.rfloat import copysign
         if copysign(1., self.value) == -1.:    # -0.0
             key = (float, "-0.0")
     #
     try:
         hash(key)
     except TypeError:
         key = id(self.value)
     self.key = key
Exemple #35
0
def special_type(d):
    if isnan(d):
        return ST_NAN
    elif isinf(d):
        if d > 0.0:
            return ST_PINF
        else:
            return ST_NINF
    else:
        if d != 0.0:
            if d > 0.0:
                return ST_POS
            else:
                return ST_NEG
        else:
            if copysign(1., d) == 1.:
                return ST_PZERO
            else:
                return ST_NZERO
Exemple #36
0
def special_type(d):
    if isnan(d):
        return ST_NAN
    elif isinf(d):
        if d > 0.0:
            return ST_PINF
        else:
            return ST_NINF
    else:
        if d != 0.0:
            if d > 0.0:
                return ST_POS
            else:
                return ST_NEG
        else:
            if copysign(1., d) == 1.:
                return ST_PZERO
            else:
                return ST_NZERO
Exemple #37
0
 def test_power_complex(self):
     inf = float('inf')
     ninf = -float('inf')
     nan = float('nan')
     cmpl = complex
     from math import copysign
     from numpypy import power, array, complex128, complex64
     # note: in some settings (namely a x86-32 build without the JIT),
     # gcc optimizes the code in rlib.rcomplex.c_pow() to not truncate
     # the 10-byte values down to 8-byte values.  It ends up with more
     # imprecision than usual (hence 2e-13 instead of 2e-15).
     for c,rel_err in ((complex128, 2e-13), (complex64, 4e-7)):
         a = array([cmpl(-5., 0), cmpl(-5., -5.), cmpl(-5., 5.),
                    cmpl(0., -5.), cmpl(0., 0.), cmpl(0., 5.),
                    cmpl(-0., -5.), cmpl(-0., 0.), cmpl(-0., 5.),
                    cmpl(-0., -0.), cmpl(inf, 0.), cmpl(inf, 5.),
                    cmpl(inf, -0.), cmpl(ninf, 0.), cmpl(ninf, 5.),
                    cmpl(ninf, -0.), cmpl(ninf, inf), cmpl(inf, inf),
                    cmpl(ninf, ninf), cmpl(5., inf), cmpl(5., ninf),
                    cmpl(nan, 5.), cmpl(5., nan), cmpl(nan, nan),
                  ], dtype=c)
         for p in (3, -1, 10000, 2.3, -10000, 10+3j):
             b = power(a, p)
             for i in range(len(a)):
                 try:
                     r = self.c_pow((float(a[i].real), float(a[i].imag)),
                             (float(p.real), float(p.imag)))
                 except ZeroDivisionError:
                     r = (nan, nan)
                 except OverflowError:
                     r = (inf, -copysign(inf, a[i].imag))
                 except ValueError:
                     r = (nan, nan)
                 msg = 'result of %r(%r)**%r got %r expected %r\n ' % \
                         (c,a[i], p, b[i], r)
                 t1 = float(r[0])
                 t2 = float(b[i].real)
                 self.rAlmostEqual(t1, t2, rel_err=rel_err, msg=msg)
                 t1 = float(r[1])
                 t2 = float(b[i].imag)
                 self.rAlmostEqual(t1, t2, rel_err=rel_err, msg=msg)
Exemple #38
0
    def descr_mod(self, space, w_rhs):
        w_rhs = self._to_float(space, w_rhs)
        if w_rhs is None:
            return space.w_NotImplemented
        x = self.floatval
        y = w_rhs.floatval
        if y == 0.0:
            raise oefmt(space.w_ZeroDivisionError, "float modulo")
        mod = math_fmod(x, y)
        if mod:
            # ensure the remainder has the same sign as the denominator
            if (y < 0.0) != (mod < 0.0):
                mod += y
        else:
            # the remainder is zero, and in the presence of signed zeroes
            # fmod returns different results across platforms; ensure
            # it has the same sign as the denominator; we'd like to do
            # "mod = y * 0.0", but that may get optimized away
            mod = copysign(0.0, y)

        return W_FloatObject(mod)
Exemple #39
0
 def pack_float(space, packer, repetitions):
     if repetitions > len(packer.args_w) - packer.args_index:
         raise space.error(space.w_ArgumentError, "too few arguments")
     for i in xrange(packer.args_index, repetitions + packer.args_index):
         w_item = packer.args_w[i]
         if not (isinstance(w_item, W_FloatObject) or isinstance(w_item, W_FixnumObject)):
             raise space.error(space.w_TypeError,
                 "can't convert %s into Float" % space.obj_to_s(space.getclass(w_item))
             )
         doubleval = space.float_w(w_item)
         l = ["\0"] * size
         try:
             unsigned = float_pack(doubleval, size)
         except OverflowError:
             unsigned = float_pack(rfloat.copysign(rfloat.INFINITY, doubleval), size)
         for i in xrange(size):
             l[i] = chr((unsigned >> (i * 8)) & 0xff)
         if bigendian:
             l.reverse()
         packer.result.extend(l)
     packer.args_index += repetitions
Exemple #40
0
def mod__Float_Float(space, w_float1, w_float2):
    x = w_float1.floatval
    y = w_float2.floatval
    if y == 0.0:
        raise FailedToImplementArgs(space.w_ZeroDivisionError, space.wrap("float modulo"))
    try:
        mod = math.fmod(x, y)
    except ValueError:
        mod = rfloat.NAN
    else:
        if mod:
            # ensure the remainder has the same sign as the denominator
            if (y < 0.0) != (mod < 0.0):
                mod += y
        else:
            # the remainder is zero, and in the presence of signed zeroes
            # fmod returns different results across platforms; ensure
            # it has the same sign as the denominator; we'd like to do
            # "mod = y * 0.0", but that may get optimized away
            mod = copysign(0.0, y)

    return W_FloatObject(mod)
Exemple #41
0
 def pack_float(space, packer, repetitions):
     if repetitions > len(packer.args_w) - packer.args_index:
         raise space.error(space.w_ArgumentError, "too few arguments")
     for i in xrange(packer.args_index, repetitions + packer.args_index):
         w_item = packer.args_w[i]
         if not (isinstance(w_item, W_FloatObject)
                 or isinstance(w_item, W_FixnumObject)):
             raise space.error(
                 space.w_TypeError, "can't convert %s into Float" %
                 space.obj_to_s(space.getclass(w_item)))
         doubleval = space.float_w(w_item)
         l = ["\0"] * size
         try:
             unsigned = float_pack(doubleval, size)
         except OverflowError:
             unsigned = float_pack(
                 rfloat.copysign(rfloat.INFINITY, doubleval), size)
         for i in xrange(size):
             l[i] = chr((unsigned >> (i * 8)) & 0xff)
         if bigendian:
             l.reverse()
         packer.result.extend(l)
     packer.args_index += repetitions
Exemple #42
0
def c_phase(x, y):
    # Windows screws up atan2 for inf and nan, and alpha Tru64 5.1 doesn't
    # follow C99 for atan2(0., 0.).
    if isnan(x) or isnan(y):
        return NAN
    if isinf(y):
        if isinf(x):
            if copysign(1., x) == 1.:
                # atan2(+-inf, +inf) == +-pi/4
                return copysign(0.25 * math.pi, y)
            else:
                # atan2(+-inf, -inf) == +-pi*3/4
                return copysign(0.75 * math.pi, y)
        # atan2(+-inf, x) == +-pi/2 for finite x
        return copysign(0.5 * math.pi, y)
    if isinf(x) or y == 0.:
        if copysign(1., x) == 1.:
            # atan2(+-y, +inf) = atan2(+-0, +x) = +-0.
            return copysign(0., y)
        else:
            # atan2(+-y, -inf) = atan2(+-0., -x) = +-pi.
            return copysign(math.pi, y)
    return math.atan2(y, x)
Exemple #43
0
def c_phase(x, y):
    # Windows screws up atan2 for inf and nan, and alpha Tru64 5.1 doesn't
    # follow C99 for atan2(0., 0.).
    if isnan(x) or isnan(y):
        return NAN
    if isinf(y):
        if isinf(x):
            if copysign(1., x) == 1.:
                # atan2(+-inf, +inf) == +-pi/4
                return copysign(0.25 * math.pi, y)
            else:
                # atan2(+-inf, -inf) == +-pi*3/4
                return copysign(0.75 * math.pi, y)
        # atan2(+-inf, x) == +-pi/2 for finite x
        return copysign(0.5 * math.pi, y)
    if isinf(x) or y == 0.:
        if copysign(1., x) == 1.:
            # atan2(+-y, +inf) = atan2(+-0, +x) = +-0.
            return copysign(0., y)
        else:
            # atan2(+-y, -inf) = atan2(+-0., -x) = +-pi.
            return copysign(math.pi, y)
    return math.atan2(y, x)
Exemple #44
0
def _pow(space, x, y):
    # Sort out special cases here instead of relying on pow()
    if y == 2.0:       # special case for performance:
        return x * x   # x * x is always correct
    if y == 0.0:
        # x**0 is 1, even 0**0
        return 1.0
    if isnan(x):
        # nan**y = nan, unless y == 0
        return x
    if isnan(y):
        # x**nan = nan, unless x == 1; x**nan = x
        if x == 1.0:
            return 1.0
        else:
            return y
    if isinf(y):
        # x**inf is: 0.0 if abs(x) < 1; 1.0 if abs(x) == 1; inf if
        # abs(x) > 1 (including case where x infinite)
        #
        # x**-inf is: inf if abs(x) < 1; 1.0 if abs(x) == 1; 0.0 if
        # abs(x) > 1 (including case where v infinite)
        x = abs(x)
        if x == 1.0:
            return 1.0
        elif (y > 0.0) == (x > 1.0):
            return INFINITY
        else:
            return 0.0
    if isinf(x):
        # (+-inf)**w is: inf for w positive, 0 for w negative; in oth
        # cases, we need to add the appropriate sign if w is an odd
        # integer.
        y_is_odd = math.fmod(abs(y), 2.0) == 1.0
        if y > 0.0:
            if y_is_odd:
                return x
            else:
                return abs(x)
        else:
            if y_is_odd:
                return copysign(0.0, x)
            else:
                return 0.0

    if x == 0.0:
        if y < 0.0:
            raise oefmt(space.w_ZeroDivisionError,
                        "0.0 cannot be raised to a negative power")

    negate_result = False
    # special case: "(-1.0) ** bignum" should not raise PowDomainError,
    # unlike "math.pow(-1.0, bignum)".  See http://mail.python.org/
    # -           pipermail/python-bugs-list/2003-March/016795.html
    if x < 0.0:
        if isnan(y):
            return NAN
        if math.floor(y) != y:
            raise PowDomainError
        # y is an exact integer, albeit perhaps a very large one.
        # Replace x by its absolute value and remember to negate the
        # pow result if y is odd.
        x = -x
        negate_result = math.fmod(abs(y), 2.0) == 1.0

    if x == 1.0:
        # (-1) ** large_integer also ends up here
        if negate_result:
            return -1.0
        else:
            return 1.0

    try:
        # We delegate to our implementation of math.pow() the error detection.
        z = math.pow(x, y)
    except OverflowError:
        raise oefmt(space.w_OverflowError, "float power")
    except ValueError:
        raise oefmt(space.w_ValueError, "float power")

    if negate_result:
        z = -z
    return z
Exemple #45
0
def test_copysign():
    assert copysign(1, 1) == 1
    assert copysign(-1, 1) == 1
    assert copysign(-1, -1) == -1
    assert copysign(1, -1) == -1
    assert copysign(1, -0.) == -1
Exemple #46
0
def copysign(space, w_x, w_y):
    """Return x with the sign of y."""
    # No exceptions possible.
    x = _get_double(space, w_x)
    y = _get_double(space, w_y)
    return space.wrap(rfloat.copysign(x, y))
Exemple #47
0
        def _format_complex(self, w_complex):
            flags = 0
            space = self.space
            tp = self._type
            self._get_locale(tp)
            default_precision = 6
            if self._align == "=":
                # '=' alignment is invalid
                msg = ("'=' alignment flag is not allowed in"
                       " complex format specifier")
                raise OperationError(space.w_ValueError, space.wrap(msg))
            if self._fill_char == "0":
                #zero padding is invalid
                msg = "Zero padding is not allowed in complex format specifier"
                raise OperationError(space.w_ValueError, space.wrap(msg))
            if self._alternate:
                flags |= rfloat.DTSF_ALT

            skip_re = 0
            add_parens = 0
            if tp == "\0":
                #should mirror str() output
                tp = "g"
                default_precision = 12
                #test if real part is non-zero
                if (w_complex.realval == 0
                        and copysign(1., w_complex.realval) == 1.):
                    skip_re = 1
                else:
                    add_parens = 1

            if tp == "n":
                #same as 'g' except for locale, taken care of later
                tp = "g"

            #check if precision not set
            if self._precision == -1:
                self._precision = default_precision

            #in CPython it's named 're' - clashes with re module
            re_num, special = rfloat.double_to_string(w_complex.realval, tp,
                                                      self._precision, flags)
            im_num, special = rfloat.double_to_string(w_complex.imagval, tp,
                                                      self._precision, flags)
            n_re_digits = len(re_num)
            n_im_digits = len(im_num)

            to_real_number = 0
            to_imag_number = 0
            re_sign = im_sign = ''
            #if a sign character is in the output, remember it and skip
            if re_num[0] == "-":
                re_sign = "-"
                to_real_number = 1
                n_re_digits -= 1
            if im_num[0] == "-":
                im_sign = "-"
                to_imag_number = 1
                n_im_digits -= 1

            #turn off padding - do it after number composition
            #calc_num_width uses self._width, so assign to temporary variable,
            #calculate width of real and imag parts, then reassign padding, align
            tmp_fill_char = self._fill_char
            tmp_align = self._align
            tmp_width = self._width
            self._fill_char = "\0"
            self._align = "<"
            self._width = -1

            #determine if we have remainder, might include dec or exponent or both
            re_have_dec, re_remainder_ptr = self._parse_number(
                re_num, to_real_number)
            im_have_dec, im_remainder_ptr = self._parse_number(
                im_num, to_imag_number)

            if self.is_unicode:
                re_num = re_num.decode("latin-1")
                im_num = im_num.decode("latin-1")

            #set remainder, in CPython _parse_number sets this
            #using n_re_digits causes tests to fail
            re_n_remainder = len(re_num) - re_remainder_ptr
            im_n_remainder = len(im_num) - im_remainder_ptr
            re_spec = self._calc_num_width(0, re_sign, to_real_number,
                                           n_re_digits, re_n_remainder,
                                           re_have_dec, re_num)

            #capture grouped digits b/c _fill_number reads from self._grouped_digits
            #self._grouped_digits will get overwritten in imaginary calc_num_width
            re_grouped_digits = self._grouped_digits
            if not skip_re:
                self._sign = "+"
            im_spec = self._calc_num_width(0, im_sign, to_imag_number,
                                           n_im_digits, im_n_remainder,
                                           im_have_dec, im_num)

            im_grouped_digits = self._grouped_digits
            if skip_re:
                re_spec.n_total = 0

            #reassign width, alignment, fill character
            self._align = tmp_align
            self._width = tmp_width
            self._fill_char = tmp_fill_char

            #compute L and R padding - stored in self._left_pad and self._right_pad
            self._calc_padding(
                self.empty,
                re_spec.n_total + im_spec.n_total + 1 + add_parens * 2)

            out = self._builder()
            fill = self._fill_char

            #compose the string
            #add left padding
            out.append_multiple_char(fill, self._left_pad)
            if add_parens:
                out.append(self._lit('(')[0])

            #if the no. has a real component, add it
            if not skip_re:
                out.append(
                    self._fill_number(re_spec, re_num, to_real_number, 0, fill,
                                      re_remainder_ptr, False,
                                      re_grouped_digits))

            #add imaginary component
            out.append(
                self._fill_number(im_spec, im_num, to_imag_number, 0, fill,
                                  im_remainder_ptr, False, im_grouped_digits))

            #add 'j' character
            out.append(self._lit('j')[0])

            if add_parens:
                out.append(self._lit(')')[0])

            #add right padding
            out.append_multiple_char(fill, self._right_pad)

            return self.space.wrap(out.build())
Exemple #48
0
 def fn(x, y):
     return rfloat.copysign(x, y)
Exemple #49
0
def float_pack(x, size):
    """Convert a Python float x into a 64-bit unsigned integer
    with the same byte representation."""
    if size == 8:
        MIN_EXP = -1021  # = sys.float_info.min_exp
        MAX_EXP = 1024  # = sys.float_info.max_exp
        MANT_DIG = 53  # = sys.float_info.mant_dig
        BITS = 64
    elif size == 4:
        MIN_EXP = -125  # C's FLT_MIN_EXP
        MAX_EXP = 128  # FLT_MAX_EXP
        MANT_DIG = 24  # FLT_MANT_DIG
        BITS = 32
    elif size == 2:
        MIN_EXP = -13
        MAX_EXP = 16
        MANT_DIG = 11
        BITS = 16
    else:
        raise ValueError("invalid size value")

    sign = rfloat.copysign(1.0, x) < 0.0
    if rfloat.isinf(x):
        mant = r_ulonglong(0)
        exp = MAX_EXP - MIN_EXP + 2
    elif rfloat.isnan(x):
        asint = cast(ULONGLONG, float2longlong(x))
        sign = asint >> 63
        # shift off lower bits, perhaps losing data
        mant = asint & ((r_ulonglong(1) << 52) - 1)
        if MANT_DIG < 53:
            mant = mant >> (53 - MANT_DIG)
        if mant == 0:
            mant = r_ulonglong(1) << (MANT_DIG - 1) - 1
        exp = MAX_EXP - MIN_EXP + 2
    elif x == 0.0:
        mant = r_ulonglong(0)
        exp = 0
    else:
        m, e = math.frexp(abs(x))  # abs(x) == m * 2**e
        exp = e - (MIN_EXP - 1)
        if exp > 0:
            # Normal case.
            mant = round_to_nearest(m * (r_ulonglong(1) << MANT_DIG))
            mant -= r_ulonglong(1) << MANT_DIG - 1
        else:
            # Subnormal case.
            if exp + MANT_DIG - 1 >= 0:
                mant = round_to_nearest(m *
                                        (r_ulonglong(1) << exp + MANT_DIG - 1))
            else:
                mant = r_ulonglong(0)
            exp = 0

        # Special case: rounding produced a MANT_DIG-bit mantissa.
        if not objectmodel.we_are_translated():
            assert 0 <= mant <= 1 << MANT_DIG - 1
        if mant == r_ulonglong(1) << MANT_DIG - 1:
            mant = r_ulonglong(0)
            exp += 1

        # Raise on overflow (in some circumstances, may want to return
        # infinity instead).
        if exp >= MAX_EXP - MIN_EXP + 2:
            raise OverflowError("float too large to pack in this format")

    # check constraints
    if not objectmodel.we_are_translated():
        assert 0 <= mant <= (1 << MANT_DIG) - 1
        assert 0 <= exp <= MAX_EXP - MIN_EXP + 2
        assert 0 <= sign <= 1
    exp = r_ulonglong(exp)
    sign = r_ulonglong(sign)
    return ((sign << BITS - 1) | (exp << MANT_DIG - 1)) | mant
Exemple #50
0
 def method_sinh(self, space, value):
     try:
         res = math.sinh(value)
     except OverflowError:
         res = rfloat.copysign(rfloat.INFINITY, value)
     return space.newfloat(res)
Exemple #51
0
    (U, U),
    (Z, -Z),
    (Z, Z),
    (U, U),
    (Z, Z),
    (Z, Z),
    (N, N),
    (U, U),
    (U, U),
    (U, U),
    (U, U),
    (N, N),
    (N, N),
    (INF, N),
    (U, U),
    (INF, -Z),
    (INF, Z),
    (U, U),
    (INF, N),
    (INF, N),
    (N, N),
    (N, N),
    (N, Z),
    (N, Z),
    (N, N),
    (N, N),
    (N, N),
])

assert copysign(1., acosh_special_values[5][2][1]) == -1.
Exemple #52
0
 def method_cosh(self, space, value):
     try:
         res = math.cosh(value)
     except OverflowError:
         res = rfloat.copysign(rfloat.INFINITY, value)
     return space.newfloat(res)
Exemple #53
0
 def f(x):
     x = rfloat.copysign(0.0, x)
     return rfloat.copysign(1.0, rfloat.log1p(x))