def _call_(self, v): r""" EXAMPLE:: sage: L.<b> = NumberField(x^4 + 3*x^2 + 1) sage: K = L.relativize(L.subfields(2)[0][1], 'a') sage: a0 = K.gen(); b0 = K.base_field().gen() sage: V, fr, to = K.relative_vector_space() sage: fr(to(a0 + 2*b0)), fr(V([0, 1])), fr(V([b0, 2*b0])) # indirect doctest (a0 + 2*b0, a0, 2*b0*a0 + b0) """ # Given a relative vector space element, we have to # compute the corresponding number field element, in terms # of an absolute generator. w = self.__V(v).list() # First, construct from w a PARI polynomial in x with coefficients # that are polynomials in y: B = self.__B _, to_B = B.structure() # Apply to_B, so now each coefficient is in an absolute field, # and is expressed in terms of a polynomial in y, then make # the PARI poly in x. w = [pari(to_B(a).polynomial('y')) for a in w] h = pari(w).Polrev() # Next we write the poly in x over a poly in y in terms # of an absolute polynomial for the rnf. g = self.__R(self.__rnf.rnfeltreltoabs(h)) return self.__K._element_class(self.__K, g)
def _pari_modulus(self): """ EXAMPLES: sage: GF(3^4,'a')._pari_modulus() Mod(1, 3)*a^4 + Mod(2, 3)*a^3 + Mod(2, 3) """ f = pari(str(self.modulus())) return f.subst('x', 'a') * pari("Mod(1,%s)" % self.characteristic())
def _pari_modulus(self): """ EXAMPLES: sage: GF(3^4,'a')._pari_modulus() Mod(1, 3)*a^4 + Mod(2, 3)*a^3 + Mod(2, 3) """ f = pari(str(self.modulus())) return f.subst('x', 'a') * pari("Mod(1,%s)"%self.characteristic())
def _element_constructor_(self, u): """ Returns the abstract group element corresponding to the unit u. INPUT: - ``u`` -- Any object from which an element of the unit group's number field `K` may be constructed; an error is raised if an element of `K` cannot be constructed from u, or if the element constructed is not a unit. EXAMPLES:: sage: x = polygen(QQ) sage: K.<a> = NumberField(x^2-38) sage: UK = UnitGroup(K) sage: UK(1) 1 sage: UK(-1) u0 sage: UK.gens() (u0, u1) sage: UK.gens_values() [-1, 6*a - 37] sage: UK.ngens() 2 sage: [UK(u) for u in UK.gens()] [u0, u1] sage: [UK(u).exponents() for u in UK.gens()] [(1, 0), (0, 1)] sage: UK(a) Traceback (most recent call last): ... ValueError: a is not a unit """ K = self.__number_field pK = self.__pari_number_field try: u = K(u) except TypeError: raise ValueError("%s is not an element of %s" % (u, K)) if self.__S: m = pK.bnfissunit(self.__S_unit_data, pari(u)).mattranspose() if m.ncols() == 0: raise ValueError("%s is not an S-unit" % u) else: if not u.is_integral() or u.norm().abs() != 1: raise ValueError("%s is not a unit" % u) m = pK.bnfisunit(pari(u)).mattranspose() # convert column matrix to a list: m = [ZZ(m[0, i].python()) for i in range(m.ncols())] # NB pari puts the torsion after the fundamental units, before # the extra S-units but we have the torsion first: m = [m[self.__nfu]] + m[:self.__nfu] + m[self.__nfu + 1:] return self.element_class(self, m)
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} 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: - ``float`` - if n is 0 (the default) or - ``list`` - list of floats if n 0 EXAMPLES:: sage: exponential_integral_1(2) 0.04890051070806112 sage: w = exponential_integral_1(2,4); w [0.04890051070806112, 0.003779352409848906..., 0.00036008245216265873, 3.7665622843924...e-05] IMPLEMENTATION: We use the PARI C-library functions eint1 and veceint1. REFERENCE: - See page 262, Prop 5.6.12, of Cohen's book "A Course in Computational Algebraic Number Theory". REMARKS: When called with the optional argument n, the PARI C-library is fast for values of n up to some bound, then very very slow. For example, if x=5, then the computation takes less than a second for n=800000, and takes "forever" for n=900000. """ if n <= 0: return float(pari(x).eint1()) else: return [float(z) for z in pari(x).eint1(n)]
def _element_constructor_(self, u): """ Returns the abstract group element corresponding to the unit u. INPUT: - ``u`` -- Any object from which an element of the unit group's number field `K` may be constructed; an error is raised if an element of `K` cannot be constructed from u, or if the element constructed is not a unit. EXAMPLES:: sage: x = polygen(QQ) sage: K.<a> = NumberField(x^2-38) sage: UK = UnitGroup(K) sage: UK(1) 1 sage: UK(-1) u0 sage: UK.gens() (u0, u1) sage: UK.gens_values() [-1, 6*a - 37] sage: UK.ngens() 2 sage: [UK(u) for u in UK.gens()] [u0, u1] sage: [UK(u).exponents() for u in UK.gens()] [(1, 0), (0, 1)] sage: UK(a) Traceback (most recent call last): ... ValueError: a is not a unit """ K = self.__number_field pK = self.__pari_number_field try: u = K(u) except TypeError: raise ValueError("%s is not an element of %s"%(u,K)) if self.__S: m = pK.bnfissunit(self.__S_unit_data, pari(u)).mattranspose() if m.ncols()==0: raise ValueError("%s is not an S-unit"%u) else: if not u.is_integral() or u.norm().abs() != 1: raise ValueError("%s is not a unit"%u) m = pK.bnfisunit(pari(u)).mattranspose() # convert column matrix to a list: m = [ZZ(m[0,i].python()) for i in range(m.ncols())] # NB pari puts the torsion after the fundamental units, before # the extra S-units but we have the torsion first: m = [m[self.__nfu]] + m[:self.__nfu] + m[self.__nfu+1:] return self.element_class(self, m)
def _pari_modulus(self): """ Return the modulus of ``self`` in a format for PARI. EXAMPLES:: sage: GF(3^4,'a')._pari_modulus() Mod(1, 3)*a^4 + Mod(2, 3)*a^3 + Mod(2, 3) """ f = pari(str(self.modulus())) return f.subst('x', 'a') * pari("Mod(1,%s)"%self.characteristic())
def _pari_modulus(self): """ Return PARI object which is equivalent to the polynomial/modulus of ``self``. EXAMPLES:: sage: k1.<a> = GF(2^16) sage: k1._pari_modulus() Mod(1, 2)*a^16 + Mod(1, 2)*a^5 + Mod(1, 2)*a^3 + Mod(1, 2)*a^2 + Mod(1, 2) """ f = pari(str(self.modulus())) return f.subst('x', 'a') * pari("Mod(1,%s)" % self.characteristic())
def _pari_modulus(self): """ Return PARI object which is equivalent to the polynomial/modulus of ``self``. EXAMPLES:: sage: k1.<a> = GF(2^16) sage: k1._pari_modulus() Mod(1, 2)*a^16 + Mod(1, 2)*a^5 + Mod(1, 2)*a^3 + Mod(1, 2)*a^2 + Mod(1, 2) """ f = pari(str(self.modulus())) return f.subst('x', 'a') * pari("Mod(1,%s)"%self.characteristic())
def _sage_(self): """ Convert this GpElement into a Sage object, if possible. EXAMPLES:: sage: gp(I).sage() i sage: gp(I).sage().parent() Maximal Order in Number Field in i with defining polynomial x^2 + 1 :: sage: M = Matrix(ZZ,2,2,[1,2,3,4]); M [1 2] [3 4] sage: gp(M) [1, 2; 3, 4] sage: gp(M).sage() [1 2] [3 4] sage: gp(M).sage() == M True """ return pari(str(self)).python()
def _ramgroups(self, P): """ Compute ramification data using PARI. INPUT: - ``P`` -- a prime ideal OUTPUT: A PARI vector holding the decomposition group, inertia groups, and higher ramification groups. ALGORITHM: This uses the PARI function :pari:`idealramgroups`. EXAMPLES:: sage: K.<a> = NumberField(x^4 - 2*x^2 + 2,'b').galois_closure() sage: P = K.ideal([17, a^2]) sage: G = K.galois_group() sage: G._ramgroups(P) [[[Vecsmall([8, 7, 6, 5, 4, 3, 2, 1])], Vecsmall([2])]] """ K = self.number_field() P = K.ideal_monoid()(P).pari_prime() return pari(K).idealramgroups(self._pari_data, P)
def __init__(self, field, num_integer_primes=10000, max_iterations=100): r""" Construct a new iterator of small degree one primes. EXAMPLES:: sage: x = QQ['x'].gen() sage: K.<a> = NumberField(x^2 - 3) sage: K.primes_of_degree_one_list(3) # random [Fractional ideal (2*a + 1), Fractional ideal (-a + 4), Fractional ideal (3*a + 2)] """ self._field = field self._poly = self._field.absolute_field('b').defining_polynomial() self._poly = ZZ['x'](self._poly.denominator() * self._poly()) # make integer polynomial self._lc = self._poly.leading_coefficient() # this uses that [ O_K : Z[a] ]^2 = | disc(f(x)) / disc(O_K) | from sage.libs.pari.all import pari self._prod_of_small_primes = ZZ( pari( 'TEMPn = %s; TEMPps = primes(TEMPn); prod(X = 1, TEMPn, TEMPps[X])' % num_integer_primes)) self._prod_of_small_primes //= self._prod_of_small_primes.gcd( self._poly.discriminant() * self._lc) self._integer_iter = iter(ZZ) self._queue = [] self._max_iterations = max_iterations
def _complex_mpfr_field_(self, CC): """ Return ComplexField element of self. INPUT: - ``CC`` -- a Complex or Real Field. EXAMPLES:: sage: z = gp(1+15*I); z 1 + 15*I sage: z._complex_mpfr_field_(CC) 1.00000000000000 + 15.0000000000000*I sage: CC(z) # CC(gp(1+15*I)) 1.00000000000000 + 15.0000000000000*I sage: CC(gp(11243.9812+15*I)) 11243.9812000000 + 15.0000000000000*I sage: ComplexField(10)(gp(11243.9812+15*I)) 11000. + 15.*I """ # Multiplying by CC(1) is necessary here since # sage: pari(gp(1+I)).sage().parent() # Maximal Order in Number Field in i with defining polynomial x^2 + 1 return CC((CC(1) * pari(self)).sage())
def _sage_(self): """ Convert this GpElement into a Sage object, if possible. EXAMPLES:: sage: gp(I).sage() i sage: gp(I).sage().parent() Number Field in i with defining polynomial x^2 + 1 with i = 1*I :: sage: M = Matrix(ZZ,2,2,[1,2,3,4]); M [1 2] [3 4] sage: gp(M) [1, 2; 3, 4] sage: gp(M).sage() [1 2] [3 4] sage: gp(M).sage() == M True Conversion of strings:: sage: s = gp('"foo"') sage: s.sage() 'foo' sage: type(s.sage()) <type 'str'> """ if self.is_string(): return str(self) return pari(str(self)).sage()
def fixed_field(self): r""" Return the fixed field of this subgroup (as a subfield of the Galois closure of the number field associated to the ambient Galois group). EXAMPLES:: sage: L.<a> = NumberField(x^4 + 1) sage: G = L.galois_group() sage: H = G.decomposition_group(L.primes_above(3)[0]) sage: H.fixed_field() (Number Field in a0 with defining polynomial x^2 + 2 with a0 = a^3 + a, Ring morphism: From: Number Field in a0 with defining polynomial x^2 + 2 with a0 = a^3 + a To: Number Field in a with defining polynomial x^4 + 1 Defn: a0 |--> a^3 + a) An embedding is returned also if the subgroup is trivial (:trac:`26817`):: sage: H = G.subgroup([G.identity()]) sage: H.fixed_field() (Number Field in a0 with defining polynomial x^4 + 1 with a0 = a, Ring morphism: From: Number Field in a0 with defining polynomial x^4 + 1 with a0 = a To: Number Field in a with defining polynomial x^4 + 1 Defn: a0 |--> a) """ vecs = [pari(g.domain()).Vecsmall() for g in self._elts] v = self._ambient._pari_data.galoisfixedfield(vecs) x = self._galois_closure(v[1]) return self._galois_closure.subfield(x)
def __mul__(self, right): """ Gauss composition of binary quadratic forms. The result is not reduced. EXAMPLES: We explicitly compute in the group of classes of positive definite binary quadratic forms of discriminant -23. :: sage: R = BinaryQF_reduced_representatives(-23); R [x^2 + x*y + 6*y^2, 2*x^2 - x*y + 3*y^2, 2*x^2 + x*y + 3*y^2] sage: R[0] * R[0] x^2 + x*y + 6*y^2 sage: R[1] * R[1] 4*x^2 + 3*x*y + 2*y^2 sage: (R[1] * R[1]).reduced_form() 2*x^2 + x*y + 3*y^2 sage: (R[1] * R[1] * R[1]).reduced_form() x^2 + x*y + 6*y^2 """ if not isinstance(right, BinaryQF): raise TypeError, "both self and right must be binary quadratic forms" # There could be more elegant ways, but qfbcompraw isn't # wrapped yet in the PARI C library. We may as well settle # for the below, until somebody simply implements composition # from scratch in Cython. v = list(pari('qfbcompraw(%s,%s)'%(self._pari_init_(), right._pari_init_()))) return BinaryQF(v)
def fixed_field(self): r""" Return the fixed field of this subgroup (as a subfield of the Galois closure of the number field associated to the ambient Galois group). EXAMPLES:: sage: L.<a> = NumberField(x^4 + 1) sage: G = L.galois_group() sage: H = G.decomposition_group(L.primes_above(3)[0]) sage: H.fixed_field() (Number Field in a0 with defining polynomial x^2 + 2 with a0 = a^3 + a, Ring morphism: From: Number Field in a0 with defining polynomial x^2 + 2 with a0 = a^3 + a To: Number Field in a with defining polynomial x^4 + 1 Defn: a0 |--> a^3 + a) """ if self.order() == 1: return self._galois_closure # work around a silly error vecs = [pari(g.domain()).Vecsmall() for g in self._elts] v = self._ambient._pari_data.galoisfixedfield(vecs) x = self._galois_closure(v[1]) return self._galois_closure.subfield(x)
def reduced_form(self): """ Return the unique reduced form equivalent to ``self``. See also :meth:`~is_reduced`. EXAMPLES:: sage: a = BinaryQF([33,11,5]) sage: a.is_reduced() False sage: b = a.reduced_form(); b 5*x^2 - x*y + 27*y^2 sage: b.is_reduced() True sage: a = BinaryQF([15,0,15]) sage: a.is_reduced() True sage: b = a.reduced_form(); b 15*x^2 + 15*y^2 sage: b.is_reduced() True """ if self.discriminant() >= 0 or self._a < 0: raise NotImplementedError, "only implemented for positive definite forms" if not self.is_reduced(): v = list( pari('Vec(qfbred(Qfb(%s,%s,%s)))' % (self._a, self._b, self._c))) return BinaryQF(v) else: return self
def _complex_mpfr_field_(self, CC): """ Return ComplexField element of self. INPUT: - ``CC`` -- a Complex or Real Field. EXAMPLES:: sage: z = gp(1+15*I); z 1 + 15*I sage: z._complex_mpfr_field_(CC) 1.00000000000000 + 15.0000000000000*I sage: CC(z) # CC(gp(1+15*I)) 1.00000000000000 + 15.0000000000000*I sage: CC(gp(11243.9812+15*I)) 11243.9812000000 + 15.0000000000000*I sage: ComplexField(10)(gp(11243.9812+15*I)) 11000. + 15.*I """ # Multiplying by CC(1) is necessary here since # sage: pari(gp(1+I)).sage().parent() # Maximal Order in Number Field in i with defining polynomial x^2 + 1 return CC((CC(1)*pari(self))._sage_())
def __mul__(self, right): """ Gauss composition of binary quadratic forms. The result is not reduced. EXAMPLES: We explicitly compute in the group of classes of positive definite binary quadratic forms of discriminant -23. :: sage: R = BinaryQF_reduced_representatives(-23); R [x^2 + x*y + 6*y^2, 2*x^2 - x*y + 3*y^2, 2*x^2 + x*y + 3*y^2] sage: R[0] * R[0] x^2 + x*y + 6*y^2 sage: R[1] * R[1] 4*x^2 + 3*x*y + 2*y^2 sage: (R[1] * R[1]).reduced_form() 2*x^2 + x*y + 3*y^2 sage: (R[1] * R[1] * R[1]).reduced_form() x^2 + x*y + 6*y^2 """ if not isinstance(right, BinaryQF): raise TypeError, "both self and right must be binary quadratic forms" # There could be more elegant ways, but qfbcompraw isn't # wrapped yet in the PARI C library. We may as well settle # for the below, until somebody simply implements composition # from scratch in Cython. v = list( pari('qfbcompraw(%s,%s)' % (self._pari_init_(), right._pari_init_()))) return BinaryQF(v)
def reduced_form(self): """ Return the unique reduced form equivalent to ``self``. See also :meth:`~is_reduced`. EXAMPLES:: sage: a = BinaryQF([33,11,5]) sage: a.is_reduced() False sage: b = a.reduced_form(); b 5*x^2 - x*y + 27*y^2 sage: b.is_reduced() True sage: a = BinaryQF([15,0,15]) sage: a.is_reduced() True sage: b = a.reduced_form(); b 15*x^2 + 15*y^2 sage: b.is_reduced() True """ if self.discriminant() >= 0 or self._a < 0: raise NotImplementedError, "only implemented for positive definite forms" if not self.is_reduced(): v = list(pari('Vec(qfbred(Qfb(%s,%s,%s)))'%(self._a,self._b,self._c))) return BinaryQF(v) else: return self
def _sage_(self): """ Convert this GpElement into a Sage object, if possible. EXAMPLES:: sage: gp(I).sage() i sage: gp(I).sage().parent() Number Field in i with defining polynomial x^2 + 1 :: sage: M = Matrix(ZZ,2,2,[1,2,3,4]); M [1 2] [3 4] sage: gp(M) [1, 2; 3, 4] sage: gp(M).sage() [1 2] [3 4] sage: gp(M).sage() == M True """ return pari(str(self)).python()
def __init__(self, field, num_integer_primes=10000, max_iterations=100): r""" Construct a new iterator of small degree one primes. EXAMPLES:: sage: x = QQ['x'].gen() sage: K.<a> = NumberField(x^2 - 3) sage: K.primes_of_degree_one_list(3) # random [Fractional ideal (2*a + 1), Fractional ideal (-a + 4), Fractional ideal (3*a + 2)] """ self._field = field self._poly = self._field.absolute_field("b").defining_polynomial() self._poly = ZZ["x"](self._poly.denominator() * self._poly()) # make integer polynomial # this uses that [ O_K : Z[a] ]^2 = | disc(f(x)) / disc(O_K) | from sage.libs.pari.all import pari self._prod_of_small_primes = ZZ( pari("TEMPn = %s; TEMPps = primes(TEMPn); prod(X = 1, TEMPn, TEMPps[X])" % num_integer_primes) ) self._prod_of_small_primes //= self._prod_of_small_primes.gcd(self._poly.discriminant()) self._integer_iter = iter(ZZ) self._queue = [] self._max_iterations = max_iterations
def pari(x): """ Return the PARI object constructed from a Sage/Python object. This is deprecated, import ``pari`` from ``sage.libs.pari.all``. """ from sage.misc.superseded import deprecation deprecation(17451, 'gen_py.pari is deprecated, use sage.libs.pari.all.pari instead') from sage.libs.pari.all import pari return pari(x)
def __float__(self): """ Return Python float. EXAMPLES:: sage: float(gp(10)) 10.0 """ return float(pari(str(self)))
def _call_(self, alpha): """ TESTS:: sage: K.<a> = NumberField(x^5+2) sage: R.<y> = K[] sage: D.<x0> = K.extension(y + a + 1) sage: D(a) a sage: V, from_V, to_V = D.relative_vector_space() sage: to_V(a) # indirect doctest (a) sage: to_V(a^3) # indirect doctest (a^3) sage: to_V(x0) # indirect doctest (-a - 1) sage: K.<a> = QuadraticField(-3) sage: L.<b> = K.extension(x-5) sage: L(a) a sage: a*b 5*a sage: b 5 sage: V, from_V, to_V = L.relative_vector_space() sage: to_V(a) # indirect doctest (a) """ # An element of a relative number field is represented # internally by an absolute polynomial over QQ. alpha = self.__K(alpha) # f is the absolute polynomial that defines this number field # element f = alpha.polynomial('x') g = self.__rnf.rnfeltabstorel(pari(f)).lift().lift() # Now g is a relative polynomial that defines this element. # This g is a polynomial in a pari variable x with # coefficients polynomials in a variable y. These # coefficients define the coordinates of the vector we are # constructing. # The list v below has the coefficients that are the # components of the vector we are constructing, but each is # converted into polynomials in a variable x, which we will # use to define elements of the base field. (x, y) = (self.__x, self.__y) v = [g.polcoeff(i).subst(x,y) for i in range(self.__n)] B,from_B, _ = self.__B w = [from_B(B(z)) for z in v] # Now w gives the coefficients. return self.__V(w)
def _call_(self, alpha): """ TESTS:: sage: K.<a> = NumberField(x^5+2) sage: R.<y> = K[] sage: D.<x0> = K.extension(y + a + 1) sage: D(a) a sage: V, from_V, to_V = D.relative_vector_space() sage: to_V(a) # indirect doctest (a) sage: to_V(a^3) # indirect doctest (a^3) sage: to_V(x0) # indirect doctest (-a - 1) sage: K.<a> = QuadraticField(-3) sage: L.<b> = K.extension(x-5) sage: L(a) a sage: a*b 5*a sage: b 5 sage: V, from_V, to_V = L.relative_vector_space() sage: to_V(a) # indirect doctest (a) """ # An element of a relative number field is represented # internally by an absolute polynomial over QQ. alpha = self.__K(alpha) # f is the absolute polynomial that defines this number field # element f = alpha.polynomial('x') g = self.__rnf.rnfeltabstorel(pari(f)).lift().lift() # Now g is a relative polynomial that defines this element. # This g is a polynomial in a pari variable x with # coefficients polynomials in a variable y. These # coefficients define the coordinates of the vector we are # constructing. # The list v below has the coefficients that are the # components of the vector we are constructing, but each is # converted into polynomials in a variable x, which we will # use to define elements of the base field. (x, y) = (self.__x, self.__y) v = [g.polcoeff(i).subst(x, y) for i in range(self.__n)] B, from_B, _ = self.__B w = [from_B(B(z)) for z in v] # Now w gives the coefficients. return self.__V(w)
def representation_number_list(self, B): """ Return the vector of representation numbers < B. EXAMPLES:: sage: Q = DiagonalQuadraticForm(ZZ,[1,1,1,1,1,1,1,1]) sage: Q.representation_number_list(10) [1, 16, 112, 448, 1136, 2016, 3136, 5504, 9328, 12112] """ ans = pari(1).concat(self.__pari__().qfrep(B - 1, 1) * 2) return ans.sage()
def _pari_(self): """ Return PARI list corresponding to this continued fraction. EXAMPLES:: sage: c = continued_fraction(0.12345); c [0, 8, 9, 1, 21, 1, 1] sage: pari(c) [0, 8, 9, 1, 21, 1, 1] """ return pari(self._x)
def __init__(self, K, V): r""" EXAMPLE:: sage: L.<b> = NumberField(x^4 + 3*x^2 + 1) sage: K = L.relativize(L.subfields(2)[0][1], 'a') sage: V, fr, to = K.relative_vector_space() sage: to Isomorphism map: From: Number Field in a0 with defining polynomial x^2 - b0*x + 1 over its base field To: Vector space of dimension 2 over Number Field in b0 with defining polynomial x^2 + 1 """ self.__V = V self.__K = K self.__rnf = K.pari_rnf() self.__zero = QQ(0) self.__n = K.relative_degree() self.__x = pari("'x") self.__y = pari("'y") self.__B = K.absolute_base_field() NumberFieldIsomorphism.__init__(self, Hom(K, V))
def __pari__(self): """ Return a PARI representation of ``self``. EXAMPLES:: sage: Cusp(1, 0).__pari__() +oo sage: pari(Cusp(3, 2)) 3/2 """ b = self.__b return pari(self.__a / b) if b else pari.oo()
def elliptic_j(z): r""" Returns the elliptic modular `j`-function evaluated at `z`. INPUT: - ``z`` (complex) -- a complex number with positive imaginary part. OUTPUT: (complex) The value of `j(z)`. ALGORITHM: Calls the ``pari`` function ``ellj()``. AUTHOR: John Cremona EXAMPLES:: sage: elliptic_j(CC(i)) 1728.00000000000 sage: elliptic_j(sqrt(-2.0)) 8000.00000000000 sage: z = ComplexField(100)(1,sqrt(11))/2 sage: elliptic_j(z) -32768.000... sage: elliptic_j(z).real().round() -32768 :: sage: tau = (1 + sqrt(-163))/2 sage: (-elliptic_j(tau.n(100)).real().round())^(1/3) 640320 """ CC = z.parent() from sage.rings.complex_field import is_ComplexField if not is_ComplexField(CC): CC = ComplexField() try: z = CC(z) except ValueError: raise ValueError("elliptic_j only defined for complex arguments.") from sage.libs.all import pari return CC(pari(z).ellj())
def _pari_order(self): """ Return the pari integer representing the order of this ring. EXAMPLES:: sage: Zmod(87)._pari_order() 87 """ try: return self.__pari_order except AttributeError: self.__pari_order = pari(self.order()) return self.__pari_order
def hypergeometric_U(alpha, beta, x, algorithm="pari", prec=53): r""" Default is a wrap of PARI's hyperu(alpha,beta,x) function. Optionally, algorithm = "scipy" can be used. The confluent hypergeometric function `y = U(a,b,x)` is defined to be the solution to Kummer's differential equation .. math:: xy'' + (b-x)y' - ay = 0. This satisfies `U(a,b,x) \sim x^{-a}`, as `x\rightarrow \infty`, and is sometimes denoted ``x^{-a}2_F_0(a,1+a-b,-1/x)``. This is not the same as Kummer's `M`-hypergeometric function, denoted sometimes as ``_1F_1(alpha,beta,x)``, though it satisfies the same DE that `U` does. .. warning:: In the literature, both are called "Kummer confluent hypergeometric" functions. EXAMPLES:: sage: hypergeometric_U(1,1,1,"scipy") 0.596347362323... sage: hypergeometric_U(1,1,1) 0.59634736232319... sage: hypergeometric_U(1,1,1,"pari",70) 0.59634736232319407434... """ if algorithm == "scipy": if prec != 53: raise ValueError("for the scipy algorithm the precision must be 53") import scipy.special ans = str(scipy.special.hyperu(float(alpha), float(beta), float(x))) ans = ans.replace("(", "") ans = ans.replace(")", "") ans = ans.replace("j", "*I") return sage_eval(ans) elif algorithm == "pari": from sage.libs.pari.all import pari R = RealField(prec) return R(pari(R(alpha)).hyperu(R(beta), R(x), precision=prec)) else: raise ValueError("unknown algorithm '%s'" % algorithm)
def hypergeometric_U(alpha, beta, x, algorithm="pari", prec=53): r""" Default is a wrap of PARI's hyperu(alpha,beta,x) function. Optionally, algorithm = "scipy" can be used. The confluent hypergeometric function `y = U(a,b,x)` is defined to be the solution to Kummer's differential equation .. math:: xy'' + (b-x)y' - ay = 0. This satisfies `U(a,b,x) \sim x^{-a}`, as `x\rightarrow \infty`, and is sometimes denoted ``x^{-a}2_F_0(a,1+a-b,-1/x)``. This is not the same as Kummer's `M`-hypergeometric function, denoted sometimes as ``_1F_1(alpha,beta,x)``, though it satisfies the same DE that `U` does. .. warning:: In the literature, both are called "Kummer confluent hypergeometric" functions. EXAMPLES:: sage: hypergeometric_U(1,1,1,"scipy") 0.596347362323... sage: hypergeometric_U(1,1,1) 0.59634736232319... sage: hypergeometric_U(1,1,1,"pari",70) 0.59634736232319407434... """ if algorithm == "scipy": if prec != 53: raise ValueError( "for the scipy algorithm the precision must be 53") import scipy.special ans = str(scipy.special.hyperu(float(alpha), float(beta), float(x))) ans = ans.replace("(", "") ans = ans.replace(")", "") ans = ans.replace("j", "*I") return sage_eval(ans) elif algorithm == 'pari': from sage.libs.pari.all import pari R = RealField(prec) return R(pari(R(alpha)).hyperu(R(beta), R(x), precision=prec)) else: raise ValueError("unknown algorithm '%s'" % algorithm)
def as_hom(self): r""" Return the homomorphism L -> L corresponding to self, where L is the Galois closure of the ambient number field. EXAMPLE:: sage: G = QuadraticField(-7,'w').galois_group() sage: G[1].as_hom() Ring endomorphism of Number Field in w with defining polynomial x^2 + 7 Defn: w |--> -w """ L = self.parent().splitting_field() a = L(self.parent()._pari_data.galoispermtopol(pari(self.domain()).Vecsmall())) return L.hom(a, L)
def __init__(self, x, parent=None): """ EXAMPLES: sage: R = PariRing() sage: f = R('x^3 + 1/2') sage: f x^3 + 1/2 sage: type(f) <class 'sage.rings.pari_ring.PariRing_with_category.element_class'> sage: loads(f.dumps()) == f True """ if parent is None: parent = _inst ring_element.RingElement.__init__(self, parent) self.__x = pari.pari(x)
def __init__(self, p, modulus, name=None): """ Create a finite field of characteristic `p` defined by the polynomial ``modulus``, with distinguished generator called ``name``. EXAMPLE:: sage: from sage.rings.finite_rings.finite_field_pari_ffelt import FiniteField_pari_ffelt sage: R.<x> = PolynomialRing(GF(3)) sage: k = FiniteField_pari_ffelt(3, x^2 + 2*x + 2, 'a'); k Finite Field in a of size 3^2 """ import constructor from sage.libs.pari.all import pari from sage.rings.integer import Integer from sage.structure.proof.all import arithmetic proof = arithmetic() p = Integer(p) if ((p < 2) or (proof and not p.is_prime()) or (not proof and not p.is_pseudoprime())): raise ArithmeticError("p must be a prime number") Fp = constructor.FiniteField(p) if name is None: name = modulus.variable_name() FiniteField.__init__(self, base=Fp, names=name, normalize=True) modulus = self.polynomial_ring()(modulus) n = modulus.degree() if n < 2: raise ValueError("the degree must be at least 2") self._modulus = modulus self._degree = n self._card = p ** n self._kwargs = {} self._gen_pari = pari(modulus).ffgen() self._zero_element = self.element_class(self, 0) self._one_element = self.element_class(self, 1) self._gen = self.element_class(self, self._gen_pari)
def __init__(self, p, modulus, name=None): """ Create a finite field of characteristic `p` defined by the polynomial ``modulus``, with distinguished generator called ``name``. EXAMPLE:: sage: from sage.rings.finite_rings.finite_field_pari_ffelt import FiniteField_pari_ffelt sage: R.<x> = PolynomialRing(GF(3)) sage: k = FiniteField_pari_ffelt(3, x^2 + 2*x + 2, 'a'); k Finite Field in a of size 3^2 """ import constructor from sage.libs.pari.all import pari from sage.rings.integer import Integer from sage.structure.proof.all import arithmetic proof = arithmetic() p = Integer(p) if ((p < 2) or (proof and not p.is_prime()) or (not proof and not p.is_pseudoprime())): raise ArithmeticError("p must be a prime number") Fp = constructor.FiniteField(p) if name is None: name = modulus.variable_name() FiniteField.__init__(self, base=Fp, names=name, normalize=True) modulus = self.polynomial_ring()(modulus) n = modulus.degree() if n < 2: raise ValueError("the degree must be at least 2") self._modulus = modulus self._degree = n self._card = p**n self._kwargs = {} self._gen_pari = pari(modulus).ffgen() self._zero_element = self.element_class(self, 0) self._one_element = self.element_class(self, 1) self._gen = self.element_class(self, self._gen_pari)
def _call_(self, v): r""" EXAMPLES:: sage: L.<b> = NumberField(x^4 + 3*x^2 + 1) sage: K = L.relativize(L.subfields(2)[0][1], 'a') sage: a0 = K.gen(); b0 = K.base_field().gen() sage: V, fr, to = K.relative_vector_space() sage: fr(to(a0 + 2*b0)), fr(V([0, 1])), fr(V([b0, 2*b0])) # indirect doctest (a + 2*b0, a, 2*b0*a + b0) """ K = self.codomain() B = K.base_field().absolute_field('a') # Convert v to a PARI polynomial in x with coefficients that # are polynomials in y. _, to_B = B.structure() h = pari([to_B(a).__pari__('y') for a in v]).Polrev() # Rewrite the polynomial in terms of an absolute generator for # the relative number field. g = K._pari_rnfeq()._eltreltoabs(h) return K._element_class(K, g)
def exp_int(t): r""" The exponential integral `\int_t^\infty e^{-x}/x dx` (t belongs to RR). This function is deprecated - please use ``Ei`` or ``exponential_integral_1`` as needed instead. EXAMPLES:: sage: exp_int(6) doctest:...: DeprecationWarning: The method exp_int() is deprecated. Use -Ei(-x) or exponential_integral_1(x) as needed instead. 0.000360082452162659 """ from sage.misc.misc import deprecation deprecation("The method exp_int() is deprecated. Use -Ei(-x) or exponential_integral_1(x) as needed instead.") try: return t.eint1() except AttributeError: from sage.libs.pari.all import pari try: return pari(t).eint1() except: raise NotImplementedError
def as_hom(self): r""" Return the homomorphism L -> L corresponding to self, where L is the Galois closure of the ambient number field. EXAMPLES:: sage: G = QuadraticField(-7,'w').galois_group() sage: G[1].as_hom() Ring endomorphism of Number Field in w with defining polynomial x^2 + 7 Defn: w |--> -w TESTS: Number fields defined by non-monic and non-integral polynomials are supported (:trac:`252`):: sage: R.<x> = QQ[] sage: f = 7/9*x^3 + 7/3*x^2 - 56*x + 123 sage: K.<a> = NumberField(f) sage: G = K.galois_group() sage: G[1].as_hom() Ring endomorphism of Number Field in a with defining polynomial 7/9*x^3 + 7/3*x^2 - 56*x + 123 Defn: a |--> -7/15*a^2 - 18/5*a + 96/5 sage: prod(x - sigma(a) for sigma in G) == f.monic() True """ G = self.parent() L = G.splitting_field() # First compute the image of the standard generator of the # PARI number field. a = G._pari_data.galoispermtopol(pari(self.domain()).Vecsmall()) # Now convert this to a conjugate of the standard generator of # the Sage number field. P = L._pari_absolute_structure()[1].lift() a = L(P(a.Mod(L.pari_polynomial('y')))) return L.hom(a, L)
def as_hom(self): r""" Return the homomorphism L -> L corresponding to self, where L is the Galois closure of the ambient number field. EXAMPLES:: sage: G = QuadraticField(-7,'w').galois_group() sage: G[1].as_hom() Ring endomorphism of Number Field in w with defining polynomial x^2 + 7 with w = 2.645751311064591?*I Defn: w |--> -w TESTS: Number fields defined by non-monic and non-integral polynomials are supported (:trac:`252`):: sage: R.<x> = QQ[] sage: f = 7/9*x^3 + 7/3*x^2 - 56*x + 123 sage: K.<a> = NumberField(f) sage: G = K.galois_group() sage: G[1].as_hom() Ring endomorphism of Number Field in a with defining polynomial 7/9*x^3 + 7/3*x^2 - 56*x + 123 Defn: a |--> -7/15*a^2 - 18/5*a + 96/5 sage: prod(x - sigma(a) for sigma in G) == f.monic() True """ G = self.parent() L = G.splitting_field() # First compute the image of the standard generator of the # PARI number field. a = G._pari_data.galoispermtopol(pari(self.domain()).Vecsmall()) # Now convert this to a conjugate of the standard generator of # the Sage number field. P = L._pari_absolute_structure()[1].lift() a = L(P(a.Mod(L.pari_polynomial('y')))) return L.hom(a, L)
def fixed_field(self): r""" Return the fixed field of this subgroup (as a subfield of the Galois closure of the number field associated to the ambient Galois group). EXAMPLES:: sage: L.<a> = NumberField(x^4 + 1) sage: G = L.galois_group() sage: H = G.decomposition_group(L.primes_above(3)[0]) sage: H.fixed_field() (Number Field in a0 with defining polynomial x^2 + 2, Ring morphism: From: Number Field in a0 with defining polynomial x^2 + 2 To: Number Field in a with defining polynomial x^4 + 1 Defn: a0 |--> a^3 + a) """ if self.order() == 1: return self._galois_closure # work around a silly error vecs = [pari(g.domain()).Vecsmall() for g in self._elts] v = self._ambient._pari_data.galoisfixedfield(vecs) x = self._galois_closure(v[1]) return self._galois_closure.subfield(x)
def pari(x): """ Return the PARI object constructed from a Sage/Python object. For Sage types, this uses the `_pari_()` method on the object if possible and otherwise it uses the string representation. EXAMPLES:: sage: pari([2,3,5]) [2, 3, 5] sage: pari(Matrix(2,2,range(4))) [0, 1; 2, 3] sage: pari(x^2-3) x^2 - 3 :: sage: a = pari(1); a, a.type() (1, 't_INT') sage: a = pari(1/2); a, a.type() (1/2, 't_FRAC') sage: a = pari(1/2); a, a.type() (1/2, 't_FRAC') Conversion from reals uses the real's own precision:: sage: a = pari(1.2); a, a.type(), a.precision() (1.20000000000000, 't_REAL', 4) # 32-bit (1.20000000000000, 't_REAL', 3) # 64-bit Conversion from strings uses the current PARI real precision. By default, this is 96 bits on 32-bit systems and 128 bits on 64-bit systems:: sage: a = pari('1.2'); a, a.type(), a.precision() (1.20000000000000, 't_REAL', 5) # 32-bit (1.20000000000000, 't_REAL', 4) # 64-bit But we can change this precision:: sage: pari.set_real_precision(35) # precision in decimal digits 15 sage: a = pari('1.2'); a, a.type(), a.precision() (1.2000000000000000000000000000000000, 't_REAL', 6) # 32-bit (1.2000000000000000000000000000000000, 't_REAL', 4) # 64-bit Set the precision to 15 digits for the remaining tests:: sage: pari.set_real_precision(15) 35 Conversion from matrices is supported, but not from vectors; use lists or tuples instead:: sage: a = pari(matrix(2,3,[1,2,3,4,5,6])); a, a.type() ([1, 2, 3; 4, 5, 6], 't_MAT') sage: v = vector([1.2,3.4,5.6]) sage: pari(v) Traceback (most recent call last): ... PariError: syntax error, unexpected ')', expecting )-> or ',' sage: b = pari(list(v)); b,b.type() ([1.20000000000000, 3.40000000000000, 5.60000000000000], 't_VEC') sage: b = pari(tuple(v)); b, b.type() ([1.20000000000000, 3.40000000000000, 5.60000000000000], 't_VEC') Some more exotic examples:: sage: K.<a> = NumberField(x^3 - 2) sage: pari(K) [y^3 - 2, [1, 1], -108, 1, [[1, 1.25992104989487, 1.58740105196820; 1, -0.629960524947437 + 1.09112363597172*I, -0.793700525984100 - 1.37472963699860*I], [1, 1.25992104989487, 1.58740105196820; 1, 0.461163111024285, -2.16843016298270; 1, -1.72108416091916, 0.581029111014503], [1, 1, 2; 1, 0, -2; 1, -2, 1], [3, 0, 0; 0, 0, 6; 0, 6, 0], [6, 0, 0; 0, 6, 0; 0, 0, 3], [2, 0, 0; 0, 0, 1; 0, 1, 0], [2, [0, 0, 2; 1, 0, 0; 0, 1, 0]], []], [1.25992104989487, -0.629960524947437 + 1.09112363597172*I], [1, y, y^2], [1, 0, 0; 0, 1, 0; 0, 0, 1], [1, 0, 0, 0, 0, 2, 0, 2, 0; 0, 1, 0, 1, 0, 0, 0, 0, 2; 0, 0, 1, 0, 1, 0, 1, 0, 0]] sage: E = EllipticCurve('37a1') sage: pari(E) [0, 0, 1, -1, 0, 0, -2, 1, -1, 48, -216, 37, 110592/37, Vecsmall([1]), [Vecsmall([64, 1])], [0, 0, 0, 0, 0, 0, 0, 0]] Conversion from basic Python types:: sage: pari(int(-5)) -5 sage: pari(long(2**150)) 1427247692705959881058285969449495136382746624 sage: pari(float(pi)) 3.14159265358979 sage: pari(complex(exp(pi*I/4))) 0.707106781186548 + 0.707106781186547*I sage: pari(False) 0 sage: pari(True) 1 Some commands are just executed without returning a value:: sage: pari("dummy = 0; kill(dummy)") sage: type(pari("dummy = 0; kill(dummy)")) <type 'NoneType'> TESTS:: sage: pari(None) Traceback (most recent call last): ... ValueError: Cannot convert None to pari """ from sage.libs.pari.all import pari return pari(x)
def _element_constructor_(self, x): r""" Coerce ``x`` into the finite field. INPUT: - ``x`` -- object OUTPUT: If possible, makes a finite field element from ``x``. EXAMPLES:: sage: from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari sage: k = FiniteField_ext_pari(3^4, 'a') sage: b = k(5) # indirect doctest sage: b.parent() Finite Field in a of size 3^4 sage: a = k.gen() sage: k(a + 2) a + 2 Univariate polynomials coerce into finite fields by evaluating the polynomial at the field's generator:: sage: from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari sage: R.<x> = QQ[] sage: k, a = FiniteField_ext_pari(5^2, 'a').objgen() sage: k(R(2/3)) 4 sage: k(x^2) a + 3 sage: R.<x> = GF(5)[] sage: k(x^3-2*x+1) 2*a + 4 sage: x = polygen(QQ) sage: k(x^25) a sage: Q, q = FiniteField_ext_pari(5^7, 'q').objgen() sage: L = GF(5) sage: LL.<xx> = L[] sage: Q(xx^2 + 2*xx + 4) q^2 + 2*q + 4 Multivariate polynomials only coerce if constant:: sage: R = k['x,y,z']; R Multivariate Polynomial Ring in x, y, z over Finite Field in a of size 5^2 sage: k(R(2)) 2 sage: R = QQ['x,y,z'] sage: k(R(1/5)) Traceback (most recent call last): ... TypeError: unable to coerce Gap elements can also be coerced into finite fields:: sage: from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari sage: F = FiniteField_ext_pari(8, 'a') sage: a = F.multiplicative_generator(); a a sage: b = gap(a^3); b Z(2^3)^3 sage: F(b) a + 1 sage: a^3 a + 1 sage: a = GF(13)(gap('0*Z(13)')); a 0 sage: a.parent() Finite Field of size 13 sage: F = GF(16, 'a') sage: F(gap('Z(16)^3')) a^3 sage: F(gap('Z(16)^2')) a^2 You can also call a finite extension field with a string to produce an element of that field, like this:: sage: k = GF(2^8, 'a') sage: k('a^200') a^4 + a^3 + a^2 This is especially useful for fast conversions from Singular etc. to ``FiniteField_ext_pariElements``. AUTHORS: - David Joyner (2005-11) - Martin Albrecht (2006-01-23) - Martin Albrecht (2006-03-06): added coercion from string """ if isinstance(x, element_ext_pari.FiniteField_ext_pariElement): if x.parent() is self: return x elif x.parent() == self: # canonically isomorphic finite fields return element_ext_pari.FiniteField_ext_pariElement(self, x) else: # This is where we *would* do coercion from one finite field to another... raise TypeError, "no coercion defined" elif sage.interfaces.gap.is_GapElement(x): from sage.interfaces.gap import gfq_gap_to_sage try: return gfq_gap_to_sage(x, self) except (ValueError, IndexError, TypeError): raise TypeError, "no coercion defined" if isinstance(x, (int, long, integer.Integer, rational.Rational, pari.pari_gen, list)): return element_ext_pari.FiniteField_ext_pariElement(self, x) elif isinstance(x, multi_polynomial_element.MPolynomial): if x.is_constant(): return self(x.constant_coefficient()) else: raise TypeError, "no coercion defined" elif isinstance(x, polynomial_element.Polynomial): if x.is_constant(): return self(x.constant_coefficient()) else: return x.change_ring(self)(self.gen()) elif isinstance(x, str): x = x.replace(self.variable_name(),'a') x = pari.pari(x) t = x.type() if t == 't_POL': if (x.variable() == 'a' \ and x.polcoeff(0).type()[2] == 'I'): #t_INT and t_INTMOD return self(x) if t[2] == 'I': #t_INT and t_INTMOD return self(x) raise TypeError, "string element does not match this finite field" try: if x.parent() == self.vector_space(): x = pari.pari('+'.join(['%s*a^%s'%(x[i], i) for i in range(self.degree())])) return element_ext_pari.FiniteField_ext_pariElement(self, x) except AttributeError: pass try: return element_ext_pari.FiniteField_ext_pariElement(self, integer.Integer(x)) except TypeError, msg: raise TypeError, "%s\nno coercion defined"%msg
def __init__(self, q, name, modulus=None): """ Create finite field of order `q` with variable printed as name. EXAMPLES:: sage: from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari sage: k = FiniteField_ext_pari(9, 'a'); k Finite Field in a of size 3^2 """ if element_ext_pari.dynamic_FiniteField_ext_pariElement is None: element_ext_pari._late_import() from constructor import FiniteField as GF q = integer.Integer(q) if q < 2: raise ArithmeticError, "q must be a prime power" from sage.structure.proof.all import arithmetic proof = arithmetic() if proof: F = q.factor() else: from sage.rings.arith import is_pseudoprime_small_power F = is_pseudoprime_small_power(q, get_data=True) if len(F) != 1: raise ArithmeticError, "q must be a prime power" if F[0][1] > 1: base_ring = GF(F[0][0]) else: raise ValueError, "The size of the finite field must not be prime." #base_ring = self FiniteField_generic.__init__(self, base_ring, name, normalize=True) self._kwargs = {} self.__char = F[0][0] self.__pari_one = pari.pari(1).Mod(self.__char) self.__degree = integer.Integer(F[0][1]) self.__order = q self.__is_field = True if modulus is None or modulus == "default": from constructor import exists_conway_polynomial if exists_conway_polynomial(self.__char, self.__degree): modulus = "conway" else: modulus = "random" if isinstance(modulus,str): if modulus == "conway": from constructor import conway_polynomial modulus = conway_polynomial(self.__char, self.__degree) elif modulus == "random": # The following is fast/deterministic, but has serious problems since # it crashes on 64-bit machines, and I can't figure out why: # self.__pari_modulus = pari.pari.finitefield_init(self.__char, self.__degree, self.variable_name()) # So instead we iterate through random polys until we find an irreducible one. R = GF(self.__char)['x'] while True: modulus = R.random_element(self.__degree) modulus = modulus.monic() if modulus.degree() == self.__degree and modulus.is_irreducible(): break else: raise ValueError("Modulus parameter not understood") elif isinstance(modulus, (list, tuple)): modulus = GF(self.__char)['x'](modulus) elif sage.rings.polynomial.polynomial_element.is_Polynomial(modulus): if modulus.parent() is not base_ring: modulus = modulus.change_ring(base_ring) else: raise ValueError("Modulus parameter not understood") self.__modulus = modulus f = pari.pari(str(modulus)) self.__pari_modulus = f.subst(modulus.parent().variable_name(), 'a') * self.__pari_one self.__gen = element_ext_pari.FiniteField_ext_pariElement(self, pari.pari('a')) self._zero_element = self._element_constructor_(0) self._one_element = self._element_constructor_(1)