#10771: gcd and lcm for fraction fields
--------------------------------+-------------------------------------------
   Reporter:  SimonKing         |       Owner:  AlexGhitza             
       Type:  defect            |      Status:  needs_work             
   Priority:  major             |   Milestone:  sage-4.7               
  Component:  basic arithmetic  |    Keywords:  gcd lcm fraction fields
     Author:  Simon King        |    Upstream:  N/A                    
   Reviewer:  Marco Streng      |      Merged:                         
Work_issues:                    |  
--------------------------------+-------------------------------------------

Comment(by SimonKing):

 Hi Luis!

 Replying to [comment:11 lftabera]:
 > > That's implemented as element methods for the category of `Fields()`.
 Somehow, the category framework is cool, isn't it?
 >
 > I do not full understand this, but I am happy that works.

 Then let me explain:

 Any category (in Sage) comes with a parent class and an "element class".
 That very often is an abstract thing, but you can inherit from it, and in
 particular you can implement methods for it.

 If things are properly done, then a parent P is declared as an object in
 some category, and its class ''automatically(!)'' inherits from the parent
 class of its category:
 {{{
 sage: QQ.__class__
 <class 'sage.rings.rational_field.RationalField_with_category'>
 sage: issubclass(QQ.__class__,QuotientFields().parent_class)
 True
 }}}

 If things are very properly done, then the parent has an attribute
 `Element`, which is supposed to be a class. That class will (again
 automatically) be translated into a subclass of the element class of the
 parent's category, and is available as the attribute `element_class`:
 {{{
 sage: m = matrix(GF(2),[[1]])
 sage: G = MatrixGroup([m])
 sage: G.Element
 <class 'sage.groups.matrix_gps.matrix_group_element.MatrixGroupElement'>
 sage: G.__class__
 <class
 
'sage.groups.matrix_gps.matrix_group.MatrixGroup_gens_finite_field_with_category'>
 sage: G.element_class
 <class
 
'sage.groups.matrix_gps.matrix_group_element.MatrixGroup_gens_finite_field_with_category.element_class'>
 sage: issubclass(G.element_class,G.Element)
 True
 sage: issubclass(G.element_class,G.category().element_class)
 True
 sage: isinstance(G.random_element(),G.category().element_class)
 True
 }}}

 So, if things are very properly done, then a method defined as an "element
 method" of a category, will be available by looking up the method
 resolution order, since the elements of the parent are actual instances of
 the category's element class.

 Sometimes things are done properly, but not ''very'' properly:
 {{{
 sage: QQ.category()
 Category of quotient fields
 sage: isinstance(QQ, QQ.category().parent_class)
 True
 sage: hasattr(QQ,'Element')
 False
 sage: isinstance(QQ.one(), QQ.category().element_class)
 False
 }}}

 Hence, the methods that I defined for the element class of the "category
 of quotient fields" is not available to elements of `QQ` by simply looking
 up the method resolution order. But: There also is a `__getattr__` method
 implemented for `sage.structure.element.Element`, and this can access the
 element methods of the category of the parent of an element (uff!) even if
 the element is no instance of the "proper" element class.

 This is why the new gcd works for the rationals, but it's slower than with
 the method resolution order, and this is why I also did not remove the
 existing lcm for rationals.

 > Some thoughts:
 >
 > For QQ and the like, could it be that gcd and lcm should only take care
 of coercing to a good setting and then the real algorithm should be in
 _lcm, _gcd? Note that QQ already has ._gcd and ._lcm so these methods has
 to be taken into account.

 That's a nice observation. By searching a little, I found that `_gcd` is
 used in the method
 `sage.structure.element.PrincipalIdealDomainElement.gcd`.

 However, there are only very few classes that define a `_gcd` method:
 `sage.structure.element.EuclideanDomainElement`,
 `sage.structure.element.FieldElement`, `sage.rings.rational.Rational`, and
 then there are hits in `...polynomial_element_generic` and
 `...polynomial_modn_dense_ntl`.

 In other words, I guess that the `_gcd` method is an artefact of earlier
 attempts to reflect mathematics in the class hierarchy -- this should now
 be done in the category framework. `_gcd` will ''only'' play a role if

  1. the class of an element derives from `PrincipalIdealDomainElement`,
 and

  2. the class of an element additionally defines `_gcd`.

 It seems to me that there is precisely one class that directly inherits
 from `PrincipalIdealDomainElement`, and there is precisely one class that
 directly inherits from that class:
 {{{
 sage: search_src("\(PrincipalIdealDomainElement")
 structure/element.pxd:83:cdef class
 EuclideanDomainElement(PrincipalIdealDomainElement):
 structure/element.pyx:2370:cdef class
 EuclideanDomainElement(PrincipalIdealDomainElement):

 sage: search_src("\(EuclideanDomainElement")
 structure/element.pyx:2362:PY_SET_TP_NEW(EuclideanDomainElement, Element)
 rings/integer.pxd:9:cdef class Integer(EuclideanDomainElement):
 }}}

 So, `_gcd` is only used for the `Integer` class. I guess it could easily
 be removed.

 > For generic Fields, It should appear in the documentation that the
 methods return 0 if both arguments are zero and a non-zero element
 otherwise. The user should not suppose that the non-zero element is
 actually one, since this is changed by subclasses.

 Right. I'll take care of that, but now I have a bus to catch...

-- 
Ticket URL: <http://trac.sagemath.org/sage_trac/ticket/10771#comment:12>
Sage <http://www.sagemath.org>
Sage: Creating a Viable Open Source Alternative to Magma, Maple, Mathematica, 
and MATLAB

-- 
You received this message because you are subscribed to the Google Groups 
"sage-trac" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/sage-trac?hl=en.

Reply via email to