# HG changeset patch
# User Simon King <simon.king@uni-jena.de>
# Date 1300026255 -3600
# Node ID dc42cb80eeef9cbd3a953b7ce17585fd8034cfcf
# Parent  10f49e34d981dccab46b3c81dc60a14f0ee2d747
Initial wrapper for Singular/Plural - Sage-Trac #4539.
* * *
MPolynomialRing_plural now accepts matrix parameters to specify commutativity
relations. Added ExteriorAlgebra.
* * *
[mq]: plural_3.patch

diff -r 10f49e34d981 -r dc42cb80eeef module_list.py
--- a/module_list.py	Mon Sep 19 16:34:42 2011 -0700
+++ b/module_list.py	Sun Mar 13 15:24:15 2011 +0100
@@ -1487,6 +1487,13 @@
               include_dirs = [SAGE_INC + 'singular'],
               depends = singular_depends),
 
+    Extension('sage.rings.polynomial.plural',
+              sources = ['sage/rings/polynomial/plural.pyx'],
+              libraries = ['m', 'readline', 'singular', 'givaro', 'gmpxx', 'gmp'],
+              language="c++",
+              include_dirs = [SAGE_ROOT +'/local/include/singular'],
+              depends = [SAGE_ROOT + "/local/include/libsingular.h"]),
+
     Extension('sage.rings.polynomial.multi_polynomial_libsingular',
               sources = ['sage/rings/polynomial/multi_polynomial_libsingular.pyx'],
               libraries = ['m', 'readline', 'singular', 'givaro', 'gmpxx', 'gmp'],
diff -r 10f49e34d981 -r dc42cb80eeef sage/algebras/free_algebra.py
--- a/sage/algebras/free_algebra.py	Mon Sep 19 16:34:42 2011 -0700
+++ b/sage/algebras/free_algebra.py	Sun Mar 13 15:24:15 2011 +0100
@@ -66,7 +66,6 @@
 
 import sage.structure.parent_gens
 
-        
 def FreeAlgebra(R, n, names):
     """
     Return the free algebra over the ring `R` on `n`
@@ -166,14 +165,19 @@
     Element = FreeAlgebraElement
     def __init__(self, R, n, names):
         """
+        The free algebra on `n` generators over a base ring.
         INPUT:
         
-        
         -  ``R`` - ring
         
         -  ``n`` - an integer
         
         -  ``names`` - generator names
+    
+        EXAMPLES::
+    
+        sage: F.<x,y,z> = FreeAlgebra(QQ, 3); F # indirect doctet
+        Free Algebra on 3 generators (x, y, z) over Rational Field
         """
         if not isinstance(R, Ring):
             raise TypeError, "Argument R must be a ring."
@@ -254,7 +258,7 @@
             sage: print F  # indirect doctest
             Free Algebra on 3 generators (x0, x1, x2) over Rational Field
             sage: F.rename('QQ<<x0,x1,x2>>')
-            sage: print F
+            sage: print F #indirect doctest
             QQ<<x0,x1,x2>>
             sage: FreeAlgebra(ZZ,1,['a'])
             Free Algebra on 1 generators (a,) over Integer Ring
@@ -315,7 +319,7 @@
         
         ::
         
-            sage: F._coerce_(x*y)
+            sage: F._coerce_(x*y) # indirect doctest
             x*y
         
         Elements of the integers coerce in, since there is a coerce map
@@ -389,6 +393,18 @@
         return self._coerce_try(x, [self.base_ring()])
 
     def _coerce_map_from_(self, R):
+        """
+        Elements of the free algebra canonically coerce in.
+
+        EXAMPLES::
+        
+        sage: F.<x,y,z> = FreeAlgebra(GF(7),3); F
+        Free Algebra on 3 generators (x, y, z) over Finite Field of size 7
+        
+        sage: F._coerce_(x*y) # indirect doctest
+        x*y
+        """
+            
         if self.__monoid.has_coerce_map_from(R):
             return True
 
@@ -427,6 +443,17 @@
         which form a free basis for the module of A, and a list of
         matrices, which give the action of the free generators of A on this
         monomial basis.
+        Quaternion algebra defined in terms of three generators::
+        
+        sage: n = 3
+        sage: A = FreeAlgebra(QQ,n,'i')
+        sage: F = A.monoid()
+        sage: i, j, k = F.gens()
+        sage: mons = [ F(1), i, j, k ]
+        sage: M = MatrixSpace(QQ,4)
+        sage: mats = [M([0,1,0,0, -1,0,0,0, 0,0,0,-1, 0,0,1,0]),  M([0,0,1,0, 0,0,0,1, -1,0,0,0, 0,-1,0,0]),  M([0,0,0,1, 0,0,-1,0, 0,1,0,0, -1,0,0,0]) ]
+        sage: H.<i,j,k> = A.quotient(mons, mats); H
+        Free algebra quotient on 3 generators ('i', 'j', 'k') and dimension 4 over Rational Field
         """
         import free_algebra_quotient
         return free_algebra_quotient.FreeAlgebraQuotient(self, mons, mats, names)
@@ -456,6 +483,74 @@
         """
         return self.__monoid
     
-                    
+    def g_algebra(self, relations, order='degrevlex', check = True):
+        """
+            
+            The G-Algebra derrived from this algebra by relations.
+            By default is assumed, that two variables commute.
+
+            
+            TODO:
+            * Coercion doesn't work yet, there is some cheating about assumptions
+            * The optional argument check controlls checking the degeneracy conditions 
+            Furthermore, the default values interfere with non degeneracy conditions...
+            
+            EXAMPLES:
+            sage: A.<x,y,z>=FreeAlgebra(QQ,3)
+            sage: G=A.g_algebra({y*x:-x*y})
+            sage: (x,y,z)=G.gens()
+            sage: x*y
+            x*y
+            sage: y*x
+            -x*y
+            sage: z*x
+            x*z
+            sage: (x,y,z)=A.gens()
+            sage: G=A.g_algebra({y*x:-x*y+1})
+            sage: (x,y,z)=G.gens()
+            sage: y*x
+            -x*y + 1
+            sage: (x,y,z)=A.gens()
+            sage: G=A.g_algebra({y*x:-x*y+z})
+            sage: (x,y,z)=G.gens()
+            sage: y*x
+            -x*y + z
+        """
+        from sage.matrix.constructor  import Matrix
+        from sage.rings.polynomial.plural import NCPolynomialRing_plural
+        
+        base_ring=self.base_ring()
+        n=self.ngens()
+        cmat=Matrix(base_ring,n)
+        dmat=Matrix(self,n)
+        for i in xrange(n):
+            for j in xrange(i+1,n):
+                cmat[i,j]=1
+        for (to_commute,commuted) in relations.iteritems():
+            #This is dirty, coercion is broken
+            assert isinstance(to_commute,FreeAlgebraElement), to_commute.__class__
+            assert isinstance(commuted,FreeAlgebraElement), commuted
+            ((v1,e1),(v2,e2))=list(list(to_commute)[0][1])
+            assert e1==1
+            assert e2==1
+            assert v1>v2
+            c_coef=None
+            d_poly=None
+            for (c,m) in commuted:
+                if list(m)==[(v2,1),(v1,1)]:
+                    c_coef=c
+                    #buggy coercion workaround
+                    d_poly=commuted-self(c)*self(m)
+                    break
+            assert not c_coef is None,list(m)
+            v2_ind = self.gens().index(v2)
+            v1_ind = self.gens().index(v1)
+            cmat[v2_ind,v1_ind]=c_coef
+            if d_poly:
+                dmat[v2_ind,v1_ind]=d_poly
+        
+        return NCPolynomialRing_plural(base_ring, n, ",".join([str(g) for g in self.gens()]), c=cmat, d=dmat, order=order, check=check)
+            
+            
 from sage.misc.cache import Cache
 cache = Cache(FreeAlgebra_generic)
diff -r 10f49e34d981 -r dc42cb80eeef sage/libs/singular/function.pxd
--- a/sage/libs/singular/function.pxd	Mon Sep 19 16:34:42 2011 -0700
+++ b/sage/libs/singular/function.pxd	Sun Mar 13 15:24:15 2011 +0100
@@ -19,20 +19,24 @@
 from sage.libs.singular.decl cimport ring as singular_ring
 from sage.rings.polynomial.multi_polynomial_libsingular cimport MPolynomialRing_libsingular, MPolynomial_libsingular
 
+cdef poly* access_singular_poly(p) except <poly*> -1
+cdef singular_ring* access_singular_ring(r) except <singular_ring*> -1
+
 cdef class RingWrap:
     cdef singular_ring *_ring
 
 cdef class Resolution:
     cdef syStrategy *_resolution
-    cdef MPolynomialRing_libsingular base_ring
+    cdef object base_ring
 
 cdef class Converter(SageObject):
     cdef leftv *args
-    cdef MPolynomialRing_libsingular _ring
+    cdef object _sage_ring
+    cdef singular_ring* _singular_ring
     cdef leftv* pop_front(self) except NULL
     cdef leftv * _append_leftv(self, leftv *v)
     cdef leftv * _append(self, void* data, int res_type)
-    cdef leftv * append_polynomial(self, MPolynomial_libsingular p) except NULL
+    cdef leftv * append_polynomial(self, p) except NULL
     cdef leftv * append_ideal(self,  i) except NULL
     cdef leftv * append_number(self, n) except NULL
     cdef leftv * append_int(self, n) except NULL
@@ -43,7 +47,7 @@
     cdef leftv * append_intvec(self, v) except NULL
     cdef leftv * append_list(self, l) except NULL
     cdef leftv * append_matrix(self, a) except NULL
-    cdef leftv * append_ring(self, MPolynomialRing_libsingular r) except NULL
+    cdef leftv * append_ring(self, r) except NULL
     cdef leftv * append_module(self, m) except NULL
     cdef to_sage_integer_matrix(self, intvec *mat)
     cdef object to_sage_module_element_sequence_destructive(self, ideal *i)
@@ -69,7 +73,7 @@
 
     cdef BaseCallHandler get_call_handler(self)
     cdef bint function_exists(self)
-    cdef MPolynomialRing_libsingular common_ring(self, tuple args, ring=?)
+    cdef common_ring(self, tuple args, ring=?)
 
 cdef class SingularLibraryFunction(SingularFunction):
     pass
@@ -78,4 +82,4 @@
     pass
 
 # the most direct function call interface
-cdef inline call_function(SingularFunction self, tuple args, MPolynomialRing_libsingular R, bint signal_handler=?, object attributes=?)
+cdef inline call_function(SingularFunction self, tuple args, object R, bint signal_handler=?, object attributes=?)
diff -r 10f49e34d981 -r dc42cb80eeef sage/libs/singular/function.pyx
--- a/sage/libs/singular/function.pyx	Mon Sep 19 16:34:42 2011 -0700
+++ b/sage/libs/singular/function.pyx	Sun Mar 13 15:24:15 2011 +0100
@@ -14,6 +14,8 @@
 - Michael Brickenstein (2009-10): extension to more Singular types
 - Martin Albrecht (2010-01): clean up, support for attributes
 - Simon King (2011-04): include the documentation provided by Singular as a code block.
+- Burcin Erocal (2010-7): plural support
+- Michael Brickenstein (2010-7): plural support
 
 EXAMPLES:
 
@@ -81,6 +83,9 @@
 from sage.rings.polynomial.multi_polynomial_libsingular cimport MPolynomial_libsingular, new_MP
 from sage.rings.polynomial.multi_polynomial_libsingular cimport MPolynomialRing_libsingular
 
+from sage.rings.polynomial.plural cimport NCPolynomialRing_plural, NCPolynomial_plural, new_NCP
+from sage.rings.polynomial.multi_polynomial_ideal import NCPolynomialIdeal
+
 from sage.rings.polynomial.multi_polynomial_ideal import MPolynomialIdeal
 
 from sage.rings.polynomial.multi_polynomial_ideal_libsingular cimport sage_ideal_to_singular_ideal, singular_ideal_to_sage_sequence
@@ -90,7 +95,7 @@
 from sage.libs.singular.decl cimport iiMake_proc, iiExprArith1, iiExprArith2, iiExprArith3, iiExprArithM, iiLibCmd
 from sage.libs.singular.decl cimport ggetid, IDEAL_CMD, CMD_M, POLY_CMD, PROC_CMD, RING_CMD, QRING_CMD, NUMBER_CMD, INT_CMD, INTVEC_CMD, RESOLUTION_CMD
 from sage.libs.singular.decl cimport MODUL_CMD, LIST_CMD, MATRIX_CMD, VECTOR_CMD, STRING_CMD, V_LOAD_LIB, V_REDEFINE, INTMAT_CMD, NONE, PACKAGE_CMD
-from sage.libs.singular.decl cimport IsCmd, rChangeCurrRing, currRing, p_Copy
+from sage.libs.singular.decl cimport IsCmd, rChangeCurrRing, currRing, p_Copy, rIsPluralRing, rPrint, rOrderingString
 from sage.libs.singular.decl cimport IDROOT, enterid, currRingHdl, memcpy, IDNEXT, IDTYP, IDPACKAGE
 from sage.libs.singular.decl cimport errorreported, verbose, Sy_bit, currentVoice, myynest
 from sage.libs.singular.decl cimport intvec_new_int3, intvec_new, matrix, mpNew
@@ -123,8 +128,7 @@
     
     for (i, p) in enumerate(v):
         component = <int>i+1
-        poly_component = p_Copy(
-            (<MPolynomial_libsingular>p)._poly, r)
+        poly_component = copy_sage_polynomial_into_singular_poly(p)
         p_iter = poly_component
         while p_iter!=NULL:
             p_SetComp(p_iter, component, r)
@@ -133,6 +137,7 @@
         res=p_Add_q(res, poly_component, r)
     return res
 
+
 cdef class RingWrap:
     """
     A simple wrapper around Singular's rings.
@@ -149,12 +154,145 @@
             sage: ring(l, ring=P)
             <RingWrap>
         """
+        if not self.is_commutative():
+            return "<noncommutative RingWrap>"
         return "<RingWrap>"
     
     def __dealloc__(self):
         if self._ring!=NULL:
             self._ring.ref -= 1
 
+    def ngens(self):
+        """
+        Get number of generators
+
+        EXAMPLE::
+
+            sage: from sage.libs.singular.function import singular_function
+            sage: P.<x,y,z> = PolynomialRing(QQ)
+            sage: ringlist = singular_function("ringlist")
+            sage: l = ringlist(P)
+            sage: ring = singular_function("ring")
+            sage: ring(l, ring=P).ngens()
+            3
+        """
+        return self._ring.N
+
+    def var_names(self):
+        """
+        Get name of variables
+
+        EXAMPLE::
+
+            sage: from sage.libs.singular.function import singular_function
+            sage: P.<x,y,z> = PolynomialRing(QQ)
+            sage: ringlist = singular_function("ringlist")
+            sage: l = ringlist(P)
+            sage: ring = singular_function("ring")
+            sage: ring(l, ring=P).var_names()
+            ['x', 'y', 'z']
+        """
+        return [self._ring.names[i] for i in range(self.ngens())]
+
+    def npars(self):
+        """
+        Get number of parameters
+
+        EXAMPLE::
+
+            sage: from sage.libs.singular.function import singular_function
+            sage: P.<x,y,z> = PolynomialRing(QQ)
+            sage: ringlist = singular_function("ringlist")
+            sage: l = ringlist(P)
+            sage: ring = singular_function("ring")
+            sage: ring(l, ring=P).npars()
+            0
+        """
+        return self._ring.P
+
+    def ordering_string(self):
+        """
+        Get Singular string defining monomial ordering
+
+        EXAMPLE::
+
+            sage: from sage.libs.singular.function import singular_function
+            sage: P.<x,y,z> = PolynomialRing(QQ)
+            sage: ringlist = singular_function("ringlist")
+            sage: l = ringlist(P)
+            sage: ring = singular_function("ring")
+            sage: ring(l, ring=P).ordering_string()
+            'dp(3),C'
+        """
+        return rOrderingString(self._ring)
+    
+    
+
+    def par_names(self):
+        """
+        Get parameter names
+
+        EXAMPLE::
+
+            sage: from sage.libs.singular.function import singular_function
+            sage: P.<x,y,z> = PolynomialRing(QQ)
+            sage: ringlist = singular_function("ringlist")
+            sage: l = ringlist(P)
+            sage: ring = singular_function("ring")
+            sage: ring(l, ring=P).par_names()
+            []
+        """
+        return [self._ring.parameter[i] for i in range(self.npars())]
+
+    def characteristic(self):
+        """
+        Get characteristic
+
+        EXAMPLE::
+
+            sage: from sage.libs.singular.function import singular_function
+            sage: P.<x,y,z> = PolynomialRing(QQ)
+            sage: ringlist = singular_function("ringlist")
+            sage: l = ringlist(P)
+            sage: ring = singular_function("ring")
+            sage: ring(l, ring=P).characteristic()
+            0
+        """
+        return self._ring.ch
+
+    def is_commutative(self):
+        """
+        Determine whether a given ring is  commutative
+
+        EXAMPLE::
+
+            sage: from sage.libs.singular.function import singular_function
+            sage: P.<x,y,z> = PolynomialRing(QQ)
+            sage: ringlist = singular_function("ringlist")
+            sage: l = ringlist(P)
+            sage: ring = singular_function("ring")
+            sage: ring(l, ring=P).is_commutative()
+            True
+        """
+        return not rIsPluralRing(self._ring)
+    
+    def _output(self): # , debug = False
+        """
+        Use Singular output
+
+        EXAMPLE::
+
+            sage: from sage.libs.singular.function import singular_function
+            sage: P.<x,y,z> = PolynomialRing(QQ)
+            sage: ringlist = singular_function("ringlist")
+            sage: l = ringlist(P)
+            sage: ring = singular_function("ring")
+            sage: ring(l, ring=P)._output()
+        """
+        rPrint(self._ring)
+#        if debug:
+#        rDebugPrint(self._ring)
+            
 cdef class Resolution:
     """
     A simple wrapper around Singular's resolutions.
@@ -171,8 +309,9 @@
            sage: M = syz(I)
            sage: resolution = mres(M, 0)
         """
-        assert PY_TYPE_CHECK(base_ring, MPolynomialRing_libsingular)
-        self.base_ring = <MPolynomialRing_libsingular> base_ring
+        #FIXME: still not working noncommutative
+        assert is_sage_wrapper_for_singular_ring(base_ring)
+        self.base_ring = base_ring
     def __repr__(self):
         """
         EXAMPLE::
@@ -230,26 +369,114 @@
     args.CleanUp()
     omFreeBin(args, sleftv_bin)
 
+# =====================================
+# = Singular/Plural Abstraction Layer =
+# =====================================
 
-def all_polynomials(s):
+def is_sage_wrapper_for_singular_ring(ring):
+    """
+    Check whether wrapped ring arises from Singular or Singular/Plural
+
+    EXAMPLE::
+
+    sage: from sage.libs.singular.function import is_sage_wrapper_for_singular_ring
+    sage: P.<x,y,z> = QQ[]
+    sage: is_sage_wrapper_for_singular_ring(P)
+    True
+
+    sage: A.<x,y,z> = FreeAlgebra(QQ, 3)
+    sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex') 
+    sage: is_sage_wrapper_for_singular_ring(P)
+    True
+
+    """
+    if PY_TYPE_CHECK(ring, MPolynomialRing_libsingular):
+        return True
+    if PY_TYPE_CHECK(ring, NCPolynomialRing_plural):
+        return True
+    return False
+
+cdef new_sage_polynomial(ring,  poly *p):
+    if PY_TYPE_CHECK(ring, MPolynomialRing_libsingular):
+        return new_MP(ring, p)
+    else:
+        if PY_TYPE_CHECK(ring, NCPolynomialRing_plural):
+            return new_NCP(ring, p)
+    raise ValueError("not a singular or plural ring")
+
+def is_singular_poly_wrapper(p):
+    """
+        checks if p is some data type corresponding to some singular ``poly```.
+        
+        EXAMPLE::
+            sage: from sage.rings.polynomial.plural import NCPolynomialRing_plural
+            sage: from sage.matrix.constructor  import Matrix
+            sage: from sage.libs.singular.function import is_singular_poly_wrapper
+            sage: c=Matrix(2)
+            sage: c[0,1]=-1
+            sage: P = NCPolynomialRing_plural(QQ, 2, 'x,y', c=c, d=Matrix(2))
+            sage: (x,y)=P.gens()
+            sage: is_singular_poly_wrapper(x+y)
+            True
+        
+    """
+    return PY_TYPE_CHECK(p, MPolynomial_libsingular) or PY_TYPE_CHECK(p,  NCPolynomial_plural)
+
+def all_singular_poly_wrapper(s):
     """
     Tests for a sequence ``s``, whether it consists of
     singular polynomials.
     
     EXAMPLE::
         
-        sage: from sage.libs.singular.function import all_polynomials
+        sage: from sage.libs.singular.function import all_singular_poly_wrapper
         sage: P.<x,y,z> = QQ[]
-        sage: all_polynomials([x+1, y])
+        sage: all_singular_poly_wrapper([x+1, y])
         True
-        sage: all_polynomials([x+1, y, 1])
+        sage: all_singular_poly_wrapper([x+1, y, 1])
         False
     """
     for p in s:
-        if not isinstance(p, MPolynomial_libsingular):
+        if not is_singular_poly_wrapper(p):
             return False
     return True
 
+cdef poly* access_singular_poly(p) except <poly*> -1:
+    """
+        Get the raw ``poly`` pointer from a wrapper object
+        EXAMPLE::
+            # sage: P.<a,b,c> = PolynomialRing(QQ)
+            #  sage: p=a+b
+            #  sage: from sage.libs.singular.function import access_singular_poly
+            #  sage: access_singular_poly(p)
+    """
+    if PY_TYPE_CHECK(p, MPolynomial_libsingular):
+        return (<MPolynomial_libsingular> p)._poly
+    else:
+        if PY_TYPE_CHECK(p, NCPolynomial_plural):
+            return (<NCPolynomial_plural> p)._poly
+    raise ValueError("not a singular polynomial wrapper")
+
+cdef ring* access_singular_ring(r) except <ring*> -1:
+    """
+        Get the singular ``ring`` pointer from a 
+        wrapper object.
+        
+        EXAMPLE::
+            # sage: P.<x,y,z> = QQ[]
+            # sage: from sage.libs.singular.function import access_singular_ring
+            # sage: access_singular_ring(P)
+
+    """
+    if PY_TYPE_CHECK(r, MPolynomialRing_libsingular):
+        return (<MPolynomialRing_libsingular> r )._ring
+    if PY_TYPE_CHECK(r, NCPolynomialRing_plural):
+        return (<NCPolynomialRing_plural> r )._ring
+    raise ValueError("not a singular polynomial ring wrapper")
+  
+cdef poly* copy_sage_polynomial_into_singular_poly(p):
+    return p_Copy(access_singular_poly(p), access_singular_ring(p.parent()))
+
 def all_vectors(s):
     """
     Checks if a sequence ``s`` consists of free module
@@ -270,13 +497,17 @@
         False
     """
     for p in s:
-        if not (isinstance(p, FreeModuleElement_generic_dense)\
-            and isinstance(p.parent().base_ring(), MPolynomialRing_libsingular)):
+        if not (PY_TYPE_CHECK(p, FreeModuleElement_generic_dense)\
+            and is_sage_wrapper_for_singular_ring(p.parent().base_ring())):
             return False
     return True
 
 
 
+
+
+
+
 cdef class Converter(SageObject):
     """
     A :class:`Converter` interfaces between Sage objects and Singular
@@ -305,17 +536,22 @@
         """
         cdef leftv *v
         self.args = NULL
-        self._ring = ring
+        self._sage_ring = ring
+        if ring is not None:
+            self._singular_ring = access_singular_ring(ring)
+        
         from  sage.matrix.matrix_mpolynomial_dense import Matrix_mpolynomial_dense
         from sage.matrix.matrix_integer_dense import Matrix_integer_dense
+        from sage.matrix.matrix_generic_dense import Matrix_generic_dense
         for a in args:
-            if PY_TYPE_CHECK(a, MPolynomial_libsingular):
-                v = self.append_polynomial(<MPolynomial_libsingular> a)
+            if is_singular_poly_wrapper(a):
+                v = self.append_polynomial(a)
 
-            elif PY_TYPE_CHECK(a, MPolynomialRing_libsingular):
-                v = self.append_ring(<MPolynomialRing_libsingular> a)
+            elif is_sage_wrapper_for_singular_ring(a):
+                v = self.append_ring(a)
 
-            elif PY_TYPE_CHECK(a, MPolynomialIdeal):
+            elif PY_TYPE_CHECK(a, MPolynomialIdeal) or \
+                    PY_TYPE_CHECK(a, NCPolynomialIdeal):
                 v = self.append_ideal(a)
 
             elif PY_TYPE_CHECK(a, int) or PY_TYPE_CHECK(a, long):
@@ -329,14 +565,17 @@
 
             elif PY_TYPE_CHECK(a, Matrix_integer_dense):
                 v = self.append_intmat(a)
-
+            
+            elif PY_TYPE_CHECK(a, Matrix_generic_dense) and\
+                is_sage_wrapper_for_singular_ring(a.parent().base_ring()):
+                self.append_matrix(a)
+            
             elif PY_TYPE_CHECK(a, Resolution):
                 v = self.append_resolution(a)
 
             elif PY_TYPE_CHECK(a, FreeModuleElement_generic_dense)\
-                and isinstance(
-                    a.parent().base_ring(),
-                    MPolynomialRing_libsingular):
+                and is_sage_wrapper_for_singular_ring(
+                    a.parent().base_ring()):
                 v = self.append_vector(a)
                 
             # as output ideals get converted to sequences
@@ -344,7 +583,7 @@
             # this means, that Singular lists should not be converted to Sequences,
             # as we do not want ambiguities
             elif PY_TYPE_CHECK(a, Sequence_generic)\
-                and all_polynomials(a):
+                and all_singular_poly_wrapper(a):
                 v = self.append_ideal(ring.ideal(a))
             elif PY_TYPE_CHECK(a, PolynomialSequence):
                 v = self.append_ideal(ring.ideal(a))
@@ -365,7 +604,7 @@
                     v = self.append_intvec(a)
                 else:
                     v = self.append_list(a)
-            elif a.parent() is self._ring.base_ring():
+            elif a.parent() is self._sage_ring.base_ring():
                 v = self.append_number(a)
 
             elif PY_TYPE_CHECK(a, Integer):
@@ -394,7 +633,7 @@
             sage: Converter([a,b,c],ring=P).ring()
             Multivariate Polynomial Ring in a, b, c over Finite Field of size 127
         """
-        return self._ring
+        return self._sage_ring
 
     def _repr_(self):
         """
@@ -405,7 +644,7 @@
             sage: Converter([a,b,c],ring=P) # indirect doctest
             Singular Converter in Multivariate Polynomial Ring in a, b, c over Finite Field of size 127
         """
-        return "Singular Converter in %s"%(self._ring)
+        return "Singular Converter in %s"%(self._sage_ring)
 
     def __dealloc__(self):
         if self.args:
@@ -470,29 +709,26 @@
         Convert singular matrix to matrix over the polynomial ring.
         """
         from sage.matrix.constructor import Matrix
-        sage_ring = self._ring
-        cdef ring *singular_ring = (<MPolynomialRing_libsingular>\
-            sage_ring)._ring
+        #cdef ring *singular_ring = (<MPolynomialRing_libsingular>\
+        #    self._sage_ring)._ring
         ncols = mat.ncols
         nrows = mat.nrows
-        result = Matrix(sage_ring, nrows, ncols)
-        cdef MPolynomial_libsingular p
+        result = Matrix(self._sage_ring, nrows, ncols)
         for i in xrange(nrows):
             for j in xrange(ncols):
-                p = MPolynomial_libsingular(sage_ring)
-                p._poly = mat.m[i*ncols+j]
+                p = new_sage_polynomial(self._sage_ring, mat.m[i*ncols+j])
                 mat.m[i*ncols+j]=NULL
                 result[i,j] = p
         return result
     
     cdef to_sage_vector_destructive(self, poly *p, free_module = None):
-        cdef ring *r=self._ring._ring
+        #cdef ring *r=self._ring._ring
         cdef int rank
         if free_module:
             rank = free_module.rank()
         else:
-            rank = singular_vector_maximal_component(p, r)
-            free_module = self._ring**rank
+            rank = singular_vector_maximal_component(p, self._singular_ring)
+            free_module = self._sage_ring**rank
         cdef poly *acc
         cdef poly *p_iter
         cdef poly *first
@@ -505,9 +741,9 @@
             first = NULL
             p_iter=p
             while p_iter != NULL:
-                if p_GetComp(p_iter, r) == i:
-                    p_SetComp(p_iter,0, r)
-                    p_Setm(p_iter, r)
+                if p_GetComp(p_iter, self._singular_ring) == i:
+                    p_SetComp(p_iter,0, self._singular_ring)
+                    p_Setm(p_iter, self._singular_ring)
                     if acc == NULL:
                         first = p_iter
                     else:
@@ -522,7 +758,8 @@
                 else:
                     previous = p_iter
                     p_iter = pNext(p_iter)
-            result.append(new_MP(self._ring, first))
+            
+            result.append(new_sage_polynomial(self._sage_ring, first))
         return free_module(result)
           
     cdef object to_sage_module_element_sequence_destructive( self, ideal *i):
@@ -536,10 +773,10 @@
         - ``r`` -- a SINGULAR ring
         - ``sage_ring`` -- a Sage ring matching r
         """
-        cdef MPolynomialRing_libsingular sage_ring = self._ring
+        #cdef MPolynomialRing_libsingular sage_ring = self._ring
         cdef int j
         cdef int rank=i.rank
-        free_module = sage_ring**rank       
+        free_module = self._sage_ring ** rank       
         l = []
 
         for j from 0 <= j < IDELEMS(i):
@@ -568,11 +805,13 @@
         return result
     
     
-    cdef leftv *append_polynomial(self, MPolynomial_libsingular p) except NULL:
+    cdef leftv *append_polynomial(self, p) except NULL:
         """
         Append the polynomial ``p`` to the list.
         """
-        cdef poly* _p = p_Copy(p._poly, <ring*>(<MPolynomialRing_libsingular>p._parent)._ring)
+        cdef poly* _p
+        _p = copy_sage_polynomial_into_singular_poly(p)
+                
         return self._append(_p, POLY_CMD)
 
     cdef leftv *append_ideal(self,  i) except NULL:
@@ -589,7 +828,7 @@
         """
         rank = max([v.parent().rank() for v in m])
         cdef ideal *result
-        cdef ring *r = self._ring._ring
+        cdef ring *r = self._singular_ring
         cdef ideal *i
         cdef int j = 0
 
@@ -605,21 +844,21 @@
         """
         Append the number ``n`` to the list.
         """
-        cdef number *_n =  sa2si(n, self._ring._ring)
+        cdef number *_n =  sa2si(n, self._singular_ring)
         return self._append(<void *>_n, NUMBER_CMD)
 
-    cdef leftv *append_ring(self, MPolynomialRing_libsingular r) except NULL:
+    cdef leftv *append_ring(self, r) except NULL:
         """
         Append the ring ``r`` to the list.
         """
-        cdef ring *_r =  <ring*> r._ring
+        cdef ring *_r =  access_singular_ring(r)
         _r.ref+=1
         return self._append(<void *>_r, RING_CMD)
 
     cdef leftv *append_matrix(self, mat) except NULL:
         
         sage_ring = mat.base_ring()
-        cdef ring *r=<ring*> (<MPolynomialRing_libsingular> sage_ring)._ring
+        cdef ring *r=<ring*> access_singular_ring(sage_ring)
 
         cdef poly *p
         ncols = mat.ncols()
@@ -627,8 +866,8 @@
         cdef matrix* _m=mpNew(nrows,ncols)
         for i in xrange(nrows):
             for j in xrange(ncols):
-                p = p_Copy(
-                    (<MPolynomial_libsingular> mat[i,j])._poly, r)
+                #FIXME
+                p = copy_sage_polynomial_into_singular_poly(mat[i,j])
                 _m.m[ncols*i+j]=p
         return self._append(_m, MATRIX_CMD)
 
@@ -646,7 +885,7 @@
         Append the list ``l`` to the list.
         """
         
-        cdef Converter c = Converter(l, self._ring)
+        cdef Converter c = Converter(l, self._sage_ring)
         n = len(c)
 
         cdef lists *singular_list=<lists*>omAlloc0Bin(slists_bin)
@@ -677,7 +916,7 @@
         Append vector ``v`` from free 
         module over polynomial ring.
         """
-        cdef ring *r = self._ring._ring
+        cdef ring *r = self._singular_ring
         cdef poly *p = sage_vector_to_poly(v, r)
         return self._append(<void*> p, VECTOR_CMD)
     
@@ -717,15 +956,17 @@
 
         - ``to_convert`` - a Singular ``leftv``
         """
+        #FIXME
         cdef MPolynomial_libsingular res_poly
         cdef int rtyp = to_convert.rtyp
         cdef lists *singular_list
         cdef Resolution res_resolution
         if rtyp == IDEAL_CMD:
-            return singular_ideal_to_sage_sequence(<ideal*>to_convert.data, self._ring._ring, self._ring)
+            return singular_ideal_to_sage_sequence(<ideal*>to_convert.data, self._singular_ring, self._sage_ring)
 
         elif rtyp == POLY_CMD:
-            res_poly = MPolynomial_libsingular(self._ring)
+            #FIXME
+            res_poly = MPolynomial_libsingular(self._sage_ring)
             res_poly._poly = <poly*>to_convert.data
             to_convert.data = NULL
             #prevent it getting free, when cleaning the leftv
@@ -735,7 +976,7 @@
             return <long>to_convert.data
         
         elif rtyp == NUMBER_CMD:
-            return si2sa(<number *>to_convert.data, self._ring._ring, self._ring.base_ring())
+            return si2sa(<number *>to_convert.data, self._singular_ring, self._sage_ring.base_ring())
 
         elif rtyp == INTVEC_CMD:
             return si2sa_intvec(<intvec *>to_convert.data)
@@ -751,10 +992,7 @@
             
 
         elif rtyp == RING_CMD or rtyp==QRING_CMD:
-            ring_wrap_result=RingWrap()
-            (<RingWrap> ring_wrap_result)._ring=<ring*> to_convert.data
-            (<RingWrap> ring_wrap_result)._ring.ref+=1
-            return ring_wrap_result
+            return new_RingWrap( <ring*> to_convert.data )
 
         elif rtyp == MATRIX_CMD:
             return self.to_sage_matrix(<matrix*>  to_convert.data )
@@ -777,7 +1015,7 @@
             return self.to_sage_integer_matrix(
                 <intvec*> to_convert.data)
         elif rtyp == RESOLUTION_CMD:
-            res_resolution = Resolution(self._ring)
+            res_resolution = Resolution(self._sage_ring)
             res_resolution._resolution = <syStrategy*> to_convert.data
             res_resolution._resolution.references += 1
             return res_resolution
@@ -946,7 +1184,7 @@
         """
         return "%s (singular function)" %(self._name)
 
-    def __call__(self, *args, MPolynomialRing_libsingular ring=None, bint interruptible=True, attributes=None):
+    def __call__(self, *args, ring=None, bint interruptible=True, attributes=None):
         """
         Call this function with the provided arguments ``args`` in the
         ring ``R``.
@@ -1026,7 +1264,8 @@
         """
         if ring is None:
             ring = self.common_ring(args, ring)
-        if not PY_TYPE_CHECK(ring, MPolynomialRing_libsingular):
+        if not (PY_TYPE_CHECK(ring, MPolynomialRing_libsingular) or \
+                PY_TYPE_CHECK(ring, NCPolynomialRing_plural)):
             raise TypeError("Cannot call Singular function '%s' with ring parameter of type '%s'"%(self._name,type(ring)))
         return call_function(self, args, ring, interruptible, attributes)
     
@@ -1085,7 +1324,7 @@
         singular_doc = get_docstring(self._name).split('\n')
         return prefix + "\n::\n\n"+'\n'.join(["    "+L for L in singular_doc])
 
-    cdef MPolynomialRing_libsingular common_ring(self, tuple args, ring=None):
+    cdef common_ring(self, tuple args, ring=None):
         """
         Return the common ring for the argument list ``args``.
 
@@ -1103,13 +1342,16 @@
         from  sage.matrix.matrix_mpolynomial_dense import Matrix_mpolynomial_dense
         from sage.matrix.matrix_integer_dense import Matrix_integer_dense
         for a in args:
-            if PY_TYPE_CHECK(a, MPolynomialIdeal):
+            if PY_TYPE_CHECK(a, MPolynomialIdeal) or \
+                    PY_TYPE_CHECK(a, NCPolynomialIdeal):
                 ring2 = a.ring()
-            elif PY_TYPE_CHECK(a, MPolynomial_libsingular):
+            elif is_singular_poly_wrapper(a):
                 ring2 = a.parent()
-            elif PY_TYPE_CHECK(a, MPolynomialRing_libsingular):
+            elif is_sage_wrapper_for_singular_ring(a):
                 ring2 = a
-            elif PY_TYPE_CHECK(a, int) or PY_TYPE_CHECK(a, long) or PY_TYPE_CHECK(a, basestring):
+            elif PY_TYPE_CHECK(a, int) or\
+                PY_TYPE_CHECK(a, long) or\
+                PY_TYPE_CHECK(a, basestring):
                 continue
             elif PY_TYPE_CHECK(a, Matrix_integer_dense):
                 continue
@@ -1122,9 +1364,8 @@
             elif PY_TYPE_CHECK(a, Resolution):
                 ring2 = (<Resolution> a).base_ring
             elif PY_TYPE_CHECK(a, FreeModuleElement_generic_dense)\
-                and PY_TYPE_CHECK(
-                    a.parent().base_ring(),
-                     MPolynomialRing_libsingular):
+                and is_sage_wrapper_for_singular_ring(
+                    a.parent().base_ring()):
                 ring2 = a.parent().base_ring()
             elif ring is not None:
                 a.parent() is ring
@@ -1136,7 +1377,7 @@
                 raise ValueError("Rings do not match up.")
         if ring is None:
             raise ValueError("Could not detect ring.")
-        return <MPolynomialRing_libsingular>ring
+        return ring
 
     def __reduce__(self):
         """
@@ -1167,7 +1408,7 @@
         else:
             return cmp(self._name, (<SingularFunction>other)._name)
 
-cdef inline call_function(SingularFunction self, tuple args, MPolynomialRing_libsingular R, bint signal_handler=True, attributes=None):
+cdef inline call_function(SingularFunction self, tuple args, object R, bint signal_handler=True, attributes=None):
     global currRingHdl
     global errorreported
     global currentVoice
@@ -1175,8 +1416,12 @@
     global error_messages
 
 
-    cdef ring *si_ring = R._ring
-
+    cdef ring *si_ring
+    if PY_TYPE_CHECK(R, MPolynomialRing_libsingular):
+        si_ring = (<MPolynomialRing_libsingular>R)._ring
+    else:
+        si_ring = (<NCPolynomialRing_plural>R)._ring
+ 
     if si_ring != currRing:
         rChangeCurrRing(si_ring)
 
@@ -1418,7 +1663,42 @@
         <Resolution>
         sage: singular_list(resolution)
         [[(-2*y, 2, y + 1, 0), (0, -2, x - 1, 0), (x*y - y, -y + 1, 1, -y), (x^2 + 1, -x - 1, -1, -x)], [(-x - 1, y - 1, 2*x, -2*y)], [(0)]]
-
+        sage: from sage.rings.polynomial.plural import NCPolynomialRing_plural
+        sage: from sage.matrix.constructor  import Matrix
+        sage: c=Matrix(2)
+        sage: c[0,1]=-1
+        sage: P = NCPolynomialRing_plural(QQ, 2, 'x,y', c=c, d=Matrix(2))
+        sage: (x,y)=P.gens()
+        sage: I= Sequence([x*y,x+y], check=False, immutable=True)#P.ideal(x*y,x+y)
+        sage: twostd = singular_function("twostd")
+        sage: twostd(I)
+        [x + y, y^2]
+        sage: M=syz(I)
+        doctest...
+        sage: M
+        [(x + y, x*y)]
+        sage: syz(M, ring=P)
+        [(0)]
+        sage: mres(I, 0)
+        <Resolution>
+        sage: M=P**3
+        sage: v=M((100*x,5*y,10*y*x*y))
+        sage: leadcoef(v)
+        -10
+        sage: v = M([x+y,x*y+y**3,x])
+        sage: lead(v)
+        (0, y^3)
+        sage: jet(v, 2)
+        (x + y, x*y, x)
+        sage: l = ringlist(P)
+        sage: len(l)
+        6
+        sage: ring(l, ring=P)
+        <noncommutative RingWrap>
+        sage: I=twostd(I)
+        sage: l[3]=I
+        sage: ring(l, ring=P)
+        <noncommutative RingWrap>
         
     """
 
@@ -1490,3 +1770,12 @@
                     ph = IDNEXT(ph)
         h = IDNEXT(h)
     return l
+
+
+#cdef ring*?
+cdef inline RingWrap new_RingWrap(ring* r):
+    cdef RingWrap ring_wrap_result = PY_NEW(RingWrap)
+    ring_wrap_result._ring = r
+    ring_wrap_result._ring.ref += 1
+    
+    return ring_wrap_result
diff -r 10f49e34d981 -r dc42cb80eeef sage/libs/singular/singular-cdefs.pxi
--- a/sage/libs/singular/singular-cdefs.pxi	Mon Sep 19 16:34:42 2011 -0700
+++ b/sage/libs/singular/singular-cdefs.pxi	Sun Mar 13 15:24:15 2011 +0100
@@ -148,6 +148,22 @@
         bint (*nGreaterZero)(number* a)
         void (*nPower)(number* a, int i, number* * result)
 
+    # polynomials
+
+    ctypedef struct poly "polyrec":
+        poly *next
+
+    # ideals
+
+    ctypedef struct ideal "sip_sideal":
+        poly **m # gens array
+        long rank # rank of module, 1 for ideals
+        int nrows # always 1
+        int ncols # number of gens
+
+    # polynomial procs
+    ctypedef struct p_Procs_s "p_Procs_s":
+        pass
     # rings
 
     ctypedef struct ring "ip_sring":
@@ -160,6 +176,9 @@
         int  CanShortOut # control printing capabilities
         number *minpoly # minpoly for base extension field
         char **names # variable names
+        p_Procs_s *p_Procs #polxnomial procs
+        ideal *qideal #quotient ideal
+        
         char **parameter # parameter names
         ring *algring # base extension field
         short N # number of variables
@@ -197,10 +216,7 @@
         ringorder_Ws
         ringorder_L
 
-    # polynomials
 
-    ctypedef struct poly "polyrec":
-        poly *next
 
     # groebner basis options
     
@@ -985,6 +1001,35 @@
 
     cdef int LANG_TOP
 
+# Non-commutative functions
+    ctypedef enum nc_type:
+      nc_error # Something's gone wrong!
+      nc_general # yx=q xy+... 
+      nc_skew # yx=q xy 
+      nc_comm # yx= xy 
+      nc_lie,  # yx=xy+... 
+      nc_undef, # for internal reasons */
+      nc_exterior #
+
+  
+cdef extern from "gring.h":
+    void ncRingType(ring *, nc_type)
+    nc_type ncRingType_get "ncRingType" (ring *)
+    int nc_CallPlural(matrix* CC, matrix* DD, poly* CN, poly* DN, ring* r)
+    bint nc_SetupQuotient(ring *, ring *, bint)
+    
+cdef extern from "sca.h":
+    void sca_p_ProcsSet(ring *, p_Procs_s *)
+    void scaFirstAltVar(ring *, int)
+    void scaLastAltVar(ring *, int)
+
+cdef extern from "ring.h":
+    bint rIsPluralRing(ring* r)
+    void rPrint "rWrite"(ring* r)
+    char* rOrderingString "rOrdStr"(ring* r)
+#    void rDebugPrint(ring* r)
+    void pDebugPrint "p_DebugPrint" (poly*p, ring* r)
+    
 cdef extern from "stairc.h":
     # Computes the monomial basis for R[x]/I
     ideal *scKBase(int deg, ideal *s, ideal *Q)
diff -r 10f49e34d981 -r dc42cb80eeef sage/modules/free_module.py
--- a/sage/modules/free_module.py	Mon Sep 19 16:34:42 2011 -0700
+++ b/sage/modules/free_module.py	Sun Mar 13 15:24:15 2011 +0100
@@ -187,6 +187,8 @@
 from sage.structure.parent_gens import ParentWithGens
 from sage.misc.cachefunc import cached_method
 
+from warnings import warn
+
 ###############################################################################
 #
 # Constructor functions
@@ -350,32 +352,42 @@
         if not isinstance(sparse,bool):
             raise TypeError, "Argument sparse (= %s) must be True or False" % sparse
 
+
+        # We should have two sided, left sided and right sided ideals,
+        # but that's another story ....
+        #
         if not (hasattr(base_ring,'is_commutative') and base_ring.is_commutative()):
-            raise TypeError, "The base_ring must be a commutative ring."
-
-        if not sparse and isinstance(base_ring,sage.rings.real_double.RealDoubleField_class):
-            return RealDoubleVectorSpace_class(rank)
-
-        elif not sparse and isinstance(base_ring,sage.rings.complex_double.ComplexDoubleField_class):
-            return ComplexDoubleVectorSpace_class(rank)
-
-        elif base_ring.is_field():
-            return FreeModule_ambient_field(base_ring, rank, sparse=sparse)
-
-        elif isinstance(base_ring, principal_ideal_domain.PrincipalIdealDomain):
-            return FreeModule_ambient_pid(base_ring, rank, sparse=sparse)
-
-        elif isinstance(base_ring, sage.rings.number_field.order.Order) \
-            and base_ring.is_maximal() and base_ring.class_number() == 1:
+            warn("""You are constructing a free module   over a noncommutative ring. Sage does 
+             not have a concept of left/right and both sided modules, so be careful. It's also
+             not guaranteed that all multiplications are done from the right side.""")
+            
+        #            raise TypeError, "The base_ring must be a commutative ring."
+
+        try:
+            if not sparse and isinstance(base_ring,sage.rings.real_double.RealDoubleField_class):
+             return RealDoubleVectorSpace_class(rank)
+
+            elif not sparse and isinstance(base_ring,sage.rings.complex_double.ComplexDoubleField_class):
+             return ComplexDoubleVectorSpace_class(rank)
+
+            elif base_ring.is_field():
+             return FreeModule_ambient_field(base_ring, rank, sparse=sparse)
+
+            elif isinstance(base_ring, principal_ideal_domain.PrincipalIdealDomain):
                 return FreeModule_ambient_pid(base_ring, rank, sparse=sparse)
-        
-        elif isinstance(base_ring, integral_domain.IntegralDomain) or base_ring.is_integral_domain():
-            return FreeModule_ambient_domain(base_ring, rank, sparse=sparse)
+
+            elif isinstance(base_ring, sage.rings.number_field.order.Order) \
+                and base_ring.is_maximal() and base_ring.class_number() == 1:
+                return FreeModule_ambient_pid(base_ring, rank, sparse=sparse)
+        
+            elif isinstance(base_ring, integral_domain.IntegralDomain) or base_ring.is_integral_domain():
+                return FreeModule_ambient_domain(base_ring, rank, sparse=sparse)
             
-        else:
+            else:
+                return FreeModule_ambient(base_ring, rank, sparse=sparse)
+        except NotImplementedError:
             return FreeModule_ambient(base_ring, rank, sparse=sparse)
 
-
 FreeModule = FreeModuleFactory("FreeModule")    
 
 
@@ -563,8 +575,10 @@
             Category of modules with basis over Integer Ring
 
         """
-        if not isinstance(base_ring, commutative_ring.CommutativeRing):
-            raise TypeError, "base_ring (=%s) must be a commutative ring"%base_ring
+        if not base_ring.is_commutative():
+            warn("""You are constructing a free module over a noncommutative ring. Sage does not have a concept of left/right and both sided modules be careful. It's also not guarantied that all multiplications are done from the right side.""")
+            #raise TypeError, "base_ring (=%s) must be a commutative ring"%base_ring
+            
         rank = sage.rings.integer.Integer(rank)
         if rank < 0:
             raise ValueError, "rank (=%s) must be nonnegative"%rank
diff -r 10f49e34d981 -r dc42cb80eeef sage/rings/ideal_monoid.py
--- a/sage/rings/ideal_monoid.py	Mon Sep 19 16:34:42 2011 -0700
+++ b/sage/rings/ideal_monoid.py	Sun Mar 13 15:24:15 2011 +0100
@@ -47,8 +47,6 @@
             sage: M = sage.rings.ideal_monoid.IdealMonoid(R); M # indirect doctest
             Monoid of ideals of Number Field in a with defining polynomial x^2 + 23
         """
-        if not is_CommutativeRing(R):
-            raise TypeError, "R must be a commutative ring"
         self.__R = R
         Parent.__init__(self, base = sage.rings.integer_ring.ZZ, category = Monoids())
         self._populate_coercion_lists_()
diff -r 10f49e34d981 -r dc42cb80eeef sage/rings/polynomial/multi_polynomial_ideal.py
--- a/sage/rings/polynomial/multi_polynomial_ideal.py	Mon Sep 19 16:34:42 2011 -0700
+++ b/sage/rings/polynomial/multi_polynomial_ideal.py	Sun Mar 13 15:24:15 2011 +0100
@@ -431,7 +431,7 @@
         sage: P.<a,b,c,d,e> = PolynomialRing(GF(127))
         sage: J = sage.rings.ideal.Cyclic(P).homogenize()
         sage: from sage.misc.sageinspect import sage_getsource
-        sage: "buchberger" in sage_getsource(J.interreduced_basis)
+        sage: "buchberger" in sage_getsource(J.interreduced_basis) #indirect doctest
         True
 
     The following tests against a bug that was fixed in trac ticket #11298::
@@ -647,8 +647,8 @@
         EXAMPLES::
         
             sage: R.<a,b,c,d,e,f,g,h,i,j> = PolynomialRing(GF(127),10)
-            sage: I = sage.rings.ideal.Cyclic(R,4)
-            sage: magma(I)                                          # optional - magma
+            sage: I = sage.rings.ideal.Cyclic(R,4) # indirect doctest
+            sage: magma(I)    # optional - magma
             Ideal of Polynomial ring of rank 10 over GF(127)
             Order: Graded Reverse Lexicographical
             Variables: a, b, c, d, e, f, g, h, i, j
@@ -726,11 +726,123 @@
             mgb = [e.replace("$.1",a) for e in mgb]
 
         from sage.rings.polynomial.multi_polynomial_sequence import PolynomialSequence
-
         B = PolynomialSequence([R(e) for e in mgb], R, immutable=True)
         return B
-
-class MPolynomialIdeal_singular_repr:
+        
+class MPolynomialIdeal_singular_base_repr:
+    @require_field
+    def syzygy_module(self):
+        r"""
+        Computes the first syzygy (i.e., the module of relations of the
+        given generators) of the ideal.
+        
+        EXAMPLE::
+        
+            sage: R.<x,y> = PolynomialRing(QQ)
+            sage: f = 2*x^2 + y
+            sage: g = y
+            sage: h = 2*f + g
+            sage: I = Ideal([f,g,h])
+            sage: M = I.syzygy_module(); M
+            [       -2        -1         1]
+            [       -y 2*x^2 + y         0]
+            sage: G = vector(I.gens())
+            sage: M*G
+            (0, 0)
+        
+        ALGORITHM: Uses Singular's syz command
+        """
+        import sage.libs.singular
+        syz = sage.libs.singular.ff.syz
+        from sage.matrix.constructor import matrix
+
+        #return self._singular_().syz().transpose().sage_matrix(self.ring())
+        S = syz(self)
+        return matrix(self.ring(), S)
+
+    @libsingular_standard_options
+    def _groebner_basis_libsingular(self, algorithm="groebner", redsb=True, red_tail=True):
+        """
+        Return the reduced Groebner basis of this ideal. If the
+        Groebner basis for this ideal has been calculated before the
+        cached Groebner basis is returned regardless of the requested
+        algorithm.
+        
+        INPUT:
+        
+        -  ``algorithm`` - see below for available algorithms
+        - ``redsb`` - return a reduced Groebner basis (default: ``True``)
+        - ``red_tail`` - perform tail reduction (default: ``True``)
+
+        ALGORITHMS:
+        
+        'groebner'
+            Singular's heuristic script (default)
+
+        'std'
+            Buchberger's algorithm
+        
+        'slimgb'
+            the *SlimGB* algorithm
+
+        'stdhilb'
+            Hilbert Basis driven Groebner basis
+        
+        'stdfglm'
+            Buchberger and FGLM
+        
+        EXAMPLES:
+        
+        We compute a Groebner basis of 'cyclic 4' relative to
+        lexicographic ordering. ::
+        
+            sage: R.<a,b,c,d> = PolynomialRing(QQ, 4, order='lex')
+            sage: I = sage.rings.ideal.Cyclic(R,4); I
+            Ideal (a + b + c + d, a*b + a*d + b*c + c*d, a*b*c + a*b*d
+            + a*c*d + b*c*d, a*b*c*d - 1) of Multivariate Polynomial
+            Ring in a, b, c, d over Rational Field
+        
+        ::
+        
+            sage: I._groebner_basis_libsingular()
+            [c^2*d^6 - c^2*d^2 - d^4 + 1, c^3*d^2 + c^2*d^3 - c - d,
+            b*d^4 - b + d^5 - d, b*c - b*d + c^2*d^4 + c*d - 2*d^2,
+            b^2 + 2*b*d + d^2, a + b + c + d]
+        
+        ALGORITHM: Uses libSINGULAR.
+        """
+        from sage.rings.polynomial.multi_polynomial_ideal_libsingular import std_libsingular, slimgb_libsingular
+        from sage.libs.singular import singular_function
+        from sage.libs.singular.option import opt
+
+        import sage.libs.singular
+        groebner = sage.libs.singular.ff.groebner
+
+        if get_verbose()>=2:
+            opt['prot'] = True
+        for name,value in kwds.iteritems():
+            if value is not None:
+                opt[name] = value
+
+        T = self.ring().term_order()
+        
+        if algorithm == "std":
+            S = std_libsingular(self)
+        elif algorithm == "slimgb":
+            S = slimgb_libsingular(self)
+        elif algorithm == "groebner":
+            S = groebner(self)
+        else:
+            try:
+                fnc = singular_function(algorithm)
+                S = fnc(self)
+            except NameError:
+                raise NameError("Algorithm '%s' unknown"%algorithm)
+        return S
+    
+
+class MPolynomialIdeal_singular_repr(
+        MPolynomialIdeal_singular_base_repr):
     """
     An ideal in a multivariate polynomial ring, which has an
     underlying Singular ring associated to it.
@@ -1523,88 +1635,6 @@
             print "Highest degree reached during computation: %2d."%log_parser.max_deg
         return S
 
-    @libsingular_standard_options
-    def _groebner_basis_libsingular(self, algorithm="groebner", *args, **kwds):
-        """
-        Return the reduced Groebner basis of this ideal. If the
-        Groebner basis for this ideal has been calculated before the
-        cached Groebner basis is returned regardless of the requested
-        algorithm.
-        
-        INPUT:
-        
-        -  ``algorithm`` - see below for available algorithms
-        - ``redsb`` - return a reduced Groebner basis (default: ``True``)
-        - ``red_tail`` - perform tail reduction (default: ``True``)
-
-        ALGORITHMS:
-        
-        'groebner'
-            Singular's heuristic script (default)
-
-        'std'
-            Buchberger's algorithm
-        
-        'slimgb'
-            the *SlimGB* algorithm
-
-        'stdhilb'
-            Hilbert Basis driven Groebner basis
-        
-        'stdfglm'
-            Buchberger and FGLM
-        
-        EXAMPLES:
-        
-        We compute a Groebner basis of 'cyclic 4' relative to
-        lexicographic ordering. ::
-        
-            sage: R.<a,b,c,d> = PolynomialRing(QQ, 4, order='lex')
-            sage: I = sage.rings.ideal.Cyclic(R,4); I
-            Ideal (a + b + c + d, a*b + a*d + b*c + c*d, a*b*c + a*b*d
-            + a*c*d + b*c*d, a*b*c*d - 1) of Multivariate Polynomial
-            Ring in a, b, c, d over Rational Field
-        
-        ::
-        
-            sage: I._groebner_basis_libsingular()
-            [c^2*d^6 - c^2*d^2 - d^4 + 1, c^3*d^2 + c^2*d^3 - c - d,
-            b*d^4 - b + d^5 - d, b*c - b*d + c^2*d^4 + c*d - 2*d^2,
-            b^2 + 2*b*d + d^2, a + b + c + d]
-        
-        ALGORITHM:
-
-        Uses libSINGULAR.
-        """
-        from sage.rings.polynomial.multi_polynomial_ideal_libsingular import std_libsingular, slimgb_libsingular
-        from sage.libs.singular import singular_function
-        from sage.libs.singular.option import opt
-
-        import sage.libs.singular
-        groebner = sage.libs.singular.ff.groebner
-
-        if get_verbose()>=2:
-            opt['prot'] = True
-        for name,value in kwds.iteritems():
-            if value is not None:
-                opt[name] = value
-
-        T = self.ring().term_order()
-        
-        if algorithm == "std":
-            S = std_libsingular(self)
-        elif algorithm == "slimgb":
-            S = slimgb_libsingular(self)
-        elif algorithm == "groebner":
-            S = groebner(self)
-        else:
-            try:
-                fnc = singular_function(algorithm)
-                S = fnc(self)
-            except NameError:
-                raise NameError("Algorithm '%s' unknown"%algorithm)
-        return S
-    
     @require_field
     def genus(self):
         """
@@ -1665,6 +1695,7 @@
             False
         """
         R = self.ring()
+
         if not isinstance(other, MPolynomialIdeal_singular_repr) or other.ring() != R:
             raise ValueError, "other must be an ideal in the ring of self, but it isn't."
 
@@ -2571,7 +2602,7 @@
         
             sage: R.<x,y,z> = PolynomialRing(QQ)
             sage: I = R.ideal(x^2-2*x*z+5, x*y^2+y*z+1, 3*y^2-8*x*z)
-            sage: I.normal_basis()
+            sage: I.normal_basis() #indirect doctest
             [z^2, y*z, x*z, z, x*y, y, x, 1]
         """
         from sage.rings.polynomial.multi_polynomial_ideal_libsingular import kbase_libsingular
@@ -2627,6 +2658,12 @@
     def _macaulay2_(self, macaulay2=None):
         """
         Return Macaulay2 ideal corresponding to this ideal.
+    EXAMPLES::
+    
+        sage: R.<x,y,z,w> = PolynomialRing(ZZ, 4)
+        sage: I = ideal(x*y-z^2, y^2-w^2)  #indirect doctest
+        sage: macaulay2(I) # optional - macaulay2
+        Ideal (x*y - z^2, y^2 - w^2) of Multivariate Polynomial Ring in x, y, z, w over Integer Ring
         """
         if macaulay2 is None: macaulay2 = macaulay2_default
         try:
@@ -2708,6 +2745,156 @@
         R = self.ring()
         return R(k)
 
+class NCPolynomialIdeal(MPolynomialIdeal_singular_repr, Ideal_generic):
+    def __init__(self, ring, gens, coerce=True):
+        r"""
+        Computes a non-commutative ideal.
+        
+        EXAMPLES::
+        
+            sage: A.<x,y,z> = FreeAlgebra(QQ, 3)
+            sage: H = A.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y})
+            sage: H.inject_variables()
+            Defining x, y, z
+
+            sage: I = H.ideal([y^2, x^2, z^2-H.one_element()],coerce=False) # indirect doctest
+        """
+        Ideal_generic.__init__(self, ring, gens, coerce=coerce)
+
+    def __call_singular(self, cmd, arg = None):
+        """
+        Internal function for calling a Singular function
+
+        INPUTS:
+
+        - ``cmd`` - string, representing a Singular function
+
+        - ``arg`` (Default: None) - arguments for which cmd is called
+
+        OUTPUTS:
+
+        - result of the Singular function call
+
+        EXAMPLES::
+
+            sage: A.<x,y,z> = FreeAlgebra(QQ, 3)
+            sage: H = A.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y})
+            sage: H.inject_variables()
+            Defining x, y, z
+            sage: id = H.ideal(x + y, y + z)
+            sage: id.std()  # indirect doctest
+            Ideal (z, y, x) of Noncommutative Multivariate Polynomial Ring in x, y, z over Rational Field, nc-relations: {y*x: x*y - z, z*y: y*z - 2*y, z*x: x*z + 2*x}
+        """
+        from sage.libs.singular.function import singular_function
+        fun = singular_function(cmd)
+        if arg is None:
+             return fun(self, ring=self.ring())
+        
+        return fun(self, arg, ring=self.ring())
+
+    def std(self):
+        r"""
+        Computes a left GB of the ideal.
+        
+        EXAMPLES::
+        
+            sage: A.<x,y,z> = FreeAlgebra(QQ, 3)
+            sage: H = A.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y})
+            sage: H.inject_variables()
+            Defining x, y, z
+            sage: I = H.ideal([y^2, x^2, z^2-H.one_element()],coerce=False)
+            sage: I.std()
+            Ideal (z^2 - 1, y*z - y, x*z + x, y^2, 2*x*y - z - 1, x^2) of Noncommutative Multivariate Polynomial Ring in x, y, z over Rational Field...
+        
+        ALGORITHM: Uses Singular's std command
+        """
+        return self.ring().ideal( self.__call_singular('std') )
+#        return self.__call_singular('std')
+
+    def twostd(self):
+        r"""
+        Computes a two-sided GB of the ideal.
+        
+        EXAMPLES::
+        
+            sage: A.<x,y,z> = FreeAlgebra(QQ, 3)
+            sage: H = A.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y})
+            sage: H.inject_variables()
+            Defining x, y, z
+            sage: I = H.ideal([y^2, x^2, z^2-H.one_element()],coerce=False)
+            sage: I.twostd()
+            Ideal (z^2 - 1, y*z - y, x*z + x, y^2, 2*x*y - z - 1, x^2) of Noncommutative Multivariate Polynomial Ring in x, y, z over Rational Field...
+        
+        ALGORITHM: Uses Singular's twostd command
+        """
+        return self.ring().ideal( self.__call_singular('twostd') )
+#        return self.__call_singular('twostd')
+
+#    def syz(self):
+#        return self.__call_singular('syz')
+
+    @require_field
+    def syzygy_module(self):
+        r"""
+        Computes the first syzygy (i.e., the module of relations of the
+        given generators) of the ideal.
+        
+        EXAMPLE::
+        
+            sage: A.<x,y,z> = FreeAlgebra(QQ, 3)
+            sage: H = A.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y})
+            sage: H.inject_variables()
+            Defining x, y, z
+            sage: I = H.ideal([y^2, x^2, z^2-H.one_element()],coerce=False)
+            sage: G = vector(I.gens()); G 
+            doctest:357: UserWarning: You are constructing a free module   over a noncommutative ring. Sage does
+                         not have a concept of left/right and both sided modules be careful. It's also
+                         not guarantied that all multiplications are done from the right side.
+            doctest:573: UserWarning: You are constructing a free module over a noncommutative ring. Sage does not have a concept of left/right and both sided modules be careful. It's also not guarantied that all multiplications are done from the right side.
+            (y^2, x^2, z^2 - 1)
+            sage: M = I.syzygy_module(); M
+            [                                                                         -z^2 - 8*z - 15                                                                                        0                                                                                      y^2]
+            [                                                                                       0                                                                          -z^2 + 8*z - 15                                                                                      x^2]
+            [                                                              x^2*z^2 + 8*x^2*z + 15*x^2                                                              -y^2*z^2 + 8*y^2*z - 15*y^2                                                                   -4*x*y*z + 2*z^2 + 2*z]
+            [                 x^2*y*z^2 + 9*x^2*y*z - 6*x*z^3 + 20*x^2*y - 72*x*z^2 - 282*x*z - 360*x                                                              -y^3*z^2 + 7*y^3*z - 12*y^3                                                                                  6*y*z^2]
+            [                                                              x^3*z^2 + 7*x^3*z + 12*x^3                 -x*y^2*z^2 + 9*x*y^2*z - 4*y*z^3 - 20*x*y^2 + 52*y*z^2 - 224*y*z + 320*y                                                                                 -6*x*z^2]
+            [  x^2*y^2*z + 4*x^2*y^2 - 8*x*y*z^2 - 48*x*y*z + 12*z^3 - 64*x*y + 108*z^2 + 312*z + 288                                                                           -y^4*z + 4*y^4                                                                                        0]
+            [                                                  2*x^3*y*z + 8*x^3*y + 9*x^2*z + 27*x^2                                   -2*x*y^3*z + 8*x*y^3 - 12*y^2*z^2 + 99*y^2*z - 195*y^2                                                                -36*x*y*z + 24*z^2 + 18*z]
+            [                                                  2*x^3*y*z + 8*x^3*y + 9*x^2*z + 27*x^2                                   -2*x*y^3*z + 8*x*y^3 - 12*y^2*z^2 + 99*y^2*z - 195*y^2                                                                -36*x*y*z + 24*z^2 + 18*z]
+            [                                                                           x^4*z + 4*x^4    -x^2*y^2*z + 4*x^2*y^2 - 4*x*y*z^2 + 32*x*y*z - 6*z^3 - 64*x*y + 66*z^2 - 240*z + 288                                                                                        0]
+            [x^3*y^2*z + 4*x^3*y^2 + 18*x^2*y*z - 36*x*z^3 + 66*x^2*y - 432*x*z^2 - 1656*x*z - 2052*x                                      -x*y^4*z + 4*x*y^4 - 8*y^3*z^2 + 62*y^3*z - 114*y^3                                                                        48*y*z^2 - 36*y*z]
+
+            sage: M*G
+            (0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
+        
+        ALGORITHM: Uses Singular's syz command
+        """
+        import sage.libs.singular
+        syz = sage.libs.singular.ff.syz
+        from sage.matrix.constructor import matrix
+
+        #return self._singular_().syz().transpose().sage_matrix(self.ring())
+        S = syz(self)
+        return matrix(self.ring(), S)
+
+
+    def res(self, length):
+        r"""
+        Computes the first syzygy (i.e., the module of relations of the
+        given generators) of the ideal.
+        
+        EXAMPLE::
+        
+            sage: A.<x,y,z> = FreeAlgebra(QQ, 3)
+            sage: H = A.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y})
+            sage: H.inject_variables()
+            Defining x, y, z
+            sage: I = H.ideal([y^2, x^2, z^2-H.one_element()],coerce=False)
+            sage: I.res(3)
+            <Resolution>
+        """
+        return self.__call_singular('res', length)
+
 
 class MPolynomialIdeal( MPolynomialIdeal_singular_repr, \
                         MPolynomialIdeal_macaulay2_repr, \
diff -r 10f49e34d981 -r dc42cb80eeef sage/rings/polynomial/multi_polynomial_ideal_libsingular.pyx
--- a/sage/rings/polynomial/multi_polynomial_ideal_libsingular.pyx	Mon Sep 19 16:34:42 2011 -0700
+++ b/sage/rings/polynomial/multi_polynomial_ideal_libsingular.pyx	Sun Mar 13 15:24:15 2011 +0100
@@ -65,16 +65,20 @@
 from sage.libs.singular.decl cimport scKBase, poly, testHomog, idSkipZeroes, idRankFreeModule, kStd
 from sage.libs.singular.decl cimport OPT_REDTAIL, singular_options, kInterRed, t_rep_gb, p_GetCoeff
 from sage.libs.singular.decl cimport nInvers, pp_Mult_nn, p_Delete, n_Delete
+from sage.libs.singular.decl cimport rIsPluralRing
 
 from sage.structure.parent_base cimport ParentWithBase
 
 from sage.rings.polynomial.multi_polynomial_libsingular cimport new_MP
+from sage.rings.polynomial.plural cimport new_NCP
 
 from sage.rings.polynomial.multi_polynomial_ideal import MPolynomialIdeal
 from sage.rings.polynomial.multi_polynomial_libsingular cimport MPolynomial_libsingular
 from sage.rings.polynomial.multi_polynomial_libsingular cimport MPolynomialRing_libsingular
 from sage.structure.sequence import Sequence
 
+from sage.rings.polynomial.plural cimport NCPolynomialRing_plural, NCPolynomial_plural
+
 cdef object singular_ideal_to_sage_sequence(ideal *i, ring *r, object parent):
     """
     convert a SINGULAR ideal to a Sage Sequence (the format Sage
@@ -88,12 +92,18 @@
     """
     cdef int j
     cdef MPolynomial_libsingular p
+    cdef NCPolynomial_plural p_nc
                 
     l = []
 
-    for j from 0 <= j < IDELEMS(i):
-        p = new_MP(parent, p_Copy(i.m[j], r))
-        l.append( p )
+    if rIsPluralRing(r):
+        for j from 0 <= j < IDELEMS(i):
+            p_nc = new_NCP(parent, p_Copy(i.m[j], r))
+            l.append( p_nc )
+    else:
+        for j from 0 <= j < IDELEMS(i):
+            p = new_MP(parent, p_Copy(i.m[j], r))
+            l.append( p )
 
     return Sequence(l, check=False, immutable=True)
 
@@ -113,18 +123,26 @@
     cdef ideal *i
     cdef int j = 0
 
-    if not PY_TYPE_CHECK(R,MPolynomialRing_libsingular):
+    if PY_TYPE_CHECK(R,MPolynomialRing_libsingular):
+        r = (<MPolynomialRing_libsingular>R)._ring
+    elif PY_TYPE_CHECK(R, NCPolynomialRing_plural):
+        r = (<NCPolynomialRing_plural>R)._ring
+    else:
         raise TypeError("Ring must be of type 'MPolynomialRing_libsingular'")
-
-    r = (<MPolynomialRing_libsingular>R)._ring
+        
+    #r = (<MPolynomialRing_libsingular>R)._ring
     rChangeCurrRing(r);
 
     i = idInit(len(gens),1)
     for f in gens:
-        if not PY_TYPE_CHECK(f,MPolynomial_libsingular):
+        if PY_TYPE_CHECK(f,MPolynomial_libsingular):
+            i.m[j] = p_Copy((<MPolynomial_libsingular>f)._poly, r)
+        elif PY_TYPE_CHECK(f, NCPolynomial_plural):
+            i.m[j] = p_Copy((<NCPolynomial_plural>f)._poly, r)
+        else:
             id_Delete(&i, r)
             raise TypeError("All generators must be of type MPolynomial_libsingular.")
-        i.m[j] = p_Copy((<MPolynomial_libsingular>f)._poly, r)
+        #i.m[j] = p_Copy((<MPolynomial_libsingular>f)._poly, r)
         j+=1 
     return i
 
diff -r 10f49e34d981 -r dc42cb80eeef sage/rings/polynomial/multi_polynomial_libsingular.pyx
--- a/sage/rings/polynomial/multi_polynomial_libsingular.pyx	Mon Sep 19 16:34:42 2011 -0700
+++ b/sage/rings/polynomial/multi_polynomial_libsingular.pyx	Sun Mar 13 15:24:15 2011 +0100
@@ -2017,7 +2017,7 @@
         EXAMPLES::
 
             sage: P.<x,y,z>=PolynomialRing(QQ,3)
-            sage: 3/2*x + 1/2*y + 1
+            sage: 3/2*x + 1/2*y + 1 #indirect doctest
             3/2*x + 1/2*y + 1
 
         """
@@ -2034,7 +2034,7 @@
         EXAMPLES::
 
             sage: P.<x,y,z>=PolynomialRing(QQ,3)
-            sage: 3/2*x - 1/2*y - 1
+            sage: 3/2*x - 1/2*y - 1 #indirect doctest
             3/2*x - 1/2*y - 1
 
         """
@@ -2053,7 +2053,7 @@
         EXAMPLES::
 
             sage: P.<x,y,z>=PolynomialRing(QQ,3)
-            sage: 3/2*x
+            sage: 3/2*x # indirect doctest
             3/2*x
         """
 
@@ -2065,8 +2065,17 @@
         return new_MP((<MPolynomialRing_libsingular>self._parent),_p)
         
     cpdef ModuleElement _lmul_(self, RingElement right):
-        # all currently implemented rings are commutative
-        return self._rmul_(right)
+        """
+        Multiply left and right.
+
+        EXAMPLES::
+
+            sage: P.<x,y,z>=PolynomialRing(QQ,3)
+            sage: (3/2*x - 1/2*y - 1) * (3/2) # indirect doctest
+            9/4*x - 3/4*y - 3/2
+        """
+        # all currently implemented baser rings are commutative
+        return right._rmul_(self)
         
     cpdef RingElement  _mul_(left, RingElement right):
         """
@@ -2075,7 +2084,7 @@
         EXAMPLES::
 
             sage: P.<x,y,z>=PolynomialRing(QQ,3)
-            sage: (3/2*x - 1/2*y - 1) * (3/2*x + 1/2*y + 1)
+            sage: (3/2*x - 1/2*y - 1) * (3/2*x + 1/2*y + 1) # indirect doctest
             9/4*x^2 - 1/4*y^2 - y - 1
 
             sage: P.<x,y> = PolynomialRing(QQ,order='lex')
@@ -2098,7 +2107,7 @@
         EXAMPLES::
 
             sage: R.<x,y>=PolynomialRing(QQ,2)
-            sage: f = (x + y)/3
+            sage: f = (x + y)/3 # indirect doctest
             sage: f.parent()
             Multivariate Polynomial Ring in x, y over Rational Field
 
@@ -2274,7 +2283,7 @@
 
             sage: P.<x,y,z> = QQ[]
             sage: f = - 1*x^2*y - 25/27 * y^3 - z^2
-            sage: latex(f)
+            sage: latex(f)  # indirect doctest
             - x^{2} y - \frac{25}{27} y^{3} - z^{2}
         """
         cdef ring *_ring = (<MPolynomialRing_libsingular>self._parent)._ring
@@ -4248,7 +4257,7 @@
         EXAMPLES::
 
             sage: R.<x,y> = PolynomialRing(GF(7), 2)
-            sage: f = (x^3 + 2*y^2*x)^7; f
+            sage: f = (x^3 + 2*y^2*x)^7; f          # indirect doctest
             x^21 + 2*x^7*y^14
 
             sage: h = macaulay2(f); h               # optional
diff -r 10f49e34d981 -r dc42cb80eeef sage/rings/polynomial/plural.pxd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sage/rings/polynomial/plural.pxd	Sun Mar 13 15:24:15 2011 +0100
@@ -0,0 +1,40 @@
+include "../../libs/singular/singular-cdefs.pxi"
+
+from sage.rings.ring cimport Ring
+from sage.structure.element cimport RingElement, Element
+from sage.structure.parent cimport Parent
+from sage.libs.singular.function cimport RingWrap
+from sage.rings.polynomial.multi_polynomial_libsingular cimport MPolynomialRing_libsingular 
+
+
+cdef class NCPolynomialRing_plural(Ring):
+    cdef object __ngens
+    cdef object _c
+    cdef object _d
+    cdef object __term_order
+    cdef public object _has_singular
+    cdef public object _magma_gens, _magma_cache
+#    cdef _richcmp_c_impl(left, Parent right, int op)
+    cdef int _cmp_c_impl(left, Parent right) except -2
+    
+    cdef ring *_ring
+#    cdef NCPolynomial_plural _one_element
+#    cdef NCPolynomial_plural _zero_element
+    
+    cdef public object _relations
+    pass
+
+cdef class ExteriorAlgebra_plural(NCPolynomialRing_plural):
+    pass
+
+cdef class NCPolynomial_plural(RingElement):
+    cdef poly *_poly
+    cpdef _repr_short_(self)
+    cdef long _hash_c(self)
+    cpdef is_constant(self)
+#    cpdef _homogenize(self, int var)
+
+cdef NCPolynomial_plural new_NCP(NCPolynomialRing_plural parent, poly *juice)
+
+cpdef MPolynomialRing_libsingular new_CRing(RingWrap rw, base_ring)
+cpdef NCPolynomialRing_plural new_NRing(RingWrap rw, base_ring)
diff -r 10f49e34d981 -r dc42cb80eeef sage/rings/polynomial/plural.pyx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sage/rings/polynomial/plural.pyx	Sun Mar 13 15:24:15 2011 +0100
@@ -0,0 +1,2683 @@
+r"""
+Noncommutative Polynomials via libSINGULAR/Plural
+
+This module implements specialized and optimized implementations for
+noncommutative multivariate polynomials over many coefficient rings, via the
+shared library interface to SINGULAR. In particular, the following coefficient
+rings are supported by this implementation:
+
+- the rational numbers `\QQ`, and
+
+- finite fields `\GF{p}` for `p` prime
+
+AUTHORS:
+
+The PLURAL wrapper is due to
+
+  - Burcin Erocal (2008-11 and 2010-07): initial implementation and concept
+
+  - Michael Brickenstein (2008-11 and 2010-07): initial implementation and concept
+
+  - Oleksandr Motsak (2010-07): complete overall fnoncommutative unctionality and first release
+
+  - Alexander Dreyer (2010-07): noncommutative ring functionality and documentation
+
+The underlying libSINGULAR interface was implemented by
+
+- Martin Albrecht (2007-01): initial implementation
+
+- Joel Mohler (2008-01): misc improvements, polishing
+
+- Martin Albrecht (2008-08): added `\QQ(a)` and `\ZZ` support
+
+- Simon King (2009-04): improved coercion
+
+- Martin Albrecht (2009-05): added `\ZZ/n\ZZ` support, refactoring
+
+- Martin Albrecht (2009-06): refactored the code to allow better
+  re-use
+
+TODO:
+
+- extend functionality towards those of libSINGULARs commutative part
+
+EXAMPLES:
+
+We show how to construct various noncommutative polynomial rings::
+
+    sage: A.<x,y,z> = FreeAlgebra(QQ, 3)
+    sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex')
+    sage: P.inject_variables()
+    Defining x, y, z
+
+    sage: P
+    Noncommutative Multivariate Polynomial Ring in x, y, z over Rational Field, nc-relations: {y*x: -x*y}
+
+    sage: y*x + 1/2
+    -x*y + 1/2
+
+    sage: A.<x,y,z> = FreeAlgebra(GF(17), 3)
+    sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex')
+    sage: P.inject_variables()
+    Defining x, y, z
+
+    sage: P
+    Noncommutative Multivariate Polynomial Ring in x, y, z over Finite Field of size 17, nc-relations: {y*x: -x*y}
+
+    sage: y*x + 7
+    -x*y + 7
+    
+    
+Raw use of this class::
+    sage: from sage.matrix.constructor  import Matrix
+    sage: c = Matrix(3)
+    sage: c[0,1] = -2
+    sage: c[0,2] = 1
+    sage: c[1,2] = 1
+    
+    sage: d = Matrix(3)
+    sage: d[0, 1] = 17
+    
+    sage: from sage.rings.polynomial.plural import NCPolynomialRing_plural
+    sage: R.<x,y,z> = NCPolynomialRing_plural(QQ, 3, c = c, d = d, order='lex')
+    sage: R
+    Noncommutative Multivariate Polynomial Ring in x, y, z over Rational Field, nc-relations: {y*x: -2*x*y + 17}
+
+    sage: R.term_order()
+    Lexicographic term order
+
+    sage: a,b,c = R.gens()
+    sage: f = 57 * a^2*b + 43 * c + 1; f
+    57*x^2*y + 43*z + 1
+
+    sage: R.term_order()
+    Lexicographic term order
+
+TESTS::
+
+    sage: A.<x,y,z> = FreeAlgebra(QQ, 3)
+    sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex')
+    sage: P.inject_variables()
+    Defining x, y, z
+
+    sage: from sage.rings.polynomial.plural import NCPolynomialRing_plural, NCPolynomial_plural
+    sage: TestSuite(NCPolynomialRing_plural).run()
+    sage: TestSuite(NCPolynomial_plural).run()
+"""
+include "sage/ext/stdsage.pxi"
+include "sage/ext/interrupt.pxi"
+
+
+from sage.libs.singular.function cimport RingWrap
+from sage.structure.parent_base cimport ParentWithBase
+from sage.structure.parent_gens cimport ParentWithGens
+
+# singular rings
+from sage.libs.singular.ring cimport singular_ring_new, singular_ring_delete
+
+from sage.rings.integer cimport Integer
+from sage.structure.element cimport Element, ModuleElement
+
+from sage.libs.singular.polynomial cimport singular_polynomial_call, singular_polynomial_cmp, singular_polynomial_add, singular_polynomial_sub, singular_polynomial_neg, singular_polynomial_pow, singular_polynomial_mul, singular_polynomial_rmul
+from sage.libs.singular.polynomial cimport singular_polynomial_deg, singular_polynomial_str_with_changed_varnames, singular_polynomial_latex, singular_polynomial_str, singular_polynomial_div_coeff
+
+from sage.rings.polynomial.polydict import ETuple
+
+from sage.libs.singular.singular cimport si2sa, sa2si, overflow_check
+from sage.rings.integer_ring import ZZ
+from term_order import TermOrder
+
+
+from sage.rings.polynomial.multi_polynomial_libsingular cimport MPolynomialRing_libsingular
+#from sage.rings.polynomial.multi_polynomial_libsingular cimport addwithcarry
+from sage.rings.polynomial.multi_polynomial_ring_generic import MPolynomialRing_generic 
+
+
+from sage.structure.parent cimport Parent
+from sage.structure.element cimport CommutativeRingElement
+from sage.rings.finite_rings.finite_field_prime_modn import FiniteField_prime_modn
+from sage.rings.integer_ring import is_IntegerRing, ZZ
+
+cdef class NCPolynomialRing_plural(Ring):
+    def __init__(self, base_ring, n, names, c, d, order='degrevlex', check = True):
+        """
+        Construct a noncommutative polynomial G-algebra subject to the following conditions:
+
+        INPUT:
+
+        - ``base_ring`` - base ring (must be either GF(q), ZZ, ZZ/nZZ,
+                          QQ or absolute number field)
+
+        - ``n`` - number of variables (must be at least 1)
+
+        - ``names`` - names of ring variables, may be string of list/tuple
+
+        - ``c``, ``d``- upper triangular matrices of coefficients,
+        resp. commutative polynomials, satisfying the nondegeneracy conditions, which
+        are to be tested if check == True. These matrices describe the noncommutative
+        relations:      
+
+            self.gen(j)*self.gen(i) == c[i, j] * self.gen(i)*self.gen(j) + d[i, j], 
+
+        where 0 <= i < j < self.ngens()
+        
+        - ``order`` - term order (default: ``degrevlex``)
+
+        - ``check`` - check the noncommutative conditions (default: ``True``)
+
+        EXAMPLES::
+
+            sage: from sage.matrix.constructor  import Matrix
+            sage: c = Matrix(3)
+            sage: c[0,1] = -1
+            sage: c[0,2] = 1
+            sage: c[1,2] = 1
+
+            sage: d = Matrix(3)
+            sage: d[0, 1] = 17
+
+            sage: from sage.rings.polynomial.plural import NCPolynomialRing_plural
+            sage: P.<x,y,z> = NCPolynomialRing_plural(QQ, 3, c = c, d = d, order='lex')
+
+            sage: P # indirect doctest 
+            Noncommutative Multivariate Polynomial Ring in x, y, z over Rational Field, nc-relations: {y*x: -x*y + 17}
+
+            sage: P(x*y)
+            x*y
+
+            sage: f = 27/113 * x^2 + y*z + 1/2; f
+            27/113*x^2 + y*z + 1/2
+
+            sage: P.term_order()
+            Lexicographic term order
+
+            sage: from sage.rings.polynomial.plural import NCPolynomialRing_plural
+            sage: P.<x,y,z> = NCPolynomialRing_plural(GF(7), 3, c = c, d = d, order='degrevlex')
+
+            sage: P # indirect doctest 
+            Noncommutative Multivariate Polynomial Ring in x, y, z over Finite Field of size 7, nc-relations: {y*x: -x*y + 3}
+
+            sage: P(x*y)
+            x*y
+
+            sage: f = 3 * x^2 + y*z + 5; f
+            3*x^2 + y*z - 2
+
+            sage: P.term_order()
+            Degree reverse lexicographic term order
+
+        """
+
+        self._relations = None
+        n = int(n)
+        if n < 0:
+            raise ValueError, "Multivariate Polynomial Rings must " + \
+                  "have more than 0 variables."
+
+        from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
+
+        order = TermOrder(order,n)
+        P = PolynomialRing(base_ring, n, names, order=order)
+        
+        self._c = c.change_ring(P)
+        self._d = d.change_ring(P)
+
+        from sage.libs.singular.function import singular_function
+        ncalgebra = singular_function('nc_algebra')
+
+        cdef RingWrap rw = ncalgebra(self._c, self._d, ring = P)
+
+        #       rw._output()
+        self._ring = rw._ring
+        self._ring.ShortOut = 0
+
+        self.__ngens = n
+        self.__term_order = order
+
+        ParentWithGens.__init__(self, base_ring, names)
+        self._populate_coercion_lists_()
+        
+        #MPolynomialRing_generic.__init__(self, base_ring, n, names, order)
+        #self._has_singular = True
+        assert(n == len(self._names))
+        
+        self._one_element = new_NCP(self, p_ISet(1, self._ring))
+        self._zero_element = new_NCP(self, NULL)
+        
+
+        if check:
+            import sage.libs.singular
+            test = sage.libs.singular.ff.nctools__lib.ndcond(ring = self)
+            if (len(test) != 1) or (test[0] != 0):
+                raise ValueError, "NDC check failed!"
+
+    def __dealloc__(self):
+        r"""
+        Carefully deallocate the ring, without changing "currRing"
+        (since this method can be at unpredictable times due to garbage
+        collection).
+
+        TESTS:
+        This example caused a segmentation fault with a previous version
+        of this method:
+            sage: import gc
+            sage: from sage.rings.polynomial.plural import NCPolynomialRing_plural
+            sage: from sage.algebras.free_algebra import FreeAlgebra
+            sage: A1.<x,y,z> = FreeAlgebra(QQ, 3)
+            sage: R1 = A1.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y}, order=TermOrder('degrevlex', 2))
+            sage: A2.<x,y,z> = FreeAlgebra(GF(5), 3)
+            sage: R2 = A2.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y}, order=TermOrder('degrevlex', 2))
+            sage: A3.<x,y,z> = FreeAlgebra(GF(11), 3)
+            sage: R3 = A3.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y}, order=TermOrder('degrevlex', 2))
+            sage: A4.<x,y,z> = FreeAlgebra(GF(13), 3)
+            sage: R4 = A4.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y}, order=TermOrder('degrevlex', 2))
+            sage: _ = gc.collect()
+            sage: foo = R1.gen(0)
+            sage: del foo
+            sage: del R1
+            sage: _ = gc.collect()
+            sage: del R2
+            sage: _ = gc.collect()
+            sage: del R3
+            sage: _ = gc.collect()
+        """
+        singular_ring_delete(self._ring)
+    
+    def _element_constructor_(self, element):
+        """
+        Make sure element is a valid member of self, and return the constructed element. 
+
+        EXAMPLES::
+            sage: A.<x,y,z> = FreeAlgebra(QQ, 3)
+
+            sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex')
+
+        We can construct elements from the base ring::
+
+            sage: P(1/2)
+            1/2
+            
+
+        and all kinds of integers::
+
+            sage: P(17)
+            17
+
+            sage: P(int(19))
+            19
+
+            sage: P(long(19))
+            19
+            
+        TESTS::
+
+        Check conversion from self::
+            sage: A.<x,y,z> = FreeAlgebra(QQ, 3)
+            sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex')
+            sage: P.inject_variables()
+            Defining x, y, z
+
+            sage: P._element_constructor_(1/2)
+            1/2
+
+            sage: P._element_constructor_(x*y)
+            x*y
+
+            sage: P._element_constructor_(y*x)
+            -x*y         
+
+        Raw use of this class::
+            sage: from sage.matrix.constructor  import Matrix
+            sage: c = Matrix(3)
+            sage: c[0,1] = -2
+            sage: c[0,2] = 1
+            sage: c[1,2] = 1
+
+            sage: d = Matrix(3)
+            sage: d[0, 1] = 17
+
+            sage: from sage.rings.polynomial.plural import NCPolynomialRing_plural
+            sage: R.<x,y,z> = NCPolynomialRing_plural(QQ, 3, c = c, d = d, order='lex')
+            sage: R._element_constructor_(x*y)
+            x*y
+            
+            sage: P._element_constructor_(17)
+            17
+
+            sage: P._element_constructor_(int(19))
+            19
+
+        Testing special cases::
+            sage: P._element_constructor_(1)
+            1
+
+            sage: P._element_constructor_(0)
+            0
+        """
+
+        if element == 0:
+            return self._zero_element
+        if element == 1:
+            return self._one_element
+
+        cdef poly *_p
+        cdef ring *_ring,
+        cdef number *_n 
+       
+        _ring = self._ring
+       
+        base_ring = self.base_ring()
+
+        if(_ring != currRing): rChangeCurrRing(_ring)
+
+
+        if PY_TYPE_CHECK(element, NCPolynomial_plural):
+
+            if element.parent() is <object>self:
+                return element
+            elif element.parent() == self:
+                # is this safe?
+                _p = p_Copy((<NCPolynomial_plural>element)._poly, _ring)
+
+        elif PY_TYPE_CHECK(element, CommutativeRingElement):
+            # base ring elements
+            if  <Parent>element.parent() is base_ring:
+                # shortcut for GF(p)
+                if isinstance(base_ring, FiniteField_prime_modn):
+                    _p = p_ISet(int(element) % _ring.ch, _ring)
+                else: 
+                    _n = sa2si(element,_ring)
+                    _p = p_NSet(_n, _ring)
+                    
+            # also accepting ZZ
+            elif is_IntegerRing(element.parent()):
+                if isinstance(base_ring, FiniteField_prime_modn):
+                    _p = p_ISet(int(element),_ring)
+                else:
+                    _n = sa2si(base_ring(element),_ring)
+                    _p = p_NSet(_n, _ring)
+            else:
+                # fall back to base ring
+                element = base_ring._coerce_c(element)
+                _n = sa2si(element,_ring)
+                _p = p_NSet(_n, _ring)
+
+        # Accepting int
+        elif PY_TYPE_CHECK(element, int):
+            if isinstance(base_ring, FiniteField_prime_modn):
+                _p = p_ISet(int(element) % _ring.ch,_ring)
+            else:
+                _n = sa2si(base_ring(element),_ring)
+                _p = p_NSet(_n, _ring)
+                
+        # and longs
+        elif PY_TYPE_CHECK(element, long):
+            if isinstance(base_ring, FiniteField_prime_modn):
+                element = element % self.base_ring().characteristic()
+                _p = p_ISet(int(element),_ring)
+            else:
+                _n = sa2si(base_ring(element),_ring)
+                _p = p_NSet(_n, _ring)
+
+        else:
+            raise NotImplementedError("not able to constructor "+repr(element) +
+                                      " of type "+ repr(type(element))) #### ??????
+
+
+        return new_NCP(self,_p)
+
+
+        
+    cpdef _coerce_map_from_(self, S):
+       """
+       The only things that coerce into this ring are:
+           - the integer ring
+           - other localizations away from fewer primes
+
+         EXAMPLES::
+           sage: A.<x,y,z> = FreeAlgebra(QQ, 3)
+           sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex')
+
+           sage: P._coerce_map_from_(ZZ)
+           True
+       """
+
+       if self.base_ring().has_coerce_map_from(S):
+           return True
+       
+       
+       
+    def __hash__(self):
+       """
+       Return a hash for this noncommutative ring, that is, a hash of the string
+       representation of this polynomial ring.
+
+       EXAMPLES::
+           sage: A.<x,y,z> = FreeAlgebra(QQ, 3)
+           sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex')
+           sage: hash(P)      # somewhat random output
+           ...
+
+       TESTS::
+
+       Check conversion from self::
+           sage: A.<x,y,z> = FreeAlgebra(QQ, 3)
+           sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex')
+           sage: from sage.matrix.constructor  import Matrix
+           sage: c = Matrix(3)
+           sage: c[0,1] = -1
+           sage: c[0,2] = 1
+           sage: c[1,2] = 1
+
+           sage: from sage.rings.polynomial.plural import NCPolynomialRing_plural
+           sage: R.<x,y,z> = NCPolynomialRing_plural(QQ, 3, c = c, d = Matrix(3), order='lex')
+           sage: hash(R) == hash(P)
+           True
+       """
+       return hash(str(self.__repr__()) + str(self.term_order()) )
+
+
+    def __cmp__(self, right):
+        r"""
+        Multivariate polynomial rings are said to be equal if:
+        
+        - their base rings match,
+        - their generator names match,
+        - their term orderings match, and
+        - their relations match.
+
+
+        EXAMPLES::
+           sage: A.<x,y,z> = FreeAlgebra(QQ, 3)
+           sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex')
+
+           sage: P == P
+           True
+           sage: Q = A.g_algebra(relations={y*x:-x*y}, order = 'lex')
+           sage: Q == P
+           True
+                     
+           sage: from sage.matrix.constructor  import Matrix
+           sage: c = Matrix(3)
+           sage: c[0,1] = -1
+           sage: c[0,2] = 1
+           sage: c[1,2] = 1
+           sage: from sage.rings.polynomial.plural import NCPolynomialRing_plural
+           sage: R.<x,y,z> = NCPolynomialRing_plural(QQ, 3, c = c, d = Matrix(3), order='lex')
+           sage: R == P
+           True
+           
+           sage: c[0,1] = -2
+           sage: R.<x,y,z> = NCPolynomialRing_plural(QQ, 3, c = c, d = Matrix(3), order='lex')
+           sage: P == R
+           False
+        """
+
+        if PY_TYPE_CHECK(right, NCPolynomialRing_plural):
+
+            return cmp( (self.base_ring(), map(str, self.gens()),
+                         self.term_order(), self._c, self._d),
+                        (right.base_ring(), map(str, right.gens()),
+                         right.term_order(),
+                         (<NCPolynomialRing_plural>right)._c,
+                         (<NCPolynomialRing_plural>right)._d)
+                        )
+        else:
+            return cmp(type(self),type(right))
+
+    def __pow__(self, n, _):
+        """
+        Return the free module of rank `n` over this ring.
+
+        EXAMPLES::
+            sage: A.<x,y,z> = FreeAlgebra(QQ, 3)
+            sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex')
+            sage: P.inject_variables()
+            Defining x, y, z
+
+            sage: f = x^3 + y
+            sage: f^2
+            x^6 + y^2        
+        """
+        import sage.modules.all 
+        return sage.modules.all.FreeModule(self, n)
+    
+    def term_order(self):
+        """
+        Return the term ordering of the noncommutative ring.
+
+        EXAMPLES::
+        
+        sage: A.<x,y,z> = FreeAlgebra(QQ, 3)
+        sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex')
+        sage: P.term_order()
+        Lexicographic term order
+
+        sage: P = A.g_algebra(relations={y*x:-x*y})
+        sage: P.term_order()
+        Degree reverse lexicographic term order
+        """
+        return self.__term_order
+
+    def is_commutative(self):
+        """
+        Return False.
+
+        EXAMPLES::
+        
+        sage: A.<x,y,z> = FreeAlgebra(QQ, 3)
+        sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex')
+        sage: P.is_commutative()
+        False
+        """
+        return False
+    
+    def is_field(self):
+        """
+        Return False.
+
+        EXAMPLES::
+        
+        sage: A.<x,y,z> = FreeAlgebra(QQ, 3)
+        sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex')
+        sage: P.is_field()
+        False
+        """    
+        return False
+    
+    def _repr_(self):
+        """
+        EXAMPLE:
+            sage: from sage.rings.polynomial.plural import NCPolynomialRing_plural
+            sage: from sage.matrix.constructor  import Matrix
+            sage: c=Matrix(2)
+            sage: c[0,1]=-1
+            sage: P.<x,y> = NCPolynomialRing_plural(QQ, 2, c=c, d=Matrix(2))
+            sage: P # indirect doctest
+            Noncommutative Multivariate Polynomial Ring in x, y over Rational Field, nc-relations: {y*x: -x*y}
+            sage: x*y
+            x*y
+            sage: y*x
+            -x*y
+        """
+#TODO: print the relations
+        varstr = ", ".join([ rRingVar(i,self._ring)  for i in range(self.__ngens) ])
+        return "Noncommutative Multivariate Polynomial Ring in %s over %s, nc-relations: %s"%(varstr,self.base_ring(), self.relations())
+
+
+    def _ringlist(self):
+        """
+        Return an internal list representation of the noncummutative ring.
+
+        EXAMPLES::
+        sage: A.<x,y,z> = FreeAlgebra(QQ, 3)
+        sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex')
+        sage: P._ringlist()
+        [0, ['x', 'y', 'z'], [['lp', (1, 1, 1)], ['C', (0,)]], [0], [ 0 -1  1]
+        [ 0  0  1]
+        [ 0  0  0], [0 0 0]
+        [0 0 0]
+        [0 0 0]]
+        """
+        cdef ring* _ring = self._ring
+        if(_ring != currRing): rChangeCurrRing(_ring)
+        from sage.libs.singular.function import singular_function
+        ringlist = singular_function('ringlist')
+        result = ringlist(self, ring=self)
+       
+
+
+
+        return result
+        
+
+    def relations(self, add_commutative = False):
+        """
+        EXAMPLE:
+            sage: from sage.rings.polynomial.plural import NCPolynomialRing_plural
+            sage: from sage.matrix.constructor  import Matrix
+            sage: c=Matrix(2)
+            sage: c[0,1]=-1
+            sage: P = NCPolynomialRing_plural(QQ, 2, 'x,y', c=c, d=Matrix(2))
+            sage: P # indirect doctest
+            Noncommutative Multivariate Polynomial Ring in x, y over Rational Field, nc-relations: ...
+        """
+        if self._relations is not None:
+            return self._relations
+
+        from sage.algebras.free_algebra import FreeAlgebra
+        A = FreeAlgebra( self.base_ring(), self.ngens(), self.gens() )
+
+        res = {}
+        n = self.ngens()
+        for r in range(0, n-1, 1):
+            for c in range(r+1, n, 1):
+                if  (self.gen(c) * self.gen(r) != self.gen(r) * self.gen(c)) or add_commutative:
+                    res[ A.gen(c) * A.gen(r) ] = self.gen(c) * self.gen(r) # C[r, c] * P.gen(r) * P.gen(c) + D[r, c]
+        
+            
+        self._relations = res
+        return self._relations
+
+    def ngens(self):
+        """
+        Returns the number of variables in this noncommutative polynomial ring.
+
+        EXAMPLES::
+
+            sage: A.<x,y,z> = FreeAlgebra(QQ, 3)
+            sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex')
+            sage: P.inject_variables()
+            Defining x, y, z
+
+            sage: P.ngens()
+            3
+        """
+        return int(self.__ngens)
+
+    def gen(self, int n=0):
+        """
+        Returns the ``n``-th generator of this noncommutative polynomial
+        ring.
+
+        INPUT:
+
+        - ``n`` -- an integer ``>= 0``
+
+        EXAMPLES::
+
+            sage: A.<x,y,z> = FreeAlgebra(QQ, 3)
+            sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex')
+            sage: P.gen(),P.gen(1)
+            (x, y)          
+
+            sage: P.gen(1)
+            y
+        """
+        cdef poly *_p
+        cdef ring *_ring = self._ring
+
+        if n < 0 or n >= self.__ngens:
+            raise ValueError, "Generator not defined."
+
+        rChangeCurrRing(_ring)
+        _p = p_ISet(1,_ring)
+        p_SetExp(_p, n+1, 1, _ring)
+        p_Setm(_p, _ring);
+
+        return new_NCP(self,_p)
+
+    def ideal(self, *gens, **kwds):
+        """
+        Create an ideal in this polynomial ring.
+
+        INPUT:
+ 
+        - ``*gens`` - list or tuple of generators (or several input arguments)
+
+        - ``coerce`` - bool (default: ``True``); this must be a
+          keyword argument. Only set it to ``False`` if you are certain
+          that each generator is already in the ring.
+
+        EXAMPLES::
+            sage: A.<x,y,z> = FreeAlgebra(QQ, 3)
+            sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex')
+            sage: P.inject_variables()
+            Defining x, y, z
+            
+            sage: P.ideal([x + 2*y + 2*z-1, 2*x*y + 2*y*z-y, x^2 + 2*y^2 + 2*z^2-x])
+            Ideal (x + 2*y + 2*z - 1, 2*x*y + 2*y*z - y, x^2 - x + 2*y^2 + 2*z^2) of Noncommutative Multivariate Polynomial Ring in x, y, z over Rational Field, nc-relations: {y*x: -x*y}
+        """
+        from sage.rings.polynomial.multi_polynomial_ideal import \
+                NCPolynomialIdeal
+        coerce = kwds.get('coerce', True)
+        if len(gens) == 1:
+            gens = gens[0]
+        #if is_SingularElement(gens):
+        #    gens = list(gens)
+        #    coerce = True
+        #elif is_Macaulay2Element(gens):
+        #    gens = list(gens)
+        #    coerce = True
+        if not isinstance(gens, (list, tuple)):
+            gens = [gens]
+        if coerce:
+            gens = [self(x) for x in gens]  # this will even coerce from singular ideals correctly!
+        return NCPolynomialIdeal(self, gens, coerce=False)
+
+    def _list_to_ring(self, L):
+        """
+        Convert internal list representation to  noncommutative ring.
+
+        EXAMPLES::
+
+           sage: A.<x,y,z> = FreeAlgebra(QQ, 3)
+           sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex')
+           sage: rlist = P._ringlist();
+           sage: Q = P._list_to_ring(rlist)
+           sage: Q # indirect doctest
+           <noncommutative RingWrap>
+        """
+
+        cdef ring* _ring = self._ring
+        if(_ring != currRing): rChangeCurrRing(_ring)
+        
+        from sage.libs.singular.function import singular_function
+        ring = singular_function('ring')
+        return ring(L, ring=self)
+
+    def quotient(self, I):
+        """
+        Construct quotient ring of ``self`` and the two-sided Groebner basis of `ideal`
+
+        EXAMPLE::
+
+        sage: A.<x,y,z> = FreeAlgebra(QQ, 3)
+        sage: H = A.g_algebra(relations={y*x:-x*y},  order='lex')
+        sage: I = H.ideal([H.gen(i) ^2 for i in [0, 1]]).twostd()
+
+        sage: Q = H.quotient(I); Q
+        Noncommutative Multivariate Polynomial Ring in x, y, z over Rational Field, nc-relations: {y*x: -x*y}
+
+        TESTS::
+
+        check coercion bug::
+        sage: A.<x,y,z> = FreeAlgebra(QQ, 3)      
+        sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex')
+        sage: rlist = P._ringlist();
+        sage: A.<x,y,z> = FreeAlgebra(QQ, 3)
+        sage: H = A.g_algebra(relations={y*x:-x*y},  order='lex')
+        sage: I = H.ideal([H.gen(i) ^2 for i in [0, 1]]).twostd()
+        sage: Q = H.quotient(I); Q
+        Noncommutative Multivariate Polynomial Ring in x, y, z over Rational Field, nc-relations: {y*x: -x*y}
+        sage: Q.gen(0)^2
+        0
+        sage: Q.gen(1) * Q.gen(0)
+        -x*y
+        """
+        L = self._ringlist()
+        L[3] = I.twostd()
+        W = self._list_to_ring(L)
+        return new_NRing(W, self.base_ring())
+
+
+    ### The following methods are handy for implementing Groebner
+    ### basis algorithms. They do only superficial type/sanity checks
+    ### and should be called carefully.
+
+    def monomial_quotient(self, NCPolynomial_plural f, NCPolynomial_plural g, coeff=False):
+        r"""
+        Return ``f/g``, where both ``f`` and`` ``g`` are treated as
+        monomials. 
+
+        Coefficients are ignored by default.
+
+        INPUT:
+
+        - ``f`` - monomial
+        - ``g`` - monomial
+        - ``coeff`` - divide coefficients as well (default: ``False``)
+
+        EXAMPLES::
+
+            sage: A.<x,y,z> = FreeAlgebra(QQ, 3)
+            sage: P = A.g_algebra(relations={y*x:-x*y},  order='lex')
+            sage: P.inject_variables()
+            Defining x, y, z
+
+            sage: P.monomial_quotient(3/2*x*y,x,coeff=True)
+            3/2*y
+
+        Note, that `\ZZ` behaves different if ``coeff=True``::
+
+            sage: P.monomial_quotient(2*x,3*x)
+            1
+            sage: P.monomial_quotient(2*x,3*x,coeff=True)
+            2/3
+
+        TESTS::
+            sage: A.<x,y,z> = FreeAlgebra(QQ, 3)
+            sage: R = A.g_algebra(relations={y*x:-x*y},  order='lex')
+            sage: R.inject_variables()
+            Defining x, y, z
+        
+            sage: A.<x,y,z> = FreeAlgebra(QQ, 3)
+            sage: P = A.g_algebra(relations={y*x:-x*y},  order='lex')
+            sage: P.inject_variables()
+            Defining x, y, z
+            
+            sage: P.monomial_quotient(x*y,x)
+            y
+
+##             sage: P.monomial_quotient(x*y,R.gen())
+##             y
+
+            sage: P.monomial_quotient(P(0),P(1))
+            0
+
+            sage: P.monomial_quotient(P(1),P(0))
+            Traceback (most recent call last):
+            ...
+            ZeroDivisionError
+
+            sage: P.monomial_quotient(P(3/2),P(2/3), coeff=True)
+            9/4
+
+            sage: P.monomial_quotient(x,P(1))
+            x
+
+        TESTS::
+
+            sage: P.monomial_quotient(x,y) # Note the wrong result
+            x*y^1048575*z^1048575 # 64-bit
+            x*y^65535 # 32-bit  
+
+        .. warning::
+
+           Assumes that the head term of f is a multiple of the head
+           term of g and return the multiplicant m. If this rule is
+           violated, funny things may happen.
+        """
+        cdef poly *res
+        cdef ring *r = self._ring
+        cdef number *n, *denom
+        
+        if not <ParentWithBase>self is f._parent:
+            f = self._coerce_c(f)
+        if not <ParentWithBase>self is g._parent:
+            g = self._coerce_c(g)
+
+        if(r != currRing): rChangeCurrRing(r)
+
+        if not f._poly:
+            return self._zero_element
+        if not g._poly:
+            raise ZeroDivisionError
+
+        res = pDivide(f._poly,g._poly)
+        if coeff:
+            if r.ringtype == 0 or r.cf.nDivBy(p_GetCoeff(f._poly, r), p_GetCoeff(g._poly, r)):
+                n = r.cf.nDiv( p_GetCoeff(f._poly, r) , p_GetCoeff(g._poly, r))
+                p_SetCoeff0(res, n, r)
+            else:
+                raise ArithmeticError("Cannot divide these coefficients.")
+        else:
+            p_SetCoeff0(res, n_Init(1, r), r)
+        return new_NCP(self, res)
+    
+    def monomial_divides(self, NCPolynomial_plural a, NCPolynomial_plural b):
+        """
+        Return ``False`` if a does not divide b and ``True``
+        otherwise. 
+
+        Coefficients are ignored.
+        
+        INPUT:
+
+        - ``a`` -- monomial
+
+        - ``b`` -- monomial
+
+        EXAMPLES::
+
+            sage: A.<x,y,z> = FreeAlgebra(QQ, 3)
+            sage: P = A.g_algebra(relations={y*x:-x*y},  order='lex')
+            sage: P.inject_variables()
+            Defining x, y, z
+
+            sage: P.monomial_divides(x*y*z, x^3*y^2*z^4)
+            True
+            sage: P.monomial_divides(x^3*y^2*z^4, x*y*z)
+            False
+
+        TESTS::
+            sage: A.<x,y,z> = FreeAlgebra(QQ, 3)
+            sage: Q = A.g_algebra(relations={y*x:-x*y},  order='lex')
+            sage: Q.inject_variables()
+            Defining x, y, z
+            
+            sage: A.<x,y,z> = FreeAlgebra(QQ, 3)
+            sage: P = A.g_algebra(relations={y*x:-x*y},  order='lex')
+            sage: P.inject_variables()
+            Defining x, y, z
+            
+            sage: P.monomial_divides(P(1), P(0))
+            True
+            sage: P.monomial_divides(P(1), x)
+            True
+        """
+        cdef poly *_a
+        cdef poly *_b
+        cdef ring *_r
+        if a._parent is not b._parent:
+            b = (<NCPolynomialRing_plural>a._parent)._coerce_c(b)
+
+        _a = a._poly
+        _b = b._poly
+        _r = (<NCPolynomialRing_plural>a._parent)._ring
+
+        if _a == NULL:
+            raise ZeroDivisionError
+        if _b == NULL:
+            return True
+        
+        if not p_DivisibleBy(_a, _b, _r):
+            return False
+        else:
+            return True
+
+
+    def monomial_lcm(self, NCPolynomial_plural f, NCPolynomial_plural g):
+        """
+        LCM for monomials. Coefficients are ignored.
+        
+        INPUT:
+
+        - ``f`` - monomial
+        
+        - ``g`` - monomial
+
+        EXAMPLES::
+
+            sage: A.<x,y,z> = FreeAlgebra(QQ, 3)
+            sage: P = A.g_algebra(relations={y*x:-x*y},  order='lex')
+            sage: P.inject_variables()
+            Defining x, y, z
+            
+            sage: P.monomial_lcm(3/2*x*y,x)
+            x*y
+
+        TESTS::
+
+            sage: A.<x,y,z> = FreeAlgebra(QQ, 3)
+            sage: R = A.g_algebra(relations={y*x:-x*y},  order='lex')
+            sage: R.inject_variables()
+            Defining x, y, z
+            
+            sage: A.<x,y,z> = FreeAlgebra(QQ, 3)
+            sage: P = A.g_algebra(relations={y*x:-x*y},  order='lex')
+            sage: P.inject_variables()
+            Defining x, y, z
+            
+##             sage: P.monomial_lcm(x*y,R.gen())
+##             x*y
+
+            sage: P.monomial_lcm(P(3/2),P(2/3))
+            1
+
+            sage: P.monomial_lcm(x,P(1))
+            x
+        """
+        cdef poly *m = p_ISet(1,self._ring)
+        
+        if not <ParentWithBase>self is f._parent:
+            f = self._coerce_c(f)
+        if not <ParentWithBase>self is g._parent:
+            g = self._coerce_c(g)
+
+        if f._poly == NULL:
+            if g._poly == NULL:
+                return self._zero_element
+            else:
+                raise ArithmeticError, "Cannot compute LCM of zero and nonzero element."
+        if g._poly == NULL:
+            raise ArithmeticError, "Cannot compute LCM of zero and nonzero element."
+
+        if(self._ring != currRing): rChangeCurrRing(self._ring)
+        
+        pLcm(f._poly, g._poly, m)
+        p_Setm(m, self._ring)
+        return new_NCP(self,m)
+        
+    def monomial_reduce(self, NCPolynomial_plural f, G):
+        """
+        Try to find a ``g`` in ``G`` where ``g.lm()`` divides
+        ``f``. If found ``(flt,g)`` is returned, ``(0,0)`` otherwise,
+        where ``flt`` is ``f/g.lm()``.
+
+        It is assumed that ``G`` is iterable and contains *only*
+        elements in this polynomial ring.
+
+        Coefficients are ignored.
+        
+        INPUT:
+
+        - ``f`` - monomial
+        - ``G`` - list/set of mpolynomials
+            
+        EXAMPLES::
+
+            sage: A.<x,y,z> = FreeAlgebra(QQ, 3)
+            sage: P = A.g_algebra(relations={y*x:-x*y},  order='lex')
+            sage: P.inject_variables()
+            Defining x, y, z
+
+            sage: f = x*y^2
+            sage: G = [ 3/2*x^3 + y^2 + 1/2, 1/4*x*y + 2/7, 1/2  ]
+            sage: P.monomial_reduce(f,G)
+            (y, 1/4*x*y + 2/7)
+
+        TESTS::
+            sage: A.<x,y,z> = FreeAlgebra(QQ, 3)
+            sage: Q = A.g_algebra(relations={y*x:-x*y},  order='lex')
+            sage: Q.inject_variables()
+            Defining x, y, z
+            
+            sage: A.<x,y,z> = FreeAlgebra(QQ, 3)
+            sage: P = A.g_algebra(relations={y*x:-x*y},  order='lex')
+            sage: P.inject_variables()
+            Defining x, y, z
+            sage: f = x*y^2
+            sage: G = [ 3/2*x^3 + y^2 + 1/2, 1/4*x*y + 2/7, 1/2  ]
+
+            sage: P.monomial_reduce(P(0),G)
+            (0, 0)
+
+            sage: P.monomial_reduce(f,[P(0)])
+            (0, 0)
+        """
+        cdef poly *m = f._poly
+        cdef ring *r = self._ring
+        cdef poly *flt
+
+        if not m:
+            return f,f
+        
+        for g in G:
+            if PY_TYPE_CHECK(g, NCPolynomial_plural) \
+                   and (<NCPolynomial_plural>g) \
+                   and p_LmDivisibleBy((<NCPolynomial_plural>g)._poly, m, r):
+                flt = pDivide(f._poly, (<NCPolynomial_plural>g)._poly)
+                #p_SetCoeff(flt, n_Div( p_GetCoeff(f._poly, r) , p_GetCoeff((<NCPolynomial_plural>g)._poly, r), r), r)
+                p_SetCoeff(flt, n_Init(1, r), r)
+                return new_NCP(self,flt), g
+        return self._zero_element,self._zero_element
+
+    def monomial_pairwise_prime(self, NCPolynomial_plural g, NCPolynomial_plural h):
+        """
+        Return ``True`` if ``h`` and ``g`` are pairwise prime. Both
+        are treated as monomials.
+
+        Coefficients are ignored.
+
+        INPUT:
+
+        - ``h`` - monomial
+        - ``g`` - monomial
+
+        EXAMPLES::
+
+            sage: A.<x,y,z> = FreeAlgebra(QQ, 3)
+            sage: P = A.g_algebra(relations={y*x:-x*y},  order='lex')
+            sage: P.inject_variables()
+            Defining x, y, z
+
+            sage: P.monomial_pairwise_prime(x^2*z^3, y^4)
+            True
+
+            sage: P.monomial_pairwise_prime(1/2*x^3*y^2, 3/4*y^3)
+            False
+
+        TESTS::
+
+            sage: A.<x1,y1,z1> = FreeAlgebra(QQ, 3)
+            sage: Q = A.g_algebra(relations={y1*x1:-x1*y1},  order='lex')
+            sage: Q.inject_variables()
+            Defining x1, y1, z1
+
+            sage: A.<x,y,z> = FreeAlgebra(QQ, 3)
+            sage: P = A.g_algebra(relations={y*x:-x*y},  order='lex')
+            sage: P.inject_variables()
+            Defining x, y, z
+
+##            sage: P.monomial_pairwise_prime(x^2*z^3, x1^4)
+##            True
+
+##            sage: P.monomial_pairwise_prime((2)*x^3*y^2, Q.zero_element())
+##            True
+
+            sage: P.monomial_pairwise_prime(2*P.one_element(),x)
+            False
+        """
+        cdef int i
+        cdef ring *r
+        cdef poly *p, *q
+
+        if h._parent is not g._parent:
+            g = (<NCPolynomialRing_plural>h._parent)._coerce_c(g)
+
+        r = (<NCPolynomialRing_plural>h._parent)._ring
+        p = g._poly
+        q = h._poly
+
+        if p == NULL:
+            if q == NULL:
+                return False #GCD(0,0) = 0
+            else:
+                return True #GCD(x,0) = 1
+
+        elif q == NULL:
+            return True # GCD(0,x) = 1
+
+        elif p_IsConstant(p,r) or p_IsConstant(q,r): # assuming a base field
+            return False
+
+        for i from 1 <= i <= r.N:
+            if p_GetExp(p,i,r) and p_GetExp(q,i,r):
+                return False
+        return True
+
+    def monomial_all_divisors(self, NCPolynomial_plural t):
+        """
+        Return a list of all monomials that divide ``t``.
+
+        Coefficients are ignored.
+          
+        INPUT:
+
+        - ``t`` - a monomial
+  
+        OUTPUT:
+            a list of monomials
+
+
+        EXAMPLES::
+
+            sage: A.<x,y,z> = FreeAlgebra(QQ, 3)
+            sage: P = A.g_algebra(relations={y*x:-x*y},  order='lex')
+            sage: P.inject_variables()
+            Defining x, y, z
+
+            sage: P.monomial_all_divisors(x^2*z^3)
+            [x, x^2, z, x*z, x^2*z, z^2, x*z^2, x^2*z^2, z^3, x*z^3, x^2*z^3]
+            
+        ALGORITHM: addwithcarry idea by Toon Segers
+        """
+
+        M = list()
+
+        cdef ring *_ring = self._ring
+        cdef poly *maxvector = t._poly
+        cdef poly *tempvector = p_ISet(1, _ring)
+         
+        pos = 1
+         
+        while not p_ExpVectorEqual(tempvector, maxvector, _ring):
+          tempvector = addwithcarry(tempvector, maxvector, pos, _ring)
+          M.append(new_NCP(self, p_Copy(tempvector,_ring)))
+        return M
+
+
+
+cdef class NCPolynomial_plural(RingElement):
+    """
+    A noncommutative multivariate polynomial implemented using libSINGULAR.
+    """
+    def __init__(self, NCPolynomialRing_plural parent):
+        """
+        Construct a zero element in parent.
+
+        EXAMPLES::
+
+            sage: A.<x,z,y> = FreeAlgebra(QQ, 3)
+            sage: H = A.g_algebra(relations={y*x:-x*y},  order='lex')
+            sage: from sage.rings.polynomial.plural import NCPolynomial_plural
+            sage: NCPolynomial_plural(H)
+            0
+        """
+        self._poly = NULL
+        self._parent = <ParentWithBase>parent
+
+    def __dealloc__(self):
+        # TODO: Warn otherwise!
+        # for some mysterious reason, various things may be NULL in some cases
+        if self._parent is not <ParentWithBase>None and (<NCPolynomialRing_plural>self._parent)._ring != NULL and self._poly != NULL:
+            p_Delete(&self._poly, (<NCPolynomialRing_plural>self._parent)._ring)
+
+#    def __call__(self, *x, **kwds): # ?
+
+    # you may have to replicate this boilerplate code in derived classes if you override 
+    # __richcmp__.  The python documentation at  http://docs.python.org/api/type-structs.html 
+    # explains how __richcmp__, __hash__, and __cmp__ are tied together.
+    def __hash__(self):
+        """
+        This hash incorporates the variable name in an effort to
+        respect the obvious inclusions into multi-variable polynomial
+        rings.
+
+        The tuple algorithm is borrowed from http://effbot.org/zone/python-hash.htm.
+
+        EXAMPLES::
+
+            sage: R.<x>=QQ[]
+            sage: S.<x,y>=QQ[]
+            sage: hash(S(1/2))==hash(1/2)  # respect inclusions of the rationals
+            True
+            sage: hash(S.0)==hash(R.0)  # respect inclusions into mpoly rings
+            True
+            sage: # the point is to make for more flexible dictionary look ups
+            sage: d={S.0:12}
+            sage: d[R.0]
+            12
+        """
+        return self._hash_c()
+
+    def __richcmp__(left, right, int op):
+        """
+        Compare left and right and return -1, 0, and 1 for <,==, and >
+        respectively.
+
+        EXAMPLES::
+
+            sage: A.<x,z,y> = FreeAlgebra(QQ, 3)
+            sage: P = A.g_algebra(relations={y*x:-x*y},  order='lex')
+            sage: P.inject_variables()
+            Defining x, z, y
+
+            sage: x == x
+            True
+
+            sage: x > y
+            True
+            sage: y^2 > x
+            False
+
+##            sage: (2/3*x^2 + 1/2*y + 3) > (2/3*x^2 + 1/4*y + 10)
+#            True
+
+        TESTS::
+
+            sage: A.<x,z,y> = FreeAlgebra(QQ, 3)
+            sage: P = A.g_algebra(relations={y*x:-x*y},  order='lex')
+            sage: P.inject_variables()
+            Defining x, z, y
+
+            sage: x > P(0)
+            True
+
+            sage: P(0) == P(0)
+            True
+
+            sage: P(0) < P(1)
+            True
+
+            sage: x > P(1)
+            True
+            
+            sage: 1/2*x < 3/4*x
+            True
+
+            sage: (x+1) > x
+            True
+
+#            sage: f = 3/4*x^2*y + 1/2*x + 2/7
+#            sage: f > f
+#            False
+#            sage: f < f
+#            False
+#            sage: f == f
+#            True
+
+#            sage: P.<x,y,z> = PolynomialRing(GF(127), order='degrevlex')
+#            sage: (66*x^2 + 23) > (66*x^2 + 2)
+#            True
+        """
+        return (<Element>left)._richcmp(right, op)
+
+    cdef int _cmp_c_impl(left, Element right) except -2:
+        if left is right:
+            return 0
+        cdef poly *p = (<NCPolynomial_plural>left)._poly
+        cdef poly *q = (<NCPolynomial_plural>right)._poly
+        cdef ring *r = (<NCPolynomialRing_plural>left._parent)._ring
+        return singular_polynomial_cmp(p, q, r)
+
+    cpdef ModuleElement _add_( left, ModuleElement right):
+        """
+        Adds left and right.
+
+        EXAMPLES::
+
+            sage: A.<x,z,y> = FreeAlgebra(QQ, 3)
+            sage: P = A.g_algebra(relations={y*x:-x*y + z},  order='lex')
+            sage: P.inject_variables()
+            Defining x, z, y
+            sage: 3/2*x + 1/2*y + 1 # indirect doctest
+            3/2*x + 1/2*y + 1
+        """
+        cdef poly *_p
+        singular_polynomial_add(&_p, left._poly, 
+                                 (<NCPolynomial_plural>right)._poly,
+                                 (<NCPolynomialRing_plural>left._parent)._ring)
+        return new_NCP((<NCPolynomialRing_plural>left._parent), _p)
+
+    cpdef ModuleElement _sub_( left, ModuleElement right):
+        """
+        Subtract left and right.
+
+        EXAMPLES::
+
+            sage: A.<x,z,y> = FreeAlgebra(QQ, 3)
+            sage: P = A.g_algebra(relations={y*x:-x*y + z},  order='lex')
+            sage: P.inject_variables()
+            Defining x, z, y
+            sage: 3/2*x - 1/2*y - 1 # indirect doctest
+            3/2*x - 1/2*y - 1
+
+        """
+        cdef ring *_ring = (<NCPolynomialRing_plural>left._parent)._ring
+
+        cdef poly *_p
+        singular_polynomial_sub(&_p, left._poly, 
+                                (<NCPolynomial_plural>right)._poly,
+                                _ring)
+        return new_NCP((<NCPolynomialRing_plural>left._parent), _p)
+
+    cpdef ModuleElement _rmul_(self, RingElement left):
+        """
+        Multiply self with a base ring element.
+
+        EXAMPLES::
+
+            sage: A.<x,z,y> = FreeAlgebra(QQ, 3)
+            sage: P = A.g_algebra(relations={y*x:-x*y + z},  order='lex')
+            sage: P.inject_variables()
+            Defining x, z, y
+            sage: 3/2*x # indirect doctest
+            3/2*x
+        """
+
+        cdef ring *_ring = (<NCPolynomialRing_plural>self._parent)._ring
+        if not left:
+            return (<NCPolynomialRing_plural>self._parent)._zero_element
+        cdef poly *_p
+        singular_polynomial_rmul(&_p, self._poly, left, _ring)
+        return new_NCP((<NCPolynomialRing_plural>self._parent),_p)
+        
+    cpdef ModuleElement _lmul_(self, RingElement right):
+        """
+        Multiply self with a base ring element.
+
+        EXAMPLES::
+
+            sage: A.<x,z,y> = FreeAlgebra(QQ, 3)
+            sage: P = A.g_algebra(relations={y*x:-x*y + z},  order='lex')
+            sage: P.inject_variables()
+            Defining x, z, y
+            sage: x* (2/3) # indirect doctest
+            2/3*x
+        """
+        return self._rmul_(right)
+        
+    cpdef RingElement  _mul_(left, RingElement right):
+        """
+        Multiply left and right.
+
+        EXAMPLES::
+
+            sage: A.<x,z,y> = FreeAlgebra(QQ, 3)
+            sage: P = A.g_algebra(relations={y*x:-x*y + z},  order='lex')
+            sage: P.inject_variables()
+            Defining x, z, y
+            sage: (3/2*x - 1/2*y - 1) * (3/2*x + 1/2*y + 1) # indirect doctest
+            9/4*x^2 + 3/2*x*y - 3/4*z - 1/4*y^2 - y - 1
+
+        TEST::
+        
+            sage: A.<x,z,y> = FreeAlgebra(QQ, 3)
+            sage: P = A.g_algebra(relations={y*x:-x*y + z},  order='lex')
+            sage: P.inject_variables()
+            Defining x, z, y
+            sage: (x^2^30) * x^2^30
+            Traceback (most recent call last):
+            ...
+            OverflowError: Exponent overflow (...).
+        """
+        # all currently implemented rings are commutative
+        cdef poly *_p
+        singular_polynomial_mul(&_p, left._poly, 
+                                 (<NCPolynomial_plural>right)._poly, 
+                                 (<NCPolynomialRing_plural>left._parent)._ring)
+        return new_NCP((<NCPolynomialRing_plural>left._parent),_p)
+
+    cpdef RingElement _div_(left, RingElement right):
+        """
+        Divide left by right
+
+        EXAMPLES::
+
+            sage: A.<x,z,y> = FreeAlgebra(QQ, 3)
+            sage: R = A.g_algebra(relations={y*x:-x*y + z},  order='lex')
+            sage: R.inject_variables()
+            Defining x, z, y
+            sage: f = (x + y)/3 # indirect doctest
+            sage: f.parent()
+            Noncommutative Multivariate Polynomial Ring in x, z, y over Rational Field, nc-relations: {y*x: -x*y + z}
+
+        TESTS::
+
+            sage: A.<x,z,y> = FreeAlgebra(QQ, 3)
+            sage: R = A.g_algebra(relations={y*x:-x*y + z},  order='lex')
+            sage: R.inject_variables()
+            Defining x, z, y
+            sage: x/0
+            Traceback (most recent call last):
+            ...
+            ZeroDivisionError: rational division by zero
+        """
+        cdef poly *p 
+        cdef bint is_field = left._parent._base.is_field()
+        if p_IsConstant((<NCPolynomial_plural>right)._poly, (<NCPolynomialRing_plural>right._parent)._ring):
+            if is_field:
+                singular_polynomial_div_coeff(&p, left._poly, (<NCPolynomial_plural>right)._poly, (<NCPolynomialRing_plural>right._parent)._ring)
+                return new_NCP(left._parent, p)
+            else:
+                return left.change_ring(left.base_ring().fraction_field())/right
+        else:
+            return (<NCPolynomialRing_plural>left._parent).fraction_field()(left,right)
+
+    def __pow__(NCPolynomial_plural self, exp, ignored):
+        """
+        Return ``self**(exp)``.
+
+        The exponent must be an integer.
+
+        EXAMPLES::
+
+            sage: A.<x,z,y> = FreeAlgebra(QQ, 3)
+            sage: R = A.g_algebra(relations={y*x:-x*y + z},  order='lex')
+            sage: R.inject_variables()
+            Defining x, z, y
+            sage: f = x^3 + y
+            sage: f^2
+            x^6 + x^2*z + y^2
+
+        TESTS::
+        
+            sage: A.<x,z,y> = FreeAlgebra(QQ, 3)
+            sage: P = A.g_algebra(relations={y*x:-x*y + z},  order='lex')
+            sage: P.inject_variables()
+            Defining x, z, y
+            sage: (x+y^2^30)^10
+            Traceback (most recent call last):
+            ....
+            OverflowError: Exponent overflow (...).
+        """
+        if not PY_TYPE_CHECK_EXACT(exp, Integer) or \
+                PY_TYPE_CHECK_EXACT(exp, int):
+                    try:
+                        exp = Integer(exp)
+                    except TypeError:
+                        raise TypeError, "non-integral exponents not supported"
+
+        if exp < 0:
+            return 1/(self**(-exp))
+        elif exp == 0:
+            return (<NCPolynomialRing_plural>self._parent)._one_element
+
+        cdef ring *_ring = (<NCPolynomialRing_plural>self._parent)._ring
+        cdef poly *_p
+        singular_polynomial_pow(&_p, self._poly, exp, _ring)
+        return new_NCP((<NCPolynomialRing_plural>self._parent),_p)
+
+    def __neg__(self):
+        """
+        Return ``-self``.
+
+        EXAMPLES::
+
+            sage: A.<x,z,y> = FreeAlgebra(QQ, 3)
+            sage: R = A.g_algebra(relations={y*x:-x*y + z},  order='lex')
+            sage: R.inject_variables()
+            Defining x, z, y
+            sage: f = x^3 + y
+            sage: -f
+            -x^3 - y
+        """
+        cdef ring *_ring = (<NCPolynomialRing_plural>self._parent)._ring
+
+        cdef poly *p
+        singular_polynomial_neg(&p, self._poly, _ring)
+        return new_NCP((<NCPolynomialRing_plural>self._parent), p)
+
+    def _repr_(self):
+        """
+        EXAMPLES::
+
+            sage: A.<x,z,y> = FreeAlgebra(QQ, 3)
+            sage: R = A.g_algebra(relations={y*x:-x*y + z},  order='lex')
+            sage: R.inject_variables()
+            Defining x, z, y
+            sage: f = x^3 + y*x*z + z
+            sage: f # indirect doctest
+            x^3 - x*z*y + z^2 + z
+        """
+        cdef ring *_ring = (<NCPolynomialRing_plural>self._parent)._ring
+        s = singular_polynomial_str(self._poly, _ring)
+        return s
+
+    cpdef _repr_short_(self):
+        """
+        This is a faster but less pretty way to print polynomials. If
+        available it uses the short SINGULAR notation.
+        
+        EXAMPLES::
+
+            sage: A.<x,z,y> = FreeAlgebra(QQ, 3)
+            sage: R = A.g_algebra(relations={y*x:-x*y + z},  order='lex')
+            sage: R.inject_variables()
+            Defining x, z, y
+            sage: f = x^3 + y
+            sage: f._repr_short_()
+            'x3+y'
+        """
+        cdef ring *_ring = (<NCPolynomialRing_plural>self._parent)._ring
+        rChangeCurrRing(_ring)
+        if _ring.CanShortOut:
+            _ring.ShortOut = 1
+            s = p_String(self._poly, _ring, _ring)
+            _ring.ShortOut = 0
+        else:
+            s = p_String(self._poly, _ring, _ring)
+        return s
+                                           
+    def _latex_(self):
+        """
+        Return a polynomial LaTeX representation of this polynomial.
+
+        EXAMPLES::
+
+            sage: A.<x,z,y> = FreeAlgebra(QQ, 3)
+            sage: R = A.g_algebra(relations={y*x:-x*y + z},  order='lex')
+            sage: R.inject_variables()
+            Defining x, z, y
+            sage: f = - 1*x^2*y - 25/27 * y^3 - z^2
+            sage: latex(f) # indirect doctest
+            - x^{2} y - z^{2} - \frac{25}{27} y^{3}
+        """
+        cdef ring *_ring = (<NCPolynomialRing_plural>self._parent)._ring
+        gens = self.parent().latex_variable_names()
+        base = self.parent().base()
+        return singular_polynomial_latex(self._poly, _ring, base, gens)
+    
+    def _repr_with_changed_varnames(self, varnames):
+        """
+        Return string representing this polynomial but change the
+        variable names to ``varnames``.
+
+        EXAMPLES::
+
+            sage: A.<x,z,y> = FreeAlgebra(QQ, 3)
+            sage: R = A.g_algebra(relations={y*x:-x*y + z},  order='lex')
+            sage: R.inject_variables()
+            Defining x, z, y
+            sage: f = - 1*x^2*y - 25/27 * y^3 - z^2
+            sage: print f._repr_with_changed_varnames(['FOO', 'BAR', 'FOOBAR'])
+            -FOO^2*FOOBAR - BAR^2 - 25/27*FOOBAR^3
+        """
+        return  singular_polynomial_str_with_changed_varnames(self._poly, (<NCPolynomialRing_plural>self._parent)._ring, varnames)
+            
+    def degree(self, NCPolynomial_plural x=None):
+        """
+        Return the maximal degree of this polynomial in ``x``, where
+        ``x`` must be one of the generators for the parent of this
+        polynomial.
+
+        INPUT:
+
+        - ``x`` - multivariate polynomial (a generator of the parent of
+          self) If x is not specified (or is ``None``), return the total
+          degree, which is the maximum degree of any monomial.
+
+        OUTPUT:
+            integer
+        
+        EXAMPLES::
+
+            sage: A.<x,z,y> = FreeAlgebra(QQ, 3)
+            sage: R = A.g_algebra(relations={y*x:-x*y + z},  order='lex')
+            sage: R.inject_variables()
+            Defining x, z, y
+            sage: f = y^2 - x^9 - x
+            sage: f.degree(x)
+            9
+            sage: f.degree(y)
+            2
+            sage: (y^10*x - 7*x^2*y^5 + 5*x^3).degree(x)
+            3
+            sage: (y^10*x - 7*x^2*y^5 + 5*x^3).degree(y)
+            10
+
+        TESTS::
+
+            sage: A.<x,z,y> = FreeAlgebra(QQ, 3)
+            sage: P = A.g_algebra(relations={y*x:-x*y + z},  order='lex')
+            sage: P.inject_variables()
+            Defining x, z, y
+            sage: P(0).degree(x)
+            -1
+            sage: P(1).degree(x)
+            0
+
+        """
+        cdef ring *r = (<NCPolynomialRing_plural>self._parent)._ring
+        cdef poly *p = self._poly
+        if not x:
+            return singular_polynomial_deg(p,NULL,r)
+
+        # TODO: we can do this faster
+        if not x in self._parent.gens():
+            raise TypeError("x must be one of the generators of the parent.")
+
+        return singular_polynomial_deg(p, (<NCPolynomial_plural>x)._poly, r)
+
+    def total_degree(self):
+        """
+        Return the total degree of ``self``, which is the maximum degree
+        of all monomials in ``self``.
+
+        EXAMPLES::
+
+            sage: A.<x,z,y> = FreeAlgebra(QQ, 3)
+            sage: R = A.g_algebra(relations={y*x:-x*y + z},  order='lex')
+            sage: R.inject_variables()
+            Defining x, z, y
+            sage: f=2*x*y^3*z^2
+            sage: f.total_degree()
+            6
+            sage: f=4*x^2*y^2*z^3
+            sage: f.total_degree()
+            7
+            sage: f=99*x^6*y^3*z^9
+            sage: f.total_degree()
+            18
+            sage: f=x*y^3*z^6+3*x^2
+            sage: f.total_degree()
+            10
+            sage: f=z^3+8*x^4*y^5*z
+            sage: f.total_degree()
+            10
+            sage: f=z^9+10*x^4+y^8*x^2
+            sage: f.total_degree()
+            10
+
+        TESTS::
+
+            sage: A.<x,z,y> = FreeAlgebra(QQ, 3)
+            sage: R = A.g_algebra(relations={y*x:-x*y + z},  order='lex')
+            sage: R.inject_variables()
+            Defining x, z, y
+            sage: R(0).total_degree()
+            -1
+            sage: R(1).total_degree()
+            0
+        """
+        cdef poly *p = self._poly
+        cdef ring *r = (<NCPolynomialRing_plural>self._parent)._ring
+        return singular_polynomial_deg(p,NULL,r)
+
+    def degrees(self):
+        """ 
+        Returns a tuple with the maximal degree of each variable in
+        this polynomial.  The list of degrees is ordered by the order
+        of the generators.
+
+        EXAMPLES::
+
+            sage: A.<y0,y1,y2> = FreeAlgebra(QQ, 3)
+            sage: R = A.g_algebra(relations={y1*y0:-y0*y1 + y2},  order='lex')
+            sage: R.inject_variables()
+            Defining y0, y1, y2
+            sage: q = 3*y0*y1*y1*y2; q 
+            3*y0*y1^2*y2 
+            sage: q.degrees() 
+            (1, 2, 1)
+            sage: (q + y0^5).degrees()
+            (5, 2, 1)
+        """
+        cdef poly *p = self._poly
+        cdef ring *r = (<NCPolynomialRing_plural>self._parent)._ring
+        cdef int i
+        cdef list d = [0 for _ in range(r.N)]
+        while p:
+            for i from 0 <= i < r.N:
+                d[i] = max(d[i],p_GetExp(p, i+1, r))
+            p = pNext(p)
+        return tuple(d)
+
+
+    def coefficient(self, degrees):
+        """
+        Return the coefficient of the variables with the degrees
+        specified in the python dictionary ``degrees``.
+        Mathematically, this is the coefficient in the base ring
+        adjoined by the variables of this ring not listed in
+        ``degrees``.  However, the result has the same parent as this
+        polynomial.
+
+        This function contrasts with the function
+        ``monomial_coefficient`` which returns the coefficient in the
+        base ring of a monomial.
+
+        INPUT:
+
+        - ``degrees`` - Can be any of:
+                - a dictionary of degree restrictions
+                - a list of degree restrictions (with None in the unrestricted variables)
+                - a monomial (very fast, but not as flexible)
+
+        OUTPUT:
+            element of the parent of this element.
+
+        .. note::
+           
+           For coefficients of specific monomials, look at :meth:`monomial_coefficient`.
+
+        EXAMPLES::
+
+            sage: A.<x,z,y> = FreeAlgebra(QQ, 3)
+            sage: R = A.g_algebra(relations={y*x:-x*y + z},  order='lex')
+            sage: R.inject_variables()
+            Defining x, z, y
+            sage: f=x*y+y+5
+            sage: f.coefficient({x:0,y:1})
+            1
+            sage: f.coefficient({x:0})
+            y + 5
+            sage: f=(1+y+y^2)*(1+x+x^2)
+            sage: f.coefficient({x:0})
+            z + y^2 + y + 1
+
+            sage: f.coefficient(x)
+            y^2 - y + 1
+          
+# f.coefficient([0,None]) # y^2 + y + 1
+
+        Be aware that this may not be what you think! The physical
+        appearance of the variable x is deceiving -- particularly if
+        the exponent would be a variable. ::
+
+            sage: f.coefficient(x^0) # outputs the full polynomial
+            x^2*y^2 + x^2*y + x^2 + x*y^2 - x*y + x + z + y^2 + y + 1
+
+            sage: A.<x,z,y> = FreeAlgebra(GF(389), 3)
+            sage: R = A.g_algebra(relations={y*x:-x*y + z},  order='lex')
+            sage: R.inject_variables()
+            Defining x, z, y
+            sage: f=x*y+5
+            sage: c=f.coefficient({x:0,y:0}); c
+            5
+            sage: parent(c)
+            Noncommutative Multivariate Polynomial Ring in x, z, y over Finite Field of size 389, nc-relations: {y*x: -x*y + z}
+
+        AUTHOR:
+
+        - Joel B. Mohler (2007.10.31)
+        """
+        cdef poly *_degrees = <poly*>0
+        cdef poly *p = self._poly
+        cdef ring *r = (<NCPolynomialRing_plural>self._parent)._ring
+        cdef poly *newp = p_ISet(0,r)
+        cdef poly *newptemp
+        cdef int i
+        cdef int flag
+        cdef int gens = self._parent.ngens()
+        cdef int *exps = <int*>sage_malloc(sizeof(int)*gens)
+        for i from 0<=i<gens:
+            exps[i] = -1
+
+        if PY_TYPE_CHECK(degrees, NCPolynomial_plural) and self._parent is (<NCPolynomial_plural>degrees)._parent:
+            _degrees = (<NCPolynomial_plural>degrees)._poly
+            if pLength(_degrees) != 1:
+                raise TypeError, "degrees must be a monomial"
+            for i from 0<=i<gens:
+                if p_GetExp(_degrees,i+1,r)!=0:
+                    exps[i] = p_GetExp(_degrees,i+1,r)
+        elif type(degrees) is list:
+            for i from 0<=i<gens:
+                if degrees[i] is None:
+                    exps[i] = -1
+                else:
+                    exps[i] = int(degrees[i])
+        elif type(degrees) is dict:
+            # Extract the ordered list of degree specifications from the dictionary
+            poly_vars = self.parent().gens()
+            for i from 0<=i<gens:
+                try:
+                    exps[i] = degrees[poly_vars[i]]
+                except KeyError:
+                    pass
+        else:
+            raise TypeError, "The input degrees must be a dictionary of variables to exponents."
+
+        # Extract the monomials that match the specifications
+        while(p):
+            flag = 0
+            for i from 0<=i<gens:
+                if exps[i] != -1 and p_GetExp(p,i+1,r)!=exps[i]:
+                    #print i, p_GetExp(p,i+1,r), exps[i]
+                    flag = 1
+            if flag == 0:
+                newptemp = p_LmInit(p,r)
+                p_SetCoeff(newptemp,n_Copy(p_GetCoeff(p,r),r),r)
+                for i from 0<=i<gens:
+                    if exps[i] != -1:
+                        p_SetExp(newptemp,i+1,0,r)
+                p_Setm(newptemp,r)
+                newp = p_Add_q(newp,newptemp,r)
+            p = pNext(p)
+
+        sage_free(exps)
+
+        return new_NCP(self.parent(),newp)
+
+    def monomial_coefficient(self, NCPolynomial_plural mon):
+        """
+        Return the coefficient in the base ring of the monomial mon in
+        ``self``, where mon must have the same parent as self.
+
+        This function contrasts with the function ``coefficient``
+        which returns the coefficient of a monomial viewing this
+        polynomial in a polynomial ring over a base ring having fewer
+        variables.
+
+        INPUT:
+
+        - ``mon`` - a monomial
+
+        OUTPUT:
+            coefficient in base ring
+
+        SEE ALSO:
+            For coefficients in a base ring of fewer variables, look at ``coefficient``.
+
+        EXAMPLES::
+
+            sage: A.<x,z,y> = FreeAlgebra(GF(389), 3)
+            sage: P = A.g_algebra(relations={y*x:-x*y + z},  order='lex')
+            sage: P.inject_variables()
+            Defining x, z, y
+
+            The parent of the return is a member of the base ring.
+            sage: f = 2 * x * y
+            sage: c = f.monomial_coefficient(x*y); c
+            2
+            sage: c.parent()
+            Finite Field of size 389
+
+            sage: f = y^2 + y^2*x - x^9 - 7*x + 5*x*y
+            sage: f.monomial_coefficient(y^2)
+            1
+            sage: f.monomial_coefficient(x*y)
+            5
+            sage: f.monomial_coefficient(x^9)
+            388
+            sage: f.monomial_coefficient(x^10)
+            0
+        """
+        cdef poly *p = self._poly
+        cdef poly *m = mon._poly
+        cdef ring *r = (<NCPolynomialRing_plural>self._parent)._ring
+
+        if not mon._parent is self._parent:
+            raise TypeError("mon must have same parent as self.")
+        
+        while(p):
+            if p_ExpVectorEqual(p, m, r) == 1:
+                return si2sa(p_GetCoeff(p, r), r, (<NCPolynomialRing_plural>self._parent)._base)
+            p = pNext(p)
+
+        return (<NCPolynomialRing_plural>self._parent)._base._zero_element
+
+    def dict(self):
+        """
+        Return a dictionary representing self. This dictionary is in
+        the same format as the generic MPolynomial: The dictionary
+        consists of ``ETuple:coefficient`` pairs.
+
+        EXAMPLES::
+
+            sage: A.<x,z,y> = FreeAlgebra(GF(389), 3)
+            sage: R = A.g_algebra(relations={y*x:-x*y + z},  order='lex')
+            sage: R.inject_variables()
+            Defining x, z, y
+
+            sage: f = (2*x*y^3*z^2 + (7)*x^2 + (3))
+            sage: f.dict()
+            {(0, 0, 0): 3, (2, 0, 0): 7, (1, 2, 3): 2}
+        """
+        cdef poly *p
+        cdef ring *r
+        cdef int n
+        cdef int v
+        r = (<NCPolynomialRing_plural>self._parent)._ring
+        if r!=currRing: rChangeCurrRing(r)
+        base = (<NCPolynomialRing_plural>self._parent)._base
+        p = self._poly
+        pd = dict()
+        while p:
+            d = dict()
+            for v from 1 <= v <= r.N:
+                n = p_GetExp(p,v,r)
+                if n!=0:
+                    d[v-1] = n 
+                
+            pd[ETuple(d,r.N)] = si2sa(p_GetCoeff(p, r), r, base)
+
+            p = pNext(p)
+        return pd
+
+
+    cdef long _hash_c(self):
+        """
+        See ``self.__hash__``
+        """
+        cdef poly *p
+        cdef ring *r
+        cdef int n
+        cdef int v
+        r = (<NCPolynomialRing_plural>self._parent)._ring
+        if r!=currRing: rChangeCurrRing(r)
+        base = (<NCPolynomialRing_plural>self._parent)._base
+        p = self._poly
+        cdef long result = 0 # store it in a c-int and just let the overflowing additions wrap
+        cdef long result_mon
+        var_name_hash = [hash(vn) for vn in self._parent.variable_names()]
+        cdef long c_hash
+        while p:
+            c_hash = hash(si2sa(p_GetCoeff(p, r), r, base))
+            if c_hash != 0: # this is always going to be true, because we are sparse (correct?)
+                # Hash (self[i], gen_a, exp_a, gen_b, exp_b, gen_c, exp_c, ...) as a tuple according to the algorithm.
+                # I omit gen,exp pairs where the exponent is zero.
+                result_mon = c_hash
+                for v from 1 <= v <= r.N:
+                    n = p_GetExp(p,v,r)
+                    if n!=0:
+                        result_mon = (1000003 * result_mon) ^ var_name_hash[v-1]
+                        result_mon = (1000003 * result_mon) ^ n
+                result += result_mon
+
+            p = pNext(p)
+        if result == -1:
+            return -2
+        return result
+
+    def __getitem__(self,x):
+        """
+        Same as ``self.monomial_coefficent`` but for exponent vectors.
+        
+        INPUT:
+
+        - ``x`` - a tuple or, in case of a single-variable MPolynomial
+        ring x can also be an integer.
+        
+        EXAMPLES::
+
+            sage: A.<x,z,y> = FreeAlgebra(GF(389), 3)
+            sage: R = A.g_algebra(relations={y*x:-x*y + z},  order='lex')
+            sage: R.inject_variables()
+            Defining x, z, y
+            sage: f = (-10*x^3*y + 17*x*y)* ( 15*z^3 + 2*x*y*z - 1); f
+            20*x^4*z*y^2 - 150*x^3*z^3*y - 20*x^3*z^2*y + 10*x^3*y - 34*x^2*z*y^2 - 134*x*z^3*y + 34*x*z^2*y - 17*x*y
+            sage: f[4,1,2]
+            20
+            sage: f[1,0,1]
+            372
+            sage: f[0,0,0]
+            0
+
+            sage: R.<x> = PolynomialRing(GF(7),1); R
+            Multivariate Polynomial Ring in x over Finite Field of size 7
+            sage: f = 5*x^2 + 3; f
+            -2*x^2 + 3
+            sage: f[2]
+            5
+        """
+        cdef poly *m 
+        cdef poly *p = self._poly
+        cdef ring *r = (<NCPolynomialRing_plural>self._parent)._ring
+        cdef int i
+
+        if PY_TYPE_CHECK(x, NCPolynomial_plural):
+            return self.monomial_coefficient(x)
+        if not PY_TYPE_CHECK(x, tuple):
+            try:
+                x = tuple(x)
+            except TypeError:
+                x = (x,)
+
+        if len(x) != (<NCPolynomialRing_plural>self._parent).__ngens:
+            raise TypeError, "x must have length self.ngens()"
+
+        m = p_ISet(1,r)
+        i = 1
+        for e in x:
+            overflow_check(e)
+            p_SetExp(m, i, int(e), r)
+            i += 1
+        p_Setm(m, r)
+
+        while(p):
+            if p_ExpVectorEqual(p, m, r) == 1:
+                p_Delete(&m,r)
+                return si2sa(p_GetCoeff(p, r), r, (<NCPolynomialRing_plural>self._parent)._base)
+            p = pNext(p)
+
+        p_Delete(&m,r)
+        return (<NCPolynomialRing_plural>self._parent)._base._zero_element
+
+    def exponents(self, as_ETuples=True):
+        """
+        Return the exponents of the monomials appearing in this polynomial.
+        
+        INPUT:
+
+        - ``as_ETuples`` - (default: ``True``) if true returns the result as an list of ETuples
+                          otherwise returns a list of tuples
+
+
+        EXAMPLES::
+
+            sage: A.<x,z,y> = FreeAlgebra(GF(389), 3)
+            sage: R = A.g_algebra(relations={y*x:-x*y + z},  order='lex')
+            sage: R.inject_variables()
+            Defining x, z, y
+            sage: f = x^3 + y + 2*z^2
+            sage: f.exponents()
+            [(3, 0, 0), (0, 2, 0), (0, 0, 1)]
+            sage: f.exponents(as_ETuples=False)
+            [(3, 0, 0), (0, 2, 0), (0, 0, 1)]
+        """
+        cdef poly *p
+        cdef ring *r
+        cdef int v
+        cdef list pl, ml
+
+        r = (< NCPolynomialRing_plural>self._parent)._ring
+        p = self._poly
+
+        pl = list()
+        ml = range(r.N)
+        while p:
+            for v from 1 <= v <= r.N:
+                ml[v-1] = p_GetExp(p,v,r)
+
+            if as_ETuples:
+                pl.append(ETuple(ml))
+            else:
+                pl.append(tuple(ml))
+
+            p = pNext(p)
+        return pl
+
+    def is_homogeneous(self):
+        """
+        Return ``True`` if this polynomial is homogeneous.
+
+        EXAMPLES::
+
+            sage: A.<x,z,y> = FreeAlgebra(GF(389), 3)
+            sage: P = A.g_algebra(relations={y*x:-x*y + z},  order='lex')
+            sage: P.inject_variables()
+            Defining x, z, y
+            sage: (x+y+z).is_homogeneous()
+            True
+            sage: (x.parent()(0)).is_homogeneous()
+            True
+            sage: (x+y^2+z^3).is_homogeneous()
+            False
+            sage: (x^2 + y^2).is_homogeneous()
+            True
+            sage: (x^2 + y^2*x).is_homogeneous()
+            False
+            sage: (x^2*y + y^2*x).is_homogeneous()
+            True
+        """
+        cdef ring *_ring = (<NCPolynomialRing_plural>self._parent)._ring
+        if(_ring != currRing): rChangeCurrRing(_ring)
+        return bool(pIsHomogeneous(self._poly))
+
+
+    def is_monomial(self):
+        """
+        Return ``True`` if this polynomial is a monomial.  A monomial
+        is defined to be a product of generators with coefficient 1.
+
+        EXAMPLES::
+
+            sage: A.<x,z,y> = FreeAlgebra(GF(389), 3)
+            sage: P = A.g_algebra(relations={y*x:-x*y + z},  order='lex')
+            sage: P.inject_variables()
+            Defining x, z, y
+            sage: x.is_monomial()
+            True
+            sage: (2*x).is_monomial()
+            False
+            sage: (x*y).is_monomial()
+            True
+            sage: (x*y + x).is_monomial()
+            False
+        """
+        cdef poly *_p
+        cdef ring *_ring
+        cdef number *_n
+        _ring = (<NCPolynomialRing_plural>self._parent)._ring
+
+        if self._poly == NULL:
+            return True
+        
+        if(_ring != currRing): rChangeCurrRing(_ring)
+        
+        _p = p_Head(self._poly, _ring)
+        _n = p_GetCoeff(_p, _ring)
+
+        ret = (not self._poly.next) and n_IsOne(_n, _ring)
+
+        p_Delete(&_p, _ring)
+        return ret
+
+    def monomials(self):
+        """
+        Return the list of monomials in self. The returned list is
+        decreasingly ordered by the term ordering of
+        ``self.parent()``.
+
+        EXAMPLES::
+
+            sage: A.<x,z,y> = FreeAlgebra(GF(389), 3)
+            sage: P = A.g_algebra(relations={y*x:-x*y + z},  order='lex')
+            sage: P.inject_variables()
+            Defining x, z, y
+            sage: f = x + (3*2)*y*z^2 + (2+3)
+            sage: f.monomials()
+            [x, z^2*y, 1]
+            sage: f = P(3^2)
+            sage: f.monomials()
+            [1]
+
+        TESTS::
+
+            sage: A.<x,z,y> = FreeAlgebra(GF(389), 3)
+            sage: P = A.g_algebra(relations={y*x:-x*y + z},  order='lex')
+            sage: P.inject_variables()
+            Defining x, z, y
+            sage: f = x
+            sage: f.monomials()
+            [x]
+            sage: f = P(0)
+            sage: f.monomials()
+            [0]
+
+        Check if #7152 is fixed::
+
+            sage: x=var('x')
+            sage: K.<rho> = NumberField(x**2 + 1)
+            sage: R.<x,y> = QQ[]
+            sage: p = rho*x
+            sage: q = x
+            sage: p.monomials()
+            [x]
+            sage: q.monomials()
+            [x]
+            sage: p.monomials()
+            [x]
+        """
+        l = list()
+        cdef NCPolynomialRing_plural parent = <NCPolynomialRing_plural>self._parent
+        cdef ring *_ring = parent._ring
+        if(_ring != currRing): rChangeCurrRing(_ring)
+        cdef poly *p = p_Copy(self._poly, _ring)
+        cdef poly *t
+
+        if p == NULL:
+            return [parent._zero_element]
+        
+        while p:
+            t = pNext(p)
+            p.next = NULL
+            p_SetCoeff(p, n_Init(1,_ring), _ring)
+            p_Setm(p, _ring)
+            l.append( new_NCP(parent,p) )
+            p = t
+
+        return l
+
+    def constant_coefficient(self):
+        """
+        Return the constant coefficient of this multivariate
+        polynomial.
+
+        EXAMPLES::
+
+            sage: A.<x,z,y> = FreeAlgebra(GF(389), 3)
+            sage: P = A.g_algebra(relations={y*x:-x*y + z},  order='lex')
+            sage: P.inject_variables()
+            Defining x, z, y
+            sage: f = 3*x^2 - 2*y + 7*x^2*y^2 + 5
+            sage: f.constant_coefficient()
+            5
+            sage: f = 3*x^2 
+            sage: f.constant_coefficient()
+            0
+        """
+        cdef poly *p = self._poly
+        cdef ring *r = (<NCPolynomialRing_plural>self._parent)._ring
+        if p == NULL:
+            return (<NCPolynomialRing_plural>self._parent)._base._zero_element
+
+        while p.next:
+            p = pNext(p)
+
+        if p_LmIsConstant(p, r):
+            return si2sa( p_GetCoeff(p, r), r, (<NCPolynomialRing_plural>self._parent)._base )
+        else:
+            return (<NCPolynomialRing_plural>self._parent)._base._zero_element
+
+    cpdef is_constant(self):
+        """
+        Return ``True`` if this polynomial is constant.
+
+        EXAMPLES::
+
+            sage: A.<x,z,y> = FreeAlgebra(GF(389), 3)
+            sage: P = A.g_algebra(relations={y*x:-x*y + z},  order='lex')
+            sage: P.inject_variables()
+            Defining x, z, y
+            sage: x.is_constant()
+            False
+            sage: P(1).is_constant()
+            True
+        """
+        return bool(p_IsConstant(self._poly, (<NCPolynomialRing_plural>self._parent)._ring))
+
+    def lm(NCPolynomial_plural self):
+        """
+        Returns the lead monomial of self with respect to the term
+        order of ``self.parent()``. In Sage a monomial is a product of
+        variables in some power without a coefficient.
+
+        EXAMPLES::
+
+            sage: A.<x,y,z> = FreeAlgebra(GF(7), 3)
+            sage: R = A.g_algebra(relations={y*x:-x*y + z},  order='lex')
+            sage: R.inject_variables()
+            Defining x, y, z
+            sage: f = x^1*y^2 + y^3*z^4
+            sage: f.lm()
+            x*y^2
+            sage: f = x^3*y^2*z^4 + x^3*y^2*z^1 
+            sage: f.lm()
+            x^3*y^2*z^4
+
+            sage: A.<x,y,z> = FreeAlgebra(QQ, 3)
+            sage: R = A.g_algebra(relations={y*x:-x*y + z},  order='deglex')
+            sage: R.inject_variables()
+            Defining x, y, z
+            sage: f = x^1*y^2*z^3 + x^3*y^2*z^0
+            sage: f.lm()
+            x*y^2*z^3
+            sage: f = x^1*y^2*z^4 + x^1*y^1*z^5
+            sage: f.lm()
+            x*y^2*z^4
+
+            sage: A.<x,y,z> = FreeAlgebra(GF(127), 3)
+            sage: R = A.g_algebra(relations={y*x:-x*y + z},  order='degrevlex')
+            sage: R.inject_variables()
+            Defining x, y, z
+            sage: f = x^1*y^5*z^2 + x^4*y^1*z^3
+            sage: f.lm()
+            x*y^5*z^2
+            sage: f = x^4*y^7*z^1 + x^4*y^2*z^3
+            sage: f.lm()
+            x^4*y^7*z
+
+        """
+        cdef poly *_p
+        cdef ring *_ring
+        _ring = (<NCPolynomialRing_plural>self._parent)._ring
+        if self._poly == NULL:
+            return (<NCPolynomialRing_plural>self._parent)._zero_element
+        _p = p_Head(self._poly, _ring)
+        p_SetCoeff(_p, n_Init(1,_ring), _ring)
+        p_Setm(_p,_ring)
+        return new_NCP((<NCPolynomialRing_plural>self._parent), _p)
+
+    def lc(NCPolynomial_plural self):
+        """
+        Leading coefficient of this polynomial with respect to the
+        term order of ``self.parent()``.
+
+        EXAMPLES::
+
+            sage: A.<x,y,z> = FreeAlgebra(GF(7), 3)
+            sage: R = A.g_algebra(relations={y*x:-x*y + z},  order='lex')
+            sage: R.inject_variables()
+            Defining x, y, z
+
+            sage: f = 3*x^1*y^2 + 2*y^3*z^4
+            sage: f.lc()
+            3
+
+            sage: f = 5*x^3*y^2*z^4 + 4*x^3*y^2*z^1 
+            sage: f.lc()
+            5
+        """
+
+        cdef poly *_p
+        cdef ring *_ring
+        cdef number *_n
+        _ring = (<NCPolynomialRing_plural>self._parent)._ring
+
+        if self._poly == NULL:
+            return (<NCPolynomialRing_plural>self._parent)._base._zero_element
+        
+        if(_ring != currRing): rChangeCurrRing(_ring)
+        
+        _p = p_Head(self._poly, _ring) 
+        _n = p_GetCoeff(_p, _ring)
+
+        ret =  si2sa(_n, _ring, (<NCPolynomialRing_plural>self._parent)._base)
+        p_Delete(&_p, _ring)
+        return ret
+
+    def lt(NCPolynomial_plural self):
+        """
+        Leading term of this polynomial. In Sage a term is a product
+        of variables in some power and a coefficient.
+
+        EXAMPLES::
+
+            sage: A.<x,y,z> = FreeAlgebra(GF(7), 3)
+            sage: R = A.g_algebra(relations={y*x:-x*y + z},  order='lex')
+            sage: R.inject_variables()
+            Defining x, y, z
+
+            sage: f = 3*x^1*y^2 + 2*y^3*z^4
+            sage: f.lt()
+            3*x*y^2
+            
+            sage: f = 5*x^3*y^2*z^4 + 4*x^3*y^2*z^1 
+            sage: f.lt()
+            -2*x^3*y^2*z^4
+        """
+        if self._poly == NULL:
+            return (<NCPolynomialRing_plural>self._parent)._zero_element
+
+        return new_NCP((<NCPolynomialRing_plural>self._parent),
+                                           p_Head(self._poly,(<NCPolynomialRing_plural>self._parent)._ring))
+
+    def is_zero(self):
+        """
+        Return ``True`` if this polynomial is zero.
+
+        EXAMPLES::
+
+            sage: A.<x,z,y> = FreeAlgebra(QQ, 3)
+            sage: R = A.g_algebra(relations={y*x:-x*y + z},  order='lex')
+            sage: R.inject_variables()
+            Defining x, z, y
+
+            sage: x.is_zero()
+            False
+            sage: (x-x).is_zero()
+            True
+        """
+        if self._poly is NULL:
+            return True
+        else:
+            return False
+
+    def __nonzero__(self):
+        """
+        EXAMPLES::
+
+            sage: A.<x,z,y> = FreeAlgebra(QQ, 3)
+            sage: R = A.g_algebra(relations={y*x:-x*y + z},  order='lex')
+            sage: R.inject_variables()
+            Defining x, z, y
+
+            sage: bool(x) # indirect doctest
+            True
+            sage: bool(x-x)
+            False
+        """
+        if self._poly:
+            return True
+        else:
+            return False
+
+
+#####################################################################
+
+
+cdef inline NCPolynomial_plural new_NCP(NCPolynomialRing_plural parent,
+        poly *juice):
+    """
+    Construct NCPolynomial_plural from parent and SINGULAR poly.
+
+    EXAMPLES::
+
+    
+    """
+    cdef NCPolynomial_plural p = PY_NEW(NCPolynomial_plural)
+    p._parent = <ParentWithBase>parent
+    p._poly = juice
+    p_Normalize(p._poly, parent._ring)
+    return p
+
+
+
+
+cpdef MPolynomialRing_libsingular new_CRing(RingWrap rw, base_ring):
+    """
+    Construct MPolynomialRing_libsingular from ringWrap, assumming the ground field to be base_ring
+
+    EXAMPLES::
+        sage: H.<x,y,z> = PolynomialRing(QQ, 3)
+        sage: from sage.libs.singular.function import singular_function
+
+        sage: ringlist = singular_function('ringlist')
+        sage: ring = singular_function("ring") 
+
+        sage: L = ringlist(H, ring=H); L
+        [0, ['x', 'y', 'z'], [['dp', (1, 1, 1)], ['C', (0,)]], [0]]
+
+        sage: len(L)
+        4
+        
+        sage: W = ring(L, ring=H); W
+        <RingWrap>
+
+        sage: from sage.rings.polynomial.plural import new_CRing
+        sage: R = new_CRing(W, H.base_ring())
+        sage: R # indirect doctest
+        Multivariate Polynomial Ring in x, y, z over Rational Field
+    """
+    assert( rw.is_commutative() )
+       
+    cdef MPolynomialRing_libsingular self = <MPolynomialRing_libsingular>PY_NEW(MPolynomialRing_libsingular)
+        
+    self._ring = rw._ring
+    self._ring.ShortOut = 0
+        
+    self.__ngens = rw.ngens()
+    self.__term_order =  TermOrder(rw.ordering_string(), force=True)
+        
+    ParentWithGens.__init__(self, base_ring, rw.var_names())
+#    self._populate_coercion_lists_()  # ???
+         
+    #MPolynomialRing_generic.__init__(self, base_ring, n, names, order)
+    self._has_singular = True
+#    self._relations = self.relations()
+        
+    return self
+    
+cpdef NCPolynomialRing_plural new_NRing(RingWrap rw, base_ring):
+    """
+    Construct NCPolynomialRing_plural from ringWrap, assumming the ground field to be base_ring
+
+    EXAMPLES::
+    EXAMPLES::
+        
+        sage: A.<x,y,z> = FreeAlgebra(QQ, 3)
+        sage: H = A.g_algebra({y*x:x*y-1})
+        sage: H.inject_variables()
+        Defining x, y, z
+        sage: z*x
+        x*z
+        sage: z*y
+        y*z
+        sage: y*x
+        x*y - 1
+        sage: I = H.ideal([y^2, x^2, z^2-1])
+        sage: I._groebner_basis_libsingular() 
+        [1]
+
+        sage: from sage.libs.singular.function import singular_function
+
+        sage: ringlist = singular_function('ringlist')
+        sage: ring = singular_function("ring") 
+
+        sage: L = ringlist(H, ring=H); L
+        [0, ['x', 'y', 'z'], [['dp', (1, 1, 1)], ['C', (0,)]], [0], [0 1 1]
+        [0 0 1]
+        [0 0 0], [ 0 -1  0]
+        [ 0  0  0]
+        [ 0  0  0]]
+
+        sage: len(L)
+        6      
+
+        sage: W = ring(L, ring=H); W
+        <noncommutative RingWrap>
+
+        sage: from sage.rings.polynomial.plural import new_NRing
+        sage: R = new_NRing(W, H.base_ring())
+        sage: R # indirect doctest
+        Noncommutative Multivariate Polynomial Ring in x, y, z over Rational Field, nc-relations: {y*x: x*y - 1}
+    """
+
+    assert( not rw.is_commutative() )
+    
+    cdef NCPolynomialRing_plural self = <NCPolynomialRing_plural>PY_NEW(NCPolynomialRing_plural)
+    self._ring = rw._ring
+    self._ring.ShortOut = 0
+        
+    self.__ngens = rw.ngens()
+    self.__term_order =  TermOrder(rw.ordering_string(), force=True)
+        
+    ParentWithGens.__init__(self, base_ring, rw.var_names())
+#    self._populate_coercion_lists_()  # ???
+    
+    #MPolynomialRing_generic.__init__(self, base_ring, n, names, order)
+    self._has_singular = True
+    self._relations = self.relations()
+        
+    return self
+
+
+def new_Ring(RingWrap rw, base_ring):
+    """
+    Constructs a Sage ring out of low level RingWrap, which wraps a pointer to a Singular ring.
+    The constructed ring is either commutative or noncommutative depending on the Singular ring.
+
+    EXAMPLES::
+        
+        sage: A.<x,y,z> = FreeAlgebra(QQ, 3)
+        sage: H = A.g_algebra({y*x:x*y-1})
+        sage: H.inject_variables()
+        Defining x, y, z
+        sage: z*x
+        x*z
+        sage: z*y
+        y*z
+        sage: y*x
+        x*y - 1
+        sage: I = H.ideal([y^2, x^2, z^2-1])
+        sage: I._groebner_basis_libsingular() 
+        [1]
+
+        sage: from sage.libs.singular.function import singular_function
+
+        sage: ringlist = singular_function('ringlist')
+        sage: ring = singular_function("ring") 
+
+        sage: L = ringlist(H, ring=H); L
+        [0, ['x', 'y', 'z'], [['dp', (1, 1, 1)], ['C', (0,)]], [0], [0 1 1]
+        [0 0 1]
+        [0 0 0], [ 0 -1  0]
+        [ 0  0  0]
+        [ 0  0  0]]
+
+        sage: len(L)
+        6      
+
+        sage: W = ring(L, ring=H); W
+        <noncommutative RingWrap>
+
+        sage: from sage.rings.polynomial.plural import new_Ring
+        sage: R = new_Ring(W, H.base_ring()); R
+        Noncommutative Multivariate Polynomial Ring in x, y, z over Rational Field, nc-relations: {y*x: x*y - 1}
+
+    """
+    import warnings
+#    warnings.warn("This is a hack. Please, use it on your own risk...")
+    if rw.is_commutative():
+        return new_CRing(rw, base_ring)
+    return new_NRing(rw, base_ring)
+        
+
+def SCA(base_ring, names, alt_vars, order='degrevlex'):
+    """
+    Shortcut to construct a graded commutative algebra out of the following data: 
+
+    Input: 
+        
+    - ``base_ring``: the ground field
+    - ``names``: a list of variable names 
+    - ``alt_vars``: a list of indices of to be anti-commutative variables
+    - ``order``: orderig to be used for the constructed algebra
+
+    EXAMPLES::
+
+        sage: from sage.rings.polynomial.plural import SCA
+        sage: E = SCA(QQ, ['x', 'y', 'z'], [0, 1], order = 'degrevlex')
+        sage: E
+        Noncommutative Multivariate Polynomial Ring in x, y, z over Rational Field, nc-relations: {y*x: -x*y}
+        sage: E.inject_variables()
+        Defining x, y, z
+        sage: y*x
+        -x*y
+        sage: x^2
+        0
+        sage: y^2
+        0
+        sage: z^2
+        z^2
+    """
+    n = len(names)
+    alt_start = min(alt_vars)
+    alt_end = max(alt_vars)
+    assert( alt_start >= 0 )
+    assert( (alt_end >= alt_start) and (alt_end < n) )
+    
+    relations = {} # {y*x:-x*y}
+    from sage.algebras.free_algebra import FreeAlgebra
+    A = FreeAlgebra(base_ring, n, names)
+    for r in range(0, n-1, 1):
+        for c in range(r+1, n, 1):
+            if (r in alt_vars) and (c in alt_vars):
+                relations[ A.gen(c) * A.gen(r) ] = - A.gen(r) * A.gen(c)
+    
+    H = A.g_algebra(relations=relations, order=order)
+    I = H.ideal([H.gen(i) *H.gen(i) for i in alt_vars]).twostd()
+    return H.quotient(I)
+
+cdef poly *addwithcarry(poly *tempvector, poly *maxvector, int pos, ring *_ring):
+    if p_GetExp(tempvector, pos, _ring) < p_GetExp(maxvector, pos, _ring):
+      p_SetExp(tempvector, pos, p_GetExp(tempvector, pos, _ring)+1, _ring)
+    else:
+      p_SetExp(tempvector, pos, 0, _ring)
+      tempvector = addwithcarry(tempvector, maxvector, pos + 1, _ring)
+    p_Setm(tempvector, _ring)
+    return tempvector
diff -r 10f49e34d981 -r dc42cb80eeef sage/rings/polynomial/term_order.py
--- a/sage/rings/polynomial/term_order.py	Mon Sep 19 16:34:42 2011 -0700
+++ b/sage/rings/polynomial/term_order.py	Sun Mar 13 15:24:15 2011 +0100
@@ -689,8 +689,9 @@
                     for block in block_names:
                         try:
                             length_pattern  = re.compile("\(([0-9]+)\)$") # match with parenthesized block length at end                  
-                            block_name, block_length, _ = re.split(length_pattern,block)
+                            block_name, block_length, _ = re.split(length_pattern, block.strip())
                             block_length = int(block_length)
+                            assert( block_length > 0)
                             blocks.append( TermOrder(block_name,block_length,force=force) )
                         except:
                             raise TypeError, "%s is not a valid term order"%(name,)
diff -r 10f49e34d981 -r dc42cb80eeef sage/rings/ring.pxd
--- a/sage/rings/ring.pxd	Mon Sep 19 16:34:42 2011 -0700
+++ b/sage/rings/ring.pxd	Sun Mar 13 15:24:15 2011 +0100
@@ -5,11 +5,11 @@
     cdef public object _one_element
     cdef public object _zero_ideal
     cdef public object _unit_ideal
+    cdef public object __ideal_monoid
     cdef _an_element_c_impl(self)
 
 cdef class CommutativeRing(Ring):
     cdef public object __fraction_field
-    cdef public object __ideal_monoid
 
 cdef class IntegralDomain(CommutativeRing):
     pass
diff -r 10f49e34d981 -r dc42cb80eeef sage/rings/ring.pyx
--- a/sage/rings/ring.pyx	Mon Sep 19 16:34:42 2011 -0700
+++ b/sage/rings/ring.pyx	Sun Mar 13 15:24:15 2011 +0100
@@ -1117,6 +1117,25 @@
             if not x.is_zero():
                 return x
 
+    def ideal_monoid(self):
+        """
+        Return the monoid of ideals of this ring.
+
+        EXAMPLES::
+
+            sage: ZZ.ideal_monoid()
+            Monoid of ideals of Integer Ring
+            sage: R.<x>=QQ[]; R.ideal_monoid()
+            Monoid of ideals of Univariate Polynomial Ring in x over Rational Field
+        """
+        if self.__ideal_monoid is not None:
+            return self.__ideal_monoid
+        else:
+            from sage.rings.ideal_monoid import IdealMonoid
+            M = IdealMonoid(self)
+            self.__ideal_monoid = M
+            return M
+
 cdef class CommutativeRing(Ring):
     """
     Generic commutative ring.
@@ -1256,25 +1275,6 @@
         """
         raise NotImplementedError
 
-    def ideal_monoid(self):
-        """
-        Return the monoid of ideals of this ring.
-
-        EXAMPLES::
-
-            sage: ZZ.ideal_monoid()
-            Monoid of ideals of Integer Ring
-            sage: R.<x>=QQ[]; R.ideal_monoid()
-            Monoid of ideals of Univariate Polynomial Ring in x over Rational Field
-        """
-        if self.__ideal_monoid is not None:
-            return self.__ideal_monoid
-        else:
-            from sage.rings.ideal_monoid import IdealMonoid
-            M = IdealMonoid(self)
-            self.__ideal_monoid = M
-            return M
-
     def quotient(self, I, names=None):
         """
         Create the quotient of R by the ideal I.
