Exemplo n.º 1
0
def BezoutianQuadraticForm(f, g):
    r"""
    Compute the Bezoutian of two polynomials defined over a common base ring.  This is defined by

    .. MATH::

        {\rm Bez}(f, g) := \frac{f(x) g(y) - f(y) g(x)}{y - x}

    and has size defined by the maximum of the degrees of `f` and `g`.

    INPUT:

    - `f`, `g` -- polynomials in `R[x]`, for some ring `R`

    OUTPUT:

    a quadratic form over `R`

    EXAMPLES::

        sage: R = PolynomialRing(ZZ, 'x')
        sage: f = R([1,2,3])
        sage: g = R([2,5])
        sage: Q = BezoutianQuadraticForm(f, g) ; Q
        Quadratic form in 2 variables over Integer Ring with coefficients:
        [ 1 -12 ]
        [ * -15 ]

    AUTHORS:

    - Fernando Rodriguez-Villegas, Jonathan Hanke -- added on 11/9/2008

    """
    ## Check that f and g are polynomials with a common base ring
    if not is_Polynomial(f) or not is_Polynomial(g):
        raise TypeError("Oops!  One of your inputs is not a polynomial. =(")
    if f.base_ring() != g.base_ring(
    ):  ## TO DO:  Change this to allow coercion!
        raise TypeError(
            "Oops!  These polynomials are not defined over the same coefficient ring."
        )

    ## Initialize the quadratic form
    R = f.base_ring()
    P = PolynomialRing(R, ['x', 'y'])
    a, b = P.gens()
    n = max(f.degree(), g.degree())
    Q = QuadraticForm(R, n)

    ## Set the coefficients of Bezoutian
    bez_poly = (f(a) * g(b) - f(b) * g(a)) // (
        b - a)  ## Truncated (exact) division here
    for i in range(n):
        for j in range(i, n):
            if i == j:
                Q[i, j] = bez_poly.coefficient({a: i, b: j})
            else:
                Q[i, j] = bez_poly.coefficient({a: i, b: j}) * 2

    return Q
Exemplo n.º 2
0
def BezoutianQuadraticForm(f, g):
    r"""
    Compute the Bezoutian of two polynomials defined over a common base ring.  This is defined by

    .. MATH::

        {\rm Bez}(f, g) := \frac{f(x) g(y) - f(y) g(x)}{y - x}

    and has size defined by the maximum of the degrees of `f` and `g`.

    INPUT:

    - `f`, `g` -- polynomials in `R[x]`, for some ring `R`

    OUTPUT:

    a quadratic form over `R`

    EXAMPLES::

        sage: R = PolynomialRing(ZZ, 'x')
        sage: f = R([1,2,3])
        sage: g = R([2,5])
        sage: Q = BezoutianQuadraticForm(f, g) ; Q
        Quadratic form in 2 variables over Integer Ring with coefficients:
        [ 1 -12 ]
        [ * -15 ]

    AUTHORS:

    - Fernando Rodriguez-Villegas, Jonathan Hanke -- added on 11/9/2008

    """
    ## Check that f and g are polynomials with a common base ring
    if not is_Polynomial(f) or not is_Polynomial(g):
        raise TypeError("Oops!  One of your inputs is not a polynomial. =(")
    if f.base_ring() != g.base_ring():                   ## TO DO:  Change this to allow coercion!
        raise TypeError("Oops!  These polynomials are not defined over the same coefficient ring.")

    ## Initialize the quadratic form
    R = f.base_ring()
    P = PolynomialRing(R, ['x','y'])
    a, b = P.gens()
    n = max(f.degree(), g.degree())
    Q = QuadraticForm(R, n)

    ## Set the coefficients of Bezoutian
    bez_poly = (f(a) * g(b) - f(b) * g(a)) // (b - a)    ## Truncated (exact) division here
    for i in range(n):
        for j in range(i, n):
            if i == j:
                Q[i,j] = bez_poly.coefficient({a:i,b:j})
            else:
                Q[i,j] = bez_poly.coefficient({a:i,b:j}) * 2

    return Q
Exemplo n.º 3
0
    def __call__(self, v):
        """
        Apply the affine transformation to ``v``.

        INPUT:

        - ``v`` -- a multivariate polynomial, a vector, or anything
          that can be converted into a vector.

        OUTPUT:

        The image of ``v`` under the affine group element.

        EXAMPLES::

            sage: G = AffineGroup(2, QQ)
            sage: g = G([0,1,-1,0],[2,3]);  g
                  [ 0  1]     [2]
            x |-> [-1  0] x + [3]
            sage: v = vector([4,5])
            sage: g(v)
            (7, -1)

            sage: R.<x,y> = QQ[]
            sage: g(x), g(y)
            (y + 2, -x + 3)
            sage: p = x^2 + 2*x*y + y + 1
            sage: g(p)
            -2*x*y + y^2 - 5*x + 10*y + 20

        The action on polynomials is such that it intertwines with
        evaluation. That is::

            sage: p(*g(v)) == g(p)(*v)
            True

        Test that the univariate polynomial ring is covered::

            sage: H = AffineGroup(1, QQ)
            sage: h = H([2],[3]);  h
            x |-> [2] x + [3]
            sage: R.<z> = QQ[]
            sage: h(z+1)
            3*z + 2
        """
        from sage.rings.polynomial.polynomial_element import is_Polynomial
        from sage.rings.polynomial.multi_polynomial import is_MPolynomial

        parent = self.parent()
        if is_Polynomial(v) and parent.degree() == 1:
            ring = v.parent()
            return ring([self._A[0, 0], self._b[0]])
        if is_MPolynomial(v) and parent.degree() == v.parent().ngens():
            ring = v.parent()
            from sage.modules.all import vector

            image_coords = self._A * vector(ring, ring.gens()) + self._b
            return v(*image_coords)
        v = parent.vector_space()(v)
        return self._A * v + self._b
Exemplo n.º 4
0
    def __init__(self, spec, m=None):
        if is_Polynomial(spec):
            poly = spec
            assert len(poly.variables()) == 1

            fld = poly.base_ring()
            if m is None:
                m = ZZ(fld.order() - 1).nbits()
            spec = [
                poly.subs(fld.fetch_int(x)).integer_representation()
                for x in range(len(fld))
            ]

        self._S = tuple(map(int, spec))
        self.n = ZZ(len(self._S) - 1).nbits()
        self.m = ZZ(max(self._S)).nbits()
        if m is not None:
            m = int(m)
            lim = 1 << self.m
            assert all(0 <= y < lim for y in self._S)
        else:
            m = ZZ(max(self._S)).nbits()
        self.m = m
        assert self.input_size() >= 1
        assert self.output_size() >= 0
Exemplo n.º 5
0
    def __call__(self, v):
        """
        Apply the affine transformation to ``v``.

        INPUT:

        - ``v`` -- a multivariate polynomial, a vector, or anything
          that can be converted into a vector.

        OUTPUT:

        The image of ``v`` under the affine group element.

        EXAMPLES::

            sage: G = AffineGroup(2, QQ)
            sage: g = G([0,1,-1,0],[2,3]);  g
                  [ 0  1]     [2]
            x |-> [-1  0] x + [3]
            sage: v = vector([4,5])
            sage: g(v)
            (7, -1)

            sage: R.<x,y> = QQ[]
            sage: g(x), g(y)
            (y + 2, -x + 3)
            sage: p = x^2 + 2*x*y + y + 1
            sage: g(p)
            -2*x*y + y^2 - 5*x + 10*y + 20

        The action on polynomials is such that it intertwines with
        evaluation. That is::

            sage: p(*g(v)) == g(p)(*v)
            True

        Test that the univariate polynomial ring is covered::

            sage: H = AffineGroup(1, QQ)
            sage: h = H([2],[3]);  h
            x |-> [2] x + [3]
            sage: R.<z> = QQ[]
            sage: h(z+1)
            3*z + 2
        """
        from sage.rings.polynomial.polynomial_element import is_Polynomial
        from sage.rings.polynomial.multi_polynomial import is_MPolynomial
        parent = self.parent()
        if is_Polynomial(v) and parent.degree() == 1:
            ring = v.parent()
            return ring([self._A[0, 0], self._b[0]])
        if is_MPolynomial(v) and parent.degree() == v.parent().ngens():
            ring = v.parent()
            from sage.modules.all import vector
            image_coords = self._A * vector(ring, ring.gens()) + self._b
            return v(*image_coords)
        v = parent.vector_space()(v)
        return self._A * v + self._b
Exemplo n.º 6
0
    def __init__(self, q, names="a", modulus=None, repr="poly"):
        """
        Initialize ``self``.

        TESTS::

            sage: k.<a> = GF(2^100, modulus='strangeinput')
            Traceback (most recent call last):
            ...
            ValueError: no such algorithm for finding an irreducible polynomial: strangeinput
            sage: k.<a> = GF(2^20) ; type(k)
            <class 'sage.rings.finite_rings.finite_field_ntl_gf2e.FiniteField_ntl_gf2e_with_category'>
            sage: loads(dumps(k)) is k
            True
            sage: k1.<a> = GF(2^16)
            sage: k2.<a> = GF(2^17)
            sage: k1 == k2
            False
            sage: k3.<a> = GF(2^16, impl="pari_ffelt")
            sage: k1 == k3
            False

            sage: TestSuite(k).run()

            sage: k.<a> = GF(2^64)
            sage: k._repr_option('element_is_atomic')
            False
            sage: P.<x> = PolynomialRing(k)
            sage: (a+1)*x # indirect doctest
            (a + 1)*x
        """
        late_import()
        q = Integer(q)
        if q < 2:
            raise ValueError("q must be a 2-power")
        k = q.exact_log(2)
        if q != 1 << k:
            raise ValueError("q must be a 2-power")
        FiniteField.__init__(self, GF2, names, normalize=True)

        self._kwargs = {'repr': repr}

        from sage.rings.polynomial.polynomial_element import is_Polynomial
        if not is_Polynomial(modulus):
            from sage.misc.superseded import deprecation
            deprecation(
                16983,
                "constructing a FiniteField_ntl_gf2e without giving a polynomial as modulus is deprecated, use the more general FiniteField constructor instead"
            )
            R = GF2['x']
            if modulus is None or isinstance(modulus, str):
                modulus = R.irreducible_element(k, algorithm=modulus)
            else:
                modulus = R(modulus)

        self._cache = Cache_ntl_gf2e(self, k, modulus)
        self._modulus = modulus
Exemplo n.º 7
0
    def __init__(self, q, name="a", modulus=None, repr="poly", cache=False):
        """
        Initialize ``self``.

        EXAMPLES::

            sage: k.<a> = GF(2^3)
            sage: j.<b> = GF(3^4)
            sage: k == j
            False

            sage: GF(2^3,'a') == copy(GF(2^3,'a'))
            True
            sage: TestSuite(GF(2^3, 'a')).run()
        """
        self._kwargs = {}

        if repr not in ['int', 'log', 'poly']:
            raise ValueError("Unknown representation %s" % repr)

        q = Integer(q)
        if q < 2:
            raise ValueError("q  must be a prime power")
        F = q.factor()
        if len(F) > 1:
            raise ValueError("q must be a prime power")
        p = F[0][0]
        k = F[0][1]

        if q >= 1 << 16:
            raise ValueError("q must be < 2^16")

        import constructor
        FiniteField.__init__(self,
                             constructor.FiniteField(p),
                             name,
                             normalize=False)

        self._kwargs['repr'] = repr
        self._kwargs['cache'] = cache

        if modulus is None or modulus == 'conway':
            if k == 1:
                modulus = 'random'  # this will use the gfq_factory_pk function.
            elif ConwayPolynomials().has_polynomial(p, k):
                from sage.rings.finite_rings.conway_polynomials import conway_polynomial
                modulus = conway_polynomial(p, k)
            elif modulus is None:
                modulus = 'random'
            else:
                raise ValueError("Conway polynomial not found")

        from sage.rings.polynomial.polynomial_element import is_Polynomial
        if is_Polynomial(modulus):
            modulus = modulus.list()

        self._cache = Cache_givaro(self, p, k, modulus, repr, cache)
Exemplo n.º 8
0
    def __init__(self, q, name="a", modulus=None, repr="poly", cache=False):
        """
        Initialize ``self``.

        EXAMPLES::

            sage: k.<a> = GF(2^3)
            sage: j.<b> = GF(3^4)
            sage: k == j
            False

            sage: GF(2^3,'a') == copy(GF(2^3,'a'))
            True
            sage: TestSuite(GF(2^3, 'a')).run()
        """
        self._kwargs = {}

        if repr not in ["int", "log", "poly"]:
            raise ValueError("Unknown representation %s" % repr)

        q = Integer(q)
        if q < 2:
            raise ValueError("q must be a prime power")
        F = q.factor()
        if len(F) > 1:
            raise ValueError("q must be a prime power")
        p = F[0][0]
        k = F[0][1]

        if q >= 1 << 16:
            raise ValueError("q must be < 2^16")

        from .finite_field_constructor import GF

        FiniteField.__init__(self, GF(p), name, normalize=False)

        self._kwargs["repr"] = repr
        self._kwargs["cache"] = cache

        from sage.rings.polynomial.polynomial_element import is_Polynomial

        if not is_Polynomial(modulus):
            from sage.misc.superseded import deprecation

            deprecation(
                16930,
                "constructing a FiniteField_givaro without giving a polynomial as modulus is deprecated, use the more general FiniteField constructor instead",
            )
            R = GF(p)["x"]
            if modulus is None or isinstance(modulus, str):
                modulus = R.irreducible_element(k, algorithm=modulus)
            else:
                modulus = R(modulus)

        self._cache = Cache_givaro(self, p, k, modulus, repr, cache)
        self._modulus = modulus
Exemplo n.º 9
0
    def __init__(self, q, name="a",  modulus=None, repr="poly", cache=False):
        """
        Initialize ``self``.

        EXAMPLES::

            sage: k.<a> = GF(2^3)
            sage: j.<b> = GF(3^4)
            sage: k == j
            False

            sage: GF(2^3,'a') == copy(GF(2^3,'a'))
            True
            sage: TestSuite(GF(2^3, 'a')).run()
        """
        self._kwargs = {}

        if repr not in ['int', 'log', 'poly']:
            raise ValueError("Unknown representation %s"%repr)

        q = Integer(q)
        if q < 2:
            raise ValueError("q  must be a prime power")
        F = q.factor()
        if len(F) > 1:
            raise ValueError("q must be a prime power")
        p = F[0][0]
        k = F[0][1]

        if q >= 1<<16:
            raise ValueError("q must be < 2^16")

        import constructor
        FiniteField.__init__(self, constructor.FiniteField(p), name, normalize=False)

        self._kwargs['repr'] = repr
        self._kwargs['cache'] = cache

        if modulus is None or modulus == 'conway':
            if k == 1:
                modulus = 'random' # this will use the gfq_factory_pk function.
            elif ConwayPolynomials().has_polynomial(p, k):
                from sage.rings.finite_rings.conway_polynomials import conway_polynomial
                modulus = conway_polynomial(p, k)
            elif modulus is None:
                modulus = 'random'
            else:
                raise ValueError("Conway polynomial not found")

        from sage.rings.polynomial.polynomial_element import is_Polynomial
        if is_Polynomial(modulus):
            modulus = modulus.list()

        self._cache = Cache_givaro(self, p, k, modulus, repr, cache)
Exemplo n.º 10
0
    def __init__(self, q, names="a", modulus=None, repr="poly"):
        """
        Initialize ``self``.

        TESTS::

            sage: k.<a> = GF(2^100, modulus='strangeinput')
            Traceback (most recent call last):
            ...
            ValueError: no such algorithm for finding an irreducible polynomial: strangeinput
            sage: k.<a> = GF(2^20) ; type(k)
            <class 'sage.rings.finite_rings.finite_field_ntl_gf2e.FiniteField_ntl_gf2e_with_category'>
            sage: loads(dumps(k)) is k
            True
            sage: k1.<a> = GF(2^16)
            sage: k2.<a> = GF(2^17)
            sage: k1 == k2
            False
            sage: k3.<a> = GF(2^16, impl="pari_ffelt")
            sage: k1 == k3
            False

            sage: TestSuite(k).run()

            sage: k.<a> = GF(2^64)
            sage: k._repr_option('element_is_atomic')
            False
            sage: P.<x> = PolynomialRing(k)
            sage: (a+1)*x # indirect doctest
            (a + 1)*x
        """
        late_import()
        q = Integer(q)
        if q < 2:
            raise ValueError("q must be a 2-power")
        k = q.exact_log(2)
        if q != 1 << k:
            raise ValueError("q must be a 2-power")
        FiniteField.__init__(self, GF2, names, normalize=True)

        self._kwargs = {'repr':repr}

        from sage.rings.polynomial.polynomial_element import is_Polynomial
        if not is_Polynomial(modulus):
            from sage.misc.superseded import deprecation
            deprecation(16983, "constructing a FiniteField_ntl_gf2e without giving a polynomial as modulus is deprecated, use the more general FiniteField constructor instead")
            R = GF2['x']
            if modulus is None or isinstance(modulus, str):
                modulus = R.irreducible_element(k, algorithm=modulus)
            else:
                modulus = R(modulus)

        self._cache = Cache_ntl_gf2e(self, k, modulus)
        self._modulus = modulus
Exemplo n.º 11
0
    def __init__(self,
                 polynomial,
                 names,
                 element_class=FunctionFieldElement_polymod,
                 category=CAT):
        """
        Create a function field defined as an extension of another
        function field by adjoining a root of a univariate polynomial.

        INPUT:

            - ``polynomial`` -- a univariate polynomial over a function field
            - ``names`` -- variable names (as a tuple of length 1 or string)
            - ``category`` -- a category (defaults to category of function fields)

        EXAMPLES::

        We create an extension of a function field::

            sage: K.<x> = FunctionField(QQ); R.<y> = K[]
            sage: L = K.extension(y^5 - x^3 - 3*x + x*y); L
            Function field in y defined by y^5 + x*y - x^3 - 3*x

        Note the type::

            sage: type(L)
            <class 'sage.rings.function_field.function_field.FunctionField_polymod_with_category'>

        We can set the variable name, which doesn't have to be y::

            sage: L.<w> = K.extension(y^5 - x^3 - 3*x + x*y); L
            Function field in w defined by y^5 + x*y - x^3 - 3*x
        """
        from sage.rings.polynomial.polynomial_element import is_Polynomial
        if polynomial.parent().ngens() > 1 or not is_Polynomial(polynomial):
            raise TypeError("polynomial must be univariate a polynomial")
        if names is None:
            names = (polynomial.variable_name(), )
        if polynomial.degree() <= 0:
            raise ValueError("polynomial must have positive degree")
        base_field = polynomial.base_ring()
        if not isinstance(base_field, FunctionField):
            raise TypeError("polynomial must be over a FunctionField")
        self._element_class = element_class
        self._element_init_pass_parent = False
        self._base_field = base_field
        self._polynomial = polynomial

        Field.__init__(self, base_field, names=names, category=category)

        self._hash = hash(polynomial)
        self._ring = self._polynomial.parent()
        self._populate_coercion_lists_(coerce_list=[base_field, self._ring])
        self._gen = self(self._ring.gen())
Exemplo n.º 12
0
    def __init__(self, q, name="a", modulus=None, repr="poly", cache=False):
        """
        Initialize ``self``.

        EXAMPLES::

            sage: k.<a> = GF(2^3)
            sage: j.<b> = GF(3^4)
            sage: k == j
            False

            sage: GF(2^3,'a') == copy(GF(2^3,'a'))
            True
            sage: TestSuite(GF(2^3, 'a')).run()
        """
        self._kwargs = {}

        if repr not in ['int', 'log', 'poly']:
            raise ValueError("Unknown representation %s" % repr)

        q = Integer(q)
        if q < 2:
            raise ValueError("q must be a prime power")
        F = q.factor()
        if len(F) > 1:
            raise ValueError("q must be a prime power")
        p = F[0][0]
        k = F[0][1]

        if q >= 1 << 16:
            raise ValueError("q must be < 2^16")

        from .finite_field_constructor import GF
        FiniteField.__init__(self, GF(p), name, normalize=False)

        self._kwargs['repr'] = repr
        self._kwargs['cache'] = cache

        from sage.rings.polynomial.polynomial_element import is_Polynomial
        if not is_Polynomial(modulus):
            from sage.misc.superseded import deprecation
            deprecation(
                16930,
                "constructing a FiniteField_givaro without giving a polynomial as modulus is deprecated, use the more general FiniteField constructor instead"
            )
            R = GF(p)['x']
            if modulus is None or isinstance(modulus, str):
                modulus = R.irreducible_element(k, algorithm=modulus)
            else:
                modulus = R(modulus)

        self._cache = Cache_givaro(self, p, k, modulus, repr, cache)
        self._modulus = modulus
Exemplo n.º 13
0
    def __init__(self, polynomial, names,
            element_class = FunctionFieldElement_polymod,
            category=CAT):
        """
        Create a function field defined as an extension of another
        function field by adjoining a root of a univariate polynomial.

        INPUT:

            - ``polynomial`` -- a univariate polynomial over a function field
            - ``names`` -- variable names (as a tuple of length 1 or string)
            - ``category`` -- a category (defaults to category of function fields)

        EXAMPLES::

        We create an extension of a function field::

            sage: K.<x> = FunctionField(QQ); R.<y> = K[]
            sage: L = K.extension(y^5 - x^3 - 3*x + x*y); L
            Function field in y defined by y^5 + x*y - x^3 - 3*x

        Note the type::

            sage: type(L)
            <class 'sage.rings.function_field.function_field.FunctionField_polymod_with_category'>

        We can set the variable name, which doesn't have to be y::

            sage: L.<w> = K.extension(y^5 - x^3 - 3*x + x*y); L
            Function field in w defined by y^5 + x*y - x^3 - 3*x
        """
        from sage.rings.polynomial.polynomial_element import is_Polynomial
        if polynomial.parent().ngens()>1 or not is_Polynomial(polynomial):
            raise TypeError("polynomial must be univariate a polynomial")
        if names is None:
            names = (polynomial.variable_name(), )
        if polynomial.degree() <= 0:
            raise ValueError("polynomial must have positive degree")
        base_field = polynomial.base_ring()
        if not isinstance(base_field, FunctionField):
            raise TypeError("polynomial must be over a FunctionField")
        self._element_class = element_class
        self._element_init_pass_parent = False
        self._base_field = base_field
        self._polynomial = polynomial

        Field.__init__(self, base_field,
                                names=names, category = category)

        self._hash = hash(polynomial)
        self._ring = self._polynomial.parent()
        self._populate_coercion_lists_(coerce_list=[base_field, self._ring])
        self._gen = self(self._ring.gen())
Exemplo n.º 14
0
    def __call__(self, key):
        """
        Create a LFSR cipher.

        INPUT: A polynomial and initial state of the LFSR.
        """
        if not isinstance(key, (list,tuple)) and len(key) == 2:
            raise TypeError("Argument key (= %s) must be a list of tuple of length 2" % key)
        poly = key[0]; IS = key[1]
        if not is_Polynomial(poly):
            raise TypeError("poly (= %s) must be a polynomial." % poly)
        if not isinstance(IS, (list,tuple)):
            raise TypeError("IS (= %s) must be an initial in the key space."%K)
        if len(IS) != poly.degree():
            raise TypeError("The length of IS (= %s) must equal the degree of poly (= %s)" % (IS, poly))
        return LFSRCipher(self, poly, IS)
Exemplo n.º 15
0
    def __init__(self, q, names="a", modulus=None, repr="poly"):
        """
        Initialize ``self``.

        TESTS::

            sage: k.<a> = GF(2^100, modulus='strangeinput')
            Traceback (most recent call last):
            ...
            ValueError: no such algorithm for finding an irreducible polynomial: strangeinput
            sage: k.<a> = GF(2^20) ; type(k)
            <class 'sage.rings.finite_rings.finite_field_ntl_gf2e.FiniteField_ntl_gf2e_with_category'>
            sage: loads(dumps(k)) is k
            True
            sage: k1.<a> = GF(2^16)
            sage: k2.<a> = GF(2^17)
            sage: k1 == k2
            False
            sage: k3.<a> = GF(2^16, impl="pari_ffelt")
            sage: k1 == k3
            False

            sage: TestSuite(k).run()

            sage: k.<a> = GF(2^64)
            sage: k._repr_option('element_is_atomic')
            False
            sage: P.<x> = PolynomialRing(k)
            sage: (a+1)*x # indirect doctest
            (a + 1)*x
        """
        late_import()
        q = Integer(q)
        if q < 2:
            raise ValueError("q must be a 2-power")
        k = q.exact_log(2)
        if q != 1 << k:
            raise ValueError("q must be a 2-power")
        FiniteField.__init__(self, GF2, names, normalize=True)

        from sage.rings.polynomial.polynomial_element import is_Polynomial
        if not is_Polynomial(modulus):
            raise TypeError("modulus must be a polynomial")

        self._cache = Cache_ntl_gf2e(self, k, modulus)
        self._modulus = modulus
Exemplo n.º 16
0
    def __init__(self, q, names="a", modulus=None, repr="poly"):
        """
        Initialize ``self``.

        TESTS::

            sage: k.<a> = GF(2^100, modulus='strangeinput')
            Traceback (most recent call last):
            ...
            ValueError: no such algorithm for finding an irreducible polynomial: strangeinput
            sage: k.<a> = GF(2^20) ; type(k)
            <class 'sage.rings.finite_rings.finite_field_ntl_gf2e.FiniteField_ntl_gf2e_with_category'>
            sage: loads(dumps(k)) is k
            True
            sage: k1.<a> = GF(2^16)
            sage: k2.<a> = GF(2^17)
            sage: k1 == k2
            False
            sage: k3.<a> = GF(2^16, impl="pari_ffelt")
            sage: k1 == k3
            False

            sage: TestSuite(k).run()

            sage: k.<a> = GF(2^64)
            sage: k._repr_option('element_is_atomic')
            False
            sage: P.<x> = PolynomialRing(k)
            sage: (a+1)*x # indirect doctest
            (a + 1)*x
        """
        late_import()
        q = Integer(q)
        if q < 2:
            raise ValueError("q must be a 2-power")
        k = q.exact_log(2)
        if q != 1 << k:
            raise ValueError("q must be a 2-power")
        FiniteField.__init__(self, GF2, names, normalize=True)

        from sage.rings.polynomial.polynomial_element import is_Polynomial
        if not is_Polynomial(modulus):
            raise TypeError("modulus must be a polynomial")

        self._cache = Cache_ntl_gf2e(self, k, modulus)
        self._modulus = modulus
Exemplo n.º 17
0
    def __init__(self, q, name="a", modulus=None, repr="poly", cache=False):
        """
        Initialize ``self``.

        EXAMPLES::

            sage: k.<a> = GF(2^3)
            sage: j.<b> = GF(3^4)
            sage: k == j
            False

            sage: GF(2^3,'a') == copy(GF(2^3,'a'))
            True
            sage: TestSuite(GF(2^3, 'a')).run()
        """
        if repr not in ['int', 'log', 'poly']:
            raise ValueError("Unknown representation %s"%repr)

        q = Integer(q)
        if q < 2:
            raise ValueError("q must be a prime power")
        F = q.factor()
        if len(F) > 1:
            raise ValueError("q must be a prime power")
        p = F[0][0]
        k = F[0][1]

        if q >= 1<<16:
            raise ValueError("q must be < 2^16")

        from .finite_field_constructor import GF
        FiniteField.__init__(self, GF(p), name, normalize=False)

        from sage.rings.polynomial.polynomial_element import is_Polynomial
        if not is_Polynomial(modulus):
            raise TypeError("modulus must be a polynomial")

        self._cache = Cache_givaro(self, p, k, modulus, repr, cache)
        self._modulus = modulus
Exemplo n.º 18
0
    def __init__(self, W, q, trace=False):
        """
        Initialize ``self``.

        EXAMPLES::

            sage: W = WeylGroup("B3",prefix="s")
            sage: R.<q> = LaurentPolynomialRing(QQ)
            sage: KL = KazhdanLusztigPolynomial(W,q)
            sage: TestSuite(KL).run()
        """
        self._coxeter_group = W
        self._q = q
        self._trace = trace
        self._one = W.one()
        self._base_ring = q.parent()
        if is_Polynomial(q):
            self._base_ring_type = "polynomial"
        elif isinstance(q, LaurentPolynomial_mpair):
            self._base_ring_type = "laurent"
        else:
            self._base_ring_type = "unknown"
Exemplo n.º 19
0
    def __init__(self, q, name="a", modulus=None, repr="poly", cache=False):
        """
        Initialize ``self``.

        EXAMPLES::

            sage: k.<a> = GF(2^3)
            sage: j.<b> = GF(3^4)
            sage: k == j
            False

            sage: GF(2^3,'a') == copy(GF(2^3,'a'))
            True
            sage: TestSuite(GF(2^3, 'a')).run()
        """
        if repr not in ['int', 'log', 'poly']:
            raise ValueError("Unknown representation %s"%repr)

        q = Integer(q)
        if q < 2:
            raise ValueError("q must be a prime power")
        F = q.factor()
        if len(F) > 1:
            raise ValueError("q must be a prime power")
        p = F[0][0]
        k = F[0][1]

        if q >= 1<<16:
            raise ValueError("q must be < 2^16")

        from .finite_field_constructor import GF
        FiniteField.__init__(self, GF(p), name, normalize=False)

        from sage.rings.polynomial.polynomial_element import is_Polynomial
        if not is_Polynomial(modulus):
            raise TypeError("modulus must be a polynomial")

        self._cache = Cache_givaro(self, p, k, modulus, repr, cache)
        self._modulus = modulus
Exemplo n.º 20
0
    def __init__(self, W, q, trace=False):
        """
        Initialize ``self``.

        EXAMPLES::

            sage: W = WeylGroup("B3",prefix="s")
            sage: R.<q> = LaurentPolynomialRing(QQ)
            sage: KL = KazhdanLusztigPolynomial(W,q)
            sage: TestSuite(KL).run()
        """
        self._coxeter_group = W
        self._q = q
        self._trace = trace
        self._one = W.one()
        self._base_ring = q.parent()
        if is_Polynomial(q):
            self._base_ring_type = "polynomial"
        elif isinstance(q, LaurentPolynomial_mpair):
            self._base_ring_type = "laurent"
        else:
            self._base_ring_type = "unknown"
Exemplo n.º 21
0
    def _element_constructor_(self, x, n=0):
        r"""
        Construct a Laurent series from `x`.

        INPUT:

        - ``x`` -- object that can be converted into a Laurent series

        - ``n`` -- (default: 0) multiply the result by `t^n`

        EXAMPLES::

            sage: R.<u> = LaurentSeriesRing(Qp(5, 10))
            sage: S.<t> = LaurentSeriesRing(RationalField())
            sage: print R(t + t^2 + O(t^3))
            (1 + O(5^10))*u + (1 + O(5^10))*u^2 + O(u^3)

        Note that coercing an element into its own parent just produces
        that element again (since Laurent series are immutable)::

            sage: u is R(u)
            True

        Rational functions are accepted::

            sage: I = sqrt(-1)
            sage: K.<I> = QQ[I]
            sage: P.<t> = PolynomialRing(K)
            sage: L.<u> = LaurentSeriesRing(QQ[I])
            sage: L((t*I)/(t^3+I*2*t))
            1/2 + 1/4*I*u^2 - 1/8*u^4 - 1/16*I*u^6 + 1/32*u^8 +
            1/64*I*u^10 - 1/128*u^12 - 1/256*I*u^14 + 1/512*u^16 +
            1/1024*I*u^18 + O(u^20)

        ::

            sage: L(t*I) / L(t^3+I*2*t)
            1/2 + 1/4*I*u^2 - 1/8*u^4 - 1/16*I*u^6 + 1/32*u^8 +
            1/64*I*u^10 - 1/128*u^12 - 1/256*I*u^14 + 1/512*u^16 +
            1/1024*I*u^18 + O(u^20)

        TESTS:

        When converting from `R((z))` to `R((z))((w))`, the variable
        `z` is sent to `z` rather than to `w` (see :trac:`7085`)::

            sage: A.<z> = LaurentSeriesRing(QQ)
            sage: B.<w> = LaurentSeriesRing(A)
            sage: B(z)
            z
            sage: z/w
            z*w^-1

        Various conversions from PARI (see also :trac:`2508`)::

            sage: L.<q> = LaurentSeriesRing(QQ)
            sage: L.set_default_prec(10)
            doctest:...: DeprecationWarning: This method is deprecated.
            See http://trac.sagemath.org/16201 for details.
            sage: L(pari('1/x'))
            q^-1
            sage: L(pari('polchebyshev(5)'))
            5*q - 20*q^3 + 16*q^5
            sage: L(pari('polchebyshev(5) - 1/x^4'))
            -q^-4 + 5*q - 20*q^3 + 16*q^5
            sage: L(pari('1/polchebyshev(5)'))
            1/5*q^-1 + 4/5*q + 64/25*q^3 + 192/25*q^5 + 2816/125*q^7 + O(q^9)
            sage: L(pari('polchebyshev(5) + O(x^40)'))
            5*q - 20*q^3 + 16*q^5 + O(q^40)
            sage: L(pari('polchebyshev(5) - 1/x^4 + O(x^40)'))
            -q^-4 + 5*q - 20*q^3 + 16*q^5 + O(q^40)
            sage: L(pari('1/polchebyshev(5) + O(x^10)'))
            1/5*q^-1 + 4/5*q + 64/25*q^3 + 192/25*q^5 + 2816/125*q^7 + 8192/125*q^9 + O(q^10)
            sage: L(pari('1/polchebyshev(5) + O(x^10)'), -10)  # Multiply by q^-10
            1/5*q^-11 + 4/5*q^-9 + 64/25*q^-7 + 192/25*q^-5 + 2816/125*q^-3 + 8192/125*q^-1 + O(1)
            sage: L(pari('O(x^-10)'))
            O(q^-10)
        """
        from sage.rings.fraction_field_element import is_FractionFieldElement
        from sage.rings.polynomial.polynomial_element import is_Polynomial
        from sage.rings.polynomial.multi_polynomial_element import is_MPolynomial
        from sage.structure.element import parent

        P = parent(x)
        if isinstance(x, self.element_class) and n==0 and P is self:
            return x  # ok, since Laurent series are immutable (no need to make a copy)
        elif P is self.base_ring():
            # Convert x into a power series; if P is itself a Laurent
            # series ring A((t)), this prevents the implementation of
            # LaurentSeries.__init__() from effectively applying the
            # ring homomorphism A((t)) -> A((t))((u)) sending t to u
            # instead of the one sending t to t.  We cannot easily
            # tell LaurentSeries.__init__() to be more strict, because
            # A((t)) -> B((u)) is expected to send t to u if A admits
            # a coercion to B but A((t)) does not, and this condition
            # would be inefficient to check there.
            x = self.power_series_ring()(x)
        elif isinstance(x, pari_gen):
            t = x.type()
            if t == "t_RFRAC":   # Rational function
                x = self(self.polynomial_ring()(x.numerator())) / \
                    self(self.polynomial_ring()(x.denominator()))
                return (x << n)
            elif t == "t_SER":   # Laurent series
                n += x._valp()
                bigoh = n + x.length()
                x = self(self.polynomial_ring()(x.Vec()))
                return (x << n).add_bigoh(bigoh)
            else:  # General case, pretend to be a polynomial
                return self(self.polynomial_ring()(x)) << n
        elif is_FractionFieldElement(x) and \
             (x.base_ring() is self.base_ring() or x.base_ring() == self.base_ring()) and \
             (is_Polynomial(x.numerator()) or is_MPolynomial(x.numerator())):
            x = self(x.numerator())/self(x.denominator())
            return (x << n)
        return self.element_class(self, x, n)
Exemplo n.º 22
0
    def _element_constructor_(self, x, n=0):
        r"""
        Construct a Laurent series from `x`.

        INPUT:

        - ``x`` -- object that can be converted into a Laurent series

        - ``n`` -- (default: 0) multiply the result by `t^n`

        EXAMPLES::

            sage: R.<u> = LaurentSeriesRing(Qp(5, 10))
            sage: S.<t> = LaurentSeriesRing(RationalField())
            sage: print R(t + t^2 + O(t^3))
            (1 + O(5^10))*u + (1 + O(5^10))*u^2 + O(u^3)

        Note that coercing an element into its own parent just produces
        that element again (since Laurent series are immutable)::

            sage: u is R(u)
            True

        Rational functions are accepted::

            sage: I = sqrt(-1)
            sage: K.<I> = QQ[I]
            sage: P.<t> = PolynomialRing(K)
            sage: L.<u> = LaurentSeriesRing(QQ[I])
            sage: L((t*I)/(t^3+I*2*t))
            1/2 + 1/4*I*u^2 - 1/8*u^4 - 1/16*I*u^6 + 1/32*u^8 +
            1/64*I*u^10 - 1/128*u^12 - 1/256*I*u^14 + 1/512*u^16 +
            1/1024*I*u^18 + O(u^20)

        ::

            sage: L(t*I) / L(t^3+I*2*t)
            1/2 + 1/4*I*u^2 - 1/8*u^4 - 1/16*I*u^6 + 1/32*u^8 +
            1/64*I*u^10 - 1/128*u^12 - 1/256*I*u^14 + 1/512*u^16 +
            1/1024*I*u^18 + O(u^20)

        TESTS:

        When converting from `R((z))` to `R((z))((w))`, the variable
        `z` is sent to `z` rather than to `w` (see :trac:`7085`)::

            sage: A.<z> = LaurentSeriesRing(QQ)
            sage: B.<w> = LaurentSeriesRing(A)
            sage: B(z)
            z
            sage: z/w
            z*w^-1

        Various conversions from PARI (see also :trac:`2508`)::

            sage: L.<q> = LaurentSeriesRing(QQ)
            sage: L.set_default_prec(10)
            sage: L(pari('1/x'))
            q^-1
            sage: L(pari('poltchebi(5)'))
            5*q - 20*q^3 + 16*q^5
            sage: L(pari('poltchebi(5) - 1/x^4'))
            -q^-4 + 5*q - 20*q^3 + 16*q^5
            sage: L(pari('1/poltchebi(5)'))
            1/5*q^-1 + 4/5*q + 64/25*q^3 + 192/25*q^5 + 2816/125*q^7 + O(q^9)
            sage: L(pari('poltchebi(5) + O(x^40)'))
            5*q - 20*q^3 + 16*q^5 + O(q^40)
            sage: L(pari('poltchebi(5) - 1/x^4 + O(x^40)'))
            -q^-4 + 5*q - 20*q^3 + 16*q^5 + O(q^40)
            sage: L(pari('1/poltchebi(5) + O(x^10)'))
            1/5*q^-1 + 4/5*q + 64/25*q^3 + 192/25*q^5 + 2816/125*q^7 + 8192/125*q^9 + O(q^10)
            sage: L(pari('1/poltchebi(5) + O(x^10)'), -10)  # Multiply by q^-10
            1/5*q^-11 + 4/5*q^-9 + 64/25*q^-7 + 192/25*q^-5 + 2816/125*q^-3 + 8192/125*q^-1 + O(1)
            sage: L(pari('O(x^-10)'))
            O(q^-10)
        """
        from sage.rings.fraction_field_element import is_FractionFieldElement
        from sage.rings.polynomial.polynomial_element import is_Polynomial
        from sage.rings.polynomial.multi_polynomial_element import is_MPolynomial
        from sage.structure.element import parent

        P = parent(x)
        if isinstance(x, self.element_class) and n == 0 and P is self:
            return x  # ok, since Laurent series are immutable (no need to make a copy)
        elif P is self.base_ring():
            # Convert x into a power series; if P is itself a Laurent
            # series ring A((t)), this prevents the implementation of
            # LaurentSeries.__init__() from effectively applying the
            # ring homomorphism A((t)) -> A((t))((u)) sending t to u
            # instead of the one sending t to t.  We cannot easily
            # tell LaurentSeries.__init__() to be more strict, because
            # A((t)) -> B((u)) is expected to send t to u if A admits
            # a coercion to B but A((t)) does not, and this condition
            # would be inefficient to check there.
            x = self.power_series_ring()(x)
        elif isinstance(x, pari_gen):
            t = x.type()
            if t == "t_RFRAC":  # Rational function
                x = self(self.polynomial_ring()(x.numerator())) / \
                    self(self.polynomial_ring()(x.denominator()))
                return (x << n)
            elif t == "t_SER":  # Laurent series
                n += x._valp()
                bigoh = n + x.length()
                x = self(self.polynomial_ring()(x.Vec()))
                return (x << n).add_bigoh(bigoh)
            else:  # General case, pretend to be a polynomial
                return self(self.polynomial_ring()(x)) << n
        elif is_FractionFieldElement(x) and \
             (x.base_ring() is self.base_ring() or x.base_ring() == self.base_ring()) and \
             (is_Polynomial(x.numerator()) or is_MPolynomial(x.numerator())):
            x = self(x.numerator()) / self(x.denominator())
            return (x << n)
        return self.element_class(self, x, n)
Exemplo n.º 23
0
    def __call__(self, x, n=0):
        r"""
        Coerces the element x into this Laurent series ring.

        INPUT:


        -  ``x`` - the element to coerce

        -  ``n`` - the result of the coercion will be
           multiplied by `t^n` (default: 0)


        EXAMPLES::

            sage: R.<u> = LaurentSeriesRing(Qp(5, 10))
            sage: S.<t> = LaurentSeriesRing(RationalField())
            sage: print R(t + t^2 + O(t^3))
            (1 + O(5^10))*u + (1 + O(5^10))*u^2 + O(u^3)

        Note that coercing an element into its own parent just produces
        that element again (since Laurent series are immutable)::

            sage: u is R(u)
            True

        Rational functions are accepted::

            sage: I = sqrt(-1)
            sage: K.<I> = QQ[I]
            sage: P.<t> = PolynomialRing(K)
            sage: L.<u> = LaurentSeriesRing(QQ[I])
            sage: L((t*I)/(t^3+I*2*t))
            1/2 + 1/4*I*u^2 - 1/8*u^4 - 1/16*I*u^6 + 1/32*u^8 +
            1/64*I*u^10 - 1/128*u^12 - 1/256*I*u^14 + 1/512*u^16 +
            1/1024*I*u^18 + O(u^20)

        ::

            sage: L(t*I) / L(t^3+I*2*t)
            1/2 + 1/4*I*u^2 - 1/8*u^4 - 1/16*I*u^6 + 1/32*u^8 +
            1/64*I*u^10 - 1/128*u^12 - 1/256*I*u^14 + 1/512*u^16 +
            1/1024*I*u^18 + O(u^20)

        Various conversions from PARI (see also #2508)::

            sage: L.<q> = LaurentSeriesRing(QQ)
            sage: L.set_default_prec(10)
            sage: L(pari('1/x'))
            q^-1
            sage: L(pari('poltchebi(5)'))
            5*q - 20*q^3 + 16*q^5
            sage: L(pari('poltchebi(5) - 1/x^4'))
            -q^-4 + 5*q - 20*q^3 + 16*q^5
            sage: L(pari('1/poltchebi(5)'))
            1/5*q^-1 + 4/5*q + 64/25*q^3 + 192/25*q^5 + 2816/125*q^7 + O(q^9)
            sage: L(pari('poltchebi(5) + O(x^40)'))
            5*q - 20*q^3 + 16*q^5 + O(q^40)
            sage: L(pari('poltchebi(5) - 1/x^4 + O(x^40)'))
            -q^-4 + 5*q - 20*q^3 + 16*q^5 + O(q^40)
            sage: L(pari('1/poltchebi(5) + O(x^10)'))
            1/5*q^-1 + 4/5*q + 64/25*q^3 + 192/25*q^5 + 2816/125*q^7 + 8192/125*q^9 + O(q^10)
            sage: L(pari('1/poltchebi(5) + O(x^10)'), -10)  # Multiply by q^-10
            1/5*q^-11 + 4/5*q^-9 + 64/25*q^-7 + 192/25*q^-5 + 2816/125*q^-3 + 8192/125*q^-1 + O(1)
            sage: L(pari('O(x^-10)'))
            O(q^-10)
        """
        from sage.rings.fraction_field_element import is_FractionFieldElement
        from sage.rings.polynomial.polynomial_element import is_Polynomial
        from sage.rings.polynomial.multi_polynomial_element import is_MPolynomial

        if isinstance(x, laurent_series_ring_element.LaurentSeries
                      ) and n == 0 and self is x.parent():
            return x  # ok, since Laurent series are immutable (no need to make a copy)
        elif isinstance(x, pari_gen):
            t = x.type()
            if t == "t_RFRAC":  # Rational function
                x = self(self.polynomial_ring()(x.numerator())) / \
                    self(self.polynomial_ring()(x.denominator()))
                return (x << n)
            elif t == "t_SER":  # Laurent series
                n += x._valp()
                bigoh = n + x.length()
                x = self(self.polynomial_ring()(x.Vec()))
                return (x << n).add_bigoh(bigoh)
            else:  # General case, pretend to be a polynomial
                return self(self.polynomial_ring()(x)) << n
        elif is_FractionFieldElement(x) and \
             (x.base_ring() is self.base_ring() or x.base_ring() == self.base_ring()) and \
             (is_Polynomial(x.numerator()) or is_MPolynomial(x.numerator())):
            x = self(x.numerator()) / self(x.denominator())
            return (x << n)
        else:
            return laurent_series_ring_element.LaurentSeries(self, x, n)
Exemplo n.º 24
0
def CyclicCover(r, f, names=None, check_smooth=True):
    r"""
    Return the cyclic cover of the projective line given by `y^r = f`, for
    a univariate polynomial `f`.

    INPUT:

    - ``r`` - the order of the cover

    - ``f`` - univariate polynomial if not given, then it defaults to 0.

    - ``names``  (default: ``["x","y"]``) - names for the
       coordinate functions

    - ``check_squarefree`` (default: ``True``) - test if
      the input defines a unramified cover of the projective line.

    .. WARNING::

        When setting ``check_smooth=False`` or using a base ring that is
        not a field, the output curves are not to be trusted. For example, the
        output of ``is_singular`` or ``is_smooth`` only tests smoothness over
        the field of fractions.

    .. NOTE::

        The words "cyclic cover" are usually used for covers of degree
        greater than two.
        We usually refer to smooth double covers of the projective line as
        "hyperelliptic curves" or "elliptic curves" if the genus is one.
        We allow such cases in this implementation, but we highly recommend
        to use the more specific constructors/classes HyperellipticCurve and
        EllipticCurve for a wider range of tools.

    EXAMPLES:

    Basic examples::

        sage: R.<x> = QQ[]
        sage: CyclicCover(2, x^5 + x + 1)
        Cyclic Cover of P^1 over Rational Field defined by y^2 = x^5 + x + 1
        sage: CyclicCover(3, x^5 + x + 1)
        Cyclic Cover of P^1 over Rational Field defined by y^3 = x^5 + x + 1
        sage: CyclicCover(5, x^5 + x + 1)
        Cyclic Cover of P^1 over Rational Field defined by y^5 = x^5 + x + 1
        sage: CyclicCover(15, x^9 + x + 1)
        Cyclic Cover of P^1 over Rational Field defined by y^15 = x^9 + x + 1

        sage: k.<a> = GF(9); R.<x> = k[]
        sage: CyclicCover(5, x^9 + x + 1)
        Cyclic Cover of P^1 over Finite Field in a of size 3^2 defined by y^5 = x^9 + x + 1
        sage: CyclicCover(15, x^9 + x + 1)
        Traceback (most recent call last):
        ...
        ValueError: As the characteristic divides the order of the cover, this model is not smooth.

    We can change the names of the variables in the output::

        sage: k.<a> = GF(9); R.<x> = k[]
        sage: CyclicCover(5, x^9 + x + 1, names = ["A","B"])
        Cyclic Cover of P^1 over Finite Field in a of size 3^2 defined by B^5 = A^9 + A + 1

    Double roots::

        sage: P.<x> = GF(7)[]
        sage: CyclicCover(2,(x^3-x+2)^2*(x^6-1))
        Traceback (most recent call last):
        ...
        ValueError: Not a smooth Cyclic Cover of P^1: singularity in the provided affine patch.

        sage: CyclicCover(2, (x^3-x+2)^2*(x^6-1), check_smooth=False)
        Cyclic Cover of P^1 over Finite Field of size 7 defined by y^2 = x^12 - 2*x^10 - 3*x^9 + x^8 + 3*x^7 + 3*x^6 + 2*x^4 + 3*x^3 - x^2 - 3*x + 3


    Input with integer coefficients creates objects with the integers
    as base ring, but only checks smoothness over `\QQ`, not over Spec(`\ZZ`).
    In other words, it is checked that the discriminant is non-zero, but it is
    not checked whether the discriminant is a unit in `\ZZ^*`.::

        sage: R.<x> = ZZ[]
        sage: CyclicCover(5,(x^3-x+2)*(x^6-1))
        Cyclic Cover of P^1 over Integer Ring defined by y^5 = x^9 - x^7 + 2*x^6 - x^3 + x - 2


    """
    if not is_Polynomial(f):
        raise TypeError("Arguments f (= %s) must be a polynomial" % (f,))
    P = f.parent()
    f = P(f)
    if check_smooth:
        if P(r) == 0:
            raise ValueError(
                "As the characteristic divides the order of the cover, "
                "this model is not smooth."
            )

        try:
            smooth = f.is_squarefree()
        except NotImplementedError as err:
            raise NotImplementedError(
                str(err) + "Use " "check_smooth=False to skip this check."
            )
        if not smooth:
            raise ValueError(
                "Not a smooth Cyclic Cover of P^1: "
                "singularity in the provided affine patch."
            )
    R = P.base_ring()
    if names is None:
        names = ["x", "y"]
    A2 = AffineSpace(2, R, names=names)

    if is_FiniteField(R):
        return CyclicCover_finite_field(A2, r, f, names=names)
    else:
        return CyclicCover_generic(A2, r, f, names=names)
Exemplo n.º 25
0
    def __call__(self, P):
        r"""
        Returns a rational point P in the abstract Homset J(K), given:

        0. A point P in J = Jac(C), returning P; 1. A point P on the curve
        C such that J = Jac(C), where C is an odd degree model, returning
        [P - oo]; 2. A pair of points (P, Q) on the curve C such that J =
        Jac(C), returning [P-Q]; 2. A list of polynomials (a,b) such that
        `b^2 + h*b - f = 0 mod a`, returning [(a(x),y-b(x))].

        EXAMPLES::

            sage: P.<x> = PolynomialRing(QQ)
            sage: f = x^5 - x + 1; h = x
            sage: C = HyperellipticCurve(f,h,'u,v')
            sage: P = C(0,1,1)
            sage: J = C.jacobian()
            sage: Q = J(QQ)(P)
            sage: for i in range(6): i*Q
            (1)
            (u, v - 1)
            (u^2, v + u - 1)
            (u^2, v + 1)
            (u, v + 1)
            (1)

        ::

            sage: F.<a> = GF(3)
            sage: R.<x> = F[]
            sage: f = x^5-1
            sage: C = HyperellipticCurve(f)
            sage: J = C.jacobian()
            sage: X = J(F)
            sage: a = x^2-x+1
            sage: b = -x +1
            sage: c = x-1
            sage: d = 0
            sage: D1 = X([a,b])
            sage: D1
            (x^2 + 2*x + 1, y + x + 2)
            sage: D2 = X([c,d])
            sage: D2
            (x + 2, y)
            sage: D1+D2
            (x^2 + 2*x + 2, y + 2*x + 1)

        """
        if isinstance(P, (int, long, Integer)) and P == 0:
            R = PolynomialRing(self.value_ring(), 'x')
            return JacobianMorphism_divisor_class_field(self, (R(1), R(0)))
        elif isinstance(P, (list, tuple)):
            if len(P) == 1 and P[0] == 0:
                R = PolynomialRing(self.value_ring(), 'x')
                return JacobianMorphism_divisor_class_field(self, (R(1), R(0)))
            elif len(P) == 2:
                P1 = P[0]
                P2 = P[1]
                if is_Integer(P1) and is_Integer(P2):
                    R = PolynomialRing(self.value_ring(), 'x')
                    P1 = R(P1)
                    P2 = R(P2)
                    return JacobianMorphism_divisor_class_field(
                        self, tuple([P1, P2]))
                if is_Integer(P1) and is_Polynomial(P2):
                    R = PolynomialRing(self.value_ring(), 'x')
                    P1 = R(P1)
                    return JacobianMorphism_divisor_class_field(
                        self, tuple([P1, P2]))
                if is_Integer(P2) and is_Polynomial(P1):
                    R = PolynomialRing(self.value_ring(), 'x')
                    P2 = R(P2)
                    return JacobianMorphism_divisor_class_field(
                        self, tuple([P1, P2]))
                if is_Polynomial(P1) and is_Polynomial(P2):
                    return JacobianMorphism_divisor_class_field(self, tuple(P))
                if is_SchemeMorphism(P1) and is_SchemeMorphism(P2):
                    return self(P1) - self(P2)
            raise TypeError("Argument P (= %s) must have length 2." % P)
        elif isinstance(
                P,
                JacobianMorphism_divisor_class_field) and self == P.parent():
            return P
        elif is_SchemeMorphism(P):
            x0 = P[0]
            y0 = P[1]
            R, x = PolynomialRing(self.value_ring(), 'x').objgen()
            return self((x - x0, R(y0)))
        raise TypeError(
            "Argument P (= %s) does not determine a divisor class" % P)
Exemplo n.º 26
0
    def __call__(self, x, n=0):
        r"""
        Coerces the element x into this Laurent series ring.
        
        INPUT:
        
        
        -  ``x`` - the element to coerce
        
        -  ``n`` - the result of the coercion will be
           multiplied by `t^n` (default: 0)
        
        
        EXAMPLES::
        
            sage: R.<u> = LaurentSeriesRing(Qp(5, 10))
            sage: S.<t> = LaurentSeriesRing(RationalField())
            sage: print R(t + t^2 + O(t^3))
            (1 + O(5^10))*u + (1 + O(5^10))*u^2 + O(u^3)
        
        Note that coercing an element into its own parent just produces
        that element again (since Laurent series are immutable)::
        
            sage: u is R(u)
            True
        
        Rational functions are accepted::
        
            sage: I = sqrt(-1)
            sage: K.<I> = QQ[I]
            sage: P.<t> = PolynomialRing(K)
            sage: L.<u> = LaurentSeriesRing(QQ[I])
            sage: L((t*I)/(t^3+I*2*t))
            1/2 + 1/4*I*u^2 - 1/8*u^4 - 1/16*I*u^6 + 1/32*u^8 +
            1/64*I*u^10 - 1/128*u^12 - 1/256*I*u^14 + 1/512*u^16 +
            1/1024*I*u^18 + O(u^20)
        
        ::
        
            sage: L(t*I) / L(t^3+I*2*t)
            1/2 + 1/4*I*u^2 - 1/8*u^4 - 1/16*I*u^6 + 1/32*u^8 +
            1/64*I*u^10 - 1/128*u^12 - 1/256*I*u^14 + 1/512*u^16 +
            1/1024*I*u^18 + O(u^20)

        Various conversions from PARI (see also #2508)::
        
            sage: L.<q> = LaurentSeriesRing(QQ)
            sage: L.set_default_prec(10)
            sage: L(pari('1/x'))
            q^-1
            sage: L(pari('poltchebi(5)'))
            5*q - 20*q^3 + 16*q^5
            sage: L(pari('poltchebi(5) - 1/x^4'))
            -q^-4 + 5*q - 20*q^3 + 16*q^5
            sage: L(pari('1/poltchebi(5)'))
            1/5*q^-1 + 4/5*q + 64/25*q^3 + 192/25*q^5 + 2816/125*q^7 + O(q^9)
            sage: L(pari('poltchebi(5) + O(x^40)'))
            5*q - 20*q^3 + 16*q^5 + O(q^40)
            sage: L(pari('poltchebi(5) - 1/x^4 + O(x^40)'))
            -q^-4 + 5*q - 20*q^3 + 16*q^5 + O(q^40)
            sage: L(pari('1/poltchebi(5) + O(x^10)'))
            1/5*q^-1 + 4/5*q + 64/25*q^3 + 192/25*q^5 + 2816/125*q^7 + 8192/125*q^9 + O(q^10)
            sage: L(pari('1/poltchebi(5) + O(x^10)'), -10)  # Multiply by q^-10
            1/5*q^-11 + 4/5*q^-9 + 64/25*q^-7 + 192/25*q^-5 + 2816/125*q^-3 + 8192/125*q^-1 + O(1)
            sage: L(pari('O(x^-10)'))
            O(q^-10)
        """
        from sage.rings.fraction_field_element import is_FractionFieldElement
        from sage.rings.polynomial.polynomial_element import is_Polynomial
        from sage.rings.polynomial.multi_polynomial_element import is_MPolynomial
        
        if isinstance(x, laurent_series_ring_element.LaurentSeries) and n==0 and self is x.parent():
            return x  # ok, since Laurent series are immutable (no need to make a copy)
        elif isinstance(x, pari_gen):
            t = x.type()
            if t == "t_RFRAC":   # Rational function
                x = self(self.polynomial_ring()(x.numerator())) / \
                    self(self.polynomial_ring()(x.denominator()))
                return (x << n)
            elif t == "t_SER":   # Laurent series
                n += x._valp()
                bigoh = n + x.length()
                x = self(self.polynomial_ring()(x.Vec()))
                return (x << n).add_bigoh(bigoh)
            else:  # General case, pretend to be a polynomial
                return self(self.polynomial_ring()(x)) << n
        elif is_FractionFieldElement(x) and \
             (x.base_ring() is self.base_ring() or x.base_ring() == self.base_ring()) and \
             (is_Polynomial(x.numerator()) or is_MPolynomial(x.numerator())):
            x = self(x.numerator())/self(x.denominator())
            return (x << n)
        else:
            return laurent_series_ring_element.LaurentSeries(self, x, n)
Exemplo n.º 27
0
    def __call__(self, v):
        """
        Apply the affine transformation to ``v``.

        INPUT:

        - ``v`` -- a polynomial, a multivariate polynomial, a polyhedron, a
          vector, or anything that can be converted into a vector.

        OUTPUT:

        The image of ``v`` under the affine group element.

        EXAMPLES::

            sage: G = AffineGroup(2, QQ)
            sage: g = G([0,1,-1,0],[2,3]);  g
                  [ 0  1]     [2]
            x |-> [-1  0] x + [3]
            sage: v = vector([4,5])
            sage: g(v)
            (7, -1)

            sage: R.<x,y> = QQ[]
            sage: g(x), g(y)
            (y + 2, -x + 3)
            sage: p = x^2 + 2*x*y + y + 1
            sage: g(p)
            -2*x*y + y^2 - 5*x + 10*y + 20

        The action on polynomials is such that it intertwines with
        evaluation. That is::

            sage: p(*g(v)) == g(p)(*v)
            True

        Test that the univariate polynomial ring is covered::

            sage: H = AffineGroup(1, QQ)
            sage: h = H([2],[3]);  h
            x |-> [2] x + [3]
            sage: R.<z> = QQ[]
            sage: h(z+1)
            3*z + 2

        The action on a polyhedron is defined (see :trac:`30327`)::

            sage: F = AffineGroup(3, QQ)
            sage: M = matrix(3, [-1, -2, 0, 0, 0, 1, -2, 1, -1])
            sage: v = vector(QQ,(1,2,3))
            sage: f = F(M, v)
            sage: cube = polytopes.cube()
            sage: f(cube)
            A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 8 vertices

        """
        parent = self.parent()

        # start with the most probable case, i.e., v is in the vector space
        if v in parent.vector_space():
            return self._A * v + self._b

        from sage.rings.polynomial.polynomial_element import is_Polynomial
        if is_Polynomial(v) and parent.degree() == 1:
            ring = v.parent()
            return ring([self._A[0, 0], self._b[0]])

        from sage.rings.polynomial.multi_polynomial import is_MPolynomial
        if is_MPolynomial(v) and parent.degree() == v.parent().ngens():
            ring = v.parent()
            from sage.modules.free_module_element import vector
            image_coords = self._A * vector(ring, ring.gens()) + self._b
            return v(*image_coords)

        import sage.geometry.abc
        if isinstance(v, sage.geometry.abc.Polyhedron):
            return self._A * v + self._b

        # otherwise, coerce v into the vector space
        v = parent.vector_space()(v)
        return self._A * v + self._b
Exemplo n.º 28
0
    def create_object(self, version, key, check_irreducible=True, elem_cache=None,
                      names=None, **kwds):
        """
        EXAMPLES::

            sage: K = GF(19) # indirect doctest
            sage: TestSuite(K).run()
        """
        # IMPORTANT!  If you add a new class to the list of classes
        # that get cached by this factor object, then you *must* add
        # the following method to that class in order to fully support
        # pickling:
        #
        #     def __reduce__(self):   # and include good doctests, please!
        #         return self._factory_data[0].reduce_data(self)
        #
        # This is not in the base class for finite fields, since some finite
        # fields need not be created using this factory object, e.g., residue
        # class fields.

        if len(key) == 5:
            # for backward compatibility of pickles (see trac 10975).
            order, name, modulus, impl, _ = key
            p, n = arith.factor(order)[0]
            proof = True
        else:
            order, name, modulus, impl, _, p, n, proof = key

        if elem_cache is None:
            elem_cache = order < 500

        if n == 1 and (impl is None or impl == 'modn'):
            from finite_field_prime_modn import FiniteField_prime_modn
            # Using a check option here is probably a worthwhile
            # compromise since this constructor is simple and used a
            # huge amount.
            K = FiniteField_prime_modn(order, check=False)
        else:
            # We have to do this with block so that the finite field
            # constructors below will use the proof flag that was
            # passed in when checking for primality, factoring, etc.
            # Otherwise, we would have to complicate all of their
            # constructors with check options (like above).
            from sage.structure.proof.all import WithProof
            with WithProof('arithmetic', proof):
                if check_irreducible and polynomial_element.is_Polynomial(modulus):
                    if modulus.parent().base_ring().characteristic() == 0:
                        modulus = modulus.change_ring(FiniteField(p))
                    if not modulus.is_irreducible():
                        raise ValueError("finite field modulus must be irreducible but it is not.")
                    if modulus.degree() != n:
                        raise ValueError("The degree of the modulus does not correspond to the cardinality of the field.")
                if name is None:
                    raise TypeError("you must specify the generator name.")
                if impl is None:
                    if order < zech_log_bound:
                        # DO *NOT* use for prime subfield, since that would lead to
                        # a circular reference in the call to ParentWithGens in the
                        # __init__ method.
                        impl = 'givaro'
                    elif order % 2 == 0:
                        impl = 'ntl'
                    else:
                        impl = 'pari_ffelt'
                if impl == 'givaro':
                    if kwds.has_key('repr'):
                        repr = kwds['repr']
                    else:
                        repr = 'poly'
                    K = FiniteField_givaro(order, name, modulus, repr=repr, cache=elem_cache)
                elif impl == 'ntl':
                    from finite_field_ntl_gf2e import FiniteField_ntl_gf2e
                    K = FiniteField_ntl_gf2e(order, name, modulus)
                elif impl == 'pari_ffelt':
                    from finite_field_pari_ffelt import FiniteField_pari_ffelt
                    K = FiniteField_pari_ffelt(p, modulus, name)
                elif (impl == 'pari_mod'
                      or impl == 'pari'):    # for unpickling old pickles
                    from finite_field_ext_pari import FiniteField_ext_pari
                    K = FiniteField_ext_pari(order, name, modulus)
                else:
                    raise ValueError("no such finite field implementation: %s" % impl)

            # Temporary; see create_key_and_extra_args() above.
            if kwds.has_key('prefix'):
                K._prefix = kwds['prefix']

        return K
Exemplo n.º 29
0
def HyperellipticCurve(f, h=0, names=None, PP=None, check_squarefree=True):
    r"""
    Returns the hyperelliptic curve `y^2 + h y = f`, for
    univariate polynomials `h` and `f`. If `h`
    is not given, then it defaults to 0.

    INPUT:

    -  ``f`` - univariate polynomial

    -  ``h`` - optional univariate polynomial

    -  ``names``  (default: ``["x","y"]``) - names for the
       coordinate functions

    -  ``check_squarefree`` (default: ``True``) - test if
       the input defines a hyperelliptic curve when f is
       homogenized to degree `2g+2` and h to degree
       `g+1` for some g.

    .. WARNING::

        When setting ``check_squarefree=False`` or using a base ring that is
        not a field, the output curves are not to be trusted. For example, the
        output of ``is_singular`` is always ``False``, without this being
        properly tested in that case.

    .. NOTE::

        The words "hyperelliptic curve" are normally only used for curves of
        genus at least two, but this class allows more general smooth double
        covers of the projective line (conics and elliptic curves), even though
        the class is not meant for those and some outputs may be incorrect.

    EXAMPLES:

    Basic examples::

        sage: R.<x> = QQ[]
        sage: HyperellipticCurve(x^5 + x + 1)
        Hyperelliptic Curve over Rational Field defined by y^2 = x^5 + x + 1
        sage: HyperellipticCurve(x^19 + x + 1, x-2)
        Hyperelliptic Curve over Rational Field defined by y^2 + (x - 2)*y = x^19 + x + 1

        sage: k.<a> = GF(9); R.<x> = k[]
        sage: HyperellipticCurve(x^3 + x - 1, x+a)
        Hyperelliptic Curve over Finite Field in a of size 3^2 defined by y^2 + (x + a)*y = x^3 + x + 2

    Characteristic two::

        sage: P.<x> = GF(8,'a')[]
        sage: HyperellipticCurve(x^7+1, x)
        Hyperelliptic Curve over Finite Field in a of size 2^3 defined by y^2 + x*y = x^7 + 1
        sage: HyperellipticCurve(x^8+x^7+1, x^4+1)
        Hyperelliptic Curve over Finite Field in a of size 2^3 defined by y^2 + (x^4 + 1)*y = x^8 + x^7 + 1

        sage: HyperellipticCurve(x^8+1, x)
        Traceback (most recent call last):
        ...
        ValueError: Not a hyperelliptic curve: highly singular at infinity.

        sage: HyperellipticCurve(x^8+x^7+1, x^4)
        Traceback (most recent call last):
        ...
        ValueError: Not a hyperelliptic curve: singularity in the provided affine patch.

        sage: F.<t> = PowerSeriesRing(FiniteField(2))
        sage: P.<x> = PolynomialRing(FractionField(F))
        sage: HyperellipticCurve(x^5+t, x)
        Hyperelliptic Curve over Laurent Series Ring in t over Finite Field of size 2 defined by y^2 + x*y = x^5 + t

    We can change the names of the variables in the output::

        sage: k.<a> = GF(9); R.<x> = k[]
        sage: HyperellipticCurve(x^3 + x - 1, x+a, names=['X','Y'])
        Hyperelliptic Curve over Finite Field in a of size 3^2 defined by Y^2 + (X + a)*Y = X^3 + X + 2

    This class also allows curves of genus zero or one, which are strictly
    speaking not hyperelliptic::

        sage: P.<x> = QQ[]
        sage: HyperellipticCurve(x^2+1)
        Hyperelliptic Curve over Rational Field defined by y^2 = x^2 + 1
        sage: HyperellipticCurve(x^4-1)
        Hyperelliptic Curve over Rational Field defined by y^2 = x^4 - 1
        sage: HyperellipticCurve(x^3+2*x+2)
        Hyperelliptic Curve over Rational Field defined by y^2 = x^3 + 2*x + 2

    Double roots::

        sage: P.<x> = GF(7)[]
        sage: HyperellipticCurve((x^3-x+2)^2*(x^6-1))
        Traceback (most recent call last):
        ...
        ValueError: Not a hyperelliptic curve: singularity in the provided affine patch.

        sage: HyperellipticCurve((x^3-x+2)^2*(x^6-1), check_squarefree=False)
        Hyperelliptic Curve over Finite Field of size 7 defined by y^2 = x^12 + 5*x^10 + 4*x^9 + x^8 + 3*x^7 + 3*x^6 + 2*x^4 + 3*x^3 + 6*x^2 + 4*x + 3

    The input for a (smooth) hyperelliptic curve of genus `g` should not
    contain polynomials of degree greater than `2g+2`. In the following
    example, the hyperelliptic curve has genus 2 and there exists a model
    `y^2 = F` of degree 6, so the model `y^2 + yh = f` of degree 200 is not
    allowed.::

        sage: P.<x> = QQ[]
        sage: h = x^100
        sage: F = x^6+1
        sage: f = F-h^2/4
        sage: HyperellipticCurve(f, h)
        Traceback (most recent call last):
        ...
        ValueError: Not a hyperelliptic curve: highly singular at infinity.

        sage: HyperellipticCurve(F)
        Hyperelliptic Curve over Rational Field defined by y^2 = x^6 + 1

    An example with a singularity over an inseparable extension of the
    base field::

        sage: F.<t> = GF(5)[]
        sage: P.<x> = F[]
        sage: HyperellipticCurve(x^5+t)
        Traceback (most recent call last):
        ...
        ValueError: Not a hyperelliptic curve: singularity in the provided affine patch.

    Input with integer coefficients creates objects with the integers
    as base ring, but only checks smoothness over `\QQ`, not over Spec(`\ZZ`).
    In other words, it is checked that the discriminant is non-zero, but it is
    not checked whether the discriminant is a unit in `\ZZ^*`.::

        sage: P.<x> = ZZ[]
        sage: HyperellipticCurve(3*x^7+6*x+6)
        Hyperelliptic Curve over Integer Ring defined by y^2 = 3*x^7 + 6*x + 6

    TESTS:

    Check that `f` can be a constant (see :trac:`15516`)::

        sage: R.<u> = PolynomialRing(Rationals())
        sage: HyperellipticCurve(-12, u^4 + 7)
        Hyperelliptic Curve over Rational Field defined by y^2 + (x^4 + 7)*y = -12

    Check that two curves with the same class name have the same class type::

        sage: R.<t> = PolynomialRing(GF(next_prime(10^9)))
        sage: C = HyperellipticCurve(t^5 + t + 1)
        sage: C2 = HyperellipticCurve(t^5 + 3*t + 1)
        sage: type(C2) == type(C)
        True

    Check that the inheritance is correct::

        sage: R.<t> = PolynomialRing(GF(next_prime(10^9)))
        sage: C = HyperellipticCurve(t^5 + t + 1)
        sage: type(C).mro()
        [<class 'sage.schemes.hyperelliptic_curves.constructor.HyperellipticCurve_g2_FiniteField_with_category'>,
         <class 'sage.schemes.hyperelliptic_curves.constructor.HyperellipticCurve_g2_FiniteField'>,
         <class 'sage.schemes.hyperelliptic_curves.hyperelliptic_g2.HyperellipticCurve_g2'>,
         <class 'sage.schemes.hyperelliptic_curves.hyperelliptic_finite_field.HyperellipticCurve_finite_field'>,
         <class 'sage.schemes.hyperelliptic_curves.hyperelliptic_generic.HyperellipticCurve_generic'>,
        ...]
    """
    # F is the discriminant; use this for the type check
    # rather than f and h, one of which might be constant.
    F = h**2 + 4 * f
    if not is_Polynomial(F):
        raise TypeError("Arguments f (= %s) and h (= %s) must be polynomials" %
                        (f, h))
    P = F.parent()
    f = P(f)
    h = P(h)
    df = f.degree()
    dh_2 = 2 * h.degree()
    if dh_2 < df:
        g = (df - 1) // 2
    else:
        g = (dh_2 - 1) // 2
    if check_squarefree:
        # Assuming we are working over a field, this checks that after
        # resolving the singularity at infinity, we get a smooth double cover
        # of P^1.
        if P(2) == 0:
            # characteristic 2
            if h == 0:
                raise ValueError(
                    "In characteristic 2, argument h (= %s) must be non-zero."
                    % h)
            if h[g + 1] == 0 and f[2 * g + 1]**2 == f[2 * g + 2] * h[g]**2:
                raise ValueError("Not a hyperelliptic curve: " \
                                  "highly singular at infinity.")
            should_be_coprime = [h, f * h.derivative()**2 + f.derivative()**2]
        else:
            # characteristic not 2
            if not F.degree() in [2 * g + 1, 2 * g + 2]:
                raise ValueError("Not a hyperelliptic curve: " \
                                  "highly singular at infinity.")
            should_be_coprime = [F, F.derivative()]
        try:
            smooth = should_be_coprime[0].gcd(
                should_be_coprime[1]).degree() == 0
        except (AttributeError, NotImplementedError, TypeError):
            try:
                smooth = should_be_coprime[0].resultant(
                    should_be_coprime[1]) != 0
            except (AttributeError, NotImplementedError, TypeError):
                raise NotImplementedError("Cannot determine whether " \
                      "polynomials %s have a common root. Use " \
                      "check_squarefree=False to skip this check." % \
                      should_be_coprime)
        if not smooth:
            raise ValueError("Not a hyperelliptic curve: " \
                              "singularity in the provided affine patch.")
    R = P.base_ring()
    PP = ProjectiveSpace(2, R)
    if names is None:
        names = ["x", "y"]

    superclass = []
    cls_name = ["HyperellipticCurve"]

    genus_classes = {2: HyperellipticCurve_g2}

    fields = [("FiniteField", is_FiniteField, HyperellipticCurve_finite_field),
              ("RationalField", is_RationalField,
               HyperellipticCurve_rational_field),
              ("pAdicField", is_pAdicField, HyperellipticCurve_padic_field)]

    if g in genus_classes:
        superclass.append(genus_classes[g])
        cls_name.append("g%s" % g)

    for name, test, cls in fields:
        if test(R):
            superclass.append(cls)
            cls_name.append(name)
            break

    class_name = "_".join(cls_name)
    cls = dynamic_class(class_name,
                        tuple(superclass),
                        HyperellipticCurve_generic,
                        doccls=HyperellipticCurve)
    return cls(PP, f, h, names=names, genus=g)
Exemplo n.º 30
0
def HyperellipticCurve(f, h=None, names=None, PP=None, check_squarefree=True):
    r"""
    Returns the hyperelliptic curve `y^2 + h y = f`, for
    univariate polynomials `h` and `f`. If `h`
    is not given, then it defaults to 0.

    INPUT:

    -  ``f`` - univariate polynomial

    -  ``h`` - optional univariate polynomial

    -  ``names``  (default: ``["x","y"]``) - names for the
       coordinate functions

    -  ``check_squarefree`` (default: ``True``) - test if
       the input defines a hyperelliptic curve when f is
       homogenized to degree `2g+2` and h to degree
       `g+1` for some g.

    .. WARNING::

        When setting ``check_squarefree=False`` or using a base ring that is
        not a field, the output curves are not to be trusted. For example, the
        output of ``is_singular`` is always ``False``, without this being
        properly tested in that case.

    .. NOTE::

        The words "hyperelliptic curve" are normally only used for curves of
        genus at least two, but this class allows more general smooth double
        covers of the projective line (conics and elliptic curves), even though
        the class is not meant for those and some outputs may be incorrect.

    EXAMPLES:

    Basic examples::

        sage: R.<x> = QQ[]
        sage: HyperellipticCurve(x^5 + x + 1)
        Hyperelliptic Curve over Rational Field defined by y^2 = x^5 + x + 1
        sage: HyperellipticCurve(x^19 + x + 1, x-2)
        Hyperelliptic Curve over Rational Field defined by y^2 + (x - 2)*y = x^19 + x + 1

        sage: k.<a> = GF(9); R.<x> = k[]
        sage: HyperellipticCurve(x^3 + x - 1, x+a)
        Hyperelliptic Curve over Finite Field in a of size 3^2 defined by y^2 + (x + a)*y = x^3 + x + 2

    Characteristic two::

        sage: P.<x> = GF(8,'a')[]
        sage: HyperellipticCurve(x^7+1, x)
        Hyperelliptic Curve over Finite Field in a of size 2^3 defined by y^2 + x*y = x^7 + 1
        sage: HyperellipticCurve(x^8+x^7+1, x^4+1)
        Hyperelliptic Curve over Finite Field in a of size 2^3 defined by y^2 + (x^4 + 1)*y = x^8 + x^7 + 1

        sage: HyperellipticCurve(x^8+1, x)
        Traceback (most recent call last):
        ...
        ValueError: Not a hyperelliptic curve: highly singular at infinity.

        sage: HyperellipticCurve(x^8+x^7+1, x^4)
        Traceback (most recent call last):
        ...
        ValueError: Not a hyperelliptic curve: singularity in the provided affine patch.

        sage: F.<t> = PowerSeriesRing(FiniteField(2))
        sage: P.<x> = PolynomialRing(FractionField(F))
        sage: HyperellipticCurve(x^5+t, x)
        Hyperelliptic Curve over Laurent Series Ring in t over Finite Field of size 2 defined by y^2 + x*y = x^5 + t

    We can change the names of the variables in the output::

        sage: k.<a> = GF(9); R.<x> = k[]
        sage: HyperellipticCurve(x^3 + x - 1, x+a, names=['X','Y'])
        Hyperelliptic Curve over Finite Field in a of size 3^2 defined by Y^2 + (X + a)*Y = X^3 + X + 2

    This class also allows curves of genus zero or one, which are strictly
    speaking not hyperelliptic::

        sage: P.<x> = QQ[]
        sage: HyperellipticCurve(x^2+1)
        Hyperelliptic Curve over Rational Field defined by y^2 = x^2 + 1
        sage: HyperellipticCurve(x^4-1)
        Hyperelliptic Curve over Rational Field defined by y^2 = x^4 - 1
        sage: HyperellipticCurve(x^3+2*x+2)
        Hyperelliptic Curve over Rational Field defined by y^2 = x^3 + 2*x + 2

    Double roots::

        sage: P.<x> = GF(7)[]
        sage: HyperellipticCurve((x^3-x+2)^2*(x^6-1))
        Traceback (most recent call last):
        ...
        ValueError: Not a hyperelliptic curve: singularity in the provided affine patch.

        sage: HyperellipticCurve((x^3-x+2)^2*(x^6-1), check_squarefree=False)
        Hyperelliptic Curve over Finite Field of size 7 defined by y^2 = x^12 + 5*x^10 + 4*x^9 + x^8 + 3*x^7 + 3*x^6 + 2*x^4 + 3*x^3 + 6*x^2 + 4*x + 3

    The input for a (smooth) hyperelliptic curve of genus `g` should not
    contain polynomials of degree greater than `2g+2`. In the following
    example, the hyperelliptic curve has genus 2 and there exists a model
    `y^2 = F` of degree 6, so the model `y^2 + yh = f` of degree 200 is not
    allowed.::

        sage: P.<x> = QQ[]
        sage: h = x^100
        sage: F = x^6+1
        sage: f = F-h^2/4
        sage: HyperellipticCurve(f, h)
        Traceback (most recent call last):
        ...
        ValueError: Not a hyperelliptic curve: highly singular at infinity.

        sage: HyperellipticCurve(F)
        Hyperelliptic Curve over Rational Field defined by y^2 = x^6 + 1

    An example with a singularity over an inseparable extension of the
    base field::

        sage: F.<t> = GF(5)[]
        sage: P.<x> = F[]
        sage: HyperellipticCurve(x^5+t)
        Traceback (most recent call last):
        ...
        ValueError: Not a hyperelliptic curve: singularity in the provided affine patch.

    Input with integer coefficients creates objects with the integers
    as base ring, but only checks smoothness over `\QQ`, not over Spec(`\ZZ`).
    In other words, it is checked that the discriminant is non-zero, but it is
    not checked whether the discriminant is a unit in `\ZZ^*`.::

        sage: P.<x> = ZZ[]
        sage: HyperellipticCurve(3*x^7+6*x+6)
        Hyperelliptic Curve over Integer Ring defined by y^2 = 3*x^7 + 6*x + 6
    """
    if (not is_Polynomial(f)) or f == 0:
        raise TypeError, "Arguments f (=%s) and h (= %s) must be polynomials " \
                         "and f must be non-zero" % (f,h)
    P = f.parent()
    if h is None:
        h = P(0)
    try:
        h = P(h)
    except TypeError:
        raise TypeError, \
              "Arguments f (=%s) and h (= %s) must be polynomials in the same ring"%(f,h)
    df = f.degree()
    dh_2 = 2*h.degree()
    if dh_2 < df:
        g = (df-1)//2
    else:
        g = (dh_2-1)//2
    if check_squarefree:
        # Assuming we are working over a field, this checks that after
        # resolving the singularity at infinity, we get a smooth double cover
        # of P^1.
        if P(2) == 0:
            # characteristic 2
            if h == 0:
                raise ValueError, \
                   "In characteristic 2, argument h (= %s) must be non-zero."%h
            if h[g+1] == 0 and f[2*g+1]**2 == f[2*g+2]*h[g]**2:
                raise ValueError, "Not a hyperelliptic curve: " \
                                  "highly singular at infinity."
            should_be_coprime = [h, f*h.derivative()**2+f.derivative()**2]
        else:
            # characteristic not 2
            F = f + h**2/4
            if not F.degree() in [2*g+1, 2*g+2]:
                raise ValueError, "Not a hyperelliptic curve: " \
                                  "highly singular at infinity."
            should_be_coprime = [F, F.derivative()]
        try:
            smooth = should_be_coprime[0].gcd(should_be_coprime[1]).degree()==0
        except (AttributeError, NotImplementedError, TypeError):
            try:
                smooth = should_be_coprime[0].resultant(should_be_coprime[1])!=0
            except (AttributeError, NotImplementedError, TypeError):
                raise NotImplementedError, "Cannot determine whether " \
                      "polynomials %s have a common root. Use " \
                      "check_squarefree=False to skip this check." % \
                      should_be_coprime
        if not smooth:
            raise ValueError, "Not a hyperelliptic curve: " \
                              "singularity in the provided affine patch."
    R = P.base_ring()
    PP = ProjectiveSpace(2, R)
    if names is None:
        names = ["x","y"]
    if is_FiniteField(R):
        if g == 2:
            return HyperellipticCurve_g2_finite_field(PP, f, h, names=names, genus=g)
        else:
            return HyperellipticCurve_finite_field(PP, f, h, names=names, genus=g)
    elif is_RationalField(R):
        if g == 2:
            return HyperellipticCurve_g2_rational_field(PP, f, h, names=names, genus=g)
        else:
            return HyperellipticCurve_rational_field(PP, f, h, names=names, genus=g)
    elif is_pAdicField(R):
        if g == 2:
            return HyperellipticCurve_g2_padic_field(PP, f, h, names=names, genus=g)
        else:
            return HyperellipticCurve_padic_field(PP, f, h, names=names, genus=g)
    else:
        if g == 2:
            return HyperellipticCurve_g2_generic(PP, f, h, names=names, genus=g)
        else:
            return HyperellipticCurve_generic(PP, f, h, names=names, genus=g)
Exemplo n.º 31
0
    def create_object(self,
                      version,
                      key,
                      check_irreducible=True,
                      elem_cache=None,
                      names=None,
                      **kwds):
        """
        EXAMPLES::
        
            sage: K = GF(19)
            sage: TestSuite(K).run()
        """
        # IMPORTANT!  If you add a new class to the list of classes
        # that get cached by this factor object, then you *must* add
        # the following method to that class in order to fully support
        # pickling:
        #
        #     def __reduce__(self):   # and include good doctests, please!
        #         return self._factory_data[0].reduce_data(self)
        #
        # This is not in the base class for finite fields, since some finite
        # fields need not be created using this factory object, e.g., residue
        # class fields.

        if len(key) == 5:
            # for backward compatibility of pickles (see trac 10975).
            order, name, modulus, impl, _ = key
            p, n = arith.factor(order)[0]
            proof = True
        else:
            order, name, modulus, impl, _, p, n, proof = key

        if isinstance(modulus, str) and modulus.startswith("random"):
            modulus = "random"

        if elem_cache is None:
            elem_cache = order < 500

        if n == 1 and (impl is None or impl == 'modn'):
            from finite_field_prime_modn import FiniteField_prime_modn
            # Using a check option here is probably a worthwhile
            # compromise since this constructor is simple and used a
            # huge amount.
            K = FiniteField_prime_modn(order, check=False, **kwds)
        else:
            # We have to do this with block so that the finite field
            # constructors below will use the proof flag that was
            # passed in when checking for primality, factoring, etc.
            # Otherwise, we would have to complicate all of their
            # constructors with check options (like above).
            from sage.structure.proof.all import WithProof
            with WithProof('arithmetic', proof):
                if check_irreducible and polynomial_element.is_Polynomial(
                        modulus):
                    if modulus.parent().base_ring().characteristic() == 0:
                        modulus = modulus.change_ring(FiniteField(p))
                    if not modulus.is_irreducible():
                        raise ValueError(
                            "finite field modulus must be irreducible but it is not."
                        )
                    if modulus.degree() != n:
                        raise ValueError(
                            "The degree of the modulus does not correspond to the cardinality of the field."
                        )
                if name is None:
                    raise TypeError("you must specify the generator name.")
                if order < zech_log_bound:
                    # DO *NOT* use for prime subfield, since that would lead to
                    # a circular reference in the call to ParentWithGens in the
                    # __init__ method.
                    K = FiniteField_givaro(order,
                                           name,
                                           modulus,
                                           cache=elem_cache,
                                           **kwds)
                else:
                    if order % 2 == 0 and (impl is None or impl == 'ntl'):
                        from element_ntl_gf2e import FiniteField_ntl_gf2e
                        K = FiniteField_ntl_gf2e(order, name, modulus, **kwds)
                    else:
                        from finite_field_ext_pari import FiniteField_ext_pari
                        K = FiniteField_ext_pari(order, name, modulus, **kwds)

        return K
Exemplo n.º 32
0
    def __call__(self, P):
        r"""
        Returns a rational point P in the abstract Homset J(K), given:

        0. A point P in J = Jac(C), returning P; 1. A point P on the curve
        C such that J = Jac(C), where C is an odd degree model, returning
        [P - oo]; 2. A pair of points (P, Q) on the curve C such that J =
        Jac(C), returning [P-Q]; 2. A list of polynomials (a,b) such that
        `b^2 + h*b - f = 0 mod a`, returning [(a(x),y-b(x))].

        EXAMPLES::

            sage: P.<x> = PolynomialRing(QQ)
            sage: f = x^5 - x + 1; h = x
            sage: C = HyperellipticCurve(f,h,'u,v')
            sage: P = C(0,1,1)
            sage: J = C.jacobian()
            sage: Q = J(QQ)(P)
            sage: for i in range(6): i*Q
            (1)
            (u, v - 1)
            (u^2, v + u - 1)
            (u^2, v + 1)
            (u, v + 1)
            (1)

        ::

            sage: F.<a> = GF(3)
            sage: R.<x> = F[]
            sage: f = x^5-1
            sage: C = HyperellipticCurve(f)
            sage: J = C.jacobian()
            sage: X = J(F)
            sage: a = x^2-x+1
            sage: b = -x +1
            sage: c = x-1
            sage: d = 0
            sage: D1 = X([a,b])
            sage: D1
            (x^2 + 2*x + 1, y + x + 2)
            sage: D2 = X([c,d])
            sage: D2
            (x + 2, y)
            sage: D1+D2
            (x^2 + 2*x + 2, y + 2*x + 1)

        """
        if isinstance(P,(int,long,Integer)) and P == 0:
            R = PolynomialRing(self.value_ring(), 'x')
            return JacobianMorphism_divisor_class_field(self, (R(1),R(0)))
        elif isinstance(P,(list,tuple)):
            if len(P) == 1 and P[0] == 0:
                R = PolynomialRing(self.value_ring(), 'x')
                return JacobianMorphism_divisor_class_field(self, (R(1),R(0)))
            elif len(P) == 2:
                P1 = P[0]
                P2 = P[1]
                if is_Integer(P1) and is_Integer(P2):
                    R = PolynomialRing(self.value_ring(), 'x')
                    P1 = R(P1)
                    P2 = R(P2)
                    return JacobianMorphism_divisor_class_field(self, tuple([P1,P2]))
                if is_Integer(P1) and is_Polynomial(P2):
                    R = PolynomialRing(self.value_ring(), 'x')
                    P1 = R(P1)
                    return JacobianMorphism_divisor_class_field(self, tuple([P1,P2]))
                if is_Integer(P2) and is_Polynomial(P1):
                    R = PolynomialRing(self.value_ring(), 'x')
                    P2 = R(P2)
                    return JacobianMorphism_divisor_class_field(self, tuple([P1,P2]))
                if is_Polynomial(P1) and is_Polynomial(P2):
                    return JacobianMorphism_divisor_class_field(self, tuple(P))
                if is_SchemeMorphism(P1) and is_SchemeMorphism(P2):
                    return self(P1) - self(P2)
            raise TypeError("Argument P (= %s) must have length 2."%P)
        elif isinstance(P,JacobianMorphism_divisor_class_field) and self == P.parent():
            return P
        elif is_SchemeMorphism(P):
            x0 = P[0]; y0 = P[1]
            R, x = PolynomialRing(self.value_ring(), 'x').objgen()
            return self((x-x0,R(y0)))
        raise TypeError("Argument P (= %s) does not determine a divisor class"%P)