Ticket #14563: trac_14563-Z_to_quadratic_field.patch

File trac_14563-Z_to_quadratic_field.patch, 10.7 KB (added by vdelecroix, 6 years ago)
  • sage/rings/number_field/number_field.py

    # HG changeset patch
    # User Vincent Delecroix <20100.delecroix at gmail.com>
    # Date 1368224392 -7200
    # Node ID 1c41ae414bd6cbde181288c6da4566ccd2ea2bd6
    # Parent  5d8c13e7b81a1e152855073f97a4d48ee97255d1
    trac 14563
    
    Faster coercion from Integer Ring to Quadratic Number Field.
    
    diff --git a/sage/rings/number_field/number_field.py b/sage/rings/number_field/number_field.py
    a b  
    76957695            # _one_element to NumberFieldElement_absolute values, which is
    76967696            # wrong (and dangerous; such elements can actually be used to
    76977697            # crash Sage: see #5316).  Overwrite them with correct values.
    7698             self._zero_element = self(0)
    7699             self._one_element =  self(1)
     7698            self._zero_element = self._element_class(self, (QQ(0),QQ(0)))
     7699            self._one_element =  self._element_class(self, (QQ(1),QQ(0)))
    77007700
    77017701        zeta = self.gen()
    77027702        zeta._set_multiplicative_order(n)
     
    79717971                return number_field_morphisms.NumberFieldEmbedding(K, self, -self.gen() ** e)
    79727972            else:
    79737973                return None
    7974         else:
    7975             return NumberField_absolute._coerce_map_from_(self, K)
     7974
     7975        elif self.degree() == 2:
     7976            if K is ZZ:
     7977                return number_field_element_quadratic.Z_to_quadratic_field_element(self)
     7978            if K is QQ:
     7979                return number_field_element_quadratic.Q_to_quadratic_field_element(self)
     7980
     7981        return NumberField_absolute._coerce_map_from_(self, K)
    79767982
    79777983    def _log_gen(self, x):
    79787984        """
     
    89088914        # _one_element to NumberFieldElement_absolute values, which is
    89098915        # wrong (and dangerous; such elements can actually be used to
    89108916        # crash Sage: see #5316).  Overwrite them with correct values.
    8911         self._zero_element = self(0)
    8912         self._one_element =  self(1)
    8913 
     8917        self._zero_element = self._element_class(self, (QQ(0), QQ(0)))
     8918        self._one_element  = self._element_class(self, (QQ(1), QQ(0)))
    89148919
    89158920    def _coerce_map_from_(self, K):
    89168921        """
    89178922        EXAMPLES::
    8918        
     8923
    89198924            sage: K.<a> = QuadraticField(-3)
    89208925            sage: f = K.coerce_map_from(QQ); f # indirect doctest
    89218926            Natural morphism:
     
    89258930            3/5
    89268931            sage: parent(f(3/5)) is K
    89278932            True
    8928         """
     8933
     8934            sage: g = K.coerce_map_from(ZZ); g # indirect doctest
     8935            Natural morphism:
     8936              From: Integer Ring
     8937              To:   Number Field in a with defining polynomial x^2 + 3
     8938            sage: g(1)
     8939            1
     8940            sage: parent(g(1)) is K
     8941            True
     8942        """
     8943        if K is ZZ:
     8944            return number_field_element_quadratic.Z_to_quadratic_field_element(self)
    89298945        if K is QQ:
    89308946            return number_field_element_quadratic.Q_to_quadratic_field_element(self)
    8931         else:
    8932             return NumberField_absolute._coerce_map_from_(self, K)
     8947        return NumberField_absolute._coerce_map_from_(self, K)
    89338948
    89348949    def _latex_(self):
    89358950        """
  • sage/rings/number_field/number_field_element_quadratic.pyx

    diff --git a/sage/rings/number_field/number_field_element_quadratic.pyx b/sage/rings/number_field/number_field_element_quadratic.pyx
    a b  
    3636include "sage/ext/stdsage.pxi"
    3737
    3838from sage.structure.element cimport Element
    39 from sage.rings.integer cimport Integer
    4039
    4140from sage.rings.integer_ring import ZZ
    4241from sage.rings.rational_field import QQ
     
    153152    def __init__(self, parent, f):
    154153        """
    155154        Standard initialisation function.
    156        
     155
    157156        EXAMPLE::
    158157
    159158            sage: F.<a> = QuadraticField(-7)
     
    164163        self.D = parent._D
    165164        cdef Integer a, b, denom
    166165        cdef Rational ad, bd
    167        
     166
    168167        cdef NumberFieldElement_quadratic gen
    169168
    170169        if PY_TYPE_CHECK(f, NumberFieldElement_quadratic):
     
    172171            mpz_set(self.a, (<NumberFieldElement_quadratic>f).a)
    173172            mpz_set(self.b, (<NumberFieldElement_quadratic>f).b)
    174173            mpz_set(self.denom, (<NumberFieldElement_quadratic>f).denom)
    175            
    176         elif PY_TYPE_CHECK_EXACT(f, Rational):
    177             NumberFieldElement_absolute.__init__(self, parent, None)
    178             mpz_set(self.a, mpq_numref((<Rational>f).value))
    179             mpz_set_ui(self.b, 0)
    180             mpz_set(self.denom, mpq_denref((<Rational>f).value))
    181            
     174
    182175        elif PY_TYPE_CHECK_EXACT(f, tuple) and len(f) == 2:
    183176            NumberFieldElement_absolute.__init__(self, parent, None)
    184177            ad, bd = f
     
    187180            mpz_mul(self.a, self.a, mpq_numref(ad.value))
    188181            mpz_divexact(self.b, self.denom, mpq_denref(bd.value))
    189182            mpz_mul(self.b, self.b, mpq_numref(bd.value))
    190            
     183
    191184        elif PY_TYPE_CHECK_EXACT(f, tuple) and len(f) == 3:
    192185            NumberFieldElement_absolute.__init__(self, parent, None)
    193186            a, b, denom = f
     
    195188            mpz_set(self.b, b.value)
    196189            mpz_set(self.denom, denom.value)
    197190            self._reduce_c_()
    198            
     191
    199192        else:
    200193            NumberFieldElement_absolute.__init__(self, parent, f)
    201194            # poly is in gen (which may not be sqrt(d))
     
    20392032        R = self.parent()
    20402033        return R(_inverse_mod_generic(self, I))
    20412034
     2035cdef class Z_to_quadratic_field_element(Morphism):
     2036    """
     2037    Morphism that coerces from integers to elements of a quadratic number
     2038    field K.
     2039    """
     2040    cdef NumberFieldElement_quadratic zero_element    # the zero element of K
     2041
     2042    # TODO: implement __cmp__ properly so we can have a loads/dumps doctest
     2043
     2044    def __init__(self, K):
     2045        """
     2046        ``K`` is the target quadratic field
     2047
     2048        EXAMPLE::
     2049
     2050            sage: K.<a> = QuadraticField(3)
     2051            sage: phi = K.coerce_map_from(ZZ) # indirect doctest
     2052            sage: type(phi)
     2053            <type 'sage.rings.number_field.number_field_element_quadratic.Z_to_quadratic_field_element'>
     2054            sage: phi == loads(dumps(phi)) # not implemented
     2055            True
     2056
     2057            sage: R.<b> = CyclotomicField(6)
     2058            sage: psi = R.coerce_map_from(ZZ) # indirect doctest
     2059            sage: type(psi)
     2060            <type 'sage.rings.number_field.number_field_element_quadratic.Z_to_quadratic_field_element'>
     2061            sage: psi == loads(dumps(psi)) # not implemented
     2062            True
     2063        """
     2064        import sage.categories.homset
     2065        Morphism.__init__(self, sage.categories.homset.Hom(ZZ, K))
     2066        self.zero_element = K.zero_element()
     2067
     2068    cpdef Element _call_(self, x):
     2069        r"""
     2070        Evaluate at an integer ``x``.
     2071
     2072        EXAMPLE::
     2073
     2074            sage: K.<a> = QuadraticField(3)
     2075            sage: phi = K.coerce_map_from(ZZ)
     2076            sage: a = phi(2); a # indirect doctest
     2077            2
     2078            sage: a.parent() is K
     2079            True
     2080
     2081            sage: R.<b> = CyclotomicField(6)
     2082            sage: psi = R.coerce_map_from(ZZ)
     2083            sage: b = psi(-42); b # indirect doctest
     2084            -42
     2085            sage: b.parent() is R
     2086            True
     2087        """
     2088        cdef NumberFieldElement_quadratic y
     2089        if mpz_sgn((<Integer> x).value) == 0:
     2090            return self.zero_element
     2091        y = self.zero_element._new()
     2092        mpz_set(y.a, (<Integer> x).value)
     2093
     2094        # we need to set the denominator to 1 as it is 0 for
     2095        # the zero element of K... (because gcd(0,0) = 0).
     2096        mpz_set_ui(y.denom, 1)
     2097
     2098        return y
     2099
     2100    def _repr_type(self):
     2101        r"""
     2102        Return a short name for this morphism.
     2103
     2104        EXAMPLE::
     2105
     2106            sage: K.<a> = QuadraticField(3)
     2107            sage: phi = K.coerce_map_from(ZZ)
     2108            sage: repr(phi) # indirect doctest
     2109            'Natural morphism:\n  From: Integer Ring\n  To:   Number Field in a with defining polynomial x^2 - 3'
     2110
     2111            sage: R.<b> = CyclotomicField(6)
     2112            sage: psi = R.coerce_map_from(ZZ)
     2113            sage: repr(psi) # indirect doctest
     2114            'Natural morphism:\n  From: Integer Ring\n  To:   Cyclotomic Field of order 6 and degree 2'
     2115        """
     2116        return "Natural"
     2117
    20422118cdef class Q_to_quadratic_field_element(Morphism):
    20432119    """
    20442120    Morphism that coerces from rationals to elements of a quadratic number
    20452121    field K.
    20462122    """
    20472123    cdef NumberFieldElement_quadratic zero_element    # the zero element of K
    2048    
     2124
    20492125    # TODO: implement __cmp__ properly so we can have a loads/dumps doctest
    20502126
    20512127    def __init__(self, K):
    2052         """ 
    2053         K is the target quadratic field
    2054        
     2128        """
     2129        ``K`` is the target quadratic field
     2130
    20552131        EXAMPLE::
    2056    
     2132
    20572133            sage: K.<a> = QuadraticField(3)
    20582134            sage: phi = K.coerce_map_from(QQ) # indirect doctest
    20592135            sage: type(phi)
    20602136            <type 'sage.rings.number_field.number_field_element_quadratic.Q_to_quadratic_field_element'>
    20612137            sage: phi == loads(dumps(phi)) # not implemented
    20622138            True
     2139
     2140            sage: R.<b> = CyclotomicField(6)
     2141            sage: psi = R.coerce_map_from(QQ)
     2142            sage: type(psi)
     2143            <type 'sage.rings.number_field.number_field_element_quadratic.Q_to_quadratic_field_element'>
     2144            sage: psi == loads(dumps(psi)) # not implemented
     2145            True
    20632146        """
    20642147        import sage.categories.homset
    20652148        Morphism.__init__(self, sage.categories.homset.Hom(QQ, K))
     
    20672150
    20682151    cpdef Element _call_(self, x):
    20692152        r"""
    2070         Evaluate at a rational x.
     2153        Evaluate at a rational ``x``.
    20712154
    20722155        EXAMPLE::
    20732156
     
    20772160            2/3
    20782161            sage: a.parent() is K
    20792162            True
     2163
     2164            sage: R.<b> = CyclotomicField(6)
     2165            sage: psi = R.coerce_map_from(QQ)
     2166            sage: b = psi(-23/15); b # indirect doctest
     2167            -23/15
     2168            sage: b.parent() is R
     2169            True
    20802170        """
    20812171        cdef NumberFieldElement_quadratic y = self.zero_element._new()
    2082         y.D = self.zero_element.D
    20832172        mpz_set(y.a, mpq_numref((<Rational>x).value))
    20842173        mpz_set(y.denom, mpq_denref((<Rational>x).value))
    20852174        return y
     
    20942183            sage: phi = K.coerce_map_from(QQ)
    20952184            sage: repr(phi) # indirect doctest
    20962185            'Natural morphism:\n  From: Rational Field\n  To:   Number Field in a with defining polynomial x^2 - 3'
     2186
     2187            sage: R.<b> = CyclotomicField(6)
     2188            sage: psi = R.coerce_map_from(QQ)
     2189            sage: repr(psi) # indirect doctest
     2190            'Natural morphism:\n  From: Rational Field\n  To:   Cyclotomic Field of order 6 and degree 2'
    20972191        """
    20982192        return "Natural"