Commits

Volker Braun committed b3e0e55

rebased to sage-5.7.beta2

  • Participants
  • Parent commits fe4f12f

Comments (0)

Files changed (20)

File 13687_32bitfix.patch

-# HG changeset patch
-# Parent 35615722fd3e6d0aed6e37164f7318ac8cfe872e
-
-Fix some doctests that are different on 32-bit
-
-diff --git a/sage/rings/number_field/unit_group.py b/sage/rings/number_field/unit_group.py
---- a/sage/rings/number_field/unit_group.py
-+++ b/sage/rings/number_field/unit_group.py
-@@ -136,7 +136,8 @@
-         sage: u = UK.an_element();  u
-         u0*u1
-         sage: u.value()
--        -1/4*a^3 - 7/4*a^2 - 17/4*a - 19/4
-+        -1/4*a^3 + 7/4*a^2 - 17/4*a + 19/4     # 32-bit
-+        -1/4*a^3 - 7/4*a^2 - 17/4*a - 19/4     # 64-bit
- 
-         sage: x = polygen(QQ)
-         sage: K.<a> = NumberField(x^4 + 23)
-diff --git a/sage/rings/polynomial/polynomial_quotient_ring.py b/sage/rings/polynomial/polynomial_quotient_ring.py
---- a/sage/rings/polynomial/polynomial_quotient_ring.py
-+++ b/sage/rings/polynomial/polynomial_quotient_ring.py
-@@ -972,7 +972,7 @@
-             sage: S.S_class_group([K.ideal(2, a+1)])
-             []
-             sage: S.S_class_group([K.ideal(a)])
--            [((2, -a + 1, 1/2*xbar + 1/2, -1/2*a*xbar + 1/2*a + 1), 6, 1/2*xbar - 3/2)] # 32-bit
-+            [((2, -a + 1, 1/2*xbar + 1/2, -1/2*a*xbar + 1/2*a + 1), 6, -1/2*xbar + 3/2)] # 32-bit
-             [((2, -a + 1, 1/2*xbar + 1/2, -1/2*a*xbar + 1/2*a + 1), 6, -1/2*xbar + 3/2)] # 64-bit
- 
-         Now we take an example over a nontrivial base with two factors, each

File 13687_parent_for_groups_all.patch

-# HG changeset patch
-# User Volker Braun <vbraun@stp.dias.ie>
-# Date 1352835583 18000
-# Node ID 5a5673e6beb0a82cda2dcfedae5c874ab2176588
-# Parent  908396c26c29b73e36d91ae4821b8a353ef23c83
-New-style parents for Abelian groups
-
-diff --git a/doc/de/tutorial/tour_advanced.rst b/doc/de/tutorial/tour_advanced.rst
---- a/doc/de/tutorial/tour_advanced.rst
-+++ b/doc/de/tutorial/tour_advanced.rst
-@@ -362,7 +362,7 @@
-     Dirichlet character modulo 20 of conductor 5 mapping 11 |--> 1, 17 |--> i)
- 
-     sage: G.unit_gens()
--    [11, 17]
-+    (11, 17)
-     sage: G.zeta()
-     i
-     sage: G.zeta_order()
-diff --git a/doc/de/tutorial/tour_groups.rst b/doc/de/tutorial/tour_groups.rst
---- a/doc/de/tutorial/tour_groups.rst
-+++ b/doc/de/tutorial/tour_groups.rst
-@@ -82,10 +82,10 @@
-     sage: d * b**2 * c**3 
-     b^2*c^3*d
-     sage: F = AbelianGroup(3,[2]*3); F
--    Multiplicative Abelian Group isomorphic to C2 x C2 x C2
-+    Multiplicative Abelian group isomorphic to C2 x C2 x C2
-     sage: H = AbelianGroup([2,3], names="xy"); H
--    Multiplicative Abelian Group isomorphic to C2 x C3
-+    Multiplicative Abelian group isomorphic to C2 x C3
-     sage: AbelianGroup(5)
--    Multiplicative Abelian Group isomorphic to Z x Z x Z x Z x Z
-+    Multiplicative Abelian group isomorphic to Z x Z x Z x Z x Z
-     sage: AbelianGroup(5).order()
-     +Infinity
-diff --git a/doc/en/bordeaux_2008/nf_galois_groups.rst b/doc/en/bordeaux_2008/nf_galois_groups.rst
---- a/doc/en/bordeaux_2008/nf_galois_groups.rst
-+++ b/doc/en/bordeaux_2008/nf_galois_groups.rst
-@@ -311,7 +311,7 @@
-     sage: category(C)
-     Category of groups
-     sage: C.gens()
--    [Fractional ideal class (5, a), Fractional ideal class (3, a)]
-+    (Fractional ideal class (5, a), Fractional ideal class (3, a))
- 
- 
- Arithmetic in the class group
-diff --git a/doc/en/reference/groups.rst b/doc/en/reference/groups.rst
---- a/doc/en/reference/groups.rst
-+++ b/doc/en/reference/groups.rst
-@@ -9,9 +9,12 @@
-    sage/groups/group
-    sage/groups/generic
-    sage/groups/abelian_gps/abelian_group
-+   sage/groups/abelian_gps/values
-+   sage/groups/abelian_gps/dual_abelian_group
-+   sage/groups/abelian_gps/element_base
-    sage/groups/abelian_gps/abelian_group_element
-+   sage/groups/abelian_gps/dual_abelian_group_element
-    sage/groups/abelian_gps/abelian_group_morphism
--   sage/groups/abelian_gps/dual_abelian_group
-    sage/groups/additive_abelian/additive_abelian_group
-    sage/groups/additive_abelian/additive_abelian_wrapper
-    sage/groups/perm_gps/permgroup
-diff --git a/doc/en/tutorial/tour_advanced.rst b/doc/en/tutorial/tour_advanced.rst
---- a/doc/en/tutorial/tour_advanced.rst
-+++ b/doc/en/tutorial/tour_advanced.rst
-@@ -360,7 +360,7 @@
-     Dirichlet character modulo 20 of conductor 5 mapping 11 |--> 1, 17 |--> i)
- 
-     sage: G.unit_gens()
--    [11, 17]
-+    (11, 17)
-     sage: G.zeta()
-     i
-     sage: G.zeta_order()
-diff --git a/doc/en/tutorial/tour_groups.rst b/doc/en/tutorial/tour_groups.rst
---- a/doc/en/tutorial/tour_groups.rst
-+++ b/doc/en/tutorial/tour_groups.rst
-@@ -80,10 +80,10 @@
-     sage: d * b**2 * c**3 
-     b^2*c^3*d
-     sage: F = AbelianGroup(3,[2]*3); F
--    Multiplicative Abelian Group isomorphic to C2 x C2 x C2
-+    Multiplicative Abelian group isomorphic to C2 x C2 x C2
-     sage: H = AbelianGroup([2,3], names="xy"); H
--    Multiplicative Abelian Group isomorphic to C2 x C3
-+    Multiplicative Abelian group isomorphic to C2 x C3
-     sage: AbelianGroup(5)
--    Multiplicative Abelian Group isomorphic to Z x Z x Z x Z x Z
-+    Multiplicative Abelian group isomorphic to Z x Z x Z x Z x Z
-     sage: AbelianGroup(5).order()
-     +Infinity
-diff --git a/doc/fr/tutorial/tour_advanced.rst b/doc/fr/tutorial/tour_advanced.rst
---- a/doc/fr/tutorial/tour_advanced.rst
-+++ b/doc/fr/tutorial/tour_advanced.rst
-@@ -360,7 +360,7 @@
-     Dirichlet character modulo 20 of conductor 5 mapping 11 |--> 1, 17 |--> i)
- 
-     sage: G.unit_gens()
--    [11, 17]
-+    (11, 17)
-     sage: G.zeta()
-     i
-     sage: G.zeta_order()
-diff --git a/doc/fr/tutorial/tour_groups.rst b/doc/fr/tutorial/tour_groups.rst
---- a/doc/fr/tutorial/tour_groups.rst
-+++ b/doc/fr/tutorial/tour_groups.rst
-@@ -83,10 +83,10 @@
-     sage: d * b**2 * c**3 
-     b^2*c^3*d
-     sage: F = AbelianGroup(3,[2]*3); F
--    Multiplicative Abelian Group isomorphic to C2 x C2 x C2
-+    Multiplicative Abelian group isomorphic to C2 x C2 x C2
-     sage: H = AbelianGroup([2,3], names="xy"); H
--    Multiplicative Abelian Group isomorphic to C2 x C3
-+    Multiplicative Abelian group isomorphic to C2 x C3
-     sage: AbelianGroup(5)
--    Multiplicative Abelian Group isomorphic to Z x Z x Z x Z x Z
-+    Multiplicative Abelian group isomorphic to Z x Z x Z x Z x Z
-     sage: AbelianGroup(5).order()
-     +Infinity
-diff --git a/doc/ru/tutorial/tour_advanced.rst b/doc/ru/tutorial/tour_advanced.rst
---- a/doc/ru/tutorial/tour_advanced.rst
-+++ b/doc/ru/tutorial/tour_advanced.rst
-@@ -325,7 +325,7 @@
-     Dirichlet character modulo 20 of conductor 5 mapping 11 |--> 1, 17 |--> i)
- 
-     sage: G.unit_gens()
--    [11, 17]
-+    (11, 17)
-     sage: G.zeta()
-     i
-     sage: G.zeta_order()
-diff --git a/doc/ru/tutorial/tour_groups.rst b/doc/ru/tutorial/tour_groups.rst
---- a/doc/ru/tutorial/tour_groups.rst
-+++ b/doc/ru/tutorial/tour_groups.rst
-@@ -80,10 +80,10 @@
-     sage: d * b**2 * c**3 
-     b^2*c^3*d
-     sage: F = AbelianGroup(3,[2]*3); F
--    Multiplicative Abelian Group isomorphic to C2 x C2 x C2
-+    Multiplicative Abelian group isomorphic to C2 x C2 x C2
-     sage: H = AbelianGroup([2,3], names="xy"); H
--    Multiplicative Abelian Group isomorphic to C2 x C3
-+    Multiplicative Abelian group isomorphic to C2 x C3
-     sage: AbelianGroup(5)
--    Multiplicative Abelian Group isomorphic to Z x Z x Z x Z x Z
-+    Multiplicative Abelian group isomorphic to Z x Z x Z x Z x Z
-     sage: AbelianGroup(5).order()
-     +Infinity
-diff --git a/module_list.py b/module_list.py
---- a/module_list.py
-+++ b/module_list.py
-@@ -488,6 +488,9 @@
-     Extension('sage.groups.group',
-               sources = ['sage/groups/group.pyx']),
- 
-+    Extension('sage.groups.old',
-+              sources = ['sage/groups/old.pyx']),
-+
-     Extension('sage.groups.perm_gps.permgroup_element',
-               sources = ['sage/groups/perm_gps/permgroup_element.pyx']),
- 
-diff --git a/sage/algebras/group_algebra.py b/sage/algebras/group_algebra.py
---- a/sage/algebras/group_algebra.py
-+++ b/sage/algebras/group_algebra.py
-@@ -30,6 +30,7 @@
- from sage.algebras.algebra_element import AlgebraElement
- from sage.rings.all import IntegerRing
- from sage.groups.group import Group
-+from sage.groups.old import Group as OldGroup
- from sage.structure.formal_sum import FormalSums, FormalSum
- from sage.sets.set import Set
- 
-@@ -67,7 +68,7 @@
-         if not base_ring.is_commutative():
-             raise NotImplementedError("Base ring must be commutative")
-         
--        if not isinstance(group, Group):
-+        if not isinstance(group, (Group, OldGroup)):
-             raise TypeError('"%s" is not a group' % group)
- 
-         ParentWithGens.__init__(self, base_ring, category = GroupAlgebras(base_ring))
-@@ -251,7 +252,7 @@
-             sage: ZG(1) == ZG(G(1))
-             True
-             sage: ZG(FormalSum([(1,f), (2, f**2)]))
--            2*f^2 + f
-+            f + 2*f^2
-             sage: G = GL(2,7)
-             sage: OG = GroupAlgebra(G, ZZ[sqrt(5)])
-             sage: OG(2)
-diff --git a/sage/algebras/group_algebra_new.py b/sage/algebras/group_algebra_new.py
---- a/sage/algebras/group_algebra_new.py
-+++ b/sage/algebras/group_algebra_new.py
-@@ -256,10 +256,11 @@
-             Group algebra of group "General Linear Group of degree 3 over Finite Field of size 7" over base ring Integer Ring
-         """
-         from sage.groups.group import Group
-+        from sage.groups.old import Group as OldGroup
-         if not base_ring.is_commutative():
-             raise NotImplementedError("Base ring must be commutative")
- 
--        if not isinstance(group, Group):
-+        if not isinstance(group, (Group, OldGroup)):
-             raise TypeError('"%s" is not a group' % group)
- 
-         self._group = group
-@@ -680,7 +681,7 @@
-             True
-         """
-         from sage.rings.all import is_Ring
--        from sage.groups.group import Group
-+        from sage.groups.old import Group
-         k = self.base_ring()
-         G = self.group()
-         if isinstance(S, GroupAlgebra):
-@@ -732,7 +733,7 @@
-             [0 1]
-         """
-         from sage.rings.all import is_Ring
--        from sage.groups.group import Group
-+        from sage.groups.old import Group
-         from sage.structure.formal_sum import FormalSum
-         k = self.base_ring()
-         G = self.group()
-diff --git a/sage/all.py b/sage/all.py
---- a/sage/all.py
-+++ b/sage/all.py
-@@ -42,6 +42,7 @@
- exit = quit
- 
- import os, sys
-+import operator
- 
- if 'SAGE_ROOT' not in os.environ:
-     raise RuntimeError("To use the Sage libraries, set the environment variable SAGE_ROOT to the Sage build directory and LD_LIBRARY_PATH to $SAGE_ROOT/local/lib")
-diff --git a/sage/categories/action.pyx b/sage/categories/action.pyx
---- a/sage/categories/action.pyx
-+++ b/sage/categories/action.pyx
-@@ -216,8 +216,9 @@
-     An action that acts as the inverse of the given action.
- 
-     TESTS:
-+
-     This illustrates a shortcoming in the current coercion model.
--    See the comments in _call_ below. 
-+    See the comments in _call_ below::
-     
-         sage: x = polygen(QQ,'x')
-         sage: a = 2*x^2+2; a
-@@ -231,10 +232,11 @@
-     def __init__(self, Action action):
-         G = action.G
-         try:
-+            from sage.groups.old import Group as OldGroup
-             from sage.groups.group import Group
-             # We must be in the case that parent(~a) == parent(a)
-             # so we can invert in call_c code below.
--            if (PY_TYPE_CHECK(G, Group) and G.is_multiplicative()) or G.is_field():
-+            if (isinstance(G, (Group, OldGroup)) and G.is_multiplicative()) or G.is_field():
-                 Action.__init__(self, G, action.underlying_set(), action._is_left)
-                 self._action = action
-                 return
-diff --git a/sage/categories/category.py b/sage/categories/category.py
---- a/sage/categories/category.py
-+++ b/sage/categories/category.py
-@@ -23,7 +23,7 @@
-     sage: Sets()
-     Category of sets
-     sage: GSets(AbelianGroup([2,4,9]))
--    Category of G-sets for Multiplicative Abelian Group isomorphic to C2 x C4 x C9
-+    Category of G-sets for Multiplicative Abelian group isomorphic to C2 x C4 x C9
-     sage: Semigroups()
-     Category of semigroups
-     sage: VectorSpaces(FiniteField(11))
-diff --git a/sage/groups/abelian_gps/abelian_group.py b/sage/groups/abelian_gps/abelian_group.py
---- a/sage/groups/abelian_gps/abelian_group.py
-+++ b/sage/groups/abelian_gps/abelian_group.py
-@@ -1,31 +1,60 @@
- r"""
- Multiplicative Abelian Groups
- 
--AUTHORS:
-+This module lets you compute with finitely generated Abelian groups of the form
- 
--- William Stein, David Joyner (2008-12): added (user requested) is_cyclic,
--  fixed elementary_divisors.
-+.. math::
- 
--- David Joyner (2006-03): (based on free abelian monoids by David
--  Kohel)
-+    G = \ZZ^r \oplus \ZZ_{k_1} \oplus \cdots \oplus \ZZ_{k_t}
- 
--- David Joyner (2006-05) several significant bug fixes
-+It is customary to denote the infinite cyclic group `\ZZ` as having
-+order `0`, so the data defining the Abelian group can be written as an
-+integer vector
- 
--- David Joyner (2006-08) trivial changes to docs, added random, fixed
--  bug in how invariants are recorded
-+.. math::
- 
--- David Joyner (2006-10) added dual_group method
-+    \vec{k} = (0, \dots, 0, k_1, \dots, k_t)
- 
--- David Joyner (2008-02) fixed serious bug in word_problem
-+where there are `r` zeroes and `t` non-zero values. To construct this
-+Abelian group in Sage, you can either specify all entries of `\vec{k}`
-+or only the non-zero entries together with the total number of
-+generators::
- 
--- David Joyner (2008-03) fixed bug in trivial group case
-+    sage: AbelianGroup([0,0,0,2,3])
-+    Multiplicative Abelian group isomorphic to Z x Z x Z x C2 x C3
-+    sage: AbelianGroup(5, [2,3])
-+    Multiplicative Abelian group isomorphic to Z x Z x Z x C2 x C3
- 
--- David Loeffler (2009-05) added subgroups method
-+It is also legal to specify `1` as the order. The corresponding
-+generator will be the neutral element, but it will still take up an
-+index in the labelling of the generators::
- 
-+    sage: G = AbelianGroup([2,1,3], names='g')
-+    sage: G.gens()
-+    (g0, 1, g2)
- 
--TODO: 
-+Note that this presentation is not unique, for example `\ZZ_6 = \ZZ_2
-+\times \ZZ_3`. The orders of the generators
-+`\vec{k}=(0,\dots,0,k_1,\dots, k_t)` has previously been called
-+invariants in Sage, even though they are not necessarily the (unique)
-+invariant factors of the group. You should now use
-+:meth:`~AbelianGroup_class.gens_orders` instead::
- 
--- additive abelian groups should also be supported
-+   sage: J = AbelianGroup([2,0,3,2,4]);  J
-+   Multiplicative Abelian group isomorphic to C2 x Z x C3 x C2 x C4
-+   sage: J.gens_orders()            # use this instead
-+   (2, 0, 3, 2, 4)
-+   sage: J.invariants()             # deprecated
-+   (2, 0, 3, 2, 4)
-+   sage: J.elementary_divisors()    # these are the "invariant factors"
-+   (2, 2, 12, 0)
-+   sage: for i in range(J.ngens()):
-+   ...       print i, J.gen(i), J.gen(i).order()     # or use this form
-+   0 f0 2
-+   1 f1 +Infinity
-+   2 f2 3
-+   3 f3 2
-+   4 f4 4
- 
- Background on invariant factors and the Smith normal form 
- (according to section 4.1 of [C1]): An abelian group is a
-@@ -37,7 +66,7 @@
- 
- .. math::
- 
--   A = \langle a_1\rangle \times \dots \times  \langle a_\ell\rangle ,
-+    A = \langle a_1\rangle \times \dots \times  \langle a_\ell\rangle ,
- 
- where `ord(a_i)=p_i^{c_i}`, for some primes `p_i` and some
- positive integers `c_i`, `i=1,...,\ell`. GAP calls the 
-@@ -59,15 +88,15 @@
- 
- .. math::
- 
--   F=
--   \left(
--   \begin{array}{cccc}
--   f_{11} & f_{12} & \dots & f_{1m}\\
--   f_{21} & f_{22} & \dots & f_{2m}\\
--   \vdots &        & \ddots & \vdots \\
--   f_{\ell,1} & f_{\ell,2} & \dots & f_{\ell,m}
--   \end{array}
--   \right),
-+    F=
-+    \left(
-+    \begin{array}{cccc}
-+    f_{11} & f_{12} & \dots & f_{1m}\\
-+    f_{21} & f_{22} & \dots & f_{2m}\\
-+    \vdots &        & \ddots & \vdots \\
-+    f_{\ell,1} & f_{\ell,2} & \dots & f_{\ell,m}
-+    \end{array}
-+    \right),
- 
- regarded as a map 
- `\ZZ^m\rightarrow (\ZZ/p_1^{c_1}\ZZ)\times ...\times (\ZZ/p_\ell^{c_\ell}\ZZ)`.
-@@ -80,41 +109,37 @@
- 
- .. math::
- 
--  s_1, s_2/s_1, s_3/s_2, ... s_r/s_{r-1}.
--
--
-+    s_1, s_2/s_1, s_3/s_2, ... s_r/s_{r-1}.
- 
- Sage supports multiplicative abelian groups on any prescribed finite
--number `n \geq 0` of generators.  Use the ``AbelianGroup`` function
--to create an abelian group, and the ``gen`` and ``gens``
--functions to obtain the corresponding generators.  You can print the
--generators as arbitrary strings using the optional ``names``
--argument to the ``AbelianGroup`` function.
-+number `n \geq 0` of generators.  Use the :func:`AbelianGroup`
-+function to create an abelian group, and the
-+:meth:`~AbelianGroup_class.gen` and :meth:`~AbelianGroup_class.gens`
-+methods to obtain the corresponding generators.  You can print the
-+generators as arbitrary strings using the optional ``names`` argument
-+to the :func:`AbelianGroup` function.
- 
- EXAMPLE 1:
- 
- We create an abelian group in zero or more variables; the syntax T(1)
--creates the identity element even in the rank zero case.
--
--::
-+creates the identity element even in the rank zero case::
- 
-     sage: T = AbelianGroup(0,[])
-     sage: T
--    Trivial Abelian Group
-+    Trivial Abelian group
-     sage: T.gens()
-     ()
-     sage: T(1)
-     1
- 
--EXAMPLE 2: An abelian group uses a multiplicative representation of
--elements, but the underlying representation is lists of integer
--exponents.
-+EXAMPLE 2:
- 
--::
-+An Abelian group uses a multiplicative representation of elements, but
-+the underlying representation is lists of integer exponents::
- 
-     sage: F = AbelianGroup(5,[3,4,5,5,7],names = list("abcde"))
-     sage: F
--    Multiplicative Abelian Group isomorphic to C3 x C4 x C5 x C5 x C7
-+    Multiplicative Abelian group isomorphic to C3 x C4 x C5 x C5 x C7
-     sage: (a,b,c,d,e) = F.gens()
-     sage: a*b^2*e*d
-     a*b^2*d*e
-@@ -139,36 +164,59 @@
- 
-    Many basic properties for infinite abelian groups are not
-    implemented.
-+
-+
-+AUTHORS:
-+
-+- William Stein, David Joyner (2008-12): added (user requested) is_cyclic,
-+  fixed elementary_divisors.
-+
-+- David Joyner (2006-03): (based on free abelian monoids by David
-+  Kohel)
-+
-+- David Joyner (2006-05) several significant bug fixes
-+
-+- David Joyner (2006-08) trivial changes to docs, added random, fixed
-+  bug in how invariants are recorded
-+
-+- David Joyner (2006-10) added dual_group method
-+
-+- David Joyner (2008-02) fixed serious bug in word_problem
-+
-+- David Joyner (2008-03) fixed bug in trivial group case
-+
-+- David Loeffler (2009-05) added subgroups method
-+
-+- Volker Braun (2012-11) port to new Parent base. Use tuples for
-+  immutables. Rename invariants to gens_orders.
- """
- 
- ##########################################################################
--#  Copyright (C) 2006 David Joyner and William Stein
-+#  Copyright (C) 2006 William Stein <wstein@gmail.com>
-+#  Copyright (C) 2006 David Joyner  <wdjoyner@gmail.com>
-+#  Copyright (C) 2012 Volker Braun  <vbraun.name@gmail.com>
- #
- #  Distributed under the terms of the GNU General Public License (GPL):
- #
- #                  http://www.gnu.org/licenses/
- ##########################################################################
- 
--# TODO: change the "invariants" terminology everywhere to elementary_divisors
--
--
- 
- from sage.rings.integer import Integer
--
-+from sage.rings.integer_ring import ZZ
-+from sage.structure.unique_representation import UniqueRepresentation
- from sage.rings.infinity import infinity
- from sage.rings.arith import divisors, gcd
--from abelian_group_element import AbelianGroupElement
-+from sage.groups.abelian_gps.abelian_group_element import AbelianGroupElement
-+from sage.misc.cachefunc import cached_method
- from sage.misc.misc import prod
- from sage.misc.mrange import mrange, cartesian_product_iterator
--import sage.groups.group as group
--from sage.rings.integer_ring import IntegerRing
- from sage.rings.arith import lcm
--ZZ = IntegerRing()
-+from sage.groups.group import AbelianGroup as AbelianGroupBase
-+
- 
- # TODO: this uses perm groups - the AbelianGroupElement instance method
- # uses a different implementation.
--  
--
- def word_problem(words, g, verbose = False):
-     r"""
-     G and H are abelian, g in G, H is a subgroup of G generated by a
-@@ -202,7 +250,7 @@
-     EXAMPLE::
-     
-         sage: G.<a,b,c> = AbelianGroup(3,[2,3,4]); G
--        Multiplicative Abelian Group isomorphic to C2 x C3 x C4
-+        Multiplicative Abelian group isomorphic to C2 x C3 x C4
-         sage: w = word_problem([a*b,a*c], b*c); w #random 
-         [[a*b, 1], [a*c, 1]]  
-         sage: prod([x^i for x,i in w]) == b*c
-@@ -242,13 +290,12 @@
-           AbelianGroupElement is implemented differently (wrapping
-           GAP's 'EpimorphismFromFreeGroup' and
-           'PreImagesRepresentative') and may be faster.
--       
-     """
-     from sage.interfaces.all import gap
-     G = g.parent()
--    invs = G.invariants()
-+    invs = map(str, G.gens_orders())
-     gap.eval("l:=One(Rationals)")
--    s1 = 'A:=AbelianGroup(%s)'%invs
-+    s1 = 'A:=AbelianGroup([' + ','.join(invs) + '])'
-     gap.eval(s1)
-     s2 = 'phi:=IsomorphismPermGroup(A)'
-     gap.eval(s2)
-@@ -279,32 +326,90 @@
-     return [[words[l3[2*i]-1],LL[i]] for i in range(len(LL))]
- 
- 
--def AbelianGroup(n, invfac=None, names="f"):
-+def _normalize(n, gens_orders=None, names="f"):
-+    """
-+    Helper function for :func:`AbelianGroup`. Beat some sense into the
-+    arguments.
-+
-+    This function is also used by some descendents of
-+    :class:`AbelianGroup_class`.
-+
-+    INPUT:
-+
-+    See :func:`AbelianGroup`
-+
-+    OUTPUT:
-+
-+    Unique data for defining a :class:`AbelianGroup_class`. Raises an
-+    exception if the input is invalid.
-+
-+    EXAMPLES::
-+
-+        sage: from sage.groups.abelian_gps.abelian_group import _normalize
-+        sage: _normalize(5, [2,1,0], names='abc')
-+        ((0, 0, 2, 1, 0), 'abc')
-+        sage: _normalize(5, (2.0, 1.0, 0/1), names=list('abc'))
-+        ((0, 0, 2, 1, 0), ('a', 'b', 'c'))
-+        sage: _normalize([0,2,1,0], names='a')
-+        ((0, 2, 1, 0), 'a')
-+
-+    TESTS::
-+
-+        sage: _normalize(5, (2.0, 1.5, 0/1), names=list('abc'))
-+        Traceback (most recent call last):
-+        ...
-+        TypeError: Attempt to coerce non-integral RealNumber to Integer
-+        sage: _normalize('1', '[2]', names='a')
-+        Traceback (most recent call last):
-+        ...
-+        TypeError: unable to convert x (=[) to an integer
-+        sage: _normalize(3, 'str', names='a')
-+        Traceback (most recent call last):
-+        ...
-+        TypeError: unable to convert x (=s) to an integer
-+   """
-+    if gens_orders is None:
-+        if isinstance(n, (list, tuple)):
-+            gens_orders = n
-+            n = len(n)
-+        else:
-+            gens_orders = []
-+    n = ZZ(n)
-+    if len(gens_orders) < n:
-+        gens_orders = [0] * (n - len(gens_orders)) + list(gens_orders)
-+    gens_orders = tuple(ZZ(i) for i in gens_orders)
-+    if len(gens_orders) > n:
-+        raise ValueError('gens_orders (='+str(gens_orders)+') must have length n (='+str(n)+')')
-+    if isinstance(names, list):
-+        names = tuple(names)
-+    return (gens_orders, names)
-+
-+def AbelianGroup(n, gens_orders=None, names="f"):
-     r"""
-     Create the multiplicative abelian group in `n` generators
--    with given invariants (which need not be prime powers).
-+    with given orders of generators (which need not be prime powers).
-     
-     INPUT:
-     
-+    - ``n`` -- integer (optional). If not specified, will be derived
-+       from ``gens_orders``.
-     
--    -  ``n`` - integer
-+    - ``gens_orders`` -- a list of non-negative integers in the form
-+       `[a_0, a_1, \dots, a_{n-1}]`, typically written in increasing
-+       order. This list is padded with zeros if it has length less
-+       than n. The orders of the commuting generators, with `0`
-+       denoting an infinite cyclic factor.
-     
--    -  ``invfac`` - (the"invariant factors") a list of
--       non-negative integers in the form [a0, a1,...,a(n-1)], typically
--       written in increasing order. This list is padded with zeros if it
--       has length less than n.
-+    -  ``names`` -- (optional) names of generators
-     
--    -  ``names`` - (optional) names of generators
-+    Alternatively, you can also give input in the form
-+    ``AbelianGroup(gens_orders, names="f")``, where the names keyword
-+    argument must be explicitly named.
-     
--       Alternatively, you can also give input in the following form:
--    
--       ``AbelianGroup(invfac, names="f")``,
--    
--       where names must be explicitly named.
--    
--    
--    OUTPUT: Abelian group with generators and invariant type. The
--    default name for generator A.i is fi, as in GAP.
-+    OUTPUT:
-+
-+    Abelian group with generators and invariant type. The default name
-+    for generator ``A.i`` is ``fi``, as in GAP.
-     
-     EXAMPLES::
-     
-@@ -317,52 +422,41 @@
-         sage: d * b**2 * c**3 
-         b^2*c^3*d
-         sage: F = AbelianGroup(3,[2]*3); F
--        Multiplicative Abelian Group isomorphic to C2 x C2 x C2
-+        Multiplicative Abelian group isomorphic to C2 x C2 x C2
-         sage: H = AbelianGroup([2,3], names="xy"); H
--        Multiplicative Abelian Group isomorphic to C2 x C3
-+        Multiplicative Abelian group isomorphic to C2 x C3
-         sage: AbelianGroup(5)
--        Multiplicative Abelian Group isomorphic to Z x Z x Z x Z x Z
-+        Multiplicative Abelian group isomorphic to Z x Z x Z x Z x Z
-         sage: AbelianGroup(5).order()
-         +Infinity
-     
--    Notice how `0`'s are padded on.
-+    Notice that `0`'s are prepended if necessary::
-     
--    ::
--    
--        sage: AbelianGroup(5, [2,3,4])
--        Multiplicative Abelian Group isomorphic to Z x Z x C2 x C3 x C4
--    
--    The invariant list can't be longer than the number of generators.
--    
--    ::
-+        sage: G = AbelianGroup(5, [2,3,4]);  G
-+        Multiplicative Abelian group isomorphic to Z x Z x C2 x C3 x C4
-+        sage: G.gens_orders()
-+        (0, 0, 2, 3, 4)
-+
-+    The invariant list must not be longer than the number of generators::
-     
-         sage: AbelianGroup(2, [2,3,4])
-         Traceback (most recent call last):
-         ...
--        ValueError: invfac (=[2, 3, 4]) must have length n (=2)
-+        ValueError: gens_orders (=(2, 3, 4)) must have length n (=2)
-     """
--    if invfac is None:
--        if isinstance(n, (list, tuple)):
--            invfac = n
--            n = len(n)
--        else:
--            invfac = []
--    if len(invfac) < n:
--        invfac = [0] * (n - len(invfac)) + invfac 
--    elif len(invfac) > n:
--        raise ValueError, "invfac (=%s) must have length n (=%s)"%(invfac, n)
--    M = AbelianGroup_class(n, invfac, names)
-+    gens_orders, names = _normalize(n, gens_orders, names)
-+    M = AbelianGroup_class(gens_orders, names)
-     return M
- 
- def is_AbelianGroup(x):
-     """
--    Return True if `x` is an abelian group.
-+    Return True if ``x`` is an Abelian group.
-     
-     EXAMPLES::
-     
-         sage: from sage.groups.abelian_gps.abelian_group import is_AbelianGroup
-         sage: F = AbelianGroup(5,[5,5,7,8,9],names = list("abcde")); F
--        Multiplicative Abelian Group isomorphic to C5 x C5 x C7 x C8 x C9
-+        Multiplicative Abelian group isomorphic to C5 x C5 x C7 x C8 x C9
-         sage: is_AbelianGroup(F)
-         True
-         sage: is_AbelianGroup(AbelianGroup(7, [3]*7))
-@@ -371,142 +465,165 @@
-     return isinstance(x, AbelianGroup_class)
- 
- 
--class AbelianGroup_class(group.AbelianGroup):
-+class AbelianGroup_class(UniqueRepresentation, AbelianGroupBase):
-     """
--    Abelian group on `n` generators. The invariant factors
--    `[a_1,a_2,...,a_k]` need not be prime powers.
--    divisors will be).
-+    The parent for Abelian groups with chosen generator orders.
-+
-+    .. warning::
-+
-+        You should use :func:`AbelianGroup` to construct Abelian
-+        groups and not instantiate this class directly.
-+    
-+    INPUT:
-+
-+    - ``generator_orders`` -- list of integers. The orders of the
-+      (commuting) generators. Zero denotes an infinite cyclic
-+      generator.
-+
-+    - ``names`` -- names of the group generators (optional).
-     
-     EXAMPLES::
-     
-+        sage: Z2xZ3 = AbelianGroup([2,3])
-+        sage: Z6 = AbelianGroup([6])
-+        sage: Z2xZ3 is Z2xZ3, Z6 is Z6
-+        (True, True)
-+        sage: Z2xZ3 is Z6
-+        False
-+        sage: Z2xZ3 == Z6
-+        True
-+
-         sage: F = AbelianGroup(5,[5,5,7,8,9],names = list("abcde")); F
--        Multiplicative Abelian Group isomorphic to C5 x C5 x C7 x C8 x C9
-+        Multiplicative Abelian group isomorphic to C5 x C5 x C7 x C8 x C9
-         sage: F = AbelianGroup(5,[2, 4, 12, 24, 120],names = list("abcde")); F
--        Multiplicative Abelian Group isomorphic to C2 x C4 x C12 x C24 x C120
-+        Multiplicative Abelian group isomorphic to C2 x C4 x C12 x C24 x C120
-         sage: F.elementary_divisors()
--        [2, 4, 12, 24, 120]
--
--    The entry 1 in the list of invariants is ignored::
--
--        sage: F = AbelianGroup(3,[1,2,3],names='a')
--        sage: F.invariants()
--        [2, 3]
--        sage: F.gens()
--        (a0, a1)
--        sage: F.ngens()
--        2
--        sage: (F.0).order()
--        2
--        sage: (F.1).order()
--        3
--        sage: AbelianGroup(1, [1], names='e')
--        Multiplicative Abelian Group isomorphic to C1
--        sage: AbelianGroup(1, [1], names='e').gens()
--        (e,)
--        sage: AbelianGroup(1, [1], names='e').list()
--        [1]
--        sage: AbelianGroup(3, [2, 1, 2], names=list('abc')).list()
--        [1, b, a, a*b]
-+        (2, 4, 12, 24, 120)
- 
-         sage: F.category()
-         Category of groups
- 
-+    TESTS::
-+
-+        sage: AbelianGroup([]).gens_orders()
-+        ()
-+        sage: AbelianGroup([1]).gens_orders()
-+        (1,)
-+        sage: AbelianGroup([1,1]).gens_orders()
-+        (1, 1)
-+        sage: AbelianGroup(0).gens_orders()
-+        ()
-     """
--    def __init__(self, n, invfac, names="f"):
--        #invfac.sort()
--        n = Integer(n)
--        # if necessary, remove 1 from invfac first
--        if n != 1:
--            while True:
--                try:
--                    i = invfac.index(1)
--                except ValueError:
--                    break
--                else:
--                    del invfac[i]
--                    n = n-1
-+    Element = AbelianGroupElement
- 
--        if n < 0:
--            raise ValueError, "n (=%s) must be nonnegative."%n
-+    def __init__(self, generator_orders, names):
-+        """
-+        The Python constructor
- 
--        self.__invariants = invfac
-+        TESTS::
- 
--        # *now* define ngens
--        self.__ngens = len(self.__invariants)
--        self._assign_names(names[:n])
--        from sage.categories.groups import Groups
--        group.Group.__init__(self, category = Groups()) # should be CommutativeGroups()
-+            sage: G = AbelianGroup([0,5,0,7],names = list("abcd")); G
-+            Multiplicative Abelian group isomorphic to Z x C5 x Z x C7
-+            sage: TestSuite(G).run()
-+        """
-+        assert isinstance(names, (basestring, tuple))
-+        assert isinstance(generator_orders, tuple)
-+        assert all(isinstance(order,Integer) for order in generator_orders)
-+        self._gens_orders = generator_orders
-+        n = ZZ(len(generator_orders))
-+        names = self.normalize_names(n, names)
-+        self._assign_names(names)
-+        AbelianGroupBase.__init__(self) # TODO: category=CommutativeGroups()
- 
--    def __call__(self, x):
-+    def is_isomorphic(left, right):
-         """
--        Create an element of this abelian group from `x`.
-+        Check whether ``left`` and ``right`` are isomorphic
-         
-+        INPUT:
-+
-+        - ``right`` -- anything.
-+
-+        OUTPUT:
-+
-+        Boolean. Whether ``left`` and ``right`` are isomorphic as abelian groups.
-+
-         EXAMPLES::
--        
--            sage: F = AbelianGroup(10, [2]*10)
--            sage: F(F.2)
--            f2
--            sage: F(1)
--            1
--        """
--        if isinstance(x, AbelianGroupElement) and x.parent() is self: 
--            return x
--        return AbelianGroupElement(self, x)
--                                
--    def __contains__(self, x):
--        """
--        Return True if `x` is an element of this abelian group.
--        
--        EXAMPLES::
--        
--            sage: F = AbelianGroup(10,[2]*10)
--            sage: F.2 * F.3 in F
--            True
--        """
--        return isinstance(x, AbelianGroupElement) and x.parent() == self
- 
--    def __eq__(self, right):
--        """
--        Compare self and right.
--        
--        The ordering is the ordering induced by that on the invariant
--        factors lists.
--        
--        EXAMPLES::
--        
-             sage: G1 = AbelianGroup([2,3,4,5])
-             sage: G2 = AbelianGroup([2,3,4,5,1])
--            sage: G1 < G2
--            False
--            sage: G1 > G2
--            False
--            sage: G1 == G2
-+            sage: G1.is_isomorphic(G2)
-+            True
-+            sage: G1 == G2    # syntactic sugar
-             True
-         """
-         if not is_AbelianGroup(right):
-             return False
--        if set(self.variable_names()) != set(right.variable_names()):
--            return False
--        svars = list(self.variable_names())
--        sinvs = self.invariants()
--        rvars = list(right.variable_names())
--        rinvs = right.invariants()
--        for i in xrange(len(svars)):
--            if rinvs[rvars.index(svars[i])] != sinvs[i]:
-+        return left.elementary_divisors() == right.elementary_divisors()
-+
-+    __eq__ = is_isomorphic
-+
-+    def __ne__(left, right):
-+        """
-+        Check whether ``left`` and ``right`` are not isomorphic
-+
-+        OUTPUT:
-+
-+        Boolean.
-+
-+        EXAMPLES::
-+
-+            sage: G1 = AbelianGroup([2,3,4,5])
-+            sage: G2 = AbelianGroup([2,3,4,5,1])
-+            sage: G1 != G2
-+            False
-+            sage: G1.__ne__(G2)
-+            False
-+        """
-+        return not left.is_isomorphic(right)
-+
-+    def is_subgroup(left, right):
-+        """
-+        Test whether ``left`` is a subgroup of ``right``.
-+
-+        EXAMPLES::
-+
-+            sage: G = AbelianGroup([2,3,4,5])
-+            sage: G.is_subgroup(G)
-+            True
-+
-+            sage: H = G.subgroup([G.1])
-+            sage: H.is_subgroup(G)
-+            True
-+
-+            sage: G.<a, b> = AbelianGroup(2)
-+            sage: H.<c> = AbelianGroup(1)
-+            sage: H < G
-+            False
-+       """
-+        for l in left.gens():
-+            if l not in right:
-                 return False
-         return True
-+
-+    __le__ = is_subgroup
-+
-+    def __ge__(left, right):
-+        """
-+        Test whether ``right`` is a subgroup of ``left``
-+
-+        EXAMPLE::
-+
-+            sage: G.<a, b> = AbelianGroup(2)
-+            sage: H.<c> = AbelianGroup(1)
-+            sage: G >= H
-+            False
-+        """
-+        return right.__le__(left)
-     
--    def __ne__(self, right):
--        return not self == right
--    
--    def __ge__(self, right):
--        for a in right.gens():
--            if a not in self:
--                return False
--        return True
--    
--    def __lt__(self, right):
-+    def __lt__(left, right):
-         """
-+        Test whether ``left`` is a strict subgroup of ``right``
-+
-         EXAMPLE::
-         
-             sage: G.<a, b> = AbelianGroup(2)
-@@ -514,16 +631,35 @@
-             sage: H < G
-             False
-         """
--        return self <= right and self != right
-+        return left <= right and left != right
-     
--    def __gt__(self, right):
--        return self >= right and self != right
-+    def __gt__(left, right):
-+        """
-+        Test whether ``right`` is a strict subgroup of ``left``
-+
-+        EXAMPLE::
-+
-+            sage: G.<a, b> = AbelianGroup(2)
-+            sage: H.<c> = AbelianGroup(1)
-+            sage: G > H
-+            False
-+        """
-+        return left >= right and left != right
-     
--    def __le__(self, right):
--        for a in self.gens():
--            if a not in right:
--                return False
--        return True
-+    def is_trivial(self):
-+        """
-+        Return whether the group is trivial
-+
-+        A group is trivial if it has precisely one element.
-+
-+        EXAMPLES::
-+
-+            sage: AbelianGroup([2, 3]).is_trivial()
-+            False
-+            sage: AbelianGroup([1, 1]).is_trivial()
-+            True
-+        """
-+        return self.elementary_divisors() == ()
- 
-     def __nonzero__(self):
-         """
-@@ -536,18 +672,62 @@
-             True
-             sage: bool(AbelianGroup([]))
-             False
-+            sage: bool(AbelianGroup([1,1,1]))
-+            False
-         """
--        return len(self.invariants()) != 0
-+        return not self.is_trivial()
- 
--    def dual_group(self):
-+    @cached_method
-+    def dual_group(self, names="X", base_ring=None):
-         """
-         Returns the dual group.
-+
-+        INPUT:
-+
-+        - ``names`` -- string or list of strings. The generator names
-+          for the dual group.
-+
-+        - ``base_ring`` -- the base ring. If ``None`` (default), then
-+          a suitable cyclotomic field is picked automatically.
-         
--        EXAMPLES:
-+        OUTPUT:
-+
-+        The
-+        :class:`~sage.groups.abelian_gps.dual_abelian_group.DualAbelianGroup_class
-+        <dual abelian group>`
-+
-+        EXAMPLES::
-+
-+            sage: G = AbelianGroup([2])
-+            sage: G.dual_group()
-+            Dual of Abelian Group isomorphic to Z/2Z over Cyclotomic Field of order 2 and degree 1
-+            sage: G.dual_group().gens()
-+            (X,)
-+            sage: G.dual_group(names='Z').gens()
-+            (Z,)
-+
-+            sage: G.dual_group(base_ring=QQ)
-+            Dual of Abelian Group isomorphic to Z/2Z over Rational Field
-+
-+
-+        TESTS::
-+
-+            sage: H = AbelianGroup(1)
-+            sage: H.dual_group()
-+            Traceback (most recent call last):
-+            ...
-+            ValueError: the group must be finite
-         """
--        from sage.groups.abelian_gps.dual_abelian_group import DualAbelianGroup
--        return DualAbelianGroup(self)
-+        from sage.groups.abelian_gps.dual_abelian_group import DualAbelianGroup_class
-+        if not self.is_finite():
-+            raise ValueError('the group must be finite')
-+        if base_ring is None:
-+            from sage.rings.number_field.number_field import CyclotomicField
-+            from sage.rings.arith import LCM
-+            base_ring = CyclotomicField(LCM(self.gens_orders()))
-+        return DualAbelianGroup_class(self, names=names, base_ring=base_ring)
-                   
-+    @cached_method
-     def elementary_divisors(self):
-         r"""
-         This returns the elementary divisors of the group, using Pari.
-@@ -566,34 +746,39 @@
-             on these ""smaller invariants"" to compute `d_{i-1}`, and so on.
-             (Thanks to Robert Miller for communicating this algorithm.)
- 
-+        OUTPUT:
-+
-+        A tuple of integers.
-+
-         EXAMPLES::
-         
-             sage: G = AbelianGroup(2,[2,3])
-             sage: G.elementary_divisors()
--            [6]
-+            (6,)
-             sage: G = AbelianGroup(1, [6])
-             sage: G.elementary_divisors()
--            [6]
-+            (6,)
-             sage: G = AbelianGroup(2,[2,6])
-             sage: G
--            Multiplicative Abelian Group isomorphic to C2 x C6
--            sage: G.invariants()
--            [2, 6]
-+            Multiplicative Abelian group isomorphic to C2 x C6
-+            sage: G.gens_orders()
-+            (2, 6)
-             sage: G.elementary_divisors()
--            [2, 6]
-+            (2, 6)
-             sage: J = AbelianGroup([1,3,5,12])
-             sage: J.elementary_divisors()
--            [3, 60]
-+            (3, 60)
-             sage: G = AbelianGroup(2,[0,6])
-             sage: G.elementary_divisors()
--            [6, 0]
-+            (6, 0)
-             sage: AbelianGroup([3,4,5]).elementary_divisors()
--            [60]
-+            (60,)
-         """
-         from sage.matrix.constructor import diagonal_matrix
--        ed = diagonal_matrix(ZZ, self.invariants()).elementary_divisors()
--        return [d for d in ed if d!=1]
-+        ed = diagonal_matrix(ZZ, self.gens_orders()).elementary_divisors()
-+        return tuple(d for d in ed if d!=1)
- 
-+    @cached_method
-     def exponent(self):
-         """
-         Return the exponent of this abelian group.
-@@ -601,20 +786,15 @@
-         EXAMPLES::
-         
-             sage: G = AbelianGroup([2,3,7]); G
--            Multiplicative Abelian Group isomorphic to C2 x C3 x C7
-+            Multiplicative Abelian group isomorphic to C2 x C3 x C7
-             sage: G.exponent()
-             42
-             sage: G = AbelianGroup([2,4,6]); G
--            Multiplicative Abelian Group isomorphic to C2 x C4 x C6
-+            Multiplicative Abelian group isomorphic to C2 x C4 x C6
-             sage: G.exponent()
-             12
-         """
--        try:
--            return self.__exponent
--        except AttributeError:
--            self.__exponent = e = lcm(self.invariants())
--            return e
--            
-+        return lcm(self.gens_orders())
-     
-     def identity(self):
-         r"""
-@@ -633,9 +813,25 @@
-             f0
-         """
-         return self(1)
--
-     
-     def _group_notation(self, eldv):
-+        """
-+        Return abstract group notation for generator orders ``eldv``
-+
-+        INPUT:
-+
-+        - ``eldv`` -- iterable of integers.
-+
-+        OUTPUT:
-+
-+        String.
-+
-+        EXAMPLES::
-+
-+            sage: G = AbelianGroup([2,2])
-+            sage: G._group_notation([0,1,2,3])
-+            'Z x C1 x C2 x C3'
-+        """
-         v = []
-         for x in eldv:
-             if x:
-@@ -652,9 +848,9 @@
-         
-             sage: F = AbelianGroup(10, [2]*10)
-             sage: F._latex_()
--            '$\\mathrm{AbelianGroup}( 10, [2, 2, 2, 2, 2, 2, 2, 2, 2, 2] )$'
-+            '$\\mathrm{AbelianGroup}( 10, (2, 2, 2, 2, 2, 2, 2, 2, 2, 2) )$'
-         """
--        s = "$\mathrm{AbelianGroup}( %s, %s )$"%(len(self.invariants()), self.invariants())
-+        s = "$\mathrm{AbelianGroup}( %s, %s )$"%(self.ngens(), self.gens_orders())
-         return s
- 
-     def _gap_init_(self):
-@@ -669,12 +865,10 @@
-             sage: gap(G)
-             Group( [ f1, f2, f3 ] )
-         
--        Only works for finite groups.
--        
--        ::
-+        Only works for finite groups::
-         
-             sage: G = AbelianGroup(3,[0,3,4],names="abc"); G
--            Multiplicative Abelian Group isomorphic to Z x C3 x C4
-+            Multiplicative Abelian group isomorphic to Z x C3 x C4
-             sage: G._gap_init_()
-             Traceback (most recent call last):
-             ...
-@@ -683,11 +877,10 @@
-         # TODO: Use the package polycyclic has AbelianPcpGroup, which can handle
-         # the infinite case but it is a GAP package not GPL'd.
-         # Use this when the group is infinite...
--        if (False and prod(self.invariants())==0):   # if False for now...
--            return 'AbelianPcpGroup(%s)'%self.invariants()
-+        # return 'AbelianPcpGroup(%s)'%list(self.invariants())
-         if not self.is_finite():
--            raise TypeError, "abelian groups in GAP are finite, but self is infinite"
--        return 'AbelianGroup(%s)'%self.invariants()
-+            raise TypeError('abelian groups in GAP are finite, but self is infinite')
-+        return 'AbelianGroup(%s)'%list(self.gens_orders())
- 
-     def gen(self, i=0):
-         """
-@@ -700,36 +893,129 @@
-             a0
-             sage: F.2
-             a2
--            sage: F.invariants()
--            [0, 0, 0, 0, 0]
-+            sage: F.gens_orders()
-+            (0, 0, 0, 0, 0)
-+
-+            sage: G = AbelianGroup([2,1,3])
-+            sage: G.gens()
-+            (f0, 1, f2)
-         """
--        n = self.__ngens
-+        n = self.ngens()
-         if i < 0 or i >= n: 
-             raise IndexError, "Argument i (= %s) must be between 0 and %s."%(i, n-1)
--        x = [0]*int(n)
--        x[int(i)] = 1 
--        return AbelianGroupElement(self, x)
-+        x = [0]*n
-+        if self._gens_orders[i] != 1:
-+            x[i] = 1
-+        return self.element_class(x, self)
-+
-+    def gens(self):
-+        """
-+        Return the generators of the group.
-+
-+        OUTPUT:
-+
-+        A tuple of group elements. The generators according to the
-+        chosen :meth:`gens_orders`.
-+
-+        EXAMPLES::
-+
-+            sage: F = AbelianGroup(5,[3,2],names='abcde')
-+            sage: F.gens()
-+            (a, b, c, d, e)
-+            sage: [ g.order() for g in F.gens() ]
-+            [+Infinity, +Infinity, +Infinity, 3, 2]
-+        """
-+        return tuple( self.gen(i) for i in range(self.ngens()) )
-+
-+    def gens_orders(self):
-+        """
-+        Return the orders of the cyclic factors that this group has
-+        been defined with.
-+
-+        Use :meth:`elementary_divisors` if you are looking for an
-+        invariant of the group.
-+
-+        OUTPUT:
-+
-+        A tuple of integers.
-+
-+        EXAMPLES::
-+
-+            sage: Z2xZ3 = AbelianGroup([2,3])
-+            sage: Z2xZ3.gens_orders()
-+            (2, 3)
-+            sage: Z2xZ3.elementary_divisors()
-+            (6,)
-+
-+            sage: Z6 = AbelianGroup([6])
-+            sage: Z6.gens_orders()
-+            (6,)
-+            sage: Z6.elementary_divisors()
-+            (6,)
-+
-+            sage: Z2xZ3.is_isomorphic(Z6)
-+            True
-+            sage: Z2xZ3 is Z6
-+            False
-+
-+        TESTS::
-+
-+            sage: F = AbelianGroup(3, [2], names='abc')
-+            sage: map(type, F.gens_orders())
-+            [<type 'sage.rings.integer.Integer'>,
-+             <type 'sage.rings.integer.Integer'>,
-+             <type 'sage.rings.integer.Integer'>]
-+        """
-+        return self._gens_orders
- 
-     def invariants(self):
-         """
--        Return a copy of the list of invariants of this group.
--        
--        It is safe to modify the returned list.
-+        Return the orders of the cyclic factors that this group has
-+        been defined with.
-+
-+        For historical reasons this has been called invariants in
-+        Sage, even though they are not necessarily the invariant
-+        factors of the group. Use :meth:`gens_orders` instead::
-+
-+            sage: J = AbelianGroup([2,0,3,2,4]);  J
-+            Multiplicative Abelian group isomorphic to C2 x Z x C3 x C2 x C4
-+            sage: J.invariants()    # deprecated
-+            (2, 0, 3, 2, 4)
-+            sage: J.gens_orders()   # use this instead
-+            (2, 0, 3, 2, 4)
-+            sage: for i in range(J.ngens()):
-+            ...       print i, J.gen(i), J.gen(i).order()     # or use this
-+            0 f0 2
-+            1 f1 +Infinity
-+            2 f2 3
-+            3 f3 2
-+            4 f4 4
-+
-+        Use :meth:`elementary_divisors` if you are looking for an
-+        invariant of the group.
-+
-+        OUTPUT:
-+
-+        A tuple of integers. Zero means infinite cyclic factor.
-         
-         EXAMPLES::
-         
-             sage: J = AbelianGroup([2,3])
-             sage: J.invariants()
--            [2, 3]
--            sage: v = J.invariants(); v
--            [2, 3]
--            sage: v[0] = 5
--            sage: J.invariants()
--            [2, 3]
--            sage: J.invariants() is J.invariants()
--            False
-+            (2, 3)
-+            sage: J.elementary_divisors()
-+            (6,)
-+
-+        TESTS::
-+
-+            sage: F = AbelianGroup(3, [2], names='abc')
-+            sage: map(type, F.gens_orders())
-+            [<type 'sage.rings.integer.Integer'>,
-+             <type 'sage.rings.integer.Integer'>,
-+             <type 'sage.rings.integer.Integer'>]
-         """
--        return list(self.__invariants)
-+        # TODO: deprecate
-+        return self.gens_orders()
- 
-     def is_cyclic(self):
-         """
-@@ -738,25 +1024,25 @@
-         EXAMPLES::
-         
-             sage: J = AbelianGroup([2,3])
--            sage: J.invariants()
--            [2, 3]
-+            sage: J.gens_orders()
-+            (2, 3)
-             sage: J.elementary_divisors()
--            [6]
-+            (6,)
-             sage: J.is_cyclic()
-             True
-             sage: G = AbelianGroup([6])
--            sage: G.invariants()
--            [6]
-+            sage: G.gens_orders()
-+            (6,)
-             sage: G.is_cyclic()
-             True
-             sage: H = AbelianGroup([2,2])
--            sage: H.invariants()
--            [2, 2]
-+            sage: H.gens_orders()
-+            (2, 2)
-             sage: H.is_cyclic()
-             False
-             sage: H = AbelianGroup([2,4])
-             sage: H.elementary_divisors()
--            [2, 4]
-+            (2, 4)
-             sage: H.is_cyclic()
-             False
-             sage: H.permutation_group().is_cyclic()
-@@ -765,7 +1051,7 @@
-             sage: T.is_cyclic()
-             True            
-             sage: T = AbelianGroup(1,[0]); T
--            Multiplicative Abelian Group isomorphic to Z
-+            Multiplicative Abelian group isomorphic to Z
-             sage: T.is_cyclic()
-             True
-             sage: B = AbelianGroup([3,4,5])
-@@ -774,6 +1060,7 @@
-         """
-         return len(self.elementary_divisors()) <= 1
- 
-+    @cached_method
-     def ngens(self):
-         """
-         The number of free generators of the abelian group.
-@@ -784,8 +1071,9 @@
-             sage: F.ngens()
-             10000
-         """
--        return self.__ngens
-+        return len(self.gens_orders())
- 
-+    @cached_method
-     def order(self):
-         """
-         Return the order of this group.
-@@ -799,18 +1087,12 @@
-             sage: G.order()
-             +Infinity
-         """
--        try:
--            return self.__len
--        except AttributeError:
--            from sage.rings.all import infinity, Integer
--            if len(self.invariants()) < self.ngens():
--                self.__len = infinity
--            else:
--                self.__len = Integer(prod(self.invariants()))
--                if self.__len == 0:
--                    self.__len = infinity
--        return self.__len
--    
-+        from sage.rings.all import infinity
-+        length = prod(self.gens_orders())
-+        if length == 0:
-+            return infinity
-+        return length
-+
-     def permutation_group(self):
-         r"""
-         Return the permutation group isomorphic to this abelian group.
-@@ -822,7 +1104,7 @@
-         EXAMPLES::
-         
-             sage: G = AbelianGroup(2,[2,3]); G
--            Multiplicative Abelian Group isomorphic to C2 x C3
-+            Multiplicative Abelian group isomorphic to C2 x C3
-             sage: G.permutation_group()
-             Permutation Group with generators [(3,4,5), (1,2)]
-         """
-@@ -830,7 +1112,6 @@
-         s = 'Image(IsomorphismPermGroup(%s))'%self._gap_init_()
-         return PermutationGroup(gap_group=s)
- 
--
-     def is_commutative(self):
-         """
-         Return True since this group is commutative.
-@@ -847,32 +1128,38 @@
- 
-     def random_element(self):
-         """
--        Return a random element of this group. (Renamed random to
--        random_element.)
-+        Return a random element of this group.
-         
-         EXAMPLES::
-         
-             sage: G = AbelianGroup([2,3,9])
-             sage: G.random_element()
--            f0*f1^2*f2
-+            f1^2
-         """
-         from sage.misc.prandom import randint
--        if self.order() is infinity:
--            NotImplementedError, "The group must be finite"
--        gens = self.gens()
--        g = gens[0]**0
--        for i in range(len(gens)):
--            g = g*gens[i]**(randint(1,gens[i].order()))
--        return g
--
-+        result = self.one()
-+        for g in self.gens():
-+            order = g.order()
-+            if order not in ZZ:
-+                order = 42  # infinite order; randomly chosen maximum
-+            result *= g**(randint(0,order))
-+        return result
- 
-     def _repr_(self):
--        eldv = self.invariants()
-+        """
-+        Return a string representation of ``self``.
-+
-+        EXAMPLES::
-+
-+            sage: G = AbelianGroup([2,3,9])
-+            sage: G._repr_()
-+            'Multiplicative Abelian group isomorphic to C2 x C3 x C9'
-+       """
-+        eldv = self.gens_orders()
-         if len(eldv) == 0:
--            return "Trivial Abelian Group"
-+            return "Trivial Abelian group"
-         g = self._group_notation(eldv)
--        return "Multiplicative Abelian Group isomorphic to " + g
--
-+        return "Multiplicative Abelian group isomorphic to " + g
- 
-     def subgroup(self, gensH, names="f"):
-         """
-@@ -881,74 +1168,59 @@
-          
-          INPUT:
-          
--         
--         -  ``gensH`` - list of elements which are products of
--            the generators of the ambient abelian group G = self
--         
-+         - ``gensH`` -- list of elements which are products of the
-+            generators of the ambient abelian group G = self
-          
-          EXAMPLES::
-          
-              sage: G.<a,b,c> = AbelianGroup(3, [2,3,4]); G
--             Multiplicative Abelian Group isomorphic to C2 x C3 x C4
-+             Multiplicative Abelian group isomorphic to C2 x C3 x C4
-              sage: H = G.subgroup([a*b,a]); H
--             Multiplicative Abelian Group isomorphic to C2 x C3, which is the subgroup of
--             Multiplicative Abelian Group isomorphic to C2 x C3 x C4
--             generated by [a*b, a]
-+             Multiplicative Abelian subgroup isomorphic to C2 x C3 generated by {a*b, a}
-              sage: H < G
-              True
-              sage: F = G.subgroup([a,b^2])
-              sage: F
--             Multiplicative Abelian Group isomorphic to C2 x C3, which is the subgroup of
--             Multiplicative Abelian Group isomorphic to C2 x C3 x C4
--             generated by [a, b^2]
-+             Multiplicative Abelian subgroup isomorphic to C2 x C3 generated by {a, b^2}
-              sage: F.gens()
--             [a, b^2]
-+             (a, b^2)
-              sage: F = AbelianGroup(5,[30,64,729],names = list("abcde"))
-              sage: a,b,c,d,e = F.gens()
-              sage: F.subgroup([a,b])
--             Multiplicative Abelian Group isomorphic to Z x Z, which is
--             the subgroup of Multiplicative Abelian Group isomorphic to
--             Z x Z x C30 x C64 x C729 generated by [a, b]
-+             Multiplicative Abelian subgroup isomorphic to Z x Z generated by {a, b}
-              sage: F.subgroup([c,e])
--             Multiplicative Abelian Group isomorphic to C2 x C3 x C5 x
--             C729, which is the subgroup of Multiplicative Abelian
--             Group isomorphic to Z x Z x C30 x C64 x C729 generated by
--             [c, e]
-+             Multiplicative Abelian subgroup isomorphic to C2 x C3 x C5 x C729 generated by {c, e}
-          """
--        if not isinstance(gensH, (list, tuple)):
--            raise TypeError, "gensH = (%s) must be a list or tuple"%(gensH)
--         
-         G = self
--        for i in range(len(gensH)):
--            if not(gensH[i] in G):
--                raise TypeError, "Subgroup generators must belong to the given group."
-+        gensH = tuple(gensH)
-+        if isinstance(names, list):
-+            names = tuple(names)
-+        for h in gensH:
-+            if h not in G:
-+                raise TypeError('Subgroup generators must belong to the given group.')
-         return AbelianGroup_subgroup(self, gensH, names)
- 
-+    @cached_method
-     def list(self):
-         """
--        Return list of all elements of this group.
-+        Return tuple of all elements of this group.
-         
-         EXAMPLES::
-         
-             sage: G = AbelianGroup([2,3], names = "ab")
-             sage: G.list()
--            [1, b, b^2, a, a*b, a*b^2]
-+            (1, b, b^2, a, a*b, a*b^2)
-         
-         ::
-         
-             sage: G = AbelianGroup([]); G
--            Trivial Abelian Group
-+            Trivial Abelian group
-             sage: G.list()
--            [1]
-+            (1,)
-         """
--        try:
--            return list(self.__list)
--        except AttributeError:
--            pass
-         if not(self.is_finite()):
-            raise NotImplementedError, "Group must be finite"
--        self.__list = list(self.__iter__())
--        return list(self.__list)
-+        return tuple(self.__iter__())
-      
-     def __iter__(self):
-         """
-@@ -973,14 +1245,13 @@
-             [1]
-             sage: G = AbelianGroup([])
-             sage: G.list()
--            [1]
-+            (1,)
-             sage: list(G)
-             [1]
-         """
--        invs = self.invariants()
-+        invs = self.gens_orders()
-         for t in mrange(invs):
--            yield AbelianGroupElement(self, t)
--
-+            yield self(t)
- 
-     def subgroups(self, check=False):
-         r"""
-@@ -1010,35 +1281,28 @@
-         EXAMPLES::
- 
-             sage: AbelianGroup([2,3]).subgroups()
--            [Multiplicative Abelian Group isomorphic to C2 x C3, which is the subgroup of
--            Multiplicative Abelian Group isomorphic to C2 x C3
--            generated by [f0*f1^2],
--             Multiplicative Abelian Group isomorphic to C2, which is the subgroup of
--            Multiplicative Abelian Group isomorphic to C2 x C3
--            generated by [f0],
--             Multiplicative Abelian Group isomorphic to C3, which is the subgroup of
--            Multiplicative Abelian Group isomorphic to C2 x C3
--            generated by [f1],
--             Trivial Abelian Group, which is the subgroup of
--            Multiplicative Abelian Group isomorphic to C2 x C3
--            generated by []]
--
-+            [Multiplicative Abelian subgroup isomorphic to C2 x C3 generated by {f0*f1^2},
-+             Multiplicative Abelian subgroup isomorphic to C2 generated by {f0},
-+             Multiplicative Abelian subgroup isomorphic to C3 generated by {f1},
-+             Trivial Abelian subgroup]
-             sage: len(AbelianGroup([2,4,8]).subgroups())
-             81
- 
-+        TESTS::
-+
-+            sage: AbelianGroup([]).subgroups()
-+            [Trivial Abelian group]
-         """
-         if not self.is_finite(): raise ValueError, "Group must be finite"
-         from sage.misc.misc import verbose
- 
--        v = self.invariants()
--        
--        
--        if len(v) <= 1:
--            if v == [] or v[0] == 1:
--                return [self]
--            else:
--                return [ self.subgroup([self.gen(0)**i]) for i in divisors(v[0])[:-1]] + [self.subgroup([])]
-+        if self.is_trivial():
-+            return [self]
-+        if self.ngens() == 1:
-+            n = self.gen(0).order()
-+            return [ self.subgroup([self.gen(0)**i]) for i in divisors(n) ]
- 
-+        v = self.gens_orders()
-         A = AbelianGroup(v[:-1])
-         x = v[-1]
- 
-@@ -1046,8 +1310,8 @@
- 
-         subgps = []
-         for G in Wsubs:
--            verbose("G = subgp generated by %s" % G.gens())
--            verbose("invariants are:", [t.order() for t in G.gens()]) # G.invariants() doesn't work
-+            verbose("G = subgp generated by %s" % list(G.gens()))
-+            verbose("invariants are:", [t.order() for t in G.gens()])
-             for H in divisors(x):
-                 # H = the subgroup of *index* H.
-                 its = [xrange(0, H, H/gcd(H, G.gen(i).order())) for i in xrange(len(G.gens()))] 
-@@ -1085,13 +1349,11 @@
- 
-             sage: G = AbelianGroup([4,4])
-             sage: G.subgroup( [ G([1,0]), G([1,2]) ])
--            Multiplicative Abelian Group isomorphic to C2 x C4, which is the subgroup of
--            Multiplicative Abelian Group isomorphic to C4 x C4
--            generated by [f0, f0*f1^2]
-+            Multiplicative Abelian subgroup isomorphic to C2 x C4
-+            generated by {f0, f0*f1^2}
-             sage: AbelianGroup([4,4]).subgroup_reduced( [ [1,0], [1,2] ])
--            Multiplicative Abelian Group isomorphic to C2 x C4, which is the subgroup of
--            Multiplicative Abelian Group isomorphic to C4 x C4
--            generated by [f1^2, f0]
-+            Multiplicative Abelian subgroup isomorphic to C2 x C4
-+            generated by {f1^2, f0}
-         """
-         from sage.matrix.constructor import matrix
-         d = self.ngens()
-@@ -1102,12 +1364,13 @@
-             # can't happen?
-             print "Vectors not LI: ", elts
-             raise e
--        rel_lattice = X.span([X.gen(i) * self.invariants()[i] for i in xrange(d)])
-+        rel_lattice = X.span([X.gen(i) * self.gens_orders()[i] for i in xrange(d)])
-         isect = elt_lattice.intersection(rel_lattice)
-         mat = matrix([elt_lattice.coordinate_vector(x) for x in isect.gens()]).change_ring(ZZ)
-         D,U,V = mat.smith_form()
-         new_basis = [(elt_lattice.linear_combination_of_basis((~V).row(i)).list(), D[i,i]) for i in xrange(U.ncols())]
--        return self.subgroup([self([x[0][i] % self.invariants()[i] for i in xrange(d)]) for x in new_basis if x[1] != 1])
-+        return self.subgroup([self([x[0][i] % self.gens_orders()[i]
-+                                    for i in xrange(d)]) for x in new_basis if x[1] != 1])
- 
- class AbelianGroup_subgroup(AbelianGroup_class):
-     """
-@@ -1126,61 +1389,21 @@
-             sage: F = AbelianGroup(5,[30,64,729],names = list("abcde"))
-             sage: a,b,c,d,e = F.gens()
-             sage: F.subgroup([a^3,b])
--            Multiplicative Abelian Group isomorphic to Z x Z, which is the subgroup of
--            Multiplicative Abelian Group isomorphic to Z x Z x C30 x C64 x C729
--            generated by [a^3, b]            
--        
--        ::
--        
-+            Multiplicative Abelian subgroup isomorphic to Z x Z generated by {a^3, b}
-             sage: F.subgroup([c])
--            Multiplicative Abelian Group isomorphic to C2 x C3 x C5, which is the subgroup of
--            Multiplicative Abelian Group isomorphic to Z x Z x C30 x C64 x C729
--            generated by [c]
--        
--        ::
--        
--            sage: F.subgroup([a,c])
--            Multiplicative Abelian Group isomorphic to C2 x C3 x C5 x
--            Z, which is the subgroup of Multiplicative Abelian Group
--            isomorphic to Z x Z x C30 x C64 x C729 generated by [a, c]
--        
--        ::
--        
--            sage: F.subgroup([a,b*c])
--            Multiplicative Abelian Group isomorphic to Z x Z, which is
--            the subgroup of Multiplicative Abelian Group isomorphic to
--            Z x Z x C30 x C64 x C729 generated by [a, b*c]
--        
--        ::
--        
--            sage: F.subgroup([b*c,d])
--            Multiplicative Abelian Group isomorphic to C64 x Z, which
--            is the subgroup of Multiplicative Abelian Group isomorphic
--            to Z x Z x C30 x C64 x C729 generated by [b*c, d]
--        
--        ::
--        
--            sage: F.subgroup([a*b,c^6,d],names = list("xyz"))
--            Multiplicative Abelian Group isomorphic to C5 x C64 x Z,
--            which is the subgroup of Multiplicative Abelian Group
--            isomorphic to Z x Z x C30 x C64 x C729 generated by [a*b,
--            c^6, d]
--        
--        ::
--        
-+            Multiplicative Abelian subgroup isomorphic to C2 x C3 x C5 generated by {c}
-+            sage: F.subgroup([a, c])
-+            Multiplicative Abelian subgroup isomorphic to C2 x C3 x C5 x Z generated by {a, c}
-+            sage: F.subgroup([a, b*c])
-+            Multiplicative Abelian subgroup isomorphic to Z x Z generated by {a, b*c}
-+            sage: F.subgroup([b*c, d])
-+            Multiplicative Abelian subgroup isomorphic to C64 x Z generated by {b*c, d}
-+            sage: F.subgroup([a*b, c^6, d],names=list("xyz"))
-+            Multiplicative Abelian subgroup isomorphic to C5 x C64 x Z generated by {a*b, c^6, d}
-             sage: H.<x,y,z> = F.subgroup([a*b, c^6, d]); H
--            Multiplicative Abelian Group isomorphic to C5 x C64 x Z,
--            which is the subgroup of Multiplicative Abelian Group
--            isomorphic to Z x Z x C30 x C64 x C729 generated by [a*b,
--            c^6, d]
--        
--        ::
--        
--            sage: G = F.subgroup([a*b,c^6,d],names = list("xyz")); G
--            Multiplicative Abelian Group isomorphic to C5 x C64 x Z,
--            which is the subgroup of Multiplicative Abelian Group
--            isomorphic to Z x Z x C30 x C64 x C729 generated by [a*b,
--            c^6, d]
-+            Multiplicative Abelian subgroup isomorphic to C5 x C64 x Z generated by {a*b, c^6, d}
-+            sage: G = F.subgroup([a*b, c^6, d],names = list("xyz")); G
-+            Multiplicative Abelian subgroup isomorphic to C5 x C64 x Z generated by {a*b, c^6, d}
-             sage: x,y,z = G.gens()
-             sage: x.order()
-             +Infinity
-@@ -1191,28 +1414,20 @@
-             sage: A = AbelianGroup(5,[3, 5, 5, 7, 8], names = "abcde")
-             sage: a,b,c,d,e = A.gens()
-             sage: A.subgroup([a,b])
--            Multiplicative Abelian Group isomorphic to C3 x C5, which is the subgroup of
--            Multiplicative Abelian Group isomorphic to C3 x C5 x C5 x C7 x C8
--            generated by [a, b]
-+            Multiplicative Abelian subgroup isomorphic to C3 x C5 generated by {a, b}
-             sage: A.subgroup([a,b,c,d^2,e])
--            Multiplicative Abelian Group isomorphic to C3 x C5 x C5 x C7 x C8, which is the subgroup of
--            Multiplicative Abelian Group isomorphic to C3 x C5 x C5 x C7 x C8
--            generated by [a, b, c, d^2, e]
--            sage: A.subgroup([a,b,c,d^2,e^2])
--            Multiplicative Abelian Group isomorphic to C3 x C4 x C5 x C5 x C7, which is the subgroup of
--            Multiplicative Abelian Group isomorphic to C3 x C5 x C5 x C7 x C8
--            generated by [a, b, c, d^2, e^2]
--            sage: B = A.subgroup([a^3,b,c,d,e^2]); B
--            Multiplicative Abelian Group isomorphic to C4 x C5 x C5 x C7, which is the subgroup of
--            Multiplicative Abelian Group isomorphic to C3 x C5 x C5 x C7 x C8
--            generated by [b, c, d, e^2]
--            sage: B.invariants()
--            [4, 5, 5, 7]
-+            Multiplicative Abelian subgroup isomorphic to C3 x C5 x C5 x C7 x C8 generated by {a, b, c, d^2, e}
-+            sage: A.subgroup([a, b, c, d^2, e^2])
-+            Multiplicative Abelian subgroup isomorphic to C3 x C4 x C5 x C5 x C7 generated by {a, b, c, d^2, e^2}
-+            sage: B = A.subgroup([a^3, b, c, d, e^2]); B
-+            Multiplicative Abelian subgroup isomorphic to C4 x C5 x C5 x C7 generated by {b, c, d, e^2}
-+            sage: B.gens_orders()
-+            (4, 5, 5, 7)
-             sage: A = AbelianGroup(4,[1009, 2003, 3001, 4001], names = "abcd")
-             sage: a,b,c,d = A.gens()
-             sage: B = A.subgroup([a^3,b,c,d])
--            sage: B.invariants()
--            [1009, 2003, 3001, 4001]
-+            sage: B.gens_orders()
-+            (1009, 2003, 3001, 4001)
-             sage: A.order()
-             24266473210027
-             sage: B.order()
-@@ -1220,41 +1435,35 @@
-             sage: A = AbelianGroup(4,[1008, 2003, 3001, 4001], names = "abcd")
-             sage: a,b,c,d = A.gens()
-             sage: B = A.subgroup([a^3,b,c,d]); B
--            Multiplicative Abelian Group isomorphic to C3 x C7 x C16 x
--            C2003 x C3001 x C4001, which is the subgroup of
--            Multiplicative Abelian Group isomorphic to C1008 x C2003 x
--            C3001 x C4001 generated by [a^3, b, c, d]
-+            Multiplicative Abelian subgroup isomorphic
-+            to C3 x C7 x C16 x C2003 x C3001 x C4001 generated by {a^3, b, c, d}
-         
-         Infinite groups can also be handled::
-         
-             sage: G = AbelianGroup([3,4,0], names = "abc")
-             sage: a,b,c = G.gens()
--            sage: F = G.subgroup([a,b^2,c]); F
--            Multiplicative Abelian Group isomorphic to C2 x C3 x Z,
--            which is the subgroup of Multiplicative Abelian Group
--            isomorphic to C3 x C4 x Z generated by [a, b^2, c]
-+            sage: F = G.subgroup([a, b^2, c]); F
-+            Multiplicative Abelian subgroup isomorphic to C2 x C3 x Z generated by {a, b^2, c}
-         
--        ::
--        
--            sage: F.invariants()
--            [2, 3, 0]
-+            sage: F.gens_orders()
-+            (2, 3, 0)
-             sage: F.gens()
--            [a, b^2, c]
-+            (a, b^2, c)
-             sage: F.order()
-             +Infinity
-         """
-         from sage.interfaces.all import gap
-         if not isinstance(ambient, AbelianGroup_class):
-             raise TypeError, "ambient (=%s) must be an abelian group."%ambient
--        if not isinstance(gens, list):
--            raise TypeError, "gens (=%s) must be a list"%gens
-+        if not isinstance(gens, tuple):
-+            raise TypeError, "gens (=%s) must be a tuple"%gens
-             
--        self.__ambient_group = ambient
--        Hgens = [x for x in gens if x != ambient(1)]  ## in case someone puts 1 in the list of generators
--        self.__gens = Hgens
-+        self._ambient_group = ambient
-+        Hgens = tuple(x for x in gens if x != ambient.one())  ## in case someone puts 1 in the list of generators
-+        self._gens = Hgens
-         m = len(gens)
-         ell = len(ambient.gens())
--        ambient_invs = ambient.invariants()
-+        ambient_invs = ambient.gens_orders()
-         invsf = [x for x in ambient_invs if x > 0]    ## fixes the problem with 
-         invs0 = [x for x in ambient_invs if x == 0]   ## the infinite parts
-         Ggens = list(ambient.variable_names())
-@@ -1264,7 +1473,7 @@
-             Ggens0 = [x for x in ambient.variable_names() if
-                         ambient_invs[Ggens.index(x)] == 0]
-             ##     ^^ only look at "finite" names 
--            Gf = AbelianGroup_class(len(invsf), invsf, names = Gfgens)
-+            Gf = AbelianGroup(invsf, names=Gfgens)
-             s1 = "G:= %s; gens := GeneratorsOfGroup(G)"%Gf._gap_init_()
-             gap.eval(s1)
-             Hgensf = [x for x in Hgens if len(set(Ggens0).intersection(set(list(str(x)))))==0]
-@@ -1274,35 +1483,35 @@
-             for i in range(len(Gfgens)):
-                cmd = ("%s := gens["+str(i+1)+"]")%Gfgens[i]
-                gap.eval(cmd)
--        if invs0==[]:
--           Hgensf = Hgens
--           Hgens0 = []  # added for consistency
--           G = ambient
--           s1 = "G:= %s; gens := GeneratorsOfGroup(G)"%G._gap_init_()
--           gap.eval(s1)
--           for i in range(len(Ggens)):
--               cmd = '%s := gens[%s]'%(Ggens[i], i+1)
--               #print i,"  \n",cmd
--               gap.eval(cmd)
--        s2 = "gensH:=%s"%Hgensf #### remove from this the ones <--> 0 invar
-+        else:  # invs0==[]:
-+            Hgensf = Hgens
-+            Hgens0 = []  # added for consistency
-+            G = ambient
-+            s1 = "G:= %s; gens := GeneratorsOfGroup(G)"%G._gap_init_()
-+            gap.eval(s1)
-+            for i in range(len(Ggens)):
-+                cmd = '%s := gens[%s]'%(Ggens[i], i+1)
-+                #print i,"  \n",cmd
-+                gap.eval(cmd)
-+        s2 = "gensH:=%s"%list(Hgensf) #### remove from this the ones <--> 0 invar
-         gap.eval(s2)
-         s3 = 'H:=Subgroup(G,gensH)'
-         gap.eval(s3)
-         # a GAP command which returns the "invariants" of the
-         # subgroup as an AbelianPcpGroup, RelativeOrdersOfPcp(Pcp(G)),
-         # works if G is the subgroup declared as a AbelianPcpGroup
--        self.__abinvs = eval(gap.eval("AbelianInvariants(H)"))
--        invs = self.__abinvs
-+        self._abinvs = eval(gap.eval("AbelianInvariants(H)"))
-+        invs = self._abinvs
-         #print s3, invs
-         if Hgens0 != []:
-             for x in Hgens0:
-                invs.append(0)
--        #print Hgensf, invs, invs0
--        AbelianGroup_class.__init__(self, len(invs), invs, names)
-+        invs = tuple(ZZ(i) for i in invs)
-+        AbelianGroup_class.__init__(self, invs, names)
- 
-     def __contains__(self, x):