Ticket #12353: 12353.patch
File 12353.patch, 10.5 KB (added by , 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 2001 2001 INPUT: 2002 2002 2003 2003 - ``p``: A prime number, the generator of a univariate polynomial ring, or ``+Infinity`` 2004 2004 2005 - ``prec``: an integer, yielding the precision in bits. Note that 2005 2006 if ``p`` is prime then the ``prec`` is the *capped* precision, 2006 2007 while it is the *set* precision if ``p`` is ``+Infinity``. 2008 2007 2009 - ``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. 2008 2016 2009 2017 TESTS:: 2010 2018 … … 2018 2026 sage: F2 2019 2027 Completion[+Infinity] 2020 2028 sage: F2.extras 2021 {' sci_not': False, 'rnd': 'RNDN'}2029 {'type': 'MPFR', 'sci_not': False, 'rnd': 'RNDN'} 2022 2030 2023 2031 """ 2024 2032 Functor.__init__(self, Rings(), Rings()) 2025 2033 self.p = p 2026 2034 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))) 2028 2048 2029 2049 def __str__(self): 2030 2050 """ … … 2050 2070 2051 2071 """ 2052 2072 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) 2059 2085 except (NotImplementedError,AttributeError): 2060 2086 if R.construction() is None: 2061 2087 raise NotImplementedError, "Completion is not implemented for %s"%R.__class__ … … 2097 2123 c = cmp(self.p, other.p) 2098 2124 return c 2099 2125 2126 _real_types = ['Interval','MPFR','RDF','RLF'] 2127 _dvr_types = [None, 'fixed-mod','capped-abs','capped-rel','lazy'] 2128 2100 2129 def merge(self, other): 2101 2130 """ 2102 2131 Two Completion functors are merged, if they are equal. If the precisions of … … 2119 2148 sage: (R3(1) + R4(1)).parent() 2120 2149 Real Field with 30 bits of precision 2121 2150 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 2126 2201 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 2128 2219 extras = self.extras.copy() 2129 2220 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 2137 2224 ## Completion has a lower rank than FractionField 2138 2225 ## and is thus applied first. However, fact is that 2139 2226 ## 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 576 576 from sage.categories.pushout import CompletionFunctor 577 577 return (CompletionFunctor(sage.rings.infinity.Infinity, 578 578 self.prec(), 579 {' sci_not': self.scientific_notation(), 'rnd': self.rounding_mode()}),579 {'type': 'MPFR', 'sci_not': self.scientific_notation(), 'rnd': self.rounding_mode()}), 580 580 sage.rings.rational_field.QQ) 581 581 582 582 def gen(self, i=0): … … 4954 4954 4955 4955 # here because this imports the other two real fields 4956 4956 def 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 """ 4957 5004 if type == "RDF": 4958 5005 return RDF 4959 elif type == "RQDF":4960 from real_rqdf import RQDF4961 return RQDF4962 5006 elif type == "Interval": 4963 5007 from real_mpfi import RealIntervalField 4964 5008 return RealIntervalField(prec, sci_not)