Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement sin_minpoly and tan_minpoly #145

Draft
wants to merge 6 commits into
base: master
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
152 changes: 143 additions & 9 deletions flatsurf/geometry/subfield.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,21 @@
ISSAC 2015. Proceedings of the 2015 ACM International
Symposium on Symbolic and Algebraic Computation.
Pages 259--266.
DOI: http://dx.doi.org/10.1145/2755996.2756664
DOI: https://doi.org/10.1145/2755996.2756664

.. [Ca2008]
Jack S. Calcut
The tangent analogues of the Chebyshev polynomials

.. [WaZe1993]
William Watkins, Joel Zeitlin
The minimal polynomial of cos(2π/n)
The American Mathematical Monthly
Vol. 100, No. 5 (May, 1993)
Pages 471--474.
DOI: https://doi.org/10.2307/2324301
"""

from sage.misc.misc_c import prod
from sage.rings.all import ZZ, QQ, AA, QQbar, NumberField, polygen
from sage.structure.element import parent
Expand All @@ -19,6 +32,7 @@
from sage.categories.homset import Hom
from sage.categories.fields import Fields
from sage.rings.qqbar import do_polred
from sage.rings.number_field.number_field import CyclotomicField


def number_field_elements_from_algebraics(elts, name="a"):
Expand Down Expand Up @@ -301,6 +315,29 @@ def chebyshev_T(n, c):
return T1


def tan_chebyshev_T(n, c):
r"""
Return a pair `(P, Q)`.

EXAMPLES::

sage: from flatsurf.geometry.subfield import tan_chebyshev_T

sage: x = polygen(ZZ)
sage: tan_chebyshev_T(3, x)
(-x^3 + 3*x, -3*x^2 + 1)

sage: P, Q = tan_chebyshev_T(3, tan(pi/7))
sage: bool(P / Q == tan(3*pi/7))
True
"""
P = c
Q = parent(c)(1)
for i in range(n - 1):
P, Q = c * Q + P, Q - c * P
return P, Q


def cos_minpoly_odd_prime(p, var):
r"""
(-1)^k + (-1)^{k-1} T1 + ... + T_k
Expand Down Expand Up @@ -352,14 +389,9 @@ def cos_minpoly(n, var="x"):
x^2 - 2
sage: cos_minpoly(5)
x^2 - x - 1
sage: cos_minpoly(6)
x^2 - 3
sage: cos_minpoly(8)
x^4 - 4*x^2 + 2
sage: cos_minpoly(9)
x^3 - 3*x - 1
sage: cos_minpoly(10)
x^4 - 5*x^2 + 5

sage: all((2 * QQbar.zeta(2*n)).real().minpoly() == cos_minpoly(n) for n in range(1,25))
True

sage: cos_minpoly(90)
x^24 - 24*x^22 + 252*x^20 - 1519*x^18 + 5796*x^16 - 14553*x^14 + 24206*x^12 - 26169*x^10 + 17523*x^8 - 6623*x^6 + 1182*x^4 - 72*x^2 + 1
Expand Down Expand Up @@ -400,3 +432,105 @@ def cos_minpoly(n, var="x"):
M = M(chebyshev_T(nn, var))

return M


def sin_minpoly(n, var="x"):
r"""
Return the minimal polynomial of 2 cos pi/n

EXAMPLES::

sage: from flatsurf.geometry.subfield import sin_minpoly

sage: sin_minpoly(1)
x
sage: sin_minpoly(2)
x - 2
sage: sin_minpoly(3)
x^2 - 3
sage: sin_minpoly(4)
x^2 - 2

sage: all((2 * QQbar.zeta(2*n)).imag().minpoly() == sin_minpoly(n) for n in range(1,25))
True
"""
n = ZZ(n)
# use sin(π/n) = cos((n-2)π/(2n))
if n % 2:
return cos_minpoly(2 * n)
elif n % 4 == 2:
# n = 4k+2
# (n-2)/(2n) = k/(2k+1)
p = cos_minpoly(n // 2)
if n % 8 == 2:
P = p.parent()
d = p.degree()
return P([(-1) ** (i + d) * c for i, c in enumerate(p)])
else:
return p
else:
return cos_minpoly(n)


def tan_minpoly(n):
r"""
Return the minimal polynomial of tan pi/n

EXAMPLES::

sage: from flatsurf.geometry.subfield import tan_minpoly

sage: tan_minpoly(3)
x^2 - 3
sage: tan_minpoly(4)
x - 1
sage: tan_minpoly(5)
x^4 - 10*x^2 + 5
sage: tan_minpoly(6)
x^2 - 1/3

sage: all((QQbar.zeta(2*n).imag() / QQbar.zeta(2*n).real()).minpoly() == tan_minpoly(n) for n in range(3,15))
True
"""
N = 2 * n
while N % 4:
N *= 2
K = CyclotomicField(N)
z = K.gen() ** (N // (2 * n))
I = K.gen() ** (N // 4)

sin = (z - z.conjugate()) / I
cos = z + z.conjugate()
return (sin / cos).minpoly()


def atan_minpoly(n):
r"""
Return the minimal polynomial of tan pi/n

EXAMPLES::

sage: from flatsurf.geometry.subfield import atan_minpoly

sage: atan_minpoly(3)
x^2 - 1/3
sage: atan_minpoly(4)
x - 1
sage: atan_minpoly(5)
x^4 - 2*x^2 + 1/5
sage: atan_minpoly(6)
x^2 - 3

sage: all((QQbar.zeta(2*n).real() / QQbar.zeta(2*n).imag()).minpoly() == atan_minpoly(n) for n in range(3,15))
True
"""
N = 2 * n
while N % 4:
N *= 2
K = CyclotomicField(N)
z = K.gen() ** (N // (2 * n))
I = K.gen() ** (N // 4)

sin = (z - z.conjugate()) / I
cos = z + z.conjugate()
return (cos / sin).minpoly()