def mpf_atan(x, prec, rnd=round_fast): sign, man, exp, bc = x if not man: if x == fzero: return fzero if x == finf: return atan_inf(0, prec, rnd) if x == fninf: return atan_inf(1, prec, rnd) return fnan mag = exp + bc # Essentially infinity if mag > prec+20: return atan_inf(sign, prec, rnd) # Essentially ~ x if -mag > prec+20: return mpf_perturb(x, 1-sign, prec, rnd) wp = prec + 30 + abs(mag) # For large x, use atan(x) = pi/2 - atan(1/x) if mag >= 2: x = mpf_rdiv_int(1, x, wp) reciprocal = True else: reciprocal = False t = to_fixed(x, wp) if sign: t = -t if wp < ATAN_TAYLOR_PREC: a = atan_taylor(t, wp) else: a = atan_newton(t, wp) if reciprocal: a = ((pi_fixed(wp)>>1)+1) - a if sign: a = -a return from_man_exp(a, -wp, prec, rnd)
def __rdiv__(s, t): prec, rounding = prec_rounding if isinstance(t, int_types): return make_mpf(mpf_rdiv_int(t, s._mpf_, prec, rounding)) t = mpf_convert_lhs(t) if t is NotImplemented: return t return t / s
def mpc_erf(z, prec, rnd=round_fast): re, im = z if im == fzero: return (mpf_erf(re, prec, rnd), fzero) wp = prec + 20 z2 = mpc_mul(z, z, prec+20) v = mpc_hyp1f1_rat((1,2), (3,2), mpc_neg(z2), wp, rnd) sqrtpi = mpf_sqrt(mpf_pi(wp), wp) c = mpf_rdiv_int(2, sqrtpi, wp) c = mpc_mul_mpf(z, c, wp) return mpc_mul(c, v, prec, rnd)
def mpc_erf(z, prec, rnd=round_fast): re, im = z if im == fzero: return (mpf_erf(re, prec, rnd), fzero) wp = prec + 20 z2 = mpc_square(z, prec + 20) v = mpc_hyp1f1_rat((1, 2), (3, 2), mpc_neg(z2), wp, rnd) sqrtpi = mpf_sqrt(mpf_pi(wp), wp) c = mpf_rdiv_int(2, sqrtpi, wp) c = mpc_mul_mpf(z, c, wp) return mpc_mul(c, v, prec, rnd)
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
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
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
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
def mpc_nthroot(z, n, prec, rnd=round_fast): """ Complex n-th root. Use Newton method as in the real case when it is faster, otherwise use z**(1/n) """ a, b = z if a[0] == 0 and b == fzero: re = mpf_nthroot(a, n, prec, rnd) return (re, fzero) if n < 2: if n == 0: return mpc_one if n == 1: return mpc_pos((a, b), prec, rnd) if n == -1: return mpc_div(mpc_one, (a, b), prec, rnd) inverse = mpc_nthroot((a, b), -n, prec + 5, reciprocal_rnd[rnd]) return mpc_div(mpc_one, inverse, prec, rnd) if n <= 20: prec2 = int(1.2 * (prec + 10)) asign, aman, aexp, abc = a bsign, bman, bexp, bbc = b pf = mpc_abs((a, b), prec) if pf[-2] + pf[-1] > -10 and pf[-2] + pf[-1] < prec: af = to_fixed(a, prec2) bf = to_fixed(b, prec2) re, im = mpc_nthroot_fixed(af, bf, n, prec2) extra = 10 re = from_man_exp(re, -prec2 - extra, prec2, rnd) im = from_man_exp(im, -prec2 - extra, prec2, rnd) return re, im fn = from_int(n) prec2 = prec + 10 + 10 nth = mpf_rdiv_int(1, fn, prec2) re, im = mpc_pow((a, b), (nth, fzero), prec2, rnd) re = normalize(re[0], re[1], re[2], re[3], prec, rnd) im = normalize(im[0], im[1], im[2], im[3], prec, rnd) return re, im
def mpc_nthroot(z, n, prec, rnd=round_fast): """ Complex n-th root. Use Newton method as in the real case when it is faster, otherwise use z**(1/n) """ a, b = z if a[0] == 0 and b == fzero: re = mpf_nthroot(a, n, prec, rnd) return (re, fzero) if n < 2: if n == 0: return mpc_one if n == 1: return mpc_pos((a, b), prec, rnd) if n == -1: return mpc_div(mpc_one, (a, b), prec, rnd) inverse = mpc_nthroot((a, b), -n, prec+5, reciprocal_rnd[rnd]) return mpc_div(mpc_one, inverse, prec, rnd) if n <= 20: prec2 = int(1.2 * (prec + 10)) asign, aman, aexp, abc = a bsign, bman, bexp, bbc = b pf = mpc_abs((a,b), prec) if pf[-2] + pf[-1] > -10 and pf[-2] + pf[-1] < prec: af = to_fixed(a, prec2) bf = to_fixed(b, prec2) re, im = mpc_nthroot_fixed(af, bf, n, prec2) extra = 10 re = from_man_exp(re, -prec2-extra, prec2, rnd) im = from_man_exp(im, -prec2-extra, prec2, rnd) return re, im fn = from_int(n) prec2 = prec+10 + 10 nth = mpf_rdiv_int(1, fn, prec2) re, im = mpc_pow((a, b), (nth, fzero), prec2, rnd) re = normalize(re[0], re[1], re[2], re[3], prec, rnd) im = normalize(im[0], im[1], im[2], im[3], prec, rnd) return re, im
if a[0] == 0 and b == fzero: re = mpf_nthroot(a, n, prec, rnd) return (re, fzero) if n < 2: if n == 0: return mpc_one if n == 1: return mpc_pos((a, b), prec, rnd) if n == -1: return mpc_div(mpc_one, (a, b), prec, rnd) inverse = mpc_nthroot((a, b), -n, prec+5, reciprocal_rnd[rnd]) return mpc_div(mpc_one, inverse, prec, rnd) if n > 20: fn = from_int(n) prec2 = prec+10 nth = mpf_rdiv_int(1, fn, prec2) re, im = mpc_pow((a, b), (nth, fzero), prec2, rnd) re = normalize(re[0], re[1], re[2], re[3], prec, rnd) im = normalize(im[0], im[1], im[2], im[3], prec, rnd) return re, im prec2 = int(1.2 * (prec + 10)) asign, aman, aexp, abc = a bsign, bman, bexp, bbc = b af = to_fixed(a, prec2) bf = to_fixed(b, prec2) re, im = mpc_nthroot_fixed(af, bf, n, prec2) extra = 10 re = from_man_exp(re, -prec2-extra, prec2, rnd) im = from_man_exp(im, -prec2-extra, prec2, rnd) return re, im
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
def mpf_bernoulli(n, prec, rnd=None): """Computation of Bernoulli numbers (numerically)""" if n < 2: if n < 0: raise ValueError("Bernoulli numbers only defined for n >= 0") if n == 0: return fone if n == 1: return mpf_neg(fhalf) # For odd n > 1, the Bernoulli numbers are zero if n & 1: return fzero # If precision is extremely high, we can save time by computing # the Bernoulli number at a lower precision that is sufficient to # obtain the exact fraction, round to the exact fraction, and # convert the fraction back to an mpf value at the original precision if prec > BERNOULLI_PREC_CUTOFF and prec > bernoulli_size(n) * 1.1 + 1000: p, q = bernfrac(n) return from_rational(p, q, prec, rnd or round_floor) if n > MAX_BERNOULLI_CACHE: return mpf_bernoulli_huge(n, prec, rnd) wp = prec + 30 # Reuse nearby precisions wp += 32 - (prec & 31) cached = bernoulli_cache.get(wp) if cached: numbers, state = cached if n in numbers: if not rnd: return numbers[n] return mpf_pos(numbers[n], prec, rnd) m, bin, bin1 = state if n - m > 10: return mpf_bernoulli_huge(n, prec, rnd) else: if n > 10: return mpf_bernoulli_huge(n, prec, rnd) numbers = {0: fone} m, bin, bin1 = state = [2, MP_BASE(10), MP_ONE] bernoulli_cache[wp] = (numbers, state) while m <= n: #print m case = m % 6 # Accurately estimate size of B_m so we can use # fixed point math without using too much precision szbm = bernoulli_size(m) s = 0 sexp = max(0, szbm) - wp if m < 6: a = MP_ZERO else: a = bin1 for j in xrange(1, m // 6 + 1): usign, uman, uexp, ubc = u = numbers[m - 6 * j] if usign: uman = -uman s += lshift(a * uman, uexp - sexp) # Update inner binomial coefficient j6 = 6 * j a *= ((m - 5 - j6) * (m - 4 - j6) * (m - 3 - j6) * (m - 2 - j6) * (m - 1 - j6) * (m - j6)) a //= ((4 + j6) * (5 + j6) * (6 + j6) * (7 + j6) * (8 + j6) * (9 + j6)) if case == 0: b = mpf_rdiv_int(m + 3, f3, wp) if case == 2: b = mpf_rdiv_int(m + 3, f3, wp) if case == 4: b = mpf_rdiv_int(-m - 3, f6, wp) s = from_man_exp(s, sexp, wp) b = mpf_div(mpf_sub(b, s, wp), from_int(bin), wp) numbers[m] = b m += 2 # Update outer binomial coefficient bin = bin * ((m + 2) * (m + 3)) // (m * (m - 1)) if m > 6: bin1 = bin1 * ((2 + m) * (3 + m)) // ((m - 7) * (m - 6)) state[:] = [m, bin, bin1]
def mpf_bernoulli(n, prec, rnd=None): """Computation of Bernoulli numbers (numerically)""" if n < 2: if n < 0: raise ValueError("Bernoulli numbers only defined for n >= 0") if n == 0: return fone if n == 1: return mpf_neg(fhalf) # For odd n > 1, the Bernoulli numbers are zero if n & 1: return fzero # If precision is extremely high, we can save time by computing # the Bernoulli number at a lower precision that is sufficient to # obtain the exact fraction, round to the exact fraction, and # convert the fraction back to an mpf value at the original precision if prec > BERNOULLI_PREC_CUTOFF and prec > bernoulli_size(n)*1.1 + 1000: p, q = bernfrac(n) return from_rational(p, q, prec, rnd or round_floor) if n > MAX_BERNOULLI_CACHE: return mpf_bernoulli_huge(n, prec, rnd) wp = prec + 30 # Reuse nearby precisions wp += 32 - (prec & 31) cached = bernoulli_cache.get(wp) if cached: numbers, state = cached if n in numbers: if not rnd: return numbers[n] return mpf_pos(numbers[n], prec, rnd) m, bin, bin1 = state if n - m > 10: return mpf_bernoulli_huge(n, prec, rnd) else: if n > 10: return mpf_bernoulli_huge(n, prec, rnd) numbers = {0:fone} m, bin, bin1 = state = [2, MPZ(10), MPZ_ONE] bernoulli_cache[wp] = (numbers, state) while m <= n: #print m case = m % 6 # Accurately estimate size of B_m so we can use # fixed point math without using too much precision szbm = bernoulli_size(m) s = 0 sexp = max(0, szbm) - wp if m < 6: a = MPZ_ZERO else: a = bin1 for j in xrange(1, m//6+1): usign, uman, uexp, ubc = u = numbers[m-6*j] if usign: uman = -uman s += lshift(a*uman, uexp-sexp) # Update inner binomial coefficient j6 = 6*j a *= ((m-5-j6)*(m-4-j6)*(m-3-j6)*(m-2-j6)*(m-1-j6)*(m-j6)) a //= ((4+j6)*(5+j6)*(6+j6)*(7+j6)*(8+j6)*(9+j6)) if case == 0: b = mpf_rdiv_int(m+3, f3, wp) if case == 2: b = mpf_rdiv_int(m+3, f3, wp) if case == 4: b = mpf_rdiv_int(-m-3, f6, wp) s = from_man_exp(s, sexp, wp) b = mpf_div(mpf_sub(b, s, wp), from_int(bin), wp) numbers[m] = b m += 2 # Update outer binomial coefficient bin = bin * ((m+2)*(m+3)) // (m*(m-1)) if m > 6: bin1 = bin1 * ((2+m)*(3+m)) // ((m-7)*(m-6)) state[:] = [m, bin, bin1] return numbers[n]
if a[0] == 0 and b == fzero: re = mpf_nthroot(a, n, prec, rnd) return (re, fzero) if n < 2: if n == 0: return mpc_one if n == 1: return mpc_pos((a, b), prec, rnd) if n == -1: return mpc_div(mpc_one, (a, b), prec, rnd) inverse = mpc_nthroot((a, b), -n, prec + 5, reciprocal_rnd[rnd]) return mpc_div(mpc_one, inverse, prec, rnd) if n > 20: fn = from_int(n) prec2 = prec + 10 nth = mpf_rdiv_int(1, fn, prec2) re, im = mpc_pow((a, b), (nth, fzero), prec2, rnd) re = normalize(re[0], re[1], re[2], re[3], prec, rnd) im = normalize(im[0], im[1], im[2], im[3], prec, rnd) return re, im prec2 = int(1.2 * (prec + 10)) asign, aman, aexp, abc = a bsign, bman, bexp, bbc = b af = to_fixed(a, prec2) bf = to_fixed(b, prec2) re, im = mpc_nthroot_fixed(af, bf, n, prec2) extra = 10 re = from_man_exp(re, -prec2 - extra, prec2, rnd) im = from_man_exp(im, -prec2 - extra, prec2, rnd) return re, im