Beispiel #1
0
def atan_newton(x, prec):
    if prec >= 100:
        r = math.atan((x>>(prec-53))/2.0**53)
    else:
        r = math.atan(x/2.0**prec)
    prevp = 50
    r = int(r * 2.0**53) >> (53-prevp)
    extra_p = 50
    for wp in giant_steps(prevp, prec):
        wp += extra_p
        r = r << (wp-prevp)
        cos, sin = cos_sin_fixed(r, wp)
        tan = (sin << wp) // cos
        a = ((tan-rshift(x, prec-wp)) << wp) // ((MPZ_ONE<<wp) + ((tan**2)>>wp))
        r = r - a
        prevp = wp
    return rshift(r, prevp-prec)
Beispiel #2
0
def atan_newton(x, prec):
    if prec >= 100:
        r = math.atan((x >> (prec - 53)) / 2.0 ** 53)
    else:
        r = math.atan(x / 2.0 ** prec)
    prevp = 50
    r = MPZ(int(r * 2.0 ** 53) >> (53 - prevp))
    extra_p = 50
    for wp in giant_steps(prevp, prec):
        wp += extra_p
        r = r << (wp - prevp)
        cos, sin = cos_sin_fixed(r, wp)
        tan = (sin << wp) // cos
        a = ((tan - rshift(x, prec - wp)) << wp) // ((MPZ_ONE << wp) + ((tan ** 2) >> wp))
        r = r - a
        prevp = wp
    return rshift(r, prevp - prec)
Beispiel #3
0
def atan_newton(x, prec):
    if prec >= 100:
        r = math.atan((x>>(prec-53))/2.0**53)
    else:
        r = math.atan(x/2.0**prec)
    prevp = 50
    r = int(r * 2.0**53) >> (53-prevp)
    extra_p = 100
    for p in giant_steps(prevp, prec):
        s = int(0.137 * p**0.579)
        p += s + 50
        r = r << (p-prevp)
        cos, sin = expi_series(r, p, s)
        tan = (sin << p) // cos
        a = ((tan - rshift(x, prec-p)) << p) // ((MP_ONE<<p) + ((tan**2)>>p))
        r = r - a
        prevp = p
    return rshift(r, prevp-prec)
Beispiel #4
0
def atan_newton(x, prec):
    if prec >= 100:
        r = math.atan((x>>(prec-53))/2.0**53)
    else:
        r = math.atan(x/2.0**prec)
    prevp = 50
    r = int(r * 2.0**53) >> (53-prevp)
    extra_p = 100
    for p in giant_steps(prevp, prec):
        s = int(0.137 * p**0.579)
        p += s + 50
        r = r << (p-prevp)
        cos, sin = expi_series(r, p, s)
        tan = (sin << p) // cos
        a = ((tan - rshift(x, prec-p)) << p) // ((MP_ONE<<p) + ((tan**2)>>p))
        r = r - a
        prevp = p
    return rshift(r, prevp-prec)
Beispiel #5
0
def nthroot_fixed(y, n, prec, exp1):
    start = 50
    try:
        y1 = rshift(y, prec - n*start)
        r = MP_BASE(y1**(1.0/n))
    except OverflowError:
        y1 = from_int(y1, start)
        fn = from_int(n)
        fn = mpf_rdiv_int(1, fn, start)
        r = mpf_pow(y1, fn, start)
        r = to_int(r)
    extra = 10
    extra1 = n
    prevp = start
    for p in giant_steps(start, prec+extra):
        pm, pe = int_pow_fixed(r, n-1, prevp)
        r2 = rshift(pm, (n-1)*prevp - p - pe - extra1)
        B = lshift(y, 2*p-prec+extra1)//r2
        r = (B + (n-1) * lshift(r, p-prevp))//n
        prevp = p
    return r
Beispiel #6
0
def nthroot_fixed(y, n, prec, exp1):
    start = 50
    try:
        y1 = rshift(y, prec - n*start)
        r = MP_BASE(int(y1**(1.0/n)))
    except OverflowError:
        y1 = from_int(y1, start)
        fn = from_int(n)
        fn = mpf_rdiv_int(1, fn, start)
        r = mpf_pow(y1, fn, start)
        r = to_int(r)
    extra = 10
    extra1 = n
    prevp = start
    for p in giant_steps(start, prec+extra):
        pm, pe = int_pow_fixed(r, n-1, prevp)
        r2 = rshift(pm, (n-1)*prevp - p - pe - extra1)
        B = lshift(y, 2*p-prec+extra1)//r2
        r = (B + (n-1) * lshift(r, p-prevp))//n
        prevp = p
    return r
Beispiel #7
0
def log_newton(x, prec):
    extra = 10
    # 40-bit approximation
    fx = math.log(long(x)) - 0.69314718055994529*prec
    r = MP_BASE(fx * 2.0**40)
    prevp = 40
    for p in giant_steps2(40, prec+extra):
        rb = lshift(r, p-prevp)
        # Parameters for exponential series
        if p < 300:
            r = int(2 * p**0.4)
            exp_func = exp_series
        else:
            r = int(0.7 * p**0.5)
            exp_func = exp_series2
        exp_extra = r + 10
        e = exp_func((-rb) << exp_extra, p + exp_extra, r)
        s = ((rshift(x, prec-p)*e)>>(p + exp_extra)) - (1 << p)
        s1 = -((s*s)>>(p+1))
        r = rb + s + s1
        prevp = p
    return r >> extra
Beispiel #8
0
def log_newton(x, prec):
    extra = 10
    # 40-bit approximation
    fx = math.log(long(x)) - 0.69314718055994529 * prec
    r = MP_BASE(fx * 2.0**40)
    prevp = 40
    for p in giant_steps2(40, prec + extra):
        rb = lshift(r, p - prevp)
        # Parameters for exponential series
        if p < 300:
            r = int(2 * p**0.4)
            exp_func = exp_series
        else:
            r = int(0.7 * p**0.5)
            exp_func = exp_series2
        exp_extra = r + 10
        e = exp_func((-rb) << exp_extra, p + exp_extra, r)
        s = ((rshift(x, prec - p) * e) >> (p + exp_extra)) - (1 << p)
        s1 = -((s * s) >> (p + 1))
        r = rb + s + s1
        prevp = p
    return r >> extra
Beispiel #9
0
def mpc_nthroot_fixed(a, b, n, prec):
    # a, b signed integers at fixed precision prec
    start = 50
    a1 = int(rshift(a, prec - n*start))
    b1 = int(rshift(b, prec - n*start))
    try:
        r = (a1 + 1j * b1)**(1.0/n)
        re = r.real
        im = r.imag
        # XXX: workaround bug in gmpy
        if abs(re) < 0.1: re = 0
        if abs(im) < 0.1: im = 0
        re = MP_BASE(re)
        im = MP_BASE(im)
    except OverflowError:
        a1 = from_int(a1, start)
        b1 = from_int(b1, start)
        fn = from_int(n)
        nth = mpf_rdiv_int(1, fn, start)
        re, im = mpc_pow((a1, b1), (nth, fzero), start)
        re = to_int(re)
        im = to_int(im)
    extra = 10
    prevp = start
    extra1 = n
    for p in giant_steps(start, prec+extra):
        # this is slow for large n, unlike int_pow_fixed
        re2, im2 = complex_int_pow(re, im, n-1)
        re2 = rshift(re2, (n-1)*prevp - p - extra1)
        im2 = rshift(im2, (n-1)*prevp - p - extra1)
        r4 = (re2*re2 + im2*im2) >> (p + extra1)
        ap = rshift(a, prec - p)
        bp = rshift(b, prec - p)
        rec = (ap * re2 + bp * im2) >> p
        imc = (-ap * im2 + bp * re2) >> p
        reb = (rec << p) // r4
        imb = (imc << p) // r4
        re = (reb + (n-1)*lshift(re, p-prevp))//n
        im = (imb + (n-1)*lshift(im, p-prevp))//n
        prevp = p
    return re, im
Beispiel #10
0
def mpc_nthroot_fixed(a, b, n, prec):
    # a, b signed integers at fixed precision prec
    start = 50
    a1 = int(rshift(a, prec - n * start))
    b1 = int(rshift(b, prec - n * start))
    try:
        r = (a1 + 1j * b1)**(1.0 / n)
        re = r.real
        im = r.imag
        # XXX: workaround bug in gmpy
        if abs(re) < 0.1: re = 0
        if abs(im) < 0.1: im = 0
        re = MP_BASE(re)
        im = MP_BASE(im)
    except OverflowError:
        a1 = from_int(a1, start)
        b1 = from_int(b1, start)
        fn = from_int(n)
        nth = mpf_rdiv_int(1, fn, start)
        re, im = mpc_pow((a1, b1), (nth, fzero), start)
        re = to_int(re)
        im = to_int(im)
    extra = 10
    prevp = start
    extra1 = n
    for p in giant_steps(start, prec + extra):
        # this is slow for large n, unlike int_pow_fixed
        re2, im2 = complex_int_pow(re, im, n - 1)
        re2 = rshift(re2, (n - 1) * prevp - p - extra1)
        im2 = rshift(im2, (n - 1) * prevp - p - extra1)
        r4 = (re2 * re2 + im2 * im2) >> (p + extra1)
        ap = rshift(a, prec - p)
        bp = rshift(b, prec - p)
        rec = (ap * re2 + bp * im2) >> p
        imc = (-ap * im2 + bp * re2) >> p
        reb = (rec << p) // r4
        imb = (imc << p) // r4
        re = (reb + (n - 1) * lshift(re, p - prevp)) // n
        im = (imb + (n - 1) * lshift(im, p - prevp)) // n
        prevp = p
    return re, im
Beispiel #11
0
def mpf_log(x, prec, rnd=round_fast):
    """
    Compute the natural logarithm of the mpf value x. If x is negative,
    ComplexResult is raised.
    """
    sign, man, exp, bc = x
    if not man:
        if x == fzero: return fninf
        if x == finf: return finf
        if x == fnan: return fnan
    if sign:
        raise ComplexResult("logarithm of a negative number")

    # log(2^n)
    if man == 1:
        if not exp:
            return fzero
        return from_man_exp(exp*ln2_fixed(prec+20), -prec-20, prec, rnd)

    # Assume 20 bits to be sufficient for cancelling rounding errors
    wp = prec + 20
    mag = bc + exp

    # Already on the standard interval, (0.5, 1)
    if not mag:
        t = rshift(man, bc-wp)
        log2n = 0
        # Watch out for "x = 0.9999"
        # Proceed only if 1-x lost at most 15 bits of accuracy
        res = (MP_ONE << wp) - t
        if not (res >> (wp - 15)):
            # Find out extra precision needed
            delta = mpf_sub(x, fone, 10)
            delta_bits = -(delta[2] + delta[3])
            # O(x^2) term vanishes relatively
            if delta_bits > wp + 10:
                xm1 = mpf_sub(x, fone, prec, rnd)
                return mpf_perturb(xm1, 1, prec, rnd)
            else:
                wp += delta_bits
                t = rshift(man, bc-wp)

    # Already on the standard interval, (1, 2)
    elif mag == 1:
        t = rshift(man, bc-wp-1)
        log2n = 0
        # Watch out for "x = 1.0001"
        # Similar to above; note that we flip signs
        # to obtain a positive residual, ensuring that
        # the following shift rounds down
        res = t - (MP_ONE << wp)
        if not (res >> (wp - 15)):
            # Find out extra precision needed
            delta = mpf_sub(x, fone, 10)
            delta_bits = -(delta[2] + delta[3])
            # O(x^2) term vanishes relatively
            if delta_bits > wp + 10:
                xm1 = mpf_sub(x, fone, prec, rnd)
                return mpf_perturb(xm1, 1, prec, rnd)
            else:
                wp += delta_bits
                t = rshift(man, bc-wp-1)

    # Rescale
    else:
        # Estimated precision needed for n*log(2) to
        # be accurate relatively
        wp += int(math.log(1+abs(mag),2))
        log2n = mag * ln2_fixed(wp)
        # Rescaled argument as a fixed-point number
        t = rshift(man, bc-wp)

    # Use the faster method
    if wp < LOG_TAYLOR_PREC:
        a = log_taylor(t, wp)
    else:
        a = log_newton(t, wp)

    return from_man_exp(a + log2n, -wp, prec, rnd)
Beispiel #12
0
def mpf_nthroot(s, n, prec, rnd=round_fast):
    """nth-root of a positive number

    Use the Newton method when faster, otherwise use x**(1/n)
    """
    sign, man, exp, bc = s
    if sign:
        raise ComplexResult("nth root of a negative number")
    if not man:
        if s == fnan:
            return fnan
        if s == fzero:
            if n > 0:
                return fzero
            if n == 0:
                return fone
            return finf
        # Infinity
        if not n:
            return fnan
        if n < 0:
            return fzero
        return finf
    flag_inverse = False
    if n < 2:
        if n == 0:
            return fone
        if n == 1:
            return mpf_pos(s, prec, rnd)
        if n == -1:
            return mpf_div(fone, s, prec, rnd)
        # n < 0
        rnd = reciprocal_rnd[rnd]
        flag_inverse = True
        extra_inverse = 5
        prec += extra_inverse
        n = -n
    if n > 20 and (n >= 20000 or prec < int(233 + 28.3 * n**0.62)):
        prec2 = prec + 10
        fn = from_int(n)
        nth = mpf_rdiv_int(1, fn, prec2)
        r = mpf_pow(s, nth, prec2, rnd)
        s = normalize(r[0], r[1], r[2], r[3], prec, rnd)
        if flag_inverse:
            return mpf_div(fone, s, prec-extra_inverse, rnd)
        else:
            return s
    # Convert to a fixed-point number with prec2 bits.
    prec2 = prec + 2*n - (prec%n)
    # a few tests indicate that
    # for 10 < n < 10**4 a bit more precision is needed
    if n > 10:
        prec2 += prec2//10
        prec2 = prec2 - prec2%n
    # Mantissa may have more bits than we need. Trim it down.
    shift = bc - prec2
    # Adjust exponents to make prec2 and exp+shift multiples of n.
    sign1 = 0
    es = exp+shift
    if es < 0:
      sign1 = 1
      es = -es
    if sign1:
      shift += es%n
    else:
      shift -= es%n
    man = rshift(man, shift)
    extra = 10
    exp1 = ((exp+shift-(n-1)*prec2)//n) - extra
    rnd_shift = 0
    if flag_inverse:
        if rnd == 'u' or rnd == 'c':
            rnd_shift = 1
    else:
        if rnd == 'd' or rnd == 'f':
            rnd_shift = 1
    man = nthroot_fixed(man+rnd_shift, n, prec2, exp1)
    s = from_man_exp(man, exp1, prec, rnd)
    if flag_inverse:
        return mpf_div(fone, s, prec-extra_inverse, rnd)
    else:
        return s
Beispiel #13
0
def mpf_nthroot(s, n, prec, rnd=round_fast):
    """nth-root of a positive number

    Use the Newton method when faster, otherwise use x**(1/n)
    """
    sign, man, exp, bc = s
    if sign:
        raise ComplexResult("nth root of a negative number")
    if not man:
        if s == fnan:
            return fnan
        if s == fzero:
            if n > 0:
                return fzero
            if n == 0:
                return fone
            return finf
        # Infinity
        if not n:
            return fnan
        if n < 0:
            return fzero
        return finf
    flag_inverse = False
    if n < 2:
        if n == 0:
            return fone
        if n == 1:
            return mpf_pos(s, prec, rnd)
        if n == -1:
            return mpf_div(fone, s, prec, rnd)
        # n < 0
        rnd = reciprocal_rnd[rnd]
        flag_inverse = True
        extra_inverse = 5
        prec += extra_inverse
        n = -n
    if n > 20 and (n >= 20000 or prec < int(233 + 28.3 * n**0.62)):
        prec2 = prec + 10
        fn = from_int(n)
        nth = mpf_rdiv_int(1, fn, prec2)
        r = mpf_pow(s, nth, prec2, rnd)
        s = normalize(r[0], r[1], r[2], r[3], prec, rnd)
        if flag_inverse:
            return mpf_div(fone, s, prec-extra_inverse, rnd)
        else:
            return s
    # Convert to a fixed-point number with prec2 bits.
    prec2 = prec + 2*n - (prec%n)
    # a few tests indicate that
    # for 10 < n < 10**4 a bit more precision is needed
    if n > 10:
        prec2 += prec2//10
        prec2 = prec2 - prec2%n
    # Mantissa may have more bits than we need. Trim it down.
    shift = bc - prec2
    # Adjust exponents to make prec2 and exp+shift multiples of n.
    sign1 = 0
    es = exp+shift
    if es < 0:
        sign1 = 1
        es = -es
    if sign1:
        shift += es%n
    else:
        shift -= es%n
    man = rshift(man, shift)
    extra = 10
    exp1 = ((exp+shift-(n-1)*prec2)//n) - extra
    rnd_shift = 0
    if flag_inverse:
        if rnd == 'u' or rnd == 'c':
            rnd_shift = 1
    else:
        if rnd == 'd' or rnd == 'f':
            rnd_shift = 1
    man = nthroot_fixed(man+rnd_shift, n, prec2, exp1)
    s = from_man_exp(man, exp1, prec, rnd)
    if flag_inverse:
        return mpf_div(fone, s, prec-extra_inverse, rnd)
    else:
        return s
Beispiel #14
0
def mpf_log(x, prec, rnd=round_fast):
    """
    Compute the natural logarithm of the mpf value x. If x is negative,
    ComplexResult is raised.
    """
    sign, man, exp, bc = x
    if not man:
        if x == fzero: return fninf
        if x == finf: return finf
        if x == fnan: return fnan
    if sign:
        raise ComplexResult("logarithm of a negative number")

    # log(2^n)
    if man == 1:
        if not exp:
            return fzero
        return from_man_exp(exp * ln2_fixed(prec + 20), -prec - 20, prec, rnd)

    # Assume 20 bits to be sufficient for cancelling rounding errors
    wp = prec + 20
    mag = bc + exp

    # Already on the standard interval, (0.5, 1)
    if not mag:
        t = rshift(man, bc - wp)
        log2n = 0
        # Watch out for "x = 0.9999"
        # Proceed only if 1-x lost at most 15 bits of accuracy
        res = (MP_ONE << wp) - t
        if not (res >> (wp - 15)):
            # Find out extra precision needed
            delta = mpf_sub(x, fone, 10)
            delta_bits = -(delta[2] + delta[3])
            # O(x^2) term vanishes relatively
            if delta_bits > wp + 10:
                xm1 = mpf_sub(x, fone, prec, rnd)
                return mpf_perturb(xm1, 1, prec, rnd)
            else:
                wp += delta_bits
                t = rshift(man, bc - wp)

    # Already on the standard interval, (1, 2)
    elif mag == 1:
        t = rshift(man, bc - wp - 1)
        log2n = 0
        # Watch out for "x = 1.0001"
        # Similar to above; note that we flip signs
        # to obtain a positive residual, ensuring that
        # the following shift rounds down
        res = t - (MP_ONE << wp)
        if not (res >> (wp - 15)):
            # Find out extra precision needed
            delta = mpf_sub(x, fone, 10)
            delta_bits = -(delta[2] + delta[3])
            # O(x^2) term vanishes relatively
            if delta_bits > wp + 10:
                xm1 = mpf_sub(x, fone, prec, rnd)
                return mpf_perturb(xm1, 1, prec, rnd)
            else:
                wp += delta_bits
                t = rshift(man, bc - wp - 1)

    # Rescale
    else:
        # Estimated precision needed for n*log(2) to
        # be accurate relatively
        wp += int(math.log(1 + abs(mag), 2))
        log2n = mag * ln2_fixed(wp)
        # Rescaled argument as a fixed-point number
        t = rshift(man, bc - wp)

    # Use the faster method
    if wp < LOG_TAYLOR_PREC:
        a = log_taylor(t, wp)
    else:
        a = log_newton(t, wp)

    return from_man_exp(a + log2n, -wp, prec, rnd)