Commits

Volker Braun committed a98e820

updated to sage-5.4.rc3

Comments (0)

Files changed (8)

 trac_11763_fix_associahedron.patch
 trac_11763_lazy_import.patch
 trac_13312_polyhedral_neg_polar.patch
-trac12215_weak_cached_function.patch    #+SimonKing
-trac12215_segfault_fixes.patch          #+SimonKing
-trac12215_my_segfault_unfix.patch       #+SimonKing
 trac_9880_revert_marking_random_from_trac_10187.patch #+pynac
 trac_11667_use_groebner_basis_with_degree_bound.patch  #+todo
 trac_11559_fix_Chow_group.patch   #+todo maybe delete
 trac_12553_palp_database.patch
 trac_13084_ppl_lattice_polygon.patch
 trac_13451_invariant_theory.patch
-trac_13451_binary_quadratic.patch
 trac_13084_toric_weierstrass.patch
 trac_13458_toric_Weierstrass_covering.patch
 trac_12892_orbit_closure_morphism.patch

trac12215_my_segfault_unfix.patch

-# HG changeset patch
-# Parent 9a32a7f311dedad3759e8c2ff8d89965eed92702
-diff --git a/sage/categories/action.pyx b/sage/categories/action.pyx
---- a/sage/categories/action.pyx
-+++ b/sage/categories/action.pyx
-@@ -53,11 +53,16 @@
-         self._is_left = is_left
-         self.op = op
- 
--    def __dealloc__(self):
--        if self.__domain is not None:
--            Py_INCREF(self.__domain)
--        if self.__codomain is not None:
--            Py_INCREF(self.__codomain)
-+    #def __cinit__(self):
-+    #    print 'Action __cinit__ ' + str(id(self))
-+
-+    #def __dealloc__(self):
-+    #    print 'Action __dealloc__ ' + str(id(self))
-+        #if self.__domain is not None:
-+        #    Py_INCREF(self.__domain)
-+        #if self.__codomain is not None:
-+        #    Py_INCREF(self.__codomain)
-+    #    pass
- 
-     def _apply_functor(self, x):
-         return self(x)

trac12215_segfault_fixes.patch

-# HG changeset patch
-# User Simon King <simon.king@uni-jena.de>
-# Date 1325028381 -3600
-# Node ID 033dfc4df60427c573eaebef7d5462893954dbc1
-# Parent  0eafa544448adf489086442357aa2e0b38913bf3
-#12215: Fixing segfaults resulting from the first patch of #12215 and from combination with #12313.
- - Rename pari._unsafe_deallocate_pari_stack into pari.__dealloc__.
- - Use a strong cache for symmetric function algebras.
- - Introduce sage.categories.action.Action.__dealloc__ that INCREASES the reference count of the (co)domain.
-
-diff --git a/sage/all.py b/sage/all.py
---- a/sage/all.py
-+++ b/sage/all.py
-@@ -233,7 +233,9 @@
-     import sage.libs.flint.flint
-     sage.libs.flint.flint.free_flint_stack()
- 
--    pari._unsafe_deallocate_pari_stack()
-+#    By trac ticket #12215, the deallocation is move to where it should happen,
-+#    namely PariInstance.__dealloc__.
-+#    pari._unsafe_deallocate_pari_stack()
-     
-     ### The following is removed -- since it would cleanup
-     ### the tmp directory that the sage cleaner depends upon.
-diff --git a/sage/categories/action.pyx b/sage/categories/action.pyx
---- a/sage/categories/action.pyx
-+++ b/sage/categories/action.pyx
-@@ -35,6 +35,7 @@
- from weakref import ref
- 
- include "../ext/stdsage.pxi"
-+include "../ext/python_ref.pxi"
- 
- cdef inline category(x):
-     try:
-@@ -52,7 +53,13 @@
-         self.S = ref(S)
-         self._is_left = is_left
-         self.op = op
--        
-+
-+    def __dealloc__(self):
-+        if self.__domain is not None:
-+            Py_INCREF(self.__domain)
-+        if self.__codomain is not None:
-+            Py_INCREF(self.__codomain)
-+
-     def _apply_functor(self, x):
-         return self(x)
-         
-diff --git a/sage/combinat/sf/sf.py b/sage/combinat/sf/sf.py
---- a/sage/combinat/sf/sf.py
-+++ b/sage/combinat/sf/sf.py
-@@ -4,6 +4,7 @@
- from sage.combinat.partition import Partitions
- from sage.combinat.free_module import CombinatorialFreeModule
- from sage.rings.rational_field import QQ
-+from sage.misc.cachefunc import cached_function
- 
- #from sage.combinat.sf.categories import *
- import sage.combinat.sf.sfa as sfa
-@@ -201,6 +202,26 @@
-        the coercions which have a cache.
- 
-     """
-+    @cached_function
-+    def __classcall__(cls, R):
-+        """
-+        By trac ticket #12290, :class:`~sage.structure.unique_representation.UniqueRepresentation`
-+        uses a weak cache. However, large parts of ``sage.combinat`` rely on
-+        symmetric function algebras being strongly cached. Therefore, we
-+        override the weak cache by a strong cache.
-+
-+        TESTS:
-+
-+        The following example would not work without a strong cache and is thus
-+        an indirect doctest::
-+
-+            sage: P = JackPolynomialsP(QQ,1)
-+            sage: p = P([2,1])
-+            sage: p^2            # indirect doctest
-+            JackP[2, 2, 1, 1] + JackP[2, 2, 2] + JackP[3, 1, 1, 1] + 2*JackP[3, 2, 1] + JackP[3, 3] + JackP[4, 1, 1] + JackP[4, 2]
-+
-+        """
-+        return super(SymmetricFunctions,cls).__classcall__(cls,R)
- 
-     def __init__(self, R):
-         """
-diff --git a/sage/libs/pari/gen.pyx b/sage/libs/pari/gen.pyx
---- a/sage/libs/pari/gen.pyx
-+++ b/sage/libs/pari/gen.pyx
-@@ -9016,7 +9016,14 @@
-         pariOut.flush = sage_flush
-         sig_off()
- 
--    def _unsafe_deallocate_pari_stack(self):
-+    def __dealloc__(self):
-+        """
-+        Proper deallocation of the unique pari instance.
-+
-+        See trac ticket #12215. The fact that Sage does not crash at exit
-+        is an indirect doctest.
-+
-+        """
-         if bot:
-             sage_free(<void*>bot)
-         global top, bot
-diff --git a/sage/rings/residue_field.pyx b/sage/rings/residue_field.pyx
---- a/sage/rings/residue_field.pyx
-+++ b/sage/rings/residue_field.pyx
-@@ -774,7 +774,6 @@
-         self._PBinv = PBinv
-         self._to_order = to_order # used for lift
-         self._PB = PB # used for lift
--        from sage.categories.homset import Hom
-         from sage.categories.all import SetsWithPartialMaps
-         self._repr_type_str = "Partially defined reduction"
-         Map.__init__(self, Hom(K, F, SetsWithPartialMaps()))
-@@ -938,11 +937,17 @@
-         abar
-         sage: (1+abar)^179
-         24*abar + 12
--        sage: k.coerce_map_from(OK)
-+        sage: phi = k.coerce_map_from(OK); phi
-         Ring morphism:
-           From: Maximal Order in Number Field in a with defining polynomial x^3 - 7
-           To:   Residue field in abar of Fractional ideal (2*a^2 + 3*a - 10)
- 
-+    By trac ticket #12215, phi is in fact contained in the homset with
-+    domain ``OK`` and codomain ``k``::
-+
-+        sage: phi in Hom(OK,k)
-+        True
-+
-         #sage: R.<t> = GF(19)[]; P = R.ideal(t^2 + 5)
-         #sage: k.<a> = R.residue_field(P)
-         #sage: f = k.coerce_map_from(R); f
-@@ -986,9 +991,8 @@
-         self._PBinv = PBinv
-         self._PB = PB # used for lift
-         self._to_order = to_order # used for lift
--        from sage.rings.homset import RingHomset
-         self._repr_type_str = "Reduction"
--        RingHomomorphism.__init__(self, RingHomset(K, F))
-+        RingHomomorphism.__init__(self, Hom(K,F))
- 
-     cpdef Element _call_(self, x):
-         """

trac12215_weak_cached_function.patch

-# HG changeset patch
-# User Simon King <simon.king@uni-jena.de>
-# Date 1324770536 -3600
-# Node ID 99523e355bff17c54bb3acd2ef56442829cd423c
-# Parent  7f1758ee8190d44d826e71c9e5145033adc4464f
-#12215: Introduce weak_cached_function, and use it in UniqueRepresentation.
-
-diff --git a/sage/categories/category.py b/sage/categories/category.py
---- a/sage/categories/category.py
-+++ b/sage/categories/category.py
-@@ -71,7 +71,9 @@
- from sage.structure.unique_representation import UniqueRepresentation
- from sage.structure.dynamic_class import dynamic_class_internal
- 
--@cached_function
-+from weakref import WeakValueDictionary
-+_join_cache = WeakValueDictionary()
-+
- def _join(categories, as_list):
-     """
-     This is an auxiliary function for :meth:`Category.join`
-@@ -100,6 +102,12 @@
-         from objects import Objects
-         return Objects()
- 
-+    if not as_list:
-+        try:
-+            return _join_cache[categories]
-+        except KeyError:
-+            pass
-+
-     # Ensure associativity by flattening JoinCategory's
-     # Invariant: the super categories of a JoinCategory are not JoinCategories themselves
-     categories = sum( (tuple(category.super_categories()) if isinstance(category, JoinCategory) else (category,)
-@@ -114,9 +122,10 @@
-     if as_list:
-         return list(result)
-     if len(result) == 1:
--        return result[0]
-+        out = _join_cache[categories] = result[0]
-     else:
--        return JoinCategory(result)
-+        out = _join_cache[categories] = JoinCategory(result)
-+    return out
- 
- 
- class Category(UniqueRepresentation, SageObject):
-@@ -233,10 +242,16 @@
-         ...               return "D"
-         ...
- 
--    Categories should always have uniq representation. We check
--    this before proceeding::
-+    Categories should always have unique representation; by trac ticket
-+    #12215, this means that it will be kept in cache, but only if there
-+    is still some strong reference to it.
-+    
-+    We check this before proceeding::
- 
-         sage: id(As()) == id(As())
-+        False
-+        sage: a = As()
-+        sage: id(As()) == id(As())
-         True
-         sage: As().parent_class == As().parent_class
-         True
-diff --git a/sage/misc/cachefunc.pyx b/sage/misc/cachefunc.pyx
---- a/sage/misc/cachefunc.pyx
-+++ b/sage/misc/cachefunc.pyx
-@@ -9,7 +9,7 @@
-   methods to instances).
- - Tom Boothby (added DiskCachedFunction).
- - Simon King (improved performance, more doctests, cython version,
--  added CachedMethodCallerNoArgs).
-+  added CachedMethodCallerNoArgs. Weak cached function).
- 
- EXAMPLES:
- 
-@@ -29,6 +29,43 @@
-     sage: test_pfunc(5) is test_pfunc(5)
-     True
- 
-+In some cases, one would only want to keep the result in cache as long
-+as there is any other reference to the result. By trac ticket #12215,
-+this is enabled for :class:`~sage.structure.unique_representation.UniqueRepresentation`,
-+which is used to create unique parents: If an algebraic structure, such
-+as a finite field, is only temporarily used, then it will not stay in
-+cache forever. That behaviour is implemented using ``weak_cached_function``,
-+that behaves the same as ``cached_function``, except that it uses a
-+``WeakValueDictionary`` for storing the results.
-+::
-+
-+    sage: from sage.misc.cachefunc import weak_cached_function
-+    sage: class A: pass
-+    sage: @weak_cached_function
-+    ... def f():
-+    ...    print "doing a computation"
-+    ...    return A()
-+    ...
-+    sage: a = f()
-+    doing a computation
-+
-+The result is cached::
-+    
-+    sage: b = f()
-+    sage: a is b
-+    True
-+
-+However, if there are no strong references left, the result
-+may be garbage collected, and thus a new computation would
-+take place::
-+
-+    sage: del a
-+    sage: del b
-+    sage: import gc
-+    sage: n = gc.collect()
-+    sage: a = f()
-+    doing a computation
-+
- Unfortunately, cython functions do not allow arbitrary
- decorators. However, one can wrap a Cython function and
- turn it into a cached function, by trac ticket #11115.
-@@ -272,6 +309,8 @@
- import os
- from sage.misc.sageinspect import sage_getfile, sage_getsourcelines
- 
-+from weakref import WeakValueDictionary
-+
- def _cached_function_unpickle(module,name):
-     """
-     Unpickling of cached functions.
-@@ -717,6 +756,190 @@
- 
- cached_function = CachedFunction
- 
-+cdef class WeakCachedFunction(CachedFunction):
-+    """
-+    A version of :class:`CachedFunction` using weak references on the values.
-+    
-+    If f is a function, do either ``g = weak_cached_function(f)`` to make
-+    a cached version of f, or put ``@weak_cached_function`` right before
-+    the definition of f (i.e., use Python decorators, but then
-+    the optional argument ``name`` can not be used)::
-+
-+        @weak_cached_function
-+        def f(...):
-+            ...
-+
-+    EXAMPLES::
-+
-+        sage: from sage.misc.cachefunc import weak_cached_function
-+        sage: class A: pass
-+        sage: @weak_cached_function
-+        ... def f():
-+        ...    print "doing a computation"
-+        ...    return A()
-+        ...
-+        sage: a = f()
-+        doing a computation
-+
-+    The result is cached::
-+
-+        sage: b = f()
-+        sage: a is b
-+        True
-+
-+    However, if there are no strong references left, the result
-+    may be garbage collected, and thus a new computation would
-+    take place::
-+
-+        sage: del a
-+        sage: del b
-+        sage: import gc
-+        sage: n = gc.collect()
-+        sage: a = f()
-+        doing a computation
-+
-+    """
-+    def __init__(self, f, classmethod=False, name=None):
-+        """
-+        The inputs to the function must be hashable.
-+        The outputs to the function must be weakly referenceable.
-+
-+        TESTS::
-+
-+            sage: from sage.misc.cachefunc import weak_cached_function
-+            sage: class A: pass
-+            sage: @weak_cached_function
-+            ... def f():
-+            ...    return A()
-+            ...
-+            sage: f
-+            Cached version of <function f at ...>
-+
-+        We demonstrate that pickling works, provided the uncached function
-+        is available::
-+
-+            sage: import __main__
-+            sage: __main__.f = f
-+            sage: loads(dumps(f))
-+            Cached version of <function f at ...>
-+            sage: f.cache
-+            <WeakValueDictionary at ...>
-+
-+        """
-+        self._common_init(f, ArgumentFixer(f,classmethod=classmethod), name=name)
-+        self.cache = WeakValueDictionary()
-+    def __call__(self, *args, **kwds):
-+        """
-+        Return value from cache or call the wrapped function,
-+        caching the output.
-+
-+        TESTS::
-+
-+            sage: from sage.misc.cachefunc import weak_cached_function
-+            sage: class A: pass
-+            sage: @weak_cached_function
-+            ... def f():
-+            ...    print "doing a computation"
-+            ...    return A()
-+            ...
-+            sage: a = f()    # indirect doctest
-+            doing a computation
-+
-+        The result is cached::
-+
-+            sage: b = f()
-+            sage: a is b
-+            True
-+
-+        However, if there are no strong references left, the result
-+        may be garbage collected, and thus a new computation would
-+        take place::
-+
-+            sage: del a
-+            sage: del b
-+            sage: import gc
-+            sage: n = gc.collect()
-+            sage: a = f()
-+            doing a computation
-+
-+        """
-+        # We shortcut a common case of no arguments
-+        if args or kwds:
-+            k = self._fix_to_pos(*args, **kwds)
-+        else:
-+            if self._default_key is not None:
-+                k = self._default_key
-+            else:
-+                k = self._default_key = self._fix_to_pos()
-+
-+        try:
-+            return self.cache[k]
-+        except KeyError:
-+            w = self.f(*args, **kwds)
-+            self.cache[k] = w
-+            return w
-+    def is_in_cache(self, *args, **kwds):
-+        """
-+        Checks if the argument list is in the cache.
-+
-+        EXAMPLES::
-+
-+            sage: from sage.misc.cachefunc import weak_cached_function
-+            sage: class A:
-+            ...     def __init__(self, x):
-+            ...         self.x = x
-+            ...
-+            sage: @weak_cached_function
-+            ... def f(n):
-+            ...    return A(n)
-+            ...
-+            sage: a = f(5)
-+
-+        The key 5 is in the cache, as long as there is a strong
-+        reference to the corresponding value::
-+
-+            sage: f.is_in_cache(5)
-+            True
-+
-+        However, if there are no strong references left, the cached
-+        item is removed from cache after garbage collection::
-+
-+            sage: del a
-+            sage: import gc
-+            sage: n = gc.collect()
-+            sage: f.is_in_cache(5)
-+            False
-+
-+        """
-+        return self._fix_to_pos(*args, **kwds) in self.cache
-+
-+    def set_cache(self, value, *args, **kwds):
-+        """
-+        Set the value for those args and keyword args
-+        Mind the unintuitive syntax (value first).
-+        Any idea on how to improve that welcome!
-+
-+        It is required that the given value is weak
-+        referenceable. The item will be removed from
-+        cache if the value is garbage collected.
-+
-+        EXAMPLES::
-+
-+            sage: from sage.misc.cachefunc import weak_cached_function
-+            sage: @weak_cached_function
-+            ... def f(n):
-+            ...     raise RuntimeError
-+            ...
-+            sage: f.set_cache(ZZ, 5)
-+            sage: f(5)
-+            Integer Ring
-+
-+         """
-+        self.cache[self._fix_to_pos(*args, **kwds)] = value
-+
-+
-+weak_cached_function = WeakCachedFunction
-+
- class CachedMethodPickle(object):
-     """
-     This class helps to unpickle cached methods.
-diff --git a/sage/rings/polynomial/polynomial_ring_constructor.py b/sage/rings/polynomial/polynomial_ring_constructor.py
---- a/sage/rings/polynomial/polynomial_ring_constructor.py
-+++ b/sage/rings/polynomial/polynomial_ring_constructor.py
-@@ -42,7 +42,7 @@
- from sage.rings.integer import Integer
- from sage.rings.finite_rings.integer_mod_ring import is_IntegerModRing
- 
--from sage.misc.cachefunc import cached_function
-+from sage.misc.cachefunc import weak_cached_function
- 
- from sage.categories.fields import Fields
- _Fields = Fields()
-@@ -553,7 +553,7 @@
- _IntegralDomains = categories.integral_domains.IntegralDomains()
- _Rings = category = categories.rings.Rings()
- 
--@cached_function
-+@weak_cached_function
- def polynomial_default_category(base_ring,multivariate):
-     """
-     Choose an appropriate category for a polynomial ring.
-diff --git a/sage/structure/dynamic_class.py b/sage/structure/dynamic_class.py
---- a/sage/structure/dynamic_class.py
-+++ b/sage/structure/dynamic_class.py
-@@ -116,7 +116,7 @@
- #                  http://www.gnu.org/licenses/
- #*****************************************************************************
- 
--from sage.misc.cachefunc import cached_function
-+from sage.misc.cachefunc import weak_cached_function
- from sage.structure.unique_representation import ClasscallMetaclass
- 
- def dynamic_class(name, bases, cls = None, reduction = None, doccls=None):
-@@ -255,7 +255,7 @@
-     #    assert(cls is None or issubtype(type(cls), type) or type(cls) is classobj)
-     return dynamic_class_internal(name, bases, cls, reduction, doccls)
- 
--@cached_function
-+@weak_cached_function
- def dynamic_class_internal(name, bases, cls = None, reduction = None, doccls = None):
-     r"""
-     See sage.structure.dynamic_class.dynamic_class? for indirect doctests.
-diff --git a/sage/structure/factory.pyx b/sage/structure/factory.pyx
---- a/sage/structure/factory.pyx
-+++ b/sage/structure/factory.pyx
-@@ -37,11 +37,13 @@
-     def __init__(self, name):
-         """
-         INPUT: 
--            name -- a name in the global namespace referring to self 
--                    or a fully qualified path name to self, which is 
--                    used to locate the factory on unpickling. 
-+
-+        name -- a name in the global namespace referring to self 
-+                or a fully qualified path name to self, which is 
-+                used to locate the factory on unpickling. 
-                     
--        EXAMPLES: 
-+        EXAMPLES::
-+
-             sage: from sage.structure.factory import UniqueFactory
-             sage: fake_factory = UniqueFactory('ZZ')
-             sage: loads(dumps(fake_factory))
-@@ -51,11 +53,12 @@
-             Rational Field
-         """
-         self._name = name
--        self._cache = {}
-+        self._cache = weakref.WeakValueDictionary()
-         
-     def __reduce__(self):
-         """
--        EXAMPLES: 
-+        EXAMPLES::
-+
-             sage: A = FiniteField(127)
-             sage: A is loads(dumps(A)) # indirect doctest
-             True
-@@ -69,7 +72,8 @@
-             sage: D is loads(dumps(D))
-             True
-             
--        TESTS:
-+        TESTS::
-+
-             sage: loads(dumps(FiniteField)) is FiniteField
-             True
-             sage: from sage.structure.factory import test_factory
-@@ -88,19 +92,24 @@
-         Do not override this method, override create_key and create_object and 
-         put the docstring in the body of the class. 
-         
--        EXAMPLES: 
-+        EXAMPLES::
-+
-             sage: from sage.structure.factory import test_factory
-             sage: _ = test_factory(1,2,3); _
-             Making object (1, 2, 3)
-             <sage.structure.factory.A instance at ...>
-             
-         It already created one, so don't re-create.
-+        ::
-+
-             sage: test_factory(1,2,3)
-             <sage.structure.factory.A instance at ...>
-             sage: test_factory(1,2,3) is test_factory(1,2,3)
-             True
-             
-         Of course, with a different key, a new object will be created. 
-+        ::
-+
-             sage: test_factory(1,2,3) is test_factory(1,2,4)
-             Making object (1, 2, 4)
-             False
-@@ -115,7 +124,8 @@
-         if necessary (for example, it isn't in the cache or it is unpickling
-         from an older version of Sage). 
-         
--        EXAMPLES: 
-+        EXAMPLES::
-+
-             sage: from sage.structure.factory import test_factory
-             sage: a = test_factory.get_object(3.0, 'a', {}); a
-             Making object a
-@@ -130,25 +140,21 @@
-             False
-         """
-         try:
--            obj = self._cache[version, key]()
--            if obj is not None:
--                return obj
-+            return self._cache[version, key]
-         except KeyError:
-             pass
-         obj = self.create_object(version, key, **extra_args)
--        self._cache[version, key] = weakref.ref(obj)
-+        self._cache[version, key] = obj
-         try:
-             other_keys = self.other_keys(key, obj)
-             for key in other_keys:
-                 try:
--                    new_obj = self._cache[version, key]()
--                    if new_obj is not None:
--                        obj = new_obj
--                        break
-+                    obj = self._cache[version, key]
-+                    break
-                 except KeyError:
-                     pass
-             for key in other_keys:
--                self._cache[version, key] = weakref.ref(obj)
-+                self._cache[version, key] = obj
-             obj._factory_data = self, version, key, extra_args
-             if obj.__class__.__reduce__.__objclass__ is object:
-                 # replace the generic object __reduce__ to use this one
-@@ -156,7 +162,7 @@
-         except AttributeError:
-             pass
-         return obj
--        
-+
-     cpdef get_version(self, sage_version):
-         """
-         This is provided to allow more or less granular control over
-@@ -171,7 +177,8 @@
-         Defaults to the Sage version that is passed in, but courser
-         granularity can be provided. 
-         
--        EXAMPLES: 
-+        EXAMPLES::
-+
-             sage: from sage.structure.factory import test_factory
-             sage: test_factory.get_version((3,1,0))
-             (3, 1, 0)
-@@ -185,7 +192,8 @@
-         
-         Defaults to \code{self.create_key}. 
-         
--        EXAMPLES: 
-+        EXAMPLES::
-+
-             sage: from sage.structure.factory import test_factory
-             sage: test_factory.create_key_and_extra_args(1, 2, key=5)
-             ((1, 2), {})
-@@ -199,7 +207,8 @@
-         Given the arguments and keywords, create a key that uniquely 
-         determines this object.
-         
--        EXAMPLES: 
-+        EXAMPLES::
-+
-             sage: from sage.structure.factory import test_factory
-             sage: test_factory.create_key(1, 2, key=5)
-             (1, 2)
-@@ -211,7 +220,8 @@
-         Create the object from the key and extra arguments. This is only 
-         called if the object was not found in the cache.
-         
--        EXAMPLES: 
-+        EXAMPLES::
-+
-             sage: from sage.structure.factory import test_factory
-             sage: test_factory.create_object(0, (1,2,3))
-             Making object (1, 2, 3)
-@@ -230,7 +240,8 @@
-         may result in a new (more specific) key. This allows the more specific 
-         key to be cached as well, and used for pickling. 
- 
--        EXAMPLES: 
-+        EXAMPLES::
-+
-             sage: key, _ = GF.create_key_and_extra_args(27, 'k'); key
-             (27, ('k',), 'conway', None, '{}', 3, 3, True)
-             sage: K = GF.create_object(0, key); K
-@@ -251,7 +262,8 @@
-         here so the factory internals can change without having to re-write
-         __reduce__ methods that use it. 
-         
--        EXAMPLE:               
-+        EXAMPLE::
-+
-             sage: V = FreeModule(ZZ, 5)
-             sage: factory, data = FreeModule.reduce_data(V)
-             sage: factory(*data)
-@@ -282,7 +294,8 @@
-     It takes a factory as the first argument, passes the rest of the 
-     arguments onto the factory's get_object method. 
-     
--    EXAMPLES: 
-+    EXAMPLES::
-+
-         sage: V = FreeModule(ZZ, 5)
-         sage: func, data = FreeModule.reduce_data(V)
-         sage: func is sage.structure.factory.generic_factory_unpickle
-@@ -296,7 +309,8 @@
-     """
-     Used to provide a __reduce__ method if one does not already exist.
-     
--    EXAMPLES: 
-+    EXAMPLES::
-+
-         sage: V = QQ^6
-         sage: sage.structure.factory.generic_factory_reduce(V, 1) == V.__reduce_ex__(1)
-         True
-@@ -310,7 +324,8 @@
-     """
-     Used in unpickling the factory itself. 
-     
--    EXAMPLES: 
-+    EXAMPLES::
-+
-         sage: from sage.structure.factory import lookup_global
-         sage: lookup_global('ZZ')
-         Integer Ring
-@@ -333,7 +348,8 @@
- 
-     def create_key(self, *args, **kwds):
-         """
--        EXAMPLES: 
-+        EXAMPLES::
-+
-             sage: from sage.structure.factory import UniqueFactoryTester
-             sage: test_factory = UniqueFactoryTester('foo')
-             sage: test_factory.create_key(1, 2, 3)
-@@ -343,7 +359,8 @@
-     
-     def create_object(self, version, key, **extra_args):
-         """
--        EXAMPLES: 
-+        EXAMPLES::
-+
-             sage: from sage.structure.factory import UniqueFactoryTester
-             sage: test_factory = UniqueFactoryTester('foo')
-             sage: test_factory.create_object('version', key=(1, 2, 4))
-diff --git a/sage/structure/unique_representation.py b/sage/structure/unique_representation.py
---- a/sage/structure/unique_representation.py
-+++ b/sage/structure/unique_representation.py
-@@ -16,7 +16,7 @@
- #                  http://www.gnu.org/licenses/
- #******************************************************************************
- 
--from sage.misc.cachefunc import cached_function
-+from sage.misc.cachefunc import weak_cached_function
- from sage.misc.classcall_metaclass import ClasscallMetaclass
- 
- class UniqueRepresentation:
-@@ -91,11 +91,14 @@
-         ...
- 
-     Two coexisting instances of MyClass created with the same
--    argument data are guaranteed to share the same identity::
-+    argument data are guaranteed to share the same identity. Since
-+    trac ticket #12215, this is only the case if there is some
-+    strong reference to the returned instance, since otherwise
-+    it may be garbage collected::
- 
-         sage: x = MyClass(1)
-         sage: y = MyClass(1)
--        sage: x is y
-+        sage: x is y               # There is a strong reference
-         True
-         sage: z = MyClass(2)
-         sage: x is z
-@@ -432,7 +435,7 @@
- 
-     __metaclass__ = ClasscallMetaclass
- 
--    @cached_function # automatically a staticmethod
-+    @weak_cached_function # automatically a staticmethod
-     def __classcall__(cls, *args, **options):
-         """
-         Constructs a new object of this class or reuse an existing one.

trac_11763_lazy_import.patch

 # HG changeset patch
-# Parent c6f0386fe64054ecf920477e9c312bba111e6b01
+# Parent 4d74b3c885558318f735d0f2f90c73ddc85414c7
 
 Lazily import Polyhedron
 
 -from polyhedra import PolyhedralSets
 +from sage.misc.lazy_import import lazy_import
 +lazy_import('sage.categories.polyhedra', 'PolyhedralSets')
+diff --git a/sage/combinat/root_system/all.py b/sage/combinat/root_system/all.py
+--- a/sage/combinat/root_system/all.py
++++ b/sage/combinat/root_system/all.py
+@@ -1,4 +1,6 @@
+-from associahedron import Associahedron
++from sage.misc.lazy_import import lazy_import
++lazy_import('sage.combinat.root_system.associahedron', 'Associahedron')
++
+ from cartan_type import CartanType
+ from dynkin_diagram import DynkinDiagram, dynkin_diagram
+ from cartan_matrix import cartan_matrix
 diff --git a/sage/geometry/polyhedron/all.py b/sage/geometry/polyhedron/all.py
 --- a/sage/geometry/polyhedron/all.py
 +++ b/sage/geometry/polyhedron/all.py

trac_13451_binary_quadratic.patch

-# HG changeset patch
-# Parent 9f9a4b3b5b4068a38d6fb099e7501fdfe777b682
-
-Add binary quadratic forms and their discriminant
-
-diff --git a/sage/schemes/invariant_theory.py b/sage/schemes/invariant_theory.py
---- a/sage/schemes/invariant_theory.py
-+++ b/sage/schemes/invariant_theory.py
-@@ -105,6 +105,7 @@
- ########################################################################
- 
- from sage.rings.all import QQ
-+from sage.misc.functional import is_odd
- from sage.matrix.constructor import matrix
- from sage.structure.sage_object import SageObject
- from sage.misc.cachefunc import cached_method
-@@ -112,6 +113,45 @@
- 
- 
- ######################################################################
-+def _guess_variables(polynomial, *args):
-+    """
-+    Return the polynomial variables
-+
-+    INPUT:
-+
-+    - ``polynomial`` -- a polynomial.
-+
-+    - ``*args`` -- the variables. If none are specified, all variables
-+      in ``polynomial`` are returned. If a list or tuple is passed,
-+      the content is returned. If multiple arguments are passed, they
-+      are returned.
-+
-+    OUTPUT:
-+
-+    A tuple of variables in the parent ring of the polynoimal.
-+    
-+    EXAMPLES::
-+
-+       sage: from sage.schemes.invariant_theory import _guess_variables
-+       sage: R.<x,y> = QQ[]
-+       sage: _guess_variables(x^2+y^2)
-+       (x, y)
-+       sage: _guess_variables(x^2+y^2, x)
-+       (x,)
-+       sage: _guess_variables(x^2+y^2, x,y)
-+       (x, y)
-+       sage: _guess_variables(x^2+y^2, [x,y])
-+       (x, y)
-+    """
-+    if len(args)==0 or (len(args)==1 and args[0] is None):
-+        return polynomial.variables()
-+    elif len(args) == 1 and isinstance(args[0], (tuple, list)):
-+        return tuple(args[0])
-+    else:
-+        return tuple(args)
-+    
-+
-+######################################################################
- 
- class AlgebraicForm(SageObject):
-     """
-@@ -190,12 +230,7 @@
-         self._n = n
-         self._d = d
-         self._polynomial = polynomial
--        if len(args)==0 or (len(args)==1 and args[0] is None):
--            variables = polynomial.variables()
--        elif len(args) == 1 and isinstance(args[0], (tuple, list)):
--            variables = tuple(args[0])
--        else:
--            variables = tuple(args)
-+        variables = _guess_variables(polynomial, *args)
-         if len(variables) == n:
-             pass
-         elif len(variables) == n-1:
-@@ -442,6 +477,264 @@
- 
- ######################################################################
- 
-+class QuadraticForm(AlgebraicForm):
-+    """
-+    Invariant theory of a multivariate quadratic form
-+    
-+    You should use the :class:`invariant_theory
-+    <InvariantTheoryFactory>` factory object to contstruct instances
-+    of this class. See :meth:`~InvariantTheoryFactory.quadratic_form`
-+    for details.
-+
-+    TESTS::
-+
-+        sage: R.<a,b,c,d,e,f,g, x,y,z> = QQ[]
-+        sage: p = a*x^2 + b*y^2 + c*z^2 + d*x*y + e*x*z + f*y*z
-+        sage: invariant_theory.quadratic_form(p, x,y,z)
-+        ternary quadratic with coefficients (a, b, c, d, e, f)
-+        sage: type(_)
-+        <class 'sage.schemes.invariant_theory.TernaryQuadratic'>
-+
-+        sage: R.<a,b,c,d,e,f,g, x,y,z> = QQ[]
-+        sage: p = a*x^2 + b*y^2 + c*z^2 + d*x*y + e*x*z + f*y*z
-+        sage: invariant_theory.quadratic_form(p, x,y,z)
-+        ternary quadratic with coefficients (a, b, c, d, e, f)
-+        sage: type(_)
-+        <class 'sage.schemes.invariant_theory.TernaryQuadratic'>
-+
-+    Since we can not always decide whether the form is homogeneous or
-+    not based on the number of variables, you need to explicitly
-+    specify it if you want the variables to be treated as
-+    inhomogeneous::
-+
-+        sage: invariant_theory.inhomogeneous_quadratic_form(p.subs(z=1), x,y)
-+        ternary quadratic with coefficients (a, b, c, d, e, f)
-+   """
-+
-+    def __init__(self, n, polynomial, *args):
-+        """
-+        The Python constructor
-+
-+        TESTS::
-+
-+            sage: R.<x,y> = QQ[]
-+            sage: from sage.schemes.invariant_theory import QuadraticForm
-+            sage: QuadraticForm(2, x^2+2*y^2+3*x*y)
-+            binary quadratic with coefficients (1, 2, 3)
-+            sage: QuadraticForm(3, x^2+y^2)
-+            ternary quadratic with coefficients (1, 1, 0, 0, 0, 0)
-+        """
-+        super(QuadraticForm, self).__init__(n, 2, polynomial, *args)
-+
-+
-+    @cached_method
-+    def monomials(self):
-+        """
-+        List the basis monomials in the form.
-+        
-+        OUTPUT:
-+
-+        A tuple of monomials. They are in the same order as
-+        :meth:`coeffs`.
-+
-+        EXAMPLES::
-+
-+            sage: R.<x,y> = QQ[]
-+            sage: quadratic = invariant_theory.quadratic_form(x^2+y^2)
-+            sage: quadratic.monomials()
-+            (x^2, y^2, x*y)
-+
-+            sage: quadratic = invariant_theory.inhomogeneous_quadratic_form(x^2+y^2)
-+            sage: quadratic.monomials()
-+            (x^2, y^2, 1, x*y, x, y)
-+        """
-+        var = self._variables
-+        def prod(a,b):
-+            if a is None and b is None: 
-+                return self._ring.one()
-+            elif a is None:
-+                return b
-+            elif b is None:
-+                return a
-+            else:
-+                return a*b
-+        squares = tuple( prod(x,x) for x in var )
-+        mixed = []
-+        for i in range(self._n):
-+            for j in range(i+1, self._n):
-+                mixed.append(prod(var[i], var[j]))
-+        mixed = tuple(mixed)
-+        return squares + mixed
-+
-+
-+    @cached_method
-+    def coeffs(self):
-+        """
-+        The coefficients of a binary quartic.
-+    
-+        Given
-+    
-+        .. math::
-+    
-+            f(x) = a_0 x_1^4 + a_1 x_0 x_1^3 + a_2 x_0^2 x_1^2 +
-+                   a_3 x_0^3 x_1 + a_4 x_0^4
-+    
-+        this function returns `a = (a_0, a_1, a_2, a_3, a_4)`
-+    
-+        EXAMPLES::
-+    
-+            sage: R.<a0, a1, a2, a3, a4, x0, x1> = QQ[]
-+            sage: p = a0*x1^4 + a1*x1^3*x0 + a2*x1^2*x0^2 + a3*x1*x0^3 + a4*x0^4
-+            sage: quartic = invariant_theory.binary_quartic(p, x0, x1)
-+            sage: quartic.coeffs()
-+            (a0, a1, a2, a3, a4)
-+    
-+            sage: R.<a0, a1, a2, a3, a4, x> = QQ[]
-+            sage: p = a0 + a1*x + a2*x^2 + a3*x^3 + a4*x^4
-+            sage: quartic = invariant_theory.binary_quartic(p, x)
-+            sage: quartic.coeffs()
-+            (a0, a1, a2, a3, a4)
-+        """
-+        return self._extract_coefficients(self.monomials())
-+
-+
-+    def scaled_coeffs(self):
-+        """
-+        The coefficients of a binary quartic.
-+    
-+        Given
-+    
-+        .. math::
-+    
-+            f(x) = a_0 x_1^4 + 4 a_1 x_0 x_1^3 + 6 a_2 x_0^2 x_1^2 +
-+                   4 a_3 x_0^3 x_1 + a_4 x_0^4
-+    
-+        this function returns `a = (a_0, a_1, a_2, a_3, a_4)`
-+    
-+        EXAMPLES::
-+    
-+            sage: R.<a,b,c,d,e,f,g, x,y,z> = QQ[]
-+            sage: p = a*x^2 + b*y^2 + c*z^2 + d*x*y + e*x*z + f*y*z
-+            sage: inv = invariant_theory.quadratic_form(p, x,y,z); inv
-+            ternary quadratic with coefficients (a, b, c, d, e, f)
-+            sage: inv.coeffs()
-+            (a, b, c, d, e, f)
-+            sage: inv.scaled_coeffs()
-+            (a, b, c, 1/2*d, 1/2*e, 1/2*f)
-+        """
-+        coeff = self.coeffs()
-+        squares = coeff[0:self._n]
-+        mixed = tuple( c/2 for c in coeff[self._n:] )
-+        return squares + mixed
-+    
-+
-+    @cached_method
-+    def matrix(self):
-+        """
-+        Return the quadratic form as a symmetric matrix
-+
-+        OUTPUT:
-+        
-+        This method returns a symmetric matrix `A` such that the
-+        quadratic `Q` equals
-+
-+        .. math::
-+
-+            Q(x,y,z,\dots) = (x,y,\dots) A (x,y,\dots)^t
-+
-+        EXAMPLES::
-+
-+            sage: R.<x,y,z> = QQ[]
-+            sage: quadratic = invariant_theory.ternary_quadratic(x^2+y^2+z^2+x*y)
-+            sage: matrix(quadratic)
-+            [  1 1/2   0]
-+            [1/2   1   0]
-+            [  0   0   1]
-+            sage: quadratic._matrix_() == matrix(quadratic)
-+            True
-+        """
-+        coeff = self.scaled_coeffs()
-+        A = matrix(self._ring, self._n)
-+        for i in range(self._n):
-+            A[i,i] = coeff[i]
-+        ij = self._n
-+        for i in range(self._n):
-+            for j in range(i+1, self._n):
-+                A[i,j] = coeff[ij]
-+                A[j,i] = coeff[ij]
-+                ij += 1
-+        return A
-+
-+    _matrix_ = matrix
-+
-+    
-+    def discriminant(self):
-+        """
-+        Return the discriminant of the quadratic form.
-+
-+        Up to an overall constant factor, this is just the determinant
-+        of the defining matrix, see :meth:`matrix`. For a quadratic
-+        form in `n` variables, the overall constant is `2^{n-1}` if
-+        `n` is odd and `(-1)^{n/2} 2^n` if `n` is even.
-+
-+        EXAMPLES::
-+
-+            sage: R.<a,b,c, x,y> = QQ[]
-+            sage: p = a*x^2+b*x*y+c*y^2
-+            sage: quadratic = invariant_theory.quadratic_form(p, x,y)
-+            sage: quadratic.discriminant()
-+            b^2 - 4*a*c
-+
-+            sage: R.<a,b,c,d,e,f,g, x,y,z> = QQ[]
-+            sage: p = a*x^2 + b*y^2 + c*z^2 + d*x*y + e*x*z + f*y*z
-+            sage: quadratic = invariant_theory.quadratic_form(p, x,y,z)
-+            sage: quadratic.discriminant()
-+            4*a*b*c - c*d^2 - b*e^2 + d*e*f - a*f^2
-+        """
-+        A = 2*self._matrix_()
-+        if is_odd(self._n):
-+            return A.det() / 2
-+        else:
-+            return (-1)**(self._n/2) * A.det()
-+
-+
-+
-+    def as_QuadraticForm(self):
-+        """
-+        Convert into a :class:`~sage.quadratic_forms.quadratic_form.QuadraticForm`.
-+        
-+        OUTPUT:
-+
-+        Sage has a special quadratic forms subsystem. This method
-+        converts ``self`` into this
-+        :class:`~sage.quadratic_forms.quadratic_form.QuadraticForm`
-+        representation.
-+
-+        EXAMPLES::
-+
-+            sage: R.<x,y,z> = QQ[]
-+            sage: p = x^2+y^2+z^2+2*x*y+3*x*z
-+            sage: quadratic = invariant_theory.ternary_quadratic(p)
-+            sage: matrix(quadratic)
-+            [  1   1 3/2]
-+            [  1   1   0]
-+            [3/2   0   1]
-+            sage: quadratic.as_QuadraticForm()
-+            Quadratic form in 3 variables over Multivariate Polynomial 
-+            Ring in x, y, z over Rational Field with coefficients: 
-+            [ 1/2 1 3/2 ]
-+            [ * 1/2 0 ]
-+            [ * * 1/2 ]
-+            sage: _.polynomial('X,Y,Z')
-+            X^2 + 2*X*Y + Y^2 + 3*X*Z + Z^2
-+       """
-+        R = self._ring
-+        B = self._matrix_()
-+        import sage.quadratic_forms.quadratic_form
-+        return sage.quadratic_forms.quadratic_form.QuadraticForm(R, B)
-+
-+######################################################################
-+
- class BinaryQuartic(AlgebraicForm):
-     """
-     Invariant theory of a binary quartic
-@@ -780,7 +1073,7 @@
- 
- 
- ######################################################################
--class TernaryQuadratic(AlgebraicForm):
-+class TernaryQuadratic(QuadraticForm):
-     """
-     Invariant theory of a ternary quadratic
-     
-@@ -813,7 +1106,7 @@
-             sage: TernaryQuadratic(x^2+y^2+z^2)
-             ternary quadratic with coefficients (1, 1, 1, 0, 0, 0)
-         """
--        super(TernaryQuadratic, self).__init__(3, 2, polynomial, *args)
-+        super(QuadraticForm, self).__init__(3, 2, polynomial, *args)
-         self._x = self._variables[0]
-         self._y = self._variables[1]
-         self._z = self._variables[2]
-@@ -905,41 +1198,6 @@
- 
- 
-     @cached_method
--    def _matrix_(self):
--        """
--        Return the quadratic as a symmetric matrix
--
--        OUTPUT:
--        
--        This method returns a symmetric matrix `A` such that the
--        quadratic `Q` equals
--
--        .. math::
--
--            Q(x,y,z) = (x,y,z) A (x,y,z)^t
--
--        EXAMPLES::
--
--            sage: R.<x,y,z> = QQ[]
--            sage: quadratic = invariant_theory.ternary_quadratic(x^2+y^2+z^2+x*y)
--            sage: matrix(quadratic)
--            [  1 1/2   0]
--            [1/2   1   0]
--            [  0   0   1]
--            sage: quadratic._matrix_() == matrix(quadratic)
--            True
--        """
--        a200, a020, a002, a110, a101, a011 = self.scaled_coeffs()
--        A = matrix(self._ring, [
--                [a200, a110, a101],
--                [a110, a020, a011], 
--                [a101, a011, a002]])
--        return A
--
--    matrix = _matrix_
--
--
--    @cached_method
-     def dual(self):
-         """
-         Return the dual ternary quadratic
-@@ -1424,7 +1682,61 @@
-         ternary cubic with coefficients (1, 1, 1, 0, 0, 0, 0, 0, 0, 0)
-     """
-     
--    def binary_quartic(self, *args, **kwds):
-+    def quadratic_form(self, polynomial, *args,  **kwds):
-+        """
-+        Invariants of a homogeneous quadratic form
-+    
-+        INPUT:
-+        
-+        - ``quadratic`` -- a homogeneous quadratic in 3 homogeneous
-+          variables, or an inhomogeneous quadratic in 2 variables.
-+        
-+        - ``x``, ``y``, ``z`` -- the variables. If ``z`` is ``None``,
-+          the cubic is assumed to be inhomogeneous.
-+        
-+        EXAMPLES::
-+        
-+            sage: R.<x,y,z> = QQ[]
-+            sage: quadratic = x^2+y^2+z^2
-+            sage: inv = invariant_theory.quadratic_form(quadratic)
-+            sage: type(inv)
-+            <class 'sage.schemes.invariant_theory.TernaryQuadratic'>
-+        """
-+        variables = _guess_variables(polynomial, *args)
-+        n = len(variables)
-+        if n == 3:
-+            return TernaryQuadratic(polynomial, *args, **kwds)
-+        else:
-+            return QuadraticForm(n, polynomial, *args, **kwds)
-+
-+    def inhomogeneous_quadratic_form(self, polynomial, *args,  **kwds):
-+        """
-+        Invariants of an inhomogeneous quadratic form
-+    
-+        INPUT:
-+        
-+        - ``quadratic`` -- a homogeneous quadratic in 3 homogeneous
-+          variables, or an inhomogeneous quadratic in 2 variables.
-+        
-+        - ``x``, ``y``, ``z`` -- the variables. If ``z`` is ``None``,
-+          the cubic is assumed to be inhomogeneous.
-+        
-+        EXAMPLES::
-+        
-+            sage: R.<x,y,z> = QQ[]
-+            sage: quadratic = x^2+2*y^2+3*x*y+4*x+5*y+6
-+            sage: inv = invariant_theory.inhomogeneous_quadratic_form(quadratic)
-+            sage: type(inv)
-+            <class 'sage.schemes.invariant_theory.TernaryQuadratic'>
-+        """
-+        variables = _guess_variables(polynomial, *args)
-+        n = len(variables) + 1
-+        if n == 3:
-+            return TernaryQuadratic(polynomial, *args, **kwds)
-+        else:
-+            return QuadraticForm(n, polynomial, *args, **kwds)
-+
-+    def binary_quartic(self, quartic, *args, **kwds):
-         """
-         Invariant theory of a quartic in two variables
-     
-@@ -1470,9 +1782,9 @@
-             sage: type(quartic)
-             <class 'sage.schemes.invariant_theory.BinaryQuartic'>
-         """
--        return BinaryQuartic(*args, **kwds)
-+        return BinaryQuartic(quartic, *args, **kwds)
- 
--    def ternary_quadratic(self, *args, **kwds):
-+    def ternary_quadratic(self, quadratic, *args, **kwds):
-         """
-         Invariants of a cubic in three variables
-     
-@@ -1492,9 +1804,9 @@
-             sage: type(inv)
-             <class 'sage.schemes.invariant_theory.TernaryQuadratic'>
-         """
--        return TernaryQuadratic(*args, **kwds)
-+        return TernaryQuadratic(quadratic, *args, **kwds)
- 
--    def ternary_cubic(self, *args, **kwds):
-+    def ternary_cubic(self, cubic, *args, **kwds):
-         r"""
-         Invariants of a cubic in three variables
-     
-@@ -1579,7 +1891,7 @@
-             ...     +54*S*T*U^2*H^4 -432*S^2*U*H^5 -27*T*H^6 )
-             0
-         """
--        return TernaryCubic(*args, **kwds)
-+        return TernaryCubic(cubic, *args, **kwds)
- 
- 
- invariant_theory = InvariantTheoryFactory()

trac_13451_invariant_theory.patch

 # HG changeset patch
-# Parent 7fed67aab52513896cd79b72dffc2edb236ec1f5
+# Parent 02cc3facf8d37706c121b9c4fb0e8182ab6a5c6a
 
-Classical invariant theory: binary quartic and ternary cubic
+Classical invariant theory: binary quartic and ternary cubic, binary
+quadratic forms and their discriminant
 
-diff --git a/doc/en/reference/schemes.rst b/doc/en/reference/schemes.rst
---- a/doc/en/reference/schemes.rst
-+++ b/doc/en/reference/schemes.rst
-@@ -7,6 +7,7 @@
-    :maxdepth: 2
+diff --git a/doc/en/reference/rings.rst b/doc/en/reference/rings.rst
+--- a/doc/en/reference/rings.rst
++++ b/doc/en/reference/rings.rst
+@@ -17,3 +17,4 @@
+    sage/rings/fraction_field_element
+    sage/rings/quotient_ring
+    sage/rings/quotient_ring_element
++   sage/rings/invariant_theory
+diff --git a/sage/rings/all.py b/sage/rings/all.py
+--- a/sage/rings/all.py
++++ b/sage/rings/all.py
+@@ -160,3 +160,6 @@
+ from misc import composite_field
  
-    sage/schemes/readme
-+   sage/schemes/invariant_theory
- 
-    sage/schemes/generic/scheme
-    sage/schemes/generic/spec
-diff --git a/sage/schemes/all.py b/sage/schemes/all.py
---- a/sage/schemes/all.py
-+++ b/sage/schemes/all.py
-@@ -36,5 +36,6 @@
- 
- from toric.all import *
- 
+ import tests
++
 +from sage.misc.lazy_import import lazy_import
-+lazy_import('sage.schemes.invariant_theory', 'invariant_theory')
- 
--
-diff --git a/sage/schemes/invariant_theory.py b/sage/schemes/invariant_theory.py
++lazy_import('sage.rings.invariant_theory', 'invariant_theory')
+diff --git a/sage/rings/invariant_theory.py b/sage/rings/invariant_theory.py
 new file mode 100644
 --- /dev/null
-+++ b/sage/schemes/invariant_theory.py
-@@ -0,0 +1,1586 @@
++++ b/sage/rings/invariant_theory.py
+@@ -0,0 +1,1930 @@
 +r"""
 +Classical Invariant Theory
 +
 +########################################################################
 +
 +from sage.rings.all import QQ
++from sage.misc.functional import is_odd
 +from sage.matrix.constructor import matrix
 +from sage.structure.sage_object import SageObject
 +from sage.misc.cachefunc import cached_method
 +
 +
 +######################################################################
++def _guess_variables(polynomial, *args):
++    """
++    Return the polynomial variables
++
++    INPUT:
++
++    - ``polynomial`` -- a polynomial.
++
++    - ``*args`` -- the variables. If none are specified, all variables
++      in ``polynomial`` are returned. If a list or tuple is passed,
++      the content is returned. If multiple arguments are passed, they
++      are returned.
++
++    OUTPUT:
++
++    A tuple of variables in the parent ring of the polynoimal.
++
++    EXAMPLES::
++
++       sage: from sage.rings.invariant_theory import _guess_variables
++       sage: R.<x,y> = QQ[]
++       sage: _guess_variables(x^2+y^2)
++       (x, y)
++       sage: _guess_variables(x^2+y^2, x)
++       (x,)
++       sage: _guess_variables(x^2+y^2, x,y)
++       (x, y)
++       sage: _guess_variables(x^2+y^2, [x,y])
++       (x, y)
++    """
++    if len(args)==0 or (len(args)==1 and args[0] is None):
++        return polynomial.variables()
++    elif len(args) == 1 and isinstance(args[0], (tuple, list)):
++        return tuple(args[0])
++    else:
++        return tuple(args)
++
++
++######################################################################
 +
 +class AlgebraicForm(SageObject):
 +    """
 +    INPUT:
 +
 +    - ``n`` -- The number of variables.
-+    
++
 +    - ``d`` -- The degree of the polynomial.
 +
 +    - ``polynomial`` -- The polynomial.
-+    
++
 +    - ``*args`` -- The variables, as a single list/tuple, multiple
 +      arguments, or ``None`` to use all variables of the polynomial.
 +
 +    EXAMPLES::
 +
-+        sage: from sage.schemes.invariant_theory import AlgebraicForm
++        sage: from sage.rings.invariant_theory import AlgebraicForm
 +        sage: R.<x,y> = QQ[]
 +        sage: p = x^2 + y^2
 +        sage: AlgebraicForm(2, 2, p).variables()
 +        sage: AlgebraicForm(3, 2, p, None).variables()
 +        (x, y, None)
 +
-+
-+        sage: from sage.schemes.invariant_theory import AlgebraicForm
++        sage: from sage.rings.invariant_theory import AlgebraicForm
 +        sage: R.<x,y,s,t> = QQ[]
 +        sage: p = s*x^2 + t*y^2
 +        sage: AlgebraicForm(2, 2, p, [x,y]).variables()
 +        Traceback (most recent call last):
 +        ...
 +        ValueError: polynomial is of the wrong degree
-+        
++
 +        sage: AlgebraicForm(2, 2, x^2+y, [x,y]).variables()
 +        Traceback (most recent call last):
 +        ...
 +
 +        TESTS::
 +
-+            sage: from sage.schemes.invariant_theory import AlgebraicForm
++            sage: from sage.rings.invariant_theory import AlgebraicForm
 +            sage: R.<x,y> = QQ[]
 +            sage: form = AlgebraicForm(2, 2, x^2 + y^2)
 +        """
 +        self._n = n
 +        self._d = d
 +        self._polynomial = polynomial
-+        if len(args)==0 or (len(args)==1 and args[0] is None):
-+            variables = polynomial.variables()
-+        elif len(args) == 1 and isinstance(args[0], (tuple, list)):
-+            variables = tuple(args[0])
-+        else:
-+            variables = tuple(args)
++        variables = _guess_variables(polynomial, *args)
 +        if len(variables) == n:
 +            pass
 +        elif len(variables) == n-1:
 +
 +        EXAMPLES::
 +
-+            sage: from sage.schemes.invariant_theory import AlgebraicForm
++            sage: from sage.rings.invariant_theory import AlgebraicForm
 +            sage: R.<x,y,t> = QQ[]
 +            sage: p = x^2 + y^2
 +            sage: inv = AlgebraicForm(3, 2, p, [x,y,None])
 +        degrees = set()
 +        R = self._ring
 +        for e in self._polynomial.exponents():
-+            deg = sum([ e[R.gens().index(x)] 
++            deg = sum([ e[R.gens().index(x)]
 +                        for x in self._variables if x is not None ])
 +            degrees.add(deg)
 +        if self._homogeneous and len(degrees)>1:
 +          corrently under this special linear group element acting on
 +          the homogeneous variables. If ``None``, a random matrix will
 +          be picked.
-+          
++
 +        - ``invariant`` -- boolean. Whether to additionaly test that
 +          it is an invariant.
 +
 +            return c
 +        return cmp(self.coeffs(), other.coeffs())
 +
-+    
++
 +    def _repr_(self):
 +        """
 +        Return a string representation
-+        
-+        OUTPUT: 
-+        
++
++        OUTPUT:
++
 +        String.
 +
 +        EXAMPLES::
 +            'binary quartic with coefficients (1, 0, 0, 0, 1)'
 +        """
 +        s = ''
-+        ary = ['unary', 'binary', 'ternary', 'quaternary', 'quinary', 
++        ary = ['unary', 'binary', 'ternary', 'quaternary', 'quinary',
 +               'senary', 'septenary', 'octonary', 'nonary', 'denary']
 +        try:
 +            s += ary[self._n-1]
 +        except IndexError:
 +            s += 'algebraic'
-+        ic = ['monic', 'quadratic', 'cubic', 'quartic', 'quintic', 
-+              'sextic', 'septimic', 'octavic', 'nonic', 'decimic', 
++        ic = ['monic', 'quadratic', 'cubic', 'quartic', 'quintic',
++              'sextic', 'septimic', 'octavic', 'nonic', 'decimic',
 +              'undecimic', 'duodecimic']
 +        s += ' '
 +        try:
 +    def form(self):
 +        """
 +        Return the defining polynomial
-+        
++
 +        OUTPUT:
 +
 +        The polynomial used to define the algebraic form.
 +    def variables(self):
 +        """
 +        Return the variables of the form
-+        
++
 +        OUTPUT:
 +
 +        A tuple of variables. If inhomogeneous notation is use for the
 +        """
 +        return self._variables
 +
-+    
++
 +    def _extract_coefficients(self, monomials):
 +        """
 +        Return the coefficients of ``monomials``.
-+    
++
 +        INPUT:
-+    
++
 +        - ``polynomial`` -- the input polynomial
-+    
++
 +        - ``monomials`` -- a list of monomials in the polynomial ring
-+    
++
 +        - ``variables`` -- a list of variables in the polynomial ring
-+    
++
 +        OUTPUT:
-+    
++
 +        A tuple containing the coefficients of the monomials in the given
 +        polynomial.
-+    
++
 +        EXAMPLES::
-+    
-+            sage: from sage.schemes.invariant_theory import AlgebraicForm
++
++            sage: from sage.rings.invariant_theory import AlgebraicForm
 +            sage: R.<x,y,z,a30,a21,a12,a03,a20,a11,a02,a10,a01,a00> = QQ[]
 +            sage: p = ( a30*x^3 + a21*x^2*y + a12*x*y^2 + a03*y^3 + a20*x^2*z +
 +            ...         a11*x*y*z + a02*y^2*z + a10*x*z^2 + a01*y*z^2 + a00*z^3 )
 +            sage: m = [x^3, y^3, z^3, x^2*y, x^2*z, x*y^2, y^2*z, x*z^2, y*z^2, x*y*z]
 +            sage: base._extract_coefficients(m)
 +            (a30, a03, a00, a21, a20, a12, a02, a10, a01, a11)
-+    
++
 +            sage: base = AlgebraicForm(3, 3, p.subs(z=1), [x,y])
 +            sage: m = [x^3, y^3, 1, x^2*y, x^2, x*y^2, y^2, x, y, x*y]
 +            sage: base._extract_coefficients(m)
 +        if len(coeffs) != 0:
 +            raise ValueError('The polynomial contains more monomials than given: '+str(coeffs))
 +        return result
-+        
++
++
++    def coefficients(self):
++        """
++        Alias for ``coeffs()``
++
++        See the documentation for ``coeffs()`` for details.
++
++        EXAMPLES::
++
++            sage: R.<a,b,c,d,e,f,g, x,y,z> = QQ[]
++            sage: p = a*x^2 + b*y^2 + c*z^2 + d*x*y + e*x*z + f*y*z
++            sage: q = invariant_theory.quadratic_form(p, x,y,z)
++            sage: q.coefficients()
++            (a, b, c, d, e, f)
++            sage: q.coeffs()
++            (a, b, c, d, e, f)
++        """
++        return self.coeffs()
++
++
++######################################################################
++
++class QuadraticForm(AlgebraicForm):
++    """
++    Invariant theory of a multivariate quadratic form
++
++    You should use the :class:`invariant_theory
++    <InvariantTheoryFactory>` factory object to contstruct instances
++    of this class. See :meth:`~InvariantTheoryFactory.quadratic_form`
++    for details.
++
++    TESTS::
++
++        sage: R.<a,b,c,d,e,f,g, x,y,z> = QQ[]
++        sage: p = a*x^2 + b*y^2 + c*z^2 + d*x*y + e*x*z + f*y*z
++        sage: invariant_theory.quadratic_form(p, x,y,z)
++        ternary quadratic with coefficients (a, b, c, d, e, f)
++        sage: type(_)
++        <class 'sage.rings.invariant_theory.TernaryQuadratic'>
++
++        sage: R.<a,b,c,d,e,f,g, x,y,z> = QQ[]
++        sage: p = a*x^2 + b*y^2 + c*z^2 + d*x*y + e*x*z + f*y*z
++        sage: invariant_theory.quadratic_form(p, x,y,z)
++        ternary quadratic with coefficients (a, b, c, d, e, f)
++        sage: type(_)
++        <class 'sage.rings.invariant_theory.TernaryQuadratic'>
++
++    Since we can not always decide whether the form is homogeneous or
++    not based on the number of variables, you need to explicitly
++    specify it if you want the variables to be treated as
++    inhomogeneous::
++
++        sage: invariant_theory.inhomogeneous_quadratic_form(p.subs(z=1), x,y)
++        ternary quadratic with coefficients (a, b, c, d, e, f)
++   """
++
++    def __init__(self, n, polynomial, *args):
++        """
++        The Python constructor
++
++        TESTS::
++
++            sage: R.<x,y> = QQ[]
++            sage: from sage.rings.invariant_theory import QuadraticForm
++            sage: QuadraticForm(2, x^2+2*y^2+3*x*y)
++            binary quadratic with coefficients (1, 2, 3)
++            sage: QuadraticForm(3, x^2+y^2)
++            ternary quadratic with coefficients (1, 1, 0, 0, 0, 0)
++        """
++        super(QuadraticForm, self).__init__(n, 2, polynomial, *args)
++
++
++    @cached_method
++    def monomials(self):
++        """
++        List the basis monomials in the form.
++
++        OUTPUT:
++
++        A tuple of monomials. They are in the same order as
++        :meth:`coeffs`.
++
++        EXAMPLES::
++
++            sage: R.<x,y> = QQ[]
++            sage: quadratic = invariant_theory.quadratic_form(x^2+y^2)
++            sage: quadratic.monomials()
++            (x^2, y^2, x*y)
++
++            sage: quadratic = invariant_theory.inhomogeneous_quadratic_form(x^2+y^2)
++            sage: quadratic.monomials()
++            (x^2, y^2, 1, x*y, x, y)
++        """
++        var = self._variables
++        def prod(a,b):
++            if a is None and b is None:
++                return self._ring.one()
++            elif a is None:
++                return b
++            elif b is None:
++                return a
++            else:
++                return a*b
++        squares = tuple( prod(x,x) for x in var )
++        mixed = []
++        for i in range(self._n):
++            for j in range(i+1, self._n):
++                mixed.append(prod(var[i], var[j]))
++        mixed = tuple(mixed)
++        return squares + mixed
++
++
++    @cached_method
++    def coeffs(self):
++        r"""
++        The coefficients of a quadratic form.
++
++        Given
++
++        .. math::
++
++            f(x) = \sum_{0\leq i<n} a_i x_i^2 + \sum_{0\leq j <k<n}
++            a_{jk} x_j x_k
++
++        this function returns `a = (a_0, \dots, a_n, a_{00}, a_{01}, \dots, a_{n-1,n})`
++
++        EXAMPLES::
++
++            sage: R.<a,b,c,d,e,f,g, x,y,z> = QQ[]
++            sage: p = a*x^2 + b*y^2 + c*z^2 + d*x*y + e*x*z + f*y*z
++            sage: inv = invariant_theory.quadratic_form(p, x,y,z); inv
++            ternary quadratic with coefficients (a, b, c, d, e, f)
++            sage: inv.coeffs()
++            (a, b, c, d, e, f)
++            sage: inv.scaled_coeffs()
++            (a, b, c, 1/2*d, 1/2*e, 1/2*f)
++        """
++        return self._extract_coefficients(self.monomials())
++
++
++    def scaled_coeffs(self):
++        """
++        The scaled coefficients of a quadratic form.
++
++        Given
++
++        .. math::
++
++            f(x) = \sum_{0\leq i<n} a_i x_i^2 + \sum_{0\leq j <k<n}
++            2 a_{jk} x_j x_k
++
++        this function returns `a = (a_0, \cdots, a_n, a_{00}, a_{01}, \dots, a_{n-1,n})`
++
++        EXAMPLES::
++
++            sage: R.<a,b,c,d,e,f,g, x,y,z> = QQ[]
++            sage: p = a*x^2 + b*y^2 + c*z^2 + d*x*y + e*x*z + f*y*z
++            sage: inv = invariant_theory.quadratic_form(p, x,y,z); inv
++            ternary quadratic with coefficients (a, b, c, d, e, f)
++            sage: inv.coeffs()
++            (a, b, c, d, e, f)
++            sage: inv.scaled_coeffs()
++            (a, b, c, 1/2*d, 1/2*e, 1/2*f)
++        """
++        coeff = self.coeffs()
++        squares = coeff[0:self._n]
++        mixed = tuple( c/2 for c in coeff[self._n:] )
++        return squares + mixed
++
++
++    @cached_method
++    def matrix(self):
++        """
++        Return the quadratic form as a symmetric matrix
++
++        OUTPUT:
++
++        This method returns a symmetric matrix `A` such that the
++        quadratic `Q` equals
++
++        .. math::
++
++            Q(x,y,z,\dots) = (x,y,\dots) A (x,y,\dots)^t
++
++        EXAMPLES::
++
++            sage: R.<x,y,z> = QQ[]
++            sage: quadratic = invariant_theory.ternary_quadratic(x^2+y^2+z^2+x*y)
++            sage: matrix(quadratic)
++            [  1 1/2   0]
++            [1/2   1   0]
++            [  0   0   1]
++            sage: quadratic._matrix_() == matrix(quadratic)
++            True
++        """
++        coeff = self.scaled_coeffs()
++        A = matrix(self._ring, self._n)
++        for i in range(self._n):
++            A[i,i] = coeff[i]
++        ij = self._n
++        for i in range(self._n):
++            for j in range(i+1, self._n):
++                A[i,j] = coeff[ij]
++                A[j,i] = coeff[ij]
++                ij += 1
++        return A
++
++    _matrix_ = matrix
++
++
++    def discriminant(self):
++        """
++        Return the discriminant of the quadratic form.
++
++        Up to an overall constant factor, this is just the determinant
++        of the defining matrix, see :meth:`matrix`. For a quadratic
++        form in `n` variables, the overall constant is `2^{n-1}` if
++        `n` is odd and `(-1)^{n/2} 2^n` if `n` is even.
++
++        EXAMPLES::
++
++            sage: R.<a,b,c, x,y> = QQ[]
++            sage: p = a*x^2+b*x*y+c*y^2
++            sage: quadratic = invariant_theory.quadratic_form(p, x,y)
++            sage: quadratic.discriminant()
++            b^2 - 4*a*c
++
++            sage: R.<a,b,c,d,e,f,g, x,y,z> = QQ[]
++            sage: p = a*x^2 + b*y^2 + c*z^2 + d*x*y + e*x*z + f*y*z
++            sage: quadratic = invariant_theory.quadratic_form(p, x,y,z)
++            sage: quadratic.discriminant()
++            4*a*b*c - c*d^2 - b*e^2 + d*e*f - a*f^2
++        """
++        A = 2*self._matrix_()
++        if is_odd(self._n):
++            return A.det() / 2
++        else:
++            return (-1)**(self._n/2) * A.det()
++
++
++
++    def as_QuadraticForm(self):
++        """
++        Convert into a :class:`~sage.quadratic_forms.quadratic_form.QuadraticForm`.
++
++        OUTPUT:
++
++        Sage has a special quadratic forms subsystem. This method
++        converts ``self`` into this
++        :class:`~sage.quadratic_forms.quadratic_form.QuadraticForm`
++        representation.
++
++        EXAMPLES::
++
++            sage: R.<x,y,z> = QQ[]
++            sage: p = x^2+y^2+z^2+2*x*y+3*x*z
++            sage: quadratic = invariant_theory.ternary_quadratic(p)
++            sage: matrix(quadratic)
++            [  1   1 3/2]
++            [  1   1   0]
++            [3/2   0   1]
++            sage: quadratic.as_QuadraticForm()
++            Quadratic form in 3 variables over Multivariate Polynomial
++            Ring in x, y, z over Rational Field with coefficients:
++            [ 1/2 1 3/2 ]
++            [ * 1/2 0 ]
++            [ * * 1/2 ]
++            sage: _.polynomial('X,Y,Z')
++            X^2 + 2*X*Y + Y^2 + 3*X*Z + Z^2
++       """
++        R = self._ring
++        B = self._matrix_()
++        import sage.quadratic_forms.quadratic_form
++        return sage.quadratic_forms.quadratic_form.QuadraticForm(R, B)
 +
 +######################################################################
 +
 +class BinaryQuartic(AlgebraicForm):
 +    """
 +    Invariant theory of a binary quartic
-+    
++
 +    You should use the :class:`invariant_theory
 +    <InvariantTheoryFactory>` factory object to contstruct instances
 +    of this class. See :meth:`~InvariantTheoryFactory.binary_quartic`
 +        TESTS::
 +
 +            sage: R.<x,y> = QQ[]
-+            sage: from sage.schemes.invariant_theory import BinaryQuartic
++            sage: from sage.rings.invariant_theory import BinaryQuartic
 +            sage: BinaryQuartic(x^4+y^4)
 +            binary quartic with coefficients (1, 0, 0, 0, 1)
 +        """
 +    def monomials(self):
 +        """
 +        List the basis monomials in the form.
-+        
++
 +        OUTPUT:
 +
 +        A tuple of monomials. They are in the same order as
 +    def coeffs(self):
 +        """
 +        The coefficients of a binary quartic.
-+    
++
 +        Given
-+    
++
 +        .. math::
-+    
++
 +            f(x) = a_0 x_1^4 + a_1 x_0 x_1^3 + a_2 x_0^2 x_1^2 +
 +                   a_3 x_0^3 x_1 + a_4 x_0^4
-+    
++
 +        this function returns `a = (a_0, a_1, a_2, a_3, a_4)`
-+    
++
 +        EXAMPLES::
-+    
++
 +            sage: R.<a0, a1, a2, a3, a4, x0, x1> = QQ[]
 +            sage: p = a0*x1^4 + a1*x1^3*x0 + a2*x1^2*x0^2 + a3*x1*x0^3 + a4*x0^4
 +            sage: quartic = invariant_theory.binary_quartic(p, x0, x1)
 +            sage: quartic.coeffs()
 +            (a0, a1, a2, a3, a4)
-+    
++
 +            sage: R.<a0, a1, a2, a3, a4, x> = QQ[]
 +            sage: p = a0 + a1*x + a2*x^2 + a3*x^3 + a4*x^4
 +            sage: quartic = invariant_theory.binary_quartic(p, x)
 +    def scaled_coeffs(self):
 +        """
 +        The coefficients of a binary quartic.
-+    
++
 +        Given
-+    
++
 +        .. math::
-+    
++
 +            f(x) = a_0 x_1^4 + 4 a_1 x_0 x_1^3 + 6 a_2 x_0^2 x_1^2 +
 +                   4 a_3 x_0^3 x_1 + a_4 x_0^4
-+    
++
 +        this function returns `a = (a_0, a_1, a_2, a_3, a_4)`
-+    
++
 +        EXAMPLES::
-+    
++
 +            sage: R.<a0, a1, a2, a3, a4, x0, x1> = QQ[]
 +            sage: quartic = a0*x1^4 + 4*a1*x1^3*x0 + 6*a2*x1^2*x0^2 + 4*a3*x1*x0^3 + a4*x0^4
 +            sage: inv = invariant_theory.binary_quartic(quartic, x0, x1)
 +            sage: inv.scaled_coeffs()
 +            (a0, a1, a2, a3, a4)
-+    
++
 +            sage: R.<a0, a1, a2, a3, a4, x> = QQ[]
 +            sage: quartic = a0 + 4*a1*x + 6*a2*x^2 + 4*a3*x^3 + a4*x^4
 +            sage: inv = invariant_theory.binary_quartic(quartic, x)
 +        """
 +        coeff = self.coeffs()
 +        return (coeff[0], coeff[1]/4, coeff[2]/6, coeff[3]/4, coeff[4])
-+