# Path: abelfunctions/puiseux.py
# def puiseux(f, alpha, beta=None, order=None, parametric=True):
#     r"""Singular parts of the Puiseux series above :math:`x=\alpha`.
# 
#     Parameters
#     ----------
#     f : polynomial
#         A plane algebraic curve in `x` and `y`.
#     alpha : complex
#         The x-point over which to compute the Puiseux series of `f`.
#     t : variable
#         Variable used in the Puiseux series expansions.
#     beta : complex
#         (Optional) The y-point at which to compute the Puiseux series.
#     order : int
#         (Default: `None`) If provided, returns Puiseux series expansions
#         up the the specified order.
# 
#     Returns
#     -------
#     list of PuiseuxTSeries
# 
#     """
#     R = f.parent()
#     x,y = R.gens()
# 
#     # recenter the curve at x=alpha
#     if alpha in [infinity,'oo']:
#         alpha = infinity
#         d = f.degree(x)
#         F = f(1/x,y)*x**d
#         n,d = F.numerator(), F.denominator()
#         falpha,_ = n.polynomial(x).quo_rem(d.univariate_polynomial())
#         falpha = falpha(x).numerator()
#     else:
#         falpha = f(x+alpha,y)
# 
#     # determine the points on the curve lying above x=alpha
#     R = falpha.parent()
#     x,y = R.gens()
#     g, transform = almost_monicize(falpha)
#     galpha = R(g(0,y)).univariate_polynomial()
#     betas = galpha.roots(ring=QQbar, multiplicities=False)
# 
#     # filter for requested value of beta. raise error if not found
#     if not beta is None:
#         betas = [b for b in betas if b == beta]
#         if not betas:
#             raise ValueError('The point ({0}, {1}) is not on the '
#                              'curve {2}.'.format(alpha, beta, f))
# 
#     # for each (alpha, beta) determine the corresponding singular parts of the
#     # Puiseux series expansions. note that there may be multiple, distinct
#     # places above the same point.
#     singular_parts = []
#     for beta in betas:
#         H = g(x,y+beta)
#         singular_part_ab = puiseux_rational(H)
# 
#         # recenter the result back to (alpha, beta) from (0,0)
#         for G,P,Q in singular_part_ab:
#             Q += beta
#             Q = Q/transform.univariate_polynomial()(P)
#             if alpha == infinity:
#                 P = 1/P
#             else:
#                 P += alpha
# 
#             # append to list of singular data
#             singular_parts.append((G,P,Q))
# 
#     # instantiate PuiseuxTSeries from the singular data
#     series = [PuiseuxTSeries(f, alpha, singular_data, order=order)
#               for singular_data in singular_parts]
#     return series
# 
# Path: abelfunctions/integralbasis.py
# def Int(i, px):
#     r"""Computes :math:`Int_i = \sum_{k \neq i} v(p_i-p_k)`.
# 
#     ``Int`` is used in :func:`compute_expansion_bounds` for determining
#     sufficient bounds on Puiseux series expansions.
# 
#     Parameters
#     ----------
#     i : int
#         Index of the Puiseux series in the list, `px`, to compute `Int` of.
#     p : list, PuiseuxXSeries
#         A list of :class:`PuiseuxXSeries`.
# 
#     Returns
#     -------
#     val : rational
#        The `Int` of the `i`th element of `px`.
# 
#     """
#     n = len(px)
#     pxi = px[i]
#     val = QQ(0)
#     for k in range(n):
#         if k != i:
#             val += (pxi-px[k]).valuation()
#     return val


from abelfunctions.puiseux import puiseux
from abelfunctions.integralbasis import Int
from sage.misc.cachefunc import cached_function
from sage.rings.integer_ring import ZZ
from sage.rings.qqbar import QQbar
from sage.rings.rational_field import QQ
r"""Singularities :mod:`abelfunctions.singularities`
================================================

A module for computing the singular points of a complex plane algebraic curve
including their multiplicities, branching numbers, multiplicities, and delta
invariants.

Each singularity :math:`P = (x,y,z)` on the projectivization of the curve has
associated with it a three-tuple :math:`(m, \delta, r)` representing the
multiplicity, delta invariant, and branching number of the multiplicity.

Functions
---------

singularities

Examples

# Path: abelfunctions/puiseux.py
# def puiseux(f, alpha, beta=None, order=None, parametric=True):
#     r"""Singular parts of the Puiseux series above :math:`x=\alpha`.
# 
#     Parameters
#     ----------
#     f : polynomial
#         A plane algebraic curve in `x` and `y`.
#     alpha : complex
#         The x-point over which to compute the Puiseux series of `f`.
#     t : variable
#         Variable used in the Puiseux series expansions.
#     beta : complex
#         (Optional) The y-point at which to compute the Puiseux series.
#     order : int
#         (Default: `None`) If provided, returns Puiseux series expansions
#         up the the specified order.
# 
#     Returns
#     -------
#     list of PuiseuxTSeries
# 
#     """
#     R = f.parent()
#     x,y = R.gens()
# 
#     # recenter the curve at x=alpha
#     if alpha in [infinity,'oo']:
#         alpha = infinity
#         d = f.degree(x)
#         F = f(1/x,y)*x**d
#         n,d = F.numerator(), F.denominator()
#         falpha,_ = n.polynomial(x).quo_rem(d.univariate_polynomial())
#         falpha = falpha(x).numerator()
#     else:
#         falpha = f(x+alpha,y)
# 
#     # determine the points on the curve lying above x=alpha
#     R = falpha.parent()
#     x,y = R.gens()
#     g, transform = almost_monicize(falpha)
#     galpha = R(g(0,y)).univariate_polynomial()
#     betas = galpha.roots(ring=QQbar, multiplicities=False)
# 
#     # filter for requested value of beta. raise error if not found
#     if not beta is None:
#         betas = [b for b in betas if b == beta]
#         if not betas:
#             raise ValueError('The point ({0}, {1}) is not on the '
#                              'curve {2}.'.format(alpha, beta, f))
# 
#     # for each (alpha, beta) determine the corresponding singular parts of the
#     # Puiseux series expansions. note that there may be multiple, distinct
#     # places above the same point.
#     singular_parts = []
#     for beta in betas:
#         H = g(x,y+beta)
#         singular_part_ab = puiseux_rational(H)
# 
#         # recenter the result back to (alpha, beta) from (0,0)
#         for G,P,Q in singular_part_ab:
#             Q += beta
#             Q = Q/transform.univariate_polynomial()(P)
#             if alpha == infinity:
#                 P = 1/P
#             else:
#                 P += alpha
# 
#             # append to list of singular data
#             singular_parts.append((G,P,Q))
# 
#     # instantiate PuiseuxTSeries from the singular data
#     series = [PuiseuxTSeries(f, alpha, singular_data, order=order)
#               for singular_data in singular_parts]
#     return series
# 
# Path: abelfunctions/integralbasis.py
# def Int(i, px):
#     r"""Computes :math:`Int_i = \sum_{k \neq i} v(p_i-p_k)`.
# 
#     ``Int`` is used in :func:`compute_expansion_bounds` for determining
#     sufficient bounds on Puiseux series expansions.
# 
#     Parameters
#     ----------
#     i : int
#         Index of the Puiseux series in the list, `px`, to compute `Int` of.
#     p : list, PuiseuxXSeries
#         A list of :class:`PuiseuxXSeries`.
# 
#     Returns
#     -------
#     val : rational
#        The `Int` of the `i`th element of `px`.
# 
#     """
#     n = len(px)
#     pxi = px[i]
#     val = QQ(0)
#     for k in range(n):
#         if k != i:
#             val += (pxi-px[k]).valuation()
#     return val


# Path: abelfunctions/singularities.py
from abelfunctions.puiseux import puiseux
from abelfunctions.integralbasis import Int
from sage.misc.cachefunc import cached_function
from sage.rings.integer_ring import ZZ
from sage.rings.qqbar import QQbar
from sage.rings.rational_field import QQ

r"""Singularities :mod:`abelfunctions.singularities`
================================================

A module for computing the singular points of a complex plane algebraic curve
including their multiplicities, branching numbers, multiplicities, and delta
invariants.

Each singularity :math:`P = (x,y,z)` on the projectivization of the curve has
associated with it a three-tuple :math:`(m, \delta, r)` representing the
multiplicity, delta invariant, and branching number of the multiplicity.

Functions
---------

singularities

Examples

--------