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
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)
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]
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)
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)
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()
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)]
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]
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)
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)
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)
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
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)
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
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)
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)
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)
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)]
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)
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)]