def mpf_asin(x, prec, rnd=round_fast): sign, man, exp, bc = x if bc+exp > 0 and x not in (fone, fnone): raise ComplexResult("asin(x) is real only for -1 <= x <= 1") flag_nr = True if prec < 1000 or exp+bc < -13: flag_nr = False else: ebc = exp + bc if ebc < -13: flag_nr = False elif ebc < -3: if prec < 3000: flag_nr = False if not flag_nr: # asin(x) = 2*atan(x/(1+sqrt(1-x**2))) wp = prec + 15 a = mpf_mul(x, x) b = mpf_add(fone, mpf_sqrt(mpf_sub(fone, a, wp), wp), wp) c = mpf_div(x, b, wp) return mpf_shift(mpf_atan(c, prec, rnd), 1) # use Newton's method extra = 10 extra_p = 10 prec2 = prec + extra r = math.asin(to_float(x)) r = from_float(r, 50, rnd) for p in giant_steps(50, prec2): wp = p + extra_p c, s = cos_sin(r, wp, rnd) tmp = mpf_sub(x, s, wp, rnd) tmp = mpf_div(tmp, c, wp, rnd) r = mpf_add(r, tmp, wp, rnd) sign, man, exp, bc = r return normalize(sign, man, exp, bc, prec, rnd)
def exp_newton(x, prec): extra = 10 r = mpf_exp(x, 60) start = 50 prevp = start for p in giant_steps(start, prec+extra, 4): h = mpf_sub(x, mpf_log(r, p), p) h2 = mpf_mul(h, h, p) h3 = mpf_mul(h2, h, p) h4 = mpf_mul(h2, h2, p) t = mpf_add(h, mpf_shift(h2, -1), p) t = mpf_add(t, mpf_div(h3, from_int(6, p), p), p) t = mpf_add(t, mpf_div(h4, from_int(24, p), p), p) t = mpf_mul(r, t, p) r = mpf_add(r, t, p) return r
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)
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)
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)
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