Beispiel #1
0
def _negaconvolution_fft(L1, L2, n):
   """
   Returns negacyclic convolution of lists L1 and L2, using FFT
   algorithm. L1 and L2 must both be length `2^n`, where
   `n \geq 3`. Assumes all entries of L1 and L2 belong to the
   same ring.

   EXAMPLES::

       sage: from sage.rings.polynomial.convolution import _negaconvolution_naive
       sage: from sage.rings.polynomial.convolution import _negaconvolution_fft
       sage: _negaconvolution_naive(range(8), range(5, 13))
       [-224, -234, -224, -192, -136, -54, 56, 196]
       sage: _negaconvolution_fft(range(8), range(5, 13), 3)
       [-224, -234, -224, -192, -136, -54, 56, 196]

   ::

       sage: for n in range(3, 10):
       ...      L1 = [ZZ.random_element(100) for _ in range(1 << n)]
       ...      L2 = [ZZ.random_element(100) for _ in range(1 << n)]
       ...      assert _negaconvolution_naive(L1, L2) == _negaconvolution_fft(L1, L2, n)
"""
   assert n >= 3

   R = parent(L1[0])

   # split into 2^m pieces of 2^(k-1) coefficients each, with k as small
   # as possible, subject to m <= k (so that the ring of Fourier coefficients
   # has enough roots of unity)
   m = (n + 1) >> 1
   k = n + 1 - m

   M = 1 << m
   K = 1 << k

   # split inputs into polynomials
   L1 = _split(L1, m, k)
   L2 = _split(L2, m, k)

   # fft each input
   _fft(L1, K, 0, m, K >> 1)
   _fft(L2, K, 0, m, K >> 1)

   # pointwise multiply
   L3 = [_negaconvolution(L1[i], L2[i], k) for i in range(M)]

   # inverse fft
   _ifft(L3, K, 0, m, K >> 1)

   # combine back into a single list
   L3 = _nega_combine(L3, m, k)

   # normalise
   return [R(x / M) for x in L3]
    def eval_formula(self, n, x):
        """
        Evaluate ``chebyshev_T`` using an explicit formula.
        See [ASHandbook]_ 227 (p. 782) for details for the recurions.
        See also [EffCheby]_ for fast evaluation techniques.

        INPUT:

        - ``n`` -- an integer

        - ``x`` -- a value to evaluate the polynomial at (this can be
          any ring element)

        EXAMPLES::

            sage: chebyshev_T.eval_formula(-1,x)
            x
            sage: chebyshev_T.eval_formula(0,x)
            1
            sage: chebyshev_T.eval_formula(1,x)
            x
            sage: chebyshev_T.eval_formula(2,0.1) == chebyshev_T._evalf_(2,0.1)
            True
            sage: chebyshev_T.eval_formula(10,x)
            512*x^10 - 1280*x^8 + 1120*x^6 - 400*x^4 + 50*x^2 - 1
            sage: chebyshev_T.eval_algebraic(10,x).expand()
            512*x^10 - 1280*x^8 + 1120*x^6 - 400*x^4 + 50*x^2 - 1
        """
        if n < 0:
            return self.eval_formula(-n, x)
        elif n == 0:
            return parent(x).one()

        res = parent(x).zero()
        for j in xrange(0, n//2+1):
            f = factorial(n-1-j) / factorial(j) / factorial(n-2*j)
            res += (-1)**j * (2*x)**(n-2*j) * f
        res *= n/2
        return res
Beispiel #3
0
    def _element_constructor_(self, *x, **kwds):
        r"""
        Construct an element of ``self``.

        INPUT:

        - element of a compatible toric object (lattice, sublattice, quotient)
          or something that defines such an element (list, generic vector,
          etc.).

        OUTPUT:

        - :class:`toric lattice quotient element
          <ToricLattice_quotient_element>`.

        EXAMPLES::

            sage: N = ToricLattice(3)
            sage: Ns = N.submodule([N(2,4,0), N(9,12,0)])
            sage: Q = N/Ns
            sage: x = Q(1,2,3)  # indirect doctest
            sage: x
            N[1, 2, 3]
            sage: type(x)
            <class 'sage.geometry.toric_lattice.ToricLattice_quotient_with_category.element_class'>
            sage: x is Q(x)
            True
            sage: x.parent() is Q
            True
            sage: x == Q(N(1,2,3))
            True
            sage: y = Q(3,6,3)
            sage: y
            N[3, 6, 3]
            sage: x == y
            True
        """
        if len(x) == 1 and (x[0] not in ZZ or x[0] == 0):
            x = x[0]
        if parent(x) is self:
            return x
        try:
            x = x.lift()
        except AttributeError:
            pass
        try:
            return self.element_class(self, self._V(x), **kwds)
        except TypeError:
            return self.linear_combination_of_smith_form_gens(x)
Beispiel #4
0
    def _element_constructor_(self, *x, **kwds):
        r"""
        Construct an element of ``self``.

        INPUT:

        - element of a compatible toric object (lattice, sublattice, quotient)
          or something that defines such an element (list, generic vector,
          etc.).

        OUTPUT:

        - :class:`toric lattice quotient element
          <ToricLattice_quotient_element>`.

        EXAMPLES::

            sage: N = ToricLattice(3)
            sage: Ns = N.submodule([N(2,4,0), N(9,12,0)])
            sage: Q = N/Ns
            sage: x = Q(1,2,3)  # indirect doctest
            sage: x
            N[1, 2, 3]
            sage: type(x)
            <class 'sage.geometry.toric_lattice.ToricLattice_quotient_with_category.element_class'>
            sage: x is Q(x)
            True
            sage: x.parent() is Q
            True
            sage: x == Q(N(1,2,3))
            True
            sage: y = Q(3,6,3)
            sage: y
            N[3, 6, 3]
            sage: x == y
            True
        """
        if len(x) == 1 and (x[0] not in ZZ or x[0] == 0):
            x = x[0]
        if parent(x) is self:
            return x
        try:
            x = x.lift()
        except AttributeError:
            pass
        try:
            return self.element_class(self, self._V(x), **kwds)
        except TypeError:
            return self.linear_combination_of_smith_form_gens(x)
Beispiel #5
0
    def __contains__(self, x):
        r"""
        Check in the element x is in the mathematical parent self.

        EXAMPLES::

            sage: D5 = FiniteCoxeterGroups().example()
            sage: D5.an_element() in D5
            True
            sage: 1 in D5
            False

        (also tested by :meth:`test_an_element` :meth:`test_some_elements`)
        """
        from sage.structure.all import parent
        return parent(x) is self
    def eval_algebraic(self, n, x):
        """
        Evaluate :class:`chebyshev_U` as polynomial, using a recursive
        formula.

        INPUT:

        - ``n`` -- an integer

        - ``x`` -- a value to evaluate the polynomial at (this can be
          any ring element)

        EXAMPLES::

            sage: chebyshev_U.eval_algebraic(5,x)
            -2*((2*x + 1)*(2*x - 1)*x - 4*(2*x^2 - 1)*x)*(2*x + 1)*(2*x - 1)
            sage: parent(chebyshev_U(3, Mod(8,9)))
            Ring of integers modulo 9
            sage: parent(chebyshev_U(3, Mod(1,9)))
            Ring of integers modulo 9
            sage: chebyshev_U(-3,x) + chebyshev_U(1,x)
            0
            sage: chebyshev_U(-1,Mod(5,8))
            0
            sage: parent(chebyshev_U(-1,Mod(5,8)))
            Ring of integers modulo 8
            sage: R.<t> = ZZ[]
            sage: chebyshev_U.eval_algebraic(-2, t)
            -1
            sage: chebyshev_U.eval_algebraic(-1, t)
            0
            sage: chebyshev_U.eval_algebraic(0, t)
            1
            sage: chebyshev_U.eval_algebraic(1, t)
            2*t
            sage: n = 97; x = RIF(pi/n)
            sage: chebyshev_U(n-1, cos(x)).contains_zero()
            True
            sage: R.<t> = Zp(2, 6, 'capped-abs')[]
            sage: chebyshev_U(10^6+1, t)
            (2 + O(2^6))*t + (O(2^6))
        """
        if n == -1:
            return parent(x).zero()
        if n < 0:
            return -self._eval_recursive_(-n-2, x)[0]
        return self._eval_recursive_(n, x)[0]
Beispiel #7
0
    def __call__(self, x):
        """
        Evaluate this matrix morphism at an element that can be coerced
        into the domain.

        EXAMPLES::

            sage: V = QQ^3; W = QQ^2
            sage: H = Hom(V, W); H
            Set of Morphisms (Linear Transformations) from
            Vector space of dimension 3 over Rational Field to
            Vector space of dimension 2 over Rational Field
            sage: phi = H(matrix(QQ, 3, 2, range(6))); phi
            Vector space morphism represented by the matrix:
            [0 1]
            [2 3]
            [4 5]
            Domain: Vector space of dimension 3 over Rational Field
            Codomain: Vector space of dimension 2 over Rational Field
            sage: phi(V.0)
            (0, 1)
            sage: phi([1,2,3])
            (16, 22)
            sage: phi(5)
            Traceback (most recent call last):
            ...
            TypeError: 5 must be coercible into Vector space of dimension 3 over Rational Field
            sage: phi([1,1])
            Traceback (most recent call last):
            ...
            TypeError: [1, 1] must be coercible into Vector space of dimension 3 over Rational Field
        """
        try:
            if parent(x) is not self.domain():
                x = self.domain()(x)
        except TypeError:
            raise TypeError("%s must be coercible into %s"%(x,self.domain()))
        if self.domain().is_ambient():
            x = x.element()
        else:
            x = self.domain().coordinate_vector(x)
        v = x*self.matrix()
        C = self.codomain()
        if C.is_ambient():
            return C(v)
        return C(C.linear_combination_of_basis(v), check=False)
Beispiel #8
0
    def _coerce_impl(self, x):
        """
        Coerce x into self, if possible.

        EXAMPLES::

            sage: J = J0(37) ; J.Hom(J)._coerce_impl(matrix(ZZ,4,[5..20]))
            Abelian variety endomorphism of Abelian variety J0(37) of dimension 2
            sage: K = J0(11) * J0(11) ; J.Hom(K)._coerce_impl(matrix(ZZ,4,[5..20]))
            Abelian variety morphism:
              From: Abelian variety J0(37) of dimension 2
              To:   Abelian variety J0(11) x J0(11) of dimension 2
        """
        if self.matrix_space().has_coerce_map_from(parent(x)):
            return self(x)
        else:
            return HomsetWithBase._coerce_impl(self, x)
Beispiel #9
0
def squarefree_part(x):
    """
    Return the square free part of ``x``, i.e., a divisor
    `z` such that `x = z y^2`, for a perfect square
    `y^2`.

    EXAMPLES::

        sage: squarefree_part(100)
        1
        sage: squarefree_part(12)
        3
        sage: squarefree_part(10)
        10
        sage: squarefree_part(216r) # see #8976
        6

    ::

        sage: x = QQ['x'].0
        sage: S = squarefree_part(-9*x*(x-6)^7*(x-3)^2); S
        -9*x^2 + 54*x
        sage: S.factor()
        (-9) * (x - 6) * x

    ::

        sage: f = (x^3 + x + 1)^3*(x-1); f
        x^10 - x^9 + 3*x^8 + 3*x^5 - 2*x^4 - x^3 - 2*x - 1
        sage: g = squarefree_part(f); g
        x^4 - x^3 + x^2 - 1
        sage: g.factor()
        (x - 1) * (x^3 + x + 1)
    """
    try:
        return x.squarefree_part()
    except AttributeError:
        pass
    from sage.arith.all import factor
    from sage.structure.all import parent
    F = factor(x)
    n = parent(x)(1)
    for p, e in F:
        if e % 2:
            n *= p
    return n * F.unit()
Beispiel #10
0
def _split(L, m, k):
   """
   Assumes L is a list of length `2^{m+k-1}`. Splits it into
   `2^m` lists of length `2^{k-1}`, returned as a list
   of lists. Each list is zero padded up to length `2^k`.

   EXAMPLES::

       sage: from sage.rings.polynomial.convolution import _split
       sage: _split([1, 2, 3, 4, 5, 6, 7, 8], 2, 2)
       [[1, 2, 0, 0], [3, 4, 0, 0], [5, 6, 0, 0], [7, 8, 0, 0]]
       sage: _split([1, 2, 3, 4, 5, 6, 7, 8], 1, 3)
       [[1, 2, 3, 4, 0, 0, 0, 0], [5, 6, 7, 8, 0, 0, 0, 0]]
       sage: _split([1, 2, 3, 4, 5, 6, 7, 8], 3, 1)
       [[1, 0], [2, 0], [3, 0], [4, 0], [5, 0], [6, 0], [7, 0], [8, 0]]
   """
   K = 1 << (k-1)
   zero = parent(L[0])(0)
   zeroes = [zero] * K
   return [[L[i+j] for j in range(K)] + zeroes for i in range(0, K << m, K)]
Beispiel #11
0
    def eval_algebraic(self, n, x):
        """
        Evaluate :class:`chebyshev_T` as polynomial, using a recursive
        formula.

        INPUT:

        - ``n`` -- an integer

        - ``x`` -- a value to evaluate the polynomial at (this can be
          any ring element)

        EXAMPLES::

            sage: chebyshev_T.eval_algebraic(5, x)
            2*(2*(2*x^2 - 1)*x - x)*(2*x^2 - 1) - x
            sage: chebyshev_T(-7, x) - chebyshev_T(7,x)
            0
            sage: R.<t> = ZZ[]
            sage: chebyshev_T.eval_algebraic(-1, t)
            t
            sage: chebyshev_T.eval_algebraic(0, t)
            1
            sage: chebyshev_T.eval_algebraic(1, t)
            t
            sage: chebyshev_T(7^100, 1/2)
            1/2
            sage: chebyshev_T(7^100, Mod(2,3))
            2
            sage: n = 97; x = RIF(pi/2/n)
            sage: chebyshev_T(n, cos(x)).contains_zero()
            True
            sage: R.<t> = Zp(2, 8, 'capped-abs')[]
            sage: chebyshev_T(10^6+1, t)
            (2^7 + O(2^8))*t^5 + (O(2^8))*t^4 + (2^6 + O(2^8))*t^3 + (O(2^8))*t^2 + (1 + 2^6 + O(2^8))*t + (O(2^8))
        """
        if n == 0:
            return parent(x).one()
        if n < 0:
            return self._eval_recursive_(-n, x)[0]
        return self._eval_recursive_(n, x)[0]
Beispiel #12
0
    def _eval_recursive_(self, n, x, both=False):
        """
        If ``both=True``, compute ``(U(n,x), U(n-1,x))`` using a
        recursive formula.
        If ``both=False``, return instead a tuple ``(U(n,x), False)``.

        EXAMPLES::

            sage: chebyshev_U._eval_recursive_(3, x)
            (4*((2*x + 1)*(2*x - 1) - 2*x^2)*x, False)
            sage: chebyshev_U._eval_recursive_(3, x, True)
            (4*((2*x + 1)*(2*x - 1) - 2*x^2)*x, ((2*x + 1)*(2*x - 1) + 2*x)*((2*x + 1)*(2*x - 1) - 2*x))
        """
        if n == 0:
            return parent(x).one(), 2*x

        assert n >= 1
        a, b = self._eval_recursive_((n-1)//2, x, True)
        if n % 2 == 0:
            return (b+a)*(b-a), both and 2*b*(x*b-a)
        else:
            return 2*a*(b-x*a), both and (b+a)*(b-a)
Beispiel #13
0
    def _evalf_(self, n, x, **kwds):
        """
        Evaluate :class:`chebyshev_U` numerically with mpmath.

        EXAMPLES::

            sage: chebyshev_U(5,-4+3.*I)
            98280.0000000000 - 11310.0000000000*I
            sage: chebyshev_U(10,3).n(75)
            4.661117900000000000000e7
            sage: chebyshev_U._evalf_(1.5, Mod(8,9))
            Traceback (most recent call last):
            ...
            TypeError: cannot evaluate chebyshev_U with parent Ring of integers modulo 9
        """
        try:
            real_parent = kwds['parent']
        except KeyError:
            real_parent = parent(x)

            if not is_RealField(real_parent) and not is_ComplexField(
                    real_parent):
                # parent is not a real or complex field: figure out a good parent
                if x in RR:
                    x = RR(x)
                    real_parent = RR
                elif x in CC:
                    x = CC(x)
                    real_parent = CC

        if not is_RealField(real_parent) and not is_ComplexField(real_parent):
            raise TypeError(
                "cannot evaluate chebyshev_U with parent {}".format(
                    real_parent))

        from sage.libs.mpmath.all import call as mpcall
        from sage.libs.mpmath.all import chebyu as mpchebyu

        return mpcall(mpchebyu, n, x, parent=real_parent)
Beispiel #14
0
    def _eval_recursive_(self, n, x, both=False):
        """
        If ``both=True``, compute ``(U(n,x), U(n-1,x))`` using a
        recursive formula.
        If ``both=False``, return instead a tuple ``(U(n,x), False)``.

        EXAMPLES::

            sage: chebyshev_U._eval_recursive_(3, x)
            (4*((2*x + 1)*(2*x - 1) - 2*x^2)*x, False)
            sage: chebyshev_U._eval_recursive_(3, x, True)
            (4*((2*x + 1)*(2*x - 1) - 2*x^2)*x, ((2*x + 1)*(2*x - 1) + 2*x)*((2*x + 1)*(2*x - 1) - 2*x))
        """
        if n == 0:
            return parent(x).one(), 2 * x

        assert n >= 1
        a, b = self._eval_recursive_((n - 1) // 2, x, True)
        if n % 2 == 0:
            return (b + a) * (b - a), both and 2 * b * (x * b - a)
        else:
            return 2 * a * (b - x * a), both and (b + a) * (b - a)
Beispiel #15
0
    def _eval_recursive_(self, n, x, both=False):
        """
        If ``both=True``, compute ``(T(n,x), T(n-1,x))`` using a
        recursive formula.
        If ``both=False``, return instead a tuple ``(T(n,x), False)``.

        EXAMPLES::

            sage: chebyshev_T._eval_recursive_(5, x)
            (2*(2*(2*x^2 - 1)*x - x)*(2*x^2 - 1) - x, False)
            sage: chebyshev_T._eval_recursive_(5, x, True)
            (2*(2*(2*x^2 - 1)*x - x)*(2*x^2 - 1) - x, 2*(2*x^2 - 1)^2 - 1)
        """
        if n == 1:
            return x, parent(x).one()

        assert n >= 2
        a, b = self._eval_recursive_((n+1)//2, x, both or n % 2)
        if n % 2 == 0:
            return 2*a*a - 1, both and 2*a*b - x
        else:
            return 2*a*b - x, both and 2*b*b - 1
Beispiel #16
0
    def _evalf_(self, n, x, **kwds):
        """
        Evaluate :class:`chebyshev_U` numerically with mpmath.

        EXAMPLES::

            sage: chebyshev_U(5,-4+3.*I)
            98280.0000000000 - 11310.0000000000*I
            sage: chebyshev_U(10,3).n(75)
            4.661117900000000000000e7
            sage: chebyshev_U._evalf_(1.5, Mod(8,9))
            Traceback (most recent call last):
            ...
            TypeError: cannot evaluate chebyshev_U with parent Ring of integers modulo 9
        """
        try:
            real_parent = kwds['parent']
        except KeyError:
            real_parent = parent(x)

            if not is_RealField(real_parent) and not is_ComplexField(real_parent):
                # parent is not a real or complex field: figure out a good parent
                if x in RR:
                    x = RR(x)
                    real_parent = RR
                elif x in CC:
                    x = CC(x)
                    real_parent = CC

        if not is_RealField(real_parent) and not is_ComplexField(real_parent):
            raise TypeError("cannot evaluate chebyshev_U with parent {}".format(real_parent))

        from sage.libs.mpmath.all import call as mpcall
        from sage.libs.mpmath.all import chebyu as mpchebyu

        return mpcall(mpchebyu, n, x, parent=real_parent)
Beispiel #17
0
    def eval_formula(self, n, x):
        """
        Evaluate ``chebyshev_U`` using an explicit formula.
        See [ASHandbook]_ 227 (p. 782) for details on the recurions.
        See also [EffCheby]_ for the recursion formulas.

        INPUT:

        - ``n`` -- an integer

        - ``x`` -- a value to evaluate the polynomial at (this can be
          any ring element)

        EXAMPLES::

            sage: chebyshev_U.eval_formula(10, x)
            1024*x^10 - 2304*x^8 + 1792*x^6 - 560*x^4 + 60*x^2 - 1
            sage: chebyshev_U.eval_formula(-2, x)
            -1
            sage: chebyshev_U.eval_formula(-1, x)
            0
            sage: chebyshev_U.eval_formula(0, x)
            1
            sage: chebyshev_U.eval_formula(1, x)
            2*x
            sage: chebyshev_U.eval_formula(2,0.1) == chebyshev_U._evalf_(2,0.1)
            True
        """
        if n < -1:
            return -self.eval_formula(-n-2, x)

        res = parent(x).zero()
        for j in xrange(0, n//2+1):
            f = binomial(n-j, j)
            res += (-1)**j * (2*x)**(n-2*j) * f
        return res
Beispiel #18
0
    def __call__(self, M):
        r"""
        Create a homomorphism in this space from M. M can be any of the
        following:

        - a Morphism of abelian varieties

        - a matrix of the appropriate size
          (i.e. 2\*self.domain().dimension() x
          2\*self.codomain().dimension()) whose entries are coercible
          into self.base_ring()

        - anything that can be coerced into self.matrix_space()

        EXAMPLES::

            sage: H = Hom(J0(11), J0(22))
            sage: phi = H(matrix(ZZ,2,4,[5..12])) ; phi
            Abelian variety morphism:
              From: Abelian variety J0(11) of dimension 1
              To:   Abelian variety J0(22) of dimension 2
            sage: phi.matrix()
            [ 5  6  7  8]
            [ 9 10 11 12]
            sage: phi.matrix().parent()
            Full MatrixSpace of 2 by 4 dense matrices over Integer Ring

        ::

            sage: H = J0(22).Hom(J0(11)*J0(11))
            sage: m1 = J0(22).degeneracy_map(11,1).matrix() ; m1
            [ 0  1]
            [-1  1]
            [-1  0]
            [ 0 -1]
            sage: m2 = J0(22).degeneracy_map(11,2).matrix() ; m2
            [ 1 -2]
            [ 0 -2]
            [ 1 -1]
            [ 0 -1]
            sage: m = m1.transpose().stack(m2.transpose()).transpose() ; m
            [ 0  1  1 -2]
            [-1  1  0 -2]
            [-1  0  1 -1]
            [ 0 -1  0 -1]
            sage: phi = H(m) ; phi
            Abelian variety morphism:
              From: Abelian variety J0(22) of dimension 2
              To:   Abelian variety J0(11) x J0(11) of dimension 2
            sage: phi.matrix()
            [ 0  1  1 -2]
            [-1  1  0 -2]
            [-1  0  1 -1]
            [ 0 -1  0 -1]
        """
        if isinstance(M, morphism.Morphism):
            if M.parent() is self:
                return M
            elif M.domain() == self.domain() and M.codomain() == self.codomain():
                M = M.matrix()
            else:
                raise ValueError("cannot convert %s into %s" % (M, self))
        elif is_Matrix(M):
            if M.base_ring() != ZZ:
                M = M.change_ring(ZZ)
            if M.nrows() != 2*self.domain().dimension() or M.ncols() != 2*self.codomain().dimension():
                raise TypeError("matrix has wrong dimension")
        elif self.matrix_space().has_coerce_map_from(parent(M)):
            M = self.matrix_space()(M)
        else:
            raise TypeError("can only coerce in matrices or morphisms")
        return self.element_class(self, M)
Beispiel #19
0
    def _evalf_(self, n, x, **kwds):
        """
        Evaluates :class:`chebyshev_T` numerically with mpmath.

        EXAMPLES::

            sage: chebyshev_T._evalf_(10,3)
            2.26195370000000e7
            sage: chebyshev_T._evalf_(10,3,parent=RealField(75))
            2.261953700000000000000e7
            sage: chebyshev_T._evalf_(10,I)
            -3363.00000000000
            sage: chebyshev_T._evalf_(5,0.3)
            0.998880000000000
            sage: chebyshev_T(1/2, 0)
            0.707106781186548
            sage: chebyshev_T(1/2, 3/2)
            1.11803398874989
            sage: chebyshev_T._evalf_(1.5, Mod(8,9))
            Traceback (most recent call last):
            ...
            TypeError: cannot evaluate chebyshev_T with parent Ring of integers modulo 9

        This simply evaluates using :class:`RealField` or :class:`ComplexField`::

            sage: chebyshev_T(1234.5, RDF(2.1))
            5.48174256255782e735
            sage: chebyshev_T(1234.5, I)
            -1.21629397684152e472 - 1.21629397684152e472*I

        For large values of ``n``, mpmath fails (but the algebraic formula
        still works)::

            sage: chebyshev_T._evalf_(10^6, 0.1)
            Traceback (most recent call last):
            ...
            NoConvergence: Hypergeometric series converges too slowly. Try increasing maxterms.
            sage: chebyshev_T(10^6, 0.1)
            0.636384327171504
        """
        try:
            real_parent = kwds['parent']
        except KeyError:
            real_parent = parent(x)

            if not is_RealField(real_parent) and not is_ComplexField(real_parent):
                # parent is not a real or complex field: figure out a good parent
                if x in RR:
                    x = RR(x)
                    real_parent = RR
                elif x in CC:
                    x = CC(x)
                    real_parent = CC

        if not is_RealField(real_parent) and not is_ComplexField(real_parent):
            raise TypeError("cannot evaluate chebyshev_T with parent {}".format(real_parent))

        from sage.libs.mpmath.all import call as mpcall
        from sage.libs.mpmath.all import chebyt as mpchebyt

        return mpcall(mpchebyt, n, x, parent=real_parent)
    def _call_(self, x):
        """
        Evaluate this matrix morphism at an element of the domain.

        .. NOTE::

            Coercion is done in the generic :meth:`__call__` method,
            which calls this method.

        EXAMPLES::

            sage: V = QQ^3; W = QQ^2
            sage: H = Hom(V, W); H
            Set of Morphisms (Linear Transformations) from
            Vector space of dimension 3 over Rational Field to
            Vector space of dimension 2 over Rational Field
            sage: phi = H(matrix(QQ, 3, 2, range(6))); phi
            Vector space morphism represented by the matrix:
            [0 1]
            [2 3]
            [4 5]
            Domain: Vector space of dimension 3 over Rational Field
            Codomain: Vector space of dimension 2 over Rational Field
            sage: phi(V.0)
            (0, 1)
            sage: phi(V([1, 2, 3]))
            (16, 22)

        Last, we have a situation where coercion occurs::

            sage: U = V.span([[3,2,1]])
            sage: U.0
            (1, 2/3, 1/3)
            sage: phi(2*U.0)
            (16/3, 28/3)

        TESTS::

            sage: V = QQ^3; W = span([[1,2,3],[-1,2,5/3]], QQ)
            sage: phi = V.hom(matrix(QQ,3,[1..9]))

        We compute the image of some elements::

            sage: phi(V.0)    #indirect doctest
            (1, 2, 3)
            sage: phi(V.1)
            (4, 5, 6)
            sage: phi(V.0  - 1/4*V.1)
            (0, 3/4, 3/2)

        We restrict ``phi`` to ``W`` and compute the image of an element::

            sage: psi = phi.restrict_domain(W)
            sage: psi(W.0) == phi(W.0)
            True
            sage: psi(W.1) == phi(W.1)
            True
        """
        try:
            if parent(x) is not self.domain():
                x = self.domain()(x)
        except TypeError:
            raise TypeError("%s must be coercible into %s"%(x,self.domain()))
        if self.domain().is_ambient():
            x = x.element()
        else:
            x = self.domain().coordinate_vector(x)
        C = self.codomain()
        v = x.change_ring(C.base_ring()) * self.matrix()
        if not C.is_ambient():
            v = C.linear_combination_of_basis(v)
        # The call method of parents uses (coercion) morphisms.
        # Hence, in order to avoid recursion, we call the element
        # constructor directly; after all, we already know the
        # coordinates.
        return C._element_constructor_(v)
Beispiel #21
0
def slider(vmin, vmax=None, step_size=None, default=None, label=None, display_value=True, _range=False):
    """
    A slider widget.

    INPUT:

    For a numeric slider (select a value from a range):

    - ``vmin``, ``vmax`` -- minimum and maximum value

    - ``step_size`` -- the step size

    For a selection slider (select a value from a list of values):

    - ``vmin`` -- a list of possible values for the slider

    For all sliders:

    - ``default`` -- initial value

    - ``label`` -- optional label

    - ``display_value`` -- (boolean) if ``True``, display the current
      value.

    EXAMPLES::

        sage: from sage.repl.ipython_kernel.all_jupyter import slider
        sage: slider(5, label="slide me")
        TransformIntSlider(value=5, description=u'slide me', min=5)
        sage: slider(5, 20)
        TransformIntSlider(value=5, max=20, min=5)
        sage: slider(5, 20, 0.5)
        TransformFloatSlider(value=5.0, max=20.0, min=5.0, step=0.5)
        sage: slider(5, 20, default=12)
        TransformIntSlider(value=12, max=20, min=5)

    The parent of the inputs determines the parent of the value::

        sage: w = slider(5); w
        TransformIntSlider(value=5, min=5)
        sage: parent(w.get_interact_value())
        Integer Ring
        sage: w = slider(int(5)); w
        IntSlider(value=5, min=5)
        sage: parent(w.get_interact_value())
        <... 'int'>
        sage: w = slider(5, 20, step_size=RDF("0.1")); w
        TransformFloatSlider(value=5.0, max=20.0, min=5.0)
        sage: parent(w.get_interact_value())
        Real Double Field
        sage: w = slider(5, 20, step_size=10/3); w
        SelectionSlider(index=2, options=(5, 25/3, 35/3, 15, 55/3), value=35/3)
        sage: parent(w.get_interact_value())
        Rational Field

    Symbolic input is evaluated numerically::

        sage: w = slider(e, pi); w
        TransformFloatSlider(value=2.718281828459045, max=3.141592653589793, min=2.718281828459045)
        sage: parent(w.get_interact_value())
        Real Field with 53 bits of precision

    For a selection slider, the default is adjusted to one of the
    possible values::

        sage: slider(range(10), default=17/10)
        SelectionSlider(index=2, options=(0, 1, 2, 3, 4, 5, 6, 7, 8, 9), value=2)

    TESTS::

        sage: slider(range(5), range(5))
        Traceback (most recent call last):
        ...
        TypeError: unexpected argument 'vmax' for a selection slider
        sage: slider(range(5), step_size=2)
        Traceback (most recent call last):
        ...
        TypeError: unexpected argument 'step_size' for a selection slider
        sage: slider(5).readout
        True
        sage: slider(5, display_value=False).readout
        False
    """
    kwds = {"readout": display_value}
    if label:
        kwds["description"] = u(label)

    # If vmin is iterable, return a SelectionSlider
    if isinstance(vmin, Iterable):
        if vmax is not None:
            raise TypeError("unexpected argument 'vmax' for a selection slider")
        if step_size is not None:
            raise TypeError("unexpected argument 'step_size' for a selection slider")
        if _range:
            # https://github.com/ipython/ipywidgets/issues/760
            raise NotImplementedError("range_slider does not support a list of values")
        options = list(vmin)
        # Find default in options
        def err(v):
            if v is default:
                return (-1, 0)
            try:
                if v == default:
                    return (0, 0)
                return (0, abs(v - default))
            except Exception:
                return (1, 0)
        kwds["options"] = options
        if default is not None:
            kwds["value"] = min(options, key=err)
        return SelectionSlider(**kwds)

    if default is not None:
        kwds["value"] = default

    # Sum all input numbers to figure out type/parent
    p = parent(sum(x for x in (vmin, vmax, step_size) if x is not None))

    # Change SR to RR
    if p is SR:
        p = RR

    # Convert all inputs to the common parent
    if vmin is not None:
        vmin = p(vmin)
    if vmax is not None:
        vmax = p(vmax)
    if step_size is not None:
        step_size = p(step_size)

    def tuple_elements_p(t):
        "Convert all entries of the tuple `t` to `p`"
        return tuple(p(x) for x in t)

    zero = p()
    if isinstance(zero, Integral):
        if p is int:
            if _range:
                cls = IntRangeSlider
            else:
                cls = IntSlider
        else:
            if _range:
                kwds["transform"] = tuple_elements_p
                cls = TransformIntRangeSlider
            else:
                kwds["transform"] = p
                cls = TransformIntSlider
    elif isinstance(zero, Rational):
        # Rational => implement as SelectionSlider
        if _range:
            # https://github.com/ipython/ipywidgets/issues/760
            raise NotImplementedError("range_slider does not support rational numbers")
        vmin, vmax, value = _get_min_max_value(vmin, vmax, default, step_size)
        kwds["value"] = value
        kwds["options"] = srange(vmin, vmax, step_size, include_endpoint=True)
        return SelectionSlider(**kwds)
    elif isinstance(zero, Real):
        if p is float:
            if _range:
                cls = FloatRangeSlider
            else:
                cls = FloatSlider
        else:
            if _range:
                kwds["transform"] = tuple_elements_p
                cls = TransformFloatRangeSlider
            else:
                kwds["transform"] = p
                cls = TransformFloatSlider
    else:
        raise TypeError("unknown parent {!r} for slider".format(p))

    kwds["min"] = vmin
    if vmax is not None:
        kwds["max"] = vmax
    if step_size is not None:
        kwds["step"] = step_size
    return cls(**kwds)
Beispiel #22
0
def exponential_integral_1(x, n=0):
    r"""
    Returns the exponential integral `E_1(x)`. If the optional
    argument `n` is given, computes list of the first
    `n` values of the exponential integral
    `E_1(x m)`.

    The exponential integral `E_1(x)` is

    .. MATH::

                      E_1(x) = \int_{x}^{\infty} \frac{e^{-t}}{t} \; dt

    INPUT:

    - ``x`` -- a positive real number

    - ``n`` -- (default: 0) a nonnegative integer; if
      nonzero, then return a list of values ``E_1(x*m)`` for m =
      1,2,3,...,n. This is useful, e.g., when computing derivatives of
      L-functions.


    OUTPUT:

    A real number if n is 0 (the default) or a list of reals if n > 0.
    The precision is the same as the input, with a default of 53 bits
    in case the input is exact.

    EXAMPLES::

        sage: exponential_integral_1(2)
        0.0489005107080611
        sage: exponential_integral_1(2, 4)  # abs tol 1e-18
        [0.0489005107080611, 0.00377935240984891, 0.000360082452162659, 0.0000376656228439245]
        sage: exponential_integral_1(40, 5)
        [0.000000000000000, 2.22854325868847e-37, 6.33732515501151e-55, 2.02336191509997e-72, 6.88522610630764e-90]
        sage: exponential_integral_1(0)
        +Infinity
        sage: r = exponential_integral_1(RealField(150)(1))
        sage: r
        0.21938393439552027367716377546012164903104729
        sage: parent(r)
        Real Field with 150 bits of precision
        sage: exponential_integral_1(RealField(150)(100))
        3.6835977616820321802351926205081189876552201e-46

    TESTS:

    The relative error for a single value should be less than 1 ulp::

        sage: for prec in [20..1000]:  # long time (22s on sage.math, 2013)
        ....:     R = RealField(prec)
        ....:     S = RealField(prec+64)
        ....:     for t in range(8):  # Try 8 values for each precision
        ....:         a = R.random_element(-15,10).exp()
        ....:         x = exponential_integral_1(a)
        ....:         y = exponential_integral_1(S(a))
        ....:         e = float(abs(S(x) - y)/x.ulp())
        ....:         if e >= 1.0:
        ....:             print("exponential_integral_1(%s) with precision %s has error of %s ulp"%(a, prec, e))

    The absolute error for a vector should be less than `2^{-p} c`, where
    `p` is the precision in bits of `x` and `c = 2` ``max(1, exponential_integral_1(x))``::

        sage: for prec in [20..128]:  # long time (15s on sage.math, 2013)
        ....:     R = RealField(prec)
        ....:     S = RealField(prec+64)
        ....:     a = R.random_element(-15,10).exp()
        ....:     n = 2^ZZ.random_element(14)
        ....:     x = exponential_integral_1(a, n)
        ....:     y = exponential_integral_1(S(a), n)
        ....:     c = RDF(2 * max(1.0, y[0]))
        ....:     for i in range(n):
        ....:         e = float(abs(S(x[i]) - y[i]) << prec)
        ....:         if e >= c:
        ....:             print("exponential_integral_1(%s, %s)[%s] with precision %s has error of %s >= %s"%(a, n, i, prec, e, c))

    ALGORITHM: use the PARI C-library function ``eint1``.

    REFERENCE:

    - See Proposition 5.6.12 of Cohen's book "A Course in
      Computational Algebraic Number Theory".
    """
    if isinstance(x, Expression):
        if x.is_trivial_zero():
            from sage.rings.infinity import Infinity
            return Infinity
        else:
            raise NotImplementedError("Use the symbolic exponential integral " +
                                      "function: exp_integral_e1.")

    # x == 0  =>  return Infinity
    if not x:
        from sage.rings.infinity import Infinity
        return Infinity

    # Figure out output precision
    try:
        prec = parent(x).precision()
    except AttributeError:
        prec = 53

    R = RealField(prec)
    if n <= 0:
        # Add extra bits to the input.
        # (experimentally verified -- Jeroen Demeyer)
        inprec = prec + 5 + math.ceil(math.log(prec))
        x = RealField(inprec)(x).__pari__()
        return R(x.eint1())
    else:
        # PARI's algorithm is less precise as n grows larger:
        # add extra bits.
        # (experimentally verified -- Jeroen Demeyer)
        inprec = prec + 1 + math.ceil(1.4427 * math.log(n))
        x = RealField(inprec)(x).__pari__()
        return [R(z) for z in x.eint1(n)]
Beispiel #23
0
def slider(vmin,
           vmax=None,
           step_size=None,
           default=None,
           label=None,
           display_value=True,
           _range=False):
    """
    A slider widget.

    INPUT:

    For a numeric slider (select a value from a range):

    - ``vmin``, ``vmax`` -- minimum and maximum value

    - ``step_size`` -- the step size

    For a selection slider (select a value from a list of values):

    - ``vmin`` -- a list of possible values for the slider

    For all sliders:

    - ``default`` -- initial value

    - ``label`` -- optional label

    - ``display_value`` -- (boolean) if ``True``, display the current
      value.

    EXAMPLES::

        sage: from sage.repl.ipython_kernel.all_jupyter import slider
        sage: slider(5, label="slide me")
        TransformIntSlider(value=5, description=u'slide me', min=5)
        sage: slider(5, 20)
        TransformIntSlider(value=5, max=20, min=5)
        sage: slider(5, 20, 0.5)
        TransformFloatSlider(value=5.0, max=20.0, min=5.0, step=0.5)
        sage: slider(5, 20, default=12)
        TransformIntSlider(value=12, max=20, min=5)

    The parent of the inputs determines the parent of the value::

        sage: w = slider(5); w
        TransformIntSlider(value=5, min=5)
        sage: parent(w.get_interact_value())
        Integer Ring
        sage: w = slider(int(5)); w
        IntSlider(value=5, min=5)
        sage: parent(w.get_interact_value())
        <... 'int'>
        sage: w = slider(5, 20, step_size=RDF("0.1")); w
        TransformFloatSlider(value=5.0, max=20.0, min=5.0)
        sage: parent(w.get_interact_value())
        Real Double Field
        sage: w = slider(5, 20, step_size=10/3); w
        SelectionSlider(index=2, options=(5, 25/3, 35/3, 15, 55/3), value=35/3)
        sage: parent(w.get_interact_value())
        Rational Field

    Symbolic input is evaluated numerically::

        sage: w = slider(e, pi); w
        TransformFloatSlider(value=2.718281828459045, max=3.141592653589793, min=2.718281828459045)
        sage: parent(w.get_interact_value())
        Real Field with 53 bits of precision

    For a selection slider, the default is adjusted to one of the
    possible values::

        sage: slider(range(10), default=17/10)
        SelectionSlider(index=2, options=(0, 1, 2, 3, 4, 5, 6, 7, 8, 9), value=2)

    TESTS::

        sage: slider(range(5), range(5))
        Traceback (most recent call last):
        ...
        TypeError: unexpected argument 'vmax' for a selection slider
        sage: slider(range(5), step_size=2)
        Traceback (most recent call last):
        ...
        TypeError: unexpected argument 'step_size' for a selection slider
        sage: slider(5).readout
        True
        sage: slider(5, display_value=False).readout
        False
    """
    kwds = {"readout": display_value}
    if label:
        kwds["description"] = u(label)

    # If vmin is iterable, return a SelectionSlider
    if isinstance(vmin, Iterable):
        if vmax is not None:
            raise TypeError(
                "unexpected argument 'vmax' for a selection slider")
        if step_size is not None:
            raise TypeError(
                "unexpected argument 'step_size' for a selection slider")
        if _range:
            # https://github.com/ipython/ipywidgets/issues/760
            raise NotImplementedError(
                "range_slider does not support a list of values")
        options = list(vmin)

        # Find default in options
        def err(v):
            if v is default:
                return (-1, 0)
            try:
                if v == default:
                    return (0, 0)
                return (0, abs(v - default))
            except Exception:
                return (1, 0)

        kwds["options"] = options
        if default is not None:
            kwds["value"] = min(options, key=err)
        return SelectionSlider(**kwds)

    if default is not None:
        kwds["value"] = default

    # Sum all input numbers to figure out type/parent
    p = parent(sum(x for x in (vmin, vmax, step_size) if x is not None))

    # Change SR to RR
    if p is SR:
        p = RR

    # Convert all inputs to the common parent
    if vmin is not None:
        vmin = p(vmin)
    if vmax is not None:
        vmax = p(vmax)
    if step_size is not None:
        step_size = p(step_size)

    def tuple_elements_p(t):
        "Convert all entries of the tuple `t` to `p`"
        return tuple(p(x) for x in t)

    zero = p()
    if isinstance(zero, Integral):
        if p is int:
            if _range:
                cls = IntRangeSlider
            else:
                cls = IntSlider
        else:
            if _range:
                kwds["transform"] = tuple_elements_p
                cls = TransformIntRangeSlider
            else:
                kwds["transform"] = p
                cls = TransformIntSlider
    elif isinstance(zero, Rational):
        # Rational => implement as SelectionSlider
        if _range:
            # https://github.com/ipython/ipywidgets/issues/760
            raise NotImplementedError(
                "range_slider does not support rational numbers")
        vmin, vmax, value = _get_min_max_value(vmin, vmax, default, step_size)
        kwds["value"] = value
        kwds["options"] = srange(vmin, vmax, step_size, include_endpoint=True)
        return SelectionSlider(**kwds)
    elif isinstance(zero, Real):
        if p is float:
            if _range:
                cls = FloatRangeSlider
            else:
                cls = FloatSlider
        else:
            if _range:
                kwds["transform"] = tuple_elements_p
                cls = TransformFloatRangeSlider
            else:
                kwds["transform"] = p
                cls = TransformFloatSlider
    else:
        raise TypeError("unknown parent {!r} for slider".format(p))

    kwds["min"] = vmin
    if vmax is not None:
        kwds["max"] = vmax
    if step_size is not None:
        kwds["step"] = step_size
    return cls(**kwds)
Beispiel #24
0
def _convolution_fft(L1, L2):
   """
   Returns convolution of non-empty lists L1 and L2, using FFT
   algorithm. L1 and L2 may have arbitrary lengths `\geq 4`.
   Assumes all entries of L1 and L2 belong to the same ring.

   EXAMPLES::

       sage: from sage.rings.polynomial.convolution import _convolution_naive
       sage: from sage.rings.polynomial.convolution import _convolution_fft
       sage: _convolution_naive([1, 2, 3], [4, 5, 6])
       [4, 13, 28, 27, 18]
       sage: _convolution_fft([1, 2, 3], [4, 5, 6])
       [4, 13, 28, 27, 18]

   ::

       sage: for len1 in range(4, 30):
       ...      for len2 in range(4, 30):
       ...         L1 = [ZZ.random_element(100) for _ in range(len1)]
       ...         L2 = [ZZ.random_element(100) for _ in range(len2)]
       ...         assert _convolution_naive(L1, L2) == _convolution_fft(L1, L2)
   """
   R = parent(L1[0])

   # choose n so that output convolution length is 2^n
   len1 = len(L1)
   len2 = len(L2)
   outlen = len1 + len2 - 1
   n = int(ceil(log(outlen) / log(2.0)))

   # split into 2^m pieces of 2^(k-1) coefficients each, with k as small
   # as possible, subject to m <= k + 1 (so that the ring of Fourier
   # coefficients has enough roots of unity)
   m = (n >> 1) + 1
   k = n + 1 - m

   N = 1 << n
   M = 1 << m
   K = 1 << k

   # zero pad inputs up to length N
   zero = R(0)
   L1 = L1 + [zero] * (N - len(L1))
   L2 = L2 + [zero] * (N - len(L2))

   # split inputs into polynomials
   L1 = _split(L1, m, k)
   L2 = _split(L2, m, k)

   # fft each input
   _fft(L1, K, 0, m, K)
   _fft(L2, K, 0, m, K)

   # pointwise multiply
   L3 = [_negaconvolution(L1[i], L2[i], k) for i in range(M)]

   # inverse fft
   _ifft(L3, K, 0, m, K)

   # combine back into a single list
   L3 = _combine(L3, m, k)

   # normalise, and truncate to correct length
   return [R(L3[i] / M) for i in range(outlen)]