Esempio n. 1
0
def log(x, b=None):
    """
    log(x)    -> the natural (base e) logarithm of x
    log(x, b) -> the base b logarithm of x

    """
    # Basic input management
    if b is not None:
        Float._prec += 3
        if b == 2:
            blog = log2_float()
        elif b == 10:
            blog = log10_float()
        else:
            blog = log(b)
        l = log(x) / blog
        Float._prec -= 3
        return l

    if x == 0:
        raise ValueError, "logarithm of 0"

    if isinstance(x, (ComplexFloat, complex)):
        mag = abs(x)
        phase = atan2(x.imag, x.real)
        return ComplexFloat(log(mag), phase)

    if not isinstance(x, Float):
        x = Float(x)

    if x < 0:
        return log(ComplexFloat(x))

    if x == 1:
        return Float((0, 0))

    bc = bitcount(x.man)
    # Estimated precision needed for log(t) + n*log(2)
    prec = Float._prec + int(_clog(1 + abs(bc + x.exp), 2)) + 10

    # Watch out for the case when x is very close to 1
    if -1 < bc + x.exp < 2:
        near_one = abs(x - 1)
        if near_one == 0:
            return Float((0, 0))
        prec += -(near_one.exp) - bitcount(near_one.man)

    # Separate mantissa and exponent, calculate fixed-point
    # approximation and put it all together
    t = _rshift(x.man, bc - prec)
    l = _log_newton(t, prec)
    a = (x.exp + bc) * log2_fixed(prec)
    return Float((l + a, -prec))
Esempio n. 2
0
def exp(x):
    """
    exp(x) -- compute the exponential function of the real or complex
    number x
    """
    if isinstance(x, (ComplexFloat, complex)):
        mag = exp(x.real)
        re, im = cos_sin(x.imag)
        return ComplexFloat(mag * re, mag * im)
    else:
        if not isinstance(x, Float):
            x = Float(x)
        # extra precision needs to be similar in magnitude to log_2(|x|)
        prec = Float._prec + 4 + max(0, bitcount(x.man) + x.exp)
        t = make_fixed(x, prec)
        if abs(x) > 1:
            lg2 = log2_fixed(prec)
            n, t = divmod(t, lg2)
        else:
            n = 0
        y = _exp_series(t, prec)
        return Float((y, -prec + n))