Ticket #12353: 12353.patch

File 12353.patch, 10.5 KB (added by jdemeyer, 11 years ago)
  • sage/categories/pushout.py

    # HG changeset patch
    # User David Roe <roed@math.harvard.edu>
    # Date 1328611759 28800
    # Node ID 60e36db8acf2a02aae71293edfbc5d7f914ffc53
    # Parent  312f1dde57f8feeddfa1aab7d62a254a4ee3f575
    Fix coercion pushouts for real fields
    
    diff --git a/sage/categories/pushout.py b/sage/categories/pushout.py
    a b  
    20012001        INPUT:
    20022002
    20032003        - ``p``: A prime number, the generator of a univariate polynomial ring, or ``+Infinity``
     2004
    20042005        - ``prec``: an integer, yielding the precision in bits. Note that
    20052006          if ``p`` is prime then the ``prec`` is the *capped* precision,
    20062007          while it is the *set* precision if ``p`` is ``+Infinity``.
     2008
    20072009        - ``extras`` (optional dictionary): Information on how to print elements, etc.
     2010          If 'type' is given as a key, the corresponding value should be a string among the following:
     2011
     2012          - 'RDF', 'Interval', 'RLF', or 'RR' for completions at infinity
     2013
     2014          - 'capped-rel', 'capped-abs', 'fixed-mod' or 'lazy' for completions at a finite place
     2015            or ideal of a DVR.
    20082016
    20092017        TESTS::
    20102018
     
    20182026            sage: F2
    20192027            Completion[+Infinity]
    20202028            sage: F2.extras
    2021             {'sci_not': False, 'rnd': 'RNDN'}
     2029            {'type': 'MPFR', 'sci_not': False, 'rnd': 'RNDN'}
    20222030
    20232031        """
    20242032        Functor.__init__(self, Rings(), Rings())
    20252033        self.p = p
    20262034        self.prec = prec
    2027         self.extras = extras
     2035        if extras is None:
     2036            self.extras = {}
     2037            self.type = None
     2038        else:
     2039            self.extras = dict(extras)
     2040            self.type = extras.get('type', None)
     2041            from sage.rings.infinity import Infinity
     2042            if self.p == Infinity:
     2043                if self.type not in self._real_types:
     2044                    raise ValueError("completion type must be one of %s"%(", ".join(self._real_types)))
     2045            else:
     2046                if self.type not in self._dvr_types:
     2047                    raise ValueError("completion type must be one of %s"%(", ".join(self._dvr_types)))
    20282048
    20292049    def __str__(self):
    20302050        """
     
    20502070
    20512071        """
    20522072        try:
    2053             if self.extras is None:
    2054                 try:
    2055                     return R.completion(self.p, self.prec)
    2056                 except TypeError:
    2057                     return R.completion(self.p, self.prec, {})
    2058             return R.completion(self.p, self.prec, self.extras)
     2073            if len(self.extras) == 0:
     2074                if self.type is None:
     2075                    try:
     2076                        return R.completion(self.p, self.prec)
     2077                    except TypeError:
     2078                        return R.completion(self.p, self.prec, {})
     2079                else:
     2080                    return R.completion(self.p, self.prec, {'type':self.type})
     2081            else:
     2082                extras = self.extras.copy()
     2083                extras['type'] = self.type
     2084                return R.completion(self.p, self.prec, extras)
    20592085        except (NotImplementedError,AttributeError):
    20602086            if R.construction() is None:
    20612087                raise NotImplementedError, "Completion is not implemented for %s"%R.__class__
     
    20972123            c = cmp(self.p, other.p)
    20982124        return c
    20992125
     2126    _real_types = ['Interval','MPFR','RDF','RLF']
     2127    _dvr_types = [None, 'fixed-mod','capped-abs','capped-rel','lazy']
     2128
    21002129    def merge(self, other):
    21012130        """
    21022131        Two Completion functors are merged, if they are equal. If the precisions of
     
    21192148            sage: (R3(1) + R4(1)).parent()
    21202149            Real Field with 30 bits of precision
    21212150
    2122         """
    2123         if self!=other:
    2124             return None
    2125         if self.p == other.p:
     2151        TESTS:
     2152
     2153        We check that #12353 has been resolved::
     2154
     2155            sage: RealIntervalField(53)(-1) > RR(1)
     2156            False
     2157            sage: RealIntervalField(54)(-1) > RR(1)
     2158            False
     2159            sage: RealIntervalField(54)(1) > RR(-1)
     2160            True
     2161            sage: RealIntervalField(53)(1) > RR(-1)
     2162            True
     2163
     2164        We check that various pushouts work::
     2165
     2166            sage: R0 = RealIntervalField(30)
     2167            sage: R1 = RealIntervalField(30, sci_not=True)
     2168            sage: R2 = RealIntervalField(53)
     2169            sage: R3 = RealIntervalField(53, sci_not = True)
     2170            sage: R4 = RealIntervalField(90)
     2171            sage: R5 = RealIntervalField(90, sci_not = True)
     2172            sage: R6 = RealField(30)
     2173            sage: R7 = RealField(30, sci_not=True)
     2174            sage: R8 = RealField(53, rnd = 'RNDD')
     2175            sage: R9 = RealField(53, sci_not = True, rnd = 'RNDZ')
     2176            sage: R10 = RealField(53, sci_not = True)
     2177            sage: R11 = RealField(90, sci_not = True, rnd = 'RNDZ')
     2178            sage: Rlist = [R0,R1,R2,R3,R4,R5,R6,R7,R8,R9,R10,R11]
     2179            sage: from sage.categories.pushout import pushout
     2180            sage: pushouts = [R0,R0,R0,R1,R0,R1,R0,R1,R0,R1,R1,R1,R1,R1,R1,R1,R1,R1,R1,R1,R1,R1,R1,R1,R0,R1,R2,R2,R2,R3,R0,R1,R2,R3,R3,R3,R1,R1,R3,R3,R3,R3,R1,R1,R3,R3,R3,R3,R0,R1,R2,R3,R4,R4,R0,R1,R2,R3,R3,R5,R1,R1,R3,R3,R5,R5,R1,R1,R3,R3,R3,R5,R0,R1,R0,R1,R0,R1,R6,R6,R6,R7,R7,R7,R1,R1,R1,R1,R1,R1,R7,R7,R7,R7,R7,R7,R0,R1,R2,R3,R2,R3,R6,R7,R8,R9,R10,R9,R1,R1,R3,R3,R3,R3,R7,R7,R9,R9,R10,R9,R1,R1,R3,R3,R3,R3,R7,R7,R10,R10,R10,R10,R1,R1,R3,R3,R5,R5,R7,R7,R9,R9,R10,R11]
     2181            sage: all([R is S for R, S in zip(pushouts, [pushout(a, b) for a in Rlist for b in Rlist])])
     2182            True
     2183
     2184        ::
     2185
     2186            sage: P0 = ZpFM(5, 10)
     2187            sage: P1 = ZpFM(5, 20)
     2188            sage: P2 = ZpCR(5, 10)
     2189            sage: P3 = ZpCR(5, 20)
     2190            sage: P4 = ZpCA(5, 10)
     2191            sage: P5 = ZpCA(5, 20)
     2192            sage: P6 = Qp(5, 10)
     2193            sage: P7 = Qp(5, 20)
     2194            sage: Plist = [P2,P3,P4,P5,P6,P7]
     2195            sage: from sage.categories.pushout import pushout
     2196            sage: pushouts = [P2,P3,P4,P5,P6,P7,P3,P3,P5,P5,P7,P7,P4,P5,P4,P5,P6,P7,P5,P5,P5,P5,P7,P7,P6,P7,P6,P7,P6,P7,P7,P7,P7,P7,P7,P7]
     2197            sage: all([P is Q for P, Q in zip(pushouts, [pushout(a, b) for a in Plist for b in Plist])])
     2198            True
     2199        """
     2200        if self == other: # both are Completion functors with the same p
    21262201            from sage.all import Infinity
    2127             if self.prec == other.prec:
     2202            if self.p == Infinity:
     2203                new_prec = min(self.prec, other.prec)
     2204                new_type = self._real_types[min(self._real_types.index(self.type), \
     2205                                                self._real_types.index(other.type))]
     2206                new_scinot = max(self.extras.get('sci_not',0), other.extras.get('sci_not',0))
     2207                from sage.rings.real_mpfr import _rounding_modes
     2208                new_rnd = _rounding_modes[min(_rounding_modes.index(self.extras.get('rnd', 'RNDN')), \
     2209                                              _rounding_modes.index(other.extras.get('rnd', 'RNDN')))]
     2210                return CompletionFunctor(self.p, new_prec, {'type': new_type, 'sci_not':new_scinot, 'rnd':new_rnd})
     2211            else:
     2212                new_type = self._dvr_types[min(self._dvr_types.index(self.type), self._dvr_types.index(other.type))]
     2213                if new_type == 'fixed-mod':
     2214                    if self.type != 'fixed-mod' or other.type != 'fixed-mod':
     2215                        return None # no coercion into fixed-mod
     2216                    new_prec = min(self.prec, other.prec)
     2217                else:
     2218                    new_prec = max(self.prec, other.prec) # since elements track their own precision, we don't want to truncate them
    21282219                extras = self.extras.copy()
    21292220                extras.update(other.extras)
    2130                 return CompletionFunctor(self.p, self.prec, extras)
    2131             elif (self.p==Infinity and self.prec<other.prec) or (self.p<Infinity and self.prec>other.prec):
    2132                 return self
    2133             else: # self.prec > other.prec
    2134                 return other
    2135         else:
    2136             return None
     2221                extras['type'] = new_type
     2222                return CompletionFunctor(self.p, new_prec, extras)
     2223
    21372224##   Completion has a lower rank than FractionField
    21382225##   and is thus applied first. However, fact is that
    21392226##   both commute. This is used in the call method,
  • sage/rings/real_mpfr.pyx

    diff --git a/sage/rings/real_mpfr.pyx b/sage/rings/real_mpfr.pyx
    a b  
    576576        from sage.categories.pushout import CompletionFunctor
    577577        return (CompletionFunctor(sage.rings.infinity.Infinity,
    578578                                  self.prec(),
    579                                   {'sci_not': self.scientific_notation(), 'rnd': self.rounding_mode()}),
     579                                  {'type': 'MPFR', 'sci_not': self.scientific_notation(), 'rnd': self.rounding_mode()}),
    580580               sage.rings.rational_field.QQ)
    581581
    582582    def gen(self, i=0):
     
    49544954
    49554955# here because this imports the other two real fields
    49564956def create_RealField(prec=53, type="MPFR", rnd="RNDN", sci_not=0):
     4957    """
     4958    Create a real field with given precision, type, rounding mode and scientific notation.
     4959
     4960    Some options are ignored for certain types (RDF for example).
     4961
     4962    INPUT:
     4963
     4964    - prec -- a positive integer
     4965
     4966    - type -- a string, one of
     4967
     4968      - 'RDF' -- the Sage real field corresponding to native doubles
     4969
     4970      - 'Interval' -- real fields implementing interval arithmetic
     4971
     4972      - 'RLF' -- the real lazy field
     4973
     4974      - 'MPFR' -- floating point real numbers implemented using the MPFR library
     4975
     4976    - rnd -- a string, one of
     4977
     4978      - 'RNDN' -- round to nearest
     4979
     4980      - 'RNDZ' -- round toward zero
     4981
     4982      - 'RNDD' -- round down
     4983
     4984      - 'RNDU' -- round up
     4985
     4986    - sci_not -- boolean, whether to use scientific notation for printing
     4987
     4988    OUTPUT:
     4989
     4990    - the appropriate real field.
     4991
     4992    EXAMPLES::
     4993
     4994        sage: from sage.rings.real_mpfr import create_RealField
     4995        sage: create_RealField(30)
     4996        Real Field with 30 bits of precision
     4997        sage: create_RealField(20, 'RDF') # ignores precision
     4998        Real Double Field
     4999        sage: create_RealField(60, 'Interval')
     5000        Real Interval Field with 60 bits of precision
     5001        sage: create_RealField(40, 'RLF') # ignores precision
     5002        Real Lazy Field
     5003    """
    49575004    if type == "RDF":
    49585005        return RDF
    4959     elif type == "RQDF":
    4960         from real_rqdf import RQDF
    4961         return RQDF
    49625006    elif type == "Interval":
    49635007        from real_mpfi import RealIntervalField
    49645008        return RealIntervalField(prec, sci_not)