# HG changeset patch
# User Jeroen Demeyer <jdemeyer@cage.ugent.be>
# Date 1361826806 3600
# Node ID d40bb6780315cf0e0acc7eb09b51ba56572bf4ca
# Parent 31d4341b32cc4191638967f2d0bfac70ce94a5da
Fix whitespace in coercion_and_categories.rst
diff git a/doc/en/thematic_tutorials/coercion_and_categories.rst b/doc/en/thematic_tutorials/coercion_and_categories.rst
a

b


88  88  elements. But some old stuff in Sage doesn't use it. **Volunteers for 
89  89  refactoring are welcome!** 
90  90  
91   
 91  
92  92  
93  93  The parent 
94  94   
… 
… 

387  387  
388  388  Sage's category framework can differentiate the two cases:: 
389  389  
390   sage: Rings() 
 390  sage: Rings() 
391  391  Category of rings 
392  392  sage: MS1 in Rings() 
393  393  False 
… 
… 

556  556  "``Element``", whose value is a class. 
557  557   The parent *automatically* obtains an attribute ``P.element_class``, that 
558  558  subclasses both ``P.Element`` and ``P.category().element_class``. 
559   
 559  
560  560  Hence, for providing our fraction fields with their own element classes, **we 
561  561  just need to add a single line to our class**:: 
562  562  
… 
… 

696  696  
697  697  .. end of output 
698  698  
699   So, *don't be afraid of using categories!* 
 699  So, *don't be afraid of using categories!* 
700  700  
701  701  
702  702  Coercion\the basics 
… 
… 

789  789  Hence, we only have a *partial* map. This is fine for a *conversion*, 
790  790  but a partial map does not qualify as a *coercion*. 
791  791  
792   B. Coercions are structure preserving. 
 792  B. Coercions are structure preserving. 
793  793  
794  794  Any real number can be converted to an integer, namely by 
795  795  rounding. However, such a conversion is not useful in arithmetic 
… 
… 

1713  1713  raise ValueError, "The parent must be provided" 
1714  1714  B = parent.base() 
1715  1715  if d is None: 
1716   # The default denominator is one 
 1716  # The default denominator is one 
1717  1717  d = B.one_element() 
1718   # verify that both numerator and denominator belong to the base 
 1718  # verify that both numerator and denominator belong to the base 
1719  1719  if n not in B or d not in B: 
1720  1720  raise ValueError, "Numerator and denominator must be elements of %s"%B 
1721  1721  # Numerator and denominator should not just be "in" B, 
1722  1722  # but should be defined as elements of B 
1723  1723  d = B(d) 
1724  1724  n = B(n) 
1725   # the denominator must not be zero 
 1725  # the denominator must not be zero 
1726  1726  if d==0: 
1727  1727  raise ZeroDivisionError, "The denominator must not be zero" 
1728  1728  # normalize the denominator: WLOG, it shall be nonnegative. 
… 
… 

1744  1744  def _repr_(self): 
1745  1745  return "(%s):(%s)"%(self.n,self.d) 
1746  1746  
1747   # Comparison: We can assume that both arguments are coerced 
1748   # into the same parent, which is a fraction field. Hence, we 
1749   # are allowed to use the denominator() and numerator() methods 
1750   # on the second argument. 
 1747  # Comparison: We can assume that both arguments are coerced 
 1748  # into the same parent, which is a fraction field. Hence, we 
 1749  # are allowed to use the denominator() and numerator() methods 
 1750  # on the second argument. 
1751  1751  def __cmp__(self, other): 
1752  1752  return cmp(self.n*other.denominator(), other.numerator()*self.d) 
1753   # Arithmetic methods, single underscore. We can assume that both 
1754   # arguments are coerced into the same parent. 
1755   # We return instances of self.__class__, because self.__class__ will 
1756   # eventually be a subclass of MyElement. 
 1753  # Arithmetic methods, single underscore. We can assume that both 
 1754  # arguments are coerced into the same parent. 
 1755  # We return instances of self.__class__, because self.__class__ will 
 1756  # eventually be a subclass of MyElement. 
1757  1757  def _add_(self, other): 
1758  1758  C = self.__class__ 
1759  1759  D = self.d*other.denominator() 
… 
… 

1774  1774  # succeeds to look up the class definition). 
1775  1775  class MyFrac(UniqueRepresentation, Field): 
1776  1776  # Implement the category framework for elements, which also 
1777   # makes some basic conversions work. 
 1777  # makes some basic conversions work. 
1778  1778  Element = MyElement 
1779  1779  
1780   # Allow to pass to a different category, by an optional argument 
 1780  # Allow to pass to a different category, by an optional argument 
1781  1781  def __init__(self, base, category=None): 
1782   # Fraction fields only exist for integral domains 
 1782  # Fraction fields only exist for integral domains 
1783  1783  if base not in IntegralDomains(): 
1784  1784  raise ValueError, "%s is no integral domain"%base 
1785   # Implement the category framework for the parent 
 1785  # Implement the category framework for the parent 
1786  1786  Field.__init__(self, base, category=category or QuotientFields()) 
1787  1787  
1788   # Singleunderscore method for string representation 
 1788  # Singleunderscore method for string representation 
1789  1789  def _repr_(self): 
1790  1790  return "NewFrac(%s)"%repr(self.base()) 
1791  1791  
1792   # Two methods that are implicitly used in some tests 
 1792  # Two methods that are implicitly used in some tests 
1793  1793  def base_ring(self): 
1794  1794  return self.base().base_ring() 
1795  1795  def characteristic(self): 
1796  1796  return self.base().characteristic() 
1797  1797  
1798   # Implement conversions. Do not override __call__! 
 1798  # Implement conversions. Do not override __call__! 
1799  1799  def _element_constructor_(self, *args,**kwds): 
1800  1800  if len(args)!=1: 
1801  1801  return self.element_class(*args,parent=self,**kwds) 
… 
… 

1808  1808  return self.element_class(x.numerator(),x.denominator(),parent=self,**kwds) 
1809  1809  return self.element_class(x,parent=self,**kwds) 
1810  1810  
1811   # Implement coercion from the base and from fraction fields 
1812   # over a ring that coerces into the base 
 1811  # Implement coercion from the base and from fraction fields 
 1812  # over a ring that coerces into the base 
1813  1813  def _coerce_map_from_(self, S): 
1814  1814  if self.base().has_coerce_map_from(S): 
1815  1815  return True 
… 
… 

1818  1818  return True 
1819  1819  if hasattr(S,'ring_of_integers') and self.base().has_coerce_map_from(S.ring_of_integers()): 
1820  1820  return True 
1821   # Tell how this parent was constructed, in order to enable pushout constructions 
 1821  # Tell how this parent was constructed, in order to enable pushout constructions 
1822  1822  def construction(self): 
1823  1823  return MyFracFunctor(), self.base() 
1824  1824  
… 
… 

1841  1841  rank = 5 
1842  1842  def __init__(self): 
1843  1843  # The fraction field construction is a functor 
1844   # from the category of integral domains into the category of 
1845   # fields 
1846   # NOTE: We could actually narrow the codomain and use the 
1847   # category QuotientFields() 
 1844  # from the category of integral domains into the category of 
 1845  # fields 
 1846  # NOTE: We could actually narrow the codomain and use the 
 1847  # category QuotientFields() 
1848  1848  ConstructionFunctor.__init__(self, IntegralDomains(), Fields()) 
1849  1849  # Applying the functor to an object. Do not override __call__! 
1850  1850  def _apply_functor(self, R): 
1851  1851  return MyFrac(R) 
1852   # Note: To apply the functor to morphisms, implement 
1853   # _apply_functor_to_morphism 
 1852  # Note: To apply the functor to morphisms, implement 
 1853  # _apply_functor_to_morphism 
1854  1854  
1855   # Make sure that arithmetic involving elements of Frac(R) and 
1856   # MyFrac(R) works and yields elements of MyFrac(R) 
 1855  # Make sure that arithmetic involving elements of Frac(R) and 
 1856  # MyFrac(R) works and yields elements of MyFrac(R) 
1857  1857  def merge(self, other): 
1858  1858  if isinstance(other, (type(self), sage.categories.pushout.FractionField)): 
1859  1859  return self 
… 
… 

1868  1868  # rather than from sage.categories.category.Category 
1869  1869  class QuotientFieldsWithTest(Category): 
1870  1870  # Our category is a subcategory of the category of quotient fields, 
1871   # by means of the following method. 
 1871  # by means of the following method. 
1872  1872  def super_categories(self): 
1873  1873  return [QuotientFields()] 
1874  1874  
1875   # Here, we could implement methods that are available for 
1876   # all objects in this category. 
 1875  # Here, we could implement methods that are available for 
 1876  # all objects in this category. 
1877  1877  class ParentMethods: 
1878  1878  pass 
1879  1879  
1880   # Here, we add a new test that is available for all elements 
1881   # of any object in this category. 
 1880  # Here, we add a new test that is available for all elements 
 1881  # of any object in this category. 
1882  1882  class ElementMethods: 
1883  1883  def _test_factorisation(self, **options): 
1884  1884  P = self.parent() 
1885   # The methods prod() and factor() are inherited from 
1886   # some other categories. 
 1885  # The methods prod() and factor() are inherited from 
 1886  # some other categories. 
1887  1887  assert self == P.prod([P(b)**e for b,e in self.factor()]) 
1888  1888  
1889  1889  