# Path: abelfunctions/integralbasis.py
# def integral_basis(f):
#     r"""Returns the integral basis of the algebraic function field of `f`.
# 
#     An integral basis for the algebraic function field :math:`O(X)` is a
#     set of :math:`\beta_i \in \mathbb{C}(x,y)` such that
# 
#     .. math::
# 
#         \overline{O(X)} = \beta_1 \mathbb{C}[x,y] + \cdots + \beta_g
#         \mathbb{C}[x,y].
# 
#     Parameters
#     ----------
#     f : sympy.Expr
#     x : sympy.Symbol
#     y : sympy.Symbol
# 
#     Returns
#     -------
#     list, sympy.Expr
#         A list of rational functions representing an integral basis.
# 
#     """
#     R = f.parent()
#     x,y = R.gens()
# 
#     # The base algorithm assumes f is monic. If this is not the case then
#     # monicize by applying the map `y -> y/lc(x), f -> lc^(d-1) f` where lc(x)
#     # is the leading coefficient of f.
#     d  = f.degree(y)
#     lc = f.polynomial(y).leading_coefficient()
#     if lc.degree() > 0:
#         # we have to carefully manage rings here. the path is:
#         #     R(x)[y] -> R[x][y] -> R[x,y]
#         fmonic = f(x,y/lc)*lc**(d-1) # element of R(x)[y]
#         B = R.base_ring()
#         fmonic = fmonic.change_ring(B[x])  # element of R[x][y]
#         fmonic = R(fmonic)  # element of R[x,y]
#     else:
#         fmonic = f/R.base_ring()(lc)
#         lc = 1
# 
#     # if the curve lives in QQ[x,y] then use singular. otherwise, use slow
#     # self-implemented version
#     try:
#         fmonic = fmonic.change_ring(QQ)
#     except:
#         warnings.warn('using slower integral basis algorithm: '
#                       'cannot coerce curve %s to QQ[%s,%s]'%(fmonic,x,y))
#         b = _integral_basis_monic(fmonic)
#     else:
#         b = _integral_basis_monic_singular(fmonic)
# 
#     # reverse leading coefficient scaling
#     for i in range(1,len(b)):
#         b[i] = b[i](x,lc*y)
#     return b
# 
# Path: abelfunctions/tests/test_abelfunctions.py
# class AbelfunctionsTestCase(unittest.TestCase):
#     def setUp(self):
#         R = QQ['x,y']
#         x,y = R.gens()
#         self.f1 = (x**2 - x + 1)*y**2 - 2*x**2*y + x**4
#         self.f2 = -x**7 + 2*x**3*y + y**3
#         self.f3 = (y**2-x**2)*(x-1)*(2*x-3) - 4*(x**2+y**2-2*x)**2
#         self.f4 = y**2 + x**3 - x**2
#         self.f5 = (x**2 + y**2)**3 + 3*x**2*y - y**3
#         self.f6 = y**4 - y**2*x + x**2
#         self.f7 = y**3 - (x**3 + y)**2 + 1
#         self.f8 = x**2*y**6 + 2*x**3*y**5 - 1
#         self.f9 = 2*x**7*y + 2*x**7 + y**3 + 3*y**2 + 3*y
#         self.f10 = (x**3)*y**4 + 4*x**2*y**2 + 2*x**3*y - 1
# 
#         # various classifications
#         self.f = [self.f1, self.f2, self.f3, self.f4, self.f5,
#                   self.f6, self.f7, self.f8, self.f9, self.f10]
#         self.monicf = [self.f2, self.f4, self.f5, self.f6, self.f7, self.f9]
#         self.nonmonicf = [self.f1, self.f3, self.f8, self.f10]
# 
#     @classmethod
#     def setUpClass(cls):
#         R = QQ['x,y']
#         x,y = R.gens()
# 
#         cls.f2 = -x**7 + 2*x**3*y + y**3
#         cls.X2 = RiemannSurface(cls.f2)
# 
#         cls.f11 = x**2*y**3 - x**4 + 1
#         cls.X11 = RiemannSurface(cls.f11)
# 
#         cls.f12 = x**2*y**3 - y*x**4 + 1
#         cls.X12 = RiemannSurface(cls.f12)


import unittest
from abelfunctions.integralbasis import integral_basis
from abelfunctions.tests.test_abelfunctions import AbelfunctionsTestCase
from sage.all import SR
from sage.rings.big_oh import O
from sage.rings.laurent_series_ring import LaurentSeriesRing
from sage.rings.rational_field import QQ
from sage.rings.qqbar import QQbar
        a = integral_basis(self.f9)
        b = [1, y, y**2]
        self.assertEqual(a,b)

    def test_f10(self):
        x,y = self.f10.parent().gens()
        a = integral_basis(self.f10)
        b = [1, x*y, x**2*y**2, x**3*y**3]
        self.assertEqual(a,b)

    def test_rcvexample(self):
        R = QQ['x,y']
        x,y = R.gens()
        f = x**2*y**3 - x**4 + 1
        a = integral_basis(f)
        b = [1, x*y, x**2*y**2]
        self.assertEqual(a,b)

    def test_rcvexample_monicized(self):
        R = QQ['x,y']
        x,y = R.gens()
        f = y**3 - x**8 + x**4
        a = integral_basis(f)
        b = [1, y/x, y**2/x**2]
        self.assertEqual(a,b)

    def test_issue86(self):
        R = QQ['x,z']
        x,z = R.gens()
        f = -x**7 + 2*x*z**5 + z**4

# Path: abelfunctions/integralbasis.py
# def integral_basis(f):
#     r"""Returns the integral basis of the algebraic function field of `f`.
# 
#     An integral basis for the algebraic function field :math:`O(X)` is a
#     set of :math:`\beta_i \in \mathbb{C}(x,y)` such that
# 
#     .. math::
# 
#         \overline{O(X)} = \beta_1 \mathbb{C}[x,y] + \cdots + \beta_g
#         \mathbb{C}[x,y].
# 
#     Parameters
#     ----------
#     f : sympy.Expr
#     x : sympy.Symbol
#     y : sympy.Symbol
# 
#     Returns
#     -------
#     list, sympy.Expr
#         A list of rational functions representing an integral basis.
# 
#     """
#     R = f.parent()
#     x,y = R.gens()
# 
#     # The base algorithm assumes f is monic. If this is not the case then
#     # monicize by applying the map `y -> y/lc(x), f -> lc^(d-1) f` where lc(x)
#     # is the leading coefficient of f.
#     d  = f.degree(y)
#     lc = f.polynomial(y).leading_coefficient()
#     if lc.degree() > 0:
#         # we have to carefully manage rings here. the path is:
#         #     R(x)[y] -> R[x][y] -> R[x,y]
#         fmonic = f(x,y/lc)*lc**(d-1) # element of R(x)[y]
#         B = R.base_ring()
#         fmonic = fmonic.change_ring(B[x])  # element of R[x][y]
#         fmonic = R(fmonic)  # element of R[x,y]
#     else:
#         fmonic = f/R.base_ring()(lc)
#         lc = 1
# 
#     # if the curve lives in QQ[x,y] then use singular. otherwise, use slow
#     # self-implemented version
#     try:
#         fmonic = fmonic.change_ring(QQ)
#     except:
#         warnings.warn('using slower integral basis algorithm: '
#                       'cannot coerce curve %s to QQ[%s,%s]'%(fmonic,x,y))
#         b = _integral_basis_monic(fmonic)
#     else:
#         b = _integral_basis_monic_singular(fmonic)
# 
#     # reverse leading coefficient scaling
#     for i in range(1,len(b)):
#         b[i] = b[i](x,lc*y)
#     return b
# 
# Path: abelfunctions/tests/test_abelfunctions.py
# class AbelfunctionsTestCase(unittest.TestCase):
#     def setUp(self):
#         R = QQ['x,y']
#         x,y = R.gens()
#         self.f1 = (x**2 - x + 1)*y**2 - 2*x**2*y + x**4
#         self.f2 = -x**7 + 2*x**3*y + y**3
#         self.f3 = (y**2-x**2)*(x-1)*(2*x-3) - 4*(x**2+y**2-2*x)**2
#         self.f4 = y**2 + x**3 - x**2
#         self.f5 = (x**2 + y**2)**3 + 3*x**2*y - y**3
#         self.f6 = y**4 - y**2*x + x**2
#         self.f7 = y**3 - (x**3 + y)**2 + 1
#         self.f8 = x**2*y**6 + 2*x**3*y**5 - 1
#         self.f9 = 2*x**7*y + 2*x**7 + y**3 + 3*y**2 + 3*y
#         self.f10 = (x**3)*y**4 + 4*x**2*y**2 + 2*x**3*y - 1
# 
#         # various classifications
#         self.f = [self.f1, self.f2, self.f3, self.f4, self.f5,
#                   self.f6, self.f7, self.f8, self.f9, self.f10]
#         self.monicf = [self.f2, self.f4, self.f5, self.f6, self.f7, self.f9]
#         self.nonmonicf = [self.f1, self.f3, self.f8, self.f10]
# 
#     @classmethod
#     def setUpClass(cls):
#         R = QQ['x,y']
#         x,y = R.gens()
# 
#         cls.f2 = -x**7 + 2*x**3*y + y**3
#         cls.X2 = RiemannSurface(cls.f2)
# 
#         cls.f11 = x**2*y**3 - x**4 + 1
#         cls.X11 = RiemannSurface(cls.f11)
# 
#         cls.f12 = x**2*y**3 - y*x**4 + 1
#         cls.X12 = RiemannSurface(cls.f12)


# Path: abelfunctions/tests/test_integralbasis.py
import unittest
from abelfunctions.integralbasis import integral_basis
from abelfunctions.tests.test_abelfunctions import AbelfunctionsTestCase
from sage.all import SR
from sage.rings.big_oh import O
from sage.rings.laurent_series_ring import LaurentSeriesRing
from sage.rings.rational_field import QQ
from sage.rings.qqbar import QQbar

        a = integral_basis(self.f9)
        b = [1, y, y**2]
        self.assertEqual(a,b)

    def test_f10(self):
        x,y = self.f10.parent().gens()
        a = integral_basis(self.f10)
        b = [1, x*y, x**2*y**2, x**3*y**3]
        self.assertEqual(a,b)

    def test_rcvexample(self):
        R = QQ['x,y']
        x,y = R.gens()
        f = x**2*y**3 - x**4 + 1
        a = integral_basis(f)
        b = [1, x*y, x**2*y**2]
        self.assertEqual(a,b)

    def test_rcvexample_monicized(self):
        R = QQ['x,y']
        x,y = R.gens()
        f = y**3 - x**8 + x**4
        a = integral_basis(f)
        b = [1, y/x, y**2/x**2]
        self.assertEqual(a,b)

    def test_issue86(self):
        R = QQ['x,z']
        x,z = R.gens()
        f = -x**7 + 2*x*z**5 + z**4

        a = integral_basis(f)