def test_modulus_transformations(phi, n, m): assume(m != 0 and sin(phi)**2 != 0) # https://dlmf.nist.gov/19.7.E6 kappap = 1 / (1 + m)**0.5 mu = m * kappap**2 ctheta = (1 + m * sin(phi)**2) * kappap**2 / sin(phi)**2 n1 = (n + m) * kappap**2 # https://dlmf.nist.gov/19.7.E4 cbeta = m / sin(phi + 0j)**2 for left, right in ((ellipkinc(phi, 1 / m), (m**0.5 * ellipkinc(None, m, cbeta))), (ellipeinc(phi, 1 / m), (ellipeinc(None, m, cbeta) - (1 - m) * ellipkinc(None, m, cbeta)) / m**0.5), (ellippiinc(n, phi, 1 / m), m**0.5 * ellippiinc(m * n, None, m, cbeta))): # TODO: properly analytically continue assert nice_and_close(left.real, right.real) # https://dlmf.nist.gov/19.7.E5 assert nice_and_close(ellipkinc(phi, -m), kappap * ellipkinc(None, mu, ctheta)) assert nice_and_close(ellipeinc( phi, -m), (ellipeinc(None, mu, ctheta) - mu * ((ctheta - 1) / (ctheta - mu) / ctheta)**0.5) / kappap) assert nice_and_close( ellippiinc(n, phi, -m), (kappap / n1) * (mu * ellipkinc(None, mu, ctheta) + kappap**2 * n * ellippiinc(n1, None, mu, ctheta)))
def test_addition_theorems(x, y, z, a, p): xa, ya, za, pa = map(partial(add, a), (x, y, z, p)) # https://dlmf.nist.gov/19.26.E12 b = (xa**0.5 * y + x**0.5 * ya)**2 / a**2 - x # https://dlmf.nist.gov/19.26.E11 assert nice_and_close(elliprc(x, y), elliprc(xa, ya) + elliprc(x + b, y + b)) # https://dlmf.nist.gov/19.26.E5 b = ((x * y * z)**0.5 + (xa * ya * za)**0.5)**2 / a**2 - (x + y + z + a) xb, yb, zb, pb = map(partial(add, b), (x, y, z, p)) # https://dlmf.nist.gov/19.26.E10 c = p * pa * pb d = (p - x) * (p - y) * (p - z) # # https://dlmf.nist.gov/19.26.E1 assert nice_and_close(elliprf(x, y, z), elliprf(xa, ya, za) + elliprf(xb, yb, zb)) # https://dlmf.nist.gov/19.26.E7 assert nice_and_close( elliprd(x, y, z) - 3 / (z * za * zb)**0.5, elliprd(xa, ya, za) + elliprd(xb, yb, zb)) # https://dlmf.nist.gov/19.26.E8 assert nice_and_close( 2 * elliprg(x, y, z) + a * elliprf(xa, ya, za) + b * elliprf(xb, yb, zb) + (x + y + z + a + b)**0.5, 2 * (elliprg(xa, ya, za) + elliprg(xb, yb, zb))) # https://dlmf.nist.gov/19.26.E9 assert nice_and_close( elliprj(x, y, z, p) - 3 * elliprc(c - d, c), elliprj(xa, ya, za, pa) + elliprj(xb, yb, zb, pb))
def test_ellippi_m_equals_n(m): # https://dlmf.nist.gov/19.6.E1, line 4 assert nice_and_close(ellippi(m, m), ellipe(m) / (1 - m)) # https://dlmf.nist.gov/19.6.E2 assert nice_and_close(ellippi(-m**0.5, m), pi / 4 / (1 + m**0.5) + ellipk(m) / 2)
def test_elliprg(x, y, z, l): assert nice_and_close(elliprg(x, x, x), x**0.5) assert nice_and_close(elliprg(l * x, l * y, l * z), elliprg(x, y, z) * l**0.5) # TODO: elliprc sign issue assert nice_and_close(elliprg(0, y, y), pi / 4 * y**0.5) assert nice_and_close(elliprg(0, 0, z), z**0.5 / 2) assert nice_and_close(2 * elliprg(x, y, y), y * elliprc(x, y) + x**0.5)
def test_every_phi(phi): # https://dlmf.nist.gov/19.6.E8 assert nice_and_close(ellipkinc(phi, 1), asinh(tan(phi))) # https://dlmf.nist.gov/19.6.E9, line 4 assert nice_and_close(ellipeinc(phi, 1), sin(phi)) # # https://dlmf.nist.gov/19.6.E11, line 3 assert nice_and_close(ellippiinc(1, phi, 0), tan(phi))
def test_complete_1(y, z): # https://dlmf.nist.gov/19.21.E2 assert nice_and_close(3 * elliprf(0, y, z), z * elliprd(0, y, z) + y * elliprd(0, z, y)) # https://dlmf.nist.gov/19.21.E3 assert nice_and_close(6 * elliprg(0, y, z), y * z * (elliprd(0, y, z) + elliprd(0, z, y))) assert nice_and_close( 6 * elliprg(0, y, z), 3 * z * elliprf(0, y, z) + z * (y - z) * elliprd(0, y, z))
def test_complete_2(z: complex): assume(not z.imag == 0) sign = (1 if phase(z) > 0 else -1) * 1j # https://dlmf.nist.gov/19.21.E4 assert nice_and_close(elliprf(0, z - 1, z), elliprf(0, 1 - z, 1) - sign * elliprf(0, z, 1)) # https://dlmf.nist.gov/19.21.E5 assert nice_and_close( 2 * elliprg(0, z - 1, z), 2 * (elliprg(0, 1 - z, 1) + sign * elliprg(0, z, 1)) + (z - 1) * elliprf(0, 1 - z, 1) - sign * z * elliprf(0, z, 1))
def test_legendre_relation(m: complex): k = m**0.5 mm = 1 - m kp = mm**0.5 # https://dlmf.nist.gov/19.7.E2 assert nice_and_close(ellipk((+1j * k / kp)**2), kp * ellipk(m)) assert nice_and_close(ellipk((-1j * kp / k)**2), k * ellipk(mm)) assert nice_and_close(ellipe((+1j * k / kp)**2), ellipe(m) / kp) assert nice_and_close(ellipe((-1j * kp / k)**2), ellipe(mm) / k) # https://dlmf.nist.gov/19.7.E3 assert nice_and_close( ellipk(1 / m), k * (ellipk(m) - (1 if m.imag > 0 else -1) * 1j * ellipk(mm))) assert nice_and_close( ellipk(1 / mm), kp * (ellipk(mm) + (1 if m.imag >= 0 else -1) * 1j * ellipk(m))) assert nice_and_close(ellipe( 1 / m), (ellipe(m) + (1 if m.imag > 0 else -1) * 1j * ellipe(mm) - (mm * ellipk(m) + (1 if m.imag > 0 else -1) * 1j * m * ellipk(mm))) / k) assert nice_and_close(ellipe( 1 / mm), (ellipe(mm) - (1 if m.imag > 0 else -1) * 1j * ellipe(m) - (m * ellipk(mm) - (1 if m.imag > 0 else -1) * 1j * mm * ellipk(m))) / kp)
def test_every_phi_but_zero(phi): assume(sin(phi) != 0 and not isnan(ellippiinc(1, phi, 1))) c = 1 / sin(phi)**2 # https://dlmf.nist.gov/19.6.E12 assert nice_and_close(ellippiinc(1, phi, 1), (elliprc(c, c - 1) + c**0.5 / (c - 1)) / 2)
def test_trivial_zeros(n): try: # these are hard-coded, but we want it to stay like that, # if we un-hard-code them assert nice_and_close(abs(zeta(-2 * n)), 0) except RuntimeError: # overflow assume(False)
def test_ellippiinc_every_phi_m(phi, m): assume(sin(phi) != 0) c = 1 / sin(phi)**2 D = (1 - m / c)**0.5 # https://dlmf.nist.gov/19.6.E12 assert nice_and_close(ellippiinc(m, phi, 0), elliprc(c - 1, c - m)) assert nice_and_close(ellippiinc( m, phi, 1), (elliprc(c, c - 1) - m * elliprc(c, c - m)) / (1 - m)) assert nice_and_close(ellippiinc(0, phi, m), ellipkinc(phi, m)) # https://dlmf.nist.gov/19.6.E13 assert nice_and_close( ellippiinc(m, phi, m), (ellipeinc(phi, m) - m / D * sin(phi) * cos(phi)) / (1 - m)) assert nice_and_close( ellippiinc(1, phi, m), ellipkinc(phi, m) - (ellipeinc(phi, m) - D * tan(phi)) / (1 - m))
def test_elliprj(x, y, z, p): # TODO: properly analytically continue assume(distinct(x, y, z, p)) # https://dlmf.nist.gov/19.21.E13 q = (y - x) * (z - x) / (p - x) + x # # https://dlmf.nist.gov/19.21.E12 # TODO: elliprc sign issue assert nice_and_close( ((p - x) * elliprj(x, y, z, p) + (q - x) * elliprj(x, y, z, q)).real, (3 * (elliprf(x, y, z) - elliprc(y * z / x, p * q / x))).real) # https://dlmf.nist.gov/19.21.E15 # special case of above with x=0 q = y * z / p assert nice_and_close( (p * elliprj(0, y, z, p) + q * elliprj(0, y, z, q)).real, 3 * elliprf(0, y, z).real)
def test_incomplete(x, y, z): # TODO: sign of sqrt(x, y, z) assume(distinct(x, y, z)) # https://dlmf.nist.gov/19.21.E7 assert nice_and_close( abs(3 * elliprf(x, y, z) - ((x - y) * elliprd(y, z, x) + (z - y) * elliprd(x, y, z))), abs(3 * (y / x / z)**0.5)) # https://dlmf.nist.gov/19.21.E8 assert nice_and_close( abs(elliprd(y, z, x) + elliprd(z, x, y) + elliprd(x, y, z)), abs(3 * (x * y * z)**(-0.5))) # https://dlmf.nist.gov/19.21.E9 assert nice_and_close( x * elliprd(y, z, x) + y * elliprd(z, x, y) + z * elliprd(x, y, z), 3 * elliprf(x, y, z)) # https://dlmf.nist.gov/19.21.E10 assert nice_and_close( abs(2 * elliprg(x, y, z) - (z * elliprf(x, y, z) - (x - z) * (y - z) * elliprd(x, y, z) / 3)), abs((x * y / z)**0.5)) # https://dlmf.nist.gov/19.21.E11 assert nice_and_close( 6 * elliprg(x, y, z), 3 * (x + y + z) * elliprf(x, y, z) - sum(_x**2 * elliprd(_y, _z, _x) for _x, _y, _z in circular_shifts((x, y, z)))) assert nice_and_close( 6 * elliprg(x, y, z), sum(_x * (_y + _z) * elliprd(_y, _z, _x) for _x, _y, _z in circular_shifts((x, y, z))))
def test_duplication_formulas(x, y, z, p): xs, ys, zs = (_**0.5 for _ in (x, y, z)) ss = xs + ys + zs # https://dlmf.nist.gov/19.26.E25 a = y + 2 * xs * ys assert nice_and_close(elliprc(x, y), 2 * elliprc(x + a, y + a)) # https://dlmf.nist.gov/19.26.E19 a = sum(map(product, combinations((xs, ys, zs), 2))) xa, ya, za, pa = map(partial(add, a), (x, y, z, p)) # https://dlmf.nist.gov/19.26.E18 assert nice_and_close(elliprf(x, y, z), 2 * elliprf(xa, ya, za)) assert nice_and_close(elliprf(x, y, z), elliprf(xa / 4, ya / 4, za / 4)) # https://dlmf.nist.gov/19.26.E20 assert nice_and_close(elliprd(x, y, z), 2 * elliprd(xa, ya, za) + 3 / z**0.5 / za) # https://dlmf.nist.gov/19.26.E21 assert nice_and_close( 2 * elliprg(x, y, z), 4 * elliprg(xa, ya, za) - a * elliprf(x, y, z) - ss) # https://dlmf.nist.gov/19.26.E22 assert nice_and_close( elliprj(x, y, z, p), 2 * elliprj(xa, ya, za, pa) + 3 * elliprc( (p * ss + xs * ys * zs)**2, p * pa**2))
def test_complete_3(y, z, p): # https://dlmf.nist.gov/19.21.E6 assume(distinct(y, z, p)) if z < y < p or p < y < z: y, z = z, y r = (y - p) / (y - z) assume(r > 0) assert nice_and_close( (r * p)**0.5 / z * elliprj(0, y, z, p), (r - 1) * elliprf(0, y, z) * elliprd(p, r * z, z) + elliprd(0, y, z) * elliprf(p, r * z, z))
def test_argument_transformations(phi, n, m): # https://dlmf.nist.gov/19.7.E7 assume(sinh(phi) != 0) cpsi = 1 + sinh(phi)**(-2) for left, right in ((ellipkinc(1j * phi, m), ellipkinc(None, 1 - m, cpsi)), (ellipeinc(1j * phi, m), ellipkinc(None, 1 - m, cpsi) - ellipeinc(None, 1 - m, cpsi) + (1 if phi >= 0 else -1) * sinh(phi) * (1 - (1 - m) / cpsi)**0.5), (ellippiinc(n, 1j * phi, m), (ellipkinc(None, 1 - m, cpsi) - n * ellippiinc(1 - n, None, 1 - m, cpsi)) / (1 - n))): # TODO: properly analytically continue assert nice_and_close(abs(left.imag), abs(right.real))
def test_elliprj(x, y, z, p, l): assert nice_and_close(elliprj(x, x, x, x), x**(-1.5)) assert nice_and_close(elliprj(l * x, l * y, l * z, l * p), elliprj(x, y, z, p) / l**1.5) assert nice_and_close(elliprj(x, y, z, z), elliprd(x, y, z)) assert isinf(elliprj(0, 0, z, p)) assert nice_and_close(elliprj(x, x, x, p), elliprd(p, p, x)) assert nice_and_close( elliprj(x, x, x, p).real, 3 * (elliprc(x, p) - x**(-0.5)) / (x - p)) assert nice_and_close(elliprj(x, y, y, y), elliprd(x, y, y)) # assert nice_and_close(elliprj(0, y, z, (y*z)**0.5), 1.5/(y*z)**0.5 * elliprf(0, y, z)) # assert nice_and_close(elliprj(0, y, z, -(y*z)**0.5), -1.5/(y*z)**0.5 * elliprf(0, y, z)) # TODO: elliprc sign issue assume(distinct(x, y, z)) p = x + ((y - x) * (z - x))**0.5 assert nice_and_close( (p - x) * elliprj(x, y, z, p), 1.5 * (elliprf(x, y, z) - x**0.5 * elliprc(y * z, p**2)))
def test_ellippi_every_n(n): # https://dlmf.nist.gov/19.6.E3 assert nice_and_close(ellippi(n, 0), pi / 2 / (1 - n)**0.5)
def test_values(self, ours, theirs, nargs, x, y, z, p): args = (x, y, z, p)[:nargs] assert nice_and_close(ours(*args), theirs(*args))
def test_legendre_relation(z): # https://dlmf.nist.gov/19.21.E1 assert nice_and_close( elliprf(0, z + 1, z) * elliprd(0, z + 1, 1) + elliprd(0, z + 1, z) * elliprf(0, z + 1, 1), 3 * pi / 2 / z)
def test_elliprj2(y, p): assume(distinct(y, p) and y != 0) assert nice_and_close( elliprj(0, y, y, -p).real, -1.5 * pi / y**0.5 / (y + p))
def test_elliprj1(x, y, p): assume(distinct(y, p)) assert nice_and_close(elliprj(0, y, y, p), 1.5 * pi / (y * p**0.5 + p * y**0.5)) assert nice_and_close(elliprj(x, y, y, p), 3 * (elliprc(x, y) - elliprc(x, p)) / (p - y))
def test_elliprc(x, y, l): assert nice_and_close(elliprc(x, x), x**(-0.5)) assert nice_and_close(elliprc(0, x), pi / 2 / x**0.5) assert nice_and_close(elliprc(l * x, l * y), elliprc(x, y) / l**0.5)
def test_elliprd1(x, y, z): assume(x != y and y != 0 and x != z and x * z != 0) assert nice_and_close(elliprd(x, y, y), 1.5 * (elliprc(x, y) - x**0.5 / y) / (y - x)) assert nice_and_close(elliprd(x, x, z), 3 * (elliprc(z, x) - z**(-0.5)) / (z - x))
def test_elliprd(x, y, z, l): assert nice_and_close(elliprd(x, x, x), x**(-1.5)) assert nice_and_close(elliprd(l * x, l * y, l * z), elliprd(x, y, z) / l**1.5) assert nice_and_close(elliprd(0, y, y), 3 * pi / 4 / y**1.5) assert isinf(elliprd(0, 0, z))
def test_elliprf(x, y, z, l): assert nice_and_close(elliprf(x, x, x), x**(-0.5)) assert nice_and_close(elliprf(0, y, y), pi / 2 / y**0.5) assert nice_and_close(elliprf(l * x, l * y, l * z), elliprf(x, y, z) / l**0.5) assert isinf(elliprf(0, 0, z))