From 67c8cbb79521151d88e62ccafe95151e79f41bbb Mon Sep 17 00:00:00 2001 From: dcoudert Date: Sun, 28 Mar 2021 15:00:12 +0200 Subject: [PATCH 001/126] trac #30566: random spanning tree by weights --- src/sage/graphs/spanning_tree.pyx | 76 ++++++++++++++++++++++++++++--- 1 file changed, 69 insertions(+), 7 deletions(-) diff --git a/src/sage/graphs/spanning_tree.pyx b/src/sage/graphs/spanning_tree.pyx index 922ecc62ecb..e2b801e95e0 100644 --- a/src/sage/graphs/spanning_tree.pyx +++ b/src/sage/graphs/spanning_tree.pyx @@ -796,7 +796,7 @@ cpdef boruvka(G, wfunction=None, bint check=False, bint by_weight=True): return T -def random_spanning_tree(self, output_as_graph=False): +def random_spanning_tree(G, output_as_graph=False, by_weight=False, weight_function=None): r""" Return a random spanning tree of the graph. @@ -808,11 +808,27 @@ def random_spanning_tree(self, output_as_graph=False): edge `(i, j)` to the spanning tree, where `i` is the previous vertex in the random walk. + When ``by_weight`` is ``True`` or a weight function is given, the selection + of the neighbor is done proportionaly to the edge weights. + INPUT: + - ``G`` -- an undirected graph + - ``output_as_graph`` -- boolean (default: ``False``); whether to return a list of edges or a graph + - ``by_weight`` -- boolean (default: ``False``); if ``True``, the edges in + the graph are weighted, otherwise all edges have weight 1 + + - ``weight_function`` -- function (default: ``None``); a function that takes + as input an edge ``(u, v, l)`` and outputs its weight. If not ``None``, + ``by_weight`` is automatically set to ``True``. If ``None`` and + ``by_weight`` is ``True``, we use the edge label ``l`` , if ``l`` is not + ``None``, else ``1`` as a weight. The ``weight_function`` can be used to + transform the label into a weight (note that, if the weight returned is + not convertible to a float, an error is raised) + .. SEEALSO:: :meth:`~sage.graphs.generic_graph.GenericGraph.spanning_trees_count` @@ -846,6 +862,26 @@ def random_spanning_tree(self, output_as_graph=False): sage: T.set_pos(pos) sage: T.show(vertex_labels=False) + We can also use edge weights to change the probability of returning a + spanning tree:: + + sage: def foo(G, k): + ....: S = set() + ....: for _ in range(k): + ....: E = G.random_spanning_tree(by_weight=True) + ....: S.add(Graph(E).graph6_string()) + ....: return S + sage: K3 = graphs.CompleteGraph(3) + sage: for u, v in K3.edges(labels=False): + ....: K3.set_edge_label(u, v, randint(1, 2)) + sage: foo(K3, 100) == {'BW', 'Bg', 'Bo'} # random + True + sage: K4 = graphs.CompleteGraph(4) + sage: for u, v in K4.edges(labels=False): + ....: K4.set_edge_label(u, v, randint(1, 2)) + sage: print(len(foo(K4, 100))) # random + 16 + TESTS:: sage: G = Graph() @@ -861,21 +897,47 @@ def random_spanning_tree(self, output_as_graph=False): ValueError: works only for non-empty connected graphs """ from sage.misc.prandom import randint + from sage.misc.prandom import random from sage.graphs.graph import Graph - cdef int N = self.order() + cdef int N = G.order() - if not N or not self.is_connected(): + if not N or not G.is_connected(): raise ValueError('works only for non-empty connected graphs') - s = next(self.vertex_iterator()) + if G.order() == G.size() + 1: + # G is a tree + if output_as_graph: + return G.copy() + return list(G.edge_iterator(label=False)) + + if weight_function is not None: + by_weight = True + + if by_weight: + if weight_function is None: + def weight_function(e): + return 1 if e[2] is None else e[2] + + def next_neighbor(s): + p = random() * sum(weight_function(e) + for e in G.edge_iterator(s, sort_vertices=False)) + for e in G.edge_iterator(s, sort_vertices=False): + p -= weight_function(e) + if p <= 0: + break + return e[1] if e[0] == s else e[0] + + else: + def next_neighbor(s): + return G.neighbors(s)[randint(0, G.degree(s) - 1)] + + s = next(G.vertex_iterator()) cdef set found = set([s]) cdef int found_nr = 1 cdef list tree_edges = [] - cdef list neighbors while found_nr < N: - neighbors = self.neighbors(s) - new_s = neighbors[randint(0, len(neighbors) - 1)] + new_s = next_neighbor(s) if new_s not in found: found.add(new_s) found_nr += 1 From d677a53ea96a20dc332c00d1469b3ebf39521892 Mon Sep 17 00:00:00 2001 From: Lorenz Panny Date: Sun, 1 Aug 2021 12:43:53 +0800 Subject: [PATCH 002/126] warn when Ideal() creates an ideal in a field --- src/sage/rings/ideal.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/sage/rings/ideal.py b/src/sage/rings/ideal.py index 53076ac62ed..57757e36703 100644 --- a/src/sage/rings/ideal.py +++ b/src/sage/rings/ideal.py @@ -35,6 +35,8 @@ import sage.rings.infinity from sage.structure.sequence import Sequence +import warnings + def Ideal(*args, **kwds): r""" Create the ideal in ring with given generators. @@ -183,6 +185,10 @@ def Ideal(*args, **kwds): gens = args gens = Sequence(gens) R = gens.universe() + if isinstance(R, sage.rings.ring.Field) and not hasattr(R, 'fractional_ideal'): + warnings.warn(f'Constructing an ideal in {R}, which is a field.' + ' Did you intend to take numerators first?' + ' This warning can be muted by passing the base ring to Ideal() explicitly.') else: R = first gens = args[1:] From aa898ad59aa104de61ea70a4419a49870edc379e Mon Sep 17 00:00:00 2001 From: Lorenz Panny Date: Sun, 15 Aug 2021 17:35:27 +0800 Subject: [PATCH 003/126] fractional ideals should be fractional ideals --- src/sage/rings/number_field/number_field_ideal.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/rings/number_field/number_field_ideal.py b/src/sage/rings/number_field/number_field_ideal.py index 54d7ebb1535..dd18421bfd3 100644 --- a/src/sage/rings/number_field/number_field_ideal.py +++ b/src/sage/rings/number_field/number_field_ideal.py @@ -46,7 +46,7 @@ import sage.misc.misc as misc from sage.rings.finite_rings.finite_field_constructor import FiniteField -from sage.rings.ideal import Ideal_generic +from sage.rings.ideal import Ideal_generic, Ideal_fractional from sage.misc.all import prod from sage.misc.mrange import xmrange_iter from sage.misc.cachefunc import cached_method @@ -1734,7 +1734,7 @@ def is_NumberFieldIdeal(x): return isinstance(x, NumberFieldIdeal) -class NumberFieldFractionalIdeal(MultiplicativeGroupElement, NumberFieldIdeal): +class NumberFieldFractionalIdeal(MultiplicativeGroupElement, NumberFieldIdeal, Ideal_fractional): r""" A fractional ideal in a number field. From 5f69b30a313e9be643d1d6c935d54a4440584b8b Mon Sep 17 00:00:00 2001 From: Lorenz Panny Date: Sun, 15 Aug 2021 17:17:44 +0800 Subject: [PATCH 004/126] do not warn when the constructed ideal is a fractional ideal --- src/sage/rings/ideal.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/sage/rings/ideal.py b/src/sage/rings/ideal.py index 57757e36703..dc4b9dcf447 100644 --- a/src/sage/rings/ideal.py +++ b/src/sage/rings/ideal.py @@ -174,6 +174,7 @@ def Ideal(*args, **kwds): first = args[0] + inferred_field = False if not isinstance(first, sage.rings.ring.Ring): if isinstance(first, Ideal_generic) and len(args) == 1: R = first.ring() @@ -185,10 +186,7 @@ def Ideal(*args, **kwds): gens = args gens = Sequence(gens) R = gens.universe() - if isinstance(R, sage.rings.ring.Field) and not hasattr(R, 'fractional_ideal'): - warnings.warn(f'Constructing an ideal in {R}, which is a field.' - ' Did you intend to take numerators first?' - ' This warning can be muted by passing the base ring to Ideal() explicitly.') + inferred_field = isinstance(R, sage.rings.ring.Field) else: R = first gens = args[1:] @@ -196,7 +194,14 @@ def Ideal(*args, **kwds): if not isinstance(R, sage.rings.ring.CommutativeRing): raise TypeError("R must be a commutative ring") - return R.ideal(*gens, **kwds) + I = R.ideal(*gens, **kwds) + + if inferred_field and not isinstance(I, Ideal_fractional): # trac 32327 + warnings.warn(f'Constructing an ideal in {R}, which is a field.' + ' Did you intend to take numerators first?' + ' This warning can be muted by passing the base ring to Ideal() explicitly.') + + return I def is_Ideal(x): r""" From fb94cd6635a3f2a3dcd50eaebf9403bb561ec79b Mon Sep 17 00:00:00 2001 From: Lorenz Panny Date: Sun, 15 Aug 2021 17:51:53 +0800 Subject: [PATCH 005/126] only import the warnings module when needed --- src/sage/rings/ideal.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/sage/rings/ideal.py b/src/sage/rings/ideal.py index dc4b9dcf447..5817778515f 100644 --- a/src/sage/rings/ideal.py +++ b/src/sage/rings/ideal.py @@ -35,8 +35,6 @@ import sage.rings.infinity from sage.structure.sequence import Sequence -import warnings - def Ideal(*args, **kwds): r""" Create the ideal in ring with given generators. @@ -197,6 +195,7 @@ def Ideal(*args, **kwds): I = R.ideal(*gens, **kwds) if inferred_field and not isinstance(I, Ideal_fractional): # trac 32327 + import warnings warnings.warn(f'Constructing an ideal in {R}, which is a field.' ' Did you intend to take numerators first?' ' This warning can be muted by passing the base ring to Ideal() explicitly.') From bc6fdeb65596c5cb5f407210be0b437c638dd429 Mon Sep 17 00:00:00 2001 From: Lorenz Panny Date: Sun, 15 Aug 2021 17:52:33 +0800 Subject: [PATCH 006/126] oops, fix trac number in comment --- src/sage/rings/ideal.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/rings/ideal.py b/src/sage/rings/ideal.py index 5817778515f..971dde7a2d7 100644 --- a/src/sage/rings/ideal.py +++ b/src/sage/rings/ideal.py @@ -194,7 +194,7 @@ def Ideal(*args, **kwds): I = R.ideal(*gens, **kwds) - if inferred_field and not isinstance(I, Ideal_fractional): # trac 32327 + if inferred_field and not isinstance(I, Ideal_fractional): # trac 32320 import warnings warnings.warn(f'Constructing an ideal in {R}, which is a field.' ' Did you intend to take numerators first?' From 8039ce43a85aae80f543f0cfbaa97731f7252fe9 Mon Sep 17 00:00:00 2001 From: Lorenz Panny Date: Mon, 16 Aug 2021 00:15:32 +0800 Subject: [PATCH 007/126] add doctest for #32380 --- src/sage/rings/number_field/number_field_ideal.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/sage/rings/number_field/number_field_ideal.py b/src/sage/rings/number_field/number_field_ideal.py index dd18421bfd3..4618672eb13 100644 --- a/src/sage/rings/number_field/number_field_ideal.py +++ b/src/sage/rings/number_field/number_field_ideal.py @@ -1747,6 +1747,14 @@ class NumberFieldFractionalIdeal(MultiplicativeGroupElement, NumberFieldIdeal, I sage: Jinv = I^(-2) sage: J*Jinv Fractional ideal (1) + + TESTS: + + Number-field fractional ideals are fractional ideals (:trac:`32380`):: + + sage: from sage.rings.ideal import Ideal_fractional + sage: isinstance(I, Ideal_fractional) + True """ def __init__(self, field, gens, coerce=True): """ From b0bbc1e887c05fe2c8b05089cdf15fe21c0156a0 Mon Sep 17 00:00:00 2001 From: Kwankyu Lee Date: Wed, 25 Aug 2021 11:01:39 +0900 Subject: [PATCH 008/126] Remove unnecessary spacer code --- src/sage/misc/html.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/sage/misc/html.py b/src/sage/misc/html.py index 7dacc5f2748..9a0bc5efead 100644 --- a/src/sage/misc/html.py +++ b/src/sage/misc/html.py @@ -299,7 +299,8 @@ def eval(self, x, globals=None, locals=None, mode='display', combine_all=False): # Get a regular LaTeX representation of x x = latex(x, combine_all=combine_all) - # The following block, hopefully, can be removed in some future MathJax. + # The "\text{\texttt{...}}" blocks are reformed to be renderable by MathJax. + # These blocks are produced by str_function() defined in sage.misc.latex. prefix = r"\text{\texttt{" parts = x.split(prefix) for i, part in enumerate(parts): @@ -324,7 +325,6 @@ def eval(self, x, globals=None, locals=None, mode='display', combine_all=False): delimiter = "|" y = "(complicated string)" wrapper = r"\verb" + delimiter + "%s" + delimiter - spacer = r"\phantom{\verb!%s!}" y = y.replace("{ }", " ").replace("{-}", "-") for c in r"#$%&\^_{}~": char_wrapper = r"{\char`\%s}" % c @@ -336,14 +336,12 @@ def eval(self, x, globals=None, locals=None, mode='display', combine_all=False): nspaces += 1 continue if nspaces > 0: - subparts.append(spacer % ("x" * nspaces)) + subparts.append(wrapper % (" " * nspaces)) nspaces = 1 subparts.append(wrapper % subpart) - # There is a bug with omitting empty lines in arrays - if not y: - subparts.append(spacer % "x") subparts.append(part[closing + 1:]) parts[i] = "".join(subparts) + from sage.misc.latex_macros import sage_configurable_latex_macros from sage.misc.latex import _Latex_prefs latex_string = ''.join( @@ -351,6 +349,7 @@ def eval(self, x, globals=None, locals=None, mode='display', combine_all=False): [_Latex_prefs._option['macros']] + parts ) + if mode == 'display': html = r'\[{0}\]' elif mode == 'inline': From 656a8d3c6f9088e1c126a5b69b630a2c70bbe890 Mon Sep 17 00:00:00 2001 From: Kwankyu Lee Date: Tue, 31 Aug 2021 21:04:29 +0900 Subject: [PATCH 009/126] Fix doctest failures --- src/sage/misc/html.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/misc/html.py b/src/sage/misc/html.py index 9a0bc5efead..07da7581fb9 100644 --- a/src/sage/misc/html.py +++ b/src/sage/misc/html.py @@ -294,7 +294,7 @@ def eval(self, x, globals=None, locals=None, mode='display', combine_all=False): sage: MathJax().eval(3, mode='inline') \(\newcommand{\Bold}[1]{\mathbf{#1}}3\) sage: MathJax().eval(type(3), mode='inline') - \(\newcommand{\Bold}[1]{\mathbf{#1}}\verb||\) + \(\newcommand{\Bold}[1]{\mathbf{#1}}\verb||\) """ # Get a regular LaTeX representation of x x = latex(x, combine_all=combine_all) @@ -411,7 +411,7 @@ def __call__(self, obj, concatenate=True, strict=False): sagemath sage: html('sagemath', strict=True) - \[\newcommand{\Bold}[1]{\mathbf{#1}}\verb|sagemath|\] + \[\newcommand{\Bold}[1]{\mathbf{#1}}\verb|sagemath|\] """ # string obj is interpreted as an HTML in not strict mode if isinstance(obj, str) and not strict: From 69784190e03a32daeaa675709840ca30ebbf539d Mon Sep 17 00:00:00 2001 From: Miguel Marco Date: Mon, 4 Oct 2021 18:27:25 +0200 Subject: [PATCH 010/126] First attempt for transcendental extensions. Ring creation seems to work sa2si is broken si2sa not started --- src/sage/libs/singular/decl.pxd | 13 ++++++++++ src/sage/libs/singular/ring.pyx | 40 ++++++++++++++++++++++++++++- src/sage/libs/singular/singular.pyx | 37 +++++++++++++++++++++++++- 3 files changed, 88 insertions(+), 2 deletions(-) diff --git a/src/sage/libs/singular/decl.pxd b/src/sage/libs/singular/decl.pxd index 806937ff6e1..54c3fd36e58 100644 --- a/src/sage/libs/singular/decl.pxd +++ b/src/sage/libs/singular/decl.pxd @@ -401,6 +401,8 @@ cdef extern from "singular/Singular/libsingular.h": cdef omBin *slists_bin + cdef omBin *fractionObjectBin + # integer conversion constant cdef long SR_INT @@ -1136,3 +1138,14 @@ cdef extern from "singular/kernel/GBEngine/kstd1.h": cdef extern from "singular/kernel/GBEngine/syz.h": ctypedef struct syStrategy "ssyStrategy": short references + +cdef extern from "singular/polys/ext_fields/transext.h": + ctypedef struct TransExtInfo: + ring * r + ctypedef struct fraction "fractionObject": + poly *numerator + poly *denominator + int complexity + + + diff --git a/src/sage/libs/singular/ring.pyx b/src/sage/libs/singular/ring.pyx index 63b63070cd2..4c95653d3ed 100644 --- a/src/sage/libs/singular/ring.pyx +++ b/src/sage/libs/singular/ring.pyx @@ -26,7 +26,9 @@ from sage.libs.singular.decl cimport ringorder_dp, ringorder_Dp, ringorder_lp, r from sage.libs.singular.decl cimport p_Copy, prCopyR from sage.libs.singular.decl cimport n_unknown, n_Zp, n_Q, n_R, n_GF, n_long_R, n_algExt,n_transExt,n_long_C, n_Z, n_Zn, n_Znm, n_Z2m, n_CF from sage.libs.singular.decl cimport n_coeffType, cfInitCharProc -from sage.libs.singular.decl cimport rDefault, GFInfo, ZnmInfo, nInitChar, AlgExtInfo, nRegister, naInitChar +from sage.libs.singular.decl cimport rDefault, GFInfo, ZnmInfo, nInitChar, AlgExtInfo, nRegister, naInitChar, TransExtInfo + + from sage.rings.integer cimport Integer from sage.rings.integer_ring cimport IntegerRing_class @@ -40,11 +42,19 @@ from sage.rings.polynomial.term_order import TermOrder from sage.rings.polynomial.multi_polynomial_libsingular cimport MPolynomial_libsingular, MPolynomialRing_libsingular from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing +from sage.rings.polynomial.polynomial_ring import PolynomialRing_field + +from sage.rings.fraction_field import FractionField_generic, FractionField_1poly_field + from cpython.object cimport Py_EQ, Py_NE from collections import defaultdict + + + + # mapping str --> SINGULAR representation order_dict = { "dp": ringorder_dp, @@ -143,10 +153,13 @@ cdef ring *singular_ring_new(base_ring, n, names, term_order) except NULL: cdef int ringorder_column_pos cdef int ringorder_column_asc + cdef int ngens + cdef n_coeffType ringtype = n_unknown cdef MPolynomialRing_libsingular k cdef MPolynomial_libsingular minpoly cdef AlgExtInfo extParam + cdef TransExtInfo trextParam cdef n_coeffType _type = n_unknown #cdef cfInitCharProc myfunctionptr; @@ -249,6 +262,31 @@ cdef ring *singular_ring_new(base_ring, n, names, term_order) except NULL: characteristic = 0 _ring = rDefault( characteristic ,nvars, _names, nblcks, _order, _block0, _block1, _wvhdl) + elif isinstance(base_ring, FractionField_generic) and isinstance(base_ring.base(), (MPolynomialRing_libsingular, PolynomialRing_field)) and isinstance(base_ring.base().base_ring(), RationalField): + characteristic = 1 + k = PolynomialRing(RationalField(), + names=base_ring.variable_names(), order="lex", implementation="singular") + + ngens = len(k.gens()) + + _ext_names = omAlloc0(ngens*sizeof(char*)) + for i in range(ngens): + _name = str_to_bytes(k._names[i]) + _ext_names[i] = omStrDup(_name) + + _cfr = rDefault( 0, 1, _ext_names ) + + trextParam.r = _cfr + + _cf = nInitChar(n_transExt, &trextParam) + + + if (_cf is NULL): + raise RuntimeError("Failed to allocate _cf ring.") + + _ring = rDefault (_cf ,nvars, _names, nblcks, _order, _block0, _block1, _wvhdl) + + elif isinstance(base_ring, NumberField) and base_ring.is_absolute(): characteristic = 1 k = PolynomialRing(RationalField(), diff --git a/src/sage/libs/singular/singular.pyx b/src/sage/libs/singular/singular.pyx index c736d56b0c0..3f9d86812c3 100644 --- a/src/sage/libs/singular/singular.pyx +++ b/src/sage/libs/singular/singular.pyx @@ -31,6 +31,9 @@ from sage.rings.rational_field import RationalField from sage.rings.integer_ring cimport IntegerRing_class from sage.rings.finite_rings.integer_mod_ring import IntegerModRing_generic from sage.rings.finite_rings.finite_field_base import FiniteField +from sage.rings.polynomial.polynomial_ring import PolynomialRing_field +from sage.rings.fraction_field import FractionField_generic, FractionField_1poly_field + from sage.rings.finite_rings.finite_field_prime_modn import FiniteField_prime_modn from sage.rings.finite_rings.finite_field_givaro import FiniteField_givaro from sage.rings.finite_rings.finite_field_ntl_gf2e import FiniteField_ntl_gf2e @@ -40,7 +43,12 @@ from sage.libs.gmp.all cimport * from sage.cpython.string import FS_ENCODING from sage.cpython.string cimport str_to_bytes, char_to_str, bytes_to_str -from sage.rings.polynomial.multi_polynomial_libsingular cimport MPolynomial_libsingular +from sage.rings.polynomial.multi_polynomial_libsingular cimport MPolynomial_libsingular, MPolynomialRing_libsingular + +cdef extern from "singular/coeffs/coeffs.h": + ctypedef struct coeffs "n_Procs_s" + + _saved_options = (int(0),0,0) @@ -477,6 +485,30 @@ cdef number *sa2si_GFq_generic(object elem, ring *_ring): return n1 +cdef number *sa2si_transext(object elem, ring *_ring): + + cdef poly *pnumer + cdef poly *pdenom + + cdef fraction *result + + numer = elem.numerator() + pnumer = p_Copy(numer._poly, _ring) + + denom = elem.denominator() + pdenom = p_Copy(denom._poly, _ring) + + nMapFuncPtr = naSetMap(_ring.cf, currRing.cf) # choose correct mapping function + + result = omAlloc0Bin(fractionObjectBin) + + result.numerator = pnumer + result.denominator = pdenom + result.complexity = 1 + + return result + + cdef number *sa2si_NF(object elem, ring *_ring): """ """ @@ -692,6 +724,9 @@ cdef number *sa2si(Element elem, ring * _ring): if _ring.cf.type == n_unknown: return n_Init(int(elem),_ring) return sa2si_ZZmod(elem, _ring) + elif isinstance(elem._parent, FractionField_generic) and isinstance(elem._parent.base(), (MPolynomialRing_libsingular, PolynomialRing_field)) and isinstance(elem._parent.base().base_ring(), RationalField): + return sa2si_transext(elem, _ring) + else: raise ValueError("cannot convert to SINGULAR number") From 3de10e6c271db7eefb41ce3447cae99c013c3a9d Mon Sep 17 00:00:00 2001 From: Miguel Marco Date: Tue, 5 Oct 2021 22:08:33 +0200 Subject: [PATCH 011/126] Hacky solution for sa2si (coefficients that fit in int size only) --- src/sage/libs/singular/ring.pyx | 3 +- src/sage/libs/singular/singular.pyx | 87 +++++++++++++++++++++++++---- 2 files changed, 77 insertions(+), 13 deletions(-) diff --git a/src/sage/libs/singular/ring.pyx b/src/sage/libs/singular/ring.pyx index 4c95653d3ed..64fceeaff88 100644 --- a/src/sage/libs/singular/ring.pyx +++ b/src/sage/libs/singular/ring.pyx @@ -274,7 +274,8 @@ cdef ring *singular_ring_new(base_ring, n, names, term_order) except NULL: _name = str_to_bytes(k._names[i]) _ext_names[i] = omStrDup(_name) - _cfr = rDefault( 0, 1, _ext_names ) + _cfr = rDefault( 0, ngens, _ext_names ) + rComplete(_cfr, 1) trextParam.r = _cfr diff --git a/src/sage/libs/singular/singular.pyx b/src/sage/libs/singular/singular.pyx index 3f9d86812c3..2bd887646f1 100644 --- a/src/sage/libs/singular/singular.pyx +++ b/src/sage/libs/singular/singular.pyx @@ -487,26 +487,89 @@ cdef number *sa2si_GFq_generic(object elem, ring *_ring): cdef number *sa2si_transext(object elem, ring *_ring): - cdef poly *pnumer - cdef poly *pdenom + cdef int i + cdef int j + cdef number *n1 + cdef number *n2 + cdef number *a + cdef number *nlCoeff + cdef number *naCoeff + cdef number *apow1 + cdef number *apow2 + cdef number *numerator + cdef number *denominator + cdef number *cfnum + cdef number *cfden + cdef mpz_t mpz_num + cdef mpz_t mpz_den + cdef int ngens + + cdef int ex - cdef fraction *result - numer = elem.numerator() - pnumer = p_Copy(numer._poly, _ring) - denom = elem.denominator() - pdenom = p_Copy(denom._poly, _ring) + cdef nMapFunc nMapFuncPtr = NULL; + + ngens = elem.parent().ngens() nMapFuncPtr = naSetMap(_ring.cf, currRing.cf) # choose correct mapping function - result = omAlloc0Bin(fractionObjectBin) + if (nMapFuncPtr is NULL): + raise RuntimeError("Failed to determine nMapFuncPtr") + + numerdic = elem.numerator().dict() + denomdic = elem.denominator().dict() + + if _ring != currRing: + rChangeCurrRing(_ring) + n1 = _ring.cf.cfInit(0, _ring.cf) - result.numerator = pnumer - result.denominator = pdenom - result.complexity = 1 + apow2 = _ring.cf.cfInit(1, _ring.cf) - return result + + numerator = _ring.cf.cfInit(0, _ring.cf) + + for (exponents, coef) in numerdic.items(): + cfnum = _ring.cf.cfInit((int(coef.numerator())), _ring.cf) + cfden = _ring.cf.cfInit((int(coef.denominator())), _ring.cf) + naCoeff = _ring.cf.cfDiv(cfnum, cfden , _ring.cf ) + + + for (j, ex) in enumerate(exponents): + a = _ring.cf.cfParameter(j+1, _ring.cf) + for k in range(ex): + naCoeff = _ring.cf.cfMult(naCoeff, a ,_ring.cf) + numerator = _ring.cf.cfAdd(numerator, naCoeff,_ring.cf) + + if elem.denominator() != 1: + denominator = _ring.cf.cfInit(0, _ring.cf) + + for (exponents, coef) in denomdic.items(): + cfnum = _ring.cf.cfInit((int(coef.numerator())), _ring.cf) + cfden = _ring.cf.cfInit((int(coef.denominator())), _ring.cf) + naCoeff = _ring.cf.cfDiv(cfnum, cfden , _ring.cf ) + + for (j, ex) in enumerate(exponents): + a = _ring.cf.cfParameter(j+1, _ring.cf) + for k in range(ex): + naCoeff = _ring.cf.cfMult(naCoeff, a ,_ring.cf) + denominator = _ring.cf.cfAdd(denominator, naCoeff,_ring.cf) + + else: + denominator = _ring.cf.cfInit(1, _ring.cf) + + n1 = _ring.cf.cfDiv(numerator, denominator, _ring.cf) + + _ring.cf.cfDelete(&numerator, _ring.cf) + _ring.cf.cfDelete(&denominator, _ring.cf) + + _ring.cf.cfDelete(&apow2, _ring.cf) + _ring.cf.cfDelete(&naCoeff, _ring.cf) + + + + + return n1 cdef number *sa2si_NF(object elem, ring *_ring): From 2d89757c619b17fe4d090fdd0bb1178fa996cab4 Mon Sep 17 00:00:00 2001 From: Miguel Marco Date: Tue, 5 Oct 2021 22:25:50 +0200 Subject: [PATCH 012/126] Use mpz to create coefficients --- src/sage/libs/singular/decl.pxd | 1 + src/sage/libs/singular/singular.pyx | 15 +++++++++------ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/sage/libs/singular/decl.pxd b/src/sage/libs/singular/decl.pxd index 54c3fd36e58..4f387914784 100644 --- a/src/sage/libs/singular/decl.pxd +++ b/src/sage/libs/singular/decl.pxd @@ -127,6 +127,7 @@ cdef extern from "singular/Singular/libsingular.h": number* cfMult(number *, number *, const n_Procs_s* r) # algebraic number multiplication number* (*cfInit)(int i, const n_Procs_s* r ) # algebraic number from int + number* (*cfInitMPZ)(mpz_t i, const n_Procs_s* r) number* (*cfParameter)(int i, const n_Procs_s* r) int (*cfParDeg)(number* n, const n_Procs_s* r) int (*cfSize)(number* n, const n_Procs_s* r) diff --git a/src/sage/libs/singular/singular.pyx b/src/sage/libs/singular/singular.pyx index 2bd887646f1..d066c0a5824 100644 --- a/src/sage/libs/singular/singular.pyx +++ b/src/sage/libs/singular/singular.pyx @@ -500,8 +500,6 @@ cdef number *sa2si_transext(object elem, ring *_ring): cdef number *denominator cdef number *cfnum cdef number *cfden - cdef mpz_t mpz_num - cdef mpz_t mpz_den cdef int ngens cdef int ex @@ -530,8 +528,11 @@ cdef number *sa2si_transext(object elem, ring *_ring): numerator = _ring.cf.cfInit(0, _ring.cf) for (exponents, coef) in numerdic.items(): - cfnum = _ring.cf.cfInit((int(coef.numerator())), _ring.cf) - cfden = _ring.cf.cfInit((int(coef.denominator())), _ring.cf) + numer = coef.numerator() + cfnum = _ring.cf.cfInitMPZ((numer).value, _ring.cf) + denom = coef.denominator() + cfden = _ring.cf.cfInitMPZ((denom).value, _ring.cf) + naCoeff = _ring.cf.cfDiv(cfnum, cfden , _ring.cf ) @@ -545,8 +546,10 @@ cdef number *sa2si_transext(object elem, ring *_ring): denominator = _ring.cf.cfInit(0, _ring.cf) for (exponents, coef) in denomdic.items(): - cfnum = _ring.cf.cfInit((int(coef.numerator())), _ring.cf) - cfden = _ring.cf.cfInit((int(coef.denominator())), _ring.cf) + numer = coef.numerator() + cfnum = _ring.cf.cfInitMPZ((numer).value, _ring.cf) + denom = coef.denominator() + cfden = _ring.cf.cfInitMPZ((denom).value, _ring.cf) naCoeff = _ring.cf.cfDiv(cfnum, cfden , _ring.cf ) for (j, ex) in enumerate(exponents): From 64f4f572985875fe5e4a5eeda4409a1f3fb8e6fd Mon Sep 17 00:00:00 2001 From: Miguel Marco Date: Wed, 6 Oct 2021 17:30:51 +0200 Subject: [PATCH 013/126] Working implementation. Still needs cleanup, documentation, and checking for memory leaks --- src/sage/libs/singular/decl.pxd | 5 +- src/sage/libs/singular/singular.pyx | 105 ++++++++++++++++++++++++++-- 2 files changed, 102 insertions(+), 8 deletions(-) diff --git a/src/sage/libs/singular/decl.pxd b/src/sage/libs/singular/decl.pxd index 4f387914784..935d85b90b3 100644 --- a/src/sage/libs/singular/decl.pxd +++ b/src/sage/libs/singular/decl.pxd @@ -1143,10 +1143,7 @@ cdef extern from "singular/kernel/GBEngine/syz.h": cdef extern from "singular/polys/ext_fields/transext.h": ctypedef struct TransExtInfo: ring * r - ctypedef struct fraction "fractionObject": - poly *numerator - poly *denominator - int complexity + diff --git a/src/sage/libs/singular/singular.pyx b/src/sage/libs/singular/singular.pyx index d066c0a5824..8f687b6b6e2 100644 --- a/src/sage/libs/singular/singular.pyx +++ b/src/sage/libs/singular/singular.pyx @@ -45,10 +45,10 @@ from sage.cpython.string cimport str_to_bytes, char_to_str, bytes_to_str from sage.rings.polynomial.multi_polynomial_libsingular cimport MPolynomial_libsingular, MPolynomialRing_libsingular -cdef extern from "singular/coeffs/coeffs.h": - ctypedef struct coeffs "n_Procs_s" - - +ctypedef struct fraction "fractionObject": + poly *numerator + poly *denominator + int complexity _saved_options = (int(0),0,0) @@ -253,6 +253,80 @@ cdef object si2sa_GFq_generic(number *n, ring *_ring, object base): z = pNext(z) return ret +cdef object si2sa_transext(number *n, ring *_ring, object base): + """ + TESTS:: + + sage: F = PolynomialRing(QQ,'a,b').fraction_field() + sage: F.inject_variables() + Defining a, b + sage: R. = F[] + sage: a*x + (a)*x + sage: I = R.ideal([a*x]) + sage: I + Ideal ((a)*x) of Multivariate Polynomial Ring in x, y over Fraction Field of Multivariate Polynomial Ring in a, b over Rational Field + sage: I.groebner_basis() + [x] + sage: I = R.ideal([a*x+b*y^2, (b+a)/(b-a)*x^3-3*y*x]) + sage: I.groebner_basis() + [x^3 + (3*a - 3*b)/(a + b)*x*y, y^2 + (a)/(b)*x] + sage: R.term_order() + Degree reverse lexicographic term order + + """ + + cdef poly *numer + cdef poly *denom + cdef number *c + cdef int e + cdef fraction *frac + cdef object snumer + cdef object sdenom + + cdef ring *cfRing = _ring.cf.extRing + + if _ring.cf.cfIsZero(n,_ring.cf): + return base._zero_element + elif _ring.cf.cfIsOne(n,_ring.cf): + return base._one_element + + snumer = base(0) + sdenom = base(0) + + frac = n + + numer = frac.numerator + denom = frac.denominator + + while numer: + c = p_GetCoeff(numer, cfRing) + coeff = si2sa_QQ(c, &c, cfRing) + numer.coef = c + for i in range(base.ngens()): + e = p_GetExp(numer, i+1, cfRing) + if e!= 0: + coeff *= base.gen(i)**e + snumer += coeff + numer = pNext(numer) + + if not denom: + sdenom = base(1) + else: + while denom: + c = p_GetCoeff(denom, cfRing) + coeff = si2sa_QQ(c, &c, cfRing) + denom.coef = c + for i in range(base.ngens()): + e = p_GetExp(denom, i+1, cfRing) + if e!= 0: + coeff *= base.gen(i)**e + sdenom += coeff + denom = pNext(denom) + + return snumer/sdenom + + cdef object si2sa_NF(number *n, ring *_ring, object base): """ TESTS:: @@ -486,6 +560,26 @@ cdef number *sa2si_GFq_generic(object elem, ring *_ring): return n1 cdef number *sa2si_transext(object elem, ring *_ring): + """ + TESTS:: + + sage: F = PolynomialRing(QQ,'a,b').fraction_field() + sage: F.inject_variables() + Defining a, b + sage: R. = F[] + sage: a*x + (a)*x + sage: I = R.ideal([a*x]) + sage: I + Ideal ((a)*x) of Multivariate Polynomial Ring in x, y over Fraction Field of Multivariate Polynomial Ring in a, b over Rational Field + sage: I.groebner_basis() + [x] + sage: I = R.ideal([a*x+b*y^2, (b+a)/(b-a)*x^3-3*y*x]) + sage: I.groebner_basis() + [x^3 + (3*a - 3*b)/(a + b)*x*y, y^2 + (a)/(b)*x] + sage: R.term_order() + Degree reverse lexicographic term order + """ cdef int i cdef int j @@ -756,6 +850,9 @@ cdef object si2sa(number *n, ring *_ring, object base): elif isinstance(base, NumberField) and base.is_absolute(): return si2sa_NF(n, _ring, base) + elif isinstance(base, FractionField_generic) and isinstance(base.base(), (MPolynomialRing_libsingular, PolynomialRing_field)) and isinstance(base.base_ring(), RationalField): + return si2sa_transext(n, _ring, base) + elif isinstance(base, IntegerModRing_generic): if _ring.cf.type == n_unknown: return base(_ring.cf.cfInt(n, _ring.cf)) From 3d3419faf0f3115c7f89e4ce73a2231265ef26ff Mon Sep 17 00:00:00 2001 From: Miguel Marco Date: Wed, 6 Oct 2021 18:00:13 +0200 Subject: [PATCH 014/126] Fixed case with just one parameter --- src/sage/libs/singular/singular.pyx | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/sage/libs/singular/singular.pyx b/src/sage/libs/singular/singular.pyx index 8f687b6b6e2..c58cfdc577b 100644 --- a/src/sage/libs/singular/singular.pyx +++ b/src/sage/libs/singular/singular.pyx @@ -579,6 +579,21 @@ cdef number *sa2si_transext(object elem, ring *_ring): [x^3 + (3*a - 3*b)/(a + b)*x*y, y^2 + (a)/(b)*x] sage: R.term_order() Degree reverse lexicographic term order + + :: + + sage: F = PolynomialRing(QQ,'a').fraction_field() + sage: R. = F[] + sage: F.inject_variables() + Defining a + sage: a*x + (a)*x + sage: I = R.ideal([a*x+5*y^2, (1+a)/(1-a)*x^3-3*y*x]) + sage: I + Ideal (5*y^2 + (a)*x, (-a - 1)/(a - 1)*x^3 - 3*x*y) of Multivariate Polynomial Ring in x, y over Fraction Field of Univariate Polynomial Ring in a over Rational Field + sage: I.groebner_basis() + [x^3 + (3*a - 3)/(a + 1)*x*y, y^2 + (a)/5*x] + """ cdef int i @@ -598,8 +613,6 @@ cdef number *sa2si_transext(object elem, ring *_ring): cdef int ex - - cdef nMapFunc nMapFuncPtr = NULL; ngens = elem.parent().ngens() @@ -612,6 +625,14 @@ cdef number *sa2si_transext(object elem, ring *_ring): numerdic = elem.numerator().dict() denomdic = elem.denominator().dict() + if numerdic and type(list(numerdic)[0]) is not tuple: + numerdic = {(k,):b for k,b in numerdic.items()} + + if denomdic and type(list(denomdic)[0]) is not tuple: + denomdic = {(k,):b for k,b in denomdic.items()} + + + if _ring != currRing: rChangeCurrRing(_ring) n1 = _ring.cf.cfInit(0, _ring.cf) From 136a89a19aa1e476447ea5c88a66e6accb530f77 Mon Sep 17 00:00:00 2001 From: Miguel Marco Date: Wed, 6 Oct 2021 19:17:21 +0200 Subject: [PATCH 015/126] Fix problem with several parameters introduced by previous fix --- src/sage/libs/singular/decl.pxd | 2 -- src/sage/libs/singular/singular.pyx | 8 ++++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/sage/libs/singular/decl.pxd b/src/sage/libs/singular/decl.pxd index 935d85b90b3..997cb631dd1 100644 --- a/src/sage/libs/singular/decl.pxd +++ b/src/sage/libs/singular/decl.pxd @@ -402,8 +402,6 @@ cdef extern from "singular/Singular/libsingular.h": cdef omBin *slists_bin - cdef omBin *fractionObjectBin - # integer conversion constant cdef long SR_INT diff --git a/src/sage/libs/singular/singular.pyx b/src/sage/libs/singular/singular.pyx index c58cfdc577b..bbfba5039cb 100644 --- a/src/sage/libs/singular/singular.pyx +++ b/src/sage/libs/singular/singular.pyx @@ -27,6 +27,8 @@ import os from libc.stdint cimport int64_t from sage.libs.singular.decl cimport * +from sage.rings.polynomial.polydict import ETuple + from sage.rings.rational_field import RationalField from sage.rings.integer_ring cimport IntegerRing_class from sage.rings.finite_rings.integer_mod_ring import IntegerModRing_generic @@ -625,14 +627,12 @@ cdef number *sa2si_transext(object elem, ring *_ring): numerdic = elem.numerator().dict() denomdic = elem.denominator().dict() - if numerdic and type(list(numerdic)[0]) is not tuple: + if numerdic and not isinstance(list(numerdic)[0], (tuple, ETuple)): numerdic = {(k,):b for k,b in numerdic.items()} - if denomdic and type(list(denomdic)[0]) is not tuple: + if denomdic and not isinstance(list(denomdic)[0], (tuple, ETuple)): denomdic = {(k,):b for k,b in denomdic.items()} - - if _ring != currRing: rChangeCurrRing(_ring) n1 = _ring.cf.cfInit(0, _ring.cf) From 6271a79f532ade95f46c70f0afe48cee1aeb4914 Mon Sep 17 00:00:00 2001 From: Miguel Marco Date: Wed, 6 Oct 2021 23:10:45 +0200 Subject: [PATCH 016/126] Hack in plural.pyx to construct elements from numbers (through the base field) --- src/sage/rings/polynomial/plural.pyx | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/sage/rings/polynomial/plural.pyx b/src/sage/rings/polynomial/plural.pyx index 349871f5086..0d90a2fbfa3 100644 --- a/src/sage/rings/polynomial/plural.pyx +++ b/src/sage/rings/polynomial/plural.pyx @@ -419,7 +419,7 @@ cdef class NCPolynomialRing_plural(Ring): """ singular_ring_delete(self._ring) - def _element_constructor_(self, element): + def _element_constructor_(self, elem): """ Make sure element is a valid member of self, and return the constructed element. @@ -487,11 +487,22 @@ cdef class NCPolynomialRing_plural(Ring): Traceback (most recent call last): ... ValueError: unable to construct an element of this ring + + Check that it works for rings with parameters:: + + sage: F = PolynomialRing(QQ,'t1,t2').fraction_field() + sage: A = FreeAlgebra(F, 2, 'x,y') + sage: A.inject_variables() + Defining x, y + sage: B = A.g_algebra({y*x:-x*y}) + sage: B(2) + 2 + """ - if element == 0: + if elem == 0: return self._zero_element - if element == 1: + if elem == 1: return self._one_element cdef poly *_p @@ -502,6 +513,11 @@ cdef class NCPolynomialRing_plural(Ring): base_ring = self.base_ring() + try: + element = base_ring(elem) + except: + element = elem + if(_ring != currRing): rChangeCurrRing(_ring) if isinstance(element, NCPolynomial_plural): @@ -721,7 +737,7 @@ cdef class NCPolynomialRing_plural(Ring): -x*y """ from sage.repl.rich_output.backend_base import BackendBase - from sage.repl.display.pretty_print import SagePrettyPrinter + from sage.repl.display.pretty_print import SagePrettyPrinter varstr = ", ".join(char_to_str(rRingVar(i, self._ring)) for i in range(self.__ngens)) backend = BackendBase() From 2989430b29afb1e5499a6af3723967092ab4224b Mon Sep 17 00:00:00 2001 From: Miguel Marco Date: Wed, 6 Oct 2021 23:58:26 +0200 Subject: [PATCH 017/126] Make coercion to base ring in plural less agresive --- src/sage/rings/polynomial/plural.pyx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/sage/rings/polynomial/plural.pyx b/src/sage/rings/polynomial/plural.pyx index 0d90a2fbfa3..89d4e47d76b 100644 --- a/src/sage/rings/polynomial/plural.pyx +++ b/src/sage/rings/polynomial/plural.pyx @@ -138,6 +138,8 @@ from sage.structure.parent cimport Parent from sage.structure.parent_gens cimport ParentWithGens from sage.rings.polynomial.term_order import TermOrder +from sage.misc.functional import coerce + class G_AlgFactory(UniqueFactory): """ @@ -514,7 +516,7 @@ cdef class NCPolynomialRing_plural(Ring): base_ring = self.base_ring() try: - element = base_ring(elem) + element = coerce(base_ring, elem) except: element = elem From 50ac936b1477128b2676f8ec7b058caf403a78ae Mon Sep 17 00:00:00 2001 From: Miguel Marco Date: Fri, 8 Oct 2021 11:47:00 +0200 Subject: [PATCH 018/126] Force tail reduction in NCGroebnerStrategy --- src/sage/libs/singular/groebner_strategy.pyx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sage/libs/singular/groebner_strategy.pyx b/src/sage/libs/singular/groebner_strategy.pyx index a14df93ad42..1d4f7f0cdd5 100644 --- a/src/sage/libs/singular/groebner_strategy.pyx +++ b/src/sage/libs/singular/groebner_strategy.pyx @@ -372,6 +372,7 @@ cdef class NCGroebnerStrategy(SageObject): self._strat.enterS = enterSBba #- set S self._strat.sl = -1 + self._strat.noTailReduction = False #- init local data struct initS(i, NULL, self._strat) From 7ba8fc561b06207d2c2f377cd3cb1c7f1705583c Mon Sep 17 00:00:00 2001 From: Miguel Marco Date: Fri, 8 Oct 2021 11:52:16 +0200 Subject: [PATCH 019/126] Doctest the tail reduction fix --- src/sage/libs/singular/groebner_strategy.pyx | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/sage/libs/singular/groebner_strategy.pyx b/src/sage/libs/singular/groebner_strategy.pyx index 1d4f7f0cdd5..20751eafa71 100644 --- a/src/sage/libs/singular/groebner_strategy.pyx +++ b/src/sage/libs/singular/groebner_strategy.pyx @@ -341,6 +341,17 @@ cdef class NCGroebnerStrategy(SageObject): ... TypeError: First parameter must be an ideal in a g-algebra. + Check that tail reduction is applied too:: + + sage: F = PolynomialRing(QQ,'t').fraction_field() + sage: FA = FreeAlgebra(F, 6, 'x1,x2,x3,x4,x5,x6') + sage: N = FA.g_algebra({FA.gen(j)*FA.gen(i):-FA.gen(i)*FA.gen(j) for i in range(5) for j in range(i+1,6)}) + sage: I = N.ideal([g^2 for g in N.gens()],side='twosided') + sage: N.inject_variables() + Defining x1, x2, x3, x4, x5, x6 + sage: I.reduce(x1*x2*x3 + x2^2*x4) + x1*x2*x3 + """ if not isinstance(L, NCPolynomialIdeal): raise TypeError("First parameter must be an ideal in a g-algebra.") From 328dcc7b4333fa20ba30cddce8349bd21e6a8638 Mon Sep 17 00:00:00 2001 From: Miguel Marco Date: Fri, 8 Oct 2021 23:23:06 +0200 Subject: [PATCH 020/126] Make sure we are in the correct libsingular ring when creating the object --- src/sage/libs/singular/singular.pyx | 3 +++ src/sage/rings/polynomial/plural.pyx | 10 +++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/sage/libs/singular/singular.pyx b/src/sage/libs/singular/singular.pyx index bbfba5039cb..084592507f6 100644 --- a/src/sage/libs/singular/singular.pyx +++ b/src/sage/libs/singular/singular.pyx @@ -617,6 +617,9 @@ cdef number *sa2si_transext(object elem, ring *_ring): cdef nMapFunc nMapFuncPtr = NULL; + if _ring != currRing: + rChangeCurrRing(_ring) + ngens = elem.parent().ngens() nMapFuncPtr = naSetMap(_ring.cf, currRing.cf) # choose correct mapping function diff --git a/src/sage/rings/polynomial/plural.pyx b/src/sage/rings/polynomial/plural.pyx index 89d4e47d76b..80c905c0cef 100644 --- a/src/sage/rings/polynomial/plural.pyx +++ b/src/sage/rings/polynomial/plural.pyx @@ -421,7 +421,7 @@ cdef class NCPolynomialRing_plural(Ring): """ singular_ring_delete(self._ring) - def _element_constructor_(self, elem): + def _element_constructor_(self, element): """ Make sure element is a valid member of self, and return the constructed element. @@ -502,9 +502,9 @@ cdef class NCPolynomialRing_plural(Ring): """ - if elem == 0: + if element == 0: return self._zero_element - if elem == 1: + if element == 1: return self._one_element cdef poly *_p @@ -516,9 +516,9 @@ cdef class NCPolynomialRing_plural(Ring): base_ring = self.base_ring() try: - element = coerce(base_ring, elem) + element = coerce(base_ring, element) except: - element = elem + pass if(_ring != currRing): rChangeCurrRing(_ring) From 57d9d7d60208d83ebb949e32c3c39e019d0a4f4d Mon Sep 17 00:00:00 2001 From: Miguel Marco Date: Sat, 9 Oct 2021 00:01:26 +0200 Subject: [PATCH 021/126] Cleanup variables --- src/sage/libs/singular/singular.pyx | 31 +++++++++++------------------ 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/src/sage/libs/singular/singular.pyx b/src/sage/libs/singular/singular.pyx index 084592507f6..810597e40d6 100644 --- a/src/sage/libs/singular/singular.pyx +++ b/src/sage/libs/singular/singular.pyx @@ -596,25 +596,28 @@ cdef number *sa2si_transext(object elem, ring *_ring): sage: I.groebner_basis() [x^3 + (3*a - 3)/(a + 1)*x*y, y^2 + (a)/5*x] + :: + + sage: F = PolynomialRing(QQ,'a,b').fraction_field() + sage: R. = PolynomialRing(F) + sage: S. = QQ[] + sage: f = x + y + 1 + sage: R(f) + x + y + 1 + """ cdef int i cdef int j cdef number *n1 - cdef number *n2 cdef number *a - cdef number *nlCoeff cdef number *naCoeff - cdef number *apow1 - cdef number *apow2 cdef number *numerator cdef number *denominator cdef number *cfnum cdef number *cfden cdef int ngens - cdef int ex - cdef nMapFunc nMapFuncPtr = NULL; if _ring != currRing: @@ -639,21 +642,13 @@ cdef number *sa2si_transext(object elem, ring *_ring): if _ring != currRing: rChangeCurrRing(_ring) n1 = _ring.cf.cfInit(0, _ring.cf) - - apow2 = _ring.cf.cfInit(1, _ring.cf) - - numerator = _ring.cf.cfInit(0, _ring.cf) - for (exponents, coef) in numerdic.items(): numer = coef.numerator() cfnum = _ring.cf.cfInitMPZ((numer).value, _ring.cf) denom = coef.denominator() cfden = _ring.cf.cfInitMPZ((denom).value, _ring.cf) - naCoeff = _ring.cf.cfDiv(cfnum, cfden , _ring.cf ) - - for (j, ex) in enumerate(exponents): a = _ring.cf.cfParameter(j+1, _ring.cf) for k in range(ex): @@ -683,12 +678,10 @@ cdef number *sa2si_transext(object elem, ring *_ring): _ring.cf.cfDelete(&numerator, _ring.cf) _ring.cf.cfDelete(&denominator, _ring.cf) - - _ring.cf.cfDelete(&apow2, _ring.cf) + _ring.cf.cfDelete(&cfnum, _ring.cf) + _ring.cf.cfDelete(&cfden, _ring.cf) _ring.cf.cfDelete(&naCoeff, _ring.cf) - - - + _ring.cf.cfDelete(&a, _ring.cf) return n1 From e57f349e21bd48b00caa7cd18d5cfd96545f833e Mon Sep 17 00:00:00 2001 From: Miguel Marco Date: Sat, 9 Oct 2021 21:45:08 +0200 Subject: [PATCH 022/126] Make sure we free memory during coefficient creation --- src/sage/libs/singular/singular.pyx | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/sage/libs/singular/singular.pyx b/src/sage/libs/singular/singular.pyx index 810597e40d6..48073b73353 100644 --- a/src/sage/libs/singular/singular.pyx +++ b/src/sage/libs/singular/singular.pyx @@ -616,6 +616,8 @@ cdef number *sa2si_transext(object elem, ring *_ring): cdef number *denominator cdef number *cfnum cdef number *cfden + cdef number *aux1 + cdef number *aux2 cdef int ngens cdef int ex cdef nMapFunc nMapFuncPtr = NULL; @@ -652,8 +654,13 @@ cdef number *sa2si_transext(object elem, ring *_ring): for (j, ex) in enumerate(exponents): a = _ring.cf.cfParameter(j+1, _ring.cf) for k in range(ex): - naCoeff = _ring.cf.cfMult(naCoeff, a ,_ring.cf) - numerator = _ring.cf.cfAdd(numerator, naCoeff,_ring.cf) + aux1 = naCoeff + naCoeff = _ring.cf.cfMult(aux1, a ,_ring.cf) + _ring.cf.cfDelete(&aux1, _ring.cf) + _ring.cf.cfDelete(&a, _ring.cf) + aux2 = numerator + numerator = _ring.cf.cfAdd(aux2, naCoeff,_ring.cf) + _ring.cf.cfDelete(&aux2, _ring.cf) if elem.denominator() != 1: denominator = _ring.cf.cfInit(0, _ring.cf) @@ -664,12 +671,16 @@ cdef number *sa2si_transext(object elem, ring *_ring): denom = coef.denominator() cfden = _ring.cf.cfInitMPZ((denom).value, _ring.cf) naCoeff = _ring.cf.cfDiv(cfnum, cfden , _ring.cf ) - for (j, ex) in enumerate(exponents): a = _ring.cf.cfParameter(j+1, _ring.cf) for k in range(ex): - naCoeff = _ring.cf.cfMult(naCoeff, a ,_ring.cf) - denominator = _ring.cf.cfAdd(denominator, naCoeff,_ring.cf) + aux1 = naCoeff + naCoeff = _ring.cf.cfMult(aux1, a ,_ring.cf) + _ring.cf.cfDelete(&aux1, _ring.cf) + _ring.cf.cfDelete(&a, _ring.cf) + aux2 = denominator + denominator = _ring.cf.cfAdd(aux2, naCoeff,_ring.cf) + _ring.cf.cfDelete(&aux2, _ring.cf) else: denominator = _ring.cf.cfInit(1, _ring.cf) From d2e4ff7722ff5a33240ea51928156b4980d62149 Mon Sep 17 00:00:00 2001 From: Miguel Marco Date: Sun, 10 Oct 2021 11:24:42 +0200 Subject: [PATCH 023/126] Make sure single variables are represented consistently, and fix doctests broken because of the change in representation --- .../non_symmetric_macdonald_polynomials.py | 28 ++-- src/sage/combinat/sf/ns_macdonald.py | 12 +- src/sage/combinat/species/product_species.py | 2 +- .../combinat/species/recursive_species.py | 2 +- src/sage/combinat/species/species.py | 2 +- src/sage/combinat/species/sum_species.py | 4 +- ...otics_multivariate_generating_functions.py | 4 +- src/sage/rings/fraction_field.py | 4 +- src/sage/rings/invariants/invariant_theory.py | 6 +- .../multi_polynomial_libsingular.pyx | 8 +- src/sage/rings/polynomial/polydict.pyx | 4 +- .../rings/polynomial/polynomial_element.pyx | 3 +- src/sage/schemes/plane_conics/con_field.py | 6 +- .../schemes/projective/projective_morphism.py | 2 +- .../projective/projective_subscheme.py | 2 +- src/sage/schemes/toric/fano_variety.py | 122 +++++++++--------- 16 files changed, 110 insertions(+), 101 deletions(-) diff --git a/src/sage/combinat/root_system/non_symmetric_macdonald_polynomials.py b/src/sage/combinat/root_system/non_symmetric_macdonald_polynomials.py index f1dc9f608b4..5d406c1dd44 100644 --- a/src/sage/combinat/root_system/non_symmetric_macdonald_polynomials.py +++ b/src/sage/combinat/root_system/non_symmetric_macdonald_polynomials.py @@ -91,11 +91,11 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): sage: E = NonSymmetricMacdonaldPolynomials(["A",2,1], q=q, q1=t, q2=-1) sage: vars = K['x0,x1,x2'].gens() sage: E[L0([2,0,1])].expand(vars) - ((-t + 1)/(-q*t + 1))*x0^2*x1 + x0^2*x2 + ((-q*t + q)/(-q*t + 1))*x0*x1*x2 + (t - 1)/(q*t - 1)*x0^2*x1 + x0^2*x2 + (q*t - q)/(q*t - 1)*x0*x1*x2 sage: from sage.combinat.sf.ns_macdonald import E sage: E([2,0,1]) - ((-t + 1)/(-q*t + 1))*x0^2*x1 + x0^2*x2 + ((-q*t + q)/(-q*t + 1))*x0*x1*x2 + (t - 1)/(q*t - 1)*x0^2*x1 + x0^2*x2 + (q*t - q)/(q*t - 1)*x0*x1*x2 Here is a type `G_2^{(1)}` nonsymmetric Macdonald polynomial:: @@ -431,14 +431,14 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): sage: NS.E([1,0]) x0 sage: EE([0,1]) - ((-t + 1)/(-q*t + 1))*x0 + x1 + (t - 1)/(q*t - 1)*x0 + x1 sage: NS.E([0,1]) - ((-t + 1)/(-q*t + 1))*x0 + x1 + (t - 1)/(q*t - 1)*x0 + x1 sage: NS.E([2,0]) - x0^2 + ((-q*t + q)/(-q*t + 1))*x0*x1 + x0^2 + (q*t - q)/(q*t - 1)*x0*x1 sage: EE([2,0]) - x0^2 + ((-q*t + q)/(-q*t + 1))*x0*x1 + x0^2 + (q*t - q)/(q*t - 1)*x0*x1 The same, directly in the ambient lattice with several shifts:: @@ -948,20 +948,20 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): sage: EE([1,0,0]) x1 sage: EE([0,1,0]) - ((-t + 1)/(-q*t^2 + 1))*x1 + x2 + (t - 1)/(q*t^2 - 1)*x1 + x2 sage: EE([0,0,1]) - ((-t + 1)/(-q*t + 1))*x1 + ((-t + 1)/(-q*t + 1))*x2 + x3 + (t - 1)/(q*t - 1)*x1 + (t - 1)/(q*t - 1)*x2 + x3 sage: EE([1,1,0]) x1*x2 sage: EE([1,0,1]) - ((-t + 1)/(-q*t^2 + 1))*x1*x2 + x1*x3 + (t - 1)/(q*t^2 - 1)*x1*x2 + x1*x3 sage: EE([0,1,1]) - ((-t + 1)/(-q*t + 1))*x1*x2 + ((-t + 1)/(-q*t + 1))*x1*x3 + x2*x3 + (t - 1)/(q*t - 1)*x1*x2 + (t - 1)/(q*t - 1)*x1*x3 + x2*x3 sage: EE([2,0,0]) - x1^2 + ((-q*t + q)/(-q*t + 1))*x1*x2 + ((-q*t + q)/(-q*t + 1))*x1*x3 + x1^2 + (q*t - q)/(q*t - 1)*x1*x2 + (q*t - q)/(q*t - 1)*x1*x3 sage: EE([0,2,0]) - ((-t + 1)/(-q^2*t^2 + 1))*x1^2 + ((-q^2*t^3 + q^2*t^2 - q*t^2 + 2*q*t - q + t - 1)/(-q^3*t^3 + q^2*t^2 + q*t - 1))*x1*x2 + x2^2 + ((q*t^2 - 2*q*t + q)/(q^3*t^3 - q^2*t^2 - q*t + 1))*x1*x3 + ((-q*t + q)/(-q*t + 1))*x2*x3 + (t - 1)/(q^2*t^2 - 1)*x1^2 + (q^2*t^3 - q^2*t^2 + q*t^2 - 2*q*t + q - t + 1)/(q^3*t^3 - q^2*t^2 - q*t + 1)*x1*x2 + x2^2 + (q*t^2 - 2*q*t + q)/(q^3*t^3 - q^2*t^2 - q*t + 1)*x1*x3 + (q*t - q)/(q*t - 1)*x2*x3 Systematic checks with Sage's implementation of [HHL06]_:: @@ -1781,9 +1781,9 @@ def symmetric_macdonald_polynomial(self, mu): sage: P = SymmetricFunctions(K).macdonald().P() sage: g = P[2,1].expand(3); g - x0^2*x1 + x0*x1^2 + x0^2*x2 + ((-2*q*t^2 + q*t - t^2 + q - t + 2)/(-q*t^2 + 1))*x0*x1*x2 + x1^2*x2 + x0*x2^2 + x1*x2^2 + x0^2*x1 + x0*x1^2 + x0^2*x2 + (2*q*t^2 - q*t - q + t^2 + t - 2)/(q*t^2 - 1)*x0*x1*x2 + x1^2*x2 + x0*x2^2 + x1*x2^2 sage: fe = f.expand(g.parent().gens()); fe - x0^2*x1 + x0*x1^2 + x0^2*x2 + ((2*q*v^4 + v^4 - q*v^2 + v^2 - q - 2)/(q*v^4 - 1))*x0*x1*x2 + x1^2*x2 + x0*x2^2 + x1*x2^2 + x0^2*x1 + x0*x1^2 + x0^2*x2 + (2*q*v^4 - q*v^2 - q + v^4 + v^2 - 2)/(q*v^4 - 1)*x0*x1*x2 + x1^2*x2 + x0*x2^2 + x1*x2^2 sage: g.map_coefficients(lambda x: x.subs(t=v*v)) == fe True diff --git a/src/sage/combinat/sf/ns_macdonald.py b/src/sage/combinat/sf/ns_macdonald.py index 7ac278837c8..2ca5a957fd1 100644 --- a/src/sage/combinat/sf/ns_macdonald.py +++ b/src/sage/combinat/sf/ns_macdonald.py @@ -863,19 +863,19 @@ def E(mu, q=None, t=None, pi=None): sage: E([1,0,0]) x0 sage: E([0,1,0]) - ((-t + 1)/(-q*t^2 + 1))*x0 + x1 + (t - 1)/(q*t^2 - 1)*x0 + x1 sage: E([0,0,1]) - ((-t + 1)/(-q*t + 1))*x0 + ((-t + 1)/(-q*t + 1))*x1 + x2 + (t - 1)/(q*t - 1)*x0 + (t - 1)/(q*t - 1)*x1 + x2 sage: E([1,1,0]) x0*x1 sage: E([1,0,1]) - ((-t + 1)/(-q*t^2 + 1))*x0*x1 + x0*x2 + (t - 1)/(q*t^2 - 1)*x0*x1 + x0*x2 sage: E([0,1,1]) - ((-t + 1)/(-q*t + 1))*x0*x1 + ((-t + 1)/(-q*t + 1))*x0*x2 + x1*x2 + (t - 1)/(q*t - 1)*x0*x1 + (t - 1)/(q*t - 1)*x0*x2 + x1*x2 sage: E([2,0,0]) - x0^2 + ((-q*t + q)/(-q*t + 1))*x0*x1 + ((-q*t + q)/(-q*t + 1))*x0*x2 + x0^2 + (q*t - q)/(q*t - 1)*x0*x1 + (q*t - q)/(q*t - 1)*x0*x2 sage: E([0,2,0]) - ((-t + 1)/(-q^2*t^2 + 1))*x0^2 + ((-q^2*t^3 + q^2*t^2 - q*t^2 + 2*q*t - q + t - 1)/(-q^3*t^3 + q^2*t^2 + q*t - 1))*x0*x1 + x1^2 + ((q*t^2 - 2*q*t + q)/(q^3*t^3 - q^2*t^2 - q*t + 1))*x0*x2 + ((-q*t + q)/(-q*t + 1))*x1*x2 + (t - 1)/(q^2*t^2 - 1)*x0^2 + (q^2*t^3 - q^2*t^2 + q*t^2 - 2*q*t + q - t + 1)/(q^3*t^3 - q^2*t^2 - q*t + 1)*x0*x1 + x1^2 + (q*t^2 - 2*q*t + q)/(q^3*t^3 - q^2*t^2 - q*t + 1)*x0*x2 + (q*t - q)/(q*t - 1)*x1*x2 """ P, q, t, n, R, x = _check_muqt(mu, q, t, pi) res = 0 diff --git a/src/sage/combinat/species/product_species.py b/src/sage/combinat/species/product_species.py index 4bbee606925..5295e3a87c9 100644 --- a/src/sage/combinat/species/product_species.py +++ b/src/sage/combinat/species/product_species.py @@ -409,7 +409,7 @@ def _equation(self, var_mapping): sage: X = species.SingletonSpecies() sage: S = X * X sage: S.algebraic_equation_system() - [node0 - z^2] + [node0 + (-z^2)] """ from sage.misc.all import prod return prod(var_mapping[operand] for operand in self._state_info) diff --git a/src/sage/combinat/species/recursive_species.py b/src/sage/combinat/species/recursive_species.py index 7af1a0dee36..5bbc93d014d 100644 --- a/src/sage/combinat/species/recursive_species.py +++ b/src/sage/combinat/species/recursive_species.py @@ -467,7 +467,7 @@ def _equation(self, var_mapping): sage: B = species.BinaryTreeSpecies() sage: B.algebraic_equation_system() - [-node3^2 + node1, -node1 + node3 - z] + [-node3^2 + node1, -node1 + node3 + (-z)] """ try: return var_mapping[self._reference] diff --git a/src/sage/combinat/species/species.py b/src/sage/combinat/species/species.py index aa5e29356d2..06efe0ab329 100644 --- a/src/sage/combinat/species/species.py +++ b/src/sage/combinat/species/species.py @@ -769,7 +769,7 @@ def algebraic_equation_system(self): sage: B = species.BinaryTreeSpecies() sage: B.algebraic_equation_system() - [-node3^2 + node1, -node1 + node3 - z] + [-node3^2 + node1, -node1 + node3 + (-z)] :: diff --git a/src/sage/combinat/species/sum_species.py b/src/sage/combinat/species/sum_species.py index a7f0a616fdc..9168ffa76bc 100644 --- a/src/sage/combinat/species/sum_species.py +++ b/src/sage/combinat/species/sum_species.py @@ -84,7 +84,7 @@ def right_summand(self): sage: F = P + P*P sage: F.right_summand() Product of (Permutation species) and (Permutation species) - """ + """ return self._G def _name(self): @@ -214,7 +214,7 @@ def _equation(self, var_mapping): sage: X = species.SingletonSpecies() sage: S = X + X sage: S.algebraic_equation_system() - [node1 - 2*z] + [node1 + (-2*z)] """ return sum(var_mapping[operand] for operand in self._state_info) diff --git a/src/sage/rings/asymptotic/asymptotics_multivariate_generating_functions.py b/src/sage/rings/asymptotic/asymptotics_multivariate_generating_functions.py index 06301c7633c..b37e597e214 100644 --- a/src/sage/rings/asymptotic/asymptotics_multivariate_generating_functions.py +++ b/src/sage/rings/asymptotic/asymptotics_multivariate_generating_functions.py @@ -2725,7 +2725,7 @@ def smooth_critical_ideal(self, alpha): sage: F = FFPD(G, Hfac) sage: alpha = var('a1, a2') sage: F.smooth_critical_ideal(alpha) - Ideal (y^2 + 2*a1/a2*y - 1, x + ((-a2)/a1)*y + (-a1 + a2)/a1) of + Ideal (y^2 + (2*a1)/(a2)*y - 1, x + (-a2)/(a1)*y + (-a1 + a2)/(a1)) of Multivariate Polynomial Ring in x, y over Fraction Field of Multivariate Polynomial Ring in a1, a2 over Rational Field @@ -2735,7 +2735,7 @@ def smooth_critical_ideal(self, alpha): sage: F = FFPD(G, Hfac) sage: alpha = [7/3, var('a')] sage: F.smooth_critical_ideal(alpha) - Ideal (y^2 + 14/3/a*y - 1, x + (-3/7*a)*y + 3/7*a - 1) of Multivariate Polynomial Ring in x, y over Fraction Field of Univariate Polynomial Ring in a over Rational Field + Ideal (y^2 + 14/(3*a)*y - 1, x + (-3*a)/7*y + (3*a - 7)/7) of Multivariate Polynomial Ring in x, y over Fraction Field of Univariate Polynomial Ring in a over Rational Field """ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing diff --git a/src/sage/rings/fraction_field.py b/src/sage/rings/fraction_field.py index c5b5c55a785..27e6277ad1b 100644 --- a/src/sage/rings/fraction_field.py +++ b/src/sage/rings/fraction_field.py @@ -586,7 +586,7 @@ def _element_constructor_(self, x, y=None, coerce=True): sage: B. = PolynomialRing(A,'d,e') sage: R. = PolynomialRing(B,'x') sage: (a*d*x^2+a+e+1).resultant(-4*c^2*x+1) - a*d + 16*c^4*e + 16*a*c^4 + 16*c^4 + (a)*d + (16*c^4)*e + (16*a*c^4 + 16*c^4) Check that :trac:`24539` is fixed:: @@ -618,6 +618,8 @@ def _element_constructor_(self, x, y=None, coerce=True): sage: F(x) -1/2/(a^2 + a) """ + if isinstance(x, (list, tuple)) and len(x) == 1: + x = x[0] if y is None: if parent(x) is self: return x diff --git a/src/sage/rings/invariants/invariant_theory.py b/src/sage/rings/invariants/invariant_theory.py index 059a774025b..245bfdbee11 100644 --- a/src/sage/rings/invariants/invariant_theory.py +++ b/src/sage/rings/invariants/invariant_theory.py @@ -256,9 +256,9 @@ def transvectant(f, g, h=1, scale='default'): sage: S. = R[] sage: quintic = invariant_theory.binary_quintic(x^5+x^3+2*x^2+y^5, x) sage: transvectant(quintic, quintic, 2) - Binary sextic given by 1/5*x^6 + 6/5*x^5*h + (-3/25)*x^4*h^2 - + (2*y^5 - 8/25)*x^3*h^3 + (-12/25)*x^2*h^4 + 3/5*y^5*x*h^5 - + 2/5*y^5*h^6 + Binary sextic given by 1/5*x^6 + 6/5*x^5*h - 3/25*x^4*h^2 + + (50*y^5 - 8)/25*x^3*h^3 - 12/25*x^2*h^4 + (3*y^5)/5*x*h^5 + + (2*y^5)/5*h^6 """ f = f.homogenized() g = g.homogenized() diff --git a/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx b/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx index ec706f3129d..655987381fb 100644 --- a/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx +++ b/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx @@ -251,6 +251,8 @@ from sage.interfaces.macaulay2 import macaulay2 as macaulay2_default, is_Macaula from sage.misc.all import prod as mul from sage.misc.sage_eval import sage_eval +import re + cimport cypari2.gen from . import polynomial_element @@ -559,7 +561,7 @@ cdef class MPolynomialRing_libsingular(MPolynomialRing_base): sage: k. = GF(2^8) sage: P. = PolynomialRing(k,2) sage: P._coerce_(a) - (a) + a sage: z = QQ['z'].0 sage: K. = NumberField(z^2 - 2) @@ -2481,6 +2483,10 @@ cdef class MPolynomial_libsingular(MPolynomial): """ cdef ring *_ring = self._parent_ring s = singular_polynomial_str(self._poly, _ring) + regexp = re.compile(r'\([a-zA-Z][a-zA-Z0-9]*\)') + res = regexp.fullmatch(s) + if res: + return s[1:-1] return s cpdef _repr_short_(self): diff --git a/src/sage/rings/polynomial/polydict.pyx b/src/sage/rings/polynomial/polydict.pyx index 98b663a029d..651d4041272 100644 --- a/src/sage/rings/polynomial/polydict.pyx +++ b/src/sage/rings/polynomial/polydict.pyx @@ -1624,11 +1624,11 @@ cdef class ETuple: sage: R. = Frac(QQ['x'])[] sage: type(y) - + sage: y^(2^32) Traceback (most recent call last): ... - OverflowError: exponent overflow (2147483648) + OverflowError: exponent overflow (...) """ if self._length!=other._length: raise ArithmeticError diff --git a/src/sage/rings/polynomial/polynomial_element.pyx b/src/sage/rings/polynomial/polynomial_element.pyx index dabc030c828..6d1d6c7f626 100644 --- a/src/sage/rings/polynomial/polynomial_element.pyx +++ b/src/sage/rings/polynomial/polynomial_element.pyx @@ -6508,7 +6508,8 @@ cdef class Polynomial(CommutativeAlgebraElement): sage: p = ((1/b^2*d^2+1/a)*x*y^2+a*b/c*y+e+x^2) sage: q = -4*c^2*y^3+1 sage: p.resultant(q) - 16*c^4*x^6 + 48*c^4*e*x^4 + (1/b^6*d^6 + 3/(a*b^4)*d^4 + ((-12*a^3*b*c + 3)/(a^2*b^2))*d^2 + (-12*a^3*b*c + 1)/a^3)*x^3 + 48*c^4*e^2*x^2 + (((-12*a*c)/b)*d^2*e + (-12*b*c)*e)*x + 16*c^4*e^3 + 4*a^3*b^3/c + (16*c^4)*x^6 + (48*c^4)*e*x^4 + (1/(b^6)*d^6 + 3/(a*b^4)*d^4 + (-12*a^3*b*c + 3)/(a^2*b^2)*d^2 + (-12*a^3*b*c + 1)/(a^3))*x^3 + (48*c^4)*e^2*x^2 + ((-12*a*c)/(b)*d^2*e + (-12*b*c)*e)*x + (16*c^4)*e^3 + (4*a^3*b^3)/(c) + Test for :trac:`10978`:: diff --git a/src/sage/schemes/plane_conics/con_field.py b/src/sage/schemes/plane_conics/con_field.py index 04ee419f880..929ff0dccb6 100644 --- a/src/sage/schemes/plane_conics/con_field.py +++ b/src/sage/schemes/plane_conics/con_field.py @@ -683,10 +683,10 @@ def hom(self, x, Y=None): sage: T = Matrix([[t,0,1],[0,1,0],[0,0,1]]) sage: C.hom(T, D) Scheme morphism: - From: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Rational Field defined by x^2 + t*y^2 + 1/t*z^2 - To: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Rational Field defined by 1/t^2*x^2 + t*y^2 + (-2/t^2)*x*z + ((t + 1)/t^2)*z^2 + From: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Rational Field defined by x^2 + (t)*y^2 + 1/(t)*z^2 + To: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Rational Field defined by 1/(t^2)*x^2 + (t)*y^2 - 2/(t^2)*x*z + (t + 1)/(t^2)*z^2 Defn: Defined on coordinates by sending (x : y : z) to - (t*x + z : y : z) + ((t)*x + z : y : z) """ if is_Matrix(x): diff --git a/src/sage/schemes/projective/projective_morphism.py b/src/sage/schemes/projective/projective_morphism.py index adbffd9008e..056eb076b28 100644 --- a/src/sage/schemes/projective/projective_morphism.py +++ b/src/sage/schemes/projective/projective_morphism.py @@ -1114,7 +1114,7 @@ def dehomogenize(self, n): Scheme endomorphism of Affine Space of dimension 2 over Fraction Field of Univariate Polynomial Ring in t over Rational Field Defn: Defined on coordinates by sending (x, y) to - (1/t*x^2 + y^2, y^2 - 1/t) + (1/(t)*x^2 + y^2, y^2 - 1/(t)) :: diff --git a/src/sage/schemes/projective/projective_subscheme.py b/src/sage/schemes/projective/projective_subscheme.py index 8b91a17accf..609dd9bafac 100644 --- a/src/sage/schemes/projective/projective_subscheme.py +++ b/src/sage/schemes/projective/projective_subscheme.py @@ -663,7 +663,7 @@ def _forward_image(self, f, check = True): sage: f([t^2*y-z]) Closed subscheme of Projective Space of dimension 2 over Fraction Field of Univariate Polynomial Ring in t over Rational Field defined by: - y + (-1/t^2)*z + y - 1/(t^2)*z :: diff --git a/src/sage/schemes/toric/fano_variety.py b/src/sage/schemes/toric/fano_variety.py index 20b15e3fc66..579fd4821f2 100644 --- a/src/sage/schemes/toric/fano_variety.py +++ b/src/sage/schemes/toric/fano_variety.py @@ -57,10 +57,10 @@ ....: monomial_points="all") Closed subscheme of 2-d CPR-Fano toric variety covered by 3 affine patches defined by: - a0*z0^3 + a9*z0^2*z1 + a7*z0*z1^2 - + a1*z1^3 + a8*z0^2*z2 + a6*z0*z1*z2 - + a4*z1^2*z2 + a5*z0*z2^2 - + a3*z1*z2^2 + a2*z2^3 + (a0)*z0^3 + (a9)*z0^2*z1 + (a7)*z0*z1^2 + + (a1)*z1^3 + (a8)*z0^2*z2 + (a6)*z0*z1*z2 + + (a4)*z1^2*z2 + (a5)*z0*z2^2 + + (a3)*z1*z2^2 + (a2)*z2^3 In many cases it is sufficient to work with the "simplified polynomial moduli space" of anticanonical hypersurfaces:: @@ -69,7 +69,7 @@ ....: monomial_points="simplified") Closed subscheme of 2-d CPR-Fano toric variety covered by 3 affine patches defined by: - a0*z0^3 + a1*z1^3 + a6*z0*z1*z2 + a2*z2^3 + (a0)*z0^3 + (a1)*z1^3 + (a6)*z0*z1*z2 + (a2)*z2^3 The mirror family to these hypersurfaces lives inside the Fano toric variety obtained using ``simplex`` as ``Delta`` instead of ``Delta_polar``:: @@ -80,10 +80,10 @@ ....: monomial_points="simplified") Closed subscheme of 2-d CPR-Fano toric variety covered by 9 affine patches defined by: - a2*z2^3*z3^2*z4*z5^2*z8 - + a1*z1^3*z3*z4^2*z7^2*z9 - + a3*z0*z1*z2*z3*z4*z5*z7*z8*z9 - + a0*z0^3*z5*z7*z8^2*z9^2 + (a2)*z2^3*z3^2*z4*z5^2*z8 + + (a1)*z1^3*z3*z4^2*z7^2*z9 + + (a3)*z0*z1*z2*z3*z4*z5*z7*z8*z9 + + (a0)*z0^3*z5*z7*z8^2*z9^2 Here we have taken the resolved version of the ambient space for the mirror family, but in fact we don't have to resolve singularities @@ -96,7 +96,7 @@ ....: monomial_points="simplified") Closed subscheme of 2-d CPR-Fano toric variety covered by 3 affine patches defined by: - a0*z0^3 + a1*z1^3 + a3*z0*z1*z2 + a2*z2^3 + (a0)*z0^3 + (a1)*z1^3 + (a3)*z0*z1*z2 + (a2)*z2^3 This looks very similar to our second version of the anticanonical hypersurface of the projective plane, as expected, since all @@ -110,8 +110,8 @@ sage: FTV.anticanonical_hypersurface() Closed subscheme of 3-d CPR-Fano toric variety covered by 4 affine patches defined by: - a0*z2^12 + a4*z2^6*z3^6 + a3*z3^12 - + a8*z0*z1*z2*z3 + a2*z1^3 + a1*z0^2 + (a0)*z2^12 + (a4)*z2^6*z3^6 + (a3)*z3^12 + + (a8)*z0*z1*z2*z3 + (a2)*z1^3 + (a1)*z0^2 Below you will find detailed descriptions of available functions. Current functionality of this module is very basic, but it is under active @@ -806,10 +806,10 @@ def anticanonical_hypersurface(self, **kwds): ....: monomial_points="all") Closed subscheme of 2-d CPR-Fano toric variety covered by 3 affine patches defined by: - a0*z0^3 + a9*z0^2*z1 + a7*z0*z1^2 - + a1*z1^3 + a8*z0^2*z2 + a6*z0*z1*z2 - + a4*z1^2*z2 + a5*z0*z2^2 - + a3*z1*z2^2 + a2*z2^3 + (a0)*z0^3 + (a9)*z0^2*z1 + (a7)*z0*z1^2 + + (a1)*z1^3 + (a8)*z0^2*z2 + (a6)*z0*z1*z2 + + (a4)*z1^2*z2 + (a5)*z0*z2^2 + + (a3)*z1*z2^2 + (a2)*z2^3 In many cases it is sufficient to work with the "simplified polynomial moduli space" of anticanonical hypersurfaces:: @@ -818,7 +818,7 @@ def anticanonical_hypersurface(self, **kwds): ....: monomial_points="simplified") Closed subscheme of 2-d CPR-Fano toric variety covered by 3 affine patches defined by: - a0*z0^3 + a1*z1^3 + a6*z0*z1*z2 + a2*z2^3 + (a0)*z0^3 + (a1)*z1^3 + (a6)*z0*z1*z2 + (a2)*z2^3 The mirror family to these hypersurfaces lives inside the Fano toric variety obtained using ``simplex`` as ``Delta`` instead of @@ -830,10 +830,10 @@ def anticanonical_hypersurface(self, **kwds): ....: monomial_points="simplified") Closed subscheme of 2-d CPR-Fano toric variety covered by 9 affine patches defined by: - a2*z2^3*z3^2*z4*z5^2*z8 - + a1*z1^3*z3*z4^2*z7^2*z9 - + a3*z0*z1*z2*z3*z4*z5*z7*z8*z9 - + a0*z0^3*z5*z7*z8^2*z9^2 + (a2)*z2^3*z3^2*z4*z5^2*z8 + + (a1)*z1^3*z3*z4^2*z7^2*z9 + + (a3)*z0*z1*z2*z3*z4*z5*z7*z8*z9 + + (a0)*z0^3*z5*z7*z8^2*z9^2 Here we have taken the resolved version of the ambient space for the mirror family, but in fact we don't have to resolve singularities @@ -846,7 +846,7 @@ def anticanonical_hypersurface(self, **kwds): ....: monomial_points="simplified") Closed subscheme of 2-d CPR-Fano toric variety covered by 3 affine patches defined by: - a0*z0^3 + a1*z1^3 + a3*z0*z1*z2 + a2*z2^3 + (a0)*z0^3 + (a1)*z1^3 + (a3)*z0*z1*z2 + (a2)*z2^3 This looks very similar to our second anticanonical hypersurface of the projective plane, as expected, since all @@ -860,7 +860,7 @@ def anticanonical_hypersurface(self, **kwds): ....: coefficient_names="a b c d") Closed subscheme of 2-d CPR-Fano toric variety covered by 3 affine patches defined by: - a*z0^3 + b*z1^3 + d*z0*z1*z2 + c*z2^3 + (a)*z0^3 + (b)*z1^3 + (d)*z0*z1*z2 + (c)*z2^3 or give concrete coefficients :: @@ -877,7 +877,7 @@ def anticanonical_hypersurface(self, **kwds): sage: H Closed subscheme of 2-d CPR-Fano toric variety covered by 3 affine patches defined by: - t*z1^3 + (psi/(psi^2 + phi))*z0*z1*z2 + 1/t*z2^3 + (t)*z1^3 + (psi)/(phi + psi^2)*z0*z1*z2 + 1/(t)*z2^3 sage: R = H.ambient_space().base_ring() sage: R Fraction Field of @@ -1124,21 +1124,21 @@ def nef_complete_intersection(self, nef_partition, **kwds): sage: X.nef_complete_intersection(np) Closed subscheme of 3-d CPR-Fano toric variety covered by 10 affine patches defined by: - a0*z1*z4^2*z5^2*z7^3 + a2*z2*z4*z5*z6*z7^2*z8^2 - + a3*z2*z3*z4*z7*z8 + a1*z0*z2, - b3*z1*z4*z5^2*z6^2*z7^2*z8^2 + b0*z2*z5*z6^3*z7*z8^4 - + b5*z1*z3*z4*z5*z6*z7*z8 + b2*z2*z3*z6^2*z8^3 - + b1*z1*z3^2*z4 + b4*z0*z1*z5*z6 + (a0)*z1*z4^2*z5^2*z7^3 + (a2)*z2*z4*z5*z6*z7^2*z8^2 + + (a3)*z2*z3*z4*z7*z8 + (a1)*z0*z2, + (b3)*z1*z4*z5^2*z6^2*z7^2*z8^2 + (b0)*z2*z5*z6^3*z7*z8^4 + + (b5)*z1*z3*z4*z5*z6*z7*z8 + (b2)*z2*z3*z6^2*z8^3 + + (b1)*z1*z3^2*z4 + (b4)*z0*z1*z5*z6 Now we include only monomials associated to vertices of `\Delta_i`:: sage: X.nef_complete_intersection(np, monomial_points="vertices") Closed subscheme of 3-d CPR-Fano toric variety covered by 10 affine patches defined by: - a0*z1*z4^2*z5^2*z7^3 + a2*z2*z4*z5*z6*z7^2*z8^2 - + a3*z2*z3*z4*z7*z8 + a1*z0*z2, - b3*z1*z4*z5^2*z6^2*z7^2*z8^2 + b0*z2*z5*z6^3*z7*z8^4 - + b2*z2*z3*z6^2*z8^3 + b1*z1*z3^2*z4 + b4*z0*z1*z5*z6 + (a0)*z1*z4^2*z5^2*z7^3 + (a2)*z2*z4*z5*z6*z7^2*z8^2 + + (a3)*z2*z3*z4*z7*z8 + (a1)*z0*z2, + (b3)*z1*z4*z5^2*z6^2*z7^2*z8^2 + (b0)*z2*z5*z6^3*z7*z8^4 + + (b2)*z2*z3*z6^2*z8^3 + (b1)*z1*z3^2*z4 + (b4)*z0*z1*z5*z6 (effectively, we set ``b5=0``). Next we provide coefficients explicitly instead of using default generic names:: @@ -1148,8 +1148,8 @@ def nef_complete_intersection(self, nef_partition, **kwds): ....: coefficients=[("a", "a^2", "a/e", "c_i"), list(range(1,6))]) Closed subscheme of 3-d CPR-Fano toric variety covered by 10 affine patches defined by: - a*z1*z4^2*z5^2*z7^3 + a/e*z2*z4*z5*z6*z7^2*z8^2 - + c_i*z2*z3*z4*z7*z8 + a^2*z0*z2, + (a)*z1*z4^2*z5^2*z7^3 + (a)/(e)*z2*z4*z5*z6*z7^2*z8^2 + + (c_i)*z2*z3*z4*z7*z8 + (a^2)*z0*z2, 4*z1*z4*z5^2*z6^2*z7^2*z8^2 + z2*z5*z6^3*z7*z8^4 + 3*z2*z3*z6^2*z8^3 + 2*z1*z3^2*z4 + 5*z0*z1*z5*z6 @@ -1161,14 +1161,14 @@ def nef_complete_intersection(self, nef_partition, **kwds): sage: X.nef_complete_intersection(np) Closed subscheme of 3-d CPR-Fano toric variety covered by 22 affine patches defined by: - a2*z2*z4*z5*z6*z7^2*z8^2*z9^2*z10^2*z11*z12*z13 - + a0*z1*z4^2*z5^2*z7^3*z9*z10^2*z12*z13 - + a3*z2*z3*z4*z7*z8*z9*z10*z11*z12 + a1*z0*z2, - b0*z2*z5*z6^3*z7*z8^4*z9^3*z10^2*z11^2*z12*z13^2 - + b3*z1*z4*z5^2*z6^2*z7^2*z8^2*z9^2*z10^2*z11*z12*z13^2 - + b2*z2*z3*z6^2*z8^3*z9^2*z10*z11^2*z12*z13 - + b5*z1*z3*z4*z5*z6*z7*z8*z9*z10*z11*z12*z13 - + b1*z1*z3^2*z4*z11*z12 + b4*z0*z1*z5*z6*z13 + (a2)*z2*z4*z5*z6*z7^2*z8^2*z9^2*z10^2*z11*z12*z13 + + (a0)*z1*z4^2*z5^2*z7^3*z9*z10^2*z12*z13 + + (a3)*z2*z3*z4*z7*z8*z9*z10*z11*z12 + (a1)*z0*z2, + (b0)*z2*z5*z6^3*z7*z8^4*z9^3*z10^2*z11^2*z12*z13^2 + + (b3)*z1*z4*z5^2*z6^2*z7^2*z8^2*z9^2*z10^2*z11*z12*z13^2 + + (b2)*z2*z3*z6^2*z8^3*z9^2*z10*z11^2*z12*z13 + + (b5)*z1*z3*z4*z5*z6*z7*z8*z9*z10*z11*z12*z13 + + (b1)*z1*z3^2*z4*z11*z12 + (b4)*z0*z1*z5*z6*z13 """ return NefCompleteIntersection(self, nef_partition, **kwds) @@ -1356,7 +1356,7 @@ class AnticanonicalHypersurface(AlgebraicScheme_subscheme_toric): sage: ftv.AnticanonicalHypersurface(P1xP1) Closed subscheme of 2-d CPR-Fano toric variety covered by 4 affine patches defined by: - a0*s^2*x^2 + a3*t^2*x^2 + a6*s*t*x*y + a1*s^2*y^2 + a2*t^2*y^2 + (a0)*s^2*x^2 + (a3)*t^2*x^2 + (a6)*s*t*x*y + (a1)*s^2*y^2 + (a2)*t^2*y^2 See :meth:`~CPRFanoToricVariety_field.anticanonical_hypersurface()` for a more elaborate example. @@ -1374,7 +1374,7 @@ def __init__(self, P_Delta, monomial_points=None, coefficient_names=None, sage: ftv.AnticanonicalHypersurface(P1xP1) Closed subscheme of 2-d CPR-Fano toric variety covered by 4 affine patches defined by: - a0*s^2*x^2 + a3*t^2*x^2 + a6*s*t*x*y + a1*s^2*y^2 + a2*t^2*y^2 + (a0)*s^2*x^2 + (a3)*t^2*x^2 + (a6)*s*t*x*y + (a1)*s^2*y^2 + (a2)*t^2*y^2 Check that finite fields are handled correctly :trac:`14899`:: @@ -1473,10 +1473,10 @@ class NefCompleteIntersection(AlgebraicScheme_subscheme_toric): sage: X.nef_complete_intersection(np) Closed subscheme of 3-d CPR-Fano toric variety covered by 8 affine patches defined by: - a2*z0^2*z1 + a5*z0*z1*z3 + a1*z1*z3^2 - + a3*z0^2*z4 + a4*z0*z3*z4 + a0*z3^2*z4, - b1*z1*z2^2 + b2*z2^2*z4 + b5*z1*z2*z5 - + b4*z2*z4*z5 + b3*z1*z5^2 + b0*z4*z5^2 + (a2)*z0^2*z1 + (a5)*z0*z1*z3 + (a1)*z1*z3^2 + + (a3)*z0^2*z4 + (a4)*z0*z3*z4 + (a0)*z3^2*z4, + (b1)*z1*z2^2 + (b2)*z2^2*z4 + (b5)*z1*z2*z5 + + (b4)*z2*z4*z5 + (b3)*z1*z5^2 + (b0)*z4*z5^2 See :meth:`CPRFanoToricVariety_field.nef_complete_intersection` for a more elaborate example. @@ -1499,10 +1499,10 @@ def __init__(self, P_Delta, nef_partition, sage: NefCompleteIntersection(X, np) Closed subscheme of 3-d CPR-Fano toric variety covered by 8 affine patches defined by: - a2*z0^2*z1 + a5*z0*z1*z3 + a1*z1*z3^2 - + a3*z0^2*z4 + a4*z0*z3*z4 + a0*z3^2*z4, - b1*z1*z2^2 + b2*z2^2*z4 + b5*z1*z2*z5 - + b4*z2*z4*z5 + b3*z1*z5^2 + b0*z4*z5^2 + (a2)*z0^2*z1 + (a5)*z0*z1*z3 + (a1)*z1*z3^2 + + (a3)*z0^2*z4 + (a4)*z0*z3*z4 + (a0)*z3^2*z4, + (b1)*z1*z2^2 + (b2)*z2^2*z4 + (b5)*z1*z2*z5 + + (b4)*z2*z4*z5 + (b3)*z1*z5^2 + (b0)*z4*z5^2 """ if not is_CPRFanoToricVariety(P_Delta): raise TypeError("nef complete intersections can only be " @@ -1597,10 +1597,10 @@ def cohomology_class(self): sage: CI Closed subscheme of 3-d CPR-Fano toric variety covered by 8 affine patches defined by: - a2*z0^2*z1 + a5*z0*z1*z3 + a1*z1*z3^2 - + a3*z0^2*z4 + a4*z0*z3*z4 + a0*z3^2*z4, - b1*z1*z2^2 + b2*z2^2*z4 + b5*z1*z2*z5 - + b4*z2*z4*z5 + b3*z1*z5^2 + b0*z4*z5^2 + (a2)*z0^2*z1 + (a5)*z0*z1*z3 + (a1)*z1*z3^2 + + (a3)*z0^2*z4 + (a4)*z0*z3*z4 + (a0)*z3^2*z4, + (b1)*z1*z2^2 + (b2)*z2^2*z4 + (b5)*z1*z2*z5 + + (b4)*z2*z4*z5 + (b3)*z1*z5^2 + (b0)*z4*z5^2 sage: CI.cohomology_class() [2*z3*z4 + 4*z3*z5 + 2*z4*z5] """ @@ -1630,10 +1630,10 @@ def nef_partition(self): sage: CI Closed subscheme of 3-d CPR-Fano toric variety covered by 8 affine patches defined by: - a2*z0^2*z1 + a5*z0*z1*z3 + a1*z1*z3^2 - + a3*z0^2*z4 + a4*z0*z3*z4 + a0*z3^2*z4, - b1*z1*z2^2 + b2*z2^2*z4 + b5*z1*z2*z5 - + b4*z2*z4*z5 + b3*z1*z5^2 + b0*z4*z5^2 + (a2)*z0^2*z1 + (a5)*z0*z1*z3 + (a1)*z1*z3^2 + + (a3)*z0^2*z4 + (a4)*z0*z3*z4 + (a0)*z3^2*z4, + (b1)*z1*z2^2 + (b2)*z2^2*z4 + (b5)*z1*z2*z5 + + (b4)*z2*z4*z5 + (b3)*z1*z5^2 + (b0)*z4*z5^2 sage: CI.nef_partition() Nef-partition {0, 1, 3} U {2, 4, 5} sage: CI.nef_partition() is np From 58f528c55f996ccebf47dca3c8d7935476cb56d1 Mon Sep 17 00:00:00 2001 From: Miguel Marco Date: Sun, 10 Oct 2021 20:57:29 +0200 Subject: [PATCH 024/126] Clean unnecessary parenthesis in single variables. --- src/sage/arith/misc.py | 2 +- src/sage/crypto/mq/rijndael_gf.py | 22 ++-- .../arithmetic_dynamics/generic_ds.py | 2 +- .../arithmetic_dynamics/projective_ds.py | 4 +- .../groups/matrix_gps/finitely_generated.py | 2 +- src/sage/libs/singular/polynomial.pyx | 3 + src/sage/libs/singular/singular.pyx | 18 +-- src/sage/quadratic_forms/quadratic_form.py | 2 +- ...otics_multivariate_generating_functions.py | 2 +- src/sage/rings/finite_rings/residue_field.pyx | 2 +- src/sage/rings/fraction_field.py | 2 +- .../rings/multi_power_series_ring_element.py | 2 +- src/sage/rings/polynomial/flatten.py | 2 +- .../multi_polynomial_libsingular.pyx | 13 +- src/sage/rings/polynomial/plural.pyx | 2 +- .../rings/polynomial/polynomial_element.pyx | 2 +- src/sage/schemes/affine/affine_morphism.py | 6 +- src/sage/schemes/curves/affine_curve.py | 2 +- src/sage/schemes/curves/closed_point.py | 14 +- src/sage/schemes/curves/projective_curve.py | 4 +- .../elliptic_curves/ell_curve_isogeny.py | 4 +- src/sage/schemes/generic/algebraic_scheme.py | 2 +- src/sage/schemes/plane_conics/con_field.py | 10 +- .../schemes/plane_conics/con_finite_field.py | 2 +- .../schemes/projective/projective_morphism.py | 10 +- src/sage/schemes/toric/fano_variety.py | 120 +++++++++--------- src/sage/structure/coerce.pyx | 2 +- .../mpoly_doctest.py | 2 +- 28 files changed, 129 insertions(+), 131 deletions(-) diff --git a/src/sage/arith/misc.py b/src/sage/arith/misc.py index 039e786aff7..ed918732ba7 100644 --- a/src/sage/arith/misc.py +++ b/src/sage/arith/misc.py @@ -1933,7 +1933,7 @@ def xgcd(a, b): sage: xgcd(y^2, a*y+b) (1, a^2/b^2, ((-a)/b^2)*y + 1/b) sage: xgcd((b+g)*y^2, (a+g)*y+b) - (1, (a^2 + (2*g)*a + 3)/(b^3 + (g)*b^2), ((-a + (-g))/b^2)*y + 1/b) + (1, (a^2 + (2*g)*a + 3)/(b^3 + g*b^2), ((-a + (-g))/b^2)*y + 1/b) Here is an example of a xgcd for two polynomials over the integers, where the linear combination is not the gcd but the gcd multiplied by the resultant:: diff --git a/src/sage/crypto/mq/rijndael_gf.py b/src/sage/crypto/mq/rijndael_gf.py index eb6119bafe0..619026bfe96 100644 --- a/src/sage/crypto/mq/rijndael_gf.py +++ b/src/sage/crypto/mq/rijndael_gf.py @@ -119,7 +119,7 @@ sage: mc_pc = rgf.mix_columns_poly_constr() sage: mc_pc(1, 2) - a02 + (x)*a12 + (x + 1)*a22 + a32 + a02 + x*a12 + (x + 1)*a22 + a32 sage: mc_pc(2, 3, algorithm='decrypt') (x^3 + x^2 + 1)*a03 + (x^3 + 1)*a13 + (x^3 + x^2 + x)*a23 + (x^3 + x + 1)*a33 @@ -274,7 +274,7 @@ sage: rcpc A polynomial constructor of a round component of Rijndael-GF block cipher with block length 4, key length 6, and 12 rounds. sage: rcpc(2, 1) - a01 + a12 + (x)*a23 + (x + 1)*a30 + a01 + a12 + x*a23 + (x + 1)*a30 sage: state = rgf._hex_to_GF('afb73eeb1cd1b85162280f27fb20d585') sage: result = rgf.apply_poly(state, rcpc) @@ -303,7 +303,7 @@ sage: poly = rgf.mix_columns_poly_constr()(0, 3) sage: poly - (x)*a03 + (x + 1)*a13 + a23 + a33 + x*a03 + (x + 1)*a13 + a23 + a33 sage: rgf.compose(rgf.sub_bytes_poly_constr(), poly) (x^3 + x)*a03^254 + (x^3 + x^2 + x + 1)*a13^254 + @@ -325,7 +325,7 @@ (x^2 + x + 1)*a13^239 + (x^7 + x^6 + x^5 + x^4 + x^2)*a23^239 + (x^7 + x^6 + x^5 + x^4 + x^2)*a33^239 + - (x)*a03^223 + + x*a03^223 + (x + 1)*a13^223 + a23^223 + a33^223 + @@ -462,7 +462,7 @@ def __init__(self, Nb, Nk, state_chr='a', key_chr='k'): sage: rgf = RijndaelGF(4, 6, state_chr='myChr') sage: rgf.mix_columns_poly_constr()(3, 2) - (x + 1)*myChr02 + myChr12 + myChr22 + (x)*myChr32 + (x + 1)*myChr02 + myChr12 + myChr22 + x*myChr32 We can also alter the name of variables in polynomials representing elements from round keys by changing ``key_chr``. :: @@ -1483,10 +1483,10 @@ def compose(self, f, g, algorithm='encrypt', f_attr=None, g_attr=None): sage: from sage.crypto.mq.rijndael_gf import RijndaelGF sage: rgf = RijndaelGF(4, 4) sage: mcp = rgf.mix_columns_poly_constr()(1, 3); mcp - a03 + (x)*a13 + (x + 1)*a23 + a33 + a03 + x*a13 + (x + 1)*a23 + a33 sage: result = rgf.compose(rgf.shift_rows_poly_constr(), mcp) sage: result - a03 + (x)*a10 + (x + 1)*a21 + a32 + a03 + x*a10 + (x + 1)*a21 + a32 We can test the correctness of this:: @@ -1503,7 +1503,7 @@ def compose(self, f, g, algorithm='encrypt', f_attr=None, g_attr=None): sage: fn = rgf.compose(rgf.shift_rows_poly_constr(), ....: rgf.mix_columns_poly_constr()) sage: fn(1, 3) - a03 + (x)*a10 + (x + 1)*a21 + a32 + a03 + x*a10 + (x + 1)*a21 + a32 If we use ``compose`` to make a new ``Round_Component_Poly_Constr`` object, we can use that object as input to ``apply_poly`` and @@ -1958,7 +1958,7 @@ def mix_columns_poly_constr(self): sage: mc_pc A polynomial constructor for the function 'Mix Columns' of Rijndael-GF block cipher with block length 4, key length 4, and 10 rounds. sage: mc_pc(1, 2) - a02 + (x)*a12 + (x + 1)*a22 + a32 + a02 + x*a12 + (x + 1)*a22 + a32 sage: mc_pc(1, 0, algorithm='decrypt') (x^3 + 1)*a00 + (x^3 + x^2 + x)*a10 + (x^3 + x + 1)*a20 + (x^3 + x^2 + 1)*a30 @@ -1994,7 +1994,7 @@ def _mix_columns_pc(self, row, col, algorithm='encrypt'): sage: from sage.crypto.mq.rijndael_gf import RijndaelGF sage: rgf = RijndaelGF(4, 4) sage: rgf._mix_columns_pc(3, 1) - (x + 1)*a01 + a11 + a21 + (x)*a31 + (x + 1)*a01 + a11 + a21 + x*a31 We can use this to calculate individual entries of a state matrix after the decryption version of MixColumns has been applied to it as such:: @@ -2197,7 +2197,7 @@ def __init__(self, polynomial_constr, rgf, round_component_name=None): sage: rcpc = RijndaelGF.Round_Component_Poly_Constr( ....: rgf._mix_columns_pc, rgf, "Mix Columns") sage: poly = rcpc(1, 2); poly - a02 + (x)*a12 + (x + 1)*a22 + a32 + a02 + x*a12 + (x + 1)*a22 + a32 sage: state = rgf._hex_to_GF('d1876c0f79c4300ab45594add66ff41f') sage: result = rgf.mix_columns(state) sage: result[1,2] == poly(state.list()) diff --git a/src/sage/dynamics/arithmetic_dynamics/generic_ds.py b/src/sage/dynamics/arithmetic_dynamics/generic_ds.py index 0ad4d747f94..6a80a88ed0b 100644 --- a/src/sage/dynamics/arithmetic_dynamics/generic_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/generic_ds.py @@ -142,7 +142,7 @@ class DynamicalSystem(SchemeMorphism_polynomial, sage: DynamicalSystem([GF(5)(3)*x^2, K(t)*y^2]) Dynamical System of Projective Space of dimension 1 over Finite Field in t of size 5^2 Defn: Defined on coordinates by sending (x : y) to - (-2*x^2 : (t)*y^2) + (-2*x^2 : t*y^2) """ @staticmethod diff --git a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py index 164c4c35f47..5fba51056f0 100644 --- a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py @@ -499,7 +499,7 @@ def _number_field_from_algebraics(self): sage: f._number_field_from_algebraics() Dynamical System of Projective Space of dimension 1 over Number Field in a with defining polynomial y^2 - 2 with a = 1.414213562373095? Defn: Defined on coordinates by sending (x : y) to - (x^2 + (a)*y^2 : y^2) + (x^2 + a*y^2 : y^2) """ return self.as_scheme_morphism()._number_field_from_algebraics().as_dynamical_system() @@ -5251,7 +5251,7 @@ def reduced_form(self, **kwds): ( Dynamical System of Projective Space of dimension 1 over Number Field in w with defining polynomial x^2 - 2 with w = 1.414213562373095? Defn: Defined on coordinates by sending (x : y) to - (x^3 : (w)*y^3) , + (x^3 : w*y^3) , [ 1 -12] [ 0 1] diff --git a/src/sage/groups/matrix_gps/finitely_generated.py b/src/sage/groups/matrix_gps/finitely_generated.py index a69e5bfd325..45f86f6fe9b 100644 --- a/src/sage/groups/matrix_gps/finitely_generated.py +++ b/src/sage/groups/matrix_gps/finitely_generated.py @@ -1152,7 +1152,7 @@ def reynolds_operator(self, poly, chi=None): sage: R. = K[] sage: f = -K.gen()*x sage: G.reynolds_operator(f) - (t)*x + (t)*y + t*x + t*y """ if poly.parent().ngens() != self.degree(): raise TypeError("number of variables in polynomial must match size of matrices") diff --git a/src/sage/libs/singular/polynomial.pyx b/src/sage/libs/singular/polynomial.pyx index 7687de8f2d8..eed1967ca9e 100644 --- a/src/sage/libs/singular/polynomial.pyx +++ b/src/sage/libs/singular/polynomial.pyx @@ -23,6 +23,8 @@ cdef extern from *: # hack to get at cython macro import re plusminus_pattern = re.compile("([^\(^])([\+\-])") +parenthvar_pattern = re.compile(r"\(([a-zA-Z][a-zA-Z0-9]*)\)") + from sage.cpython.string cimport bytes_to_str, str_to_bytes @@ -441,6 +443,7 @@ cdef object singular_polynomial_str(poly *p, ring *r): s = bytes_to_str(p_String(p, r, r)) s = plusminus_pattern.sub("\\1 \\2 ", s) + s = parenthvar_pattern.sub("\\1", s) return s diff --git a/src/sage/libs/singular/singular.pyx b/src/sage/libs/singular/singular.pyx index 48073b73353..b576c7e9719 100644 --- a/src/sage/libs/singular/singular.pyx +++ b/src/sage/libs/singular/singular.pyx @@ -264,15 +264,15 @@ cdef object si2sa_transext(number *n, ring *_ring, object base): Defining a, b sage: R. = F[] sage: a*x - (a)*x + a*x sage: I = R.ideal([a*x]) sage: I - Ideal ((a)*x) of Multivariate Polynomial Ring in x, y over Fraction Field of Multivariate Polynomial Ring in a, b over Rational Field + Ideal (a*x) of Multivariate Polynomial Ring in x, y over Fraction Field of Multivariate Polynomial Ring in a, b over Rational Field sage: I.groebner_basis() [x] sage: I = R.ideal([a*x+b*y^2, (b+a)/(b-a)*x^3-3*y*x]) sage: I.groebner_basis() - [x^3 + (3*a - 3*b)/(a + b)*x*y, y^2 + (a)/(b)*x] + [x^3 + (3*a - 3*b)/(a + b)*x*y, y^2 + a/b*x] sage: R.term_order() Degree reverse lexicographic term order @@ -570,15 +570,15 @@ cdef number *sa2si_transext(object elem, ring *_ring): Defining a, b sage: R. = F[] sage: a*x - (a)*x + a*x sage: I = R.ideal([a*x]) sage: I - Ideal ((a)*x) of Multivariate Polynomial Ring in x, y over Fraction Field of Multivariate Polynomial Ring in a, b over Rational Field + Ideal (a*x) of Multivariate Polynomial Ring in x, y over Fraction Field of Multivariate Polynomial Ring in a, b over Rational Field sage: I.groebner_basis() [x] sage: I = R.ideal([a*x+b*y^2, (b+a)/(b-a)*x^3-3*y*x]) sage: I.groebner_basis() - [x^3 + (3*a - 3*b)/(a + b)*x*y, y^2 + (a)/(b)*x] + [x^3 + (3*a - 3*b)/(a + b)*x*y, y^2 + a/b*x] sage: R.term_order() Degree reverse lexicographic term order @@ -589,12 +589,12 @@ cdef number *sa2si_transext(object elem, ring *_ring): sage: F.inject_variables() Defining a sage: a*x - (a)*x + a*x sage: I = R.ideal([a*x+5*y^2, (1+a)/(1-a)*x^3-3*y*x]) sage: I - Ideal (5*y^2 + (a)*x, (-a - 1)/(a - 1)*x^3 - 3*x*y) of Multivariate Polynomial Ring in x, y over Fraction Field of Univariate Polynomial Ring in a over Rational Field + Ideal (5*y^2 + a*x, (-a - 1)/(a - 1)*x^3 - 3*x*y) of Multivariate Polynomial Ring in x, y over Fraction Field of Univariate Polynomial Ring in a over Rational Field sage: I.groebner_basis() - [x^3 + (3*a - 3)/(a + 1)*x*y, y^2 + (a)/5*x] + [x^3 + (3*a - 3)/(a + 1)*x*y, y^2 + a/5*x] :: diff --git a/src/sage/quadratic_forms/quadratic_form.py b/src/sage/quadratic_forms/quadratic_form.py index e53203c66d9..02df1fe76ba 100644 --- a/src/sage/quadratic_forms/quadratic_form.py +++ b/src/sage/quadratic_forms/quadratic_form.py @@ -1288,7 +1288,7 @@ def polynomial(self,names='x'): 2*a*y0^2 + 3*a*y0*y1 + (-a + 1)*y1^2 + (2*a + 4)*y2^2 sage: Q = QuadraticForm(F,4,[a, 3*a, 0, 1 - a, a - 3, 0, 2*a + 4, 4 + a, 0, 1]) sage: Q.polynomial(names='z') - (a)*z0^2 + (3*a)*z0*z1 + (a - 3)*z1^2 + (a + 4)*z2^2 + (-a + 1)*z0*z3 + (2*a + 4)*z1*z3 + z3^2 + a*z0^2 + (3*a)*z0*z1 + (a - 3)*z1^2 + (a + 4)*z2^2 + (-a + 1)*z0*z3 + (2*a + 4)*z1*z3 + z3^2 sage: B. = QuaternionAlgebra(F,-1,-1) sage: Q = QuadraticForm(B, 3, [2*a, 3*a, i, 1 - a, 0, 2*a + 4]) sage: Q.polynomial() diff --git a/src/sage/rings/asymptotic/asymptotics_multivariate_generating_functions.py b/src/sage/rings/asymptotic/asymptotics_multivariate_generating_functions.py index b37e597e214..3f43a3197aa 100644 --- a/src/sage/rings/asymptotic/asymptotics_multivariate_generating_functions.py +++ b/src/sage/rings/asymptotic/asymptotics_multivariate_generating_functions.py @@ -2725,7 +2725,7 @@ def smooth_critical_ideal(self, alpha): sage: F = FFPD(G, Hfac) sage: alpha = var('a1, a2') sage: F.smooth_critical_ideal(alpha) - Ideal (y^2 + (2*a1)/(a2)*y - 1, x + (-a2)/(a1)*y + (-a1 + a2)/(a1)) of + Ideal (y^2 + (2*a1)/a2*y - 1, x + (-a2)/a1*y + (-a1 + a2)/a1) of Multivariate Polynomial Ring in x, y over Fraction Field of Multivariate Polynomial Ring in a1, a2 over Rational Field diff --git a/src/sage/rings/finite_rings/residue_field.pyx b/src/sage/rings/finite_rings/residue_field.pyx index 007a68e4c0f..09de1cb3c0f 100644 --- a/src/sage/rings/finite_rings/residue_field.pyx +++ b/src/sage/rings/finite_rings/residue_field.pyx @@ -109,7 +109,7 @@ First over a small non-prime field:: sage: R. = PolynomialRing(Rf) sage: ubar = Rf(u) sage: I = ideal([ubar*X + Y]); I - Ideal ((ubar)*X + Y) of Multivariate Polynomial Ring in X, Y over Residue field in ubar of Fractional ideal (47, 517/55860*u^5 + 235/3724*u^4 + 9829/13965*u^3 + 54106/13965*u^2 + 64517/27930*u + 755696/13965) + Ideal (ubar*X + Y) of Multivariate Polynomial Ring in X, Y over Residue field in ubar of Fractional ideal (47, 517/55860*u^5 + 235/3724*u^4 + 9829/13965*u^3 + 54106/13965*u^2 + 64517/27930*u + 755696/13965) sage: I.groebner_basis() [X + (-19*ubar^2 - 5*ubar - 17)*Y] diff --git a/src/sage/rings/fraction_field.py b/src/sage/rings/fraction_field.py index 27e6277ad1b..acf1ffa8f60 100644 --- a/src/sage/rings/fraction_field.py +++ b/src/sage/rings/fraction_field.py @@ -586,7 +586,7 @@ def _element_constructor_(self, x, y=None, coerce=True): sage: B. = PolynomialRing(A,'d,e') sage: R. = PolynomialRing(B,'x') sage: (a*d*x^2+a+e+1).resultant(-4*c^2*x+1) - (a)*d + (16*c^4)*e + (16*a*c^4 + 16*c^4) + a*d + (16*c^4)*e + (16*a*c^4 + 16*c^4) Check that :trac:`24539` is fixed:: diff --git a/src/sage/rings/multi_power_series_ring_element.py b/src/sage/rings/multi_power_series_ring_element.py index 782a6f077a3..4d85381b9df 100644 --- a/src/sage/rings/multi_power_series_ring_element.py +++ b/src/sage/rings/multi_power_series_ring_element.py @@ -462,7 +462,7 @@ def __call__(self, *x, **kwds): sage: cc = K.hom([-i]) sage: R. = PowerSeriesRing(K) sage: f = s^2 + i*s*t + (3+4*i)*s^3 + R.O(4); f - s^2 + (i)*s*t + (4*i + 3)*s^3 + O(s, t)^4 + s^2 + i*s*t + (4*i + 3)*s^3 + O(s, t)^4 sage: f(t, s, base_map=cc) (-i)*s*t + t^2 + (-4*i + 3)*t^3 + O(s, t)^4 """ diff --git a/src/sage/rings/polynomial/flatten.py b/src/sage/rings/polynomial/flatten.py index b7dadef0b51..4ffe29f9ebe 100644 --- a/src/sage/rings/polynomial/flatten.py +++ b/src/sage/rings/polynomial/flatten.py @@ -113,7 +113,7 @@ def __init__(self, domain): sage: from sage.rings.polynomial.flatten import FlatteningMorphism sage: f = FlatteningMorphism(R) sage: f(R('v*a*x^2 + b^2 + 1/v*y')) - (v)*x^2*a + b^2 + (1/2*v^2)*y + v*x^2*a + b^2 + (1/2*v^2)*y :: diff --git a/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx b/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx index 655987381fb..591e72c88c7 100644 --- a/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx +++ b/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx @@ -251,7 +251,6 @@ from sage.interfaces.macaulay2 import macaulay2 as macaulay2_default, is_Macaula from sage.misc.all import prod as mul from sage.misc.sage_eval import sage_eval -import re cimport cypari2.gen from . import polynomial_element @@ -1967,7 +1966,7 @@ cdef class MPolynomial_libsingular(MPolynomial): sage: F. = GF(7^2) sage: R. = F[] sage: p = a*x^2 + y + a^3; p - (a)*x^2 + y + (-2*a - 3) + a*x^2 + y + (-2*a - 3) sage: q = copy(p) sage: p == q True @@ -2483,10 +2482,6 @@ cdef class MPolynomial_libsingular(MPolynomial): """ cdef ring *_ring = self._parent_ring s = singular_polynomial_str(self._poly, _ring) - regexp = re.compile(r'\([a-zA-Z][a-zA-Z0-9]*\)') - res = regexp.fullmatch(s) - if res: - return s[1:-1] return s cpdef _repr_short_(self): @@ -4233,10 +4228,10 @@ cdef class MPolynomial_libsingular(MPolynomial): sage: K. = NumberField(p^3-2) sage: KXY. = K[] sage: factor(x^3 - 2*y^3) - (x + (-s)*y) * (x^2 + (s)*x*y + (s^2)*y^2) + (x + (-s)*y) * (x^2 + s*x*y + (s^2)*y^2) sage: k = (x^3-2*y^3)^5*(x+s*y)^2*(2/3 + s^2) sage: k.factor() - ((s^2 + 2/3)) * (x + (s)*y)^2 * (x + (-s)*y)^5 * (x^2 + (s)*x*y + (s^2)*y^2)^5 + ((s^2 + 2/3)) * (x + s*y)^2 * (x + (-s)*y)^5 * (x^2 + s*x*y + (s^2)*y^2)^5 This shows that ticket :trac:`2780` is fixed, i.e. that the unit part of the factorization is set correctly:: @@ -4327,7 +4322,7 @@ cdef class MPolynomial_libsingular(MPolynomial): sage: q=y^11 + (a)*y^10 + (a + 1)*x*y^3 sage: f = p*q sage: f.factor() - x * y^3 * (y^8 + (a)*y^7 + (a + 1)*x) * (x^7*y^3 + x*y^9 + (a)*x^8 + (a)*y^4) + x * y^3 * (y^8 + a*y^7 + (a + 1)*x) * (x^7*y^3 + x*y^9 + a*x^8 + a*y^4) We test several examples which were known to return wrong results in the past (see :trac:`10902`):: diff --git a/src/sage/rings/polynomial/plural.pyx b/src/sage/rings/polynomial/plural.pyx index 80c905c0cef..972d22049da 100644 --- a/src/sage/rings/polynomial/plural.pyx +++ b/src/sage/rings/polynomial/plural.pyx @@ -2272,7 +2272,7 @@ cdef class NCPolynomial_plural(RingElement): sage: phi(x*y - x^2*z) a^2*b^3 - a^2*b^2*c sage: phi(x*y - z2*x^2*z) - (z2)*a^2*b^3 - a^2*b^2*c + z2*a^2*b^3 - a^2*b^2*c sage: phi = R.hom([a*b, b, a*b*c], base_map=GF(9).frobenius_endomorphism(), check=False) sage: phi(x*y - x^2*z) a^2*b^3 - a^2*b^2*c diff --git a/src/sage/rings/polynomial/polynomial_element.pyx b/src/sage/rings/polynomial/polynomial_element.pyx index 6d1d6c7f626..4ce01469a99 100644 --- a/src/sage/rings/polynomial/polynomial_element.pyx +++ b/src/sage/rings/polynomial/polynomial_element.pyx @@ -6508,7 +6508,7 @@ cdef class Polynomial(CommutativeAlgebraElement): sage: p = ((1/b^2*d^2+1/a)*x*y^2+a*b/c*y+e+x^2) sage: q = -4*c^2*y^3+1 sage: p.resultant(q) - (16*c^4)*x^6 + (48*c^4)*e*x^4 + (1/(b^6)*d^6 + 3/(a*b^4)*d^4 + (-12*a^3*b*c + 3)/(a^2*b^2)*d^2 + (-12*a^3*b*c + 1)/(a^3))*x^3 + (48*c^4)*e^2*x^2 + ((-12*a*c)/(b)*d^2*e + (-12*b*c)*e)*x + (16*c^4)*e^3 + (4*a^3*b^3)/(c) + (16*c^4)*x^6 + (48*c^4)*e*x^4 + (1/(b^6)*d^6 + 3/(a*b^4)*d^4 + (-12*a^3*b*c + 3)/(a^2*b^2)*d^2 + (-12*a^3*b*c + 1)/(a^3))*x^3 + (48*c^4)*e^2*x^2 + ((-12*a*c)/b*d^2*e + (-12*b*c)*e)*x + (16*c^4)*e^3 + (4*a^3*b^3)/c Test for :trac:`10978`:: diff --git a/src/sage/schemes/affine/affine_morphism.py b/src/sage/schemes/affine/affine_morphism.py index 63a4f348af9..fa9e7ed51d3 100644 --- a/src/sage/schemes/affine/affine_morphism.py +++ b/src/sage/schemes/affine/affine_morphism.py @@ -950,7 +950,7 @@ def reduce_base_field(self): From: Affine Space of dimension 2 over Finite Field in t of size 5^4 To: Affine Space of dimension 1 over Finite Field in t of size 5^4 Defn: Defined on coordinates by sending (a, b) to - (a^2 + (t)*b) + (a^2 + t*b) :: @@ -961,7 +961,7 @@ def reduce_base_field(self): sage: g = f.reduce_base_field();g Scheme endomorphism of Affine Space of dimension 1 over Cyclotomic Field of order 4 and degree 2 Defn: Defined on coordinates by sending (x) to - (x^2 + (v)) + (x^2 + v) sage: g.base_ring() is K True @@ -1005,7 +1005,7 @@ def reduce_base_field(self): To: Affine Space of dimension 2 over Number Field in a with defining polynomial x^3 - x + 1 with a = -1.324717957244746? Defn: Defined on coordinates by sending (x) to - (x^2 + (a)*x + 3, 5*x) + (x^2 + a*x + 3, 5*x) :: diff --git a/src/sage/schemes/curves/affine_curve.py b/src/sage/schemes/curves/affine_curve.py index 9fd99a3b3fc..52fa2cb4419 100644 --- a/src/sage/schemes/curves/affine_curve.py +++ b/src/sage/schemes/curves/affine_curve.py @@ -2404,7 +2404,7 @@ def places_on(self, point): Point (x + (a + 1), y + (-a + 1)), Point (x - 1, y + (a + 1)), Point (x - 1, y + (-a - 1)), - Point (x + (-a - 1), y + (a)), + Point (x + (-a - 1), y + a), Point (x + (-a - 1), y + (-a)), Point (x + 1, y + 1), Point (x + 1, y - 1)] diff --git a/src/sage/schemes/curves/closed_point.py b/src/sage/schemes/curves/closed_point.py index 718b8a20c76..d35ad60b35e 100644 --- a/src/sage/schemes/curves/closed_point.py +++ b/src/sage/schemes/curves/closed_point.py @@ -105,11 +105,11 @@ class IntegralCurveClosedPoint(CurveClosedPoint): sage: C.closed_points() [Point (x, y), Point (x, y + 1), - Point (x + (a), y + (a)), - Point (x + (a), y + (a + 1)), - Point (x + (a + 1), y + (a)), + Point (x + a, y + a), + Point (x + a, y + (a + 1)), + Point (x + (a + 1), y + a), Point (x + (a + 1), y + (a + 1)), - Point (x + 1, y + (a)), + Point (x + 1, y + a), Point (x + 1, y + (a + 1))] """ def __init__(self, curve, prime_ideal, degree): @@ -269,7 +269,7 @@ def rational_point(self): Point (x + (z2 + 1), y + (-z2 + 1)), Point (x - 1, y + (z2 + 1)), Point (x - 1, y + (-z2 - 1)), - Point (x + (-z2 - 1), y + (z2)), + Point (x + (-z2 - 1), y + z2), Point (x + (-z2 - 1), y + (-z2)), Point (x + 1, y + 1), Point (x + 1, y - 1)] @@ -356,8 +356,8 @@ def rational_point(self): [Point (x, z), Point (x, y), Point (y, z), - Point (x + (a)*z, y + (a + 1)*z), - Point (x + (a + 1)*z, y + (a)*z)] + Point (x + a*z, y + (a + 1)*z), + Point (x + (a + 1)*z, y + a*z)] sage: [p.rational_point() for p in _] [(0 : 1 : 0), (0 : 0 : 1), (1 : 0 : 0), (a : a + 1 : 1), (a + 1 : a : 1)] sage: set(_) == set(C.rational_points()) diff --git a/src/sage/schemes/curves/projective_curve.py b/src/sage/schemes/curves/projective_curve.py index 0e6ba6a1e4b..8433f27ddbf 100644 --- a/src/sage/schemes/curves/projective_curve.py +++ b/src/sage/schemes/curves/projective_curve.py @@ -2628,11 +2628,11 @@ def closed_points(self, degree=1): [Point (x0, x1), Point (x0 + (-z2 - 1)*x2, x1), Point (x0 + (z2 + 1)*x2, x1), - Point (x0 + (z2)*x2, x1 + (z2 - 1)*x2), + Point (x0 + z2*x2, x1 + (z2 - 1)*x2), Point (x0 + (-z2)*x2, x1 + (-z2 + 1)*x2), Point (x0 + (-z2 - 1)*x2, x1 + (-z2 - 1)*x2), Point (x0 + (z2 + 1)*x2, x1 + (z2 + 1)*x2), - Point (x0 + (z2 - 1)*x2, x1 + (z2)*x2), + Point (x0 + (z2 - 1)*x2, x1 + z2*x2), Point (x0 + (-z2 + 1)*x2, x1 + (-z2)*x2), Point (x0 + x2, x1 - x2), Point (x0 - x2, x1 + x2)] diff --git a/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py b/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py index 4cb6514053a..d9c494a249b 100644 --- a/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py +++ b/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py @@ -2418,7 +2418,7 @@ def __init_odd_kernel_polynomial(self, E, psi): sage: R. = F[] sage: f = x + alpha^2 + 1 sage: phi._EllipticCurveIsogeny__init_odd_kernel_polynomial(E, f) - (x^3 + (alpha^2 + 1)*x + alpha^3 + alpha^2 + alpha, x^3*y + (alpha^2 + 1)*x^2*y + (alpha^2 + alpha + 1)*x^2 + (alpha^2 + 1)*x*y + (alpha^2 + alpha)*x + (alpha)*y + (alpha), alpha^2 + alpha + 1, alpha^3 + alpha^2 + alpha, 1, 3) + (x^3 + (alpha^2 + 1)*x + alpha^3 + alpha^2 + alpha, x^3*y + (alpha^2 + 1)*x^2*y + (alpha^2 + alpha + 1)*x^2 + (alpha^2 + 1)*x*y + (alpha^2 + alpha)*x + alpha*y + alpha, alpha^2 + alpha + 1, alpha^3 + alpha^2 + alpha, 1, 3) sage: E = EllipticCurve(j=-262537412640768000) sage: f = (E.isogenies_prime_degree()[0]).kernel_polynomial() @@ -2567,7 +2567,7 @@ def __compute_omega_general(self, E, psi, psi_pr, phi, phi_pr): sage: fi = phi._EllipticCurveIsogeny__phi sage: fi_pr = fi.derivative() sage: phi._EllipticCurveIsogeny__compute_omega_general(E, psi, psi_pr, fi, fi_pr) - x^3*y + (alpha^2 + 1)*x^2*y + (alpha^2 + alpha + 1)*x^2 + (alpha^2 + 1)*x*y + (alpha^2 + alpha)*x + (alpha)*y + (alpha) + x^3*y + (alpha^2 + 1)*x^2*y + (alpha^2 + alpha + 1)*x^2 + (alpha^2 + 1)*x*y + (alpha^2 + alpha)*x + alpha*y + alpha A bug fixed in :trac:`7907`:: diff --git a/src/sage/schemes/generic/algebraic_scheme.py b/src/sage/schemes/generic/algebraic_scheme.py index 164826d9b5a..f0d73d0dcd3 100644 --- a/src/sage/schemes/generic/algebraic_scheme.py +++ b/src/sage/schemes/generic/algebraic_scheme.py @@ -1982,7 +1982,7 @@ def weil_restriction(self): Closed subscheme of Affine Space of dimension 4 over Number Field in w with defining polynomial x^5 - 2 defined by: (-w)*z0^3 + (3*w)*z0*z1^2 + z2^2 - z3^2, - (-3*w)*z0^2*z1 + (w)*z1^3 + 2*z2*z3 - 1 + (-3*w)*z0^2*z1 + w*z1^3 + 2*z2*z3 - 1 sage: X.weil_restriction().ambient_space() is A.weil_restriction() True diff --git a/src/sage/schemes/plane_conics/con_field.py b/src/sage/schemes/plane_conics/con_field.py index 929ff0dccb6..5ecce3b3168 100644 --- a/src/sage/schemes/plane_conics/con_field.py +++ b/src/sage/schemes/plane_conics/con_field.py @@ -683,10 +683,10 @@ def hom(self, x, Y=None): sage: T = Matrix([[t,0,1],[0,1,0],[0,0,1]]) sage: C.hom(T, D) Scheme morphism: - From: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Rational Field defined by x^2 + (t)*y^2 + 1/(t)*z^2 - To: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Rational Field defined by 1/(t^2)*x^2 + (t)*y^2 - 2/(t^2)*x*z + (t + 1)/(t^2)*z^2 + From: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Rational Field defined by x^2 + t*y^2 + 1/t*z^2 + To: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Rational Field defined by 1/(t^2)*x^2 + t*y^2 - 2/(t^2)*x*z + (t + 1)/(t^2)*z^2 Defn: Defined on coordinates by sending (x : y : z) to - ((t)*x + z : y : z) + (t*x + z : y : z) """ if is_Matrix(x): @@ -760,7 +760,7 @@ def _magma_init_(self, magma): sage: F. = GF(25) sage: C = Conic([3,0,1,4,a,2]) sage: C - Projective Conic Curve over Finite Field in a of size 5^2 defined by -2*x^2 - y^2 + x*z + (a)*y*z + 2*z^2 + Projective Conic Curve over Finite Field in a of size 5^2 defined by -2*x^2 - y^2 + x*z + a*y*z + 2*z^2 sage: magma(C) # optional - magma Conic over GF(5^2) defined by 3*X^2 + 4*Y^2 + X*Z + a*Y*Z + 2*Z^2 @@ -1077,7 +1077,7 @@ def rational_point(self, algorithm = 'default', read_cache = True): sage: F. = FiniteField(7^20) sage: C = Conic([1, a, -5]); C - Projective Conic Curve over Finite Field in a of size 7^20 defined by x^2 + (a)*y^2 + 2*z^2 + Projective Conic Curve over Finite Field in a of size 7^20 defined by x^2 + a*y^2 + 2*z^2 sage: C.rational_point() # output is random (4*a^19 + 5*a^18 + 4*a^17 + a^16 + 6*a^15 + 3*a^13 + 6*a^11 + a^9 + 3*a^8 + 2*a^7 + 4*a^6 + 3*a^5 + 3*a^4 + a^3 + a + 6 : 5*a^18 + a^17 + a^16 + 6*a^15 + 4*a^14 + a^13 + 5*a^12 + 5*a^10 + 2*a^9 + 6*a^8 + 6*a^7 + 6*a^6 + 2*a^4 + 3 : 1) diff --git a/src/sage/schemes/plane_conics/con_finite_field.py b/src/sage/schemes/plane_conics/con_finite_field.py index 82f71c815d1..86a7e168259 100644 --- a/src/sage/schemes/plane_conics/con_finite_field.py +++ b/src/sage/schemes/plane_conics/con_finite_field.py @@ -108,7 +108,7 @@ def has_rational_point(self, point=False, read_cache=True, sage: F. = FiniteField(7^20) sage: C = Conic([1, a, -5]); C - Projective Conic Curve over Finite Field in a of size 7^20 defined by x^2 + (a)*y^2 + 2*z^2 + Projective Conic Curve over Finite Field in a of size 7^20 defined by x^2 + a*y^2 + 2*z^2 sage: C.has_rational_point(point = True) # output is random (True, (a^18 + 2*a^17 + 4*a^16 + 6*a^13 + a^12 + 6*a^11 + 3*a^10 + 4*a^9 + 2*a^8 + 4*a^7 + a^6 + 4*a^4 + 6*a^2 + 3*a + 6 : 5*a^19 + 5*a^18 + 5*a^17 + a^16 + 2*a^15 + 3*a^14 + 4*a^13 + 5*a^12 + a^11 + 3*a^10 + 2*a^8 + 3*a^7 + 4*a^6 + 4*a^5 + 6*a^3 + 5*a^2 + 2*a + 4 : 1)) diff --git a/src/sage/schemes/projective/projective_morphism.py b/src/sage/schemes/projective/projective_morphism.py index 056eb076b28..a4fd0ec575c 100644 --- a/src/sage/schemes/projective/projective_morphism.py +++ b/src/sage/schemes/projective/projective_morphism.py @@ -601,7 +601,7 @@ def _matrix_times_polymap_(self, mat, h): sage: matrix([[i,0], [0,i]]) * f Scheme endomorphism of Projective Space of dimension 1 over Number Field in i with defining polynomial x^2 + 1 Defn: Defined on coordinates by sending (x : y) to - ((1/3*i)*x^2 + (1/2*i)*y^2 : (i)*y^2) + ((1/3*i)*x^2 + (1/2*i)*y^2 : i*y^2) """ from sage.modules.free_module_element import vector from sage.dynamics.arithmetic_dynamics.generic_ds import DynamicalSystem @@ -1114,7 +1114,7 @@ def dehomogenize(self, n): Scheme endomorphism of Affine Space of dimension 2 over Fraction Field of Univariate Polynomial Ring in t over Rational Field Defn: Defined on coordinates by sending (x, y) to - (1/(t)*x^2 + y^2, y^2 - 1/(t)) + (1/t*x^2 + y^2, y^2 - 1/t) :: @@ -1969,7 +1969,7 @@ def reduce_base_field(self): sage: f.reduce_base_field() Scheme endomorphism of Projective Space of dimension 1 over Finite Field in t2 of size 3^2 Defn: Defined on coordinates by sending (x : y) to - (x^2 + (t2)*y^2 : y^2) + (x^2 + t2*y^2 : y^2) sage: f2 = H2([x^2 + 5*y^2,y^2, 2*x*y]) sage: f2.reduce_base_field() Scheme morphism: @@ -1983,7 +1983,7 @@ def reduce_base_field(self): From: Projective Space of dimension 2 over Finite Field in t of size 3^4 To: Projective Space of dimension 1 over Finite Field in t of size 3^4 Defn: Defined on coordinates by sending (a : b : c) to - (a^2 + (t)*b^2 : c^2) + (a^2 + t*b^2 : c^2) :: @@ -2006,7 +2006,7 @@ def reduce_base_field(self): sage: f.reduce_base_field() Scheme endomorphism of Projective Space of dimension 1 over Finite Field in z4 of size 5^4 Defn: Defined on coordinates by sending (x : y) to - ((z4^3 + z4^2 + z4 - 2)*x^2 + (z4)*y^2 : x*y) + ((z4^3 + z4^2 + z4 - 2)*x^2 + z4*y^2 : x*y) sage: f=DynamicalSystem_projective([L.gen(3)*x^2 + L.gen(2)*y^2, x*y]) sage: f.reduce_base_field() Dynamical System of Projective Space of dimension 1 over Finite Field in z6 of size 5^6 diff --git a/src/sage/schemes/toric/fano_variety.py b/src/sage/schemes/toric/fano_variety.py index 579fd4821f2..8935197298d 100644 --- a/src/sage/schemes/toric/fano_variety.py +++ b/src/sage/schemes/toric/fano_variety.py @@ -57,10 +57,10 @@ ....: monomial_points="all") Closed subscheme of 2-d CPR-Fano toric variety covered by 3 affine patches defined by: - (a0)*z0^3 + (a9)*z0^2*z1 + (a7)*z0*z1^2 - + (a1)*z1^3 + (a8)*z0^2*z2 + (a6)*z0*z1*z2 - + (a4)*z1^2*z2 + (a5)*z0*z2^2 - + (a3)*z1*z2^2 + (a2)*z2^3 + a0*z0^3 + a9*z0^2*z1 + a7*z0*z1^2 + + a1*z1^3 + a8*z0^2*z2 + a6*z0*z1*z2 + + a4*z1^2*z2 + a5*z0*z2^2 + + a3*z1*z2^2 + a2*z2^3 In many cases it is sufficient to work with the "simplified polynomial moduli space" of anticanonical hypersurfaces:: @@ -69,7 +69,7 @@ ....: monomial_points="simplified") Closed subscheme of 2-d CPR-Fano toric variety covered by 3 affine patches defined by: - (a0)*z0^3 + (a1)*z1^3 + (a6)*z0*z1*z2 + (a2)*z2^3 + a0*z0^3 + a1*z1^3 + a6*z0*z1*z2 + a2*z2^3 The mirror family to these hypersurfaces lives inside the Fano toric variety obtained using ``simplex`` as ``Delta`` instead of ``Delta_polar``:: @@ -80,10 +80,10 @@ ....: monomial_points="simplified") Closed subscheme of 2-d CPR-Fano toric variety covered by 9 affine patches defined by: - (a2)*z2^3*z3^2*z4*z5^2*z8 - + (a1)*z1^3*z3*z4^2*z7^2*z9 - + (a3)*z0*z1*z2*z3*z4*z5*z7*z8*z9 - + (a0)*z0^3*z5*z7*z8^2*z9^2 + a2*z2^3*z3^2*z4*z5^2*z8 + + a1*z1^3*z3*z4^2*z7^2*z9 + + a3*z0*z1*z2*z3*z4*z5*z7*z8*z9 + + a0*z0^3*z5*z7*z8^2*z9^2 Here we have taken the resolved version of the ambient space for the mirror family, but in fact we don't have to resolve singularities @@ -96,7 +96,7 @@ ....: monomial_points="simplified") Closed subscheme of 2-d CPR-Fano toric variety covered by 3 affine patches defined by: - (a0)*z0^3 + (a1)*z1^3 + (a3)*z0*z1*z2 + (a2)*z2^3 + a0*z0^3 + a1*z1^3 + a3*z0*z1*z2 + a2*z2^3 This looks very similar to our second version of the anticanonical hypersurface of the projective plane, as expected, since all @@ -110,8 +110,8 @@ sage: FTV.anticanonical_hypersurface() Closed subscheme of 3-d CPR-Fano toric variety covered by 4 affine patches defined by: - (a0)*z2^12 + (a4)*z2^6*z3^6 + (a3)*z3^12 - + (a8)*z0*z1*z2*z3 + (a2)*z1^3 + (a1)*z0^2 + a0*z2^12 + a4*z2^6*z3^6 + a3*z3^12 + + a8*z0*z1*z2*z3 + a2*z1^3 + a1*z0^2 Below you will find detailed descriptions of available functions. Current functionality of this module is very basic, but it is under active @@ -806,10 +806,10 @@ def anticanonical_hypersurface(self, **kwds): ....: monomial_points="all") Closed subscheme of 2-d CPR-Fano toric variety covered by 3 affine patches defined by: - (a0)*z0^3 + (a9)*z0^2*z1 + (a7)*z0*z1^2 - + (a1)*z1^3 + (a8)*z0^2*z2 + (a6)*z0*z1*z2 - + (a4)*z1^2*z2 + (a5)*z0*z2^2 - + (a3)*z1*z2^2 + (a2)*z2^3 + a0*z0^3 + a9*z0^2*z1 + a7*z0*z1^2 + + a1*z1^3 + a8*z0^2*z2 + a6*z0*z1*z2 + + a4*z1^2*z2 + a5*z0*z2^2 + + a3*z1*z2^2 + a2*z2^3 In many cases it is sufficient to work with the "simplified polynomial moduli space" of anticanonical hypersurfaces:: @@ -818,7 +818,7 @@ def anticanonical_hypersurface(self, **kwds): ....: monomial_points="simplified") Closed subscheme of 2-d CPR-Fano toric variety covered by 3 affine patches defined by: - (a0)*z0^3 + (a1)*z1^3 + (a6)*z0*z1*z2 + (a2)*z2^3 + a0*z0^3 + a1*z1^3 + a6*z0*z1*z2 + a2*z2^3 The mirror family to these hypersurfaces lives inside the Fano toric variety obtained using ``simplex`` as ``Delta`` instead of @@ -830,10 +830,10 @@ def anticanonical_hypersurface(self, **kwds): ....: monomial_points="simplified") Closed subscheme of 2-d CPR-Fano toric variety covered by 9 affine patches defined by: - (a2)*z2^3*z3^2*z4*z5^2*z8 - + (a1)*z1^3*z3*z4^2*z7^2*z9 - + (a3)*z0*z1*z2*z3*z4*z5*z7*z8*z9 - + (a0)*z0^3*z5*z7*z8^2*z9^2 + a2*z2^3*z3^2*z4*z5^2*z8 + + a1*z1^3*z3*z4^2*z7^2*z9 + + a3*z0*z1*z2*z3*z4*z5*z7*z8*z9 + + a0*z0^3*z5*z7*z8^2*z9^2 Here we have taken the resolved version of the ambient space for the mirror family, but in fact we don't have to resolve singularities @@ -846,7 +846,7 @@ def anticanonical_hypersurface(self, **kwds): ....: monomial_points="simplified") Closed subscheme of 2-d CPR-Fano toric variety covered by 3 affine patches defined by: - (a0)*z0^3 + (a1)*z1^3 + (a3)*z0*z1*z2 + (a2)*z2^3 + a0*z0^3 + a1*z1^3 + a3*z0*z1*z2 + a2*z2^3 This looks very similar to our second anticanonical hypersurface of the projective plane, as expected, since all @@ -860,7 +860,7 @@ def anticanonical_hypersurface(self, **kwds): ....: coefficient_names="a b c d") Closed subscheme of 2-d CPR-Fano toric variety covered by 3 affine patches defined by: - (a)*z0^3 + (b)*z1^3 + (d)*z0*z1*z2 + (c)*z2^3 + a*z0^3 + b*z1^3 + d*z0*z1*z2 + c*z2^3 or give concrete coefficients :: @@ -877,7 +877,7 @@ def anticanonical_hypersurface(self, **kwds): sage: H Closed subscheme of 2-d CPR-Fano toric variety covered by 3 affine patches defined by: - (t)*z1^3 + (psi)/(phi + psi^2)*z0*z1*z2 + 1/(t)*z2^3 + t*z1^3 + psi/(phi + psi^2)*z0*z1*z2 + 1/t*z2^3 sage: R = H.ambient_space().base_ring() sage: R Fraction Field of @@ -1124,21 +1124,21 @@ def nef_complete_intersection(self, nef_partition, **kwds): sage: X.nef_complete_intersection(np) Closed subscheme of 3-d CPR-Fano toric variety covered by 10 affine patches defined by: - (a0)*z1*z4^2*z5^2*z7^3 + (a2)*z2*z4*z5*z6*z7^2*z8^2 - + (a3)*z2*z3*z4*z7*z8 + (a1)*z0*z2, - (b3)*z1*z4*z5^2*z6^2*z7^2*z8^2 + (b0)*z2*z5*z6^3*z7*z8^4 - + (b5)*z1*z3*z4*z5*z6*z7*z8 + (b2)*z2*z3*z6^2*z8^3 - + (b1)*z1*z3^2*z4 + (b4)*z0*z1*z5*z6 + a0*z1*z4^2*z5^2*z7^3 + a2*z2*z4*z5*z6*z7^2*z8^2 + + a3*z2*z3*z4*z7*z8 + a1*z0*z2, + b3*z1*z4*z5^2*z6^2*z7^2*z8^2 + b0*z2*z5*z6^3*z7*z8^4 + + b5*z1*z3*z4*z5*z6*z7*z8 + b2*z2*z3*z6^2*z8^3 + + b1*z1*z3^2*z4 + b4*z0*z1*z5*z6 Now we include only monomials associated to vertices of `\Delta_i`:: sage: X.nef_complete_intersection(np, monomial_points="vertices") Closed subscheme of 3-d CPR-Fano toric variety covered by 10 affine patches defined by: - (a0)*z1*z4^2*z5^2*z7^3 + (a2)*z2*z4*z5*z6*z7^2*z8^2 - + (a3)*z2*z3*z4*z7*z8 + (a1)*z0*z2, - (b3)*z1*z4*z5^2*z6^2*z7^2*z8^2 + (b0)*z2*z5*z6^3*z7*z8^4 - + (b2)*z2*z3*z6^2*z8^3 + (b1)*z1*z3^2*z4 + (b4)*z0*z1*z5*z6 + a0*z1*z4^2*z5^2*z7^3 + a2*z2*z4*z5*z6*z7^2*z8^2 + + a3*z2*z3*z4*z7*z8 + a1*z0*z2, + b3*z1*z4*z5^2*z6^2*z7^2*z8^2 + b0*z2*z5*z6^3*z7*z8^4 + + b2*z2*z3*z6^2*z8^3 + b1*z1*z3^2*z4 + b4*z0*z1*z5*z6 (effectively, we set ``b5=0``). Next we provide coefficients explicitly instead of using default generic names:: @@ -1148,7 +1148,7 @@ def nef_complete_intersection(self, nef_partition, **kwds): ....: coefficients=[("a", "a^2", "a/e", "c_i"), list(range(1,6))]) Closed subscheme of 3-d CPR-Fano toric variety covered by 10 affine patches defined by: - (a)*z1*z4^2*z5^2*z7^3 + (a)/(e)*z2*z4*z5*z6*z7^2*z8^2 + a*z1*z4^2*z5^2*z7^3 + a/e*z2*z4*z5*z6*z7^2*z8^2 + (c_i)*z2*z3*z4*z7*z8 + (a^2)*z0*z2, 4*z1*z4*z5^2*z6^2*z7^2*z8^2 + z2*z5*z6^3*z7*z8^4 + 3*z2*z3*z6^2*z8^3 + 2*z1*z3^2*z4 + 5*z0*z1*z5*z6 @@ -1161,14 +1161,14 @@ def nef_complete_intersection(self, nef_partition, **kwds): sage: X.nef_complete_intersection(np) Closed subscheme of 3-d CPR-Fano toric variety covered by 22 affine patches defined by: - (a2)*z2*z4*z5*z6*z7^2*z8^2*z9^2*z10^2*z11*z12*z13 - + (a0)*z1*z4^2*z5^2*z7^3*z9*z10^2*z12*z13 - + (a3)*z2*z3*z4*z7*z8*z9*z10*z11*z12 + (a1)*z0*z2, - (b0)*z2*z5*z6^3*z7*z8^4*z9^3*z10^2*z11^2*z12*z13^2 - + (b3)*z1*z4*z5^2*z6^2*z7^2*z8^2*z9^2*z10^2*z11*z12*z13^2 - + (b2)*z2*z3*z6^2*z8^3*z9^2*z10*z11^2*z12*z13 - + (b5)*z1*z3*z4*z5*z6*z7*z8*z9*z10*z11*z12*z13 - + (b1)*z1*z3^2*z4*z11*z12 + (b4)*z0*z1*z5*z6*z13 + a2*z2*z4*z5*z6*z7^2*z8^2*z9^2*z10^2*z11*z12*z13 + + a0*z1*z4^2*z5^2*z7^3*z9*z10^2*z12*z13 + + a3*z2*z3*z4*z7*z8*z9*z10*z11*z12 + a1*z0*z2, + b0*z2*z5*z6^3*z7*z8^4*z9^3*z10^2*z11^2*z12*z13^2 + + b3*z1*z4*z5^2*z6^2*z7^2*z8^2*z9^2*z10^2*z11*z12*z13^2 + + b2*z2*z3*z6^2*z8^3*z9^2*z10*z11^2*z12*z13 + + b5*z1*z3*z4*z5*z6*z7*z8*z9*z10*z11*z12*z13 + + b1*z1*z3^2*z4*z11*z12 + b4*z0*z1*z5*z6*z13 """ return NefCompleteIntersection(self, nef_partition, **kwds) @@ -1356,7 +1356,7 @@ class AnticanonicalHypersurface(AlgebraicScheme_subscheme_toric): sage: ftv.AnticanonicalHypersurface(P1xP1) Closed subscheme of 2-d CPR-Fano toric variety covered by 4 affine patches defined by: - (a0)*s^2*x^2 + (a3)*t^2*x^2 + (a6)*s*t*x*y + (a1)*s^2*y^2 + (a2)*t^2*y^2 + a0*s^2*x^2 + a3*t^2*x^2 + a6*s*t*x*y + a1*s^2*y^2 + a2*t^2*y^2 See :meth:`~CPRFanoToricVariety_field.anticanonical_hypersurface()` for a more elaborate example. @@ -1374,7 +1374,7 @@ def __init__(self, P_Delta, monomial_points=None, coefficient_names=None, sage: ftv.AnticanonicalHypersurface(P1xP1) Closed subscheme of 2-d CPR-Fano toric variety covered by 4 affine patches defined by: - (a0)*s^2*x^2 + (a3)*t^2*x^2 + (a6)*s*t*x*y + (a1)*s^2*y^2 + (a2)*t^2*y^2 + a0*s^2*x^2 + a3*t^2*x^2 + a6*s*t*x*y + a1*s^2*y^2 + a2*t^2*y^2 Check that finite fields are handled correctly :trac:`14899`:: @@ -1473,10 +1473,10 @@ class NefCompleteIntersection(AlgebraicScheme_subscheme_toric): sage: X.nef_complete_intersection(np) Closed subscheme of 3-d CPR-Fano toric variety covered by 8 affine patches defined by: - (a2)*z0^2*z1 + (a5)*z0*z1*z3 + (a1)*z1*z3^2 - + (a3)*z0^2*z4 + (a4)*z0*z3*z4 + (a0)*z3^2*z4, - (b1)*z1*z2^2 + (b2)*z2^2*z4 + (b5)*z1*z2*z5 - + (b4)*z2*z4*z5 + (b3)*z1*z5^2 + (b0)*z4*z5^2 + a2*z0^2*z1 + a5*z0*z1*z3 + a1*z1*z3^2 + + a3*z0^2*z4 + a4*z0*z3*z4 + a0*z3^2*z4, + b1*z1*z2^2 + b2*z2^2*z4 + b5*z1*z2*z5 + + b4*z2*z4*z5 + b3*z1*z5^2 + b0*z4*z5^2 See :meth:`CPRFanoToricVariety_field.nef_complete_intersection` for a more elaborate example. @@ -1499,10 +1499,10 @@ def __init__(self, P_Delta, nef_partition, sage: NefCompleteIntersection(X, np) Closed subscheme of 3-d CPR-Fano toric variety covered by 8 affine patches defined by: - (a2)*z0^2*z1 + (a5)*z0*z1*z3 + (a1)*z1*z3^2 - + (a3)*z0^2*z4 + (a4)*z0*z3*z4 + (a0)*z3^2*z4, - (b1)*z1*z2^2 + (b2)*z2^2*z4 + (b5)*z1*z2*z5 - + (b4)*z2*z4*z5 + (b3)*z1*z5^2 + (b0)*z4*z5^2 + a2*z0^2*z1 + a5*z0*z1*z3 + a1*z1*z3^2 + + a3*z0^2*z4 + a4*z0*z3*z4 + a0*z3^2*z4, + b1*z1*z2^2 + b2*z2^2*z4 + b5*z1*z2*z5 + + b4*z2*z4*z5 + b3*z1*z5^2 + b0*z4*z5^2 """ if not is_CPRFanoToricVariety(P_Delta): raise TypeError("nef complete intersections can only be " @@ -1597,10 +1597,10 @@ def cohomology_class(self): sage: CI Closed subscheme of 3-d CPR-Fano toric variety covered by 8 affine patches defined by: - (a2)*z0^2*z1 + (a5)*z0*z1*z3 + (a1)*z1*z3^2 - + (a3)*z0^2*z4 + (a4)*z0*z3*z4 + (a0)*z3^2*z4, - (b1)*z1*z2^2 + (b2)*z2^2*z4 + (b5)*z1*z2*z5 - + (b4)*z2*z4*z5 + (b3)*z1*z5^2 + (b0)*z4*z5^2 + a2*z0^2*z1 + a5*z0*z1*z3 + a1*z1*z3^2 + + a3*z0^2*z4 + a4*z0*z3*z4 + a0*z3^2*z4, + b1*z1*z2^2 + b2*z2^2*z4 + b5*z1*z2*z5 + + b4*z2*z4*z5 + b3*z1*z5^2 + b0*z4*z5^2 sage: CI.cohomology_class() [2*z3*z4 + 4*z3*z5 + 2*z4*z5] """ @@ -1630,10 +1630,10 @@ def nef_partition(self): sage: CI Closed subscheme of 3-d CPR-Fano toric variety covered by 8 affine patches defined by: - (a2)*z0^2*z1 + (a5)*z0*z1*z3 + (a1)*z1*z3^2 - + (a3)*z0^2*z4 + (a4)*z0*z3*z4 + (a0)*z3^2*z4, - (b1)*z1*z2^2 + (b2)*z2^2*z4 + (b5)*z1*z2*z5 - + (b4)*z2*z4*z5 + (b3)*z1*z5^2 + (b0)*z4*z5^2 + a2*z0^2*z1 + a5*z0*z1*z3 + a1*z1*z3^2 + + a3*z0^2*z4 + a4*z0*z3*z4 + a0*z3^2*z4, + b1*z1*z2^2 + b2*z2^2*z4 + b5*z1*z2*z5 + + b4*z2*z4*z5 + b3*z1*z5^2 + b0*z4*z5^2 sage: CI.nef_partition() Nef-partition {0, 1, 3} U {2, 4, 5} sage: CI.nef_partition() is np diff --git a/src/sage/structure/coerce.pyx b/src/sage/structure/coerce.pyx index 7dc6cbd59ff..4d9069725ae 100644 --- a/src/sage/structure/coerce.pyx +++ b/src/sage/structure/coerce.pyx @@ -484,7 +484,7 @@ cdef class CoercionModel: EXAMPLES:: sage: f = ZZ['t','x'].0 + QQ['x'].0 + CyclotomicField(13).gen(); f - t + x + (zeta13) + t + x + zeta13 sage: f.parent() Multivariate Polynomial Ring in t, x over Cyclotomic Field of order 13 and degree 12 sage: ZZ['x','y'].0 + ~Frac(QQ['y']).0 diff --git a/src/sage/tests/books/computational-mathematics-with-sagemath/mpoly_doctest.py b/src/sage/tests/books/computational-mathematics-with-sagemath/mpoly_doctest.py index bb56738cd50..0e6cad57fee 100644 --- a/src/sage/tests/books/computational-mathematics-with-sagemath/mpoly_doctest.py +++ b/src/sage/tests/books/computational-mathematics-with-sagemath/mpoly_doctest.py @@ -93,7 +93,7 @@ sage: (x^10 + y^5).gcd(x^4 - y^2) x^2 + y sage: (x^10 + y^5).factor() - (x^2 + y) * (x^2 + (a^3)*y) * (x^2 + (a^2)*y) * (x^2 + (a)*y) * (x^2 + (-a^3 - a^2 - a - 1)*y) + (x^2 + y) * (x^2 + (a^3)*y) * (x^2 + (a^2)*y) * (x^2 + a*y) * (x^2 + (-a^3 - a^2 - a - 1)*y) Sage example in ./mpoly.tex, line 564:: From b45fc7e3f206cad0078ad259d5e951a1feb3fdfb Mon Sep 17 00:00:00 2001 From: Miguel Marco Date: Tue, 12 Oct 2021 18:02:46 +0200 Subject: [PATCH 025/126] Clean intermediate coefficients too --- src/sage/libs/singular/singular.pyx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/sage/libs/singular/singular.pyx b/src/sage/libs/singular/singular.pyx index b576c7e9719..aadc0d244f8 100644 --- a/src/sage/libs/singular/singular.pyx +++ b/src/sage/libs/singular/singular.pyx @@ -651,6 +651,8 @@ cdef number *sa2si_transext(object elem, ring *_ring): denom = coef.denominator() cfden = _ring.cf.cfInitMPZ((denom).value, _ring.cf) naCoeff = _ring.cf.cfDiv(cfnum, cfden , _ring.cf ) + _ring.cf.cfDelete(&cfnum, _ring.cf) + _ring.cf.cfDelete(&cfden, _ring.cf) for (j, ex) in enumerate(exponents): a = _ring.cf.cfParameter(j+1, _ring.cf) for k in range(ex): @@ -671,6 +673,8 @@ cdef number *sa2si_transext(object elem, ring *_ring): denom = coef.denominator() cfden = _ring.cf.cfInitMPZ((denom).value, _ring.cf) naCoeff = _ring.cf.cfDiv(cfnum, cfden , _ring.cf ) + _ring.cf.cfDelete(&cfnum, _ring.cf) + _ring.cf.cfDelete(&cfden, _ring.cf) for (j, ex) in enumerate(exponents): a = _ring.cf.cfParameter(j+1, _ring.cf) for k in range(ex): @@ -689,8 +693,6 @@ cdef number *sa2si_transext(object elem, ring *_ring): _ring.cf.cfDelete(&numerator, _ring.cf) _ring.cf.cfDelete(&denominator, _ring.cf) - _ring.cf.cfDelete(&cfnum, _ring.cf) - _ring.cf.cfDelete(&cfden, _ring.cf) _ring.cf.cfDelete(&naCoeff, _ring.cf) _ring.cf.cfDelete(&a, _ring.cf) From 4a02d25877f187d78a0f748847daa580f27adda7 Mon Sep 17 00:00:00 2001 From: Miguel Marco Date: Thu, 14 Oct 2021 13:28:59 +0200 Subject: [PATCH 026/126] Improve documentation --- src/sage/libs/singular/ring.pyx | 7 + src/sage/libs/singular/singular.pyx | 340 +++++++++++++++++++++++++++- 2 files changed, 343 insertions(+), 4 deletions(-) diff --git a/src/sage/libs/singular/ring.pyx b/src/sage/libs/singular/ring.pyx index 64fceeaff88..f8cd183bb00 100644 --- a/src/sage/libs/singular/ring.pyx +++ b/src/sage/libs/singular/ring.pyx @@ -6,6 +6,8 @@ AUTHORS: - Martin Albrecht (2009-07): initial implementation - Kwankyu Lee (2010-06): added matrix term order support + +- Miguel Marco (2021): added transcendental extensions over Q """ #***************************************************************************** # Copyright (C) 2009 Martin Albrecht @@ -127,6 +129,11 @@ cdef ring *singular_ring_new(base_ring, n, names, term_order) except NULL: sage: P. = Zmod(25213521351515232)[]; P Multivariate Polynomial Ring in x, y, z over Ring of integers modulo 25213521351515232 + sage: K = PolynomialRing(QQ, 's,t').fraction_field() + sage: P. = K[]; P + Multivariate Polynomial Ring in x, y over Fraction Field of Multivariate Polynomial Ring in s, t over Rational Field + + TESTS: Check that ``degneglex`` and ``degrevlex`` are the same up to reversal of diff --git a/src/sage/libs/singular/singular.pyx b/src/sage/libs/singular/singular.pyx index aadc0d244f8..cb8a1b6aad0 100644 --- a/src/sage/libs/singular/singular.pyx +++ b/src/sage/libs/singular/singular.pyx @@ -4,6 +4,8 @@ libSingular: Conversion Routines and Initialisation AUTHOR: - Martin Albrecht + +- Miguel Marco (2021): added transcendental extensions over Q """ # **************************************************************************** @@ -56,6 +58,21 @@ _saved_options = (int(0),0,0) cdef Rational si2sa_QQ(number *n, number **nn, ring *_ring): """ + Create a sage rational number from a singular one. + + INPUT: + + - ``n`` - a (pointer to) a singular rational number + + - ``*n`` - a pointer to a pointer like before + + - ``_ ring`` - a (pointer to) a singular ring, in whose coefficient field + lives ``n`` + + OUTPUT: + + - A sage Rational + TESTS:: sage: P. = QQ[] @@ -113,6 +130,20 @@ cdef Rational si2sa_QQ(number *n, number **nn, ring *_ring): cdef Integer si2sa_ZZ(number *n, ring *_ring): """ + Create a sage integer number from a singular one. + + INPUT: + + - ``n`` - a (pointer to) a singular integer number + + - ``_ ring`` - a (pointer to) a singular ring, in whose coefficient field + lives ``n`` + + OUTPUT: + + - A sage Integer + + TESTS:: sage: P. = ZZ[] @@ -134,6 +165,21 @@ cdef Integer si2sa_ZZ(number *n, ring *_ring): cdef FFgivE si2sa_GFqGivaro(number *n, ring *_ring, Cache_givaro cache): """ + Create a sage element of a small finite field from a singular one. + + INPUT: + + - ``n`` - a (pointer to) a singular number in a finite field + + - ``_ ring`` - a (pointer to) a singular ring, in whose coefficient field + lives ``n`` + + - ``cache`` - A Givaro number field + + OUTPUT: + + - A sage element of ``cache`` + TESTS:: sage: K. = GF(5^3) @@ -174,6 +220,23 @@ cdef FFgivE si2sa_GFqGivaro(number *n, ring *_ring, Cache_givaro cache): cdef FFgf2eE si2sa_GFqNTLGF2E(number *n, ring *_ring, Cache_ntl_gf2e cache): """ + Create a sage element of a finite field of characteristic 2 from a + singular one. + + INPUT: + + - ``n`` - a (pointer to) a singular number in a finite field + + - ``_ ring`` - a (pointer to) a singular ring, in whose coefficient field + lives ``n`` + + - ``cache`` - A ntl_gf2e number field + + OUTPUT: + + - A sage element of ``cache`` + + TESTS:: sage: K. = GF(2^20) @@ -209,6 +272,21 @@ cdef FFgf2eE si2sa_GFqNTLGF2E(number *n, ring *_ring, Cache_ntl_gf2e cache): cdef object si2sa_GFq_generic(number *n, ring *_ring, object base): """ + Create a sage element of a generic finite field from a singular one. + + INPUT: + + - ``n`` - a (pointer to) a singular number in a finite field + + - ``_ ring`` - a (pointer to) a singular ring, in whose coefficient field + lives ``n`` + + - ``base`` - A sage finite field + + OUTPUT: + + - A sage element of ``base`` + TESTS:: sage: K. = GF(3^16) @@ -255,8 +333,25 @@ cdef object si2sa_GFq_generic(number *n, ring *_ring, object base): z = pNext(z) return ret -cdef object si2sa_transext(number *n, ring *_ring, object base): +cdef object si2sa_transext_QQ(number *n, ring *_ring, object base): """ + Create a sage element of a transcendental extension of ``QQ`` from a + singular one. + + INPUT: + + - ``n`` - a (pointer to) a singular number in a transcendental extension + of the rationals + + - ``_ ring`` - a (pointer to) a singular ring, in whose coefficient field + lives ``n`` + + - ``base`` - A sage FractionField + + OUTPUT: + + - A sage element of ``base`` + TESTS:: sage: F = PolynomialRing(QQ,'a,b').fraction_field() @@ -331,6 +426,23 @@ cdef object si2sa_transext(number *n, ring *_ring, object base): cdef object si2sa_NF(number *n, ring *_ring, object base): """ + Create a sage element of a number field from a singular one. + + INPUT: + + - ``n`` - a (pointer to) a singular number in an algebraic extension of + the rationals + + - ``_ ring`` - a (pointer to) a singular ring, in whose coefficient field + lives ``n`` + + - ``base`` - A sage NumberField + + OUTPUT: + + - A sage element of ``base`` + + TESTS:: sage: K. = NumberField(x^2 - 2) @@ -379,6 +491,21 @@ cdef object si2sa_NF(number *n, ring *_ring, object base): cdef inline object si2sa_ZZmod(number *n, ring *_ring, object base): """ + Create a sage element of a ring of integers modulo n from a singular one. + + INPUT: + + - ``n`` - a (pointer to) a singular number in a ring of integers modulo n + + - ``_ ring`` - a (pointer to) a singular ring, in whose coefficient field + lives ``n`` + + - ``base`` - A sage IntegerModRing + + OUTPUT: + + - A sage element of ``base`` + TESTS:: sage: P. = Integers(10)[] @@ -425,6 +552,20 @@ cdef inline object si2sa_ZZmod(number *n, ring *_ring, object base): cdef number *sa2si_QQ(Rational r, ring *_ring): """ + Create a singular number from a sage rational. + + INPUT: + + - ``r`` - a sage rational number + + - ``_ ring`` - a (pointer to) a singular ring, where the resul will live + + + OUTPUT: + + - A (pointer to) a singular number + + TESTS:: sage: P. = QQ[] @@ -442,6 +583,37 @@ cdef number *sa2si_QQ(Rational r, ring *_ring): cdef number *sa2si_GFqGivaro(int quo, ring *_ring): """ + Create a singular number in a small finite field. + + INPUT: + + - ``quo`` - a sage integer + + - ``_ ring`` - a (pointer to) a singular ring, where the resul will live + + + OUTPUT: + + - A (pointer to) a singular number + + Number field elements are represented as polynomials in the number field + generator. In this case, ``quo`` is the integer resulting from evaluating + that polynomial in the characteristic of the field. + + + TESTS:: + + sage: F = FiniteField(5^2) + sage: type(F) + + sage: R. = F[] + sage: R(0) + 1 + 1 + sage: R(F.gen()) + 1 + (z2 + 1) + sage: R(F.gen()^2) + 1 + (z2 - 1) + """ if _ring != currRing: rChangeCurrRing(_ring) @@ -481,6 +653,33 @@ cdef number *sa2si_GFqGivaro(int quo, ring *_ring): cdef number *sa2si_GFqNTLGF2E(FFgf2eE elem, ring *_ring): """ + Create a singular number from a sage element of a finite field of + characteristic 2. + + INPUT: + + - ``elem`` - a sage element of a ntl_gf2e finite field + + - ``_ ring`` - a (pointer to) a singular ring, where the resul will live + + + OUTPUT: + + - A (pointer to) a singular number + + TESTS:: + + sage: F = FiniteField(2^20) + sage: type(F) + + sage: R. = F[] + sage: R(0)+1 + 1 + sage: R(F.gen()) + 1 + (z20 + 1) + sage: R(F.gen()^21) + 1 + (z20^11 + z20^10 + z20^8 + z20^7 + z20^6 + z20^5 + z20^2 + z20 + 1) + """ if _ring != currRing: rChangeCurrRing(_ring) cdef int i @@ -522,6 +721,32 @@ cdef number *sa2si_GFqNTLGF2E(FFgf2eE elem, ring *_ring): cdef number *sa2si_GFq_generic(object elem, ring *_ring): """ + Create a singular number from a sage element of a generic finite field. + + INPUT: + + - ``elem`` - a sage element of a generic finite field + + - ``_ ring`` - a (pointer to) a singular ring, where the resul will live + + + OUTPUT: + + - A (pointer to) a singular number + + TESTS:: + + sage: F = FiniteField(3^20) + sage: type(F) + + sage: R. = F[] + sage: R(0) + 1 + 1 + sage: R(F.gen()) + 1 + (z20 + 1) + sage: R(F.gen()^21) + 1 + (z20^14 - z20^12 - z20^11 - z20^10 - z20^9 + z20^6 + z20^5 + z20^4 - z20^2 + z20 + 1) + """ cdef int i cdef number *n1 @@ -561,8 +786,23 @@ cdef number *sa2si_GFq_generic(object elem, ring *_ring): return n1 -cdef number *sa2si_transext(object elem, ring *_ring): +cdef number *sa2si_transext_QQ(object elem, ring *_ring): """ + Create a singular number from a sage element of a transcendental extension + of the rationals. + + INPUT: + + - ``elem`` - a sage element of a FractionField of polynomials over the rationals + + - ``_ ring`` - a (pointer to) a singular ring, where the resul will live + + + OUTPUT: + + - A (pointer to) a singular number + + TESTS:: sage: F = PolynomialRing(QQ,'a,b').fraction_field() @@ -701,6 +941,34 @@ cdef number *sa2si_transext(object elem, ring *_ring): cdef number *sa2si_NF(object elem, ring *_ring): """ + Create a singular number from a sage element of a number field. + + INPUT: + + - ``elem`` - a sage element of a NumberField + + - ``_ ring`` - a (pointer to) a singular ring, where the resul will live + + + OUTPUT: + + - A (pointer to) a singular number + + TESTS:: + + sage: F = NumberField(x^3+x+1, 'a') + sage: type(F) + + sage: R. = F[] + sage: R(0) + 1 + 1 + sage: R(1) + 1 + sage: R(F.gen()) + 1 + (a + 1) + sage: R(F.gen()^5) + 1 + (-a^2 + a + 2) + """ cdef int i cdef number *n1 @@ -767,6 +1035,20 @@ cdef number *sa2si_NF(object elem, ring *_ring): cdef number *sa2si_ZZ(Integer d, ring *_ring): """ + Create a singular number from a sage Integer. + + INPUT: + + - ``elem`` - a sage Integer + + - ``_ ring`` - a (pointer to) a singular ring, where the resul will live + + + OUTPUT: + + - A (pointer to) a singular number + + TESTS:: sage: P. = ZZ[] @@ -786,6 +1068,16 @@ cdef number *sa2si_ZZ(Integer d, ring *_ring): cdef inline number *sa2si_ZZmod(IntegerMod_abstract d, ring *_ring): """ + Create a singular number from a sage element of a IntegerModRing. + + INPUT: + + - ``elem`` - a sage IntegerMod + + - ``_ ring`` - a (pointer to) a singular ring, where the resul will live + + + TESTS:: sage: P. = Integers(10)[] @@ -859,6 +1151,21 @@ cdef inline number *sa2si_ZZmod(IntegerMod_abstract d, ring *_ring): raise ValueError cdef object si2sa(number *n, ring *_ring, object base): + r""" + Create a sage number from a singular one + + INPUT: + + - ``n`` - a (pointer to) a singular number + + - ``_ring`` - a (pointer to) the singular ring where ``n`` lives + + - ``object`` - the sage parent where the result will live + + OUTPUT: + + An element of ``base`` + """ if isinstance(base, FiniteField_prime_modn): return base(_ring.cf.cfInt(n, _ring.cf)) @@ -881,7 +1188,7 @@ cdef object si2sa(number *n, ring *_ring, object base): return si2sa_NF(n, _ring, base) elif isinstance(base, FractionField_generic) and isinstance(base.base(), (MPolynomialRing_libsingular, PolynomialRing_field)) and isinstance(base.base_ring(), RationalField): - return si2sa_transext(n, _ring, base) + return si2sa_transext_QQ(n, _ring, base) elif isinstance(base, IntegerModRing_generic): if _ring.cf.type == n_unknown: @@ -892,6 +1199,20 @@ cdef object si2sa(number *n, ring *_ring, object base): raise ValueError("cannot convert from SINGULAR number") cdef number *sa2si(Element elem, ring * _ring): + r""" + Create a singular number from a sage one. + + INPUT: + + - ``elem`` - a sage element from a parent. The parent must have a + corresponding singular coefficient type. + + - ``_ring`` - a (pointer to) the singular ring where the result will live. + + OUTPUT: + + a (pointer to) a singular number + """ cdef int i = 0 if isinstance(elem._parent, FiniteField_prime_modn): return n_Init(int(elem),_ring) @@ -918,13 +1239,24 @@ cdef number *sa2si(Element elem, ring * _ring): return n_Init(int(elem),_ring) return sa2si_ZZmod(elem, _ring) elif isinstance(elem._parent, FractionField_generic) and isinstance(elem._parent.base(), (MPolynomialRing_libsingular, PolynomialRing_field)) and isinstance(elem._parent.base().base_ring(), RationalField): - return sa2si_transext(elem, _ring) + return sa2si_transext_QQ(elem, _ring) else: raise ValueError("cannot convert to SINGULAR number") cdef object si2sa_intvec(intvec *v): + r""" + create a sage tuple from a singular vector of integers + + INPUT: + + - ``v`` - a (pointer to) a singular intvec + + OUTPUT: + + a sage tuple + """ cdef int r cdef list l = list() for r in range(v.length()): From 13e30ad037326fd816669fc03519ac9ae2ab6a90 Mon Sep 17 00:00:00 2001 From: Miguel Marco Date: Sat, 16 Oct 2021 21:00:02 +0200 Subject: [PATCH 027/126] Implemented transcendental extensions over prime fields --- src/sage/libs/singular/ring.pyx | 27 +++++ src/sage/libs/singular/singular.pyx | 154 ++++++++++++++++++++++++++++ 2 files changed, 181 insertions(+) diff --git a/src/sage/libs/singular/ring.pyx b/src/sage/libs/singular/ring.pyx index f8cd183bb00..7f6f2d7b22b 100644 --- a/src/sage/libs/singular/ring.pyx +++ b/src/sage/libs/singular/ring.pyx @@ -289,6 +289,33 @@ cdef ring *singular_ring_new(base_ring, n, names, term_order) except NULL: _cf = nInitChar(n_transExt, &trextParam) + if (_cf is NULL): + raise RuntimeError("Failed to allocate _cf ring.") + + _ring = rDefault (_cf ,nvars, _names, nblcks, _order, _block0, _block1, _wvhdl) + + elif isinstance(base_ring, FractionField_generic) and isinstance(base_ring.base(), (MPolynomialRing_libsingular, PolynomialRing_field)) and isinstance(base_ring.base().base_ring(), FiniteField_generic): + if not base_ring.base_ring().is_prime_field(): + raise NotImplementedError("Transcental extension are not implemented for non-prime finite fields") + characteristic = int(base_ring.characteristic()) + k = PolynomialRing(base_ring.base_ring(), + names=base_ring.variable_names(), order="lex", implementation="singular") + + ngens = len(k.gens()) + + _ext_names = omAlloc0(ngens*sizeof(char*)) + for i in range(ngens): + _name = str_to_bytes(k._names[i]) + _ext_names[i] = omStrDup(_name) + + _cfr = rDefault( characteristic, ngens, _ext_names ) + rComplete(_cfr, 1) + + trextParam.r = _cfr + + _cf = nInitChar(n_transExt, &trextParam) + + if (_cf is NULL): raise RuntimeError("Failed to allocate _cf ring.") diff --git a/src/sage/libs/singular/singular.pyx b/src/sage/libs/singular/singular.pyx index cb8a1b6aad0..226e225bffb 100644 --- a/src/sage/libs/singular/singular.pyx +++ b/src/sage/libs/singular/singular.pyx @@ -424,6 +424,66 @@ cdef object si2sa_transext_QQ(number *n, ring *_ring, object base): return snumer/sdenom +cdef object si2sa_transext_FF(number *n, ring *_ring, object base): + """ + + + """ + + cdef poly *numer + cdef poly *denom + cdef number *c + cdef int e + cdef fraction *frac + cdef object snumer + cdef object sdenom + + cdef ring *cfRing = _ring.cf.extRing + + if _ring.cf.cfIsZero(n,_ring.cf): + return base._zero_element + elif _ring.cf.cfIsOne(n,_ring.cf): + return base._one_element + + snumer = base(0) + sdenom = base(0) + + frac = n + + numer = frac.numerator + denom = frac.denominator + + while numer: + + + + c = p_GetCoeff(numer, cfRing) + coeff = base(cfRing.cf.cfInt(c, cfRing.cf)) + numer.coef = c + for i in range(base.ngens()): + e = p_GetExp(numer, i+1, cfRing) + if e!= 0: + coeff *= base.gen(i)**e + snumer += coeff + numer = pNext(numer) + + if not denom: + sdenom = base(1) + else: + while denom: + c = p_GetCoeff(denom, cfRing) + coeff = base(cfRing.cf.cfInt(c, cfRing.cf)) + denom.coef = c + for i in range(base.ngens()): + e = p_GetExp(denom, i+1, cfRing) + if e!= 0: + coeff *= base.gen(i)**e + sdenom += coeff + denom = pNext(denom) + + return snumer/sdenom + + cdef object si2sa_NF(number *n, ring *_ring, object base): """ Create a sage element of a number field from a singular one. @@ -939,6 +999,94 @@ cdef number *sa2si_transext_QQ(object elem, ring *_ring): return n1 + +cdef number *sa2si_transext_FF(object elem, ring *_ring): + """ + + + """ + + cdef int i + cdef int j + cdef number *n1 + cdef number *a + cdef number *naCoeff + cdef number *numerator + cdef number *denominator + cdef number *cfnum + cdef number *cfden + cdef number *aux1 + cdef number *aux2 + cdef int ngens + cdef int ex + cdef nMapFunc nMapFuncPtr = NULL; + + if _ring != currRing: + rChangeCurrRing(_ring) + + ngens = elem.parent().ngens() + + nMapFuncPtr = naSetMap(_ring.cf, currRing.cf) # choose correct mapping function + + if (nMapFuncPtr is NULL): + raise RuntimeError("Failed to determine nMapFuncPtr") + + numerdic = elem.numerator().dict() + denomdic = elem.denominator().dict() + + if numerdic and not isinstance(list(numerdic)[0], (tuple, ETuple)): + numerdic = {(k,):b for k,b in numerdic.items()} + + if denomdic and not isinstance(list(denomdic)[0], (tuple, ETuple)): + denomdic = {(k,):b for k,b in denomdic.items()} + + if _ring != currRing: + rChangeCurrRing(_ring) + n1 = _ring.cf.cfInit(0, _ring.cf) + numerator = _ring.cf.cfInit(0, _ring.cf) + for (exponents, coef) in numerdic.items(): + naCoeff = _ring.cf.cfInit(coef, _ring.cf) + for (j, ex) in enumerate(exponents): + a = _ring.cf.cfParameter(j+1, _ring.cf) + for k in range(ex): + aux1 = naCoeff + naCoeff = _ring.cf.cfMult(aux1, a ,_ring.cf) + _ring.cf.cfDelete(&aux1, _ring.cf) + _ring.cf.cfDelete(&a, _ring.cf) + aux2 = numerator + numerator = _ring.cf.cfAdd(aux2, naCoeff,_ring.cf) + _ring.cf.cfDelete(&naCoeff, _ring.cf) + _ring.cf.cfDelete(&aux2, _ring.cf) + + if elem.denominator() != 1: + denominator = _ring.cf.cfInit(0, _ring.cf) + + for (exponents, coef) in denomdic.items(): + naCoeff = _ring.cf.cfInit(coef, _ring.cf) + for (j, ex) in enumerate(exponents): + a = _ring.cf.cfParameter(j+1, _ring.cf) + for k in range(ex): + aux1 = naCoeff + naCoeff = _ring.cf.cfMult(aux1, a ,_ring.cf) + _ring.cf.cfDelete(&aux1, _ring.cf) + _ring.cf.cfDelete(&a, _ring.cf) + aux2 = denominator + denominator = _ring.cf.cfAdd(aux2, naCoeff,_ring.cf) + _ring.cf.cfDelete(&naCoeff, _ring.cf) + _ring.cf.cfDelete(&aux2, _ring.cf) + + else: + denominator = _ring.cf.cfInit(1, _ring.cf) + + n1 = _ring.cf.cfDiv(numerator, denominator, _ring.cf) + + _ring.cf.cfDelete(&numerator, _ring.cf) + _ring.cf.cfDelete(&denominator, _ring.cf) + _ring.cf.cfDelete(&a, _ring.cf) + + return n1 + + cdef number *sa2si_NF(object elem, ring *_ring): """ Create a singular number from a sage element of a number field. @@ -1190,6 +1338,9 @@ cdef object si2sa(number *n, ring *_ring, object base): elif isinstance(base, FractionField_generic) and isinstance(base.base(), (MPolynomialRing_libsingular, PolynomialRing_field)) and isinstance(base.base_ring(), RationalField): return si2sa_transext_QQ(n, _ring, base) + elif isinstance(base, FractionField_generic) and isinstance(base.base(), (MPolynomialRing_libsingular, PolynomialRing_field)) and isinstance(base.base_ring(), FiniteField_prime_modn): + return si2sa_transext_FF(n, _ring, base) + elif isinstance(base, IntegerModRing_generic): if _ring.cf.type == n_unknown: return base(_ring.cf.cfInt(n, _ring.cf)) @@ -1241,6 +1392,9 @@ cdef number *sa2si(Element elem, ring * _ring): elif isinstance(elem._parent, FractionField_generic) and isinstance(elem._parent.base(), (MPolynomialRing_libsingular, PolynomialRing_field)) and isinstance(elem._parent.base().base_ring(), RationalField): return sa2si_transext_QQ(elem, _ring) + elif isinstance(elem._parent, FractionField_generic) and isinstance(elem._parent.base(), (MPolynomialRing_libsingular, PolynomialRing_field)) and isinstance(elem._parent.base().base_ring(), FiniteField_prime_modn): + return sa2si_transext_FF(elem, _ring) + else: raise ValueError("cannot convert to SINGULAR number") From cb3070fd966e4e3f5a6066876693574682625bac Mon Sep 17 00:00:00 2001 From: Miguel Marco Date: Sun, 17 Oct 2021 19:57:01 +0200 Subject: [PATCH 028/126] Add documentation for prime fields --- src/sage/libs/singular/ring.pyx | 23 ++++++++++++ src/sage/libs/singular/singular.pyx | 56 +++++++++++++++++++++++++---- 2 files changed, 73 insertions(+), 6 deletions(-) diff --git a/src/sage/libs/singular/ring.pyx b/src/sage/libs/singular/ring.pyx index 7f6f2d7b22b..78c96e1fc02 100644 --- a/src/sage/libs/singular/ring.pyx +++ b/src/sage/libs/singular/ring.pyx @@ -133,6 +133,10 @@ cdef ring *singular_ring_new(base_ring, n, names, term_order) except NULL: sage: P. = K[]; P Multivariate Polynomial Ring in x, y over Fraction Field of Multivariate Polynomial Ring in s, t over Rational Field + sage: F = PolynomialRing(FiniteField(7),'a,b').fraction_field() + sage: R. = F[] + sage: R + Multivariate Polynomial Ring in x, y, z over Fraction Field of Multivariate Polynomial Ring in a, b over Finite Field of size 7 TESTS: @@ -144,6 +148,25 @@ cdef ring *singular_ring_new(base_ring, n, names, term_order) except NULL: sage: L = [v for d in (0..4) for v in IntegerVectors(d, 4)] sage: sorted([R.monomial(*e) for e in L]) == sorted([S.monomial(*e) for e in L]) True + + Check that we are using the libsingular backend instead of the pexpect one:: + + sage: F = PolynomialRing(FiniteField(7),'a,b').fraction_field() + sage: R. = F[] + sage: from sage.libs.singular.function import singular_function + sage: sing_print = singular_function('print') + sage: sing_print(R) + 'polynomial ring, over a field, global ordering\n// coefficients: ZZ/7(a, b)\n// number of vars : 3\n// block 1 : ordering dp\n// : names x y z\n// block 2 : ordering C' + + :: + + sage: F = PolynomialRing(QQ, 's,t').fraction_field() + sage: R. = F[] + sage: from sage.libs.singular.function import singular_function + sage: sing_print = singular_function('print') + sage: sing_print(R) + 'polynomial ring, over a field, global ordering\n// coefficients: QQ(s, t)\n// number of vars : 3\n// block 1 : ordering dp\n// : names x y z\n// block 2 : ordering C' + """ cdef long cexponent cdef GFInfo* _param diff --git a/src/sage/libs/singular/singular.pyx b/src/sage/libs/singular/singular.pyx index 226e225bffb..ca37b9c590d 100644 --- a/src/sage/libs/singular/singular.pyx +++ b/src/sage/libs/singular/singular.pyx @@ -426,7 +426,32 @@ cdef object si2sa_transext_QQ(number *n, ring *_ring, object base): cdef object si2sa_transext_FF(number *n, ring *_ring, object base): """ + Create a sage element of a transcendental extension of a prime field from a + singular one. + + INPUT: + + - ``n`` - a (pointer to) a singular number in a transcendental extension + of the rationals + + - ``_ ring`` - a (pointer to) a singular ring, in whose coefficient field + lives ``n`` + + - ``base`` - A sage FractionField + OUTPUT: + + - A sage element of ``base`` + + TESTS:: + + sage: F = PolynomialRing(FiniteField(7),'a,b').fraction_field() + sage: R. = F[] + sage: n = R(5) + sage: n + -2 + sage: type(n) + """ @@ -907,7 +932,6 @@ cdef number *sa2si_transext_QQ(object elem, ring *_ring): """ - cdef int i cdef int j cdef number *n1 cdef number *a @@ -1002,19 +1026,40 @@ cdef number *sa2si_transext_QQ(object elem, ring *_ring): cdef number *sa2si_transext_FF(object elem, ring *_ring): """ + Create a singular number from a sage element of a transcendental extension + of a prime field. + INPUT: - """ + - ``elem`` - a sage element of a FractionField of polynomials over the rationals - cdef int i + - ``_ ring`` - a (pointer to) a singular ring, where the resul will live + + + OUTPUT: + + - A (pointer to) a singular number + + + TESTS:: + + sage: F = PolynomialRing(FiniteField(7),'a,b').fraction_field() + sage: R. = F[] + sage: n = R(5) + sage: n + n + 3 + sage: Integer(n) + 5 + + + + """ cdef int j cdef number *n1 cdef number *a cdef number *naCoeff cdef number *numerator cdef number *denominator - cdef number *cfnum - cdef number *cfden cdef number *aux1 cdef number *aux2 cdef int ngens @@ -1042,7 +1087,6 @@ cdef number *sa2si_transext_FF(object elem, ring *_ring): if _ring != currRing: rChangeCurrRing(_ring) - n1 = _ring.cf.cfInit(0, _ring.cf) numerator = _ring.cf.cfInit(0, _ring.cf) for (exponents, coef) in numerdic.items(): naCoeff = _ring.cf.cfInit(coef, _ring.cf) From 5555f49c32a1c39141e298bc438983140037681e Mon Sep 17 00:00:00 2001 From: Miguel Marco Date: Sun, 17 Oct 2021 20:29:45 +0200 Subject: [PATCH 029/126] Fix doctests for prime fields --- src/sage/schemes/plane_conics/con_field.py | 15 ++++++++------- .../plane_conics/con_rational_function_field.py | 13 +++++++------ 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/sage/schemes/plane_conics/con_field.py b/src/sage/schemes/plane_conics/con_field.py index 5ecce3b3168..def754a202f 100644 --- a/src/sage/schemes/plane_conics/con_field.py +++ b/src/sage/schemes/plane_conics/con_field.py @@ -199,7 +199,7 @@ def derivative_matrix(self): sage: P. = GF(2)[] sage: c = Conic([t, 1, t^2, 1, 1, 0]); c - Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 2 (using GF2X) defined by t*x^2 + x*y + y^2 + t^2*x*z + y*z + Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 2 (using GF2X) defined by t*x^2 + x*y + y^2 + (t^2)*x*z + y*z sage: c.is_smooth() True sage: c.derivative_matrix() @@ -340,18 +340,19 @@ def diagonalization(self, names=None): sage: (t,) = K.gens() sage: C = Conic(K, [t/2,0, 1, 2, 0, 3]) sage: C.diagonalization() - (Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by 4*t*x^2 + 2*y^2 + ((3*t + 3)/t)*z^2, + (Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by (-3*t)*x^2 + 2*y^2 + (3*t + 3)/t*z^2, Scheme morphism: - From: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by 4*t*x^2 + 2*y^2 + ((3*t + 3)/t)*z^2 - To: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by 4*t*x^2 + 2*y^2 + x*z + 3*z^2 + From: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by (-3*t)*x^2 + 2*y^2 + (3*t + 3)/t*z^2 + To: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by (-3*t)*x^2 + 2*y^2 + x*z + 3*z^2 Defn: Defined on coordinates by sending (x : y : z) to - (x + 6/t*z : y : z), + (x - 1/t*z : y : z), Scheme morphism: - From: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by 4*t*x^2 + 2*y^2 + x*z + 3*z^2 - To: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by 4*t*x^2 + 2*y^2 + ((3*t + 3)/t)*z^2 + From: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by (-3*t)*x^2 + 2*y^2 + x*z + 3*z^2 + To: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by (-3*t)*x^2 + 2*y^2 + (3*t + 3)/t*z^2 Defn: Defined on coordinates by sending (x : y : z) to (x + 1/t*z : y : z)) + """ if names is None: names = self.defining_polynomial().parent().variable_names() diff --git a/src/sage/schemes/plane_conics/con_rational_function_field.py b/src/sage/schemes/plane_conics/con_rational_function_field.py index 154201f2cb2..383802d75a8 100644 --- a/src/sage/schemes/plane_conics/con_rational_function_field.py +++ b/src/sage/schemes/plane_conics/con_rational_function_field.py @@ -203,14 +203,15 @@ def has_rational_point(self, point=False, algorithm='default', Traceback (most recent call last): ... TypeError: self (=Scheme morphism: - From: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by (5*t^2 + 4)*x^2 + ((6*t^3 + 3*t^2 + 5*t + 5)/(t + 3))*y^2 + ((6*t^6 + 3*t^5 + t^3 + 6*t^2 + 6*t + 2)/(t^4 + t^3 + 4*t^2 + 3*t + 1))*z^2 - To: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by (5*t^2 + 4)*x^2 + (t^2 + 3*t + 3)*x*y + (5*t^2 + 5)*y^2 + (6*t^2 + 3*t + 2)*x*z + (4*t + 3)*y*z + (4*t^2 + t + 5)*z^2 + From: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by (-2*t^2 - 3)*x^2 + (-t^3 + 3*t^2 - 2*t - 2)/(t + 3)*y^2 + (-t^6 + 3*t^5 + t^3 - t^2 - t + 2)/(t^4 + t^3 - 3*t^2 + 3*t + 1)*z^2 + To: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by (-2*t^2 - 3)*x^2 + (t^2 + 3*t + 3)*x*y + (-2*t^2 - 2)*y^2 + (-t^2 + 3*t + 2)*x*z + (-3*t + 3)*y*z + (-3*t^2 + t - 2)*z^2 Defn: Defined on coordinates by sending (x : y : z) to - (x + ((2*t + 5)/(t + 3))*y + ((3*t^4 + 2*t^3 + 5*t^2 + 5*t + 3)/(t^4 + t^3 + 4*t^2 + 3*t + 1))*z : y + ((6*t^3 + 6*t^2 + 3*t + 6)/(t^3 + 4*t^2 + 2*t + 2))*z : z)) domain must equal right (=Scheme morphism: - From: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by (5*t^3 + 6*t^2 + 3*t + 3)*x^2 + (t + 4)*y^2 + (6*t^7 + 2*t^5 + t^4 + 2*t^3 + 3*t^2 + 6*t + 6)*z^2 - To: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by (5/(t^3 + 4*t^2 + 2*t + 2))*x^2 + (1/(t^3 + 3*t^2 + 5*t + 1))*y^2 + ((6*t^6 + 3*t^5 + t^3 + 6*t^2 + 6*t + 2)/(t^9 + 5*t^8 + t^7 + 6*t^6 + 3*t^5 + 4*t^3 + t^2 + 5*t + 3))*z^2 + (x + (2*t - 2)/(t + 3)*y + (3*t^4 + 2*t^3 - 2*t^2 - 2*t + 3)/(t^4 + t^3 - 3*t^2 + 3*t + 1)*z : y + (-t^3 - t^2 + 3*t - 1)/(t^3 - 3*t^2 + 2*t + 2)*z : z)) domain must equal right (=Scheme morphism: + From: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by (-2*t^3 - t^2 + 3*t + 3)*x^2 + (t - 3)*y^2 + (-t^7 + 2*t^5 + t^4 + 2*t^3 + 3*t^2 - t - 1)*z^2 + To: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by -2/(t^3 - 3*t^2 + 2*t + 2)*x^2 + 1/(t^3 + 3*t^2 - 2*t + 1)*y^2 + (-t^6 + 3*t^5 + t^3 - t^2 - t + 2)/(t^9 - 2*t^8 + t^7 - t^6 + 3*t^5 - 3*t^3 + t^2 - 2*t + 3)*z^2 Defn: Defined on coordinates by sending (x : y : z) to - ((t^3 + 4*t^2 + 2*t + 2)*x : (t^2 + 5)*y : (t^5 + 4*t^4 + t^2 + 3*t + 3)*z)) codomain + ((t^3 - 3*t^2 + 2*t + 2)*x : (t^2 - 2)*y : (t^5 - 3*t^4 + t^2 + 3*t + 3)*z)) codomain + TESTS:: From ecbcaf963d53e0e0e80822b98c20ec4e22007401 Mon Sep 17 00:00:00 2001 From: Miguel Marco Date: Mon, 18 Oct 2021 21:42:54 +0200 Subject: [PATCH 030/126] Use cfPower instead of repeated multiplications --- src/sage/libs/singular/singular.pyx | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/sage/libs/singular/singular.pyx b/src/sage/libs/singular/singular.pyx index ca37b9c590d..6c6c907359c 100644 --- a/src/sage/libs/singular/singular.pyx +++ b/src/sage/libs/singular/singular.pyx @@ -942,6 +942,7 @@ cdef number *sa2si_transext_QQ(object elem, ring *_ring): cdef number *cfden cdef number *aux1 cdef number *aux2 + cdef number *power cdef int ngens cdef int ex cdef nMapFunc nMapFuncPtr = NULL; @@ -974,16 +975,17 @@ cdef number *sa2si_transext_QQ(object elem, ring *_ring): cfnum = _ring.cf.cfInitMPZ((numer).value, _ring.cf) denom = coef.denominator() cfden = _ring.cf.cfInitMPZ((denom).value, _ring.cf) - naCoeff = _ring.cf.cfDiv(cfnum, cfden , _ring.cf ) + naCoeff = _ring.cf.cfDiv(cfnum, cfden, _ring.cf) _ring.cf.cfDelete(&cfnum, _ring.cf) _ring.cf.cfDelete(&cfden, _ring.cf) for (j, ex) in enumerate(exponents): a = _ring.cf.cfParameter(j+1, _ring.cf) - for k in range(ex): - aux1 = naCoeff - naCoeff = _ring.cf.cfMult(aux1, a ,_ring.cf) - _ring.cf.cfDelete(&aux1, _ring.cf) + _ring.cf.cfPower(a, ex, &power, _ring.cf) + aux1 = naCoeff + naCoeff = _ring.cf.cfMult(aux1, power, _ring.cf) + _ring.cf.cfDelete(&aux1, _ring.cf) _ring.cf.cfDelete(&a, _ring.cf) + _ring.cf.cfDelete(&power, _ring.cf) aux2 = numerator numerator = _ring.cf.cfAdd(aux2, naCoeff,_ring.cf) _ring.cf.cfDelete(&aux2, _ring.cf) @@ -996,16 +998,17 @@ cdef number *sa2si_transext_QQ(object elem, ring *_ring): cfnum = _ring.cf.cfInitMPZ((numer).value, _ring.cf) denom = coef.denominator() cfden = _ring.cf.cfInitMPZ((denom).value, _ring.cf) - naCoeff = _ring.cf.cfDiv(cfnum, cfden , _ring.cf ) + naCoeff = _ring.cf.cfDiv(cfnum, cfden, _ring.cf) _ring.cf.cfDelete(&cfnum, _ring.cf) _ring.cf.cfDelete(&cfden, _ring.cf) for (j, ex) in enumerate(exponents): a = _ring.cf.cfParameter(j+1, _ring.cf) - for k in range(ex): - aux1 = naCoeff - naCoeff = _ring.cf.cfMult(aux1, a ,_ring.cf) - _ring.cf.cfDelete(&aux1, _ring.cf) + _ring.cf.cfPower(a, ex, &power, _ring.cf) + aux1 = naCoeff + naCoeff = _ring.cf.cfMult(aux1, power, _ring.cf) + _ring.cf.cfDelete(&aux1, _ring.cf) _ring.cf.cfDelete(&a, _ring.cf) + _ring.cf.cfDelete(&power, _ring.cf) aux2 = denominator denominator = _ring.cf.cfAdd(aux2, naCoeff,_ring.cf) _ring.cf.cfDelete(&aux2, _ring.cf) From b9b1dba57d85ea7d6f68471024406a939579b5bb Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Mon, 18 Oct 2021 22:36:14 +0200 Subject: [PATCH 031/126] Enable editable mode also for other sage packages --- build/bin/sage-dist-helpers | 5 +++++ build/pkgs/sage_conf/spkg-install | 7 ++++++- build/pkgs/sage_docbuild/spkg-install | 7 ++++++- build/pkgs/sage_setup/spkg-install | 7 ++++++- build/pkgs/sagelib/spkg-install | 2 +- src/doc/en/developer/packaging.rst | 7 +++++++ 6 files changed, 31 insertions(+), 4 deletions(-) diff --git a/build/bin/sage-dist-helpers b/build/bin/sage-dist-helpers index 4a8862d50f6..7bee8527f89 100644 --- a/build/bin/sage-dist-helpers +++ b/build/bin/sage-dist-helpers @@ -246,6 +246,11 @@ sdh_pip_install() { sdh_store_and_pip_install_wheel . } +sdh_pip_editable_install() { + echo "Installing $PKG_NAME (editable mode)" + python3 -m pip install --verbose --no-deps --no-index --no-build-isolation --isolated --editable "$@" +} + sdh_store_wheel() { if [ -n "$SAGE_DESTDIR" ]; then local sudo="" diff --git a/build/pkgs/sage_conf/spkg-install b/build/pkgs/sage_conf/spkg-install index 468970ba085..e572d89f80d 100755 --- a/build/pkgs/sage_conf/spkg-install +++ b/build/pkgs/sage_conf/spkg-install @@ -9,4 +9,9 @@ if [ $? -ne 0 ]; then echo >&2 "Is $SAGE_ROOT the correct SAGE_ROOT?" exit 1 fi -cd src && sdh_pip_install . +cd src +if [ "$SAGE_EDITABLE" = yes ]; then + sdh_pip_editable_install . +else + sdh_pip_install . +fi diff --git a/build/pkgs/sage_docbuild/spkg-install b/build/pkgs/sage_docbuild/spkg-install index ea7a36674d7..1bb66bc4a07 100755 --- a/build/pkgs/sage_docbuild/spkg-install +++ b/build/pkgs/sage_docbuild/spkg-install @@ -9,4 +9,9 @@ if [ $? -ne 0 ]; then echo >&2 "Is $SAGE_ROOT the correct SAGE_ROOT?" exit 1 fi -cd src && sdh_pip_install . +cd src +if [ "$SAGE_EDITABLE" = yes ]; then + sdh_pip_editable_install . +else + sdh_pip_install . +fi diff --git a/build/pkgs/sage_setup/spkg-install b/build/pkgs/sage_setup/spkg-install index ea7a36674d7..1bb66bc4a07 100755 --- a/build/pkgs/sage_setup/spkg-install +++ b/build/pkgs/sage_setup/spkg-install @@ -9,4 +9,9 @@ if [ $? -ne 0 ]; then echo >&2 "Is $SAGE_ROOT the correct SAGE_ROOT?" exit 1 fi -cd src && sdh_pip_install . +cd src +if [ "$SAGE_EDITABLE" = yes ]; then + sdh_pip_editable_install . +else + sdh_pip_install . +fi diff --git a/build/pkgs/sagelib/spkg-install b/build/pkgs/sagelib/spkg-install index 76a306e5762..050af61a140 100755 --- a/build/pkgs/sagelib/spkg-install +++ b/build/pkgs/sagelib/spkg-install @@ -49,7 +49,7 @@ if [ "$SAGE_EDITABLE" = yes ]; then # and renamed the distribution to "sagemath-standard"). There is no clean way to uninstall # them, so we just use rm. (cd "$SITEPACKAGESDIR" && rm -rf sage sage_setup sage-[1-9]*.egg-info sage-[1-9]*.dist-info) - time python3 -m pip install --verbose --no-deps --no-index --no-build-isolation --isolated --editable . || exit 1 + time sdh_pip_editable_install . || exit 1 else # Likewise, we should remove the egg-link that may have been installed previously. (cd "$SITEPACKAGESDIR" && rm -f sagemath-standard.egg-link) diff --git a/src/doc/en/developer/packaging.rst b/src/doc/en/developer/packaging.rst index 498825377c5..122282af80e 100644 --- a/src/doc/en/developer/packaging.rst +++ b/src/doc/en/developer/packaging.rst @@ -411,6 +411,13 @@ begin with ``sdh_``, which stands for "Sage-distribution helper". creating a wheel file in ``dist/``, followed by ``sdh_store_and_pip_install_wheel`` (see below). +- ``sdh_pip_editable_install [...]``: The equivalent of running ``pip install -e`` + with the given arguments, as well as additional default arguments used for + installing packages into Sage with pip. The last argument must be + ``.`` to indicate installation from the current directory. + See `pip documentation `_ + for more details concerning editable installs. + - ``sdh_pip_uninstall [...]``: Runs ``pip uninstall`` with the given arguments. If unsuccessful, it displays a warning. From a257621c3b3aa7e4d245a691dffbc67e6e45f08b Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Tue, 19 Oct 2021 01:17:35 +0200 Subject: [PATCH 032/126] Add error handling --- build/bin/sage-dist-helpers | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build/bin/sage-dist-helpers b/build/bin/sage-dist-helpers index 7bee8527f89..84af795c901 100644 --- a/build/bin/sage-dist-helpers +++ b/build/bin/sage-dist-helpers @@ -248,7 +248,8 @@ sdh_pip_install() { sdh_pip_editable_install() { echo "Installing $PKG_NAME (editable mode)" - python3 -m pip install --verbose --no-deps --no-index --no-build-isolation --isolated --editable "$@" + python3 -m pip install --verbose --no-deps --no-index --no-build-isolation --isolated --editable "$@" || \ + sdh_die "Error installing $PKG_NAME" } sdh_store_wheel() { From 6644879d4af587e06c261dfe7601f0ca71134bc7 Mon Sep 17 00:00:00 2001 From: Kwankyu Lee Date: Wed, 13 Oct 2021 13:44:06 +0900 Subject: [PATCH 033/126] Place get converted to a prime divisor --- src/sage/coding/ag_code.py | 102 +++++++++++++++---------- src/sage/coding/ag_code_decoders.pyx | 22 +++--- src/sage/rings/function_field/place.py | 15 +++- 3 files changed, 86 insertions(+), 53 deletions(-) diff --git a/src/sage/coding/ag_code.py b/src/sage/coding/ag_code.py index 9b12c412f18..72bf5c37d5f 100644 --- a/src/sage/coding/ag_code.py +++ b/src/sage/coding/ag_code.py @@ -8,8 +8,8 @@ EXAMPLES:: - sage: F. = GF(4) - sage: P. = AffineSpace(F, 2); + sage: k. = GF(4) + sage: A. = AffineSpace(k, 2) sage: C = Curve(y^2 + y - x^3) sage: F = C.function_field() sage: pls = F.places() @@ -72,6 +72,7 @@ from sage.modules.free_module_element import vector from sage.matrix.constructor import matrix from sage.matrix.matrix_space import MatrixSpace +from sage.rings.function_field.place import FunctionFieldPlace from .linear_code import (AbstractLinearCode, LinearCodeGeneratorMatrixEncoder, @@ -97,8 +98,8 @@ def base_function_field(self): EXAMPLES:: - sage: F. = GF(4) - sage: P. = AffineSpace(F, 2); + sage: k. = GF(4) + sage: A. = AffineSpace(k, 2) sage: C = Curve(y^2 + y - x^3) sage: F = C.function_field() sage: pls = F.places() @@ -123,10 +124,12 @@ class EvaluationAGCode(AGCode): - ``G`` -- a divisor whose support is disjoint from ``pls`` + If ``G`` is a place, then it is regarded as a prime divisor. + EXAMPLES:: - sage: F. = GF(4) - sage: P. = AffineSpace(F, 2); + sage: k. = GF(4) + sage: A. = AffineSpace(k, 2) sage: C = Curve(y^2 + y - x^3) sage: F = C.function_field() sage: pls = F.places() @@ -135,6 +138,10 @@ class EvaluationAGCode(AGCode): sage: G = 5*Q sage: codes.EvaluationAGCode(pls, G) [8, 5] evaluation AG code over GF(4) + + sage: G = F.get_place(5) + sage: codes.EvaluationAGCode(pls, G) + [8, 5] evaluation AG code over GF(4) """ _registered_encoders = {} _registered_decoders = {} @@ -145,8 +152,8 @@ def __init__(self, pls, G): TESTS:: - sage: F. = GF(4) - sage: P. = AffineSpace(F, 2); + sage: k. = GF(4) + sage: A. = AffineSpace(k, 2) sage: C = Curve(y^2 + y - x^3) sage: F = C.function_field() sage: pls = F.places() @@ -156,6 +163,9 @@ def __init__(self, pls, G): sage: code = codes.EvaluationAGCode(pls, G) sage: TestSuite(code).run() """ + if issubclass(type(G), FunctionFieldPlace): + G = G.divisor() # place is converted to a prime divisor + F = G.parent().function_field() K = F.constant_base_field() n = len(pls) @@ -197,8 +207,8 @@ def __eq__(self, other): EXAMPLES:: - sage: F. = GF(4) - sage: P. = AffineSpace(F, 2); + sage: k. = GF(4) + sage: A. = AffineSpace(k, 2) sage: C = Curve(y^2 + y - x^3) sage: F = C.function_field() sage: pls = F.places() @@ -221,8 +231,8 @@ def __hash__(self): EXAMPLES:: - sage: F. = GF(4) - sage: P. = AffineSpace(F, 2); + sage: k. = GF(4) + sage: A. = AffineSpace(k, 2) sage: C = Curve(y^2 + y - x^3) sage: F = C.function_field() sage: pls = F.places() @@ -240,8 +250,8 @@ def _repr_(self): EXAMPLES:: - sage: F. = GF(4) - sage: P. = AffineSpace(F, 2); + sage: k. = GF(4) + sage: A. = AffineSpace(k, 2) sage: C = Curve(y^2 + y - x^3) sage: F = C.function_field() sage: pls = F.places() @@ -259,8 +269,8 @@ def _latex_(self): EXAMPLES:: - sage: F. = GF(4) - sage: P. = AffineSpace(F, 2); + sage: k. = GF(4) + sage: A. = AffineSpace(k, 2) sage: C = Curve(y^2 + y - x^3) sage: F = C.function_field() sage: pls = F.places() @@ -279,8 +289,8 @@ def basis_functions(self): EXAMPLES:: - sage: F. = GF(4) - sage: P. = AffineSpace(F, 2); + sage: k. = GF(4) + sage: A. = AffineSpace(k, 2) sage: C = Curve(y^2 + y - x^3) sage: F = C.function_field() sage: pls = F.places() @@ -302,8 +312,8 @@ def generator_matrix(self): EXAMPLES:: - sage: F. = GF(4) - sage: P. = AffineSpace(F, 2); + sage: k. = GF(4) + sage: A. = AffineSpace(k, 2) sage: C = Curve(y^2 + y - x^3) sage: F = C.function_field() sage: pls = F.places() @@ -325,8 +335,8 @@ def designed_distance(self): EXAMPLES:: - sage: F. = GF(4) - sage: P. = AffineSpace(F, 2); + sage: k. = GF(4) + sage: A. = AffineSpace(k, 2) sage: C = Curve(y^2 + y - x^3) sage: F = C.function_field() sage: pls = F.places() @@ -353,17 +363,24 @@ class DifferentialAGCode(AGCode): - ``G`` -- a divisor whose support is disjoint from ``pls`` + If ``G`` is a place, then it is regarded as a prime divisor. + EXAMPLES:: - sage: F. = GF(4) - sage: A2. = AffineSpace(F, 2) - sage: C = A2.curve(y^3 + y - x^4) + sage: k. = GF(4) + sage: A. = AffineSpace(k, 2) + sage: C = A.curve(y^3 + y - x^4) sage: Q = C.places_at_infinity()[0] sage: O = C([0,0]).place() sage: pls = [p for p in C.places() if p not in [O, Q]] sage: G = -O + 3*Q sage: codes.DifferentialAGCode(pls, -O + Q) [3, 2] differential AG code over GF(4) + + sage: F = C.function_field() + sage: G = F.get_place(1) + sage: codes.DifferentialAGCode(pls, G) + [3, 1] differential AG code over GF(4) """ _registered_encoders = {} _registered_decoders = {} @@ -374,8 +391,8 @@ def __init__(self, pls, G): TESTS:: - sage: F. = GF(4) - sage: P. = AffineSpace(F, 2); + sage: k. = GF(4) + sage: A. = AffineSpace(k, 2) sage: C = Curve(y^2 + y - x^3) sage: F = C.function_field() sage: pls = F.places() @@ -384,6 +401,9 @@ def __init__(self, pls, G): sage: code = codes.DifferentialAGCode(pls, 3*Q) sage: TestSuite(code).run() """ + if issubclass(type(G), FunctionFieldPlace): + G = G.divisor() # place is converted to a prime divisor + F = G.parent().function_field() K = F.constant_base_field() n = len(pls) @@ -424,8 +444,8 @@ def __eq__(self, other): EXAMPLES:: - sage: F. = GF(4) - sage: P. = AffineSpace(F, 2); + sage: k. = GF(4) + sage: A. = AffineSpace(k, 2) sage: C = Curve(y^2 + y - x^3) sage: F = C.function_field() sage: pls = F.places() @@ -452,8 +472,8 @@ def __hash__(self): EXAMPLES:: - sage: F. = GF(4) - sage: P. = AffineSpace(F, 2); + sage: k. = GF(4) + sage: A. = AffineSpace(k, 2) sage: C = Curve(y^2 + y - x^3) sage: F = C.function_field() sage: pls = F.places() @@ -471,8 +491,8 @@ def _repr_(self): EXAMPLES:: - sage: F. = GF(4) - sage: P. = AffineSpace(F, 2); + sage: k. = GF(4) + sage: A. = AffineSpace(k, 2) sage: C = Curve(y^2 + y - x^3) sage: F = C.function_field() sage: pls = F.places() @@ -490,8 +510,8 @@ def _latex_(self): EXAMPLES:: - sage: F. = GF(4) - sage: P. = AffineSpace(F, 2); + sage: k. = GF(4) + sage: A. = AffineSpace(k, 2) sage: C = Curve(y^2 + y - x^3) sage: F = C.function_field() sage: pls = F.places() @@ -510,8 +530,8 @@ def basis_differentials(self): EXAMPLES:: - sage: F. = GF(4) - sage: P. = AffineSpace(F, 2); + sage: k. = GF(4) + sage: A. = AffineSpace(k, 2) sage: C = Curve(y^2 + y - x^3) sage: F = C.function_field() sage: pls = F.places() @@ -533,8 +553,8 @@ def generator_matrix(self): EXAMPLES:: - sage: F. = GF(4) - sage: P. = AffineSpace(F, 2); + sage: k. = GF(4) + sage: A. = AffineSpace(k, 2) sage: C = Curve(y^2 + y - x^3) sage: F = C.function_field() sage: pls = F.places() @@ -558,8 +578,8 @@ def designed_distance(self): EXAMPLES:: - sage: F. = GF(4) - sage: P. = AffineSpace(F, 2); + sage: k. = GF(4) + sage: A. = AffineSpace(k, 2) sage: C = Curve(y^2 + y - x^3) sage: F = C.function_field() sage: pls = F.places() diff --git a/src/sage/coding/ag_code_decoders.pyx b/src/sage/coding/ag_code_decoders.pyx index 4a9771f221b..8d28e242030 100644 --- a/src/sage/coding/ag_code_decoders.pyx +++ b/src/sage/coding/ag_code_decoders.pyx @@ -19,27 +19,27 @@ EXAMPLES:: sage: pls.remove(O) sage: G = -O + 18*Q sage: code = codes.EvaluationAGCode(pls, G) # long time - sage: code # long time + sage: code # long time [26, 15] evaluation AG code over GF(9) - sage: decoder = code.decoder('K') # long time - sage: tau = decoder.decoding_radius() # long time - sage: tau # long time + sage: decoder = code.decoder('K') # long time + sage: tau = decoder.decoding_radius() # long time + sage: tau # long time 4 The ``decoder`` is now ready for correcting vectors received from a noisy channel:: sage: channel = channels.StaticErrorRateChannel(code.ambient_space(), tau) # long time - sage: message_space = decoder.message_space() # long time - sage: message = message_space.random_element() # long time - sage: encoder = decoder.connected_encoder() # long time - sage: sent_codeword = encoder.encode(message) # long time - sage: received_vector = channel(sent_codeword) # long time - sage: (received_vector - sent_codeword).hamming_weight() # long time + sage: message_space = decoder.message_space() # long time + sage: message = message_space.random_element() # long time + sage: encoder = decoder.connected_encoder() # long time + sage: sent_codeword = encoder.encode(message) # long time + sage: received_vector = channel(sent_codeword) # long time + sage: (received_vector - sent_codeword).hamming_weight() # long time 4 sage: decoder.decode_to_code(received_vector) == sent_codeword # long time True - sage: decoder.decode_to_message(received_vector) == message # long time + sage: decoder.decode_to_message(received_vector) == message # long time True AUTHORS: diff --git a/src/sage/rings/function_field/place.py b/src/sage/rings/function_field/place.py index 43abc67a6fb..3173eee1cbf 100644 --- a/src/sage/rings/function_field/place.py +++ b/src/sage/rings/function_field/place.py @@ -81,7 +81,7 @@ class FunctionFieldPlace(Element): INPUT: - - ``field`` -- function field + - ``parent`` -- place set of a function field - ``prime`` -- prime ideal associated with the place @@ -1188,3 +1188,16 @@ def _an_element_(self): break return p + def function_field(self): + """ + Return the function field to which this place set belongs. + + EXAMPLES:: + + sage: K.=FunctionField(GF(2)); _.=K[] + sage: L.=K.extension(Y^3+x+x^3*Y) + sage: PS = L.place_set() + sage: PS.function_field() == L + True + """ + return self._field From 50a4554dd05e50e5f11609504ce6eba0e93e34a5 Mon Sep 17 00:00:00 2001 From: Kwankyu Lee Date: Thu, 14 Oct 2021 14:39:01 +0900 Subject: [PATCH 034/126] Fix typos --- src/sage/rings/function_field/place.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/rings/function_field/place.py b/src/sage/rings/function_field/place.py index 3173eee1cbf..4b8c9d6f588 100644 --- a/src/sage/rings/function_field/place.py +++ b/src/sage/rings/function_field/place.py @@ -1194,8 +1194,8 @@ def function_field(self): EXAMPLES:: - sage: K.=FunctionField(GF(2)); _.=K[] - sage: L.=K.extension(Y^3+x+x^3*Y) + sage: K. = FunctionField(GF(2)); _. = K[] + sage: L. = K.extension(Y^3 + x + x^3*Y) sage: PS = L.place_set() sage: PS.function_field() == L True From bc435b3e26a1c68fb2f04c09eb6f3d6e87115000 Mon Sep 17 00:00:00 2001 From: Jonathan Kliem Date: Mon, 25 Oct 2021 08:28:36 +0200 Subject: [PATCH 035/126] pick up environment variable for random seed --- src/bin/sage-runtests | 3 ++- src/doc/en/developer/doctesting.rst | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/bin/sage-runtests b/src/bin/sage-runtests index d7a416185f8..25c884a553f 100755 --- a/src/bin/sage-runtests +++ b/src/bin/sage-runtests @@ -56,7 +56,8 @@ if __name__ == "__main__": 'if "build" is listed, will also run tests specific to Sage\'s build/packaging system; ' 'if set to "all", then all tests will be run') parser.add_argument("--randorder", type=int, metavar="SEED", help="randomize order of tests") - parser.add_argument("--random-seed", dest="random_seed", type=int, metavar="SEED", help="random seed (integer) for fuzzing doctests") + parser.add_argument("--random-seed", dest="random_seed", type=int, metavar="SEED", help="random seed (integer) for fuzzing doctests", + default=os.environ.get("SAGE_DOCTEST_RANDOM_SEED")) parser.add_argument("--global-iterations", "--global_iterations", type=int, default=0, help="repeat the whole testing process this many times") parser.add_argument("--file-iterations", "--file_iterations", type=int, default=0, help="repeat each file this many times, stopping on the first failure") parser.add_argument("--environment", type=str, default="sage.repl.ipython_kernel.all_jupyter", help="name of a module that provides the global environment for tests") diff --git a/src/doc/en/developer/doctesting.rst b/src/doc/en/developer/doctesting.rst index e26d7329095..7b8aa79554a 100644 --- a/src/doc/en/developer/doctesting.rst +++ b/src/doc/en/developer/doctesting.rst @@ -855,6 +855,9 @@ This seed can be set explicitly to reproduce possible failures:: cpu time: 0.0 seconds cumulative wall time: 0.0 seconds +It can also be set explicitly using the environment variable +``SAGE_DOCTEST_RANDOM_SEED``. + .. _section-optional-doctest-flag: Run Optional Doctests From a61c244c3780d0ae1a88f8aafd557ba65407ad2d Mon Sep 17 00:00:00 2001 From: Jonathan Kliem Date: Mon, 25 Oct 2021 15:58:48 +0200 Subject: [PATCH 036/126] increase tolerance for doctests in modular/modform/numerical.py --- src/sage/modular/modform/numerical.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/sage/modular/modform/numerical.py b/src/sage/modular/modform/numerical.py index f09aca90239..056f5ad88f1 100644 --- a/src/sage/modular/modform/numerical.py +++ b/src/sage/modular/modform/numerical.py @@ -71,21 +71,21 @@ class NumericalEigenforms(SageObject): sage: n = numerical_eigenforms(23) sage: n == loads(dumps(n)) True - sage: n.ap(2) # rel tol 2e-14 + sage: n.ap(2) # abs tol 1e-12 [3.0, -1.6180339887498947, 0.6180339887498968] - sage: n.systems_of_eigenvalues(7) # rel tol 2e-14 + sage: n.systems_of_eigenvalues(7) # abs tol 2e-12 [ [-1.6180339887498947, 2.2360679774997894, -3.2360679774997894], [0.6180339887498968, -2.236067977499788, 1.2360679774997936], [3.0, 4.0, 6.0] ] - sage: n.systems_of_abs(7) + sage: n.systems_of_abs(7) # abs tol 2e-12 [ - [0.6180339887..., 2.236067977..., 1.236067977...], - [1.6180339887..., 2.236067977..., 3.236067977...], + [0.6180339887498943, 2.2360679774997894, 1.2360679774997887], + [1.6180339887498947, 2.23606797749979, 3.2360679774997894], [3.0, 4.0, 6.0] ] - sage: n.eigenvalues([2,3,5]) # rel tol 2e-14 + sage: n.eigenvalues([2,3,5]) # rel tol 2e-12 [[3.0, -1.6180339887498947, 0.6180339887498968], [4.0, 2.2360679774997894, -2.236067977499788], [6.0, -3.2360679774997894, 1.2360679774997936]] From 0505175110576f1f333675f996c874f4d905de4f Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 25 Oct 2021 09:24:55 -0700 Subject: [PATCH 037/126] tox.ini: Reduce envlist to a few platforms for 'tox -p auto' --- tox.ini | 106 ++++++++++++++++++++++++++++++++------------------------ 1 file changed, 61 insertions(+), 45 deletions(-) diff --git a/tox.ini b/tox.ini index 8c5301eb28e..69c79015727 100644 --- a/tox.ini +++ b/tox.ini @@ -1,3 +1,6 @@ +# SAGE_ROOT/tox.ini: Environments for testing the Sage distribution +# + # Run a specific environment: # tox -e docker-fedora-31 # Run all in parallel: @@ -5,35 +8,53 @@ # with local squid: # EXTRA_DOCKER_BUILD_ARGS="--build-arg http_proxy=http://host.docker.internal:3128 --build-arg https_proxy=http://host.docker.internal:3128" tox -p auto [tox] -### Test that the system packages listed in debian.txt/fedora.txt files of standard spkg exist -### and satisfy the requirements tested by spkg-configure.m4, then compile a few packages. -### + envlist = - ##### Delegation to src/tox.ini ##### - doctest, coverage, startuptime, pycodestyle-minimal, relint, codespell, - ##### Sage-the-distribution tests ##### + + ##### + ##### Delegation to src/tox.ini + ##### + + # Included on tox -p auto + doctest, + coverage, + startuptime, + pycodestyle-minimal, + relint, + codespell, + + # Also available: + #pycodestyle + + ##### + ##### Sage-the-distribution tests + ##### + check_configure, - ##### Sage-the-distribution portability tests ##### - { - { - ### "docker" toxenvs copy sources from the source tree subject to the exclusions in + + ##### + ##### Sage-the-distribution portability tests + ##### + + # See https://doc.sagemath.org/html/en/developer/portability_testing.html + + ### "docker" environments copy sources from the source tree subject to the exclusions in ### the file ".dockerignore". This should work out of non-clean source trees, and all ### "docker" toxenvs can be run in parallel. - docker-{ubuntu-{trusty,xenial,bionic,latest,rolling,focal,devel}, - debian-{jessie,stretch,buster,bullseye,sid}, - linuxmint-{17,18,19,19.1,19.2,19.3}, - fedora-{26,27,28,29,30,31,32}, - centos-{7,8}, - arch-latest, - conda-forge,conda-anaconda3 - } - -{# https://github.com/docker-library/official-images#architectures-other-than-amd64 - # architectures officially supported by Docker, Inc. for running Docker - amd64,arm32v6,arm32v7,arm64v8, - # windows-amd64 # https://hub.docker.com/u/winamd64/ - # Other architectures built by official images: - # (but not officially supported by Docker, Inc.) - arm32v5,ppc64le,s390x,i386}, + + ### Package factors: + ### + ### - minimal # Install a minimal set of system packages that supports bootstrapping and compiling Sage. + ### - standard # Install all known system packages equivalent to standard packages that have spkg-configure.m4 + ### - maximal # Install all known system packages equivalent to standard/optional packages that have spkg-configure.m4 + + docker-ubuntu-trusty-minimal, + docker-debian-bullseye-standard, + docker-fedora-34-standard, + docker-archlinux-latest-maximal, + docker-manylinux-2_24-i686-standard, + docker-conda-forge-standard, + ### "local" targets should be run from a source tree that is freshly checked out ### (for example, by 'git worktree add ...') or has been cleaned by 'make bdist-clean' -- ### because they build within the source tree (because we have no VPATH support). @@ -74,26 +95,13 @@ envlist = # instead. It may install packages or update packages. It will not remove packages. # Use at your own risk. # - local-homebrew-macos - } - -{### - ### Package factors: - ### - minimal, # Install a minimal set of system packages that supports bootstrapping and compiling Sage. - standard, # Install all known system packages equivalent to standard packages that have spkg-configure.m4 - maximal # Install all known system packages equivalent to standard/optional packages that have spkg-configure.m4 - }, - ### - ### The "local-direct" toxenv passes the whole environment on to the sage build. - ### Whatever is in PATH etc. will be used. - ### - local-direct - } - -{### - ### Configuration factors: - ### - python3_spkg - } + + ### + ### The "local-direct" toxenv passes the whole environment on to the sage build. + ### Whatever is in PATH etc. will be used. + ### + # + # $ tox -e local-direct -- openblas skipsdist = true @@ -308,6 +316,14 @@ setenv = # Many docker images for another architecture are named the same, in the arch prefix. # All work for Docker on Mac; but only i386 works for Linux Docker. # + # According to https://github.com/docker-library/official-images#architectures-other-than-amd64 + # architectures officially supported by Docker, Inc. for running Docker: + # - amd64,arm32v6,arm32v7,arm64v8, + # - windows-amd64 # https://hub.docker.com/u/winamd64/ + # Other architectures built by official images: + # (but not officially supported by Docker, Inc.) + # - arm32v5,ppc64le,s390x,i386 + # arm32v5: ARCH_IMAGE_PREFIX=arm32v5/ arm32v6: ARCH_IMAGE_PREFIX=arm32v6/ arm32v7: ARCH_IMAGE_PREFIX=arm32v7/ From 609815dd15005f428d32cf0f636a5ccfc0e2b298 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 25 Oct 2021 09:25:20 -0700 Subject: [PATCH 038/126] tox.ini (check_configure): Set HOME --- tox.ini | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tox.ini b/tox.ini index 69c79015727..0fd00cd6850 100644 --- a/tox.ini +++ b/tox.ini @@ -600,6 +600,8 @@ commands = ## Test that configure behaves properly whitelist_externals = bash +setenv = + HOME = {envdir} commands = ./bootstrap bash -c 'test -z "$(./configure --quiet 2>&1)" || (echo >&2 Error: "configure --quiet" is not quiet; exit 1)' From 5392cd7925de2eb58b349b8fcc26b5cf71d46eb3 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 25 Oct 2021 09:35:08 -0700 Subject: [PATCH 039/126] tox.ini: Do not include the environments delegated to src/tox.ini in 'tox -p auto' --- tox.ini | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/tox.ini b/tox.ini index 0fd00cd6850..b70188b99bc 100644 --- a/tox.ini +++ b/tox.ini @@ -11,21 +11,6 @@ envlist = - ##### - ##### Delegation to src/tox.ini - ##### - - # Included on tox -p auto - doctest, - coverage, - startuptime, - pycodestyle-minimal, - relint, - codespell, - - # Also available: - #pycodestyle - ##### ##### Sage-the-distribution tests ##### @@ -103,6 +88,25 @@ envlist = # # $ tox -e local-direct -- openblas + + ##### + ##### Delegation to src/tox.ini + ##### + + # included with (cd src && tox -p auto): + # + # doctest, + # coverage, + # startuptime, + # pycodestyle-minimal, + # relint, + # codespell, + # + # Also available: + # + # pycodestyle + + skipsdist = true [testenv] From 47a2b421fb70095a0971d37c39689460c0b16d4c Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 25 Oct 2021 10:31:53 -0700 Subject: [PATCH 040/126] tox.ini: Add more examples --- tox.ini | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/tox.ini b/tox.ini index b70188b99bc..eea7ce74624 100644 --- a/tox.ini +++ b/tox.ini @@ -1,12 +1,28 @@ # SAGE_ROOT/tox.ini: Environments for testing the Sage distribution # -# Run a specific environment: -# tox -e docker-fedora-31 -# Run all in parallel: -# tox -p auto +# To run a specific environment: +# +# $ tox -e docker-fedora-31-standard +# +# This will do a complete build of the Sage distribution in a Docker container, which will take a while. +# +# Specific 'make' targets can be given as additional arguments after "--". +# For example, to only run the configuration phase: +# +# $ tox -e docker-debian-bullseye-standard -- config.status +# +# To build a single package (and its dependencies): +# +# $ tox -e docker-manylinux-2_24-i686-standard -- ppl +# +# It can be useful to run several of the environments in parallel. For example: +# +# $ tox -p auto -- config.status +# # with local squid: -# EXTRA_DOCKER_BUILD_ARGS="--build-arg http_proxy=http://host.docker.internal:3128 --build-arg https_proxy=http://host.docker.internal:3128" tox -p auto +# +# $ EXTRA_DOCKER_BUILD_ARGS="--build-arg http_proxy=http://host.docker.internal:3128 --build-arg https_proxy=http://host.docker.internal:3128" tox -p auto -- config.status [tox] envlist = From 7bd6ce4f39bb8e3a94ba59eaf064044a1e02b9ee Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Tue, 26 Oct 2021 16:16:11 +0200 Subject: [PATCH 041/126] Partly revert "Enable editable mode also for other sage packages" This partly reverts commit b9b1dba57d85ea7d6f68471024406a939579b5bb. --- build/pkgs/sagelib/spkg-install | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/pkgs/sagelib/spkg-install b/build/pkgs/sagelib/spkg-install index 050af61a140..76a306e5762 100755 --- a/build/pkgs/sagelib/spkg-install +++ b/build/pkgs/sagelib/spkg-install @@ -49,7 +49,7 @@ if [ "$SAGE_EDITABLE" = yes ]; then # and renamed the distribution to "sagemath-standard"). There is no clean way to uninstall # them, so we just use rm. (cd "$SITEPACKAGESDIR" && rm -rf sage sage_setup sage-[1-9]*.egg-info sage-[1-9]*.dist-info) - time sdh_pip_editable_install . || exit 1 + time python3 -m pip install --verbose --no-deps --no-index --no-build-isolation --isolated --editable . || exit 1 else # Likewise, we should remove the egg-link that may have been installed previously. (cd "$SITEPACKAGESDIR" && rm -f sagemath-standard.egg-link) From 9424a24cb59f00c4fb0e19a2356dc208317a5b09 Mon Sep 17 00:00:00 2001 From: Miguel Marco Date: Wed, 27 Oct 2021 19:52:24 +0200 Subject: [PATCH 042/126] Some minor reviewer's changes --- src/sage/libs/singular/singular.pyx | 195 +++++++++++++--------------- 1 file changed, 90 insertions(+), 105 deletions(-) diff --git a/src/sage/libs/singular/singular.pyx b/src/sage/libs/singular/singular.pyx index 6c6c907359c..bf8b461fea2 100644 --- a/src/sage/libs/singular/singular.pyx +++ b/src/sage/libs/singular/singular.pyx @@ -62,16 +62,16 @@ cdef Rational si2sa_QQ(number *n, number **nn, ring *_ring): INPUT: - - ``n`` - a (pointer to) a singular rational number + - ``n`` - a (pointer to) a singular rational number - - ``*n`` - a pointer to a pointer like before + - ``*n`` - a pointer to a pointer like before - - ``_ ring`` - a (pointer to) a singular ring, in whose coefficient field - lives ``n`` + - ``_ ring`` - a (pointer to) a singular ring, in whose coefficient field + lives ``n`` OUTPUT: - - A sage Rational + - A sage Rational TESTS:: @@ -134,14 +134,14 @@ cdef Integer si2sa_ZZ(number *n, ring *_ring): INPUT: - - ``n`` - a (pointer to) a singular integer number + - ``n`` - a (pointer to) a singular integer number - - ``_ ring`` - a (pointer to) a singular ring, in whose coefficient field - lives ``n`` + - ``_ ring`` - a (pointer to) a singular ring, in whose coefficient field + lives ``n`` OUTPUT: - - A sage Integer + - A sage Integer TESTS:: @@ -169,12 +169,12 @@ cdef FFgivE si2sa_GFqGivaro(number *n, ring *_ring, Cache_givaro cache): INPUT: - - ``n`` - a (pointer to) a singular number in a finite field + - ``n`` - a (pointer to) a singular number in a finite field - - ``_ ring`` - a (pointer to) a singular ring, in whose coefficient field - lives ``n`` + - ``_ ring`` - a (pointer to) a singular ring, in whose coefficient field + lives ``n`` - - ``cache`` - A Givaro number field + - ``cache`` - A Givaro number field OUTPUT: @@ -225,16 +225,16 @@ cdef FFgf2eE si2sa_GFqNTLGF2E(number *n, ring *_ring, Cache_ntl_gf2e cache): INPUT: - - ``n`` - a (pointer to) a singular number in a finite field + - ``n`` - a (pointer to) a singular number in a finite field - - ``_ ring`` - a (pointer to) a singular ring, in whose coefficient field - lives ``n`` + - ``_ ring`` - a (pointer to) a singular ring, in whose coefficient field + lives ``n`` - - ``cache`` - A ntl_gf2e number field + - ``cache`` - A ntl_gf2e number field OUTPUT: - - A sage element of ``cache`` + - A sage element of ``cache`` TESTS:: @@ -276,16 +276,16 @@ cdef object si2sa_GFq_generic(number *n, ring *_ring, object base): INPUT: - - ``n`` - a (pointer to) a singular number in a finite field + - ``n`` - a (pointer to) a singular number in a finite field - - ``_ ring`` - a (pointer to) a singular ring, in whose coefficient field - lives ``n`` + - ``_ ring`` - a (pointer to) a singular ring, in whose coefficient field + lives ``n`` - - ``base`` - A sage finite field + - ``base`` - A sage finite field OUTPUT: - - A sage element of ``base`` + - A sage element of ``base`` TESTS:: @@ -304,7 +304,6 @@ cdef object si2sa_GFq_generic(number *n, ring *_ring, object base): sage: R. = F[] sage: R(-1).constant_coefficient() # indirect doctest 2147483646 - """ cdef poly *z cdef long c @@ -340,17 +339,17 @@ cdef object si2sa_transext_QQ(number *n, ring *_ring, object base): INPUT: - - ``n`` - a (pointer to) a singular number in a transcendental extension + - ``n`` - a (pointer to) a singular number in a transcendental extension of the rationals - - ``_ ring`` - a (pointer to) a singular ring, in whose coefficient field - lives ``n`` + - ``_ ring`` - a (pointer to) a singular ring, in whose coefficient field + lives ``n`` - - ``base`` - A sage FractionField + - ``base`` - A sage FractionField OUTPUT: - - A sage element of ``base`` + - A sage element of ``base`` TESTS:: @@ -370,7 +369,6 @@ cdef object si2sa_transext_QQ(number *n, ring *_ring, object base): [x^3 + (3*a - 3*b)/(a + b)*x*y, y^2 + a/b*x] sage: R.term_order() Degree reverse lexicographic term order - """ cdef poly *numer @@ -431,17 +429,17 @@ cdef object si2sa_transext_FF(number *n, ring *_ring, object base): INPUT: - - ``n`` - a (pointer to) a singular number in a transcendental extension - of the rationals + - ``n`` - a (pointer to) a singular number in a transcendental extension + of the rationals - - ``_ ring`` - a (pointer to) a singular ring, in whose coefficient field - lives ``n`` + - ``_ ring`` - a (pointer to) a singular ring, in whose coefficient field + lives ``n`` - - ``base`` - A sage FractionField + - ``base`` - A sage FractionField OUTPUT: - - A sage element of ``base`` + - A sage element of ``base`` TESTS:: @@ -452,7 +450,6 @@ cdef object si2sa_transext_FF(number *n, ring *_ring, object base): -2 sage: type(n) - """ cdef poly *numer @@ -515,17 +512,17 @@ cdef object si2sa_NF(number *n, ring *_ring, object base): INPUT: - - ``n`` - a (pointer to) a singular number in an algebraic extension of - the rationals + - ``n`` - a (pointer to) a singular number in an algebraic extension of + the rationals - - ``_ ring`` - a (pointer to) a singular ring, in whose coefficient field - lives ``n`` + - ``_ ring`` - a (pointer to) a singular ring, in whose coefficient field + lives ``n`` - - ``base`` - A sage NumberField + - ``base`` - A sage NumberField OUTPUT: - - A sage element of ``base`` + - A sage element of ``base`` TESTS:: @@ -580,16 +577,16 @@ cdef inline object si2sa_ZZmod(number *n, ring *_ring, object base): INPUT: - - ``n`` - a (pointer to) a singular number in a ring of integers modulo n + - ``n`` - a (pointer to) a singular number in a ring of integers modulo n - - ``_ ring`` - a (pointer to) a singular ring, in whose coefficient field - lives ``n`` + - ``_ ring`` - a (pointer to) a singular ring, in whose coefficient field + lives ``n`` - - ``base`` - A sage IntegerModRing + - ``base`` - A sage IntegerModRing OUTPUT: - - A sage element of ``base`` + - A sage element of ``base`` TESTS:: @@ -641,14 +638,14 @@ cdef number *sa2si_QQ(Rational r, ring *_ring): INPUT: - - ``r`` - a sage rational number + - ``r`` - a sage rational number - - ``_ ring`` - a (pointer to) a singular ring, where the resul will live + - ``_ ring`` - a (pointer to) a singular ring, where the resul will live OUTPUT: - - A (pointer to) a singular number + - A (pointer to) a singular number TESTS:: @@ -672,14 +669,14 @@ cdef number *sa2si_GFqGivaro(int quo, ring *_ring): INPUT: - - ``quo`` - a sage integer + - ``quo`` - a sage integer - - ``_ ring`` - a (pointer to) a singular ring, where the resul will live + - ``_ ring`` - a (pointer to) a singular ring, where the resul will live OUTPUT: - - A (pointer to) a singular number + - A (pointer to) a singular number Number field elements are represented as polynomials in the number field generator. In this case, ``quo`` is the integer resulting from evaluating @@ -698,7 +695,6 @@ cdef number *sa2si_GFqGivaro(int quo, ring *_ring): (z2 + 1) sage: R(F.gen()^2) + 1 (z2 - 1) - """ if _ring != currRing: rChangeCurrRing(_ring) @@ -743,14 +739,14 @@ cdef number *sa2si_GFqNTLGF2E(FFgf2eE elem, ring *_ring): INPUT: - - ``elem`` - a sage element of a ntl_gf2e finite field + - ``elem`` - a sage element of a ntl_gf2e finite field - - ``_ ring`` - a (pointer to) a singular ring, where the resul will live + - ``_ ring`` - a (pointer to) a singular ring, where the resul will live OUTPUT: - - A (pointer to) a singular number + - A (pointer to) a singular number TESTS:: @@ -764,7 +760,6 @@ cdef number *sa2si_GFqNTLGF2E(FFgf2eE elem, ring *_ring): (z20 + 1) sage: R(F.gen()^21) + 1 (z20^11 + z20^10 + z20^8 + z20^7 + z20^6 + z20^5 + z20^2 + z20 + 1) - """ if _ring != currRing: rChangeCurrRing(_ring) cdef int i @@ -810,14 +805,14 @@ cdef number *sa2si_GFq_generic(object elem, ring *_ring): INPUT: - - ``elem`` - a sage element of a generic finite field + - ``elem`` - a sage element of a generic finite field - - ``_ ring`` - a (pointer to) a singular ring, where the resul will live + - ``_ ring`` - a (pointer to) a singular ring, where the resul will live OUTPUT: - - A (pointer to) a singular number + - A (pointer to) a singular number TESTS:: @@ -831,7 +826,6 @@ cdef number *sa2si_GFq_generic(object elem, ring *_ring): (z20 + 1) sage: R(F.gen()^21) + 1 (z20^14 - z20^12 - z20^11 - z20^10 - z20^9 + z20^6 + z20^5 + z20^4 - z20^2 + z20 + 1) - """ cdef int i cdef number *n1 @@ -878,14 +872,14 @@ cdef number *sa2si_transext_QQ(object elem, ring *_ring): INPUT: - - ``elem`` - a sage element of a FractionField of polynomials over the rationals + - ``elem`` - a sage element of a FractionField of polynomials over the rationals - - ``_ ring`` - a (pointer to) a singular ring, where the resul will live + - ``_ ring`` - a (pointer to) a singular ring, where the resul will live OUTPUT: - - A (pointer to) a singular number + - A (pointer to) a singular number TESTS:: @@ -929,7 +923,6 @@ cdef number *sa2si_transext_QQ(object elem, ring *_ring): sage: f = x + y + 1 sage: R(f) x + y + 1 - """ cdef int j @@ -954,7 +947,7 @@ cdef number *sa2si_transext_QQ(object elem, ring *_ring): nMapFuncPtr = naSetMap(_ring.cf, currRing.cf) # choose correct mapping function - if (nMapFuncPtr is NULL): + if nMapFuncPtr is NULL: raise RuntimeError("Failed to determine nMapFuncPtr") numerdic = elem.numerator().dict() @@ -1034,14 +1027,14 @@ cdef number *sa2si_transext_FF(object elem, ring *_ring): INPUT: - - ``elem`` - a sage element of a FractionField of polynomials over the rationals + - ``elem`` - a sage element of a FractionField of polynomials over the rationals - - ``_ ring`` - a (pointer to) a singular ring, where the resul will live + - ``_ ring`` - a (pointer to) a singular ring, where the resul will live OUTPUT: - - A (pointer to) a singular number + - A (pointer to) a singular number TESTS:: @@ -1053,9 +1046,6 @@ cdef number *sa2si_transext_FF(object elem, ring *_ring): 3 sage: Integer(n) 5 - - - """ cdef int j cdef number *n1 @@ -1076,7 +1066,7 @@ cdef number *sa2si_transext_FF(object elem, ring *_ring): nMapFuncPtr = naSetMap(_ring.cf, currRing.cf) # choose correct mapping function - if (nMapFuncPtr is NULL): + if nMapFuncPtr is NULL: raise RuntimeError("Failed to determine nMapFuncPtr") numerdic = elem.numerator().dict() @@ -1140,14 +1130,14 @@ cdef number *sa2si_NF(object elem, ring *_ring): INPUT: - - ``elem`` - a sage element of a NumberField + - ``elem`` - a sage element of a NumberField - - ``_ ring`` - a (pointer to) a singular ring, where the resul will live + - ``_ ring`` - a (pointer to) a singular ring, where the resul will live OUTPUT: - - A (pointer to) a singular number + - A (pointer to) a singular number TESTS:: @@ -1163,7 +1153,6 @@ cdef number *sa2si_NF(object elem, ring *_ring): (a + 1) sage: R(F.gen()^5) + 1 (-a^2 + a + 2) - """ cdef int i cdef number *n1 @@ -1178,7 +1167,7 @@ cdef number *sa2si_NF(object elem, ring *_ring): nMapFuncPtr = naSetMap(_ring.cf, currRing.cf) # choose correct mapping function - if (nMapFuncPtr is NULL): + if nMapFuncPtr is NULL: raise RuntimeError("Failed to determine nMapFuncPtr") elem = list(elem) @@ -1203,7 +1192,6 @@ cdef number *sa2si_NF(object elem, ring *_ring): rComplete(qqr,1) qqr.ShortOut = 0 - nMapFuncPtr = naSetMap( qqr.cf , _ring.cf ) # choose correct mapping function cdef poly *_p for i from 0 <= i < len(elem): @@ -1234,14 +1222,14 @@ cdef number *sa2si_ZZ(Integer d, ring *_ring): INPUT: - - ``elem`` - a sage Integer + - ``elem`` - a sage Integer - - ``_ ring`` - a (pointer to) a singular ring, where the resul will live + - ``_ ring`` - a (pointer to) a singular ring, where the resul will live OUTPUT: - - A (pointer to) a singular number + - A (pointer to) a singular number TESTS:: @@ -1267,11 +1255,9 @@ cdef inline number *sa2si_ZZmod(IntegerMod_abstract d, ring *_ring): INPUT: - - ``elem`` - a sage IntegerMod - - - ``_ ring`` - a (pointer to) a singular ring, where the resul will live - + - ``elem`` - a sage IntegerMod + - ``_ ring`` - a (pointer to) a singular ring, where the resul will live TESTS:: @@ -1351,15 +1337,15 @@ cdef object si2sa(number *n, ring *_ring, object base): INPUT: - - ``n`` - a (pointer to) a singular number + - ``n`` - a (pointer to) a singular number - - ``_ring`` - a (pointer to) the singular ring where ``n`` lives + - ``_ring`` - a (pointer to) the singular ring where ``n`` lives - - ``object`` - the sage parent where the result will live + - ``object`` - the sage parent where the result will live OUTPUT: - An element of ``base`` + An element of ``base`` """ if isinstance(base, FiniteField_prime_modn): return base(_ring.cf.cfInt(n, _ring.cf)) @@ -1402,14 +1388,14 @@ cdef number *sa2si(Element elem, ring * _ring): INPUT: - - ``elem`` - a sage element from a parent. The parent must have a - corresponding singular coefficient type. + - ``elem`` - a sage element from a parent. The parent must have a + corresponding singular coefficient type. - - ``_ring`` - a (pointer to) the singular ring where the result will live. + - ``_ring`` - a (pointer to) the singular ring where the result will live. OUTPUT: - a (pointer to) a singular number + a (pointer to) a singular number """ cdef int i = 0 if isinstance(elem._parent, FiniteField_prime_modn): @@ -1436,14 +1422,13 @@ cdef number *sa2si(Element elem, ring * _ring): if _ring.cf.type == n_unknown: return n_Init(int(elem),_ring) return sa2si_ZZmod(elem, _ring) - elif isinstance(elem._parent, FractionField_generic) and isinstance(elem._parent.base(), (MPolynomialRing_libsingular, PolynomialRing_field)) and isinstance(elem._parent.base().base_ring(), RationalField): - return sa2si_transext_QQ(elem, _ring) + elif isinstance(elem._parent, FractionField_generic) and isinstance(elem._parent.base(), (MPolynomialRing_libsingular, PolynomialRing_field)): + if isinstance(elem._parent.base().base_ring(), RationalField): + return sa2si_transext_QQ(elem, _ring) + elif isinstance(elem._parent.base().base_ring(), FiniteField_prime_modn): + return sa2si_transext_FF(elem, _ring) - elif isinstance(elem._parent, FractionField_generic) and isinstance(elem._parent.base(), (MPolynomialRing_libsingular, PolynomialRing_field)) and isinstance(elem._parent.base().base_ring(), FiniteField_prime_modn): - return sa2si_transext_FF(elem, _ring) - - else: - raise ValueError("cannot convert to SINGULAR number") + raise ValueError("cannot convert to SINGULAR number") cdef object si2sa_intvec(intvec *v): @@ -1452,11 +1437,11 @@ cdef object si2sa_intvec(intvec *v): INPUT: - - ``v`` - a (pointer to) a singular intvec + - ``v`` - a (pointer to) a singular intvec OUTPUT: - a sage tuple + a sage tuple """ cdef int r cdef list l = list() From 91175519586b984be1b469a7eb49679b3ecbe998 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Labb=C3=A9?= Date: Thu, 28 Oct 2021 10:38:07 +0200 Subject: [PATCH 043/126] 32696: fix failing doctest --- src/sage/finance/stock.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/sage/finance/stock.py b/src/sage/finance/stock.py index ed8cb8ed90b..aa1dbb7dc99 100644 --- a/src/sage/finance/stock.py +++ b/src/sage/finance/stock.py @@ -551,9 +551,7 @@ def load_from_file(self, file): sage: with open(filename, 'w') as fobj: ....: _ = fobj.write("Date,Open,High,Low,Close,Volume\n1212405780,187.80,187.80,187.80,187.80,100\n1212407640,187.75,188.00,187.75,188.00,2000\n1212407700,188.00,188.00,188.00,188.00,1000\n1212408000,188.00,188.11,188.00,188.00,2877\n1212408060,188.00,188.00,188.00,188.00,687") sage: finance.Stock('aapl').load_from_file(filename)[:5] - doctest:warning... - DeprecationWarning: Importing finance from here is deprecated... - [ + ... 1212408060 188.00 188.00 188.00 188.00 687, 1212408000 188.00 188.11 188.00 188.00 2877, 1212407700 188.00 188.00 188.00 188.00 1000, From bc59753278c61fca9d7b9264aa3015ec55731ea1 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 24 Oct 2021 12:59:14 -0700 Subject: [PATCH 044/126] build/pkgs/flit_core/spkg-install.in: Use sdh_pip_install --no-deps --- build/pkgs/flit_core/spkg-install.in | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build/pkgs/flit_core/spkg-install.in b/build/pkgs/flit_core/spkg-install.in index 37ac1a53437..8d6f80f4cc7 100644 --- a/build/pkgs/flit_core/spkg-install.in +++ b/build/pkgs/flit_core/spkg-install.in @@ -1,2 +1,3 @@ cd src -sdh_pip_install . +# We use --no-deps to suppress a warning regarding tomli. +sdh_pip_install --no-deps . From 2578d365b3b405cbeb13f443201bbfe10841b3ef Mon Sep 17 00:00:00 2001 From: Florian Weber Date: Fri, 29 Oct 2021 16:39:34 +0200 Subject: [PATCH 045/126] improve error message of Elliptic-Curve constructor for singular Curves --- src/sage/schemes/elliptic_curves/ell_generic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/schemes/elliptic_curves/ell_generic.py b/src/sage/schemes/elliptic_curves/ell_generic.py index 965271f7241..c261b284fc6 100644 --- a/src/sage/schemes/elliptic_curves/ell_generic.py +++ b/src/sage/schemes/elliptic_curves/ell_generic.py @@ -145,7 +145,7 @@ def __init__(self, K, ainvs): self.__base_ring = K self.__ainvs = tuple(K(a) for a in ainvs) if self.discriminant() == 0: - raise ArithmeticError("invariants " + str(ainvs) + " define a singular curve") + raise ArithmeticError(self._equation_string() + " defines a singular curve") PP = projective_space.ProjectiveSpace(2, K, names='xyz') x, y, z = PP.coordinate_ring().gens() a1, a2, a3, a4, a6 = ainvs From d05e0fb75178c73034003fc9a31b6ff6f6442df6 Mon Sep 17 00:00:00 2001 From: Lorenz Panny Date: Sat, 30 Oct 2021 15:20:46 +0800 Subject: [PATCH 046/126] avoid crashing if extensions are already not in the list --- src/sage_docbuild/__init__.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/sage_docbuild/__init__.py b/src/sage_docbuild/__init__.py index 2368d6cbf31..f27c6cf086e 100644 --- a/src/sage_docbuild/__init__.py +++ b/src/sage_docbuild/__init__.py @@ -1231,7 +1231,7 @@ def __init__(self, path): # Write self.dir/conf.py conf = r"""# This file is automatically generated by {}, do not edit! -import sys, os +import sys, os, contextlib sys.path.append({!r}) from sage.docs.conf import * @@ -1244,8 +1244,9 @@ def __init__(self, path): html_short_title = project htmlhelp_basename = name -extensions.remove('multidocs') # see #29651 -extensions.remove('inventory_builder') +with contextlib.suppress(ValueError): + extensions.remove('multidocs') # see #29651 + extensions.remove('inventory_builder') latex_domain_indices = False latex_documents = [ From fee0403038081c5f2b1a2a52c6950e34d31e8569 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sat, 30 Oct 2021 21:54:19 +0200 Subject: [PATCH 047/126] clean up various details in combinat --- src/sage/combinat/cartesian_product.py | 2 +- src/sage/combinat/composition.py | 2 +- src/sage/combinat/designs/database.py | 7 +++---- .../combinat/designs/incidence_structures.py | 12 ++++++------ src/sage/combinat/e_one_star.py | 2 +- src/sage/combinat/finite_state_machine.py | 4 ++-- src/sage/combinat/free_module.py | 4 ++-- src/sage/combinat/gelfand_tsetlin_patterns.py | 10 +++++----- src/sage/combinat/integer_vector_weighted.py | 8 ++++---- .../combinat/integer_vectors_mod_permgroup.py | 18 +++++++++--------- src/sage/combinat/matrices/dancing_links.pyx | 10 +++++----- .../multiset_partition_into_sets_ordered.py | 5 ++++- src/sage/combinat/partitions.pyx | 6 +++--- src/sage/combinat/posets/poset_examples.py | 5 +++-- src/sage/combinat/ranker.py | 4 ++-- .../root_lattice_realization_algebras.py | 10 ++++++---- .../combinat/root_system/type_reducible.py | 6 +++--- .../root_system/weight_lattice_realizations.py | 6 +++--- src/sage/combinat/skew_partition.py | 15 ++++++--------- src/sage/combinat/sloane_functions.py | 4 ++-- src/sage/combinat/tableau.py | 2 +- src/sage/combinat/tiling.py | 7 +++---- src/sage/combinat/words/finite_word.py | 10 +++++----- src/sage/combinat/words/words.py | 4 ++-- 24 files changed, 82 insertions(+), 81 deletions(-) diff --git a/src/sage/combinat/cartesian_product.py b/src/sage/combinat/cartesian_product.py index e2069f38e53..7b9cf8e62e6 100644 --- a/src/sage/combinat/cartesian_product.py +++ b/src/sage/combinat/cartesian_product.py @@ -57,7 +57,7 @@ class for ``cartesian_product``; sage: c = cartesian_product([F1, F2, F3]) sage: type(C.an_element()) - <... 'list'> + sage: type(c.an_element()) diff --git a/src/sage/combinat/composition.py b/src/sage/combinat/composition.py index 5f899c71106..46a6be10fad 100644 --- a/src/sage/combinat/composition.py +++ b/src/sage/combinat/composition.py @@ -2017,7 +2017,7 @@ def composition_iterator_fast(n): sage: L = list(composition_iterator_fast(4)); L [[1, 1, 1, 1], [1, 1, 2], [1, 2, 1], [1, 3], [2, 1, 1], [2, 2], [3, 1], [4]] sage: type(L[0]) - <... 'list'> + """ # Special cases if n < 0: diff --git a/src/sage/combinat/designs/database.py b/src/sage/combinat/designs/database.py index af61d7e3ace..02023998fc1 100644 --- a/src/sage/combinat/designs/database.py +++ b/src/sage/combinat/designs/database.py @@ -4206,7 +4206,7 @@ def BIBD_45_9_8(from_code=False): '7up5z9m9u', '7w7esu6fm', '7zmqtlrpd', '81tsbnzsw', '8kofgi1he', '8mhi35nc1', '9cv1pjiaw', '9d6ef1dah', '9dftsor9c', '9du8c1vcw', '9jr5vsnj4', 'a8b405mps', 'ajqhmxkj4', 'ax2xsvfic'] B = [Integer(x, base=36) for x in B] - return [[i for i in range(45) if x&(1< + sage: type(I.blocks()[0][0]) - <... 'sage.rings.finite_rings.integer_mod.IntegerMod_int'> + TESTS:: @@ -1290,7 +1290,7 @@ def complement(self,uniform=False): if k is False: raise ValueError("The incidence structure is not uniform.") - blocks = [] + blocks = [] num_blocks = self.num_blocks() i = 0 from itertools import combinations @@ -1388,9 +1388,9 @@ def relabel(self, perm=None, inplace=True): self._points = [perm[x] for x in self._points] if self._points == list(range(self.num_points())): - self._point_to_index = None + self._point_to_index = None else: - self._point_to_index = {v:i for i,v in enumerate(self._points)} + self._point_to_index = {v: i for i, v in enumerate(self._points)} __hash__ = None # This object is mutable because of .relabel() @@ -2128,7 +2128,7 @@ def edge_coloring(self): blocks = self.blocks() blocks_sets = [frozenset(b) for b in blocks] g = Graph([list(range(self.num_blocks())), - lambda x, y: len(blocks_sets[x]&blocks_sets[y])], + lambda x, y: len(blocks_sets[x] & blocks_sets[y])], loops=False) return [[blocks[i] for i in C] for C in g.coloring(algorithm="MILP")] diff --git a/src/sage/combinat/e_one_star.py b/src/sage/combinat/e_one_star.py index 2cca168d20f..924ee53e754 100644 --- a/src/sage/combinat/e_one_star.py +++ b/src/sage/combinat/e_one_star.py @@ -1066,7 +1066,7 @@ def repaint(self, cmap='Set1') -> None: global cm if cm is None: from matplotlib import cm - + assert cm is not None if cmap not in cm.datad: raise RuntimeError("Color map %s not known (type sorted(colors) for valid names)" % cmap) cmap = cm.__dict__[cmap] diff --git a/src/sage/combinat/finite_state_machine.py b/src/sage/combinat/finite_state_machine.py index 2cdd4045c02..2675100539c 100644 --- a/src/sage/combinat/finite_state_machine.py +++ b/src/sage/combinat/finite_state_machine.py @@ -3886,10 +3886,10 @@ def __call__(self, *args, **kwargs): (1, 0, 1, 1, 0, 1, 0, 1, 1, 0) sage: type(inverter((1, 0, 1, 1, 0, 1, 0, 1, 1, 0), ....: automatic_output_type=False)) - <... 'list'> + sage: type(inverter((1, 0, 1, 1, 0, 1, 0, 1, 1, 0), ....: automatic_output_type=True)) - <... 'tuple'> + """ if not args: raise TypeError("Called with too few arguments.") diff --git a/src/sage/combinat/free_module.py b/src/sage/combinat/free_module.py index d9f5d7c8144..bae91d64145 100644 --- a/src/sage/combinat/free_module.py +++ b/src/sage/combinat/free_module.py @@ -338,7 +338,7 @@ def element_class(self): sage: A.element_class.mro() [, - <... 'sage.modules.with_basis.indexed_element.IndexedFreeModuleElement'>, + , ...] sage: a,b,c = A.algebra_generators() sage: a * b @@ -1152,7 +1152,7 @@ class CombinatorialFreeModule_Tensor(CombinatorialFreeModule): The basis of T is indexed by tuples of basis indices of F and G:: sage: T.basis().keys() - Image of Cartesian product of {1, 2}, {3, 4} by <... 'tuple'> + Image of Cartesian product of {1, 2}, {3, 4} by sage: T.basis().keys().list() [(1, 3), (1, 4), (2, 3), (2, 4)] diff --git a/src/sage/combinat/gelfand_tsetlin_patterns.py b/src/sage/combinat/gelfand_tsetlin_patterns.py index ff5a145cd92..08615c0eae7 100644 --- a/src/sage/combinat/gelfand_tsetlin_patterns.py +++ b/src/sage/combinat/gelfand_tsetlin_patterns.py @@ -920,11 +920,11 @@ def _list_iter(self, n): sage: len(L) == G.cardinality() True sage: type(L[0]) - <... 'list'> + """ # Setup the first row - iters = [None]*n - ret = [None]*n + iters = [None] * n + ret = [None] * n iters[0] = self._top_row_iter(n) ret[0] = next(iters[0]) min_pos = 0 @@ -959,7 +959,7 @@ def _top_row_iter(self, n): sage: for x in G._top_row_iter(3): x [2, 1, 0] """ - row = [-1]*n + row = [-1] * n pos = 0 while pos >= 0: if pos == n: @@ -967,7 +967,7 @@ def _top_row_iter(self, n): pos -= 1 continue # If it would create an invalid entry, backstep - if ( pos > 0 and (row[pos] >= row[pos-1] \ + if (pos > 0 and (row[pos] >= row[pos-1] or (self._strict and row[pos] == row[pos-1]-1)) ) \ or (self._k is not None and row[pos] >= self._k): row[pos] = -1 diff --git a/src/sage/combinat/integer_vector_weighted.py b/src/sage/combinat/integer_vector_weighted.py index 8f1b68ffe85..1c2c109217c 100644 --- a/src/sage/combinat/integer_vector_weighted.py +++ b/src/sage/combinat/integer_vector_weighted.py @@ -237,12 +237,12 @@ def __iter__(self): return perm = Word(self._weights).standard_permutation() - perm = [len(self._weights)-i for i in perm] + perm = [len(self._weights) - i for i in perm] l = [x for x in sorted(self._weights, reverse=True)] for x in iterator_fast(self._n, l): yield self.element_class(self, [x[i] for i in perm]) - #.action(x) - #_left_to_right_multiply_on_right(Permutation(x)) + # .action(x) + # _left_to_right_multiply_on_right(Permutation(x)) class WeightedIntegerVectors_all(DisjointUnionEnumeratedSets): @@ -360,7 +360,7 @@ def iterator_fast(n, l): Test that :trac:`20491` is fixed:: sage: type(list(iterator_fast(2, [2]))[0][0]) - <... 'sage.rings.integer.Integer'> + """ if n < 0: return diff --git a/src/sage/combinat/integer_vectors_mod_permgroup.py b/src/sage/combinat/integer_vectors_mod_permgroup.py index 911558b4921..ef7f278e98a 100644 --- a/src/sage/combinat/integer_vectors_mod_permgroup.py +++ b/src/sage/combinat/integer_vectors_mod_permgroup.py @@ -293,7 +293,7 @@ def _repr_(self): sage: IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3)]])) Integer vectors of length 3 enumerated up to the action of Permutation Group with generators [(1,2,3)] """ - return "Integer vectors of length %s enumerated up to the action of %r"%(self.n, self._permgroup) + return "Integer vectors of length %s enumerated up to the action of %r" % (self.n, self._permgroup) def ambient(self): r""" @@ -317,7 +317,7 @@ def lift(self, elt): sage: v = S.lift(S([4,3,0,1])); v [4, 3, 0, 1] sage: type(v) - <... 'list'> + """ # TODO: For now, Sage integer vectors are just python list. # Once Integer vectors will have an element class, update this @@ -360,7 +360,7 @@ def retract(self, elt): """ # TODO: Once Sage integer vector will have a data structure # based on ClonableIntArray, remove the conversion intarray - assert len(elt) == self.n, "%s is a quotient set of %s"%(self, self.ambient()) + assert len(elt) == self.n, "%s is a quotient set of %s" % (self, self.ambient()) intarray = self.element_class(self, elt, check=False) return self.element_class(self, canonical_representative_of_orbit_of(self._sgs, intarray), check=False) @@ -628,11 +628,11 @@ def _repr_(self): """ if self._sum is not None: if self._max_part >= 0: - return "Vectors of length %s and of sum %s whose entries is in {0, ..., %s} enumerated up to the action of %s"%(self.n, self._sum, self._max_part, self.permutation_group()) + return "Vectors of length %s and of sum %s whose entries is in {0, ..., %s} enumerated up to the action of %s" % (self.n, self._sum, self._max_part, self.permutation_group()) else: - return "Integer vectors of length %s and of sum %s enumerated up to the action of %s"%(self.n, self._sum, self.permutation_group()) + return "Integer vectors of length %s and of sum %s enumerated up to the action of %s" % (self.n, self._sum, self.permutation_group()) else: - return "Integer vectors of length %s whose entries is in {0, ..., %s} enumerated up to the action of %s"%(self.n, self._max_part, self.permutation_group()) + return "Integer vectors of length %s whose entries is in {0, ..., %s} enumerated up to the action of %s" % (self.n, self._max_part, self.permutation_group()) def roots(self): r""" @@ -858,11 +858,11 @@ def retract(self, elt): """ # TODO: Once Sage integer vector will have a data structure # based on ClonableIntArray, remove the conversion intarray - assert len(elt) == self.n, "%s is a quotient set of %s"%(self, self.ambient()) + assert len(elt) == self.n, "%s is a quotient set of %s" % (self, self.ambient()) if self._sum is not None: - assert sum(elt) == self._sum, "%s is a quotient set of %s"%(self, self.ambient()) + assert sum(elt) == self._sum, "%s is a quotient set of %s" % (self, self.ambient()) if self._max_part >= 0: - assert max(elt) <= self._max_part, "%s is a quotient set of %s"%(self, self.ambient()) + assert max(elt) <= self._max_part, "%s is a quotient set of %s" % (self, self.ambient()) intarray = self.element_class(self, elt, check=False) return self.element_class(self, canonical_representative_of_orbit_of(self._sgs, intarray), check=False) diff --git a/src/sage/combinat/matrices/dancing_links.pyx b/src/sage/combinat/matrices/dancing_links.pyx index 12d0eea378a..ab43cef4260 100644 --- a/src/sage/combinat/matrices/dancing_links.pyx +++ b/src/sage/combinat/matrices/dancing_links.pyx @@ -135,7 +135,7 @@ cdef class dancing_linksWrapper: sage: x Dancing links solver for 3 columns and 2 rows sage: type(x) - <... 'sage.combinat.matrices.dancing_links.dancing_linksWrapper'> + TESTS: @@ -1064,17 +1064,17 @@ cdef class dancing_linksWrapper: # Construction of the columns (transpose of the rows) columns = [[] for _ in range(self.ncols())] - for i,row in enumerate(self.rows()): + for i, row in enumerate(self.rows()): for a in row: columns[a].append(i) # Constraints: exactly one 1 in each column - for j,column in enumerate(columns): + for j, column in enumerate(columns): S = p.sum(x[a] for a in column) name = "one 1 in {}-th column".format(j) - p.add_constraint(S==1, name=name) + p.add_constraint(S == 1, name=name) - return p,x + return p, x def one_solution_using_milp_solver(self, solver=None, integrality_tolerance=1e-3): r""" diff --git a/src/sage/combinat/multiset_partition_into_sets_ordered.py b/src/sage/combinat/multiset_partition_into_sets_ordered.py index 61bb667e2ba..1789a6d551a 100755 --- a/src/sage/combinat/multiset_partition_into_sets_ordered.py +++ b/src/sage/combinat/multiset_partition_into_sets_ordered.py @@ -2623,6 +2623,7 @@ def _has_nonempty_sets(x): and block and len(set(block)) == len(block)) for block in x) + def _union_of_sets(list_of_sets): """ Return the union of a list of iterables as a frozenset. @@ -2634,7 +2635,9 @@ def _union_of_sets(list_of_sets): sage: _union_of_sets(L) frozenset({1, 2, 3, 5, 6, 7}) """ - return reduce(lambda a,b: frozenset(a)|frozenset(b), list_of_sets, frozenset()) + return reduce(lambda a, b: frozenset(a) | frozenset(b), + list_of_sets, frozenset()) + def _concatenate(list_of_iters): """ diff --git a/src/sage/combinat/partitions.pyx b/src/sage/combinat/partitions.pyx index 12dc88c17b5..c528131892a 100644 --- a/src/sage/combinat/partitions.pyx +++ b/src/sage/combinat/partitions.pyx @@ -42,7 +42,7 @@ def ZS1_iterator(int n): sage: next(it) [4] sage: type(_) - <... 'list'> + """ # Easy cases. if n < 0: @@ -102,7 +102,7 @@ def ZS1_iterator_nk(int n, int k): sage: next(it) [4] sage: type(_) - <... 'list'> + """ # Easy cases. if n <= 0: @@ -137,7 +137,7 @@ def ZS1_iterator_nk(int n, int k): h -= 1 yield x[:m+1] else: - t = m - h + 1 # 1 + "the number of 1s to the right of x[h] that belong to the partition" + t = m - h + 1 # 1 + "the number of 1s to the right of x[h] that belong to the partition" r = x[h] - 1 # This loop finds the largest h such that x[:h] can be completed diff --git a/src/sage/combinat/posets/poset_examples.py b/src/sage/combinat/posets/poset_examples.py index c94a00a29db..f47310ccb35 100644 --- a/src/sage/combinat/posets/poset_examples.py +++ b/src/sage/combinat/posets/poset_examples.py @@ -213,7 +213,7 @@ def BooleanLattice(n, facade=None, use_subsets=False): if use_subsets: from sage.sets.set import Set - cur_level = [frozenset(range(1, n+1))] + cur_level = [frozenset(range(1, n + 1))] D = DiGraph() D.add_vertex(Set(cur_level[0])) while cur_level: @@ -227,7 +227,8 @@ def BooleanLattice(n, facade=None, use_subsets=False): return FiniteLatticePoset(D, category=FiniteLatticePosets(), facade=facade) - D = DiGraph({v: [Integer(v|(1< + sage: r {'a': 0, 'b': 1, 'c': 2} @@ -157,7 +157,7 @@ def count(): i = 0 while True: yield i - i+=1 + i += 1 counter = count() diff --git a/src/sage/combinat/root_system/root_lattice_realization_algebras.py b/src/sage/combinat/root_system/root_lattice_realization_algebras.py index ca2dba85e12..86b1e561f87 100644 --- a/src/sage/combinat/root_system/root_lattice_realization_algebras.py +++ b/src/sage/combinat/root_system/root_lattice_realization_algebras.py @@ -42,7 +42,7 @@ def _repr_(self): sage: RootSystem(["A",2,1]).ambient_space().algebra(QQ) # indirect doctest Algebra of the Ambient space of the Root system of type ['A', 2, 1] over Rational Field """ - return "Algebra of the %s over %s"%(self.basis().keys(),self.base_ring()) + return "Algebra of the %s over %s" % (self.basis().keys(), self.base_ring()) def some_elements(self): r""" @@ -1168,13 +1168,15 @@ def expand(self, alphabet): TESTS:: sage: type(p.expand(F.gens())) - <... 'sage.rings.polynomial.laurent_polynomial.LaurentPolynomial_mpair'> + sage: p = KL.zero() sage: p.expand(F.gens()) 0 sage: type(p.expand(F.gens())) - <... 'sage.rings.polynomial.laurent_polynomial.LaurentPolynomial_mpair'> + """ codomain = alphabet[0].parent() - return codomain.sum( c * prod(X**int(n) for X,n in zip(alphabet,vector(m))) for m,c in self) + return codomain.sum(c * prod(X**int(n) + for X, n in zip(alphabet, vector(m))) + for m, c in self) diff --git a/src/sage/combinat/root_system/type_reducible.py b/src/sage/combinat/root_system/type_reducible.py index 3943f5573fd..2a503a7ff58 100644 --- a/src/sage/combinat/root_system/type_reducible.py +++ b/src/sage/combinat/root_system/type_reducible.py @@ -56,7 +56,7 @@ class CartanType(SageObject, CartanType_abstract): super classes (see :meth:`~sage.combinat.root_system.cartan_type.CartanType_abstract._add_abstract_superclass`):: sage: t.__class__.mro() - [, , <... 'sage.structure.sage_object.SageObject'>, , , , <... 'object'>] + [, , , , , , ] The index set of the reducible Cartan type is obtained by relabelling successively the nodes of the Dynkin diagrams of @@ -134,7 +134,7 @@ def __init__(self, types): if all(isinstance(t, cls) for t in types) ) self._add_abstract_superclass(super_classes) - def _repr_(self, compact = True): # We should make a consistent choice here + def _repr_(self, compact=True): # We should make a consistent choice here """ EXAMPLES:: @@ -144,7 +144,7 @@ def _repr_(self, compact = True): # We should make a consistent choice here sage: CartanType("A2",CartanType("F4~").dual()) A2xF4~* """ - return "x".join(t._repr_(compact = True) for t in self._types) + return "x".join(t._repr_(compact=True) for t in self._types) def _latex_(self): r""" diff --git a/src/sage/combinat/root_system/weight_lattice_realizations.py b/src/sage/combinat/root_system/weight_lattice_realizations.py index bc9baf632b4..946d116fbde 100644 --- a/src/sage/combinat/root_system/weight_lattice_realizations.py +++ b/src/sage/combinat/root_system/weight_lattice_realizations.py @@ -248,8 +248,8 @@ def _test_weight_lattice_realization(self, **options): sage: RootSystem(['A',3]).weight_lattice()._test_weight_lattice_realization() """ from sage.rings.integer_ring import ZZ - tester = self._tester(**options) - Lambda = self.fundamental_weights() + tester = self._tester(**options) + Lambda = self.fundamental_weights() alphacheck = self.simple_coroots() tester.assertEqual(tuple(Lambda.keys()), self.index_set()) @@ -868,7 +868,7 @@ def weyl_dimension(self, highest_weight): 16 sage: type(RootSystem(['A',3]).ambient_lattice().weyl_dimension([2,1,0,0])) - <... 'sage.rings.integer.Integer'> + """ highest_weight = self(highest_weight) if not highest_weight.is_dominant(): diff --git a/src/sage/combinat/skew_partition.py b/src/sage/combinat/skew_partition.py index 585e1802c74..ab84c33b0af 100644 --- a/src/sage/combinat/skew_partition.py +++ b/src/sage/combinat/skew_partition.py @@ -1005,7 +1005,7 @@ def to_list(self): sage: s.to_list() [[4, 3, 1], [2]] sage: type(s.to_list()) - <... 'list'> + """ return [list(_) for _ in list(self)] @@ -1504,9 +1504,9 @@ def from_row_and_column_length(self, rowL, colL): if not all(i>0 for i in rowL) or not all(i>0 for i in colL): raise ValueError("row and column length must be positive") if rowL == []: - return self.element_class(self, [[],[]]) + return self.element_class(self, [[], []]) colL_new = colL[:] - resIn = [] + resIn = [] resOut = [] inPOld = len(colL) for row in rowL: @@ -1714,13 +1714,10 @@ def _count_slide(self, co, overlap=0): sage: [ sp for sp in s if sp.row_lengths() == [2,1] ] [[2, 1] / []] """ - nn = len(co) result = 1 - for i in range(nn-1): - comb = min(co[i], co[i+1]) - comb += 1 - overlap - result *= comb - + shift = 1 - overlap + for i in range(len(co) - 1): + result *= min(co[i], co[i + 1]) + shift return result def cardinality(self): diff --git a/src/sage/combinat/sloane_functions.py b/src/sage/combinat/sloane_functions.py index 4307051be34..9ce8796a27a 100644 --- a/src/sage/combinat/sloane_functions.py +++ b/src/sage/combinat/sloane_functions.py @@ -5120,7 +5120,7 @@ def list(self, n): """ self._eval(n) # force computation return self._b[:n] - _k = 1 + _k = 1 class A000153(ExtremesOfPermanentsSequence): @@ -9170,7 +9170,7 @@ def trait_names(self): EXAMPLES:: sage: type(sloane.trait_names()) - <... 'list'> + """ try: return self.__trait_names diff --git a/src/sage/combinat/tableau.py b/src/sage/combinat/tableau.py index 6301ffd4a35..0976069a23d 100644 --- a/src/sage/combinat/tableau.py +++ b/src/sage/combinat/tableau.py @@ -2628,7 +2628,7 @@ def promotion_inverse(self, n): sage: T = Tableau([[1]]) sage: type(T.promotion_inverse(2)[0][0]) - <... 'sage.rings.integer.Integer'> + """ if self.is_rectangular(): n = Integer(n) diff --git a/src/sage/combinat/tiling.py b/src/sage/combinat/tiling.py index b34dad8f9ad..a3a5774a00d 100644 --- a/src/sage/combinat/tiling.py +++ b/src/sage/combinat/tiling.py @@ -426,15 +426,14 @@ def ncube_isometry_group_cosets(n, orientation_preserving=True): sage: [len(c) for c in cosets] [8, 8, 8, 8, 8, 8] sage: type(cosets[0][0]) - <... 'sage.matrix.matrix_rational_dense.Matrix_rational_dense'> - + """ from sage.misc.misc_c import prod from sage.matrix.constructor import diagonal_matrix G = ncube_isometry_group(n, orientation_preserving) # Construct the subgroup H of G of diagonal matrices - it = itertools.product((1,-1), repeat=n) + it = itertools.product((1, -1), repeat=n) if orientation_preserving: H = [diagonal_matrix(L) for L in it if prod(L) == 1] else: @@ -1490,7 +1489,7 @@ def self_surrounding(self, radius, remove_incomplete_copies=True, # Add one row to force the placement of the central tile coord_to_int = T.coord_to_int_dict() new_row = [coord_to_int[coord] for coord in self] - new_row.append(len(coord_to_int)) # to force this row in the solution + new_row.append(len(coord_to_int)) # to force this row in the solution forced_row_number = len(rows) rows.append(new_row) diff --git a/src/sage/combinat/words/finite_word.py b/src/sage/combinat/words/finite_word.py index 609e701f7c7..4fd441172eb 100644 --- a/src/sage/combinat/words/finite_word.py +++ b/src/sage/combinat/words/finite_word.py @@ -1321,7 +1321,7 @@ def factor_iterator(self, n=None): TESTS:: sage: type( Word('cacao').factor_iterator() ) - <... 'generator'> + """ return self.suffix_tree().factor_iterator(n) @@ -5288,15 +5288,15 @@ def _s(self, i): sage: w._s(1).parent() Finite words over {1, 2, 3} """ - unpaired_i = [] # positions of unpaired is - unpaired_ip = [] # positions of unpaired i+1s - for p,x in enumerate(self): + unpaired_i = [] # positions of unpaired is + unpaired_ip = [] # positions of unpaired i+1s + for p, x in enumerate(self): if x == i: if unpaired_ip: unpaired_ip.pop() else: unpaired_i.append(p) - elif x == i+1: + elif x == i + 1: unpaired_ip.append(p) unpaired = unpaired_i + unpaired_ip diff --git a/src/sage/combinat/words/words.py b/src/sage/combinat/words/words.py index 852fca48876..8666f86d0c0 100644 --- a/src/sage/combinat/words/words.py +++ b/src/sage/combinat/words/words.py @@ -408,7 +408,7 @@ def _element_classes(self): sage: d = FiniteWords()._element_classes sage: type(d) - <... 'dict'> + sage: len(d) 7 sage: e = FiniteWords('abcdefg')._element_classes @@ -1347,7 +1347,7 @@ def _element_classes(self): sage: d = InfiniteWords()._element_classes sage: type(d) - <... 'dict'> + sage: len(d) 4 sage: e = InfiniteWords('abcdefg')._element_classes From 4ce61292fa67176642483cebf239f5954e3118de Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Sat, 30 Oct 2021 21:51:14 +0200 Subject: [PATCH 048/126] bump gmp to version 6.2.1 --- build/pkgs/gmp/checksums.ini | 6 +++--- build/pkgs/gmp/package-version.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/pkgs/gmp/checksums.ini b/build/pkgs/gmp/checksums.ini index d2cf090de11..11a552f2352 100644 --- a/build/pkgs/gmp/checksums.ini +++ b/build/pkgs/gmp/checksums.ini @@ -1,5 +1,5 @@ tarball=gmp-VERSION.tar.xz -sha1=052a5411dc74054240eec58132d2cf41211d0ff6 -md5=a325e3f09e6d91e62101e59f9bda3ec1 -cksum=942462047 +sha1=0578d48607ec0e272177d175fd1807c30b00fdf2 +md5=0b82665c4a92fd2ade7440c13fcaa42b +cksum=1546558141 upstream_url=https://gmplib.org/download/gmp/gmp-VERSION.tar.xz diff --git a/build/pkgs/gmp/package-version.txt b/build/pkgs/gmp/package-version.txt index 6abaeb2f907..024b066c0bb 100644 --- a/build/pkgs/gmp/package-version.txt +++ b/build/pkgs/gmp/package-version.txt @@ -1 +1 @@ -6.2.0 +6.2.1 From c0486f849d83ad847469d083f186a3b2e5a7e63f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Mon, 1 Nov 2021 19:11:23 +0100 Subject: [PATCH 049/126] remove the "bound_method" py2/py3 doctest adapter --- .../coercion_and_categories.rst | 2 +- .../algebras/steenrod/steenrod_algebra.py | 4 +- src/sage/categories/algebras_with_basis.py | 2 +- src/sage/categories/category_with_axiom.py | 2 +- .../categories/examples/semigroups_cython.pyx | 6 +- src/sage/categories/finite_enumerated_sets.py | 16 ++--- .../categories/hopf_algebras_with_basis.py | 2 +- src/sage/categories/magmas.py | 2 +- src/sage/categories/realizations.py | 2 +- src/sage/categories/sets_cat.py | 5 +- src/sage/combinat/integer_lists/lists.py | 4 +- src/sage/combinat/root_system/plot.py | 10 ++-- src/sage/combinat/words/words.py | 4 +- src/sage/doctest/parsing.py | 58 +------------------ .../sets/disjoint_union_enumerated_sets.py | 4 +- src/sage/structure/category_object.pyx | 2 +- src/sage/structure/element.pyx | 4 +- 17 files changed, 36 insertions(+), 93 deletions(-) diff --git a/src/doc/en/thematic_tutorials/coercion_and_categories.rst b/src/doc/en/thematic_tutorials/coercion_and_categories.rst index 4a8d86c0ae9..846b68f5210 100644 --- a/src/doc/en/thematic_tutorials/coercion_and_categories.rst +++ b/src/doc/en/thematic_tutorials/coercion_and_categories.rst @@ -1742,7 +1742,7 @@ The new test is inherited from the category. Since ``an_element()`` is returning complicated element, ``_test_factorisation`` is a serious test:: sage: P.an_element()._test_factorisation - + .. end of output diff --git a/src/sage/algebras/steenrod/steenrod_algebra.py b/src/sage/algebras/steenrod/steenrod_algebra.py index 3eb15efd811..a9120b91415 100644 --- a/src/sage/algebras/steenrod/steenrod_algebra.py +++ b/src/sage/algebras/steenrod/steenrod_algebra.py @@ -2628,7 +2628,7 @@ def gens(self): sage: A3 = SteenrodAlgebra(3, 'adem') sage: A3.gens() - Lazy family ((i))_{i in Non negative integers} + Lazy family ((i))_{i in Non negative integers} sage: A3.gens()[0] beta sage: A3.gens()[1] @@ -2647,7 +2647,7 @@ def gens(self): sage: SteenrodAlgebra(p=5, profile=[[2,1], [2,2,2]]).gens() Family (Q_0, P(1), P(5)) sage: SteenrodAlgebra(profile=lambda n: n).gens() - Lazy family ((i))_{i in Non negative integers} + Lazy family ((i))_{i in Non negative integers} You may also use ``algebra_generators`` instead of ``gens``:: diff --git a/src/sage/categories/algebras_with_basis.py b/src/sage/categories/algebras_with_basis.py index 701b428a836..972c9a94b76 100644 --- a/src/sage/categories/algebras_with_basis.py +++ b/src/sage/categories/algebras_with_basis.py @@ -56,7 +56,7 @@ class AlgebrasWithBasis(CategoryWithAxiom_over_base_ring): B[word: acb] sage: A.product - sage: A.product(a*b,b) B[word: abb] diff --git a/src/sage/categories/category_with_axiom.py b/src/sage/categories/category_with_axiom.py index 075e1542a7b..cbd3823ab5e 100644 --- a/src/sage/categories/category_with_axiom.py +++ b/src/sage/categories/category_with_axiom.py @@ -358,7 +358,7 @@ class from the base category class:: nested class ``Ds.Green`` or not (an implementation detail):: sage: Cs().Green - + Thanks to this feature (implemented in :meth:`CategoryWithAxiom.__classget__`), the user is systematically referred to the documentation of this diff --git a/src/sage/categories/examples/semigroups_cython.pyx b/src/sage/categories/examples/semigroups_cython.pyx index 6b6e179bc3a..c05ab880fb6 100644 --- a/src/sage/categories/examples/semigroups_cython.pyx +++ b/src/sage/categories/examples/semigroups_cython.pyx @@ -189,17 +189,17 @@ class LeftZeroSemigroup(LeftZeroSemigroupPython): That's really the only method which is obtained from the category ... :: sage: S(42).is_idempotent - + sage: S(42).is_idempotent() True sage: S(42)._pow_int - + sage: S(42)^10 42 sage: S(42).is_idempotent - + sage: S(42).is_idempotent() True """ diff --git a/src/sage/categories/finite_enumerated_sets.py b/src/sage/categories/finite_enumerated_sets.py index 0f423dbb5de..b4f98de21f2 100644 --- a/src/sage/categories/finite_enumerated_sets.py +++ b/src/sage/categories/finite_enumerated_sets.py @@ -117,7 +117,7 @@ def _cardinality_from_iterator(self, *ignored_args, **ignored_kwds): sage: class FreshExample(Example): pass sage: C = FreshExample(); C.rename("FreshExample") sage: C.cardinality - + This method shall return an ``Integer``; we test this here, because :meth:`_test_enumerated_set_iter_cardinality` @@ -323,21 +323,21 @@ def _list_from_iterator(self): sage: class FreshExample(Example): pass sage: C = FreshExample(); C.rename("FreshExample") sage: C.list - + sage: C.unrank - + sage: C.cardinality - + sage: l1 = C.list(); l1 [1, 2, 3] sage: C.list - + sage: C.unrank - + sage: C.cardinality - + sage: C.__iter__ - + We finally check that nothing breaks before and after calling explicitly the method ``.list()``:: diff --git a/src/sage/categories/hopf_algebras_with_basis.py b/src/sage/categories/hopf_algebras_with_basis.py index e5e0e05fe57..f74ff60b7dd 100644 --- a/src/sage/categories/hopf_algebras_with_basis.py +++ b/src/sage/categories/hopf_algebras_with_basis.py @@ -58,7 +58,7 @@ class HopfAlgebrasWithBasis(CategoryWithAxiom_over_base_ring): B[(1,2)] sage: A.product # todo: not quite ... - + sage: A.product(b,b) B[()] diff --git a/src/sage/categories/magmas.py b/src/sage/categories/magmas.py index 5aa2b09e0c4..a2707f5f3dd 100644 --- a/src/sage/categories/magmas.py +++ b/src/sage/categories/magmas.py @@ -1185,7 +1185,7 @@ def product_by_coercion(self, left, right): sage: Out = Sets().WithRealizations().example().Out(); Out The subset algebra of {1, 2, 3} over Rational Field in the Out basis sage: Out.product - + sage: Out.product.__module__ 'sage.categories.magmas' sage: x = Out.an_element() diff --git a/src/sage/categories/realizations.py b/src/sage/categories/realizations.py index 757b2f3aba3..1d64bca5f03 100644 --- a/src/sage/categories/realizations.py +++ b/src/sage/categories/realizations.py @@ -36,7 +36,7 @@ class RealizationsCategory(RegressiveCovariantConstructionCategory): TESTS:: sage: Sets().Realizations - + sage: Sets().Realizations() Category of realizations of sets sage: Sets().Realizations().super_categories() diff --git a/src/sage/categories/sets_cat.py b/src/sage/categories/sets_cat.py index fdebfd93799..f86d8e961ea 100644 --- a/src/sage/categories/sets_cat.py +++ b/src/sage/categories/sets_cat.py @@ -956,14 +956,13 @@ def _element_constructor_(self): sage: A.element_class sage: A._element_constructor_ - + sage: B = SymmetricGroup(3).algebra(ZZ) sage: B.element_class <...SymmetricGroupAlgebra_n_with_category.element_class'> sage: B._element_constructor_ - + """ if hasattr(self, "element_class"): return self._element_constructor_from_element_class diff --git a/src/sage/combinat/integer_lists/lists.py b/src/sage/combinat/integer_lists/lists.py index 8795add6e56..5143e5cb5e8 100644 --- a/src/sage/combinat/integer_lists/lists.py +++ b/src/sage/combinat/integer_lists/lists.py @@ -299,7 +299,7 @@ def _element_constructor_default(self, l): ....: Element = MyElt sage: L = MyIntegersLists(5) sage: L._element_constructor_ - + """ return self.element_class(self, l) @@ -320,7 +320,7 @@ def _element_constructor_nocheck(self, l): iterator:: sage: L._element_constructor_ - + sage: L._element_constructor_([1,2,3]) [1, 2, 3] """ diff --git a/src/sage/combinat/root_system/plot.py b/src/sage/combinat/root_system/plot.py index 41371737f7a..706cc57fc18 100644 --- a/src/sage/combinat/root_system/plot.py +++ b/src/sage/combinat/root_system/plot.py @@ -846,7 +846,7 @@ def __init__(self, space, 2 sage: options._projections [Weight space over the Rational Field of the Root system of type ['B', 2], - ] + ] sage: L = RootSystem(['B',2,1]).ambient_space() sage: options = L.plot_parse_options() @@ -854,24 +854,24 @@ def __init__(self, space, 2 sage: options._projections [Ambient space of the Root system of type ['B', 2], - ] + ] sage: options = L.plot_parse_options(affine=True) sage: options.dimension 2 sage: options._projections [Ambient space of the Root system of type ['B', 2], - ] + ] sage: options = L.plot_parse_options(affine=False) sage: options._projections - [] + [] sage: options.dimension 3 sage: options = L.plot_parse_options(affine=False, projection='barycentric') sage: options._projections - [] + [] sage: options.dimension 3 """ diff --git a/src/sage/combinat/words/words.py b/src/sage/combinat/words/words.py index 852fca48876..03c13796e9d 100644 --- a/src/sage/combinat/words/words.py +++ b/src/sage/combinat/words/words.py @@ -135,9 +135,9 @@ def __init__(self, alphabet=None, category=None): True sage: Words('abc').sortkey_letters - + sage: Words('bac').sortkey_letters - + """ if isinstance(alphabet, (int, Integer)): from sage.sets.integer_range import IntegerRange diff --git a/src/sage/doctest/parsing.py b/src/sage/doctest/parsing.py index 3346ca14a24..4378c45c713 100644 --- a/src/sage/doctest/parsing.py +++ b/src/sage/doctest/parsing.py @@ -173,59 +173,6 @@ def normalize_long_repr(s): return _long_repr_re.sub(lambda m: m.group(1), s) -_normalize_bound_method_re = re.compile( - r'[^. ]+)\sof\s(?P.+)>', re.M | re.S) - -def normalize_bound_method_repr(s): - """ - Normalize differences between Python 2 and 3 in how bound methods are - represented. - - On Python 2 bound methods are represented using the class name of the - object the method was bound to, whereas on Python 3 they are represented - with the fully-qualified name of the function that implements the method. - - In the context of a doctest it's almost impossible to convert accurately - from the latter to the former or vice-versa, so we simplify the reprs of - bound methods to just the bare method name. - - This is slightly regressive since it means one can't use the repr of a - bound method to test whether some element is getting a method from the - correct class (important sometimes in the cases of dynamic classes). - However, such tests could be written could be written more explicitly to - emphasize that they are testing such behavior. - - EXAMPLES: - - :: - - sage: from sage.doctest.parsing import normalize_bound_method_repr - sage: el = Semigroups().example().an_element() - sage: el - 42 - sage: el.is_idempotent - - sage: normalize_bound_method_repr(repr(el.is_idempotent)) - '' - - An example where the object ``repr`` contains whitespace:: - - sage: U = DisjointUnionEnumeratedSets( - ....: Family([1, 2, 3], Partitions), facade=False) - sage: U._element_constructor_ - - sage: normalize_bound_method_repr(repr(U._element_constructor_)) - '' - """ - - def subst(m): - return ''.format(**m.groupdict()) - - return _normalize_bound_method_re.sub(subst, s) - - # Collection of fixups applied in the SageOutputChecker. Each element in this # this list a pair of functions applied to the actual test output ('g' for # "got") and the expected test output ('w' for "wanted"). The first function @@ -240,10 +187,7 @@ def subst(m): (lambda g, w: 'u"' in w or "u'" in w, lambda g, w: (g, remove_unicode_u(w))), (lambda g, w: 'L' in w or 'l' in w, - lambda g, w: (g, normalize_long_repr(w))), - (lambda g, w: ' sage: U = DisjointUnionEnumeratedSets( ....: Family([1,2,3], Partitions), facade=True) sage: U._element_constructor_ - """ if not self._facade: diff --git a/src/sage/structure/category_object.pyx b/src/sage/structure/category_object.pyx index 98ab3d16a45..334ee91430d 100644 --- a/src/sage/structure/category_object.pyx +++ b/src/sage/structure/category_object.pyx @@ -782,7 +782,7 @@ cdef class CategoryObject(SageObject): its categories, that is from ``EuclideanDomains().parent_class``:: sage: ZZ._test_associativity - + sage: ZZ._test_associativity(verbose = True) sage: TestSuite(ZZ).run(verbose = True) running ._test_additive_associativity() . . . pass diff --git a/src/sage/structure/element.pyx b/src/sage/structure/element.pyx index 76df456113e..369d3e25f18 100644 --- a/src/sage/structure/element.pyx +++ b/src/sage/structure/element.pyx @@ -474,7 +474,7 @@ cdef class Element(SageObject): category of ``CommutativeRings()``:: sage: 1.is_idempotent - + sage: 1.is_idempotent.__module__ 'sage.categories.magmas' @@ -485,7 +485,7 @@ cdef class Element(SageObject): ... AttributeError: 'sage.rings.integer.Integer' object has no attribute 'blah_blah' sage: Semigroups().example().an_element().is_idempotent - + sage: Semigroups().example().an_element().blah_blah Traceback (most recent call last): ... From d5058483689a479fa5ea0b29ad625437fa0272fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Labb=C3=A9?= Date: Tue, 2 Nov 2021 15:49:05 +0100 Subject: [PATCH 050/126] 32813: added description to script 'sage -t' --- src/bin/sage-runtests | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/bin/sage-runtests b/src/bin/sage-runtests index d7a416185f8..6b73e07cbab 100755 --- a/src/bin/sage-runtests +++ b/src/bin/sage-runtests @@ -28,7 +28,10 @@ def _get_optional_defaults(): if __name__ == "__main__": - parser = argparse.ArgumentParser(usage="sage -t [options] filenames") + parser = argparse.ArgumentParser(usage="sage -t [options] filenames", + description="Run all tests in a file or a list of files whose extensions " + "are one of the following: " + ".py, .pyx, .pxd, .pxi, .sage, .spyx, .tex, .rst.") parser.add_argument("-p", "--nthreads", dest="nthreads", type=int, nargs='?', const=0, default=1, metavar="N", help="tests in parallel using N threads with 0 interpreted as max(2, min(8, cpu_count()))") From cb2cb0023271428c7f498fd25cd7237760104071 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Labb=C3=A9?= Date: Tue, 2 Nov 2021 15:49:43 +0100 Subject: [PATCH 051/126] 32813: improved error message for invalid extension file provided to 'sage -t' --- src/sage/doctest/sources.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/sage/doctest/sources.py b/src/sage/doctest/sources.py index 7acb33de658..f9f9259da5f 100644 --- a/src/sage/doctest/sources.py +++ b/src/sage/doctest/sources.py @@ -514,7 +514,8 @@ def __init__(self, path, options): self.path = path DocTestSource.__init__(self, options) base, ext = os.path.splitext(path) - if ext in ('.py', '.pyx', '.pxd', '.pxi', '.sage', '.spyx'): + valid_code_ext = ('.py', '.pyx', '.pxd', '.pxi', '.sage', '.spyx') + if ext in valid_code_ext: self.__class__ = dynamic_class('PythonFileSource',(FileDocTestSource,PythonSource)) self.encoding = "utf-8" elif ext == '.tex': @@ -524,7 +525,9 @@ def __init__(self, path, options): self.__class__ = dynamic_class('RestFileSource',(FileDocTestSource,RestSource)) self.encoding = "utf-8" else: - raise ValueError("unknown file extension %r"%ext) + valid_ext = ", ".join(valid_code_ext + ('.tex', '.rst')) + raise ValueError("unknown extension (={}) for the file to test," + " valid extensions are: {}".format(ext, valid_ext)) def __iter__(self): r""" From 0f7cca71c8faebaae554fddd0d3ae0ff00e51195 Mon Sep 17 00:00:00 2001 From: Jonathan Kliem Date: Wed, 3 Nov 2021 11:22:16 +0100 Subject: [PATCH 052/126] euclidean division may still work, if the leading coefficient is not a unit --- .../polynomial/polynomial_element_generic.py | 41 ++++++++++++------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/src/sage/rings/polynomial/polynomial_element_generic.py b/src/sage/rings/polynomial/polynomial_element_generic.py index a8a5065f827..275470b15fd 100644 --- a/src/sage/rings/polynomial/polynomial_element_generic.py +++ b/src/sage/rings/polynomial/polynomial_element_generic.py @@ -767,16 +767,20 @@ def quo_rem(self, other): Returns the quotient and remainder of the Euclidean division of ``self`` and ``other``. - Raises ZerodivisionError if ``other`` is zero. Raises ArithmeticError - if ``other`` has a nonunit leading coefficient. + Raises ZerodivisionError if ``other`` is zero. + + Raises ArithmeticError if ``other`` has a nonunit leading coefficient + and this causes the Euclidean division to fail. EXAMPLES:: - sage: P. = PolynomialRing(ZZ,sparse=True) - sage: R. = PolynomialRing(P,sparse=True) + sage: P. = PolynomialRing(ZZ, sparse=True) + sage: R. = PolynomialRing(P, sparse=True) sage: f = R.random_element(10) - sage: g = y^5+R.random_element(4) - sage: q,r = f.quo_rem(g) + sage: while x.divides(f.leading_coefficient()): + ....: f = R.random_element(10) + sage: g = y^5 + R.random_element(4) + sage: q, r = f.quo_rem(g) sage: f == q*g + r and r.degree() < g.degree() True sage: g = x*y^5 @@ -790,25 +794,32 @@ def quo_rem(self, other): ... ZeroDivisionError: Division by zero polynomial + If the leading coefficient of ``other`` is not a unit, Euclidean division may still work:: + + sage: f = -x*y^10 + 2*x*y^7 + y^3 - 2*x^2*y^2 - y + sage: g = x*y^5 + sage: f.quo_rem(g) + (-y^5 + 2*y^2, y^3 - 2*x^2*y^2 - y) + TESTS:: - sage: P. = PolynomialRing(ZZ,sparse=True) - sage: f = x^10-4*x^6-5 - sage: g = 17*x^22+x^15-3*x^5+1 - sage: q,r = g.quo_rem(f) + sage: P. = PolynomialRing(ZZ, sparse=True) + sage: f = x^10 - 4*x^6 - 5 + sage: g = 17*x^22 + x^15 - 3*x^5 + 1 + sage: q, r = g.quo_rem(f) sage: g == f*q + r and r.degree() < f.degree() True sage: zero = P(0) sage: zero.quo_rem(f) (0, 0) sage: Q. = IntegerModRing(14)[] - sage: f = y^10-4*y^6-5 - sage: g = 17*y^22+y^15-3*y^5+1 - sage: q,r = g.quo_rem(f) + sage: f = y^10 - 4*y^6 - 5 + sage: g = 17*y^22 + y^15 - 3*y^5 + 1 + sage: q, r = g.quo_rem(f) sage: g == f*q + r and r.degree() < f.degree() True - sage: f += 2*y^10 # 3 is invertible mod 14 - sage: q,r = g.quo_rem(f) + sage: f += 2*y^10 # 3 is invertible mod 14 + sage: q, r = g.quo_rem(f) sage: g == f*q + r and r.degree() < f.degree() True From bb58f1b8e29ea4589ab309205e2fdebff6ece52d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Labb=C3=A9?= Date: Wed, 3 Nov 2021 12:06:47 +0100 Subject: [PATCH 053/126] 32813: also provide the filename in error message not only the wrong extension --- src/sage/doctest/sources.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/sage/doctest/sources.py b/src/sage/doctest/sources.py index f9f9259da5f..f60c275af74 100644 --- a/src/sage/doctest/sources.py +++ b/src/sage/doctest/sources.py @@ -495,6 +495,18 @@ class FileDocTestSource(DocTestSource): TESTS:: sage: TestSuite(FDS).run() + + :: + + sage: from sage.doctest.control import DocTestDefaults + sage: from sage.doctest.sources import FileDocTestSource + sage: filename = tmp_filename(ext=".txtt") + sage: FDS = FileDocTestSource(filename,DocTestDefaults()) + Traceback (most recent call last): + ... + ValueError: unknown extension for the file to test (=...txtt), + valid extensions are: .py, .pyx, .pxd, .pxi, .sage, .spyx, .tex, .rst + """ def __init__(self, path, options): """ @@ -526,8 +538,8 @@ def __init__(self, path, options): self.encoding = "utf-8" else: valid_ext = ", ".join(valid_code_ext + ('.tex', '.rst')) - raise ValueError("unknown extension (={}) for the file to test," - " valid extensions are: {}".format(ext, valid_ext)) + raise ValueError("unknown extension for the file to test (={})," + " valid extensions are: {}".format(path, valid_ext)) def __iter__(self): r""" From 70c97a544569939d2210efb75be8aec5893c72c8 Mon Sep 17 00:00:00 2001 From: LLewark Date: Wed, 3 Nov 2021 13:53:02 +0100 Subject: [PATCH 054/126] Currently, the determinant is implemented only for knots. However, the determinant for multi-component links is defined in the same way as for knots. So I propose to allow multi-component links in the determinant function. Moreover, it seems simpler to take determinant of the symmetrized Seifert matrix, instead of the evaluation of the Alexander polynomial at -1. --- src/sage/knots/link.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/sage/knots/link.py b/src/sage/knots/link.py index ff7a64eee4f..ec8ad1399c1 100644 --- a/src/sage/knots/link.py +++ b/src/sage/knots/link.py @@ -1926,19 +1926,19 @@ def determinant(self): sage: L = Link(B([1]*16 + [2,1,2,1,2,2,2,2,2,2,2,1,2,1,2,-1,2,-2])) sage: L.determinant() 65 + sage: B = BraidGroup(3) + sage: Link(B([1, 2, 1, 1, 2])).determinant() + 4 TESTS:: + sage: B = BraidGroup(3) sage: Link(B([1, 2, 1, -2, -1])).determinant() - Traceback (most recent call last): - ... - NotImplementedError: determinant implemented only for knots + 0 """ - if self.is_knot(): - a = self.alexander_polynomial() - return Integer(abs(a(-1))) - - raise NotImplementedError("determinant implemented only for knots") + V = self.seifert_matrix() + m = V + V.transpose() + return Integer(abs(m.det())) def is_alternating(self): r""" From 69e5084843796bdf02985a203a2d8c30de774f20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Wed, 3 Nov 2021 20:59:25 +0100 Subject: [PATCH 055/126] fix E713 and E714 in geometry --- src/sage/geometry/cone.py | 4 ++-- src/sage/geometry/cone_catalog.py | 4 ++-- src/sage/geometry/hasse_diagram.py | 2 +- src/sage/geometry/lattice_polytope.py | 6 +++--- src/sage/geometry/newton_polygon.py | 4 ++-- src/sage/geometry/polyhedron/backend_cdd.py | 2 +- src/sage/geometry/polyhedron/base_mutable.py | 2 +- src/sage/geometry/toric_lattice.py | 2 +- src/sage/geometry/triangulation/element.py | 6 +++--- src/sage/geometry/triangulation/point_configuration.py | 5 ++--- 10 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/sage/geometry/cone.py b/src/sage/geometry/cone.py index 5fbe3784b80..5f0d2d84fa5 100644 --- a/src/sage/geometry/cone.py +++ b/src/sage/geometry/cone.py @@ -1520,7 +1520,7 @@ def __init__(self, rays=None, lattice=None, self._ambient_ray_indices = tuple(ambient_ray_indices) superinit(ambient.rays(self._ambient_ray_indices), ambient.lattice()) - if not PPL is None: + if PPL is not None: self._PPL_C_Polyhedron = PPL def _sage_input_(self, sib, coerced): @@ -5466,7 +5466,7 @@ def random_element(self, ring=ZZ): sage: sum(K.random_element() for i in range(10)) in K.lattice() True """ - if not ring in [ZZ, QQ]: + if ring not in [ZZ, QQ]: # This cone theoretically lives in a real vector space, # but in Sage, we work over the rationals to avoid # numerical issues. Thus ``ring`` must consist of diff --git a/src/sage/geometry/cone_catalog.py b/src/sage/geometry/cone_catalog.py index 005f341e353..980d2e55c38 100644 --- a/src/sage/geometry/cone_catalog.py +++ b/src/sage/geometry/cone_catalog.py @@ -470,12 +470,12 @@ def rearrangement(p, ambient_dim=None, lattice=None): (ambient_dim, lattice) = _preprocess_args(ambient_dim, lattice) - if p < 1 or p > ambient_dim or not p in ZZ: + if p < 1 or p > ambient_dim or p not in ZZ: raise ValueError("order p=%s should be an integer between 1 " "and ambient_dim=%d, inclusive" % (p, ambient_dim)) I = matrix.identity(ZZ, ambient_dim) - M = matrix.ones(ZZ, ambient_dim) - p*I + M = matrix.ones(ZZ, ambient_dim) - p * I G = matrix.identity(ZZ, ambient_dim).rows() + M.rows() return Cone(G, lattice=lattice) diff --git a/src/sage/geometry/hasse_diagram.py b/src/sage/geometry/hasse_diagram.py index 29c46604e56..eeed5f560d9 100644 --- a/src/sage/geometry/hasse_diagram.py +++ b/src/sage/geometry/hasse_diagram.py @@ -157,7 +157,7 @@ def default_face_constructor(atoms, coatoms, **kwds): # Now G == {H[atom] : atom in minimals} for atom in minimals: # 9: for g in G: g_atoms, g_coatoms = H[atom] - if not required_atoms is None: + if required_atoms is not None: if g_atoms.isdisjoint(required_atoms): continue if (g_atoms, g_coatoms) in faces: diff --git a/src/sage/geometry/lattice_polytope.py b/src/sage/geometry/lattice_polytope.py index a02d9ed9d5a..9e663d40ea0 100644 --- a/src/sage/geometry/lattice_polytope.py +++ b/src/sage/geometry/lattice_polytope.py @@ -5520,10 +5520,10 @@ def convex_hull(points): vpoints = [] for p in points: v = vector(ZZ, p) - if not v in vpoints: + if v not in vpoints: vpoints.append(v) p0 = vpoints[0] - vpoints = [p-p0 for p in vpoints] + vpoints = [p - p0 for p in vpoints] N = ZZ**p0.degree() H = N.submodule(vpoints) if H.rank() == 0: @@ -5534,7 +5534,7 @@ def convex_hull(points): H_points = [H.coordinates(p) for p in vpoints] H_polytope = LatticePolytope(H_points) vpoints = (H_polytope.vertices() * H.basis_matrix()).rows(copy=False) - vpoints = [p+p0 for p in vpoints] + vpoints = [p + p0 for p in vpoints] return vpoints diff --git a/src/sage/geometry/newton_polygon.py b/src/sage/geometry/newton_polygon.py index ad977843958..7bd135abad0 100644 --- a/src/sage/geometry/newton_polygon.py +++ b/src/sage/geometry/newton_polygon.py @@ -723,7 +723,7 @@ def _element_constructor_(self, arg, sort_slopes=True, last_slope=Infinity): return self.element_class(polyhedron, parent=self) if arg == 1: polyhedron = Polyhedron(base_ring=self.base_ring(), - vertices=[(0,0)], rays=[(0,1)]) + vertices=[(0, 0)], rays=[(0, 1)]) return self.element_class(polyhedron, parent=self) if not isinstance(arg, list): try: @@ -736,7 +736,7 @@ def _element_constructor_(self, arg, sort_slopes=True, last_slope=Infinity): x = y = 0 vertices = [(x, y)] for slope in arg: - if not slope in self.base_ring(): + if slope not in self.base_ring(): raise TypeError("argument must be a list of coordinates or a list of (rational) slopes") x += 1 y += slope diff --git a/src/sage/geometry/polyhedron/backend_cdd.py b/src/sage/geometry/polyhedron/backend_cdd.py index 3a24dca5cb2..9f1f4d86ec5 100644 --- a/src/sage/geometry/polyhedron/backend_cdd.py +++ b/src/sage/geometry/polyhedron/backend_cdd.py @@ -292,7 +292,7 @@ def parse_H_representation(intro, data): from itertools import chain # We add equations to the end of the Hrepresentation. for i in chain( - (j for j in range(len(data)) if not j in equations), + (j for j in range(len(data)) if j not in equations), equations): line = data[i] coefficients = [R(x) for x in line] diff --git a/src/sage/geometry/polyhedron/base_mutable.py b/src/sage/geometry/polyhedron/base_mutable.py index d982135f1f5..6cf6a911eda 100644 --- a/src/sage/geometry/polyhedron/base_mutable.py +++ b/src/sage/geometry/polyhedron/base_mutable.py @@ -128,7 +128,7 @@ def _add_dependent_object(self, ob): sage: r Relative interior of None """ - if not ob._polyhedron is self: + if ob._polyhedron is not self: raise ValueError self._dependent_objects.append(ob) diff --git a/src/sage/geometry/toric_lattice.py b/src/sage/geometry/toric_lattice.py index e8920bfb701..7e566dc39cc 100644 --- a/src/sage/geometry/toric_lattice.py +++ b/src/sage/geometry/toric_lattice.py @@ -1170,7 +1170,7 @@ def dual(self): 2-d lattice, quotient of 3-d lattice M by Sublattice """ if "_dual" not in self.__dict__: - if not self is self.saturation(): + if self is not self.saturation(): raise ValueError("only dual lattices of saturated sublattices " "can be constructed! Got %s." % self) self._dual = (self.ambient_module().dual() / diff --git a/src/sage/geometry/triangulation/element.py b/src/sage/geometry/triangulation/element.py index 9aea06b7fb5..0c1544e9a6d 100644 --- a/src/sage/geometry/triangulation/element.py +++ b/src/sage/geometry/triangulation/element.py @@ -92,7 +92,7 @@ def triangulation_render_2d(triangulation, **kwds): all_lines.append(l) else: interior_lines.append(l) - exterior_lines = [ l for l in all_lines if not l in interior_lines ] + exterior_lines = [l for l in all_lines if l not in interior_lines] plot_interior_lines = sum([ line2d([ coord[l[0]], coord[l[1]] ], zorder=1, rgbcolor=(0,1,0), **kwds) @@ -160,7 +160,7 @@ def triangulation_render_3d(triangulation, **kwds): all_lines.append(l) else: interior_lines.append(l) - exterior_lines = [ l for l in all_lines if not l in interior_lines ] + exterior_lines = [l for l in all_lines if l not in interior_lines] from sage.plot.plot3d.texture import Texture line_int = Texture(color='darkblue', ambient=1, diffuse=0) @@ -190,7 +190,7 @@ def triangulation_render_3d(triangulation, **kwds): all_triangs.append(l) else: interior_triangs.append(l) - exterior_triangs = [ l for l in all_triangs if not l in interior_triangs ] + exterior_triangs = [l for l in all_triangs if l not in interior_triangs] plot_interior_triangs = \ sum([ polygon3d([coord[t[0]], coord[t[1]], coord[t[2]]], diff --git a/src/sage/geometry/triangulation/point_configuration.py b/src/sage/geometry/triangulation/point_configuration.py index 0346c9cdac4..b10fb8cbba6 100644 --- a/src/sage/geometry/triangulation/point_configuration.py +++ b/src/sage/geometry/triangulation/point_configuration.py @@ -1273,8 +1273,8 @@ def exclude_points(self, point_idx_list): sage: p.exclude_points( p.face_interior(codim=1) ).points() (P(-1, 0), P(0, 0), P(1, -1), P(1, 1)) """ - points = [ self.point(i) for i in range(self.n_points()) - if not i in point_idx_list ] + points = [self.point(i) for i in range(self.n_points()) + if i not in point_idx_list] return PointConfiguration(points, projective=False, connected=self._connected, @@ -1282,7 +1282,6 @@ def exclude_points(self, point_idx_list): regular=self._regular, star=self._star) - def volume(self, simplex=None): """ Find n! times the n-volume of a simplex of dimension n. From 16cff67f866c39d01f2038bf59f2a239fa2dfdde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Wed, 3 Nov 2021 21:12:59 +0100 Subject: [PATCH 056/126] fix E713 and E714 in dynamics --- .../dynamics/arithmetic_dynamics/affine_ds.py | 4 +- .../endPN_automorphism_group.py | 20 +++++----- .../arithmetic_dynamics/generic_ds.py | 4 +- .../arithmetic_dynamics/projective_ds.py | 38 +++++++++--------- .../dynamics/arithmetic_dynamics/wehlerK3.py | 40 +++++++++---------- 5 files changed, 54 insertions(+), 52 deletions(-) diff --git a/src/sage/dynamics/arithmetic_dynamics/affine_ds.py b/src/sage/dynamics/arithmetic_dynamics/affine_ds.py index 84ddb002252..219a32d4db0 100644 --- a/src/sage/dynamics/arithmetic_dynamics/affine_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/affine_ds.py @@ -980,12 +980,12 @@ def orbit_structure(self, P): orbit = [] index = 1 Q = P - while not Q in orbit: + while Q not in orbit: orbit.append(Q) Q = self(Q) index += 1 I = orbit.index(Q) - return([I, index-I-1]) + return([I, index - I - 1]) def cyclegraph(self): r""" diff --git a/src/sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py b/src/sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py index ff2ea05b21c..85536d138fd 100644 --- a/src/sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py +++ b/src/sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py @@ -203,7 +203,8 @@ def automorphism_group_QQ_fixedpoints(rational_function, return_functions=False, psi = phi(phi(z)) f2 = psi.numerator() g2 = psi.denominator() - period2_points = [x for x in (f2 - z*g2).roots(multiplicities=False) if not x in rational_roots] + period2_points = [x for x in (f2 - z*g2).roots(multiplicities=False) + if x not in rational_roots] for S in Subsets(period2_points, 2): zeta = -1 alpha = S[0] @@ -760,8 +761,10 @@ def automorphism_group_QQ_CRT(rational_function, prime_lower_bound=4, return_fun return elements else: N = gcd(orderaut + [12]) #all orders of elements divide N - for order in [O for O in divisors(N) \ - if not O in badorders]: #range over all orders + for order in divisors(N): + if order in badorders: + continue + #range over all orders # that are possible over QQ such that we haven't already # found all elements of that order @@ -808,13 +811,12 @@ def automorphism_group_QQ_CRT(rational_function, prime_lower_bound=4, return_fun badorders.append(m) #no elements of that order or any order that # is a multiple of it - if len([order for order in divisors(N) \ - if not order in badorders]) == 0: + if all(order in badorders for order in divisors(N)): #found all elements of every possible order if iso_type: - return(elements, which_group(elements)) + return (elements, which_group(elements)) return elements - congruence = congruence*p + congruence = congruence * p p = primes.next(p) @@ -1918,7 +1920,7 @@ def conjugating_set_initializer(f, g): # does find a subset, then the subset will most likely minimize the combinatorics # of checking conjugations tup = greedy_independence_check(P, repeated_mult_L, point_to_mult_L) - if not tup is None: + if tup is not None: more = False source, corresponding = tup @@ -1974,7 +1976,7 @@ def conjugating_set_initializer(f, g): # we again do a greedy check for a subset of n+2 points, of which no n+1 # are linearly dependent tup = greedy_independence_check(P, repeated_mult_L, point_to_mult_L) - if not tup is None: + if tup is not None: more = False source, corresponding = tup if not more: diff --git a/src/sage/dynamics/arithmetic_dynamics/generic_ds.py b/src/sage/dynamics/arithmetic_dynamics/generic_ds.py index 0ad4d747f94..d5c26ac2cf3 100644 --- a/src/sage/dynamics/arithmetic_dynamics/generic_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/generic_ds.py @@ -160,7 +160,7 @@ def __classcall_private__(cls, morphism_or_polys, domain=None, names=None): """ if isinstance(morphism_or_polys, SchemeMorphism_polynomial): domain = morphism_or_polys.domain() - if not domain is None: + if domain is not None: if is_AffineSpace(domain) or isinstance(domain, AlgebraicScheme_subscheme_affine): from sage.dynamics.arithmetic_dynamics.affine_ds import DynamicalSystem_affine return DynamicalSystem_affine(morphism_or_polys, domain) @@ -640,7 +640,7 @@ def field_of_definition_preimage(self, point, n, return_embedding=False, simplif N = K if N.absolute_degree() == 1: if return_embedding: - return (QQ,ds.base_ring().embeddings(QQ)[0]) + return (QQ, ds.base_ring().embeddings(QQ)[0]) else: return QQ else: diff --git a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py index d4cb66af782..6f4ed4ed35e 100644 --- a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py @@ -1747,7 +1747,7 @@ def green_function(self, P, v, **kwds): BR = FractionField(P.codomain().base_ring()) GBR = self.change_ring(BR) #so the heights work - if not BR in NumberFields(): + if BR not in NumberFields(): raise NotImplementedError("must be over a number field or a number field order") if not BR.is_absolute(): raise TypeError("must be an absolute field") @@ -1962,8 +1962,8 @@ def canonical_height(self, P, **kwds): error_bound = kwds.get("error_bound", None) K = FractionField(self.codomain().base_ring()) - if not K in NumberFields(): - if not K is QQbar: + if K not in NumberFields(): + if K is not QQbar: raise NotImplementedError("must be over a number field or a number field order or QQbar") else: #since this an absolute height, we can compute the height of a QQbar point @@ -2014,7 +2014,7 @@ def canonical_height(self, P, **kwds): err = kwds.get('error_bound', None) #computes the error bound as defined in Algorithm 3.1 of [WELLS] if Res > 1: - if not err is None: + if err is not None: err = err / 2 N = ceil((R(Res).log().log() - R(d-1).log() - R(err).log())/(R(d).log())) if N < 1: @@ -2055,7 +2055,7 @@ def canonical_height(self, P, **kwds): emb = K.places(prec=prec) num_places = len(emb) + len(bad_primes) - if not error_bound is None: + if error_bound is not None: error_bound /= num_places R = RealField(prec) h = R.zero() @@ -2138,7 +2138,7 @@ def height_difference_bound(self, prec=None): 3.43967790223022 """ FF = FractionField(self.domain().base_ring()) #lift will only work over fields, so coercing into FF - if not FF in NumberFields(): + if FF not in NumberFields(): if FF == QQbar: #since this is absolute height, we can choose any number field over which the #function is defined. @@ -3950,7 +3950,7 @@ def critical_height(self, **kwds): crit_points = F.critical_points() n = len(crit_points) err_bound = kwds.get("error_bound", None) - if not err_bound is None: + if err_bound is not None: kwds["error_bound"] = err_bound / n ch = 0 for P in crit_points: @@ -5181,7 +5181,7 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', """ n = ZZ(n) - if not embedding is None: + if embedding is not None: raise ValueError('do not specify an embedding') if n < 1: raise ValueError("period must be a positive integer") @@ -5190,7 +5190,7 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', raise NotImplementedError("not implemented for subschemes") if self.degree() <= 1: raise TypeError("must have degree at least 2") - if not type in ['point', 'cycle']: + if type not in ['point', 'cycle']: raise ValueError("type must be either point or cycle") if dom.dimension_relative() > 1 or return_polynomial: if type == 'cycle': @@ -6282,10 +6282,10 @@ def all_periodic_points(self, **kwds): ValueError: algorithm must be 'dynatomic' or 'lifting' """ ring = kwds.pop("R", None) - if not ring is None: - #changes to the new ring + if ring is not None: + # changes to the new ring DS = self.change_ring(ring) - #ensures that the correct method is run, in case user switches to a finite field + # ensures that the correct method is run, in case user switches to a finite field return DS.all_periodic_points(**kwds) else: DS = self @@ -6329,7 +6329,7 @@ def all_periodic_points(self, **kwds): pt.insert(k,1) Q = PS(pt) #for each periodic point get the entire cycle - if not Q in periodic_points: + if Q not in periodic_points: #check periodic not preperiodic and add all points in cycle orb = set([Q]) Q2 = DS(Q) @@ -6347,7 +6347,7 @@ def all_periodic_points(self, **kwds): periods = kwds.pop("periods", None) badprimes = kwds.pop("bad_primes", None) num_cpus = kwds.pop("ncpus", ncpus()) - if not alg is None and alg not in ['dynatomic','lifting']: + if alg is not None and alg not in ['dynatomic', 'lifting']: raise ValueError("algorithm must be 'dynatomic' or 'lifting'") if not isinstance(primebound, (list, tuple)): @@ -6585,7 +6585,7 @@ def all_preperiodic_points(self, **kwds): (1/12*w + 1 : 1)] """ ring = kwds.pop("R",None) - if not ring is None: + if ring is not None: DS = self.change_ring(ring) else: DS = self @@ -6628,7 +6628,7 @@ def all_preperiodic_points(self, **kwds): pt.insert(k,1) Q = PS(pt) #for each preperiodic point get the entire connected component - if not Q in preper: + if Q not in preper: for t in DS.connected_rational_component(Q): preper.add(t) preper = list(preper) @@ -7351,7 +7351,7 @@ def is_polynomial(self): if self.codomain().dimension_relative() != 1: raise NotImplementedError("space must have dimension equal to 1") K = self.base_ring() - if not K in FiniteFields() and (not K in NumberFields() or not K.is_absolute()): + if K not in FiniteFields() and (K not in NumberFields() or not K.is_absolute()): raise NotImplementedError("must be over an absolute number field or finite field") if K in FiniteFields(): q = K.characteristic() @@ -7490,7 +7490,7 @@ def normal_form(self, return_conjugation=False): if self.codomain().dimension_relative() != 1: raise NotImplementedError("space must have dimension equal to 1") K = self.base_ring() - if not K in FiniteFields() and (not K in NumberFields() or not K.is_absolute()): + if K not in FiniteFields() and (K not in NumberFields() or not K.is_absolute()): raise NotImplementedError("must be over an absolute number field or finite field") if K in FiniteFields(): q = K.characteristic() @@ -8079,7 +8079,7 @@ def orbit_structure(self, P): Q.normalize_coordinates() F = copy(self) F.normalize_coordinates() - while not Q in orbit: + while Q not in orbit: orbit.append(Q) Q = F(Q) Q.normalize_coordinates() diff --git a/src/sage/dynamics/arithmetic_dynamics/wehlerK3.py b/src/sage/dynamics/arithmetic_dynamics/wehlerK3.py index c8ad02059fe..7e4ae461348 100644 --- a/src/sage/dynamics/arithmetic_dynamics/wehlerK3.py +++ b/src/sage/dynamics/arithmetic_dynamics/wehlerK3.py @@ -17,14 +17,13 @@ REFERENCES: [FH2015]_, [CS1996]_, [Weh1998]_, [Hutz2007] """ - -#***************************************************************************** +# **************************************************************************** # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. # https://www.gnu.org/licenses/ -#***************************************************************************** +# **************************************************************************** from sage.calculus.functions import jacobian from sage.categories.fields import Fields @@ -83,7 +82,8 @@ def WehlerK3Surface(polys): elif isinstance(R, CommutativeRing): return WehlerK3Surface_ring(polys) else: - raise TypeError("R (= %s) must be a commutative ring"%R) + raise TypeError("R (= %s) must be a commutative ring" % R) + def random_WehlerK3Surface(PP): r""" @@ -267,10 +267,10 @@ def _Lcoeff(self, component, i): sage: X._Lcoeff(1, 0) x0 """ - #Error Checks for Passed in Values - if not component in [0,1]: + # Error Checks for Passed in Values + if component not in [0, 1]: raise ValueError("component can only be 1 or 0") - if not i in [0,1,2]: + if i not in [0, 1, 2]: raise ValueError("index must be 0, 1, or 2") R = self.ambient_space().coordinate_ring() return self.L.coefficient(R.gen(component*3 + i)) @@ -317,11 +317,11 @@ def _Qcoeff(self, component, i, j): sage: X._Qcoeff(1, 1, 0) x0^2 """ - #Check Errors in Passed in Values - if not component in [0,1]: + # Check Errors in Passed in Values + if component not in [0, 1]: raise ValueError("component can only be 1 or 0") - if not (i in [0,1,2]) and not (j in [0,1,2]): + if i not in [0, 1, 2] or j not in [0, 1, 2]: raise ValueError("the two indexes must be either 0, 1, or 2") R = self.ambient_space().coordinate_ring() @@ -355,11 +355,11 @@ def Gpoly(self, component, k): sage: X.Gpoly(1, 0) x0^2*x1^2 + x1^4 - x0*x1^2*x2 + x1^3*x2 + x1^2*x2^2 + x2^4 """ - #Check Errors in passed in values - if not component in [0, 1]: + # Check Errors in passed in values + if component not in [0, 1]: raise ValueError("component can only be 1 or 0") - if not k in [0,1,2]: + if k not in [0, 1, 2]: raise ValueError("index must be either 0, 1, or 2") Indices = [0, 1, 2] @@ -447,7 +447,7 @@ def Lxa(self, a): sage: X.Lxa(T[0]) y0 + y1 """ - if not a in self.ambient_space()[0]: + if a not in self.ambient_space()[0]: raise TypeError("point must be in projective space of dimension 2") AS = self.ambient_space() ASC = AS.coordinate_ring() @@ -484,7 +484,7 @@ def Qxa(self, a): sage: X.Qxa(T[0]) 5*y0^2 + 7*y0*y1 + y1^2 + 11*y1*y2 + y2^2 """ - if not a in self.ambient_space()[0]: + if a not in self.ambient_space()[0]: raise TypeError("point must be in Projective Space of dimension 2") AS = self.ambient_space() ASC = AS.coordinate_ring() @@ -525,7 +525,7 @@ def Sxa(self, a): y0 + y1, 5*y0^2 + 7*y0*y1 + y1^2 + 11*y1*y2 + y2^2 """ - if not a in self.ambient_space()[0]: + if a not in self.ambient_space()[0]: raise TypeError("point must be in projective space of dimension 2") PSY = self.ambient_space()[1] return PSY.subscheme([self.Lxa(a),self.Qxa(a)]) @@ -559,7 +559,7 @@ def Lyb(self, b): sage: X.Lyb(T[1]) x0 """ - if not b in self.ambient_space()[1]: + if b not in self.ambient_space()[1]: raise TypeError("point must be in projective space of dimension 2") AS = self.ambient_space() ASC = AS.coordinate_ring() @@ -596,7 +596,7 @@ def Qyb(self, b): sage: X.Qyb(T[1]) x0^2 + 3*x0*x1 + x1^2 """ - if not b in self.ambient_space()[1]: + if b not in self.ambient_space()[1]: raise TypeError("point must be in projective space of dimension 2") AS = self.ambient_space() ASC = AS.coordinate_ring() @@ -635,7 +635,7 @@ def Syb(self, b): x0^2 + 3*x0*x1 + x1^2 """ - if not b in self.ambient_space()[1]: + if b not in self.ambient_space()[1]: raise TypeError("point must be in projective space of dimension 2") AS = self.ambient_space() PSY = AS[0] @@ -2130,7 +2130,7 @@ def fiber(self, p, component): for x in Points: if (self.L(x) == 0) and (self.Q(x) == 0): Y = self.point(x, False) - if not Y in fiber: + if Y not in fiber: fiber.append(Y) return fiber From 1ce109335091c4c96d1160a6c3512ef8ea36a507 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Wed, 3 Nov 2021 21:37:41 +0100 Subject: [PATCH 057/126] fix E713 and E714 in interfaces --- src/sage/interfaces/axiom.py | 7 +++---- src/sage/interfaces/expect.py | 6 +++--- src/sage/interfaces/interface.py | 14 +++++++------- src/sage/interfaces/mathics.py | 8 ++++---- src/sage/interfaces/maxima.py | 8 ++++---- src/sage/interfaces/maxima_lib.py | 14 +++++++------- src/sage/interfaces/octave.py | 8 ++++---- src/sage/interfaces/qepcad.py | 3 +-- src/sage/interfaces/sympy.py | 8 +------- 9 files changed, 34 insertions(+), 42 deletions(-) diff --git a/src/sage/interfaces/axiom.py b/src/sage/interfaces/axiom.py index d46b67bbb32..8819fd857fe 100644 --- a/src/sage/interfaces/axiom.py +++ b/src/sage/interfaces/axiom.py @@ -702,16 +702,15 @@ def _latex_(self): sage: a = axiom(1/2) #optional - axiom sage: latex(a) #optional - axiom \frac{1}{2} - """ self._check_valid() P = self.parent() - s = P._eval_line('outputAsTex(%s)'%self.name(), reformat=False) - if not '$$' in s: + s = P._eval_line('outputAsTex(%s)' % self.name(), reformat=False) + if '$$' not in s: raise RuntimeError("Error texing axiom object.") i = s.find('$$') j = s.rfind('$$') - s = s[i+2:j] + s = s[i + 2:j] s = multiple_replace({'\r':'', '\n':' ', ' \\sp ':'^', '\\arcsin ':'\\sin^{-1} ', diff --git a/src/sage/interfaces/expect.py b/src/sage/interfaces/expect.py index e619644f0e9..d31668974a1 100644 --- a/src/sage/interfaces/expect.py +++ b/src/sage/interfaces/expect.py @@ -1308,12 +1308,12 @@ def _synchronize(self, cmd='1+%s;\n'): if self._expect is None: return rnd = randrange(2147483647) - s = str(rnd+1) - cmd = cmd%rnd + s = str(rnd + 1) + cmd = cmd % rnd self._sendstr(cmd) try: self._expect_expr(timeout=0.5) - if not s in self._before(): + if s not in self._before(): self._expect_expr(s, timeout=0.5) self._expect_expr(timeout=0.5) except pexpect.TIMEOUT: diff --git a/src/sage/interfaces/interface.py b/src/sage/interfaces/interface.py index 7ace8e6ba03..19c6c7c8aa4 100644 --- a/src/sage/interfaces/interface.py +++ b/src/sage/interfaces/interface.py @@ -734,20 +734,20 @@ def __init__(self, parent, value, is_name=False, name=None): raise TypeError(x) def _latex_(self): -# return "\\begin{verbatim}%s\\end{verbatim}"%self + # return "\\begin{verbatim}%s\\end{verbatim}"%self string = str(self) - if not '|' in string: + if '|' not in string: delim = '|' - elif not '#' in string: + elif '#' not in string: delim = '#' - elif not '@' in string: + elif '@' not in string: delim = '@' - elif not '~' in string: + elif '~' not in string: delim = '~' - return "\\verb%s%s%s"%(delim, string, delim) + return "\\verb%s%s%s" % (delim, string, delim) def __iter__(self): - for i in range(1, len(self)+1): + for i in range(1, len(self) + 1): yield self[i] def __len__(self): diff --git a/src/sage/interfaces/mathics.py b/src/sage/interfaces/mathics.py index 2a81b23fed4..9a938ca759f 100644 --- a/src/sage/interfaces/mathics.py +++ b/src/sage/interfaces/mathics.py @@ -1062,15 +1062,15 @@ def _sage_(self, locals={}): self._check_valid() if self.is_inexact(): m = self.to_mpmath() - if not self is m and not m is None: + if self is not m and m is not None: from sage.libs.mpmath.utils import mpmath_to_sage return mpmath_to_sage(m, self.get_precision()) s = self.to_sympy() - if not self is s and not s is None: + if self is not s and s is not None: if hasattr(s, '_sage_'): return s._sage_() p = self.to_python() - if not self is p and not p is None: + if self is not p and p is not None: def conv(i): return self.parent()(i).sage() if type(p) is list: @@ -1078,7 +1078,7 @@ def conv(i): elif type(p) is tuple: return tuple([conv(i) for i in p]) elif type(p) is dict: - return {conv(k):conv(v) for k, v in p.items()} + return {conv(k): conv(v) for k, v in p.items()} else: return p return s diff --git a/src/sage/interfaces/maxima.py b/src/sage/interfaces/maxima.py index fc7f48bc052..8144d525825 100644 --- a/src/sage/interfaces/maxima.py +++ b/src/sage/interfaces/maxima.py @@ -847,13 +847,13 @@ def _synchronize(self): # The 0; *is* necessary... it comes up in certain rare cases # that are revealed by extensive testing. # Don't delete it. -- william stein - cmd = '''0;sconcat("%s",(%s+1));\n'''%(marker,r) + cmd = '''0;sconcat("%s",(%s+1));\n''' % (marker, r) self._sendstr(cmd) try: try: self._expect_expr(timeout=0.5) - if not s in self._before(): - self._expect_expr(s,timeout=0.5) + if s not in self._before(): + self._expect_expr(s, timeout=0.5) self._expect_expr(timeout=0.5) except pexpect.TIMEOUT: # Don't call self._interrupt() here, as that might send multiple @@ -944,7 +944,7 @@ def _error_check(self, cmd, out): """ r = self._error_re m = r.search(out) - if not m is None: + if m is not None: self._error_msg(cmd, out) def _error_msg(self, cmd, out): diff --git a/src/sage/interfaces/maxima_lib.py b/src/sage/interfaces/maxima_lib.py index 12005b269e8..e0e07c52c78 100644 --- a/src/sage/interfaces/maxima_lib.py +++ b/src/sage/interfaces/maxima_lib.py @@ -1607,18 +1607,18 @@ def sr_to_max(expr): # This should be safe if we treated all special operators above #furthermore, this should already use any _maxima_ methods on op, so use any #conversion methods that are registered in pynac. - op_max=maxima(op).ecl() + op_max = maxima(op).ecl() if op_max in max_op_dict: raise RuntimeError("Encountered operator mismatch in sr-to-maxima translation") - sage_op_dict[op]=op_max - max_op_dict[op_max]=op + sage_op_dict[op] = op_max + max_op_dict[op_max] = op return EclObject(([sage_op_dict[op]], [sr_to_max(o) for o in expr.operands()])) elif expr.is_symbol() or expr._is_registered_constant_(): - if not expr in sage_sym_dict: - sym_max=maxima(expr).ecl() - sage_sym_dict[expr]=sym_max - max_sym_dict[sym_max]=expr + if expr not in sage_sym_dict: + sym_max = maxima(expr).ecl() + sage_sym_dict[expr] = sym_max + max_sym_dict[sym_max] = expr return sage_sym_dict[expr] else: try: diff --git a/src/sage/interfaces/octave.py b/src/sage/interfaces/octave.py index 845fa0fd264..60daa33dbda 100644 --- a/src/sage/interfaces/octave.py +++ b/src/sage/interfaces/octave.py @@ -322,10 +322,10 @@ def _keyboard_interrupt(self): except pexpect.ExceptionPexpect as msg: raise RuntimeError( "THIS IS A BUG -- PLEASE REPORT. This should never happen.\n" + msg) self._start() - raise KeyboardInterrupt("Restarting %s (WARNING: all variables defined in previous session are now invalid)"%self) + raise KeyboardInterrupt("Restarting %s (WARNING: all variables defined in previous session are now invalid)" % self) else: - self._expect.send('\003') # control-c - raise KeyboardInterrupt("Ctrl-c pressed while running %s"%self) + self._expect.send('\003') # control-c + raise KeyboardInterrupt("Ctrl-c pressed while running %s" % self) def quit(self, verbose=False): """ @@ -339,7 +339,7 @@ def quit(self, verbose=False): # Don't bother, since it just hangs in some cases, and it # isn't necessary, since octave behaves well with respect # to signals. - if not self._expect is None: + if self._expect is not None: if verbose: print("Exiting spawned %s process." % self) return diff --git a/src/sage/interfaces/qepcad.py b/src/sage/interfaces/qepcad.py index 9fa2451ddd6..38d9c8c646a 100644 --- a/src/sage/interfaces/qepcad.py +++ b/src/sage/interfaces/qepcad.py @@ -1223,7 +1223,6 @@ def make_cells(self, text): return cells - def __getattr__(self, attrname): r""" Return a :class:`QepcadFunction` object for any QEPCAD command. @@ -1236,7 +1235,7 @@ def __getattr__(self, attrname): """ if attrname[:1] == "_": raise AttributeError - if not attrname in self._tab_completion(): + if attrname not in self._tab_completion(): raise AttributeError return QepcadFunction(self, attrname) diff --git a/src/sage/interfaces/sympy.py b/src/sage/interfaces/sympy.py index a16e3ab6aec..8fb6caf0188 100644 --- a/src/sage/interfaces/sympy.py +++ b/src/sage/interfaces/sympy.py @@ -1055,33 +1055,27 @@ def test_basics(): check_expression("x**2+y**3", "x y") check_expression("1/(x+y)**2-x**3/4", "x y") - def test_complex(): check_expression("I", "") check_expression("23+I*4", "x") - def test_complex_fail(): # Sage doesn't properly implement _sympy_ on I check_expression("I*y", "y") check_expression("x+I*y", "x y") - def test_integer(): check_expression("4*x", "x") check_expression("-4*x", "x") - def test_real(): check_expression("1.123*x", "x") check_expression("-18.22*x", "x") - - def test_functions(): # Test at least one Function without own _sage_ method from sympy import factorial - assert not "_sage_" in factorial.__dict__ + assert "_sage_" not in factorial.__dict__ check_expression("factorial(x)", "x") check_expression("sin(x)", "x") check_expression("cos(x)", "x") From 6473c4dea788afa23d886670536f0801cfc53b2a Mon Sep 17 00:00:00 2001 From: Markus Wageringel Date: Wed, 3 Nov 2021 21:54:35 +0100 Subject: [PATCH 058/126] 32824: raise error in non-commutative case --- src/sage/rings/morphism.pyx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/sage/rings/morphism.pyx b/src/sage/rings/morphism.pyx index 8cf7181feed..b18409ca88e 100644 --- a/src/sage/rings/morphism.pyx +++ b/src/sage/rings/morphism.pyx @@ -1255,11 +1255,21 @@ cdef class RingHomomorphism(RingMap): Traceback (most recent call last): ... NotImplementedError: base map must be trivial + + Non-commutative rings are not supported (:trac:`32824`):: + + sage: A = GradedCommutativeAlgebra(QQ, 'x,y,z') + sage: A.hom(A.gens(), A).kernel() + Traceback (most recent call last): + ... + NotImplementedError: rings are not commutative """ from .quotient_ring import is_QuotientRing from .ideal import Ideal_generic A = self.domain() B = self.codomain() + if not (A.is_commutative() and B.is_commutative()): + raise NotImplementedError("rings are not commutative") if A.base_ring() != B.base_ring(): raise NotImplementedError("base rings must be equal") try: From 9592ab36cddf75821d8ce82660445d83df24aad2 Mon Sep 17 00:00:00 2001 From: Lorenz Panny Date: Thu, 4 Nov 2021 14:14:54 +0800 Subject: [PATCH 059/126] fix doctest (from patchbot run) --- src/sage/doctest/forker.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/doctest/forker.py b/src/sage/doctest/forker.py index 3307d50939e..6690c627e75 100644 --- a/src/sage/doctest/forker.py +++ b/src/sage/doctest/forker.py @@ -1475,7 +1475,7 @@ def report_unexpected_exception(self, out, test, example, exc_info): sage: old_prompt = sage0._prompt sage: sage0._prompt = r"\(Pdb\) " sage: sage0.eval("DTR.run(DT, clear_globs=False)") # indirect doctest - '... ArithmeticError("invariants " + str(ainvs) + " define a singular curve")' + '... ArithmeticError(self._equation_string() + " defines a singular curve")' sage: sage0.eval("l") '...if self.discriminant() == 0:...raise ArithmeticError...' sage: sage0.eval("u") From a0c3b9d19282a5467d6d73ed61644f5a6be6cbba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Thu, 4 Nov 2021 11:50:33 +0100 Subject: [PATCH 060/126] =?UTF-8?q?cosm=C3=A9tique=20de=20l'espace?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../arithmetic_dynamics/endPN_automorphism_group.py | 6 +++--- src/sage/dynamics/arithmetic_dynamics/projective_ds.py | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py b/src/sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py index 85536d138fd..a2cf0fc198e 100644 --- a/src/sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py +++ b/src/sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py @@ -760,11 +760,11 @@ def automorphism_group_QQ_CRT(rational_function, prime_lower_bound=4, return_fun return(elements, which_group(elements)) return elements else: - N = gcd(orderaut + [12]) #all orders of elements divide N + N = gcd(orderaut + [12]) # all orders of elements divide N for order in divisors(N): if order in badorders: continue - #range over all orders + # range over all orders # that are possible over QQ such that we haven't already # found all elements of that order @@ -775,7 +775,7 @@ def automorphism_group_QQ_CRT(rational_function, prime_lower_bound=4, return_fun numelts = min(numeltsoffixedorder) # Have some elts of fixed order mod p for each p if numelts != 0: - #CRT order d elements together and check if + # CRT order d elements together and check if # they are an automorphism autos, M = CRT_automorphisms(automorphisms, orderelts, order, primepowers) diff --git a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py index 6f4ed4ed35e..2f3eeb90ab4 100644 --- a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py @@ -1332,7 +1332,7 @@ def orbit(self, P, N, **kwds): return [] R = self.domain()(P) - if R in self.domain(): #Check whether R is a zero-dimensional point + if R in self.domain(): # Check whether R is a zero-dimensional point Q = R else: Q = P @@ -1776,7 +1776,7 @@ def green_function(self, P, v, **kwds): #if doing error estimates, compute needed number of iterates D = (dim + 1) * (d - 1) + 1 - #compute upper bound + # compute upper bound if isinstance(v, RingHomomorphism_im_gens): #archimedean vindex = BR.places(prec=prec).index(v) U = GBR.local_height_arch(vindex, prec=prec) + R(binomial(dim + d, d)).log() @@ -2012,7 +2012,7 @@ def canonical_height(self, P, **kwds): R = RealField(prec) N = kwds.get('N', 10) err = kwds.get('error_bound', None) - #computes the error bound as defined in Algorithm 3.1 of [WELLS] + # computes the error bound as defined in Algorithm 3.1 of [WELLS] if Res > 1: if err is not None: err = err / 2 @@ -6328,7 +6328,7 @@ def all_periodic_points(self, **kwds): pt = [sum([P[i]*w**i for i in range(d)])] pt.insert(k,1) Q = PS(pt) - #for each periodic point get the entire cycle + # for each periodic point get the entire cycle if Q not in periodic_points: #check periodic not preperiodic and add all points in cycle orb = set([Q]) @@ -6627,7 +6627,7 @@ def all_preperiodic_points(self, **kwds): pt = [sum([P[i]*w**i for i in range(d)])] pt.insert(k,1) Q = PS(pt) - #for each preperiodic point get the entire connected component + # for each preperiodic point get the entire connected component if Q not in preper: for t in DS.connected_rational_component(Q): preper.add(t) From ae5ec64919e91486c7be530f7d1ab767454e62ed Mon Sep 17 00:00:00 2001 From: LLewark Date: Fri, 5 Nov 2021 11:05:24 +0100 Subject: [PATCH 061/126] Added Cromwell's book 'Knots and links' as reference for the definition of the determinant for multi-component links. --- src/doc/en/reference/references/index.rst | 3 +++ src/sage/knots/link.py | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/src/doc/en/reference/references/index.rst b/src/doc/en/reference/references/index.rst index 8a7e133e0ae..981d1454c9f 100644 --- a/src/doc/en/reference/references/index.rst +++ b/src/doc/en/reference/references/index.rst @@ -1716,6 +1716,9 @@ REFERENCES: C. R. Acad. Sci. Paris Sér. I Math. 296 (1983) 14 781--784. +.. [Cro2004] Peter R. Cromwell, *Knots and links*, Cambridge University Press (2004). + :doi:`10.1017/CBO9780511809767` + .. [CRS2016] Dean Crnković, Sanja Rukavina, and Andrea Švob. *Strongly regular graphs from orthogonal groups* `O^+(6,2)` *and* `O^-(6,2)`. :arxiv:`1609.07133` diff --git a/src/sage/knots/link.py b/src/sage/knots/link.py index ec8ad1399c1..d8c114b54fe 100644 --- a/src/sage/knots/link.py +++ b/src/sage/knots/link.py @@ -1935,6 +1935,10 @@ def determinant(self): sage: B = BraidGroup(3) sage: Link(B([1, 2, 1, -2, -1])).determinant() 0 + + REFERENCES: + + - Definition 6.6.3 in [Cro2004]_ """ V = self.seifert_matrix() m = V + V.transpose() From 188ff58679bde8818e4e2cd0a5e149f8e95a978c Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Sat, 6 Nov 2021 11:08:06 +0900 Subject: [PATCH 062/126] Putting the docstring first in eps_monom(). --- src/sage/groups/braid.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/sage/groups/braid.py b/src/sage/groups/braid.py index a6e53f2e1a1..688ec825893 100644 --- a/src/sage/groups/braid.py +++ b/src/sage/groups/braid.py @@ -2141,8 +2141,10 @@ def eps(self, N): in parallel. """ def eps_monom(q_tuple): + r""" + Evaluate the map `\mathcal{E}_N` for a single mononial. + """ q = self.q - r"""Evaluate the map $\mathcal{E}_N$ for a single mononial.""" ret_q = q**sum((N - 1 - q_tuple[3*i + 2])*q_tuple[3*i + 1] for i in range(self._minus_begin//3)) ret_q *= q**sum((N - 1)*(-q_tuple[rj]) From 66f5f81737d8b3dbbd50ae0d14f7acb7aced89e7 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 6 Nov 2021 12:54:02 -0700 Subject: [PATCH 063/126] build/pkgs/numpy: Update to 1.21.4 --- build/pkgs/numpy/checksums.ini | 6 +++--- build/pkgs/numpy/package-version.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/pkgs/numpy/checksums.ini b/build/pkgs/numpy/checksums.ini index b306701d888..f4013779be9 100644 --- a/build/pkgs/numpy/checksums.ini +++ b/build/pkgs/numpy/checksums.ini @@ -1,5 +1,5 @@ tarball=numpy-VERSION.zip -sha1=c7eb91a2232f7843301c355795860baaa0280909 -md5=5638d5dae3ca387be562912312db842e -cksum=2204147896 +sha1=91a1faeb617601453ebf6e2855e5ce6bf94d3588 +md5=b3c4477a027d5b6fba5e1065064fd076 +cksum=1917168823 upstream_url=https://pypi.io/packages/source/n/numpy/numpy-VERSION.zip diff --git a/build/pkgs/numpy/package-version.txt b/build/pkgs/numpy/package-version.txt index 0369d0b1e93..20a1265cf39 100644 --- a/build/pkgs/numpy/package-version.txt +++ b/build/pkgs/numpy/package-version.txt @@ -1 +1 @@ -1.21.2 +1.21.4 From e2ad5ae07c49c8f1af0ced1226cb45d17346ef65 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 6 Nov 2021 12:55:09 -0700 Subject: [PATCH 064/126] build/pkgs/networkx: Update to 2.6.3 --- build/pkgs/networkx/checksums.ini | 6 +++--- build/pkgs/networkx/package-version.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/pkgs/networkx/checksums.ini b/build/pkgs/networkx/checksums.ini index b71ff5f1866..075e0c74047 100644 --- a/build/pkgs/networkx/checksums.ini +++ b/build/pkgs/networkx/checksums.ini @@ -1,5 +1,5 @@ tarball=networkx-VERSION.tar.gz -sha1=5a39af7b0b6a6180b733c280b0ee70b9868a8566 -md5=ac9cf192fc525bb877a042a684091d72 -cksum=1918700937 +sha1=659f640c03fe52c98fa7a1d03fe3a6f6bbce2015 +md5=407eb28c54e08725559754ca7ab185e0 +cksum=3378468789 upstream_url=https://pypi.io/packages/source/n/networkx/networkx-VERSION.tar.gz diff --git a/build/pkgs/networkx/package-version.txt b/build/pkgs/networkx/package-version.txt index 097a15a2af3..ec1cf33c3f6 100644 --- a/build/pkgs/networkx/package-version.txt +++ b/build/pkgs/networkx/package-version.txt @@ -1 +1 @@ -2.6.2 +2.6.3 From 0e5702be09d2cc1b617aa33c6512e09e534547a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sat, 6 Nov 2021 21:33:53 +0100 Subject: [PATCH 065/126] use libgap in coding/ --- src/sage/coding/databases.py | 58 +++++++++++++----------------------- 1 file changed, 21 insertions(+), 37 deletions(-) diff --git a/src/sage/coding/databases.py b/src/sage/coding/databases.py index c2b1a2a9e23..87e0e41bb4e 100644 --- a/src/sage/coding/databases.py +++ b/src/sage/coding/databases.py @@ -2,19 +2,19 @@ r""" Access functions to online databases for coding theory """ - -from sage.interfaces.all import gap +from sage.libs.gap.libgap import libgap from sage.features.gap import GapPackage -# Don't put any global imports here since this module is accessible as +# Do not put any global imports here since this module is accessible as # sage.codes.databases. + def best_linear_code_in_guava(n, k, F): r""" - Returns the linear code of length ``n``, dimension ``k`` over field ``F`` + Return the linear code of length ``n``, dimension ``k`` over field ``F`` with the maximal minimum distance which is known to the GAP package GUAVA. - The function uses the tables described in ``bounds_on_minimum_distance_in_guava`` to + The function uses the tables described in :func:`bounds_on_minimum_distance_in_guava` to construct this code. This requires the optional GAP package GUAVA. INPUT: @@ -27,7 +27,7 @@ def best_linear_code_in_guava(n, k, F): OUTPUT: - - A :class:`LinearCode` which is a best linear code of the given parameters known to GUAVA. + A :class:`LinearCode` which is a best linear code of the given parameters known to GUAVA. EXAMPLES:: @@ -41,22 +41,22 @@ def best_linear_code_in_guava(n, k, F): between 2 and 4. Use ``bounds_on_minimum_distance_in_guava(10,5,GF(2))`` for further details. """ - GapPackage("guava", spkg="gap_packages").require() - gap.load_package("guava") - q = F.order() - C = gap("BestKnownLinearCode(%s,%s,GF(%s))"%(n,k,q)) from .linear_code import LinearCode + GapPackage("guava", spkg="gap_packages").require() + libgap.load_package("guava") + C = libgap.BestKnownLinearCode(n, k, F) return LinearCode(C.GeneratorMat()._matrix_(F)) + def bounds_on_minimum_distance_in_guava(n, k, F): r""" - Computes a lower and upper bound on the greatest minimum distance of a + Compute a lower and upper bound on the greatest minimum distance of a `[n,k]` linear code over the field ``F``. This function requires the optional GAP package GUAVA. The function returns a GAP record with the two bounds and an explanation for - each bound. The function Display can be used to show the explanations. + each bound. The method ``Display`` can be used to show the explanations. The values for the lower and upper bound are obtained from a table constructed by Cen Tjhai for GUAVA, derived from the table of @@ -81,21 +81,9 @@ def bounds_on_minimum_distance_in_guava(n, k, F): EXAMPLES:: sage: gap_rec = codes.databases.bounds_on_minimum_distance_in_guava(10,5,GF(2)) # optional - gap_packages (Guava package) - sage: print(gap_rec) # optional - gap_packages (Guava package) + sage: gap_rec.Display() # optional - gap_packages (Guava package) rec( - construction := - [ , - [ - [ , - [ - [ , - [ [ , [ 8, 2 ] ] ] ], - [ , - [ - [ , - [ [ , [ 4, 2 ] ] ] ] - , [ , [ 4, 2 ] ] ] ] - ] ], [ 1, 2, 3, 4, 5, 6 ] ] ], + construction := [ , [ [ , [ [ , [ [ , [ 8, 2 ] ] ] ], [ , [ [ , [ [ , [ 4, 2 ] ] ] ], [ , [ 4, 2 ] ] ] ] ] ], [ 1, 2, 3, 4, 5, 6 ] ] ], k := 5, lowerBound := 4, lowerBoundExplanation := ... @@ -107,11 +95,9 @@ def bounds_on_minimum_distance_in_guava(n, k, F): upperBoundExplanation := ... ) """ GapPackage("guava", spkg="gap_packages").require() - gap.load_package("guava") - q = F.order() - gap.eval("data := BoundsMinimumDistance(%s,%s,GF(%s))"%(n,k,q)) - Ldata = gap.eval("Display(data)") - return Ldata + libgap.load_package("guava") + return libgap.BoundsMinimumDistance(n, k, F) + def best_linear_code_in_codetables_dot_de(n, k, F, verbose=False): r""" @@ -275,8 +261,6 @@ def self_orthogonal_binary_codes(n, k, b=2, parent=None, BC=None, equal=False, from sage.rings.finite_rings.finite_field_constructor import FiniteField from sage.matrix.constructor import Matrix - - d=int(b) if d!=b or d%2==1 or d <= 0: raise ValueError("b (%s) must be a positive even integer."%b) @@ -285,11 +269,11 @@ def self_orthogonal_binary_codes(n, k, b=2, parent=None, BC=None, equal=False, if k < 1 or n < 2: return if equal: - in_test = lambda M : (M.ncols() - M.nrows()) <= (n-k) - out_test = lambda C : (C.dimension() == k) and (C.length() == n) + in_test = lambda M: (M.ncols() - M.nrows()) <= (n-k) + out_test = lambda C: (C.dimension() == k) and (C.length() == n) else: - in_test = lambda M : True - out_test = lambda C : True + in_test = lambda M: True + out_test = lambda C: True if BC is None: BC = BinaryCodeClassifier() if parent is None: From 24cb6f04e41eecc6f130bf725440700d233eef59 Mon Sep 17 00:00:00 2001 From: dcoudert Date: Sat, 6 Nov 2021 23:27:27 +0100 Subject: [PATCH 066/126] trac #32831: correct default setting of multiedges --- src/sage/graphs/base/c_graph.pyx | 2 +- src/sage/graphs/graph_input.py | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/sage/graphs/base/c_graph.pyx b/src/sage/graphs/base/c_graph.pyx index 515ca3076ff..8901ddbc536 100644 --- a/src/sage/graphs/base/c_graph.pyx +++ b/src/sage/graphs/base/c_graph.pyx @@ -1597,7 +1597,7 @@ cdef class CGraphBackend(GenericGraphBackend): The bug in :trac:`14967` and :trac:`14853` is fixed:: sage: DiGraph({0: {}, 1/2: {}}) - Multi-digraph on 2 vertices + Digraph on 2 vertices sage: A = Set([RDF.random_element(min=0, max=10) for k in range(10)]) sage: G = Graph() sage: G.add_vertices(A) diff --git a/src/sage/graphs/graph_input.py b/src/sage/graphs/graph_input.py index 77f93b96bf4..0caf56efd29 100644 --- a/src/sage/graphs/graph_input.py +++ b/src/sage/graphs/graph_input.py @@ -453,6 +453,13 @@ def from_dict_of_dicts(G, M, loops=False, multiedges=False, weighted=False, conv sage: from_dict_of_dicts(g, graphs.PetersenGraph().to_dictionary(edge_labels=True)) sage: g.is_isomorphic(graphs.PetersenGraph()) True + + TESTS: + + :trac:`32831 is fixed: + + sage: DiGraph({0: {}, 1: {}, 2: {}, 3: {}, 4: {}}) + Digraph on 5 vertices """ if any(not isinstance(M[u], dict) for u in M): raise ValueError("input dict must be a consistent format") @@ -467,6 +474,7 @@ def from_dict_of_dicts(G, M, loops=False, multiedges=False, weighted=False, conv loops = False if weighted is None: G._weighted = False + input_multiedges = multiedges if multiedges is not False: if not all(isinstance(M[u][v], list) for u in M for v in M[u]): if multiedges: @@ -501,6 +509,8 @@ def from_dict_of_dicts(G, M, loops=False, multiedges=False, weighted=False, conv for u in M: for v in M[u]: G._backend.add_edge(u, v, relabel(M[u][v]), is_directed) + if not G.size() and input_multiedges is not True: + G.allow_multiple_edges(False, check=False) def from_dict_of_lists(G, D, loops=False, multiedges=False, weighted=False): r""" From 1735e775eb4dd3aa25948edeb2b8ac3c36531672 Mon Sep 17 00:00:00 2001 From: dcoudert Date: Sun, 7 Nov 2021 09:38:28 +0100 Subject: [PATCH 067/126] trac #32831: fix block --- src/sage/graphs/graph_input.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/graphs/graph_input.py b/src/sage/graphs/graph_input.py index 0caf56efd29..2eb298a06a4 100644 --- a/src/sage/graphs/graph_input.py +++ b/src/sage/graphs/graph_input.py @@ -456,7 +456,7 @@ def from_dict_of_dicts(G, M, loops=False, multiedges=False, weighted=False, conv TESTS: - :trac:`32831 is fixed: + :trac:`32831` is fixed:: sage: DiGraph({0: {}, 1: {}, 2: {}, 3: {}, 4: {}}) Digraph on 5 vertices From 3c9efd2470843c3669c35cdc3d00f8c986d9957e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sat, 6 Nov 2021 09:12:00 +0100 Subject: [PATCH 068/126] subgroup of finite matrix group is finite --- src/sage/groups/cubic_braid.py | 34 +++++++++---------- .../groups/matrix_gps/finitely_generated.py | 7 ++-- src/sage/groups/matrix_gps/matrix_group.py | 32 +++++++++++++---- 3 files changed, 48 insertions(+), 25 deletions(-) diff --git a/src/sage/groups/cubic_braid.py b/src/sage/groups/cubic_braid.py index 2d2b5f393be..db110b57e95 100644 --- a/src/sage/groups/cubic_braid.py +++ b/src/sage/groups/cubic_braid.py @@ -76,7 +76,7 @@ # https://www.gnu.org/licenses/ # **************************************************************************** - +from sage.categories.groups import Groups from sage.misc.cachefunc import cached_method from sage.libs.gap.element import GapElement from sage.groups.free_group import FreeGroup @@ -102,12 +102,12 @@ def _reduce_tietze(tietze_list): easily possible using the second braid relation and degree reduction. EXAMPLES:: - + sage: from sage.groups.cubic_braid import _reduce_tietze sage: _reduce_tietze((2, 2, -3, 5, 3, 1, 1, 5)) [-2, -5, -1] """ - def eleminate_item(tietze_list): + def eliminate_item(tietze_list): """ this sub method searches for an item in the Tietze expression such that it together with the first entry gives a pair which can be @@ -118,14 +118,14 @@ def eleminate_item(tietze_list): l = len(tietze_list) if l < 2: return None - first = tietze_list[0] + first = tietze_list[0] second = None for i in range(1,l): if tietze_list[i] in (first, -first): if i == 1: second = tietze_list[i] break - if min(abs(abs(tietze_list[j])-abs(first)) for j in range(1, i)) > 1: + if all(abs(abs(tietze_list[j])-abs(first)) > 1 for j in range(1, i)): # the entry on position i can be moved right to the first entry # by the second braid relation second = tietze_list[i] @@ -143,7 +143,7 @@ def eleminate_item(tietze_list): l = len(tietze_list) for i in range(l): end = tietze_list[i:l] - tietze_list_red = eleminate_item(end) + tietze_list_red = eliminate_item(end) if tietze_list_red is not None: start = tietze_list[:i] return start + _reduce_tietze(tietze_list_red) @@ -788,7 +788,11 @@ def __init__(self, names, cbg_type=None): elif cbg_type == CubicBraidGroup.type.AssionS: rels.append(b[i+2]*b[i]*t[i+1]*b[i]*ti[i+1]*t[i+2]*t[i+1]*b[i]*ti[i+1]*ti[i+2]) - FinitelyPresentedGroup.__init__(self, free_group, tuple(rels)) + if self._nstrands <= 5 or cbg_type != CubicBraidGroup.type.Coxeter: + cat = Groups().Finite() + else: + cat = Groups().Infinite() + FinitelyPresentedGroup.__init__(self, free_group, tuple(rels), category=cat) self._free_group = free_group # ------------------------------------------------------------------------------------------------ @@ -1458,16 +1462,14 @@ def as_matrix_group(self, root_bur=None, domain=None, characteristic=None, var=' ... ValueError: Burau representation does not factor through the relations """ - # ------------------------------------------------------------------------------- + # ------------------------------------------------------------------ # define matrix group by generators using the Burau representation - # ------------------------------------------------------------------------------- - + # ------------------------------------------------------------------ unitary = False if isinstance(reduced, str): if reduced == 'unitary': unitary = True - - gen_list =[] + gen_list = [] for braid_gen in self.gens(): bur_mat = braid_gen.burau_matrix(root_bur=root_bur, domain=domain, characteristic=characteristic, var=var, reduced=reduced) @@ -1482,7 +1484,7 @@ def as_matrix_group(self, root_bur=None, domain=None, characteristic=None, var=' if unitary and herm_form.is_singular(): unitary = False # since a degenerated hermitian form doesn't define a unitary group if self._classical_invariant_form is None: - self._classical_invariant_form = herm_form + self._classical_invariant_form = herm_form if unitary: from sage.rings.finite_rings.finite_field_base import is_FiniteField @@ -1496,7 +1498,7 @@ def as_matrix_group(self, root_bur=None, domain=None, characteristic=None, var=' matrix_group = base_group.subgroup(gen_list) else: from sage.groups.matrix_gps.finitely_generated import MatrixGroup - matrix_group = MatrixGroup(gen_list) + matrix_group = MatrixGroup(gen_list, category=self.category()) # ------------------------------------------------------------------------------- # check if there is a well defined group homomorphism to matrix_group @@ -1505,7 +1507,7 @@ def as_matrix_group(self, root_bur=None, domain=None, characteristic=None, var=' # here. # ------------------------------------------------------------------------------- hom_to_mat = self.hom(matrix_group.gens(), check=False) - if not all( hom_to_mat(rel).is_one() for rel in self.relations()): + if not all(hom_to_mat(rel).is_one() for rel in self.relations()): raise ValueError("Burau representation does not factor through the relations") matrix_group.register_conversion(hom_to_mat) return matrix_group @@ -1539,7 +1541,6 @@ def as_permutation_group(self, use_classical=True): sage: C3 = CubicBraidGroup(3) sage: PC3 = C3.as_permutation_group() sage: C3.is_isomorphic(PC3) - #I Forcing finiteness test True sage: PC3.degree() 8 @@ -1937,7 +1938,6 @@ def is_finite(self): from sage.rings.infinity import infinity return not self.order() is infinity - # ---------------------------------------------------------------------------------- # creating a CubicBraidGroup as subgroup of self on less strands # ---------------------------------------------------------------------------------- diff --git a/src/sage/groups/matrix_gps/finitely_generated.py b/src/sage/groups/matrix_gps/finitely_generated.py index cef211ea07c..2a0f9580360 100644 --- a/src/sage/groups/matrix_gps/finitely_generated.py +++ b/src/sage/groups/matrix_gps/finitely_generated.py @@ -294,12 +294,15 @@ def MatrixGroup(*gens, **kwds): base_ring = MS.base_ring() degree = ZZ(MS.ncols()) # == MS.nrows() from sage.libs.gap.libgap import libgap + category = kwds.get('category', None) try: gap_gens = [libgap(matrix_gen) for matrix_gen in gens] gap_group = libgap.Group(gap_gens) - return FinitelyGeneratedMatrixGroup_gap(degree, base_ring, gap_group) + return FinitelyGeneratedMatrixGroup_gap(degree, base_ring, gap_group, + category=category) except (TypeError, ValueError): - return FinitelyGeneratedMatrixGroup_generic(degree, base_ring, gens) + return FinitelyGeneratedMatrixGroup_generic(degree, base_ring, gens, + category=category) ################################################################### # diff --git a/src/sage/groups/matrix_gps/matrix_group.py b/src/sage/groups/matrix_gps/matrix_group.py index e82abf76246..f2ce966c9ed 100644 --- a/src/sage/groups/matrix_gps/matrix_group.py +++ b/src/sage/groups/matrix_gps/matrix_group.py @@ -212,7 +212,24 @@ def subgroup(self, generators, check=True): sage: TestSuite(G).run() sage: TestSuite(S).run() + + sage: W = CoxeterGroup(['I',7]) + sage: s = W.simple_reflections() + sage: G = W.subgroup([s[1]]) + sage: G.category() + Category of finite groups + + sage: W = WeylGroup(['A',2]) + sage: s = W.simple_reflections() + sage: G = W.subgroup([s[1]]) + sage: G.category() + Category of finite groups """ + try: + test = self.is_finite() + except NotImplementedError: + test = self in Groups().Finite() + cat = Groups().Finite() if test else Groups() # this method enlarges the method with same name of # ParentLibGAP to cases where the ambient group is not # inherited from ParentLibGAP. @@ -224,7 +241,7 @@ def subgroup(self, generators, check=True): raise ValueError("generator %s is not in the group" % (g)) from sage.groups.matrix_gps.finitely_generated import MatrixGroup - subgroup = MatrixGroup(generators, check=check) + subgroup = MatrixGroup(generators, check=check, category=cat) subgroup._ambient = self return subgroup @@ -409,12 +426,11 @@ def __init__(self, degree, base_ring, category=None): if self._deg <= 0: raise ValueError('the degree must be at least 1') - if category is None: - category = Groups() + cat = Groups() if category is None else category if base_ring in Rings().Finite(): - category = category.Finite() + cat = cat.Finite() super(MatrixGroup_generic, self).__init__(base=base_ring, - category=category) + category=cat) def degree(self): """ @@ -759,8 +775,12 @@ def _subgroup_constructor(self, libgap_subgroup): sage: G.ambient() is SL2Z True """ + cat = Groups() + if self in Groups().Finite(): + cat = cat.Finite() from sage.groups.matrix_gps.finitely_generated import FinitelyGeneratedMatrixGroup_gap return FinitelyGeneratedMatrixGroup_gap(self.degree(), self.base_ring(), - libgap_subgroup, ambient=self) + libgap_subgroup, ambient=self, + category=cat) from sage.groups.generic import structure_description From a1095a39122b34a01959ac738832ee5a037205e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sun, 7 Nov 2021 11:22:06 +0100 Subject: [PATCH 069/126] indent doctest --- src/sage/coding/databases.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/sage/coding/databases.py b/src/sage/coding/databases.py index 87e0e41bb4e..2fe3a632e2d 100644 --- a/src/sage/coding/databases.py +++ b/src/sage/coding/databases.py @@ -83,7 +83,14 @@ def bounds_on_minimum_distance_in_guava(n, k, F): sage: gap_rec = codes.databases.bounds_on_minimum_distance_in_guava(10,5,GF(2)) # optional - gap_packages (Guava package) sage: gap_rec.Display() # optional - gap_packages (Guava package) rec( - construction := [ , [ [ , [ [ , [ [ , [ 8, 2 ] ] ] ], [ , [ [ , [ [ , [ 4, 2 ] ] ] ], [ , [ 4, 2 ] ] ] ] ] ], [ 1, 2, 3, 4, 5, 6 ] ] ], + construction := [ , + [ [ , + [ [ , + [ [ , [ 8, 2 ] ] ] ], + [ , [ [ , + [ [ , [ 4, 2 ] ] ] ], + [ , [ 4, 2 ] ] ] ] ] ], + [ 1, 2, 3, 4, 5, 6 ] ] ], k := 5, lowerBound := 4, lowerBoundExplanation := ... From 2704119820efc54ae4069ebeefb0ab74f91b0e08 Mon Sep 17 00:00:00 2001 From: Miguel Marco Date: Sun, 7 Nov 2021 17:50:32 +0100 Subject: [PATCH 070/126] Fix creating polynomial from strings in the case of field with several generators --- .../polynomial/multi_polynomial_libsingular.pyx | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx b/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx index ff7f4180f24..f2bdea65896 100644 --- a/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx +++ b/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx @@ -770,6 +770,16 @@ cdef class MPolynomialRing_libsingular(MPolynomialRing_base): sage: S(f) (2*abar)*y + Check that creating element from strings works for transcendental extensions:: + + sage: T. = QQ[] + sage: F = FractionField(T) + sage: R. = F[] + sage: R('d*z+x^2*y') + x^2*y + d*z + + + """ cdef poly *_p cdef poly *mon @@ -962,7 +972,11 @@ cdef class MPolynomialRing_libsingular(MPolynomialRing_base): # let python do the parsing d = self.gens_dict() if self.base_ring().gen() != 1: - d[str(self.base_ring().gen())]=self.base_ring().gen() + if hasattr(self.base_ring(), 'gens'): + for gen in self.base_ring().gens(): + d[str(gen)] = gen + else: + d[str(self.base_ring().gen())] = self.base_ring_gen() try: if '/' in element: element = sage_eval(element,d) From 84a04d125051e2c04e39ad7ed0d7db53cee9772d Mon Sep 17 00:00:00 2001 From: Miguel Marco Date: Sun, 7 Nov 2021 18:00:36 +0100 Subject: [PATCH 071/126] Fix variable indices in doctest --- .../non_symmetric_macdonald_polynomials.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/sage/combinat/root_system/non_symmetric_macdonald_polynomials.py b/src/sage/combinat/root_system/non_symmetric_macdonald_polynomials.py index 5d406c1dd44..482f7bb9215 100644 --- a/src/sage/combinat/root_system/non_symmetric_macdonald_polynomials.py +++ b/src/sage/combinat/root_system/non_symmetric_macdonald_polynomials.py @@ -940,28 +940,28 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): sage: E = NonSymmetricMacdonaldPolynomials(KL,q, t, -1) sage: L0 = E.keys() sage: omega = L0.fundamental_weights() - sage: P = K['x1,x2,x3'] + sage: P = K['x0,x1,x2'] sage: def EE(weight): return E[L0(weight)].expand(P.gens()) sage: EE([0,0,0]) 1 sage: EE([1,0,0]) - x1 + x0 sage: EE([0,1,0]) - (t - 1)/(q*t^2 - 1)*x1 + x2 + (t - 1)/(q*t^2 - 1)*x0 + x1 sage: EE([0,0,1]) - (t - 1)/(q*t - 1)*x1 + (t - 1)/(q*t - 1)*x2 + x3 + (t - 1)/(q*t - 1)*x0 + (t - 1)/(q*t - 1)*x1 + x2 sage: EE([1,1,0]) - x1*x2 + x0*x1 sage: EE([1,0,1]) - (t - 1)/(q*t^2 - 1)*x1*x2 + x1*x3 + (t - 1)/(q*t^2 - 1)*x0*x1 + x0*x2 sage: EE([0,1,1]) - (t - 1)/(q*t - 1)*x1*x2 + (t - 1)/(q*t - 1)*x1*x3 + x2*x3 + (t - 1)/(q*t - 1)*x0*x1 + (t - 1)/(q*t - 1)*x0*x2 + x1*x2 sage: EE([2,0,0]) - x1^2 + (q*t - q)/(q*t - 1)*x1*x2 + (q*t - q)/(q*t - 1)*x1*x3 + x0^2 + (q*t - q)/(q*t - 1)*x0*x1 + (q*t - q)/(q*t - 1)*x0*x2 sage: EE([0,2,0]) - (t - 1)/(q^2*t^2 - 1)*x1^2 + (q^2*t^3 - q^2*t^2 + q*t^2 - 2*q*t + q - t + 1)/(q^3*t^3 - q^2*t^2 - q*t + 1)*x1*x2 + x2^2 + (q*t^2 - 2*q*t + q)/(q^3*t^3 - q^2*t^2 - q*t + 1)*x1*x3 + (q*t - q)/(q*t - 1)*x2*x3 + (t - 1)/(q^2*t^2 - 1)*x0^2 + (q^2*t^3 - q^2*t^2 + q*t^2 - 2*q*t + q - t + 1)/(q^3*t^3 - q^2*t^2 - q*t + 1)*x0*x1 + x1^2 + (q*t^2 - 2*q*t + q)/(q^3*t^3 - q^2*t^2 - q*t + 1)*x0*x2 + (q*t - q)/(q*t - 1)*x1*x2 Systematic checks with Sage's implementation of [HHL06]_:: From d412c7745d70cb9bb7b40e56eafd3ebb73d3692b Mon Sep 17 00:00:00 2001 From: Miguel Marco Date: Sun, 7 Nov 2021 18:42:42 +0100 Subject: [PATCH 072/126] Fix crash in .subs() --- src/sage/libs/singular/polynomial.pyx | 5 +++-- .../polynomial/multi_polynomial_libsingular.pyx | 13 +++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/sage/libs/singular/polynomial.pyx b/src/sage/libs/singular/polynomial.pyx index eed1967ca9e..f6d244e79fa 100644 --- a/src/sage/libs/singular/polynomial.pyx +++ b/src/sage/libs/singular/polynomial.pyx @@ -621,6 +621,9 @@ cdef int singular_polynomial_subst(poly **p, int var_index, poly *value, ring *r - ``r`` - a ring """ + if r != currRing: + rChangeCurrRing(r) + if p_IsConstant(value, r): p[0] = pSubst(p[0], var_index+1, value) return 0 @@ -628,8 +631,6 @@ cdef int singular_polynomial_subst(poly **p, int var_index, poly *value, ring *r cdef unsigned long exp = p_GetExp(p[0], var_index+1, r) * p_GetMaxExp(value, r) overflow_check(exp, r) - if r != currRing: - rChangeCurrRing(r) cdef int count = singular_polynomial_length_bounded(p[0], 15) if unlikely(count >= 15 or exp > 15): sig_on() diff --git a/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx b/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx index f2bdea65896..5d34e62d04c 100644 --- a/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx +++ b/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx @@ -3519,6 +3519,19 @@ cdef class MPolynomial_libsingular(MPolynomial): ....: assert y.subs(d) == y.subs(**ds) == vy ....: assert z.subs(d) == z.subs(**ds) == vz ....: assert (x+y).subs(d) == (x+y).subs(**ds) == vx+vy + + Check that substitution doesn't crash in transcendental extensions:: + + sage: F = PolynomialRing(QQ,'c,d').fraction_field() + sage: F.inject_variables() + Defining c, d + sage: R. = F[] + sage: f = R(d*z^2 + c*y*z^2) + sage: f.subs({x:z^2,y:1}) + (c + d)*z^2 + sage: f.subs({z:x+1}) + c*x^2*y + d*x^2 + (2*c)*x*y + (2*d)*x + c*y + d + """ cdef int mi, i, need_map, try_symbolic From 48b79271d3b1b2566e55cb6efa5e7184e1fe14cb Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 7 Nov 2021 11:52:45 -0800 Subject: [PATCH 073/126] build/bin/sage-bootstrap-python: Prefer a Python that provides ssl with SNI --- build/bin/sage-bootstrap-python | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/build/bin/sage-bootstrap-python b/build/bin/sage-bootstrap-python index faee444e8dc..5c5cd1cc097 100755 --- a/build/bin/sage-bootstrap-python +++ b/build/bin/sage-bootstrap-python @@ -40,7 +40,19 @@ if [ "$LC_ALL" = "C" -o "$LANG" = "C" -o "$LC_CTYPE" = "C" ]; then export LANG fi -PYTHONS="python python3 python3.8 python3.7 python2.7 python3.6 python2" +PYTHONS="python python3 python3.10 python3.9 python3.8 python3.7 python2.7 python3.6 python2" +# Trac #32405: Prefer a Python that provides ssl with SNI, which allows developers +# to download from upstream URLs (configure --enable-download-from-upstream-url), +# in particular from PyPI, which requires SNI. +for PY in $PYTHONS; do + PYTHON="$(PATH="$SAGE_ORIG_PATH" command -v $PY)" + if [ -n "$PYTHON" ]; then + if "$PYTHON" -c "import argparse; import urllib; from hashlib import sha1; from ssl import HAS_SNI; assert HAS_SNI; from os import listdir; listdir(\"$(pwd)\");" 2>/dev/null; then + exec "$PYTHON" "$@" + fi + fi +done +# Second round, no ssl/SNI test. for PY in $PYTHONS; do PYTHON="$(PATH="$SAGE_ORIG_PATH" command -v $PY)" if [ -n "$PYTHON" ]; then From 5871cabb741cafd01023e08d7cc1f3e95f60884a Mon Sep 17 00:00:00 2001 From: dcoudert Date: Sun, 7 Nov 2021 21:09:31 +0100 Subject: [PATCH 074/126] trac #32831: fix doctest in src/sage/combinat/crystals/induced_structure.py --- src/sage/combinat/crystals/induced_structure.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/combinat/crystals/induced_structure.py b/src/sage/combinat/crystals/induced_structure.py index ec01e07b651..0cf36648bba 100644 --- a/src/sage/combinat/crystals/induced_structure.py +++ b/src/sage/combinat/crystals/induced_structure.py @@ -89,7 +89,7 @@ class InducedCrystal(UniqueRepresentation, Parent): True sage: I = crystals.Induced(P, phi, phi_inv) sage: I.digraph() - Multi-digraph on 24 vertices + Digraph on 24 vertices We construct an example without a specified inverse map:: From d410caa35701cc6093739f85dcce31c47911f7e2 Mon Sep 17 00:00:00 2001 From: dcoudert Date: Mon, 8 Nov 2021 16:28:35 +0100 Subject: [PATCH 075/126] trac #30566: cleaner use of weights --- src/sage/graphs/spanning_tree.pyx | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/sage/graphs/spanning_tree.pyx b/src/sage/graphs/spanning_tree.pyx index f50dea6b086..9cad7642635 100644 --- a/src/sage/graphs/spanning_tree.pyx +++ b/src/sage/graphs/spanning_tree.pyx @@ -796,7 +796,7 @@ cpdef boruvka(G, wfunction=None, bint check=False, bint by_weight=True): return T -def random_spanning_tree(G, output_as_graph=False, by_weight=False, weight_function=None): +def random_spanning_tree(G, output_as_graph=False, by_weight=False, weight_function=None, check_weight=True): r""" Return a random spanning tree of the graph. @@ -829,6 +829,9 @@ def random_spanning_tree(G, output_as_graph=False, by_weight=False, weight_funct transform the label into a weight (note that, if the weight returned is not convertible to a float, an error is raised) + - ``check_weight`` -- boolean (default: ``True``); whether to check that + the ``weight_function`` outputs a number for each edge. + .. SEEALSO:: :meth:`~sage.graphs.generic_graph.GenericGraph.spanning_trees_count` @@ -911,14 +914,11 @@ def random_spanning_tree(G, output_as_graph=False, by_weight=False, weight_funct return G.copy() return list(G.edge_iterator(label=False)) - if weight_function is not None: - by_weight = True + by_weight, weight_function = G._get_weight_function(by_weight=by_weight, + weight_function=weight_function, + check_weight=check_weight) if by_weight: - if weight_function is None: - def weight_function(e): - return 1 if e[2] is None else e[2] - def next_neighbor(s): p = random() * sum(weight_function(e) for e in G.edge_iterator(s, sort_vertices=False)) @@ -927,7 +927,6 @@ def random_spanning_tree(G, output_as_graph=False, by_weight=False, weight_funct if p <= 0: break return e[1] if e[0] == s else e[0] - else: def next_neighbor(s): return G.neighbors(s)[randint(0, G.degree(s) - 1)] From 8e26780afcbe40662f27b96b7dbd563843d08452 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 29 Oct 2021 16:54:52 -0700 Subject: [PATCH 076/126] build/pkgs/sagemath_doc_{html,pdf}: New; delegate to them from targets doc-html etc. --- build/make/Makefile.in | 38 ++++++++++++----------- build/pkgs/sagemath_doc_html/dependencies | 5 +++ build/pkgs/sagemath_doc_html/spkg-install | 3 ++ build/pkgs/sagemath_doc_html/trees.txt | 1 + build/pkgs/sagemath_doc_html/type | 1 + build/pkgs/sagemath_doc_pdf/dependencies | 1 + build/pkgs/sagemath_doc_pdf/spkg-install | 3 ++ build/pkgs/sagemath_doc_pdf/trees.txt | 1 + build/pkgs/sagemath_doc_pdf/type | 1 + 9 files changed, 36 insertions(+), 18 deletions(-) create mode 100644 build/pkgs/sagemath_doc_html/dependencies create mode 100755 build/pkgs/sagemath_doc_html/spkg-install create mode 100644 build/pkgs/sagemath_doc_html/trees.txt create mode 100644 build/pkgs/sagemath_doc_html/type create mode 120000 build/pkgs/sagemath_doc_pdf/dependencies create mode 100755 build/pkgs/sagemath_doc_pdf/spkg-install create mode 100644 build/pkgs/sagemath_doc_pdf/trees.txt create mode 100644 build/pkgs/sagemath_doc_pdf/type diff --git a/build/make/Makefile.in b/build/make/Makefile.in index 1972e1a14ce..241bfae009a 100644 --- a/build/make/Makefile.in +++ b/build/make/Makefile.in @@ -52,6 +52,10 @@ SAGE_SPKG = sage-spkg # These are added to SAGE_SPKG in the call SAGE_SPKG_OPTIONS = @SAGE_SPKG_OPTIONS@ +# Where the Sage distribution installs documentation. +# set to empty if --disable-doc is used +SAGE_DOCS = $(SAGE_LOCAL) + # Where the Sage distribution installs Python packages. # This can be overridden by 'make SAGE_VENV=/some/venv'. SAGE_VENV = @SAGE_VENV@ @@ -142,7 +146,7 @@ SCRIPT_PACKAGES = @SAGE_SCRIPT_PACKAGES@ # inst_git = $(INST)/.dummy $(foreach pkgname,$(BUILT_PACKAGES),\ - $(eval inst_$(pkgname) = $(foreach tree, $(trees_$(pkgname)), $($(tree))/$(SPKG_INST_RELDIR)/$(pkgname)-$(vers_$(pkgname))))) + $(eval inst_$(pkgname) = $(foreach tree, $(trees_$(pkgname)), $(and $($(tree)), $($(tree))/$(SPKG_INST_RELDIR)/$(pkgname)-$(vers_$(pkgname)))))) $(foreach pkgname,$(DUMMY_PACKAGES),\ $(eval inst_$(pkgname) = $(SAGE_LOCAL)/$(SPKG_INST_RELDIR)/.dummy)) @@ -157,7 +161,7 @@ $(SAGE_LOCAL)/$(SPKG_INST_RELDIR)/.dummy: # Filtered by installation tree -$(foreach tree,SAGE_LOCAL SAGE_VENV, \ +$(foreach tree,SAGE_LOCAL SAGE_VENV SAGE_DOC_PREFIX, \ $(eval $(tree)_INSTALLED_PACKAGE_INSTS = \ $(foreach pkgname,$(INSTALLED_PACKAGES), \ $(if $(findstring $(tree),$(trees_$(pkgname))), \ @@ -245,6 +249,11 @@ all-build-venv: toolchain-deps all-sage-venv: $(SAGE_VENV_INSTALLED_PACKAGE_INSTS) $(SAGE_VENV_UNINSTALLED_PACKAGES_CLEANS) +all-build-docs: toolchain-deps + +$(MAKE_REC) all-sage-docs + +all-sage-docs: $(SAGE_DOCS_INSTALLED_PACKAGE_INSTS) $(SAGE_DOCS_UNINSTALLED_PACKAGES_CLEANS) + # Download all packages which should be inside an sdist tarball (the -B # option to make forces all targets to be built unconditionally) download-for-sdist: @@ -316,35 +325,28 @@ base: $(inst_patch) $(inst_pkgconf) # # $ ./sage --docbuild -H -# Building the documentation has many dependencies, because all -# documented modules are imported and because we use matplotlib to -# produce plots. -DOC_DEPENDENCIES = sagelib sage_docbuild $(inst_sphinx) \ - | $(SAGERUNTIME) $(inst_maxima) $(inst_networkx) $(inst_scipy) $(inst_sympy) \ - $(inst_matplotlib) $(inst_pillow) $(inst_mathjax) $(inst_mpmath) \ - $(inst_ipykernel) $(inst_jupyter_client) $(inst_conway_polynomials) \ - $(inst_tachyon) $(inst_jmol) $(inst_thebe) $(inst_ipywidgets) - -doc: doc-html +doc: $(SAGE_DOCS_INSTALLED_PACKAGE_INSTS) $(SAGE_DOCS_UNINSTALLED_PACKAGES_CLEANS) -doc-html: $(DOC_DEPENDENCIES) - $(AM_V_at)cd "$(SAGE_SRC)/doc" && sage-logger -p "$(MAKE) doc-html" $(SAGE_ROOT)/logs/dochtml.log +# All doc-building is delegated to the script packages +# sagemath_doc_html, sagemath_doc_pdf +doc-html: sagemath_doc_html # 'doc-html-no-plot': build docs without building the graphics coming # from the '.. plot' directive, in case you want to save a few # megabytes of disk space. 'doc-clean' is a prerequisite because the # presence of graphics is cached in src/doc/output. doc-html-no-plot: doc-clean - $(AM_V_at)sage-logger -p "$(MAKE) SAGE_DOCBUILD_OPTS=\"$(SAGE_DOCBUILD_OPTS) --no-plot\" doc-html" $(SAGE_ROOT)/logs/dochtml.log + +$(MAKE_REC) SAGE_SKIP_PLOT_DIRECTIVE=yes doc-html +# Using mathjax is actually the default, but this target can be used +# to override an environment setting of SAGE_DOC_MATHJAX=no doc-html-mathjax: - $(AM_V_at)sage-logger -p "$(MAKE) SAGE_DOCBUILD_OPTS=\"$(SAGE_DOCBUILD_OPTS) -j\" doc-html" $(SAGE_ROOT)/logs/dochtml.log + +$(MAKE_REC) SAGE_DOC_MATHJAX=yes doc-html # Keep target 'doc-html-jsmath' for backwards compatibility. doc-html-jsmath: doc-html-mathjax -doc-pdf: $(DOC_DEPENDENCIES) - $(AM_V_at)cd "$(SAGE_SRC)/doc" && sage-logger -p "$(MAKE) doc-pdf" $(SAGE_ROOT)/logs/docpdf.log +doc-pdf: sagemath_doc_pdf doc-clean: doc-src-clean doc-output-clean diff --git a/build/pkgs/sagemath_doc_html/dependencies b/build/pkgs/sagemath_doc_html/dependencies new file mode 100644 index 00000000000..8d37b42880c --- /dev/null +++ b/build/pkgs/sagemath_doc_html/dependencies @@ -0,0 +1,5 @@ +sagelib sphinx | $(SAGERUNTIME) maxima networkx scipy sympy matplotlib pillow mathjax mpmath ipykernel jupyter_client conway_polynomials tachyon jmol thebe ipywidgets + +# Building the documentation has many dependencies, because all +# documented modules are imported and because we use matplotlib to +# produce plots. diff --git a/build/pkgs/sagemath_doc_html/spkg-install b/build/pkgs/sagemath_doc_html/spkg-install new file mode 100755 index 00000000000..801aa7769fe --- /dev/null +++ b/build/pkgs/sagemath_doc_html/spkg-install @@ -0,0 +1,3 @@ +#! /usr/bin/env bash +cd $SAGE_ROOT/src/doc +$MAKE doc-html diff --git a/build/pkgs/sagemath_doc_html/trees.txt b/build/pkgs/sagemath_doc_html/trees.txt new file mode 100644 index 00000000000..77be9495f24 --- /dev/null +++ b/build/pkgs/sagemath_doc_html/trees.txt @@ -0,0 +1 @@ +SAGE_DOCS diff --git a/build/pkgs/sagemath_doc_html/type b/build/pkgs/sagemath_doc_html/type new file mode 100644 index 00000000000..a6a7b9cd726 --- /dev/null +++ b/build/pkgs/sagemath_doc_html/type @@ -0,0 +1 @@ +standard diff --git a/build/pkgs/sagemath_doc_pdf/dependencies b/build/pkgs/sagemath_doc_pdf/dependencies new file mode 120000 index 00000000000..5bad6e468d6 --- /dev/null +++ b/build/pkgs/sagemath_doc_pdf/dependencies @@ -0,0 +1 @@ +../sagemath_doc_html/dependencies \ No newline at end of file diff --git a/build/pkgs/sagemath_doc_pdf/spkg-install b/build/pkgs/sagemath_doc_pdf/spkg-install new file mode 100755 index 00000000000..f04f4b75d9a --- /dev/null +++ b/build/pkgs/sagemath_doc_pdf/spkg-install @@ -0,0 +1,3 @@ +#! /usr/bin/env bash +cd $SAGE_ROOT/src/doc +$MAKE doc-pdf diff --git a/build/pkgs/sagemath_doc_pdf/trees.txt b/build/pkgs/sagemath_doc_pdf/trees.txt new file mode 100644 index 00000000000..77be9495f24 --- /dev/null +++ b/build/pkgs/sagemath_doc_pdf/trees.txt @@ -0,0 +1 @@ +SAGE_DOCS diff --git a/build/pkgs/sagemath_doc_pdf/type b/build/pkgs/sagemath_doc_pdf/type new file mode 100644 index 00000000000..134d9bc32d5 --- /dev/null +++ b/build/pkgs/sagemath_doc_pdf/type @@ -0,0 +1 @@ +optional From eeb8777b0c31bbf15f0d97171c3eccce119cffac Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 29 Oct 2021 21:18:55 -0700 Subject: [PATCH 077/126] m4/sage_spkg_collect.m4: Determine install tree for python3 via new trees.txt mechanism --- build/pkgs/python3/trees.txt | 1 + m4/sage_spkg_collect.m4 | 12 ++++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) create mode 100644 build/pkgs/python3/trees.txt diff --git a/build/pkgs/python3/trees.txt b/build/pkgs/python3/trees.txt new file mode 100644 index 00000000000..f01330b2fe5 --- /dev/null +++ b/build/pkgs/python3/trees.txt @@ -0,0 +1 @@ +SAGE_VENV diff --git a/m4/sage_spkg_collect.m4 b/m4/sage_spkg_collect.m4 index e6dcecdd24c..90f10986f78 100644 --- a/m4/sage_spkg_collect.m4 +++ b/m4/sage_spkg_collect.m4 @@ -181,10 +181,14 @@ for DIR in $SAGE_ROOT/build/pkgs/*; do dnl trees. For example, if we decide to create a separate tree for a venv with the dnl Jupyter notebook, then packages such as jupyter_core would have to be installed into dnl two trees. - SPKG_TREE_VAR=SAGE_LOCAL - if test -f "$DIR/requirements.txt" -o -f "$DIR/install-requires.txt" -o "$SPKG_NAME" = python3; then - dnl A Python package or spkg installation of python3 itself - SPKG_TREE_VAR=SAGE_VENV + if test -f "$DIR/trees.txt"; then + SPKG_TREE_VAR="$(sed "s/#.*//;" "$DIR/trees.txt")" + else + SPKG_TREE_VAR=SAGE_LOCAL + if test -f "$DIR/requirements.txt" -o -f "$DIR/install-requires.txt"; then + dnl A Python package + SPKG_TREE_VAR=SAGE_VENV + fi fi SAGE_PACKAGE_TREES="${SAGE_PACKAGE_TREES}$(printf '\ntrees_')${SPKG_NAME} = ${SPKG_TREE_VAR}" From c8e19a07dd6039be28f17e67e9fd2e693f14a52b Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 8 Nov 2021 16:26:47 -0800 Subject: [PATCH 078/126] fixup --- build/make/Makefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/make/Makefile.in b/build/make/Makefile.in index 241bfae009a..94e307a40fe 100644 --- a/build/make/Makefile.in +++ b/build/make/Makefile.in @@ -161,7 +161,7 @@ $(SAGE_LOCAL)/$(SPKG_INST_RELDIR)/.dummy: # Filtered by installation tree -$(foreach tree,SAGE_LOCAL SAGE_VENV SAGE_DOC_PREFIX, \ +$(foreach tree,SAGE_LOCAL SAGE_VENV SAGE_DOCS, \ $(eval $(tree)_INSTALLED_PACKAGE_INSTS = \ $(foreach pkgname,$(INSTALLED_PACKAGES), \ $(if $(findstring $(tree),$(trees_$(pkgname))), \ From 5a4424b3fa0c546bc05aef5320429749f1b143e9 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 8 Nov 2021 17:24:43 -0800 Subject: [PATCH 079/126] build/make/Makefile.in (all-sage): Do not include packages installed in SAGE_DOCS --- build/make/Makefile.in | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build/make/Makefile.in b/build/make/Makefile.in index 94e307a40fe..4b9abbbcdb5 100644 --- a/build/make/Makefile.in +++ b/build/make/Makefile.in @@ -232,11 +232,11 @@ build-start: all-build base-toolchain: _clean-broken-gcc base +$(MAKE_REC) toolchain -# All targets except for the base packages +# All targets except for the base packages and except the documentation all-sage: \ sagelib \ - $(INSTALLED_PACKAGE_INSTS) \ - $(UNINSTALLED_PACKAGES_CLEANS) + $(SAGE_LOCAL_INSTALLED_PACKAGE_INSTS) $(SAGE_LOCAL_UNINSTALLED_PACKAGES_CLEANS) \ + $(SAGE_VENV_INSTALLED_PACKAGE_INSTS) $(SAGE_VENV_UNINSTALLED_PACKAGES_CLEANS) # Same but filtered by installation trees: all-build-local: toolchain-deps From cb7874121095397431952b039fb10a03c538b734 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 8 Nov 2021 21:59:55 -0800 Subject: [PATCH 080/126] src/doc/en/developer/packaging.rst: Exlpain trees.txt --- src/doc/en/developer/packaging.rst | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/doc/en/developer/packaging.rst b/src/doc/en/developer/packaging.rst index 498825377c5..9bdab77e80d 100644 --- a/src/doc/en/developer/packaging.rst +++ b/src/doc/en/developer/packaging.rst @@ -171,7 +171,8 @@ The following are some additional files which can be added: | `-- baz.patch |-- spkg-check.in |-- spkg-configure.m4 - `-- spkg-src + |-- spkg-src + `-- trees.txt We discuss the individual files in the following sections. @@ -717,6 +718,28 @@ packages and optional packages should only depend on standard or optional packages. +.. _section-dependencies: + +Where packages are installed +---------------------------- + +The Sage distribution has the notion of several installation trees. + +- ``$SAGE_VENV`` is the default installation tree for all Python packages, i.e., + normal packages with an ``install-requires.txt`` and pip packages + with a ``requirements.txt``. + +- ``$SAGE_LOCAL`` is the default installation tree for all non-Python packages. + +- ``$SAGE_DOCS`` (only set at build time) is an installation tree for the + HTML and PDF documentation. + +By placing a file ``trees.txt`` in the package directory, the installation tree +can be overridden. For example, ``build/pkgs/python3/trees.txt`` contains the +word ``SAGE_VENV``, and ``build/pkgs/sagemath_doc_html/trees.txt`` contains the +word ``SAGE_DOCS``. + + .. _section-spkg-patching: Patching Sources From 9e8aa5c51838aabac16368da91404aa76c37ca68 Mon Sep 17 00:00:00 2001 From: sheerluck Date: Mon, 8 Nov 2021 13:20:01 +0300 Subject: [PATCH 081/126] tox.ini: Add gentoo-python3.10 --- .github/workflows/tox-experimental.yml | 2 +- .github/workflows/tox-optional.yml | 2 +- .github/workflows/tox.yml | 2 +- tox.ini | 1 + 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/tox-experimental.yml b/.github/workflows/tox-experimental.yml index 554a058cdb9..54c8373a362 100644 --- a/.github/workflows/tox-experimental.yml +++ b/.github/workflows/tox-experimental.yml @@ -41,7 +41,7 @@ jobs: # This list is different from the one in tox.yml: # Trac #31526 switches gcc 4.x-based distributions to using the gcc_spkg configuration factor # Trac #32281 removes gcc 4.x-based distributions whose binutils are unusable - tox_system_factor: [ubuntu-xenial, ubuntu-bionic, ubuntu-focal, ubuntu-groovy, ubuntu-hirsute, debian-jessie-gcc_spkg, debian-stretch, debian-buster, debian-bullseye, debian-sid, linuxmint-18, linuxmint-19, linuxmint-19.3, linuxmint-20.1, fedora-26, fedora-27, fedora-28, fedora-29, fedora-30, fedora-31, fedora-32, fedora-33, fedora-34, centos-7-gcc_spkg, centos-8, gentoo, archlinux-latest, opensuse-15, opensuse-15.3, opensuse-tumbleweed, slackware-14.2, conda-forge, ubuntu-bionic-i386, manylinux-2_24-i686, debian-buster-i386, centos-7-i386-gcc_spkg] + tox_system_factor: [ubuntu-xenial, ubuntu-bionic, ubuntu-focal, ubuntu-groovy, ubuntu-hirsute, debian-jessie-gcc_spkg, debian-stretch, debian-buster, debian-bullseye, debian-sid, linuxmint-18, linuxmint-19, linuxmint-19.3, linuxmint-20.1, fedora-26, fedora-27, fedora-28, fedora-29, fedora-30, fedora-31, fedora-32, fedora-33, fedora-34, centos-7-gcc_spkg, centos-8, gentoo-python3.9, gentoo-python3.10, archlinux-latest, opensuse-15, opensuse-15.3, opensuse-tumbleweed, slackware-14.2, conda-forge, ubuntu-bionic-i386, manylinux-2_24-i686, debian-buster-i386, centos-7-i386-gcc_spkg] tox_packages_factor: [maximal] targets_pattern: [0-g, h-o, p, q-z] env: diff --git a/.github/workflows/tox-optional.yml b/.github/workflows/tox-optional.yml index be97ecd37a8..bcdf349bee7 100644 --- a/.github/workflows/tox-optional.yml +++ b/.github/workflows/tox-optional.yml @@ -41,7 +41,7 @@ jobs: # This list is different from the one in tox.yml: # Trac #31526 switches gcc 4.x-based distributions to using the gcc_spkg configuration factor # Trac #32281 removes gcc 4.x-based distributions whose binutils are unusable - tox_system_factor: [ubuntu-xenial, ubuntu-bionic, ubuntu-focal, ubuntu-groovy, ubuntu-hirsute, debian-jessie-gcc_spkg, debian-stretch, debian-buster, debian-bullseye, debian-sid, linuxmint-18, linuxmint-19, linuxmint-19.3, linuxmint-20.1, fedora-26, fedora-27, fedora-28, fedora-29, fedora-30, fedora-31, fedora-32, fedora-33, fedora-34, centos-7-gcc_spkg, centos-8, gentoo, archlinux-latest, opensuse-15, opensuse-15.3, opensuse-tumbleweed, slackware-14.2, conda-forge, ubuntu-bionic-i386, manylinux-2_24-i686, debian-buster-i386, centos-7-i386-gcc_spkg] + tox_system_factor: [ubuntu-xenial, ubuntu-bionic, ubuntu-focal, ubuntu-groovy, ubuntu-hirsute, debian-jessie-gcc_spkg, debian-stretch, debian-buster, debian-bullseye, debian-sid, linuxmint-18, linuxmint-19, linuxmint-19.3, linuxmint-20.1, fedora-26, fedora-27, fedora-28, fedora-29, fedora-30, fedora-31, fedora-32, fedora-33, fedora-34, centos-7-gcc_spkg, centos-8, gentoo-python3.9, gentoo-python3.10, archlinux-latest, opensuse-15, opensuse-15.3, opensuse-tumbleweed, slackware-14.2, conda-forge, ubuntu-bionic-i386, manylinux-2_24-i686, debian-buster-i386, centos-7-i386-gcc_spkg] tox_packages_factor: [maximal] targets_pattern: [0-g, h-o, p, q-z] env: diff --git a/.github/workflows/tox.yml b/.github/workflows/tox.yml index 68d5661c5bb..493e8342920 100644 --- a/.github/workflows/tox.yml +++ b/.github/workflows/tox.yml @@ -38,7 +38,7 @@ jobs: fail-fast: false max-parallel: 20 matrix: - tox_system_factor: [ubuntu-trusty, ubuntu-xenial, ubuntu-bionic, ubuntu-focal, ubuntu-groovy, ubuntu-hirsute, ubuntu-impish, debian-jessie, debian-stretch, debian-buster, debian-bullseye, debian-sid, linuxmint-17, linuxmint-18, linuxmint-19, linuxmint-19.3, linuxmint-20.1, linuxmint-20.2, fedora-26, fedora-27, fedora-28, fedora-29, fedora-30, fedora-31, fedora-32, fedora-33, fedora-34, fedora-35, centos-7, centos-8, gentoo, gentoo-python3.7, archlinux-latest, opensuse-15, opensuse-15.3, opensuse-tumbleweed, slackware-14.2, conda-forge, ubuntu-bionic-i386, manylinux-2_24-i686, debian-buster-i386, centos-7-i386] + tox_system_factor: [ubuntu-trusty, ubuntu-xenial, ubuntu-bionic, ubuntu-focal, ubuntu-groovy, ubuntu-hirsute, ubuntu-impish, debian-jessie, debian-stretch, debian-buster, debian-bullseye, debian-sid, linuxmint-17, linuxmint-18, linuxmint-19, linuxmint-19.3, linuxmint-20.1, linuxmint-20.2, fedora-26, fedora-27, fedora-28, fedora-29, fedora-30, fedora-31, fedora-32, fedora-33, fedora-34, fedora-35, centos-7, centos-8, gentoo-python3.9, gentoo-python3.10, archlinux-latest, opensuse-15, opensuse-15.3, opensuse-tumbleweed, slackware-14.2, conda-forge, ubuntu-bionic-i386, manylinux-2_24-i686, debian-buster-i386, centos-7-i386] tox_packages_factor: [minimal, standard] env: TOX_ENV: docker-${{ matrix.tox_system_factor }}-${{ matrix.tox_packages_factor }} diff --git a/tox.ini b/tox.ini index 8c5301eb28e..3fae601230e 100644 --- a/tox.ini +++ b/tox.ini @@ -246,6 +246,7 @@ setenv = gentoo: BASE_IMAGE=sheerluck/sage-on-gentoo-stage4 gentoo-python3.7: BASE_TAG=latest-py37 gentoo-python3.9: BASE_TAG=latest-py39 + gentoo-python3.10: BASE_TAG=latest-py10 gentoo: IGNORE_MISSING_SYSTEM_PACKAGES=no # # https://hub.docker.com/_/archlinux/ From 22235afa31d10b17c2c05276b6ca573e4d53a04d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Tue, 9 Nov 2021 20:44:16 +0100 Subject: [PATCH 082/126] fix some lgtm and pep details in sloane_functions.py --- src/sage/combinat/sloane_functions.py | 178 +++++++++++++------------- 1 file changed, 88 insertions(+), 90 deletions(-) diff --git a/src/sage/combinat/sloane_functions.py b/src/sage/combinat/sloane_functions.py index 4307051be34..be0f54cd8b3 100644 --- a/src/sage/combinat/sloane_functions.py +++ b/src/sage/combinat/sloane_functions.py @@ -125,11 +125,18 @@ # just used for handy .load, .save, etc. import sys import inspect + from sage.structure.sage_object import SageObject from sage.arith.srange import srange from sage.rings.integer_ring import ZZ from sage.functions.all import prime_pi from sage.rings.integer import Integer as Integer_class +# You may have to import more here when defining new sequences +import sage.arith.all as arith +from sage.matrix.matrix_space import MatrixSpace +from sage.rings.rational_field import QQ +from sage.combinat import combinat +from sage.misc.misc_c import prod class SloaneSequence(SageObject): @@ -307,22 +314,16 @@ def __getitem__(self, n): return self(n) LENGTH = 100000 - (start, stop, step) = n.indices(2*LENGTH) + (start, stop, step) = n.indices(2 * LENGTH) if abs(stop - start) > LENGTH: - raise IndexError("slice (=%s) too long"%n) + raise IndexError("slice (=%s) too long" % n) return [self(i) for i in range(start, stop, step) if i >= self.offset] + ######################################################################## # II. Actual implementations of Sloane sequences. ######################################################################## -# You may have to import more here when defining new sequences -import sage.arith.all as arith -from sage.matrix.matrix_space import MatrixSpace -from sage.rings.rational_field import QQ -from sage.combinat import combinat -from sage.misc.misc_c import prod - # This one should be here! class A000001(SloaneSequence): @@ -638,7 +639,7 @@ def __init__(self): - Jaap Spies (2007-01-30) """ SloaneSequence.__init__(self, offset=0) - self._b=[] + self._b = [] self._precompute(2) def _repr_(self): @@ -770,7 +771,7 @@ def pi(self): d, d1 = a//b, a1//b1 while d == d1: yield d - a, a1 = 10*(a%b), 10*(a1%b1) + a, a1 = 10*(a % b), 10*(a1 % b1) d, d1 = a//b, a1//b1 @@ -867,7 +868,7 @@ def _eval(self, n): sage: [sloane.A003418._eval(n) for n in range(1,11)] [1, 2, 6, 12, 60, 60, 420, 840, 2520, 2520] """ - return arith.lcm([i for i in range(1,n+1)]) + return arith.lcm([i for i in range(1, n+1)]) class A007318(SloaneSequence): @@ -929,7 +930,7 @@ def _eval(self, n): m += 1 m -= 1 k = n - m*(m+1)//2 - return arith.binomial(m,k) + return arith.binomial(m, k) class A008275(SloaneSequence): @@ -998,7 +999,7 @@ def s(self, n, k): sage: sloane.A008275.s(5,3) 35 """ - return (-1)**(n-k) * combinat.stirling_number1(n,k) + return (-1)**(n-k) * combinat.stirling_number1(n, k) def _eval(self, n): """ @@ -1076,7 +1077,7 @@ def s2(self, n, k): sage: sloane.A008277.s2(4,2) 7 """ - return combinat.stirling_number2(n,k) + return combinat.stirling_number2(n, k) def _eval(self, n): """ @@ -1155,10 +1156,10 @@ def _eval(self, n): m += 1 m -= 1 k = n - m*(m+1)//2 - if (m+k)%2: + if (m+k) % 2: return ZZ(0) sign = (-1)**((m+k)//2 + k) - return sign * arith.binomial((m+k)//2,k) + return sign * arith.binomial((m+k)//2, k) class A000010(SloaneSequence): @@ -1977,7 +1978,7 @@ def _repr_(self): """ return "1's-counting sequence: number of 1's in binary expansion of n." - def f(self,n): + def f(self, n): """ EXAMPLES:: @@ -2383,7 +2384,8 @@ def _eval(self, n): """ if n == 0: return ZZ.one() - return ZZ(sum( (i%2) * arith.euler_phi(i) * 2**(n//i) / (2*n) for i in arith.divisors(n) )) + return ZZ(sum((i % 2) * arith.euler_phi(i) * 2**(n//i) / (2*n) + for i in arith.divisors(n))) class A000032(SloaneSequence): @@ -2562,12 +2564,12 @@ def _precompute(self, how_many=150): """ try: self._b - n = self._n + self._n except AttributeError: self._b = [] - n = self.offset - self._n = n - self._b += [i for i in range(self._n, self._n+how_many) if sloane.A004086(i) == i] + self._n = self.offset + self._b += [i for i in range(self._n, self._n + how_many) + if sloane.A004086(i) == i] self._n += how_many def _eval(self, n): @@ -2861,8 +2863,8 @@ def _eval(self, n): [1, 4, 6, 8, 9, 10, 12, 14, 15, 16] """ if n == 1: - return ZZ.one() - return sloane.A002808(n-1) + return ZZ.one() + return sloane.A002808(n - 1) class A000043(SloaneSequence): @@ -3291,7 +3293,7 @@ def _eval(self, n): sage: [sloane.A002110._eval(n) for n in range(10)] [1, 2, 6, 30, 210, 2310, 30030, 510510, 9699690, 223092870] """ - return prod([sloane.A000040(i) for i in range(1,n+1)]) #n-th prime = A000040(n) + return prod([sloane.A000040(i) for i in range(1, n + 1)]) # n-th prime = A000040(n) class A000720(SloaneSequence): @@ -3404,7 +3406,7 @@ def _eval(self, n): sage: [sloane.A064553._eval(n) for n in range(1,11)] [1, 2, 3, 4, 4, 6, 5, 8, 9, 8] """ - return prod([(prime_pi(p)+1)**e for p,e in arith.factor(n)]) + return prod([(prime_pi(p)+1)**e for p, e in arith.factor(n)]) class A001055(SloaneSequence): @@ -3469,15 +3471,15 @@ def nwf(self, n, m): return ZZ.one() if arith.is_prime(n): if m < n: - return ZZ(0) + return ZZ.zero() else: return ZZ.one() s = ZZ(0) for d in arith.divisors(n): if d > 1 and d <= m and d < n: - s += self.nwf(n//d, d) + s += self.nwf(n // d, d) if n <= m: - s += 1 + s += 1 return s def _eval(self, n): @@ -3692,7 +3694,8 @@ def _precompute(self, how_many=150): sage: len(sloane.A005117._b) - initial > 0 True """ - self._b += [i for i in range(self._n, self._n+how_many) if max(e for _,e in arith.factor(i)) <= 1] + self._b += [i for i in range(self._n, self._n+how_many) + if max(e for _, e in arith.factor(i)) <= 1] self._n += how_many def _eval(self, n): @@ -4580,7 +4583,8 @@ def _eval(self, n): # a(n) = Sum from k=1 to n of k! StirlingS2(n, k) if n == 0: return ZZ.one() - return sum(arith.factorial(k) * combinat.stirling_number2(n,k) for k in range(1, n+1)) + return sum(arith.factorial(k) * combinat.stirling_number2(n, k) + for k in range(1, n+1)) class A006318(SloaneSequence): @@ -4745,6 +4749,7 @@ def _eval(self, n): """ return arith.factorial(2*n) / (arith.factorial(n)*2**n) + class A006882(SloaneSequence): def __init__(self): r""" @@ -4897,7 +4902,7 @@ def _eval(self, n): sage: [sloane.A000984._eval(n) for n in range(10)] [1, 2, 6, 20, 70, 252, 924, 3432, 12870, 48620] """ - return arith.binomial(2*n,n) + return arith.binomial(2 * n, n) class A001405(SloaneSequence): @@ -5060,8 +5065,6 @@ def _eval(self, n): return ZZ(n * (n+1) * (2*n+1) // 6) - - # Theme: maximal permanent of an m x n (0,1)- matrix: # Seok-Zun Song et al. Extremes of permanents of (0,1)-matrices, p. 201-202. @@ -5083,7 +5086,7 @@ def _precompute(self, how_many=20): f = self._f self._b += [next(f) for i in range(how_many)] - def gen(self,a0,a1,d): + def gen(self, a0, a1, d): """ EXAMPLES:: @@ -5120,7 +5123,7 @@ def list(self, n): """ self._eval(n) # force computation return self._b[:n] - _k = 1 + _k = 1 class A000153(ExtremesOfPermanentsSequence): @@ -5163,7 +5166,7 @@ def __init__(self): """ SloaneSequence.__init__(self, offset=0) self._b = [] - self._a0a1d = (0,1,2) + self._a0a1d = (0, 1, 2) self._precompute(2) # force precomputation, e.g. a(0) will fail when asked first def _repr_(self): @@ -5218,7 +5221,7 @@ def __init__(self): """ SloaneSequence.__init__(self, offset=0) self._b = [] - self._a0a1d = (1,1,1) + self._a0a1d = (1, 1, 1) self._precompute(2) # force precomputation, e.g. a(0) will fail when asked first def _repr_(self): @@ -5277,7 +5280,7 @@ def __init__(self): - Jaap Spies (2007-01-23) """ SloaneSequence.__init__(self, offset=1) - self._a0a1d = (0,1,3) + self._a0a1d = (0, 1, 3) self._b = [] self._k = self.offset + 1 @@ -5337,7 +5340,7 @@ def __init__(self): - Jaap Spies (2007-01-13) """ SloaneSequence.__init__(self, offset=2) - self._a0a1d = (0,1,4) + self._a0a1d = (0, 1, 4) self._b = [] self._k = self.offset + 1 @@ -5397,7 +5400,7 @@ def __init__(self): - Jaap Spies (2007-01-13) """ SloaneSequence.__init__(self, offset=3) - self._a0a1d = (0,1,5) + self._a0a1d = (0, 1, 5) self._b = [] self._k = self.offset + 1 @@ -5410,8 +5413,9 @@ def _repr_(self): """ return "a(n) = n*a(n-1) + (n-5)*a(n-2), a(3) = 0, a(4) = 1." + class ExtremesOfPermanentsSequence2(ExtremesOfPermanentsSequence): - def gen(self,a0,a1,d): + def gen(self, a0, a1, d): """ EXAMPLES:: @@ -5483,7 +5487,7 @@ def __init__(self): - Jaap Spies (2007-01-23) """ SloaneSequence.__init__(self, offset=1) - self._a0a1d = (6,43,6) + self._a0a1d = (6, 43, 6) self._k = self.offset + 1 self._b = [] @@ -5545,7 +5549,7 @@ def __init__(self): - Jaap Spies (2007-01-23) """ SloaneSequence.__init__(self, offset=0) - self._a0a1d = (0,2,1) + self._a0a1d = (0, 2, 1) self._b = [] self._precompute(2) self._k1 = 2 @@ -6054,7 +6058,7 @@ def _eval(self, n): sage: [sloane.A000203._eval(n) for n in range(1,11)] [1, 3, 4, 7, 6, 12, 8, 15, 13, 18] """ - return sum(arith.divisors(n)) #alternative: return arith.sigma(n) + return sum(arith.divisors(n)) # alternative: return arith.sigma(n) class A001157(SloaneSequence): @@ -6110,7 +6114,7 @@ def _eval(self, n): sage: [sloane.A001157._eval(n) for n in range(1,11)] [1, 5, 10, 21, 26, 50, 50, 85, 91, 130] """ - return arith.sigma(n,2) + return arith.sigma(n, 2) class A008683(SloaneSequence): @@ -6395,11 +6399,8 @@ def _eval(self, n): return ZZ(10**n-1)//9 - - - # inhomogeneous second order recurrences -def recur_gen2b(a0,a1,a2,a3,b): +def recur_gen2b(a0, a1, a2, a3, b): r""" Inhomogeneous second-order linear recurrence generator with fixed coefficients and `b = f(n)` @@ -6422,6 +6423,7 @@ def recur_gen2b(a0,a1,a2,a3,b): x, y = y, a3*x+a2*y + b(n) yield x + class RecurrenceSequence(SloaneSequence): def _precompute(self, how_many=20): """ @@ -6495,7 +6497,7 @@ def __init__(self): - Jaap Spies (2007-01-19) """ SloaneSequence.__init__(self, offset=0) - self._params = (0,1,34,-1,self.g) + self._params = (0, 1, 34, -1, self.g) self._b = [] self._precompute() @@ -6510,7 +6512,7 @@ def _repr_(self): """ return "Numbers that are both triangular and square: a(n) = 34a(n-1) - a(n-2) + 2." - def g(self,k): + def g(self, k): """ EXAMPLES:: @@ -6645,7 +6647,7 @@ def _eval(self, n): sage: [sloane.A001221._eval(n) for n in range(1,10)] [0, 1, 1, 1, 1, 2, 1, 1, 1] """ - return len(arith.prime_divisors(n)) # there is a PARI function omega + return len(arith.prime_divisors(n)) # there is a PARI function omega class A001222(SloaneSequence): @@ -6891,12 +6893,12 @@ def _precompute(self, how_many=150): """ try: self._b - n = self._n + self._n except AttributeError: self._b = [] - n = 1 - self._n = n - self._b += [i for i in range(self._n, self._n+how_many) if sum(e for _,e in arith.factor(i)) == 2] + self._n = 1 + self._b += [i for i in range(self._n, self._n + how_many) + if sum(e for _, e in arith.factor(i)) == 2] self._n += how_many def _eval(self, n): @@ -6995,12 +6997,11 @@ def _precompute(self, how_many=10000): """ try: self._b - n = self._n + self._n except AttributeError: self._b = [1] - n = 1 - self._n = n - self._b += self._powerful_numbers_in_range(self._n, self._n+how_many) + self._n = 1 + self._b += self._powerful_numbers_in_range(self._n, self._n + how_many) self._n += how_many def _powerful_numbers_in_range(self, n, m): @@ -7017,7 +7018,7 @@ def _powerful_numbers_in_range(self, n, m): n = 4 # Use PARI directly -- much faster. from sage.libs.pari.all import pari - L = pari('v=listcreate(); for(i=%s,%s,if(vecmin(factor(i)[,2])>1,listput(v,i))); v'%(n,m)) + L = pari('v=listcreate(); for(i=%s,%s,if(vecmin(factor(i)[,2])>1,listput(v,i))); v' % (n, m)) return [ZZ(x) for x in L] # not very many, so not much overhead def _eval(self, n): @@ -7159,12 +7160,12 @@ def _precompute(self, how_many=150): """ try: self._b - n = self._n + self._n except AttributeError: self._b = [] - n = self.offset - self._n = n - self._b += [i for i in range(self._n, self._n+how_many) if arith.euler_phi(2*i-1) < arith.euler_phi(2*i)] + self._n = self.offset + self._b += [i for i in range(self._n, self._n + how_many) + if arith.euler_phi(2 * i - 1) < arith.euler_phi(2 * i)] self._n += how_many def _eval(self, n): @@ -7199,10 +7200,8 @@ def list(self, n): return self.list(n) - - # a group of sequences uses this function: -def recur_gen2(a0,a1,a2,a3): +def recur_gen2(a0, a1, a2, a3): r""" homogeneous general second-order linear recurrence generator with fixed coefficients @@ -7768,9 +7767,6 @@ def _repr_(self): return "Linear 2nd order recurrence, a(n) = 6 a(n-1) + 5 a(n-2)." - - - # todo jsp # # @@ -8134,7 +8130,7 @@ def _eval(self, n): # a group of sequences uses this function: -def recur_gen3(a0,a1,a2,a3,a4,a5): +def recur_gen3(a0, a1, a2, a3, a4, a5): r""" homogeneous general third-order linear recurrence generator with fixed coefficients @@ -8149,7 +8145,7 @@ def recur_gen3(a0,a1,a2,a3,a4,a5): sage: [next(it) for i in range(10)] [1, 1, 1, 3, 5, 9, 17, 31, 57, 105] """ - x, y ,z = ZZ(a0), ZZ(a1), ZZ(a2) + x, y, z = ZZ(a0), ZZ(a1), ZZ(a2) yield x while True: x, y, z = y, z, a5*x+a4*y+a3*z @@ -8583,8 +8579,11 @@ def _eval(self, n): if n == 1: return ZZ.one() m = 0 - for d in [i for i in arith.divisors(n) if i%2]: # d is odd divisor - k = min(d, 2*n/d) + for d in arith.divisors(n): + if not d % 2: + continue + # d is odd divisor + k = min(d, 2 * n // d) if k > m: m = k return ZZ(m) @@ -8660,12 +8659,12 @@ def _precompute(self, how_many=150): """ try: self._b - n = self._n + self._n except AttributeError: self._b = [] - n = 1 - self._n = n - self._b += [i for i in range(self._n, self._n+how_many) if self.is_number_of_the_third_kind(i)] + self._n = 1 + self._b += [i for i in range(self._n, self._n + how_many) + if self.is_number_of_the_third_kind(i)] self._n += how_many def _eval(self, n): @@ -8822,8 +8821,8 @@ def _eval(self, n): """ if n == 1 or n == 0: return ZZ.zero() - k = sum(i%2 for i in arith.divisors(n)) # A001227, the number of odd divisors - if n % 2 ==0: + k = sum(i % 2 for i in arith.divisors(n)) # A001227, the number of odd divisors + if n % 2 == 0: return k - 1 else: return k - 2 @@ -8902,7 +8901,7 @@ def _eval(self, n): if arith.is_prime(n) or arith.is_power_of_two(n): return ZZ.zero() - for d in srange(3,n,2): + for d in srange(3, n, 2): if n % d == 0: return min(d, 2*n//d) @@ -8942,8 +8941,8 @@ def _eval(self, n): if n < self.__n: return self.__data[n] from sage.combinat.expnums import expnums - self.__data = expnums(n+1, self.a) - self.__n = n+1 + self.__data = expnums(n + 1, self.a) + self.__n = n + 1 return self.__data[n] @@ -9111,9 +9110,8 @@ def _eval(self, n): """ if n <= 2: return ZZ.zero() - else: - return sum(sloane.A000045(i+1) * sloane.A000073(n-i-1) for i in range(n-2)) - + return sum(sloane.A000045(i + 1) * sloane.A000073(n - i - 1) + for i in range(n - 2)) ############################################################# @@ -9214,5 +9212,5 @@ def __getattribute__(self, name): except (AttributeError, TypeError): raise AttributeError(name) -sloane = Sloane() +sloane = Sloane() From 7ad6cd9a460a42a0d8a5f4f1397539bbc87d9c89 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 9 Nov 2021 12:02:22 -0800 Subject: [PATCH 083/126] build/pkgs/sagemath_doc_*/SPKG.rst: New --- build/pkgs/sagemath_doc_html/SPKG.rst | 10 ++++++++++ build/pkgs/sagemath_doc_pdf/SPKG.rst | 9 +++++++++ 2 files changed, 19 insertions(+) create mode 100644 build/pkgs/sagemath_doc_html/SPKG.rst create mode 100644 build/pkgs/sagemath_doc_pdf/SPKG.rst diff --git a/build/pkgs/sagemath_doc_html/SPKG.rst b/build/pkgs/sagemath_doc_html/SPKG.rst new file mode 100644 index 00000000000..2ece53ab56e --- /dev/null +++ b/build/pkgs/sagemath_doc_html/SPKG.rst @@ -0,0 +1,10 @@ +sagemath_doc_html: SageMath documentation in HTML format +======================================================== + +Upon installation, this package builds the SageMath documentation +in HTML format. + +It is a standard package. It is built on every invocation +of ``make`` or ``make all``, but not on ``make build``. +The documentation build can also be run separately using +``make doc-html``. diff --git a/build/pkgs/sagemath_doc_pdf/SPKG.rst b/build/pkgs/sagemath_doc_pdf/SPKG.rst new file mode 100644 index 00000000000..25c77ff12ea --- /dev/null +++ b/build/pkgs/sagemath_doc_pdf/SPKG.rst @@ -0,0 +1,9 @@ +sagemath_doc_pdf: SageMath documentation in PDF format +====================================================== + +Upon installation, this package builds the SageMath documentation +in PDF format. + +It is an optional package. It can be enabled at configuration time +using ``./configure --enable-sagemath_doc_pdf``. Alternatively, +it can be installed by using ``make doc-pdf``. From eb65e034bad3ec82b19c90211ca5bf70533e8fe5 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 9 Nov 2021 12:04:30 -0800 Subject: [PATCH 084/126] build/pkgs/sagemath_doc_*/dependencies: Add sage_docbuild --- build/pkgs/sagemath_doc_html/dependencies | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/pkgs/sagemath_doc_html/dependencies b/build/pkgs/sagemath_doc_html/dependencies index 8d37b42880c..fc793f07bae 100644 --- a/build/pkgs/sagemath_doc_html/dependencies +++ b/build/pkgs/sagemath_doc_html/dependencies @@ -1,4 +1,4 @@ -sagelib sphinx | $(SAGERUNTIME) maxima networkx scipy sympy matplotlib pillow mathjax mpmath ipykernel jupyter_client conway_polynomials tachyon jmol thebe ipywidgets +sagelib sphinx | $(SAGERUNTIME) maxima networkx scipy sympy matplotlib pillow mathjax mpmath ipykernel jupyter_client conway_polynomials tachyon jmol thebe ipywidgets sage_docbuild # Building the documentation has many dependencies, because all # documented modules are imported and because we use matplotlib to From 7989d8767056d68def98ee22116fbd24d7187d2f Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 9 Nov 2021 12:23:44 -0800 Subject: [PATCH 085/126] src/doc/Makefile: Handle errors from './sage --docbuild --all-documents' --- src/doc/Makefile | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/doc/Makefile b/src/doc/Makefile index 304d5aca147..5d2031bd964 100644 --- a/src/doc/Makefile +++ b/src/doc/Makefile @@ -30,6 +30,7 @@ doc-inventory-reference: else doc-inventory-reference: $(eval DOCS = $(shell cd $(SAGE_ROOT) && ./sage --docbuild --all-documents reference)) + @if [ -z "$(DOCS)" ]; then echo "Error: './sage --docbuild --all-documents' failed"; exit 1; fi $(eval BIBLIO = $(firstword $(DOCS))) $(eval OTHER_DOCS = $(wordlist 2, 100, $(DOCS))) $(MAKE) doc-inventory--$(subst /,-,$(BIBLIO)) @@ -40,6 +41,7 @@ endif # reference manual, html doc-html-reference: doc-inventory-reference $(eval DOCS = $(shell cd $(SAGE_ROOT) && ./sage --docbuild --all-documents reference)) + @if [ -z "$(DOCS)" ]; then echo "Error: './sage --docbuild --all-documents' failed"; exit 1; fi $(eval BIBLIO = $(firstword $(DOCS))) $(eval OTHER_DOCS = $(wordlist 2, 100, $(DOCS))) $(MAKE) SAGE_DOCBUILD_OPTS="$(SAGE_DOCBUILD_OPTS) --no-prune-empty-dirs" doc-html--$(subst /,-,$(BIBLIO)) @@ -48,7 +50,9 @@ doc-html-reference: doc-inventory-reference # other documentation, html doc-html-other: doc-html-reference - $(MAKE) SAGE_DOCBUILD_OPTS="$(SAGE_DOCBUILD_OPTS) --no-prune-empty-dirs" $(foreach doc, $(wordlist 2, 100, $(shell cd $(SAGE_ROOT) && ./sage --docbuild --all-documents all)), doc-html--$(subst /,-,$(doc))) + $(eval DOCS = $(shell cd $(SAGE_ROOT) && ./sage --docbuild --all-documents all)) + @if [ -z "$(DOCS)" ]; then echo "Error: './sage --docbuild --all-documents' failed"; exit 1; fi + $(MAKE) SAGE_DOCBUILD_OPTS="$(SAGE_DOCBUILD_OPTS) --no-prune-empty-dirs" $(foreach doc, $(wordlist 2, 100, $(DOCS)), doc-html--$(subst /,-,$(doc))) doc-html: doc-html-reference doc-html-other @@ -59,6 +63,7 @@ doc-pdf--%: # reference manual, pdf doc-pdf-reference: doc-inventory-reference $(eval DOCS = $(shell cd $(SAGE_ROOT) && ./sage --docbuild --all-documents reference)) + @if [ -z "$(DOCS)" ]; then echo "Error: './sage --docbuild --all-documents' failed"; exit 1; fi $(eval BIBLIO = $(firstword $(DOCS))) $(eval OTHER_DOCS = $(wordlist 2, 100, $(DOCS))) $(MAKE) SAGE_DOCBUILD_OPTS="$(SAGE_DOCBUILD_OPTS) --no-prune-empty-dirs" doc-pdf--$(subst /,-,$(BIBLIO)) @@ -67,7 +72,9 @@ doc-pdf-reference: doc-inventory-reference # other documentation, pdf doc-pdf-other: doc-html-reference - $(MAKE) SAGE_DOCBUILD_OPTS="$(SAGE_DOCBUILD_OPTS) --no-prune-empty-dirs" $(foreach doc, $(wordlist 2, 100, $(shell cd $(SAGE_ROOT) && ./sage --docbuild --all-documents all)), doc-pdf--$(subst /,-,$(doc))) + $(eval DOCS = $(shell cd $(SAGE_ROOT) && ./sage --docbuild --all-documents all)) + @if [ -z "$(DOCS)" ]; then echo "Error: './sage --docbuild --all-documents' failed"; exit 1; fi + $(MAKE) SAGE_DOCBUILD_OPTS="$(SAGE_DOCBUILD_OPTS) --no-prune-empty-dirs" $(foreach doc, $(wordlist 2, 100, $(DOCS)), doc-pdf--$(subst /,-,$(doc))) doc-pdf: doc-pdf-reference doc-pdf-other From d64fb763d3f58e05954d576464a5c66cc1f5307f Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 9 Nov 2021 13:43:10 -0800 Subject: [PATCH 086/126] build/make/Makefile.in: Undo reintroduction of SAGE_SKIP_PLOT_DIRECTIVE, SAGE_DOC_MATHJAX settings --- build/make/Makefile.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/make/Makefile.in b/build/make/Makefile.in index 4b9abbbcdb5..e6c9f3050cd 100644 --- a/build/make/Makefile.in +++ b/build/make/Makefile.in @@ -336,12 +336,12 @@ doc-html: sagemath_doc_html # megabytes of disk space. 'doc-clean' is a prerequisite because the # presence of graphics is cached in src/doc/output. doc-html-no-plot: doc-clean - +$(MAKE_REC) SAGE_SKIP_PLOT_DIRECTIVE=yes doc-html + +$(MAKE_REC) SAGE_DOCBUILD_OPTS="$(SAGE_DOCBUILD_OPTS) --no-plot" doc-html # Using mathjax is actually the default, but this target can be used # to override an environment setting of SAGE_DOC_MATHJAX=no doc-html-mathjax: - +$(MAKE_REC) SAGE_DOC_MATHJAX=yes doc-html + +$(MAKE_REC) SAGE_DOCBUILD_OPTS="$(SAGE_DOCBUILD_OPTS) -j" SAGE_DOC_MATHJAX=yes doc-html # Keep target 'doc-html-jsmath' for backwards compatibility. doc-html-jsmath: doc-html-mathjax From 6afc0d5535530f9f71538821ec07a7cb95d44d19 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 9 Nov 2021 13:47:36 -0800 Subject: [PATCH 087/126] build/pkgs/sagemath_doc_html/spkg-install: Move handling of SAGE_DOC_JSMATH environment variable here from src/bin/sage-env --- build/pkgs/sagemath_doc_html/spkg-install | 14 ++++++++++++++ src/bin/sage-env | 13 ------------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/build/pkgs/sagemath_doc_html/spkg-install b/build/pkgs/sagemath_doc_html/spkg-install index 801aa7769fe..71e805869c0 100755 --- a/build/pkgs/sagemath_doc_html/spkg-install +++ b/build/pkgs/sagemath_doc_html/spkg-install @@ -1,3 +1,17 @@ #! /usr/bin/env bash + +# When building documentation, use MathJax by default. To turn it off, +# set SAGE_DOC_MATHJAX to be "no" or "False". +if [ -z "$SAGE_DOC_MATHJAX" ]; then + # For backwards compatibility, we use the value of SAGE_DOC_JSMATH + # if it is set. + if [ -n "$SAGE_DOC_JSMATH" ]; then + SAGE_DOC_MATHJAX="$SAGE_DOC_JSMATH" + else + SAGE_DOC_MATHJAX="True" + fi + export SAGE_DOC_MATHJAX +fi + cd $SAGE_ROOT/src/doc $MAKE doc-html diff --git a/src/bin/sage-env b/src/bin/sage-env index b4c0c6ea207..1f832183fb4 100644 --- a/src/bin/sage-env +++ b/src/bin/sage-env @@ -633,19 +633,6 @@ export MAKE export PIP_FORMAT="columns" -# When building documentation, use MathJax by default. To turn it off, -# set SAGE_DOC_MATHJAX to be "no" or "False". -if [ -z "$SAGE_DOC_MATHJAX" ]; then - # For backwards compatibility, we use the value of SAGE_DOC_JSMATH - # if it is set. - if [ -n "$SAGE_DOC_JSMATH" ]; then - SAGE_DOC_MATHJAX="$SAGE_DOC_JSMATH" - else - SAGE_DOC_MATHJAX="True" - fi - export SAGE_DOC_MATHJAX -fi - # Set the cysignals crash logs directory if [ -z "$CYSIGNALS_CRASH_LOGS" ]; then export CYSIGNALS_CRASH_LOGS="$DOT_SAGE/crash_logs" From b2cf40c2a9b023c2449dbf4186aeb369f604390a Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 9 Nov 2021 13:55:02 -0800 Subject: [PATCH 088/126] build/make/Makefile.in: Undo reintroduction of SAGE_SKIP_PLOT_DIRECTIVE, SAGE_DOC_MATHJAX settings (fixup) --- build/make/Makefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/make/Makefile.in b/build/make/Makefile.in index e6c9f3050cd..4673be50224 100644 --- a/build/make/Makefile.in +++ b/build/make/Makefile.in @@ -341,7 +341,7 @@ doc-html-no-plot: doc-clean # Using mathjax is actually the default, but this target can be used # to override an environment setting of SAGE_DOC_MATHJAX=no doc-html-mathjax: - +$(MAKE_REC) SAGE_DOCBUILD_OPTS="$(SAGE_DOCBUILD_OPTS) -j" SAGE_DOC_MATHJAX=yes doc-html + +$(MAKE_REC) SAGE_DOCBUILD_OPTS="$(SAGE_DOCBUILD_OPTS) -j" doc-html # Keep target 'doc-html-jsmath' for backwards compatibility. doc-html-jsmath: doc-html-mathjax From 16816c8fb3ab4836474c7324800652673e094430 Mon Sep 17 00:00:00 2001 From: dcoudert Date: Wed, 10 Nov 2021 00:39:45 +0100 Subject: [PATCH 089/126] trac #30566: check that the output is a tree --- src/sage/graphs/spanning_tree.pyx | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/sage/graphs/spanning_tree.pyx b/src/sage/graphs/spanning_tree.pyx index 9cad7642635..7e13bdf1a6f 100644 --- a/src/sage/graphs/spanning_tree.pyx +++ b/src/sage/graphs/spanning_tree.pyx @@ -885,6 +885,15 @@ def random_spanning_tree(G, output_as_graph=False, by_weight=False, weight_funct sage: print(len(foo(K4, 100))) # random 16 + Check that the spanning tree returned when using weights is a tree:: + + sage: G = graphs.RandomBarabasiAlbert(50, 2) + sage: for u, v in G.edge_iterator(labels=False): + ....: G.set_edge_label(u, v, randint(1, 10)) + sage: T = G.random_spanning_tree(by_weight=True, output_as_graph=True) + sage: T.is_tree() + True + TESTS:: sage: G = Graph() From 37a03bd94e1716af2926c30eddbaf6d38303f869 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 9 Nov 2021 16:09:36 -0800 Subject: [PATCH 090/126] src/doc/en/developer/packaging.rst: Fix up section label --- src/doc/en/developer/packaging.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/en/developer/packaging.rst b/src/doc/en/developer/packaging.rst index 9bdab77e80d..33df039bbec 100644 --- a/src/doc/en/developer/packaging.rst +++ b/src/doc/en/developer/packaging.rst @@ -718,7 +718,7 @@ packages and optional packages should only depend on standard or optional packages. -.. _section-dependencies: +.. _section-trees: Where packages are installed ---------------------------- From fc89a6657450c0e10c8322615f1fced0f8ebb984 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 9 Nov 2021 16:21:15 -0800 Subject: [PATCH 091/126] build/pkgs/sagemath_doc_pdf/spkg-install: Set SAGE_DOC_MATHJAX as a workaround --- build/pkgs/sagemath_doc_pdf/spkg-install | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/build/pkgs/sagemath_doc_pdf/spkg-install b/build/pkgs/sagemath_doc_pdf/spkg-install index f04f4b75d9a..947fc17511f 100755 --- a/build/pkgs/sagemath_doc_pdf/spkg-install +++ b/build/pkgs/sagemath_doc_pdf/spkg-install @@ -1,3 +1,7 @@ #! /usr/bin/env bash +# This must be set; otherwise, sage.docs.conf uses sphinx.ext.imgmath, +# which leads to errors. +export SAGE_DOC_MATHJAX=yes + cd $SAGE_ROOT/src/doc $MAKE doc-pdf From f5bdb919debe1f54a313e16940ae36ddc023b052 Mon Sep 17 00:00:00 2001 From: Lorenz Panny Date: Wed, 10 Nov 2021 10:24:52 +0800 Subject: [PATCH 092/126] use PARI's fflog for binary finite fields --- .../rings/finite_rings/element_ntl_gf2e.pyx | 61 +++++++++++++------ 1 file changed, 43 insertions(+), 18 deletions(-) diff --git a/src/sage/rings/finite_rings/element_ntl_gf2e.pyx b/src/sage/rings/finite_rings/element_ntl_gf2e.pyx index 685f9a272bd..b437a4e20c9 100644 --- a/src/sage/rings/finite_rings/element_ntl_gf2e.pyx +++ b/src/sage/rings/finite_rings/element_ntl_gf2e.pyx @@ -1253,30 +1253,21 @@ cdef class FiniteField_ntl_gf2eElement(FinitePolyExtElement): def log(self, base): """ - Return `x` such that `b^x = a`, where `x` is `a` and `b` - is the base. + Compute an integer `x` such that `b^x = a`, where `a` is ``self`` + and `b` is ``base``. INPUT: - - ``base`` -- finite field element that generates the multiplicative - group. + - ``base`` -- finite-field element. OUTPUT: Integer `x` such that `a^x = b`, if it exists. Raises a ``ValueError`` exception if no such `x` exists. - EXAMPLES:: + ALGORITHM: :pari:`fflog` - sage: F = GF(17) - sage: F(3^11).log(F(3)) - 11 - sage: F = GF(113) - sage: F(3^19).log(F(3)) - 19 - sage: F = GF(next_prime(10000)) - sage: F(23^997).log(F(23)) - 997 + EXAMPLES:: sage: F = FiniteField(2^10, 'a') sage: g = F.gen() @@ -1287,12 +1278,46 @@ cdef class FiniteField_ntl_gf2eElement(FinitePolyExtElement): a^8 + a^7 + a^4 + a + 1 a^8 + a^7 + a^4 + a + 1 - AUTHOR: David Joyner and William Stein (2005-11) + Big instances used to take very long before :trac:`32842`:: + + sage: g = GF(2^61).gen() + sage: g.log(g^7) + 1976436865040309101 + + TESTS: + + Check that non-existence is correctly detected:: + + sage: g = GF(2^50).gen() + sage: (2^50-1) % 1023 + 0 + sage: g.log(g^1023) + Traceback (most recent call last): + ... + ValueError: no logarithm of z50 exists to base z50^49 + z50^46 + z50^45 + z50^44 + z50^41 + z50^34 + z50^33 + z50^32 + z50^27 + z50^25 + z50^24 + z50^21 + z50^18 + z50^17 + z50^16 + z50^15 + z50^12 + z50^11 + z50^10 + z50^8 + z50^7 + z50^3 + z50^2 + + AUTHORS: + + - David Joyner and William Stein (2005-11) + - Lorenz Panny (2021-11): use PARI's :pari:`fflog` instead of :func:`sage.groups.generic.discrete_log` """ - from sage.groups.generic import discrete_log + base = self.parent()(base) + + # The result is undefined if the input to fflog() is invalid. + # Since the unit group is cyclic, it suffices to check orders. + cdef Integer base_order = base.multiplicative_order() + cdef Integer self_order = self.multiplicative_order() + if not self_order.divides(base_order): + raise ValueError(f'no logarithm of {self} exists to base {base}') + + # Let's pass the known factorization of the order to PARI. + fs, = self._parent.factored_unit_order() # cached + ps = pari.Col(p for p,_ in fs) + vs = pari.Col(base_order.valuation(p) for p,_ in fs) + fac = pari.matconcat((ps, vs)) - b = self.parent()(base) - return discrete_log(self, b) + x = pari.fflog(self, base, (base_order, fac)) + return Integer(x) def unpickleFiniteField_ntl_gf2eElement(parent, elem): """ From fd298c4b7a6f845335b862f6dc2f8e18753937e7 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 9 Nov 2021 21:44:24 -0800 Subject: [PATCH 093/126] build/pkgs/sagemath_doc_pdf/dependencies: Depend on sagemath_doc_html --- build/pkgs/sagemath_doc_pdf/dependencies | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) mode change 120000 => 100644 build/pkgs/sagemath_doc_pdf/dependencies diff --git a/build/pkgs/sagemath_doc_pdf/dependencies b/build/pkgs/sagemath_doc_pdf/dependencies deleted file mode 120000 index 5bad6e468d6..00000000000 --- a/build/pkgs/sagemath_doc_pdf/dependencies +++ /dev/null @@ -1 +0,0 @@ -../sagemath_doc_html/dependencies \ No newline at end of file diff --git a/build/pkgs/sagemath_doc_pdf/dependencies b/build/pkgs/sagemath_doc_pdf/dependencies new file mode 100644 index 00000000000..4bdc1055372 --- /dev/null +++ b/build/pkgs/sagemath_doc_pdf/dependencies @@ -0,0 +1 @@ +sagemath_doc_html From d457de75f32d2d41d30ee2f618e6e7dbd47fed41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Wed, 10 Nov 2021 09:55:40 +0100 Subject: [PATCH 094/126] various code details in combinat --- src/sage/combinat/baxter_permutations.py | 9 +++++---- src/sage/combinat/k_tableau.py | 13 +++++++------ src/sage/combinat/permutation.py | 6 +----- src/sage/combinat/shifted_primed_tableau.py | 4 ++-- 4 files changed, 15 insertions(+), 17 deletions(-) diff --git a/src/sage/combinat/baxter_permutations.py b/src/sage/combinat/baxter_permutations.py index 59d9a0256fb..0e3c722f480 100644 --- a/src/sage/combinat/baxter_permutations.py +++ b/src/sage/combinat/baxter_permutations.py @@ -81,7 +81,7 @@ def __init__(self, n): self.element_class = Permutations(n).element_class self._n = ZZ(n) from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets - super(BaxterPermutations, self).__init__(category=FiniteEnumeratedSets()) + super(BaxterPermutations_size, self).__init__(category=FiniteEnumeratedSets()) def _repr_(self): """ @@ -128,7 +128,7 @@ def __contains__(self, x): if x_j > a and x_j < b and x_j > max_l: max_l = x_j min_r = len(x) + 1 - for x_j in x[i+2:]: + for x_j in x[i + 2:]: if x_j > a and x_j < b and x_j < min_r: min_r = x_j if max_l > min_r: @@ -139,7 +139,7 @@ def __contains__(self, x): if x_j < a and x_j > b and x_j < min_l: min_l = x_j max_r = 0 - for x_j in x[i+2:]: + for x_j in x[i + 2:]: if x_j < a and x_j > b and x_j > max_r: max_r = x_j if min_l < max_r: @@ -186,7 +186,8 @@ def __iter__(self): else: for b in BaxterPermutations(self._n - 1): # Left to right maxima. - for i in [self._n - 2 - i for i in b.reverse().saliances()]: + for j in b.reverse().saliances(): + i = self._n - 2 - j yield Permutations(self._n)(b[:i] + [self._n] + b[i:]) # Right to left maxima. for i in b.saliances(): diff --git a/src/sage/combinat/k_tableau.py b/src/sage/combinat/k_tableau.py index 17fccecd104..9d5a40e532d 100644 --- a/src/sage/combinat/k_tableau.py +++ b/src/sage/combinat/k_tableau.py @@ -2369,14 +2369,15 @@ def __classcall_private__(cls, T, k, weight=None): """ if isinstance(T, cls): return T - outer_shape = Core([len(t) for t in T], k+1) - inner_shape = Core([x for x in [row.count(None) for row in T] if x], k+1) - Te = [v for row in T for v in row if v is not None]+[0] + outer_shape = Core([len(t) for t in T], k + 1) + loop = (row.count(None) for row in T) + inner_shape = Core([x for x in loop if x], k + 1) + Te = [v for row in T for v in row if v is not None] + [0] count_marks = tuple(Te.count(-(i+1)) for i in range(-min(Te))) - if not all( v==1 for v in count_marks ): + if not all(v == 1 for v in count_marks): # if T is not standard -> turn into standard - if weight is not None and tuple(weight)!=count_marks: - raise ValueError("Weight = %s and tableau = %s do not agree"%(weight, T)) + if weight is not None and tuple(weight) != count_marks: + raise ValueError("Weight = %s and tableau = %s do not agree" % (weight, T)) tijseq = StrongTableaux.marked_CST_to_transposition_sequence(T, k) if tijseq is None or len(tijseq) Date: Wed, 10 Nov 2021 18:07:15 +0800 Subject: [PATCH 095/126] slightly rephrase docstring --- src/sage/rings/finite_rings/element_ntl_gf2e.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/rings/finite_rings/element_ntl_gf2e.pyx b/src/sage/rings/finite_rings/element_ntl_gf2e.pyx index b437a4e20c9..7092888fddd 100644 --- a/src/sage/rings/finite_rings/element_ntl_gf2e.pyx +++ b/src/sage/rings/finite_rings/element_ntl_gf2e.pyx @@ -1278,7 +1278,7 @@ cdef class FiniteField_ntl_gf2eElement(FinitePolyExtElement): a^8 + a^7 + a^4 + a + 1 a^8 + a^7 + a^4 + a + 1 - Big instances used to take very long before :trac:`32842`:: + Big instances used to take a very long time before :trac:`32842`:: sage: g = GF(2^61).gen() sage: g.log(g^7) From 265e0dd9af89c09b5dc35b674e70395d9f9c6211 Mon Sep 17 00:00:00 2001 From: Jonathan Kliem Date: Wed, 10 Nov 2021 15:04:14 +0100 Subject: [PATCH 096/126] fix precision in books doctest --- .../sol/linsolve_doctest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/tests/books/computational-mathematics-with-sagemath/sol/linsolve_doctest.py b/src/sage/tests/books/computational-mathematics-with-sagemath/sol/linsolve_doctest.py index 14208cd98ba..008dce524ae 100644 --- a/src/sage/tests/books/computational-mathematics-with-sagemath/sol/linsolve_doctest.py +++ b/src/sage/tests/books/computational-mathematics-with-sagemath/sol/linsolve_doctest.py @@ -19,7 +19,7 @@ Sage example in ./sol/linsolve.tex, line 84:: sage: M = (X*X-a) - sage: all(abs(M[i,j]) < 10^-14 + sage: all(abs(M[i,j]) < 10^-13 # original claim is 10^-14, which sometimes fails ....: for i in range(4) for j in range(4) ) True From 452b012926240a59607bc38869b70c0bd62210d0 Mon Sep 17 00:00:00 2001 From: Jonathan Kliem Date: Wed, 10 Nov 2021 16:40:35 +0100 Subject: [PATCH 097/126] remove comment as source code of the book has been updated --- .../sol/linsolve_doctest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/tests/books/computational-mathematics-with-sagemath/sol/linsolve_doctest.py b/src/sage/tests/books/computational-mathematics-with-sagemath/sol/linsolve_doctest.py index 008dce524ae..839ad0d7ec7 100644 --- a/src/sage/tests/books/computational-mathematics-with-sagemath/sol/linsolve_doctest.py +++ b/src/sage/tests/books/computational-mathematics-with-sagemath/sol/linsolve_doctest.py @@ -19,7 +19,7 @@ Sage example in ./sol/linsolve.tex, line 84:: sage: M = (X*X-a) - sage: all(abs(M[i,j]) < 10^-13 # original claim is 10^-14, which sometimes fails + sage: all(abs(M[i,j]) < 10^-13 ....: for i in range(4) for j in range(4) ) True From bbe3f338b1cb841137de0f8ed244cdfde60cd018 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 10 Nov 2021 10:35:28 -0800 Subject: [PATCH 098/126] build/pkgs/traitlets: Update to 5.1.1 --- build/pkgs/traitlets/checksums.ini | 6 +++--- build/pkgs/traitlets/package-version.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/pkgs/traitlets/checksums.ini b/build/pkgs/traitlets/checksums.ini index 415ba07704b..dd2af5d21ac 100644 --- a/build/pkgs/traitlets/checksums.ini +++ b/build/pkgs/traitlets/checksums.ini @@ -1,5 +1,5 @@ tarball=traitlets-VERSION.tar.gz -sha1=08d9b2db5b0cf7794e9c4ca76f7981cccc3233b6 -md5=19483ec0685e837912cff128209aa845 -cksum=3463913536 +sha1=86d03557843700d6dd0657371d15f0520c2f392f +md5=31f7fd84518fe08cb40ab18f6dde0d54 +cksum=1147319509 upstream_url=https://pypi.io/packages/source/t/traitlets/traitlets-VERSION.tar.gz diff --git a/build/pkgs/traitlets/package-version.txt b/build/pkgs/traitlets/package-version.txt index 831446cbd27..ac14c3dfaa8 100644 --- a/build/pkgs/traitlets/package-version.txt +++ b/build/pkgs/traitlets/package-version.txt @@ -1 +1 @@ -5.1.0 +5.1.1 From d6a179f69c1cceaf1af2ecd6ea5fa4463d1edcbd Mon Sep 17 00:00:00 2001 From: Lorenz Panny Date: Fri, 12 Nov 2021 14:03:55 +0800 Subject: [PATCH 099/126] fix doctest formatting --- src/sage/rings/finite_rings/integer_mod_ring.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/rings/finite_rings/integer_mod_ring.py b/src/sage/rings/finite_rings/integer_mod_ring.py index 28fb2736491..00f64ed4bd3 100644 --- a/src/sage/rings/finite_rings/integer_mod_ring.py +++ b/src/sage/rings/finite_rings/integer_mod_ring.py @@ -1366,7 +1366,7 @@ def unit_gens(self, **kwds): The choice of generators is affected by the optional keyword ``algorithm``; this can be ``'sage'`` (default) or ``'pari'``. - See :meth:`unit_group` for details. + See :meth:`unit_group` for details. :: sage: A = Zmod(55) sage: A.unit_gens(algorithm='sage') From e25bbfde58aec0f64a3b955b08eb29065ae1020f Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 18 Oct 2021 16:02:03 -0700 Subject: [PATCH 100/126] src/requirements.txt.m4: Add memory_allocator --- src/requirements.txt.m4 | 1 + 1 file changed, 1 insertion(+) diff --git a/src/requirements.txt.m4 b/src/requirements.txt.m4 index 57dca4227a6..9a2e448c603 100644 --- a/src/requirements.txt.m4 +++ b/src/requirements.txt.m4 @@ -23,6 +23,7 @@ gmpy2==esyscmd(`printf $(sed "s/[.]p.*//;" ../gmpy2/package-version.txt)') jinja2==esyscmd(`printf $(sed "s/[.]p.*//;" ../jinja2/package-version.txt)') dnl ... for sage_setup.autogen.interpreters jupyter_core==esyscmd(`printf $(sed "s/[.]p.*//;" ../jupyter_core/package-version.txt)') +memory_allocator==esyscmd(`printf $(sed "s/[.]p.*//;" ../memory_allocator/package-version.txt)') numpy==esyscmd(`printf $(sed "s/[.]p.*//;" ../numpy/package-version.txt)') dnl ... already needed by sage.env pkgconfig==esyscmd(`printf $(sed "s/[.]p.*//;" ../pkgconfig/package-version.txt)') From 4d021ab87a4a44b2928a25d4d33721018985f62f Mon Sep 17 00:00:00 2001 From: Kwankyu Lee Date: Fri, 12 Nov 2021 23:31:21 +0900 Subject: [PATCH 101/126] Convert < to < and back --- src/sage/misc/html.py | 19 +++++++++---------- src/sage/repl/rich_output/output_browser.py | 6 ++++-- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/sage/misc/html.py b/src/sage/misc/html.py index 7dacc5f2748..237177337fe 100644 --- a/src/sage/misc/html.py +++ b/src/sage/misc/html.py @@ -294,12 +294,13 @@ def eval(self, x, globals=None, locals=None, mode='display', combine_all=False): sage: MathJax().eval(3, mode='inline') \(\newcommand{\Bold}[1]{\mathbf{#1}}3\) sage: MathJax().eval(type(3), mode='inline') - \(\newcommand{\Bold}[1]{\mathbf{#1}}\verb||\) + \(\newcommand{\Bold}[1]{\mathbf{#1}}\verb||\) """ # Get a regular LaTeX representation of x x = latex(x, combine_all=combine_all) - # The following block, hopefully, can be removed in some future MathJax. + # The "\text{\texttt{...}}" blocks are reformed to be renderable by MathJax. + # These blocks are produced by str_function() defined in sage.misc.latex. prefix = r"\text{\texttt{" parts = x.split(prefix) for i, part in enumerate(parts): @@ -324,7 +325,6 @@ def eval(self, x, globals=None, locals=None, mode='display', combine_all=False): delimiter = "|" y = "(complicated string)" wrapper = r"\verb" + delimiter + "%s" + delimiter - spacer = r"\phantom{\verb!%s!}" y = y.replace("{ }", " ").replace("{-}", "-") for c in r"#$%&\^_{}~": char_wrapper = r"{\char`\%s}" % c @@ -336,14 +336,12 @@ def eval(self, x, globals=None, locals=None, mode='display', combine_all=False): nspaces += 1 continue if nspaces > 0: - subparts.append(spacer % ("x" * nspaces)) + subparts.append(wrapper % (" " * nspaces)) nspaces = 1 subparts.append(wrapper % subpart) - # There is a bug with omitting empty lines in arrays - if not y: - subparts.append(spacer % "x") subparts.append(part[closing + 1:]) parts[i] = "".join(subparts) + from sage.misc.latex_macros import sage_configurable_latex_macros from sage.misc.latex import _Latex_prefs latex_string = ''.join( @@ -351,15 +349,16 @@ def eval(self, x, globals=None, locals=None, mode='display', combine_all=False): [_Latex_prefs._option['macros']] + parts ) + mathjax_string = latex_string.replace('<', '<') if mode == 'display': html = r'\[{0}\]' elif mode == 'inline': html = r'\({0}\)' elif mode == 'plain': - return latex_string + return mathjax_string else: raise ValueError("mode must be either 'display', 'inline', or 'plain'") - return MathJaxExpr(html.format(latex_string)) + return MathJaxExpr(html.format(mathjax_string)) class HTMLFragmentFactory(SageObject): @@ -412,7 +411,7 @@ def __call__(self, obj, concatenate=True, strict=False): sagemath sage: html('sagemath', strict=True) - \[\newcommand{\Bold}[1]{\mathbf{#1}}\verb|sagemath|\] + \[\newcommand{\Bold}[1]{\mathbf{#1}}\verb|sagemath|\] """ # string obj is interpreted as an HTML in not strict mode if isinstance(obj, str) and not strict: diff --git a/src/sage/repl/rich_output/output_browser.py b/src/sage/repl/rich_output/output_browser.py index 2746e3dff8e..3d7cda599a1 100644 --- a/src/sage/repl/rich_output/output_browser.py +++ b/src/sage/repl/rich_output/output_browser.py @@ -40,10 +40,12 @@ def __init__(self, html): # pdf export of a notebook m = latex_re.match(html) if m: + mathjax_string = m.group('latex') + latex_string = mathjax_string.replace('<', '<') if m.group('mathstart') == r'\[' and m.group('mathend') == r'\]': - self.latex = OutputBuffer('$$' + m.group('latex') + '$$') + self.latex = OutputBuffer('$$' + latex_string + '$$') else: - self.latex = OutputBuffer('$' + m.group('latex') + '$') + self.latex = OutputBuffer('$' + latex_string + '$') else: self.latex = None From ba099ec02228f44a7923a81f27aaad760e948fff Mon Sep 17 00:00:00 2001 From: Kwankyu Lee Date: Fri, 12 Nov 2021 23:53:45 +0900 Subject: [PATCH 102/126] Fix doctests --- src/sage/misc/html.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/misc/html.py b/src/sage/misc/html.py index 237177337fe..cc310888512 100644 --- a/src/sage/misc/html.py +++ b/src/sage/misc/html.py @@ -294,7 +294,7 @@ def eval(self, x, globals=None, locals=None, mode='display', combine_all=False): sage: MathJax().eval(3, mode='inline') \(\newcommand{\Bold}[1]{\mathbf{#1}}3\) sage: MathJax().eval(type(3), mode='inline') - \(\newcommand{\Bold}[1]{\mathbf{#1}}\verb||\) + \(\newcommand{\Bold}[1]{\mathbf{#1}}\verb|<class|\verb| |\verb|'sage.rings.integer.Integer'>|\) """ # Get a regular LaTeX representation of x x = latex(x, combine_all=combine_all) @@ -411,7 +411,7 @@ def __call__(self, obj, concatenate=True, strict=False): sagemath sage: html('sagemath', strict=True) - \[\newcommand{\Bold}[1]{\mathbf{#1}}\verb|sagemath|\] + \[\newcommand{\Bold}[1]{\mathbf{#1}}\verb|<a|\verb| |\verb|href="http://sagemath.org">sagemath</a>|\] """ # string obj is interpreted as an HTML in not strict mode if isinstance(obj, str) and not strict: From f061fbc8d37321ab931e1bdb74bf8ffc8fb216db Mon Sep 17 00:00:00 2001 From: Isuru Fernando Date: Fri, 12 Nov 2021 09:07:08 -0800 Subject: [PATCH 103/126] add memory_allocator/distros/conda.txt --- build/pkgs/memory_allocator/distros/conda.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 build/pkgs/memory_allocator/distros/conda.txt diff --git a/build/pkgs/memory_allocator/distros/conda.txt b/build/pkgs/memory_allocator/distros/conda.txt new file mode 100644 index 00000000000..8dda733d5a5 --- /dev/null +++ b/build/pkgs/memory_allocator/distros/conda.txt @@ -0,0 +1 @@ +memory-allocator From f546c3c34a3909bfbcdbd28e209847f91e6550fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sat, 13 Nov 2021 09:52:15 +0100 Subject: [PATCH 104/126] fix E713 and E714 in coding/ --- src/sage/coding/grs_code.py | 7 ++++--- src/sage/coding/linear_code.py | 6 +++--- src/sage/coding/linear_code_no_metric.py | 12 +++++------ src/sage/coding/linear_rank_metric.py | 6 +++--- .../coding/relative_finite_field_extension.py | 21 +++++++++---------- src/sage/coding/subfield_subcode.py | 2 +- 6 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/sage/coding/grs_code.py b/src/sage/coding/grs_code.py index 74c59ffec89..1bdbc70727f 100644 --- a/src/sage/coding/grs_code.py +++ b/src/sage/coding/grs_code.py @@ -1965,13 +1965,14 @@ def decode_to_message(self, word_and_erasure_vector): n, k = C.length(), C.dimension() if word not in C.ambient_space(): raise ValueError("The word to decode has to be in the ambient space of the code") - if not erasure_vector in VectorSpace(GF(2), n): + if erasure_vector not in VectorSpace(GF(2), n): raise ValueError("The erasure vector has to be a vector over GF(2) of the same length as the code") if erasure_vector.hamming_weight() >= self.code().minimum_distance(): raise DecodingError("Too many erasures in the received word") - punctured_word = vector(self.code().base_ring(), [word[i] for i in - range(len(word)) if erasure_vector[i]!=1]) + punctured_word = vector(self.code().base_ring(), + [word[i] for i in range(len(word)) + if not erasure_vector[i]]) C1_length = len(punctured_word) if C1_length == k: return self.connected_encoder().unencode_nocheck(word) diff --git a/src/sage/coding/linear_code.py b/src/sage/coding/linear_code.py index 643e7239460..c335f04e1a9 100644 --- a/src/sage/coding/linear_code.py +++ b/src/sage/coding/linear_code.py @@ -2309,12 +2309,12 @@ def __init__(self, generator, d=None): try: basis = None - if hasattr(generator,"nrows"): # generator matrix case + if hasattr(generator, "nrows"): # generator matrix case if generator.rank() < generator.nrows(): basis = generator.row_space().basis() else: - basis = generator.basis() # vector space etc. case - if not basis is None: + basis = generator.basis() # vector space etc. case + if basis is not None: from sage.matrix.constructor import matrix generator = matrix(base_ring, basis) if generator.nrows() == 0: diff --git a/src/sage/coding/linear_code_no_metric.py b/src/sage/coding/linear_code_no_metric.py index 85fd48f3226..9e4b6115ad3 100644 --- a/src/sage/coding/linear_code_no_metric.py +++ b/src/sage/coding/linear_code_no_metric.py @@ -179,9 +179,9 @@ def __init__(self, base_field, length, default_encoder_name, default_decoder_nam if not base_field.is_field(): raise ValueError("'base_field' must be a field (and {} is not one)".format(base_field)) - if not default_encoder_name in self._registered_encoders: + if default_encoder_name not in self._registered_encoders: raise ValueError("You must set a valid encoder as default encoder for this code, by filling in the dictionary of registered encoders") - if not default_decoder_name in self._registered_decoders: + if default_decoder_name not in self._registered_decoders: raise ValueError("You must set a valid decoder as default decoder for this code, by filling in the dictionary of registered decoders") #if not self.dimension() <= length: @@ -509,7 +509,7 @@ def __contains__(self, v): sage: vector((1, 0, 0, 0, 0, 1/2, 1)) in C # indirect doctest False """ - if not v in self.ambient_space() or len(v) != self.length(): + if v not in self.ambient_space() or len(v) != self.length(): return False return self.syndrome(v) == 0 @@ -1296,13 +1296,13 @@ def systematic_permutation(self): n = self.code().length() systematic_positions = self.systematic_positions() k = len(systematic_positions) - lp = [ None ]*n - for (i,j) in zip(range(k), systematic_positions): + lp = [None] * n + for (i, j) in zip(range(k), systematic_positions): lp[i] = j j = k set_sys_pos = set(systematic_positions) for i in range(n): - if not i in set_sys_pos: + if i not in set_sys_pos: lp[j] = i j += 1 from sage.combinat.permutation import Permutation diff --git a/src/sage/coding/linear_rank_metric.py b/src/sage/coding/linear_rank_metric.py index f746acf3c91..c06b16aa05b 100644 --- a/src/sage/coding/linear_rank_metric.py +++ b/src/sage/coding/linear_rank_metric.py @@ -694,12 +694,12 @@ def __init__(self, generator, sub_field=None, basis=None): try: gen_basis = None - if hasattr(generator,"nrows"): # generator matrix case + if hasattr(generator, "nrows"): # generator matrix case if generator.rank() < generator.nrows(): gen_basis = generator.row_space().basis() else: - gen_basis = generator.basis() # vector space etc. case - if not gen_basis is None: + gen_basis = generator.basis() # vector space etc. case + if gen_basis is not None: from sage.matrix.constructor import matrix generator = matrix(base_field, gen_basis) if generator.nrows() == 0: diff --git a/src/sage/coding/relative_finite_field_extension.py b/src/sage/coding/relative_finite_field_extension.py index 2319d708f85..1a329624cce 100644 --- a/src/sage/coding/relative_finite_field_extension.py +++ b/src/sage/coding/relative_finite_field_extension.py @@ -120,7 +120,7 @@ def __init__(self, absolute_field, relative_field, embedding=None): if not s.divides(sm): raise ValueError("relative_field has to be a subfield of absolute_field") H = Hom(relative_field, absolute_field) - if embedding is not None and not embedding in H: + if embedding is not None and embedding not in H: raise ValueError("embedding has to be an embedding from relative_field to absolute_field") elif embedding is not None: self._phi = embedding @@ -231,7 +231,7 @@ def _flattened_relative_field_representation(self, b): sage: FE._flattened_relative_field_representation(b) (1, 0, 1, 1) """ - if not b in self.absolute_field(): + if b not in self.absolute_field(): raise ValueError("The input has to be an element of the absolute field") return self._representation_matrix() * vector(b) @@ -254,19 +254,18 @@ def relative_field_representation(self, b): sage: FE.relative_field_representation(b) (1, a + 1) """ - if not b in self.absolute_field(): + if b not in self.absolute_field(): raise ValueError("The input has to be an element of the absolute field") s = self.relative_field_degree() if s == 1: return vector(b) - else: - Fq = self.relative_field() - vect = self._flattened_relative_field_representation(b) - sm = self.absolute_field_degree() - list_elts = [] - for i in range(0, sm, s): - list_elts.append(Fq(vect[i:i+s])) - return vector(Fq, list_elts) + Fq = self.relative_field() + vect = self._flattened_relative_field_representation(b) + sm = self.absolute_field_degree() + list_elts = [] + for i in range(0, sm, s): + list_elts.append(Fq(vect[i:i + s])) + return vector(Fq, list_elts) def absolute_field_representation(self, a): r""" diff --git a/src/sage/coding/subfield_subcode.py b/src/sage/coding/subfield_subcode.py index c08d27a4cb3..ed7b18d7a90 100644 --- a/src/sage/coding/subfield_subcode.py +++ b/src/sage/coding/subfield_subcode.py @@ -86,7 +86,7 @@ def __init__(self, original_code, subfield, embedding=None): raise ValueError("subfield has to be a subfield of the base field of the original code") self._original_code = original_code H = Hom(subfield, F) - if embedding is not None and not embedding in H: + if embedding is not None and embedding not in H: raise ValueError("embedding has to be an embedding from subfield to original_code's base field") elif embedding is not None: self._embedding = RelativeFiniteFieldExtension(F, subfield, embedding) From 2a03332229b3dba97f88383ae7b2cdc516f87e81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sat, 13 Nov 2021 11:22:21 +0100 Subject: [PATCH 105/126] fix E713 and E714 in graphs --- src/sage/graphs/bipartite_graph.py | 4 +-- src/sage/graphs/digraph_generators.py | 4 +-- src/sage/graphs/generators/chessboard.py | 6 ++-- src/sage/graphs/generators/smallgraphs.py | 2 +- src/sage/graphs/generic_graph.py | 42 +++++++++++------------ src/sage/graphs/graph.py | 7 ++-- src/sage/graphs/graph_database.py | 2 +- src/sage/graphs/isgci.py | 2 +- src/sage/graphs/pq_trees.py | 2 +- 9 files changed, 35 insertions(+), 36 deletions(-) diff --git a/src/sage/graphs/bipartite_graph.py b/src/sage/graphs/bipartite_graph.py index e95565a9e1b..b782aa989ed 100644 --- a/src/sage/graphs/bipartite_graph.py +++ b/src/sage/graphs/bipartite_graph.py @@ -1757,7 +1757,7 @@ def vertex_cover(self, algorithm="Konig", value_only=False, Y = set() for u in X: for v in self.neighbors(u): - if not v in Z and not M.has_edge(u, v): + if v not in Z and not M.has_edge(u, v): Y.add(v) Z.update(Y) @@ -1765,7 +1765,7 @@ def vertex_cover(self, algorithm="Konig", value_only=False, X = set() for u in Y: for v in M.neighbor_iterator(u): - if not v in Z: + if v not in Z: X.add(v) Z.update(X) diff --git a/src/sage/graphs/digraph_generators.py b/src/sage/graphs/digraph_generators.py index 921aa754bb5..45bf0bb7f5b 100644 --- a/src/sage/graphs/digraph_generators.py +++ b/src/sage/graphs/digraph_generators.py @@ -763,7 +763,7 @@ def Circulant(self, n, integers): # Bad input and loops loops = False for i in integers: - if not i in ZZ: + if i not in ZZ: raise ValueError("the list must contain only integers") if not i % n: loops = True @@ -1456,7 +1456,7 @@ def RandomDirectedGNM(self, n, m, loops=False): u = int(rand.random() * n) v = int(rand.random() * n) - if (u != v or loops) and (not v in adj[u]): + if (u != v or loops) and (v not in adj[u]): adj[u][v] = 1 m -= 1 if not is_dense: diff --git a/src/sage/graphs/generators/chessboard.py b/src/sage/graphs/generators/chessboard.py index 9a10f7e8ada..50f82d47dd1 100644 --- a/src/sage/graphs/generators/chessboard.py +++ b/src/sage/graphs/generators/chessboard.py @@ -154,14 +154,14 @@ def ChessboardGraphGenerator(dim_list, rook=True, rook_radius=None, if rook: if rook_radius is None: rook_radius = max(dim) - elif not rook_radius in ZZ or rook_radius < 1: + elif rook_radius not in ZZ or rook_radius < 1: raise ValueError('the rook_radius must be either None or have an integer value >= 1') if bishop: if bishop_radius is None: bishop_radius = max(dim) - elif not bishop_radius in ZZ or bishop_radius < 1: + elif bishop_radius not in ZZ or bishop_radius < 1: raise ValueError('the bishop_radius must be either None or have an integer value >= 1') - if knight and ( not knight_x in ZZ or not knight_y in ZZ or knight_x < 1 or knight_y < 1 ): + if knight and (knight_x not in ZZ or knight_y not in ZZ or knight_x < 1 or knight_y < 1): raise ValueError('the knight_x and knight_y values must be integers of value >= 1') # We build the set of vertices of the d-dimensional chessboard diff --git a/src/sage/graphs/generators/smallgraphs.py b/src/sage/graphs/generators/smallgraphs.py index 072812c75c4..5a87ae14cf5 100644 --- a/src/sage/graphs/generators/smallgraphs.py +++ b/src/sage/graphs/generators/smallgraphs.py @@ -3571,7 +3571,7 @@ def McLaughlinGraph(): g = Graph() for b in B: for x in range(1, 23): - if not x in b: + if x not in b: g.add_edge(b, x) for b in C: diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index 0df574c5721..93264c6a4fd 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -1777,13 +1777,13 @@ def to_dictionary(self, edge_labels=False, multiple_edges=False): if self.is_directed(): for u, v, l in self.edge_iterator(): - if not v in d[u]: + if v not in d[u]: d[u][v] = [] d[u][v].append(l) else: for u, v, l in self.edge_iterator(): - if not v in d[u]: + if v not in d[u]: d[u][v] = [] d[v][u] = [] @@ -3105,7 +3105,7 @@ def allow_multiple_edges(self, new, check=True, keep_label='any'): sage: D.edges() [(0, 1, None)] """ - if not keep_label in ['any', 'min', 'max']: + if keep_label not in ['any', 'min', 'max']: raise ValueError("variable keep_label must be 'any', 'min', or 'max'") # TODO: this should be much faster for c_graphs, but for now we just do this @@ -4686,7 +4686,7 @@ def cycle_basis(self, output='vertex'): [(4, 3, 'e'), (3, 2, 'b'), (2, 1, 'a'), (1, 4, 'f')]] """ - if not output in ['vertex', 'edge']: + if output not in ['vertex', 'edge']: raise ValueError('output must be either vertex or edge') if self.is_directed(): @@ -7673,7 +7673,7 @@ def hamiltonian_path(self, s=None, t=None, use_edge_labels=False, if use_edge_labels or algorithm is None: # We force the algorithm to 'MILP' algorithm = 'MILP' - elif not algorithm in ['MILP', 'backtrack']: + elif algorithm not in ['MILP', 'backtrack']: raise ValueError("algorithm must be either 'backtrack' or 'MILP'") if self.order() < 2: @@ -7704,7 +7704,7 @@ def hamiltonian_path(self, s=None, t=None, use_edge_labels=False, elif len(zeros) == 1: if new_s is None: new_s = zeros.pop() - elif not new_s in zeros: + elif new_s not in zeros: return (0, None) if use_edge_labels else None zeros = [u for u in g if not g.out_degree(u)] @@ -7713,7 +7713,7 @@ def hamiltonian_path(self, s=None, t=None, use_edge_labels=False, elif len(zeros) == 1: if new_t is None: new_t = zeros.pop() - elif not new_t in zeros: + elif new_t not in zeros: return (0, None) if use_edge_labels else None else: @@ -7725,28 +7725,27 @@ def hamiltonian_path(self, s=None, t=None, use_edge_labels=False, return (0, None) if use_edge_labels else None elif len(ones) == 2: - if not new_s is None and not new_s in ones: + if new_s is not None and new_s not in ones: return (0, None) if use_edge_labels else None - if not new_t is None and not new_t in ones: + if new_t is not None and new_t not in ones: return (0, None) if use_edge_labels else None # Set new_s and new_t if possible if new_s is None and new_t is None: new_s,new_t = ones - elif not new_s is None and new_t is None: + elif new_s is not None and new_t is None: new_t = ones[1] if new_s == ones[0] else ones[0] - elif new_s is None and not new_t is None: + elif new_s is None and new_t is not None: new_s = ones[1] if new_t == ones[0] else ones[0] elif len(ones) == 1: - if not new_s is None and not new_t is None and not (new_s in ones or new_t in ones): + if new_s is not None and new_t is not None and not (new_s in ones or new_t in ones): return (0, None) if use_edge_labels else None - elif new_s is None and (new_t is None or (not new_t is None and not new_t in ones)): + elif new_s is None and (new_t is None or (new_t is not None and new_t not in ones)): new_s = ones.pop() - elif new_t is None and not new_s is None and not new_s in ones: + elif new_t is None and new_s is not None and new_s not in ones: new_t = ones.pop() - if not use_edge_labels and algorithm == "backtrack": path = g.longest_path(s=new_s, t=new_t, algorithm="backtrack") return path if path.order() == g.order() else None @@ -10918,7 +10917,8 @@ def merge_vertices(self, vertices): if self.is_directed(): out_edges = self.edge_boundary(vertices) - in_edges = self.edge_boundary([v for v in self if not v in vertices]) + in_edges = self.edge_boundary([v for v in self + if v not in vertices]) self.delete_vertices(vertices[1:]) self.add_edges((u, v0, l) for (u0, v0, l) in out_edges if u0 != u) self.add_edges((v0, u, l) for (v0, u0, l) in in_edges if u0 != u) @@ -13619,7 +13619,7 @@ def is_chordal(self, certificate=False, algorithm="B"): nb1 = [u for u in g.neighbor_iterator(v) if pos_in_peo[u] > pos_in_peo[v]] for xi in nb1: for yi in nb1: - if not yi in neighbors_subsets[xi]: + if yi not in neighbors_subsets[xi]: new_tup = (pos_in_peo[xi], pos_in_peo[yi]) if max_tup < new_tup: max_tup = new_tup @@ -13645,7 +13645,7 @@ def is_chordal(self, certificate=False, algorithm="B"): # ---------------- # 1- The graph is not chordal - if not hole is None: + if hole is not None: # There was a bug there once, so it's better to check the # answer is valid, especially when it is so cheap ;-) @@ -14478,7 +14478,7 @@ def clustering_average(self, implementation=None): else: implementation = 'sparse_copy' - if not implementation in ['networkx', 'boost', 'dense_copy', 'sparse_copy']: + if implementation not in ['networkx', 'boost', 'dense_copy', 'sparse_copy']: raise ValueError("the implementation can only be 'networkx', " "'boost', 'sparse_copy', 'dense_copy' or None") @@ -14602,7 +14602,7 @@ def clustering_coeff(self, else: implementation = 'sparse_copy' - if not implementation in ['networkx', 'boost', 'dense_copy', 'sparse_copy']: + if implementation not in ['networkx', 'boost', 'dense_copy', 'sparse_copy']: raise ValueError("the implementation can only be 'networkx', " "'boost', 'sparse_copy', 'dense_copy' or None") @@ -19105,7 +19105,7 @@ def layout_extend_randomly(self, pos, dim=2): # Check each vertex position is in pos, add position randomly within the # plot range if none is defined for v in self: - if not v in pos: + if v not in pos: pos[v] = [xmin + dx * random(), ymin + dy * random()] return pos diff --git a/src/sage/graphs/graph.py b/src/sage/graphs/graph.py index 75fb6241f23..fe601ddeea9 100644 --- a/src/sage/graphs/graph.py +++ b/src/sage/graphs/graph.py @@ -1530,7 +1530,7 @@ def is_tree(self, certificate=False, output='vertex'): sage: G.is_tree(certificate=True, output='edge') (False, [(0, 0, None)]) """ - if not output in ['vertex', 'edge']: + if output not in ['vertex', 'edge']: raise ValueError('output must be either vertex or edge') if not self.order() or not self.is_connected(): @@ -6499,8 +6499,7 @@ def independent_set(self, algorithm="Cliquer", value_only=False, reduction_rules return self.order() - my_cover else: my_cover = set(my_cover) - return [u for u in self if not u in my_cover] - + return [u for u in self if u not in my_cover] @doc_index("Algorithmically hard stuff") @rename_keyword(deprecation=32238, verbosity='verbose') @@ -6757,7 +6756,7 @@ def vertex_cover(self, algorithm="Cliquer", value_only=False, if value_only: size_cover_g = g.order() - len(independent) else: - cover_g = set(uu for uu in g if not uu in independent) + cover_g = set(uu for uu in g if uu not in independent) elif algorithm == "MILP": diff --git a/src/sage/graphs/graph_database.py b/src/sage/graphs/graph_database.py index c7c6fe18cca..fc114c0afec 100644 --- a/src/sage/graphs/graph_database.py +++ b/src/sage/graphs/graph_database.py @@ -430,7 +430,7 @@ class located in :mod:`sage.databases.sql_db` to make the query for key in kwds: # check validity - if not key in valid_kwds: + if key not in valid_kwds: raise KeyError('%s is not a valid key for this database.'%str(key)) # designate a query_dict diff --git a/src/sage/graphs/isgci.py b/src/sage/graphs/isgci.py index 4ddd64d2171..99f90f76179 100644 --- a/src/sage/graphs/isgci.py +++ b/src/sage/graphs/isgci.py @@ -456,7 +456,7 @@ class represented by ``gc_id`` ?* self._name = name self._gc_id = gc_id - if not recognition_function is None: + if recognition_function is not None: self._recognition_function = recognition_function def _repr_(self): diff --git a/src/sage/graphs/pq_trees.py b/src/sage/graphs/pq_trees.py index 7dfbe72349f..6a36cfa8886 100644 --- a/src/sage/graphs/pq_trees.py +++ b/src/sage/graphs/pq_trees.py @@ -220,7 +220,7 @@ def __init__(self, seq): if isinstance(e, list): e = Set(e) - if not e in self._children: + if e not in self._children: self._children.append(e) def reverse(self): From 6ce2bedfabdf3f5fbf0f6b776baa222005e8de7a Mon Sep 17 00:00:00 2001 From: Miguel Marco Date: Sat, 13 Nov 2021 23:12:58 +0100 Subject: [PATCH 106/126] Adapt overflow doctest to 32 bits --- src/sage/rings/polynomial/polydict.pyx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/sage/rings/polynomial/polydict.pyx b/src/sage/rings/polynomial/polydict.pyx index 651d4041272..95785f04521 100644 --- a/src/sage/rings/polynomial/polydict.pyx +++ b/src/sage/rings/polynomial/polydict.pyx @@ -1628,7 +1628,8 @@ cdef class ETuple: sage: y^(2^32) Traceback (most recent call last): ... - OverflowError: exponent overflow (...) + OverflowError: exponent overflow (...) # 64-bit + OverflowError: Python int too large to convert to C unsigned long # 32-bit """ if self._length!=other._length: raise ArithmeticError From feff55e50727d51b270320518ebeed932fcd1823 Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Wed, 10 Nov 2021 17:38:20 +0000 Subject: [PATCH 107/126] fixes for arb's incomplete gamma and erfi also add a bit of docs --- src/sage/rings/real_arb.pyx | 43 ++++++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/src/sage/rings/real_arb.pyx b/src/sage/rings/real_arb.pyx index c616e9cd304..87085ca091d 100644 --- a/src/sage/rings/real_arb.pyx +++ b/src/sage/rings/real_arb.pyx @@ -3468,9 +3468,27 @@ cdef class RealBall(RingElement): if _do_sig(prec(self)): sig_off() return res - def gamma(self): + def erfi(self): """ - Return the image of this ball by the Euler Gamma function. + Imaginary error function. + + EXAMPLES:: + + sage: RBF(1/2).erfi() + [0.614952094696511 +/- 2.22e-16] + """ + cdef RealBall res = self._new() + if _do_sig(prec(self)): sig_on() + arb_hypgeom_erfi(res.value, self.value, prec(self)) + if _do_sig(prec(self)): sig_off() + return res + + def gamma(self, a=None): + """ + Image of this ball by the (incomplete) Euler Gamma function + + For `a` real, return the upper incomplete Gamma function + of `\Gamma(self,a)`. For integer and rational arguments, :meth:`~sage.rings.real_arb.RealBallField.gamma` may be faster. @@ -3479,14 +3497,27 @@ cdef class RealBall(RingElement): sage: RBF(1/2).gamma() [1.772453850905516 +/- ...e-16] + sage: RBF(gamma(3/2,sqrt(2))) + [0.37118875695353 +/- 3.29e-15] + sage: RBF(3/2).gamma(sqrt(2)) + [0.37118875695353 +/- 3.29e-15] + sage: RBF(gamma(3/2,RIF(sqrt(2)))) + [0.37118875695353 +/- 3.15e-15] .. SEEALSO:: :meth:`~sage.rings.real_arb.RealBallField.gamma` """ + cdef RealBall a_ball cdef RealBall res = self._new() - if _do_sig(prec(self)): sig_on() - arb_gamma(res.value, self.value, prec(self)) - if _do_sig(prec(self)): sig_off() + if a is None: + if _do_sig(prec(self)): sig_on() + arb_gamma(res.value, self.value, prec(self)) + if _do_sig(prec(self)): sig_off() + else: + if _do_sig(prec(self)): sig_on() + a_ball = RBF(a) + arb_hypgeom_gamma_upper(res.value, self.value, a_ball.value, 0, prec(self)) + if _do_sig(prec(self)): sig_off() return res def log_gamma(self): @@ -3569,6 +3600,8 @@ cdef class RealBall(RingElement): For ``a = 1`` (or ``a = None``), this computes the Riemann zeta function. + Otherwise, it computes Hurwitz zeta function. + Use :meth:`RealBallField.zeta` to compute the Riemann zeta function of a small integer without first converting it to a real ball. From 2a4bf9647b36f78ad93e6220a93cad72528dcb15 Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Thu, 11 Nov 2021 11:37:40 +0000 Subject: [PATCH 108/126] wrap arb's Ei --- src/sage/rings/real_arb.pyx | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/sage/rings/real_arb.pyx b/src/sage/rings/real_arb.pyx index 87085ca091d..642abc9742e 100644 --- a/src/sage/rings/real_arb.pyx +++ b/src/sage/rings/real_arb.pyx @@ -3483,6 +3483,21 @@ cdef class RealBall(RingElement): if _do_sig(prec(self)): sig_off() return res + def Ei(self): + """ + Exponential integral + + EXAMPLES:: + + sage: RBF(1).Ei() + [1.89511781635594 +/- 4.94e-15] + """ + cdef RealBall res = self._new() + if _do_sig(prec(self)): sig_on() + arb_hypgeom_ei(res.value, self.value, prec(self)) + if _do_sig(prec(self)): sig_off() + return res + def gamma(self, a=None): """ Image of this ball by the (incomplete) Euler Gamma function From b5892c9e57d87bd825b69a8e8bd8e0f8ae2034f5 Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Thu, 11 Nov 2021 12:14:28 +0000 Subject: [PATCH 109/126] wrap arb's gamma_inc_lower --- src/sage/rings/real_arb.pyx | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/sage/rings/real_arb.pyx b/src/sage/rings/real_arb.pyx index 642abc9742e..e0275e5a3d2 100644 --- a/src/sage/rings/real_arb.pyx +++ b/src/sage/rings/real_arb.pyx @@ -3500,7 +3500,7 @@ cdef class RealBall(RingElement): def gamma(self, a=None): """ - Image of this ball by the (incomplete) Euler Gamma function + Image of this ball by the (upper incomplete) Euler Gamma function For `a` real, return the upper incomplete Gamma function of `\Gamma(self,a)`. @@ -3535,6 +3535,28 @@ cdef class RealBall(RingElement): if _do_sig(prec(self)): sig_off() return res + def gamma_inc_lower(self, a): + """ + Image of this ball by the lower incomplete Euler Gamma function + + For `a` real, return the lower incomplete Gamma function + of `\Gamma(self,a)`. + + EXAMPLES:: + + sage: RBF(gamma_inc_lower(1/2,sqrt(2))) + [1.60830863772925 +/- 2.75e-15] + sage: RBF(7/2).gamma_inc_lower(5) + [2.69665515418630 +/- 9.50e-15] + """ + cdef RealBall a_ball + cdef RealBall res = self._new() + if _do_sig(prec(self)): sig_on() + a_ball = RBF(a) + arb_hypgeom_gamma_lower(res.value, self.value, a_ball.value, 0, prec(self)) + if _do_sig(prec(self)): sig_off() + return res + def log_gamma(self): """ Return the image of this ball by the logarithmic Gamma function. From 335ccc78b3ecdf1722a309bcd2f99fdc79a801f0 Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Thu, 11 Nov 2021 16:25:38 +0000 Subject: [PATCH 110/126] wrapped arb chi, shi, li, Li --- src/sage/rings/real_arb.pyx | 95 ++++++++++++++++++++++++++++++++++++- 1 file changed, 93 insertions(+), 2 deletions(-) diff --git a/src/sage/rings/real_arb.pyx b/src/sage/rings/real_arb.pyx index e0275e5a3d2..974282d7328 100644 --- a/src/sage/rings/real_arb.pyx +++ b/src/sage/rings/real_arb.pyx @@ -3470,7 +3470,7 @@ cdef class RealBall(RingElement): def erfi(self): """ - Imaginary error function. + Imaginary error function EXAMPLES:: @@ -3485,7 +3485,7 @@ cdef class RealBall(RingElement): def Ei(self): """ - Exponential integral + Exponential integral EXAMPLES:: @@ -3498,6 +3498,97 @@ cdef class RealBall(RingElement): if _do_sig(prec(self)): sig_off() return res + def Si(self): + """ + Sine integral + + EXAMPLES:: + + sage: RBF(1).Si() + [0.946083070367183 +/- 9.22e-16] + """ + cdef RealBall res = self._new() + if _do_sig(prec(self)): sig_on() + arb_hypgeom_si(res.value, self.value, prec(self)) + if _do_sig(prec(self)): sig_off() + return res + + def Ci(self): + """ + Cosine integral + + EXAMPLES:: + + sage: RBF(1).Ci() + [0.337403922900968 +/- 3.25e-16] + """ + cdef RealBall res = self._new() + if _do_sig(prec(self)): sig_on() + arb_hypgeom_ci(res.value, self.value, prec(self)) + if _do_sig(prec(self)): sig_off() + return res + + + def Shi(self): + """ + Hyperbolic sine integral + + EXAMPLES:: + + sage: RBF(1).Shi() + [1.05725087537573 +/- 2.77e-15] + """ + cdef RealBall res = self._new() + if _do_sig(prec(self)): sig_on() + arb_hypgeom_shi(res.value, self.value, prec(self)) + if _do_sig(prec(self)): sig_off() + return res + + def Chi(self): + """ + Hyperbolic cosine integral + + EXAMPLES:: + + sage: RBF(1).Chi() + [0.837866940980208 +/- 4.72e-16] + """ + cdef RealBall res = self._new() + if _do_sig(prec(self)): sig_on() + arb_hypgeom_chi(res.value, self.value, prec(self)) + if _do_sig(prec(self)): sig_off() + return res + + def li(self): + """ + Logarithmic integral + + EXAMPLES:: + + sage: RBF(3).li() + [2.16358859466719 +/- 4.72e-15] + """ + cdef RealBall res = self._new() + if _do_sig(prec(self)): sig_on() + arb_hypgeom_li(res.value, self.value, 0, prec(self)) + if _do_sig(prec(self)): sig_off() + return res + + def Li(self): + """ + Offset logarithmic integral + + EXAMPLES:: + + sage: RBF(3).Li() + [1.11842481454970 +/- 7.61e-15] + """ + cdef RealBall res = self._new() + if _do_sig(prec(self)): sig_on() + arb_hypgeom_li(res.value, self.value, 1, prec(self)) + if _do_sig(prec(self)): sig_off() + return res + def gamma(self, a=None): """ Image of this ball by the (upper incomplete) Euler Gamma function From 8a532ebf510ad650addd0375daf7801f3a914a90 Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Thu, 11 Nov 2021 17:46:58 +0000 Subject: [PATCH 111/126] wrapped arb's complete beta function there are issues with Sage's beta being also implemented via pynac, so RBF(beta(a,b)) does not work, one needs RBF(a).beta(b) instead. --- src/sage/rings/real_arb.pyx | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/sage/rings/real_arb.pyx b/src/sage/rings/real_arb.pyx index 974282d7328..18cc3a8be69 100644 --- a/src/sage/rings/real_arb.pyx +++ b/src/sage/rings/real_arb.pyx @@ -3588,6 +3588,32 @@ cdef class RealBall(RingElement): arb_hypgeom_li(res.value, self.value, 1, prec(self)) if _do_sig(prec(self)): sig_off() return res + + def beta(self, a): + """ + Image of this ball by the complete beta function + + For `a` real, return the complete Gamma function `B(self,a)`. + + EXAMPLES:: + + sage: RBF(sin(3)).beta(sqrt(2/3)) + [7.407661629415 +/- 1.26e-13] + + .. TODO:: + + At the moment RBF(beta(a,b)) does not work, one needs + RBF(a).beta(b) for this to work. See :trac:`32851` + and :trac:`24641`. + """ + cdef RealBall a_ball, aone + cdef RealBall res = self._new() + if _do_sig(prec(self)): sig_on() + a_ball = RBF(a) + aone = RBF(1) + arb_hypgeom_beta_lower(res.value, self.value, a_ball.value, aone.value, 0, prec(self)) + if _do_sig(prec(self)): sig_off() + return res def gamma(self, a=None): """ From 03e7d80d40cd04ebf431073e50cef92393c71032 Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Thu, 11 Nov 2021 20:17:05 +0000 Subject: [PATCH 112/126] add missing article and gamma_inc defn and test --- src/sage/rings/real_arb.pyx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/sage/rings/real_arb.pyx b/src/sage/rings/real_arb.pyx index 18cc3a8be69..9a9a465377e 100644 --- a/src/sage/rings/real_arb.pyx +++ b/src/sage/rings/real_arb.pyx @@ -3631,7 +3631,7 @@ cdef class RealBall(RingElement): [1.772453850905516 +/- ...e-16] sage: RBF(gamma(3/2,sqrt(2))) [0.37118875695353 +/- 3.29e-15] - sage: RBF(3/2).gamma(sqrt(2)) + sage: RBF(3/2).gamma_inc(sqrt(2)) [0.37118875695353 +/- 3.29e-15] sage: RBF(gamma(3/2,RIF(sqrt(2)))) [0.37118875695353 +/- 3.15e-15] @@ -3652,6 +3652,8 @@ cdef class RealBall(RingElement): if _do_sig(prec(self)): sig_off() return res + gamma_inc = gamma + def gamma_inc_lower(self, a): """ Image of this ball by the lower incomplete Euler Gamma function @@ -3754,7 +3756,7 @@ cdef class RealBall(RingElement): For ``a = 1`` (or ``a = None``), this computes the Riemann zeta function. - Otherwise, it computes Hurwitz zeta function. + Otherwise, it computes the Hurwitz zeta function. Use :meth:`RealBallField.zeta` to compute the Riemann zeta function of a small integer without first converting it to a real ball. From 2d82f61a1533b70b25baa9c840ecc2d96b295b87 Mon Sep 17 00:00:00 2001 From: Marc Mezzarobba Date: Fri, 12 Nov 2021 10:02:34 +0100 Subject: [PATCH 113/126] #32851 fix conversions --- src/sage/rings/real_arb.pyx | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/src/sage/rings/real_arb.pyx b/src/sage/rings/real_arb.pyx index 9a9a465377e..a8fdd633206 100644 --- a/src/sage/rings/real_arb.pyx +++ b/src/sage/rings/real_arb.pyx @@ -3591,14 +3591,16 @@ cdef class RealBall(RingElement): def beta(self, a): """ - Image of this ball by the complete beta function + Image of this ball by the complete beta function For `a` real, return the complete Gamma function `B(self,a)`. EXAMPLES:: - sage: RBF(sin(3)).beta(sqrt(2/3)) - [7.407661629415 +/- 1.26e-13] + sage: RBF(sin(3)).beta(RBF(2/3).sqrt()) + [7.407661629415 +/- 1.07e-13] + sage: RealBallField(100)(7/2).beta(1) + [0.28571428571428571428571428571 +/- 5.23e-30] .. TODO:: @@ -3609,8 +3611,8 @@ cdef class RealBall(RingElement): cdef RealBall a_ball, aone cdef RealBall res = self._new() if _do_sig(prec(self)): sig_on() - a_ball = RBF(a) - aone = RBF(1) + a_ball = self._parent.coerce(a) + aone = self._parent.one() arb_hypgeom_beta_lower(res.value, self.value, a_ball.value, aone.value, 0, prec(self)) if _do_sig(prec(self)): sig_off() return res @@ -3629,15 +3631,18 @@ cdef class RealBall(RingElement): sage: RBF(1/2).gamma() [1.772453850905516 +/- ...e-16] - sage: RBF(gamma(3/2,sqrt(2))) - [0.37118875695353 +/- 3.29e-15] - sage: RBF(3/2).gamma_inc(sqrt(2)) - [0.37118875695353 +/- 3.29e-15] - sage: RBF(gamma(3/2,RIF(sqrt(2)))) - [0.37118875695353 +/- 3.15e-15] + sage: RBF(gamma(3/2, RBF(2).sqrt())) + [0.37118875695353 +/- 3.00e-15] + sage: RBF(3/2).gamma_inc(RBF(2).sqrt()) + [0.37118875695353 +/- 3.00e-15] .. SEEALSO:: :meth:`~sage.rings.real_arb.RealBallField.gamma` + + TESTS:: + + sage: RealBallField(100).gamma(1/2) + [1.77245385090551602729816748334 +/- 1.90e-30] """ cdef RealBall a_ball cdef RealBall res = self._new() @@ -3647,7 +3652,7 @@ cdef class RealBall(RingElement): if _do_sig(prec(self)): sig_off() else: if _do_sig(prec(self)): sig_on() - a_ball = RBF(a) + a_ball = self._parent.coerce(a) arb_hypgeom_gamma_upper(res.value, self.value, a_ball.value, 0, prec(self)) if _do_sig(prec(self)): sig_off() return res @@ -3663,10 +3668,10 @@ cdef class RealBall(RingElement): EXAMPLES:: - sage: RBF(gamma_inc_lower(1/2,sqrt(2))) - [1.60830863772925 +/- 2.75e-15] - sage: RBF(7/2).gamma_inc_lower(5) - [2.69665515418630 +/- 9.50e-15] + sage: RBF(gamma_inc_lower(1/2, RBF(2).sqrt())) + [1.608308637729248 +/- 8.14e-16] + sage: RealBallField(100)(7/2).gamma_inc_lower(5) + [2.6966551541863035516887949614 +/- 8.91e-29] """ cdef RealBall a_ball cdef RealBall res = self._new() From 8092951b7bd52619405cf90c00f4a4fd1312e331 Mon Sep 17 00:00:00 2001 From: Marc Mezzarobba Date: Fri, 12 Nov 2021 10:05:47 +0100 Subject: [PATCH 114/126] #32851 update a doctest --- src/sage/symbolic/function.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/symbolic/function.pyx b/src/sage/symbolic/function.pyx index 91c66fc5eff..89cdce56d70 100644 --- a/src/sage/symbolic/function.pyx +++ b/src/sage/symbolic/function.pyx @@ -627,7 +627,7 @@ cdef class Function(SageObject): sage: airy_ai(b) airy_ai([1.500000000 +/- 1.01e-10]) sage: gamma(b, 1) - gamma([1.500000000 +/- 1.01e-10], 1) + [0.50728223 +/- 4.67e-9] sage: hurwitz_zeta(b, b) hurwitz_zeta([1.500000000 +/- 1.01e-10], [1.500000000 +/- 1.01e-10]) sage: hurwitz_zeta(1/2, b) From 3a5d60cb59816538050236ebb3f9c760617601ac Mon Sep 17 00:00:00 2001 From: Marc Mezzarobba Date: Sun, 14 Nov 2021 10:41:51 +0100 Subject: [PATCH 115/126] #32851 incomplete beta function + minor fixes --- src/sage/libs/arb/arb_hypgeom.pxd | 12 ++++++------ src/sage/rings/real_arb.pyx | 31 +++++++++++++++++++++---------- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/src/sage/libs/arb/arb_hypgeom.pxd b/src/sage/libs/arb/arb_hypgeom.pxd index 627e083bdc9..fb1c40ddaa8 100644 --- a/src/sage/libs/arb/arb_hypgeom.pxd +++ b/src/sage/libs/arb/arb_hypgeom.pxd @@ -30,9 +30,9 @@ cdef extern from "arb_wrap.h": void arb_hypgeom_gamma_lower(arb_t res, const arb_t s, const arb_t z, int regularized, long prec) void _arb_hypgeom_gamma_lower_series(arb_ptr res, const arb_t s, arb_srcptr z, long zlen, int regularized, long n, long prec) void arb_hypgeom_gamma_lower_series(arb_poly_t res, const arb_t s, const arb_poly_t z, int regularized, long n, long prec) - void arb_hypgeom_beta_lower(arb_t res, const arb_t a, const arb_t b, const arb_t z, int regularized, long prec) - void _arb_hypgeom_beta_lower_series(arb_ptr res, const arb_t a, const arb_t b, arb_srcptr z, long zlen, int regularized, long n, long prec) - void arb_hypgeom_beta_lower_series(arb_poly_t res, const arb_t a, const arb_t b, const arb_poly_t z, int regularized, long n, long prec) + void arb_hypgeom_beta_lower(arb_t res, const arb_t a, const arb_t b, const arb_t z, bint regularized, long prec) + void _arb_hypgeom_beta_lower_series(arb_ptr res, const arb_t a, const arb_t b, arb_srcptr z, long zlen, bint regularized, long n, long prec) + void arb_hypgeom_beta_lower_series(arb_poly_t res, const arb_t a, const arb_t b, const arb_poly_t z, bint regularized, long n, long prec) void arb_hypgeom_expint(arb_t res, const arb_t s, const arb_t z, long prec) void arb_hypgeom_ei(arb_t res, const arb_t z, long prec) void _arb_hypgeom_ei_series(arb_ptr res, arb_srcptr z, long zlen, long len, long prec) @@ -49,9 +49,9 @@ cdef extern from "arb_wrap.h": void arb_hypgeom_chi(arb_t res, const arb_t z, long prec) void _arb_hypgeom_chi_series(arb_ptr res, arb_srcptr z, long zlen, long len, long prec) void arb_hypgeom_chi_series(arb_poly_t res, const arb_poly_t z, long len, long prec) - void arb_hypgeom_li(arb_t res, const arb_t z, int offset, long prec) - void _arb_hypgeom_li_series(arb_ptr res, arb_srcptr z, long zlen, int offset, long len, long prec) - void arb_hypgeom_li_series(arb_poly_t res, const arb_poly_t z, int offset, long len, long prec) + void arb_hypgeom_li(arb_t res, const arb_t z, bint offset, long prec) + void _arb_hypgeom_li_series(arb_ptr res, arb_srcptr z, long zlen, bint offset, long len, long prec) + void arb_hypgeom_li_series(arb_poly_t res, const arb_poly_t z, bint offset, long len, long prec) void arb_hypgeom_bessel_j(arb_t res, const arb_t nu, const arb_t z, long prec) void arb_hypgeom_bessel_y(arb_t res, const arb_t nu, const arb_t z, long prec) void arb_hypgeom_bessel_jy(arb_t res1, arb_t res2, const arb_t nu, const arb_t z, long prec) diff --git a/src/sage/rings/real_arb.pyx b/src/sage/rings/real_arb.pyx index a8fdd633206..b375d2758e7 100644 --- a/src/sage/rings/real_arb.pyx +++ b/src/sage/rings/real_arb.pyx @@ -3570,7 +3570,7 @@ cdef class RealBall(RingElement): """ cdef RealBall res = self._new() if _do_sig(prec(self)): sig_on() - arb_hypgeom_li(res.value, self.value, 0, prec(self)) + arb_hypgeom_li(res.value, self.value, False, prec(self)) if _do_sig(prec(self)): sig_off() return res @@ -3585,15 +3585,23 @@ cdef class RealBall(RingElement): """ cdef RealBall res = self._new() if _do_sig(prec(self)): sig_on() - arb_hypgeom_li(res.value, self.value, 1, prec(self)) + arb_hypgeom_li(res.value, self.value, True, prec(self)) if _do_sig(prec(self)): sig_off() return res - - def beta(self, a): + + def beta(self, a, z=1): """ - Image of this ball by the complete beta function + (Incomplete) beta function + + INPUT: + + - ``a``, ``z`` (optional) -- real balls - For `a` real, return the complete Gamma function `B(self,a)`. + OUTPUT: + + The lower incomplete beta function `B(self, a, z)`. + + With the default value of ``z``, the complete beta function `B(self, a)`. EXAMPLES:: @@ -3601,6 +3609,8 @@ cdef class RealBall(RingElement): [7.407661629415 +/- 1.07e-13] sage: RealBallField(100)(7/2).beta(1) [0.28571428571428571428571428571 +/- 5.23e-30] + sage: RealBallField(100)(7/2).beta(1, 1/2) + [0.025253813613805268728601584361 +/- 2.53e-31] .. TODO:: @@ -3608,12 +3618,13 @@ cdef class RealBall(RingElement): RBF(a).beta(b) for this to work. See :trac:`32851` and :trac:`24641`. """ - cdef RealBall a_ball, aone + cdef RealBall a_ball, z_ball cdef RealBall res = self._new() if _do_sig(prec(self)): sig_on() a_ball = self._parent.coerce(a) - aone = self._parent.one() - arb_hypgeom_beta_lower(res.value, self.value, a_ball.value, aone.value, 0, prec(self)) + z_ball = self._parent.coerce(z) + arb_hypgeom_beta_lower(res.value, self.value, a_ball.value, + z_ball.value, False, prec(self)) if _do_sig(prec(self)): sig_off() return res @@ -3622,7 +3633,7 @@ cdef class RealBall(RingElement): Image of this ball by the (upper incomplete) Euler Gamma function For `a` real, return the upper incomplete Gamma function - of `\Gamma(self,a)`. + `\Gamma(self,a)`. For integer and rational arguments, :meth:`~sage.rings.real_arb.RealBallField.gamma` may be faster. From d9ee935f95001716b8493be7689b4e3b52b1afc5 Mon Sep 17 00:00:00 2001 From: Marc Mezzarobba Date: Sun, 14 Nov 2021 11:43:29 +0100 Subject: [PATCH 116/126] #32869 ComplexBall: rename + add aliases for some special functions for consistency with sage.symbolic (and RealBall after #32851). --- src/sage/rings/complex_arb.pyx | 105 ++++++++++++++++++++++++++++----- 1 file changed, 89 insertions(+), 16 deletions(-) diff --git a/src/sage/rings/complex_arb.pyx b/src/sage/rings/complex_arb.pyx index b18359ca151..ce9b1b19a95 100644 --- a/src/sage/rings/complex_arb.pyx +++ b/src/sage/rings/complex_arb.pyx @@ -188,6 +188,7 @@ from sage.structure.parent cimport Parent from sage.structure.unique_representation import UniqueRepresentation from sage.arith.long cimport is_small_python_int +from sage.misc.superseded import deprecated_function_alias from sage.rings.complex_mpfr import ComplexField from sage.rings.complex_interval_field import ComplexIntervalField, ComplexIntervalField_class from sage.rings.integer_ring import ZZ @@ -4175,16 +4176,21 @@ cdef class ComplexBall(RingElement): if _do_sig(prec(self)): sig_off() return res - def ei(self): + def Ei(self): """ Return the exponential integral with argument ``self``. EXAMPLES:: - sage: CBF(1, 1).ei() + sage: CBF(1, 1).Ei() [1.76462598556385 +/- ...e-15] + [2.38776985151052 +/- ...e-15]*I - sage: CBF(0).ei() + sage: CBF(0).Ei() nan + + TESTS: + + sage: CBF(Ei(I)) + [0.337403922900968 +/- 3.76e-16] + [2.51687939716208 +/- 2.01e-15]*I """ cdef ComplexBall result = self._new() if _do_sig(prec(self)): sig_on() @@ -4192,16 +4198,23 @@ cdef class ComplexBall(RingElement): if _do_sig(prec(self)): sig_off() return result - def si(self): + ei = deprecated_function_alias(32869, Ei) + + def Si(self): """ Return the sine integral with argument ``self``. EXAMPLES:: - sage: CBF(1, 1).si() + sage: CBF(1, 1).Si() [1.10422265823558 +/- ...e-15] + [0.88245380500792 +/- ...e-15]*I - sage: CBF(0).si() + sage: CBF(0).Si() 0 + + TESTS: + + sage: CBF(Si(I)) + [1.05725087537573 +/- 2.77e-15]*I """ cdef ComplexBall result = self._new() if _do_sig(prec(self)): sig_on() @@ -4209,16 +4222,25 @@ cdef class ComplexBall(RingElement): if _do_sig(prec(self)): sig_off() return result - def ci(self): + sin_integral = Si # as for the symbolic function + + si = deprecated_function_alias(32869, Si) + + def Ci(self): """ Return the cosine integral with argument ``self``. EXAMPLES:: - sage: CBF(1, 1).ci() + sage: CBF(1, 1).Ci() [0.882172180555936 +/- ...e-16] + [0.287249133519956 +/- ...e-16]*I - sage: CBF(0).ci() + sage: CBF(0).Ci() nan + nan*I + + TESTS: + + sage: CBF(Ci(I)) + [0.837866940980208 +/- 4.72e-16] + [1.570796326794897 +/- 5.54e-16]*I """ cdef ComplexBall result = self._new() if _do_sig(prec(self)): sig_on() @@ -4226,34 +4248,51 @@ cdef class ComplexBall(RingElement): if _do_sig(prec(self)): sig_off() return result - def shi(self): + cos_integral = Ci # as for the symbolic function + + ci = deprecated_function_alias(32869, Ci) + + def Shi(self): """ Return the hyperbolic sine integral with argument ``self``. EXAMPLES:: - sage: CBF(1, 1).shi() + sage: CBF(1, 1).Shi() [0.88245380500792 +/- ...e-15] + [1.10422265823558 +/- ...e-15]*I - sage: CBF(0).shi() + sage: CBF(0).Shi() 0 - """ + TESTS: + + sage: CBF(Shi(I)) + [0.946083070367183 +/- 9.22e-16]*I + """ cdef ComplexBall result = self._new() if _do_sig(prec(self)): sig_on() acb_hypgeom_shi(result.value, self.value, prec(self)) if _do_sig(prec(self)): sig_off() return result - def chi(self): + sinh_integral = Shi + + shi = deprecated_function_alias(32869, Shi) + + def Chi(self): """ Return the hyperbolic cosine integral with argument ``self``. EXAMPLES:: - sage: CBF(1, 1).chi() + sage: CBF(1, 1).Chi() [0.882172180555936 +/- ...e-16] + [1.28354719327494 +/- ...e-15]*I - sage: CBF(0).chi() + sage: CBF(0).Chi() nan + nan*I + + TESTS: + + sage: CBF(Chi(I)) + [0.337403922900968 +/- 3.25e-16] + [1.570796326794897 +/- 5.54e-16]*I """ cdef ComplexBall result = self._new() if _do_sig(prec(self)): sig_on() @@ -4261,6 +4300,10 @@ cdef class ComplexBall(RingElement): if _do_sig(prec(self)): sig_off() return result + cosh_integral = Chi + + chi = deprecated_function_alias(32869, Chi) + def li(self, bint offset=False): """ Return the logarithmic integral with argument ``self``. @@ -4279,6 +4322,13 @@ cdef class ComplexBall(RingElement): 0.000000000000000 sage: Li(0).n() -1.04516378011749 + + TESTS:: + + sage: CBF(li(0)) + 0 + sage: CBF(Li(0)) + [-1.04516378011749...] """ cdef ComplexBall result = self._new() if _do_sig(prec(self)): sig_on() @@ -4286,6 +4336,29 @@ cdef class ComplexBall(RingElement): if _do_sig(prec(self)): sig_off() return result + log_integral = li + + def Li(self): + """ + Offset logarithmic integral. + + EXAMPLES:: + + sage: CBF(0).Li() + [-1.045163780117493 +/- ...e-16] + sage: li(0).n() + 0.000000000000000 + sage: Li(0).n() + -1.04516378011749 + """ + cdef ComplexBall result = self._new() + if _do_sig(prec(self)): sig_on() + acb_hypgeom_li(result.value, self.value, True, prec(self)) + if _do_sig(prec(self)): sig_off() + return result + + log_integral_offset = Li + def jacobi_theta(self, tau): r""" Return the four Jacobi theta functions evaluated at the argument From 5ef7cc8873ac811d4861f1b55a79a3183856a969 Mon Sep 17 00:00:00 2001 From: Marc Mezzarobba Date: Sun, 14 Nov 2021 12:00:59 +0100 Subject: [PATCH 117/126] =?UTF-8?q?#32871=20fix=20infinite=20recursion=20i?= =?UTF-8?q?n=20SR=20=E2=86=92=20[RC]BF=20conversion?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/sage/symbolic/expression.pyx | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/src/sage/symbolic/expression.pyx b/src/sage/symbolic/expression.pyx index 8c29b6c6657..843cfee7f4c 100644 --- a/src/sage/symbolic/expression.pyx +++ b/src/sage/symbolic/expression.pyx @@ -1793,7 +1793,20 @@ cdef class Expression(Expression_abc): Traceback (most recent call last): ... ValueError: nonzero imaginary part + + sage: from sage.symbolic.function import BuiltinFunction + sage: f = BuiltinFunction("bogus_builtin_function") + sage: RBF(f(1)) + Traceback (most recent call last): + ... + TypeError: unable to convert bogus_builtin_function(1) to a RealBall + sage: CBF(f(1)) + Traceback (most recent call last): + ... + TypeError: unable to convert bogus_builtin_function(1) to a ComplexBall """ + cdef bint progress = False + cdef int i # Note that we deliberately don't use _eval_self and don't try going # through RIF/CIF in order to avoid unsafe conversions. operator = self.operator() @@ -1827,11 +1840,18 @@ cdef class Expression(Expression_abc): # Generic case: walk through the expression. In this case, we do # not bother trying to stay in the real field. try: - res = self.operator()(*[C(a) for a in args]) + for i in range(len(args)): + if args[i].parent() is not C: + progress = True + args[i] = C(args[i]) except (TypeError, ValueError): pass - else: - return R(res) + if progress: + try: + res = self.operator()(*[C(a) for a in args]) + return R(res) + except (TypeError, ValueError): + pass # Typically more informative and consistent than the exceptions that # would propagate raise TypeError("unable to convert {!r} to a {!s}".format( From 535719018598e165bee841f6e7c8911870b5f4de Mon Sep 17 00:00:00 2001 From: Marc Mezzarobba Date: Sun, 14 Nov 2021 12:11:11 +0100 Subject: [PATCH 118/126] #32851 more aliases for compatibility with symbolic functions --- src/sage/rings/real_arb.pyx | 43 +++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/src/sage/rings/real_arb.pyx b/src/sage/rings/real_arb.pyx index b375d2758e7..80a840e7868 100644 --- a/src/sage/rings/real_arb.pyx +++ b/src/sage/rings/real_arb.pyx @@ -3491,6 +3491,11 @@ cdef class RealBall(RingElement): sage: RBF(1).Ei() [1.89511781635594 +/- 4.94e-15] + + TESTS:: + + sage: RBF(Ei(1)) + [1.89511781635594 +/- 4.94e-15] """ cdef RealBall res = self._new() if _do_sig(prec(self)): sig_on() @@ -3506,6 +3511,11 @@ cdef class RealBall(RingElement): sage: RBF(1).Si() [0.946083070367183 +/- 9.22e-16] + + TESTS:: + + sage: RBF(Si(1)) + [0.946083070367183 +/- 9.22e-16] """ cdef RealBall res = self._new() if _do_sig(prec(self)): sig_on() @@ -3513,6 +3523,8 @@ cdef class RealBall(RingElement): if _do_sig(prec(self)): sig_off() return res + sin_integral = Si + def Ci(self): """ Cosine integral @@ -3521,6 +3533,11 @@ cdef class RealBall(RingElement): sage: RBF(1).Ci() [0.337403922900968 +/- 3.25e-16] + + TESTS:: + + sage: RBF(Ci(1)) + [0.337403922900968 +/- 3.25e-16] """ cdef RealBall res = self._new() if _do_sig(prec(self)): sig_on() @@ -3528,6 +3545,7 @@ cdef class RealBall(RingElement): if _do_sig(prec(self)): sig_off() return res + cos_integral = Ci def Shi(self): """ @@ -3537,6 +3555,11 @@ cdef class RealBall(RingElement): sage: RBF(1).Shi() [1.05725087537573 +/- 2.77e-15] + + TESTS:: + + sage: RBF(Shi(1)) + [1.05725087537573 +/- 2.77e-15] """ cdef RealBall res = self._new() if _do_sig(prec(self)): sig_on() @@ -3544,6 +3567,8 @@ cdef class RealBall(RingElement): if _do_sig(prec(self)): sig_off() return res + sinh_integral = Shi + def Chi(self): """ Hyperbolic cosine integral @@ -3552,6 +3577,11 @@ cdef class RealBall(RingElement): sage: RBF(1).Chi() [0.837866940980208 +/- 4.72e-16] + + TESTS:: + + sage: RBF(Chi(1)) + [0.837866940980208 +/- 4.72e-16] """ cdef RealBall res = self._new() if _do_sig(prec(self)): sig_on() @@ -3559,6 +3589,8 @@ cdef class RealBall(RingElement): if _do_sig(prec(self)): sig_off() return res + cosh_integral = Chi + def li(self): """ Logarithmic integral @@ -3567,6 +3599,13 @@ cdef class RealBall(RingElement): sage: RBF(3).li() [2.16358859466719 +/- 4.72e-15] + + TESTS:: + + sage: RBF(li(0)) + 0 + sage: RBF(Li(0)) + [-1.04516378011749 +/- 4.23e-15] """ cdef RealBall res = self._new() if _do_sig(prec(self)): sig_on() @@ -3574,6 +3613,8 @@ cdef class RealBall(RingElement): if _do_sig(prec(self)): sig_off() return res + log_integral = li + def Li(self): """ Offset logarithmic integral @@ -3589,6 +3630,8 @@ cdef class RealBall(RingElement): if _do_sig(prec(self)): sig_off() return res + log_integral_offset = Li + def beta(self, a, z=1): """ (Incomplete) beta function From aa35a2b92adefed50bebf4b02029df7867d250f7 Mon Sep 17 00:00:00 2001 From: Marc Mezzarobba Date: Sun, 14 Nov 2021 12:15:50 +0100 Subject: [PATCH 119/126] #32851 partial support for symbolic beta --- src/sage/functions/gamma.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/sage/functions/gamma.py b/src/sage/functions/gamma.py index 3e58cbe5a22..3a4deef625d 100644 --- a/src/sage/functions/gamma.py +++ b/src/sage/functions/gamma.py @@ -1045,4 +1045,13 @@ def __init__(self): fricas='Beta', giac='Beta')) + def _method_arguments(self, x, y): + r""" + TESTS:: + + sage: RBF(beta(sin(3),sqrt(RBF(2).add_error(1e-8)/3))) + [7.407662 +/- 6.17e-7] + """ + return [x, y] + beta = Function_beta() From ed63aeba2be4fdfe02f3b2ed20e55577fe2e896d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sun, 14 Nov 2021 14:08:59 +0100 Subject: [PATCH 120/126] some details in plot (unicode, pep, etc) --- src/sage/plot/colors.py | 31 ++-- src/sage/plot/graphics.py | 364 ++++++++++++++++++-------------------- 2 files changed, 189 insertions(+), 206 deletions(-) diff --git a/src/sage/plot/colors.py b/src/sage/plot/colors.py index 0f2923aa972..6fdba0f0da0 100644 --- a/src/sage/plot/colors.py +++ b/src/sage/plot/colors.py @@ -21,7 +21,7 @@ For a list of color maps in Sage, evaluate:: sage: sorted(colormaps) - [u'Accent', u'Blues', u'BrBG', ...] + ['Accent', 'Blues', 'BrBG', ...] These are imported from matplotlib's cm_ module. @@ -290,16 +290,10 @@ def rgbcolor(c, space='rgb'): (0.25, 0.4, 0.9) sage: rgbcolor('purple') (0.5019607843137255, 0.0, 0.5019607843137255) - sage: rgbcolor(u'purple') - (0.5019607843137255, 0.0, 0.5019607843137255) sage: rgbcolor('#fa0') (1.0, 0.6666666666666666, 0.0) - sage: rgbcolor(u'#fa0') - (1.0, 0.6666666666666666, 0.0) sage: rgbcolor('#ffffff') (1.0, 1.0, 1.0) - sage: rgbcolor(u'#ffffff') - (1.0, 1.0, 1.0) sage: rgbcolor((1,1/2,1/3)) (1.0, 0.5, 0.3333333333333333) sage: rgbcolor([1,1/2,1/3]) @@ -510,8 +504,7 @@ def __eq__(self, right): """ if isinstance(right, Color): return self._rgb == right._rgb - else: - return False + return False def __ne__(self, right): """ @@ -824,7 +817,7 @@ def __int__(self): OUTPUT: - the integer `256^2 r_int + 256 g_int + b_int`, where `r_int`, `g_int`, and `b_int` - are obtained from `r`, `g`, and `b` by converting from the real interval [0.0, 1.0] + are obtained from `r`, `g`, and `b` by converting from the real interval [0.0, 1.0] to the integer range 0, 1, ..., 255. EXAMPLES:: @@ -1115,7 +1108,7 @@ def __getattr__(self, name): try: return self[name] except KeyError: - raise AttributeError("'%s' has no attribute or colormap %s"%(type(self).__name__,name)) + raise AttributeError("'%s' has no attribute or colormap %s" % (type(self).__name__, name)) def __dir__(self): """ @@ -1136,8 +1129,10 @@ def __dir__(self): methods = ['__dir__', '__getattr__'] return dir(super(ColorsDict, self)) + methods + sorted(self) + colors = ColorsDict() + # Add convenient module-scope colors. These are Color instances. for c in colors: vars()[c] = colors[c] @@ -1254,7 +1249,7 @@ def float_to_integer(r, g, b): OUTPUT: - the integer `256^2 r_int + 256 g_int + b_int`, where `r_int`, `g_int`, and `b_int` - are obtained from `r`, `g`, and `b` by converting from the real interval [0.0, 1.0] + are obtained from `r`, `g`, and `b` by converting from the real interval [0.0, 1.0] to the integer range 0, 1, ..., 255. EXAMPLES:: @@ -1337,7 +1332,7 @@ def get_cmap(cmap): and color names. For a list of map names, evaluate:: sage: sorted(colormaps) - [u'Accent', u'Blues', ...] + ['Accent', 'Blues', ...] See :func:`rgbcolor` for valid list/tuple element formats. @@ -1356,8 +1351,6 @@ def get_cmap(cmap): sage: from sage.plot.colors import get_cmap sage: get_cmap('jet') - sage: get_cmap(u'jet') - sage: get_cmap([(0,0,0), (0.5,0.5,0.5), (1,1,1)]) sage: get_cmap(['green', 'lightblue', 'blue']) @@ -1383,7 +1376,7 @@ def get_cmap(cmap): return cmap elif isinstance(cmap, str): - if not cmap in cm.datad: + if cmap not in cm.datad: raise RuntimeError("Color map %s not known (type import matplotlib.cm; matplotlib.cm.datad.keys() for valid names)" % cmap) return cm.__dict__[cmap] @@ -1431,7 +1424,7 @@ class Colormaps(MutableMapping): For a list of map names, evaluate:: sage: sorted(colormaps) - [u'Accent', u'Blues', ...] + ['Accent', 'Blues', ...] """ def __init__(self): """ @@ -1616,7 +1609,7 @@ def __getattr__(self, name): try: return self[name] except KeyError: - raise AttributeError("'%s' has no attribute or colormap %s"%(type(self).__name__,name)) + raise AttributeError("'%s' has no attribute or colormap %s" % (type(self).__name__, name)) def __repr__(self): """ @@ -1678,7 +1671,7 @@ def __delitem__(self, name): sage: maps = Colormaps() sage: count = len(maps) sage: maps.popitem() # random - (u'Spectral', ) + ('Spectral', ) sage: count - 1 == len(maps) True """ diff --git a/src/sage/plot/graphics.py b/src/sage/plot/graphics.py index 61fa25dd277..137f65016f4 100644 --- a/src/sage/plot/graphics.py +++ b/src/sage/plot/graphics.py @@ -99,7 +99,7 @@ def _parse_figsize(figsize): if len(figsize) != 2: raise ValueError("figsize should be a positive number or a list " "of two positive numbers, not {0}".format(figsize)) - figsize = (float(figsize[0]), float(figsize[1])) # floats for mpl + figsize = (float(figsize[0]), float(figsize[1])) # floats for mpl if not (figsize[0] > 0 and figsize[1] > 0): raise ValueError("figsize should be positive numbers, " "not {0} and {1}".format(figsize[0], figsize[1])) @@ -107,12 +107,12 @@ def _parse_figsize(figsize): # in this case, figsize is a single number representing the width and # should be positive try: - figsize = float(figsize) # to pass to mpl + figsize = float(figsize) # to pass to mpl except TypeError: raise TypeError("figsize should be a positive number, not {0}".format(figsize)) if figsize > 0: default_width, default_height = rcParams['figure.figsize'] - figsize = (figsize, default_height*figsize/default_width) + figsize = (figsize, default_height * figsize / default_width) else: raise ValueError("figsize should be positive, not {0}".format(figsize)) return figsize @@ -435,7 +435,6 @@ def set_legend_options(self, **kwds): else: self._legend_opts.update(kwds) - def get_axes_range(self): """ Returns a dictionary of the range of the axes for this graphics @@ -784,9 +783,9 @@ def axes_labels(self, l=None): :: sage: c = circle((0,0), 1) - sage: c.axes_labels(['axe des abscisses', u'axe des ordonnées']) + sage: c.axes_labels(['axe des abscisses', 'axe des ordonnées']) sage: c._axes_labels - ('axe des abscisses', u'axe des ordonn\xe9es') + ('axe des abscisses', 'axe des ordonnées') """ if l is None: try: @@ -852,7 +851,6 @@ def axes_label_color(self, c=None): return self._axes_label_color self._axes_label_color = rgbcolor(c) - def axes_width(self, w=None): r""" Set the axes width. Use this to draw a plot with really fat or @@ -1019,7 +1017,7 @@ def __str__(self): sage: print(S) Graphics object consisting of 1 graphics primitive """ - s = "Graphics object consisting of %s graphics primitives"%(len(self)) + s = "Graphics object consisting of %s graphics primitives" % (len(self)) if len(self) == 1: s = s[:-1] return s @@ -1193,7 +1191,7 @@ def __add__(self, other): from sage.plot.plot3d.base import Graphics3d if isinstance(other, Graphics3d): return self.plot3d() + other - raise TypeError("other (=%s) must be a Graphics objects"%other) + raise TypeError("other (=%s) must be a Graphics objects" % other) g = Graphics() g._objects = self._objects + other._objects g._show_legend = self._show_legend or other._show_legend @@ -1208,9 +1206,9 @@ def __add__(self, other): if 'flip_y' in self._extra_kwds and 'flip_y' in other._extra_kwds: g._extra_kwds['flip_y'] = (self._extra_kwds['flip_y'] or other._extra_kwds['flip_y']) - if self.aspect_ratio()=='automatic': + if self.aspect_ratio() == 'automatic': g.set_aspect_ratio(other.aspect_ratio()) - elif other.aspect_ratio()=='automatic': + elif other.aspect_ratio() == 'automatic': g.set_aspect_ratio(self.aspect_ratio()) else: g.set_aspect_ratio(max(self.aspect_ratio(), other.aspect_ratio())) @@ -1275,7 +1273,7 @@ def plot3d(self, z=0, **kwds): from sage.plot.plot3d.base import Graphics3dGroup g = Graphics3dGroup([g.plot3d(**kwds) for g in self._objects]) if z: - g = g.translate(0,0,z) + g = g.translate(0, 0, z) return g @classmethod @@ -1412,7 +1410,6 @@ def _set_scale(self, subplot, scale=None, base=None): return (xscale, yscale, basex, basey) - # This dictionary has the default values for the keywords to show(). When # show is invoked with keyword arguments, those arguments are merged with # this dictionary to create a set of keywords with the defaults filled in. @@ -2199,7 +2196,6 @@ def ymax(self, ymax=None): else: self.set_axes_range(ymax=ymax) - def get_minmax_data(self): r""" Return the x and y coordinate minimum and maximum @@ -2252,16 +2248,16 @@ def get_minmax_data(self): ymin = min(d['ymin'] for d in minmax_data) ymax = max(d['ymax'] for d in minmax_data) if isnan(xmin): - xmin=0 + xmin = 0 sage.misc.verbose.verbose("xmin was NaN (setting to 0)", level=0) if isnan(xmax): - xmax=0 + xmax = 0 sage.misc.verbose.verbose("xmax was NaN (setting to 0)", level=0) if isnan(ymin): - ymin=0 + ymin = 0 sage.misc.verbose.verbose("ymin was NaN (setting to 0)", level=0) if isnan(ymax): - ymax=0 + ymax = 0 sage.misc.verbose.verbose("ymax was NaN (setting to 0)", level=0) else: xmin = xmax = ymin = ymax = 0 @@ -2312,18 +2308,18 @@ def _limit_output_aspect_ratio(self, xmin, xmax, ymin, ymax): if aspect_ratio != 'automatic': width = xmax - xmin height = ymax - ymin - output_aspect = abs(width/height/aspect_ratio) + output_aspect = abs(width / height / aspect_ratio) if output_aspect > 1e15: height = 1e15 * width / aspect_ratio ycenter = (ymax - ymin) / 2 - ymin = ycenter - height/2 - ymax = ycenter + height/2 + ymin = ycenter - height / 2 + ymax = ycenter + height / 2 if output_aspect < 1e-15: width = 1e-15 * height * aspect_ratio xcenter = (xmax - xmin) / 2 - xmin = xcenter - width/2 - xmax = xcenter + width/2 - return {'xmin':xmin, 'xmax':xmax, 'ymin':ymin, 'ymax':ymax} + xmin = xcenter - width / 2 + xmax = xcenter + width / 2 + return {'xmin': xmin, 'xmax': xmax, 'ymin': ymin, 'ymax': ymax} def _matplotlib_tick_formatter(self, subplot, base=(10, 10), locator_options={}, scale=('linear', 'linear'), @@ -2356,45 +2352,45 @@ def _matplotlib_tick_formatter(self, subplot, base=(10, 10), MultipleLocator, NullLocator, ScalarFormatter) x_locator, y_locator = ticks - #---------------------- Location of x-ticks ---------------------# + # ---------------------- Location of x-ticks --------------------- if x_locator is None: if scale[0] == 'log': x_locator = LogLocator(base=base[0]) else: x_locator = MaxNLocator(**locator_options) - elif isinstance(x_locator,Locator): + elif isinstance(x_locator, Locator): pass elif x_locator == []: x_locator = NullLocator() - elif isinstance(x_locator,list): + elif isinstance(x_locator, list): x_locator = FixedLocator(x_locator) - else: # x_locator is a number which can be made a float + else: # x_locator is a number which can be made a float from sage.functions.other import ceil, floor - if floor(xmax/x_locator)-ceil(xmin/x_locator)>1: - x_locator=MultipleLocator(float(x_locator)) - else: # not enough room for two major ticks + if floor(xmax / x_locator) - ceil(xmin / x_locator) > 1: + x_locator = MultipleLocator(float(x_locator)) + else: # not enough room for two major ticks raise ValueError('Expand the range of the independent ' 'variable to allow two multiples of your tick locator ' '(option `ticks`).') - #---------------------- Location of y-ticks ---------------------# + # ---------------------- Location of y-ticks --------------------- if y_locator is None: if scale[1] == 'log': y_locator = LogLocator(base=base[1]) else: y_locator = MaxNLocator(**locator_options) - elif isinstance(y_locator,Locator): + elif isinstance(y_locator, Locator): pass elif y_locator == []: y_locator = NullLocator() - elif isinstance(y_locator,list): + elif isinstance(y_locator, list): y_locator = FixedLocator(y_locator) - else: # y_locator is a number which can be made a float + else: # y_locator is a number which can be made a float from sage.functions.other import ceil, floor - if floor(ymax/y_locator)-ceil(ymin/y_locator)>1: - y_locator=MultipleLocator(float(y_locator)) - else: # not enough room for two major ticks + if floor(ymax / y_locator) - ceil(ymin / y_locator) > 1: + y_locator = MultipleLocator(float(y_locator)) + else: # not enough room for two major ticks raise ValueError('Expand the range of the dependent ' 'variable to allow two multiples of your tick locator ' '(option `ticks`).') @@ -2404,7 +2400,7 @@ def _matplotlib_tick_formatter(self, subplot, base=(10, 10), from sage.misc.latex import latex from sage.symbolic.ring import SR from .misc import _multiple_of_constant - #---------------------- Formatting x-ticks ----------------------# + # ---------------------- Formatting x-ticks ---------------------- if x_formatter is None: if scale[0] == 'log': x_formatter = LogFormatterMathtext(base=base[0]) @@ -2412,16 +2408,16 @@ def _matplotlib_tick_formatter(self, subplot, base=(10, 10), x_formatter = ScalarFormatter() elif x_formatter in SR: x_const = x_formatter - x_formatter = FuncFormatter(lambda n,pos: - _multiple_of_constant(n,pos,x_const)) + x_formatter = FuncFormatter(lambda n, pos: + _multiple_of_constant(n, pos, x_const)) elif x_formatter == "latex": if scale[0] == 'log': # We need to strip out '\\mathdefault' from the string - x_formatter = FuncFormatter(lambda n,pos: - LogFormatterMathtext(base=base[0])(n,pos).replace( - "\\mathdefault","")) + x_formatter = FuncFormatter(lambda n, pos: + LogFormatterMathtext(base=base[0])(n, pos).replace( + "\\mathdefault", "")) else: - x_formatter = FuncFormatter(lambda n,pos: '$%s$'%latex(n)) + x_formatter = FuncFormatter(lambda n, pos: '$%s$' % latex(n)) elif isinstance(x_formatter, (list, tuple)): if (not isinstance(ticks[0], (list, tuple)) or len(ticks[0]) != len(x_formatter)): @@ -2429,7 +2425,7 @@ def _matplotlib_tick_formatter(self, subplot, base=(10, 10), "`tick_formatter` is a list then the first component " "of `ticks` must also be a list of equal length.") x_formatter = FixedFormatter(x_formatter) - #---------------------- Formatting y-ticks ----------------------# + # ---------------------- Formatting y-ticks ---------------------- if y_formatter is None: if scale[1] == 'log': y_formatter = LogFormatterMathtext(base=base[1]) @@ -2437,16 +2433,16 @@ def _matplotlib_tick_formatter(self, subplot, base=(10, 10), y_formatter = ScalarFormatter() elif y_formatter in SR: y_const = y_formatter - y_formatter = FuncFormatter(lambda n,pos: - _multiple_of_constant(n,pos,y_const)) + y_formatter = FuncFormatter(lambda n, pos: + _multiple_of_constant(n, pos, y_const)) elif y_formatter == "latex": if scale[1] == 'log': # We need to strip out '\\mathdefault' from the string - y_formatter = FuncFormatter(lambda n,pos: - LogFormatterMathtext(base=base[1])(n,pos).replace( - "\\mathdefault","")) + y_formatter = FuncFormatter(lambda n, pos: + LogFormatterMathtext(base=base[1])(n, pos).replace( + "\\mathdefault", "")) else: - y_formatter = FuncFormatter(lambda n,pos: '$%s$'%latex(n)) + y_formatter = FuncFormatter(lambda n, pos: '$%s$' % latex(n)) elif isinstance(y_formatter, (list, tuple)): if (not isinstance(ticks[1], (list, tuple)) or len(ticks[1]) != len(y_formatter)): @@ -2478,7 +2474,6 @@ def _matplotlib_tick_formatter(self, subplot, base=(10, 10), return (subplot, x_locator, y_locator, x_formatter, y_formatter) - def _get_vmin_vmax(self, vmin, vmax, basev, axes_pad): r""" Determine the min/max value for a variable plotted on a logarithmic @@ -2570,14 +2565,14 @@ def _get_vmin_vmax(self, vmin, vmax, basev, axes_pad): else: axes_pad = float(abs(axes_pad)) - logvmin = math.log(vmin)/math.log(basev) - logvmax = math.log(vmax)/math.log(basev) + logvmin = math.log(vmin) / math.log(basev) + logvmax = math.log(vmax) / math.log(basev) if math.floor(logvmax) - math.ceil(logvmin) < 0: vmax = basev**math.ceil(logvmax) vmin = basev**math.floor(logvmin) elif math.floor(logvmax) - math.ceil(logvmin) < 1: - if logvmax-math.floor(logvmax) > math.ceil(logvmin)-logvmin: + if logvmax - math.floor(logvmax) > math.ceil(logvmin) - logvmin: vmax = basev**math.ceil(logvmax) if axes_pad > 0: vmin -= vmin * basev**(-axes_pad) @@ -2730,15 +2725,15 @@ def matplotlib(self, filename=None, axes = self._show_axes from matplotlib.figure import Figure - if typeset == 'type1': # Requires LaTeX, dvipng, gs to be installed. + if typeset == 'type1': # Requires LaTeX, dvipng, gs to be installed. rcParams['ps.useafm'] = True rcParams['pdf.use14corefonts'] = True rcParams['text.usetex'] = True - elif typeset == 'latex': # Requires LaTeX, dvipng, gs to be installed. + elif typeset == 'latex': # Requires LaTeX, dvipng, gs to be installed. rcParams['ps.useafm'] = False rcParams['pdf.use14corefonts'] = False rcParams['text.usetex'] = True - elif typeset != 'default': # We won't change (maybe user-set) defaults + elif typeset != 'default': # We won't change (maybe user-set) defaults raise ValueError("typeset must be set to one of 'default', 'latex'," " or 'type1'; got '{}'.".format(typeset)) @@ -2772,13 +2767,13 @@ def matplotlib(self, filename=None, self._bbox_extra_artists.extend(g._bbox_extra_artists) # Set the aspect ratio if aspect_ratio is None: - aspect_ratio=self.aspect_ratio() + aspect_ratio = self.aspect_ratio() if aspect_ratio == 'automatic': subplot.set_aspect('auto', adjustable='box') else: subplot.set_aspect(aspect_ratio, adjustable='box') - #---------------- Set the axes limits and scale ------------------# + # ---------------- Set the axes limits and scale ------------------ self.set_axes_range(xmin, xmax, ymin, ymax) d = self.get_axes_range() xmin = d['xmax' if flip_x else 'xmin'] @@ -2797,7 +2792,7 @@ def matplotlib(self, filename=None, xmax, xmin = self._get_vmin_vmax(xmax, xmin, basex, axes_pad) else: xpad = 0.02 if axes_pad is None else axes_pad - xpad = (xmax - xmin)*float(xpad) + xpad = (xmax - xmin) * float(xpad) xmax += xpad xmin -= xpad @@ -2809,11 +2804,11 @@ def matplotlib(self, filename=None, ymax, ymin = self._get_vmin_vmax(ymax, ymin, basey, axes_pad) else: ypad = 0.02 if axes_pad is None else axes_pad - ypad = (ymax - ymin)*float(ypad) + ypad = (ymax - ymin) * float(ypad) ymax += ypad ymin -= ypad - #-------------------------- Set the legend -----------------------# + # -------------------------- Set the legend ----------------------- if show_legend is None: show_legend = self._show_legend @@ -2823,12 +2818,11 @@ def matplotlib(self, filename=None, lopts.update(legend_options) lopts.update(self._legend_opts) prop = FontProperties( - family = lopts.pop('font_family', 'sans-serif'), - size = lopts.pop('font_size', 'medium'), - style = lopts.pop('font_style', 'normal'), - weight = lopts.pop('font_weight', 'medium'), - variant = lopts.pop('font_variant', 'normal') - ) + family=lopts.pop('font_family', 'sans-serif'), + size=lopts.pop('font_size', 'medium'), + style=lopts.pop('font_style', 'normal'), + weight=lopts.pop('font_weight', 'medium'), + variant=lopts.pop('font_variant', 'normal')) color = lopts.pop('back_color', 'white') leg = subplot.legend(prop=prop, **lopts) if leg is None: @@ -2846,7 +2840,8 @@ def matplotlib(self, filename=None, subplot.set_xlim([xmin, xmax]) subplot.set_ylim([ymin, ymax]) - locator_options=dict(nbins=9,steps=[1,2,5,10],integer=ticks_integer) + locator_options = dict(nbins=9, steps=[1, 2, 5, 10], + integer=ticks_integer) if axes is None: axes = self._show_axes @@ -2855,7 +2850,6 @@ def matplotlib(self, filename=None, spine.set_color(self._axes_color) spine.set_linewidth(self._axes_width) - if frame: # For now, set the formatter to the old one, since that is # sort of what we are used to. We should eventually look at @@ -2863,24 +2857,24 @@ def matplotlib(self, filename=None, (subplot, x_locator, y_locator, x_formatter, y_formatter) = self._matplotlib_tick_formatter( - subplot, base=(basex, basey), - locator_options=locator_options, - scale=(xscale, yscale), - tick_formatter=tick_formatter, ticks=ticks, - xmax=xmax, xmin=xmin, ymax=ymax, ymin=ymin) + subplot, base=(basex, basey), + locator_options=locator_options, + scale=(xscale, yscale), + tick_formatter=tick_formatter, ticks=ticks, + xmax=xmax, xmin=xmin, ymax=ymax, ymin=ymin) subplot.set_frame_on(True) if axes and xscale == 'linear' and yscale == 'linear': - if (ymin<=0 and ymax>=0) or (ymax<=0 and ymin>=0): + if (ymin <= 0 and ymax >= 0) or (ymax <= 0 and ymin >= 0): subplot.axhline(color=self._axes_color, linewidth=self._axes_width) - if (xmin<=0 and xmax>=0) or (xmax<=0 and xmin>=0): + if (xmin <= 0 and xmax >= 0) or (xmax <= 0 and xmin >= 0): subplot.axvline(color=self._axes_color, linewidth=self._axes_width) elif axes: - ymiddle=False - xmiddle=False + ymiddle = False + xmiddle = False # Note that the user may specify a custom xmin and xmax which # flips the axis horizontally. Hence we need to check for both # the possibilities in the if statements below. Similar @@ -2888,68 +2882,68 @@ def matplotlib(self, filename=None, if xscale == 'log': if xmax > xmin: subplot.spines['right'].set_visible(False) - subplot.spines['left'].set_position(('outward',10)) + subplot.spines['left'].set_position(('outward', 10)) subplot.yaxis.set_ticks_position('left') subplot.yaxis.set_label_position('left') - yaxis='left' + yaxis = 'left' elif xmax < xmin: subplot.spines['left'].set_visible(False) - subplot.spines['right'].set_position(('outward',10)) + subplot.spines['right'].set_position(('outward', 10)) subplot.yaxis.set_ticks_position('right') subplot.yaxis.set_label_position('right') - yaxis='right' + yaxis = 'right' elif (xmin > 0 and xmax > xmin) or (xmax > 0 and xmin > xmax): subplot.spines['right'].set_visible(False) - subplot.spines['left'].set_position(('outward',10)) + subplot.spines['left'].set_position(('outward', 10)) subplot.yaxis.set_ticks_position('left') subplot.yaxis.set_label_position('left') - yaxis='left' + yaxis = 'left' elif (xmax < 0 and xmax > xmin) or (xmin < 0 and xmin > xmax): subplot.spines['left'].set_visible(False) - subplot.spines['right'].set_position(('outward',10)) + subplot.spines['right'].set_position(('outward', 10)) subplot.yaxis.set_ticks_position('right') subplot.yaxis.set_label_position('right') - yaxis='right' + yaxis = 'right' else: subplot.spines['left'].set_position('zero') subplot.yaxis.set_ticks_position('left') subplot.yaxis.set_label_position('left') subplot.spines['right'].set_visible(False) - ymiddle=True - yaxis='left' + ymiddle = True + yaxis = 'left' if yscale == 'log': if ymax > ymin: subplot.spines['top'].set_visible(False) - subplot.spines['bottom'].set_position(('outward',10)) + subplot.spines['bottom'].set_position(('outward', 10)) subplot.xaxis.set_ticks_position('bottom') subplot.xaxis.set_label_position('bottom') - xaxis='bottom' + xaxis = 'bottom' elif ymax < ymin: subplot.spines['bottom'].set_visible(False) - subplot.spines['top'].set_position(('outward',10)) + subplot.spines['top'].set_position(('outward', 10)) subplot.xaxis.set_ticks_position('top') subplot.xaxis.set_label_position('top') - xaxis='top' + xaxis = 'top' elif (ymin > 0 and ymax > ymin) or (ymax > 0 and ymin > ymax): subplot.spines['top'].set_visible(False) - subplot.spines['bottom'].set_position(('outward',10)) + subplot.spines['bottom'].set_position(('outward', 10)) subplot.xaxis.set_ticks_position('bottom') subplot.xaxis.set_label_position('bottom') - xaxis='bottom' + xaxis = 'bottom' elif (ymax < 0 and ymax > ymin) or (ymin < 0 and ymin > ymax): subplot.spines['bottom'].set_visible(False) - subplot.spines['top'].set_position(('outward',10)) + subplot.spines['top'].set_position(('outward', 10)) subplot.xaxis.set_ticks_position('top') subplot.xaxis.set_label_position('top') - xaxis='top' + xaxis = 'top' else: subplot.spines['bottom'].set_position('zero') subplot.xaxis.set_ticks_position('bottom') subplot.xaxis.set_label_position('bottom') subplot.spines['top'].set_visible(False) - xmiddle=True - xaxis='bottom' + xmiddle = True + xaxis = 'bottom' # For now, set the formatter to the old one, since that is # sort of what we are used to. We should eventually look at @@ -2957,11 +2951,11 @@ def matplotlib(self, filename=None, (subplot, x_locator, y_locator, x_formatter, y_formatter) = self._matplotlib_tick_formatter( - subplot, base=(basex, basey), - locator_options=locator_options, - scale=(xscale, yscale), - tick_formatter=tick_formatter, ticks=ticks, - xmax=xmax, xmin=xmin, ymax=ymax, ymin=ymin) + subplot, base=(basex, basey), + locator_options=locator_options, + scale=(xscale, yscale), + tick_formatter=tick_formatter, ticks=ticks, + xmax=xmax, xmin=xmin, ymax=ymax, ymin=ymin) # Make ticklines go on both sides of the axes # if xmiddle: @@ -2982,8 +2976,7 @@ def matplotlib(self, filename=None, # Make the zero tick labels disappear if the axes cross # inside the picture, but only if log scale is not used - if (xmiddle and ymiddle and xscale == 'linear' and - yscale == 'linear'): + if (xmiddle and ymiddle and xscale == 'linear' == yscale): from sage.plot.plot import SelectiveFormatter subplot.yaxis.set_major_formatter(SelectiveFormatter( subplot.yaxis.get_major_formatter(), skip_values=[0])) @@ -3009,20 +3002,20 @@ def matplotlib(self, filename=None, subplot.xaxis.set_minor_locator(NullLocator()) elif xscale == 'linear': subplot.xaxis.set_minor_locator(AutoMinorLocator()) - else: # log scale + else: # log scale from sage.arith.srange import srange - base_inv = 1.0/basex - subs = [float(_) for _ in srange(2*base_inv, 1, base_inv)] + base_inv = 1.0 / basex + subs = [float(_) for _ in srange(2 * base_inv, 1, base_inv)] subplot.xaxis.set_minor_locator(LogLocator(base=basex, subs=subs)) if isinstance(y_locator, (NullLocator, FixedLocator)): subplot.yaxis.set_minor_locator(NullLocator()) elif yscale == 'linear': subplot.yaxis.set_minor_locator(AutoMinorLocator()) - else: # log scale + else: # log scale from sage.arith.srange import srange - base_inv = 1.0/basey - subs = [float(_) for _ in srange(2*base_inv, 1, base_inv)] + base_inv = 1.0 / basey + subs = [float(_) for _ in srange(2 * base_inv, 1, base_inv)] subplot.yaxis.set_minor_locator(LogLocator(base=basey, subs=subs)) # Set the color and fontsize of ticks @@ -3032,121 +3025,119 @@ def matplotlib(self, filename=None, if gridlines is not None: if isinstance(gridlines, (list, tuple)): - vgridlines,hgridlines=gridlines + vgridlines, hgridlines = gridlines else: - hgridlines=gridlines - vgridlines=gridlines + hgridlines = gridlines + vgridlines = gridlines if gridlinesstyle is None: # Set up the default grid style - gridlinesstyle=dict(color='black',linestyle=':',linewidth=0.5) + gridlinesstyle = dict(color='black', linestyle=':', + linewidth=0.5) - vgridstyle=gridlinesstyle.copy() + vgridstyle = gridlinesstyle.copy() if vgridlinesstyle is not None: vgridstyle.update(vgridlinesstyle) - hgridstyle=gridlinesstyle.copy() + hgridstyle = gridlinesstyle.copy() if hgridlinesstyle is not None: hgridstyle.update(hgridlinesstyle) - if hgridlines=='minor': - hgridstyle['which']='both' - if vgridlines=='minor': - vgridstyle['which']='both' + if hgridlines == 'minor': + hgridstyle['which'] = 'both' + if vgridlines == 'minor': + vgridstyle['which'] = 'both' if not isinstance(hgridlines, str) and hasattr(hgridlines, '__iter__'): - hlines=iter(hgridlines) - hgridstyle.pop("minor",None) + hlines = iter(hgridlines) + hgridstyle.pop("minor", None) for hline in hlines: if isinstance(hline, (list, tuple)): - hl, style=hline - st=hgridstyle.copy() + hl, style = hline + st = hgridstyle.copy() st.update(style) else: - hl=hline - st=hgridstyle - subplot.axhline(hl,**st) + hl = hline + st = hgridstyle + subplot.axhline(hl, **st) else: if hgridlines not in (None, False): subplot.yaxis.grid(True, **hgridstyle) if not isinstance(vgridlines, str) and hasattr(vgridlines, '__iter__'): - vlines=iter(vgridlines) - vgridstyle.pop("minor",None) + vlines = iter(vgridlines) + vgridstyle.pop("minor", None) for vline in vlines: if isinstance(vline, (list, tuple)): - vl, style=vline - st=vgridstyle.copy() + vl, style = vline + st = vgridstyle.copy() st.update(style) else: - vl=vline - st=vgridstyle - subplot.axvline(vl,**st) + vl = vline + st = vgridstyle + subplot.axvline(vl, **st) else: if vgridlines not in (None, False): subplot.xaxis.grid(True, **vgridstyle) - - if self._axes_labels is not None: - label_options={} - label_options['color']=self._axes_label_color - label_options['size']=int(self._axes_labels_size * self._fontsize) + label_options = {} + label_options['color'] = self._axes_label_color + label_options['size'] = int(self._axes_labels_size * self._fontsize) subplot.set_xlabel(self._axes_labels[0], **label_options) subplot.set_ylabel(self._axes_labels[1], **label_options) - if axes is True and frame is False: # We set the label positions according to where we are # drawing the axes. - if xaxis=='bottom': - yaxis_labely=subplot.get_ylim()[1] - yaxis_labeloffset=8 - yaxis_vert='bottom' - xaxis_labely=0 - xaxis_vert='baseline' + if xaxis == 'bottom': + yaxis_labely = subplot.get_ylim()[1] + yaxis_labeloffset = 8 + yaxis_vert = 'bottom' + xaxis_labely = 0 + xaxis_vert = 'baseline' else: - yaxis_labely=subplot.get_ylim()[0] - yaxis_labeloffset=-8 - yaxis_vert='top' - xaxis_labely=1 - xaxis_vert='top' - - if yaxis=='left': - xaxis_labelx=subplot.get_xlim()[1] - xaxis_labeloffset=8 - xaxis_horiz='left' - yaxis_labelx=0 + yaxis_labely = subplot.get_ylim()[0] + yaxis_labeloffset = -8 + yaxis_vert = 'top' + xaxis_labely = 1 + xaxis_vert = 'top' + + if yaxis == 'left': + xaxis_labelx = subplot.get_xlim()[1] + xaxis_labeloffset = 8 + xaxis_horiz = 'left' + yaxis_labelx = 0 else: - xaxis_labelx=subplot.get_xlim()[0] - xaxis_labeloffset=-8 - xaxis_horiz='right' - yaxis_labelx=1 + xaxis_labelx = subplot.get_xlim()[0] + xaxis_labeloffset = -8 + xaxis_horiz = 'right' + yaxis_labelx = 1 from matplotlib.transforms import offset_copy - xlabel=subplot.xaxis.get_label() + xlabel = subplot.xaxis.get_label() xlabel.set_horizontalalignment(xaxis_horiz) xlabel.set_verticalalignment(xaxis_vert) - trans=subplot.spines[xaxis].get_transform() - labeltrans=offset_copy(trans, figure, x=xaxis_labeloffset, - y=0, units='points') + trans = subplot.spines[xaxis].get_transform() + labeltrans = offset_copy(trans, figure, x=xaxis_labeloffset, + y=0, units='points') subplot.xaxis.set_label_coords(x=xaxis_labelx, y=xaxis_labely, transform=labeltrans) - ylabel=subplot.yaxis.get_label() + ylabel = subplot.yaxis.get_label() ylabel.set_horizontalalignment('center') ylabel.set_verticalalignment(yaxis_vert) ylabel.set_rotation('horizontal') - trans=subplot.spines[yaxis].get_transform() - labeltrans=offset_copy(trans, figure, x=0, - y=yaxis_labeloffset, units='points') + trans = subplot.spines[yaxis].get_transform() + labeltrans = offset_copy(trans, figure, x=0, + y=yaxis_labeloffset, units='points') subplot.yaxis.set_label_coords(x=yaxis_labelx, y=yaxis_labely, transform=labeltrans) # This option makes the xlim and ylim limits not take effect # todo: figure out which limits were specified, and let the # free limits autoscale - #subplot.autoscale_view(tight=True) + # subplot.autoscale_view(tight=True) if title is not None: if title_pos is not None: if (not isinstance(title_pos, (list, tuple)) or @@ -3161,7 +3152,8 @@ def matplotlib(self, filename=None, position=title_pos) else: subplot.set_title(title, fontsize=fontsize) - else: # frame is false axes is not None, and neither is axes_labels + else: + # frame is false axes is not None, and neither is axes_labels # Then, the title is moved up to avoid overlap with axes labels if title_pos is None: title_pos = (0.5, 1.05) @@ -3195,7 +3187,6 @@ def save_image(self, filename=None, *args, **kwds): """ self.save(filename, *args, **kwds) - # filename argument is written explicitly so that it can be used as a # positional one, which is a very likely usage for this function. @@ -3304,13 +3295,13 @@ def save(self, filename, **kwds): else: from matplotlib import rcParams rc_backup = (rcParams['ps.useafm'], rcParams['pdf.use14corefonts'], - rcParams['text.usetex']) # save the rcParams + rcParams['text.usetex']) # save the rcParams figure = self.matplotlib(**options) # You can output in PNG, PS, EPS, PDF, PGF, or SVG format, depending # on the file extension. # PGF is handled by a different backend if ext == '.pgf': - from sage.features.latex import xelatex,pdflatex,lualatex + from sage.features.latex import xelatex, pdflatex, lualatex latex_implementations = [] if xelatex().is_present(): latex_implementations.append('xelatex') @@ -3325,12 +3316,10 @@ def save(self, filename, **kwds): # use pdflatex and set font encoding as per # matplotlib documentation: # https://matplotlib.org/users/pgf.html#pgf-tutorial - pgf_options= {"pgf.texsystem": "pdflatex", - "pgf.preamble": [ - r"\usepackage[utf8x]{inputenc}", - r"\usepackage[T1]{fontenc}" - ] - } + pgf_options = {"pgf.texsystem": "pdflatex", + "pgf.preamble": [ + r"\usepackage[utf8x]{inputenc}", + r"\usepackage[T1]{fontenc}"]} else: pgf_options = { "pgf.texsystem": latex_implementations[0], @@ -3348,7 +3337,7 @@ def save(self, filename, **kwds): from matplotlib.backends.backend_agg import FigureCanvasAgg figure.set_canvas(FigureCanvasAgg(figure)) # this messes up the aspect ratio! - #figure.canvas.mpl_connect('draw_event', pad_for_tick_labels) + # figure.canvas.mpl_connect('draw_event', pad_for_tick_labels) # tight_layout adjusts the *subplot* parameters so ticks aren't cut off, etc. figure.tight_layout() @@ -3363,7 +3352,7 @@ def save(self, filename, **kwds): # Restore the rcParams to the original, possibly user-set values (rcParams['ps.useafm'], rcParams['pdf.use14corefonts'], - rcParams['text.usetex']) = rc_backup + rcParams['text.usetex']) = rc_backup def _latex_(self, **kwds): """ @@ -3386,7 +3375,7 @@ def _latex_(self, **kwds): tmpfilename = tmp_filename(ext='.pgf') self.save(filename=tmpfilename, **kwds) with open(tmpfilename, "r") as tmpfile: - latex_list = tmpfile.readlines() + latex_list = tmpfile.readlines() from sage.misc.latex import latex latex.add_package_to_preamble_if_available('pgf') return ''.join(latex_list) @@ -3502,6 +3491,7 @@ def inset(self, graphics, pos=None, fontsize=None): graphics._extra_kwds['fontsize'] = 6 return MultiGraphics([(self, pos0), (graphics, pos)]) + # Deprecation notice for GraphicsArray import def GraphicsArray(*args, **kwargs): r""" From db5510e1a20932fdd81db0b710481b09af61bc1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Mon, 15 Nov 2021 17:18:44 +0100 Subject: [PATCH 121/126] fix the Krull dimension --- .../polynomial/polynomial_quotient_ring.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/sage/rings/polynomial/polynomial_quotient_ring.py b/src/sage/rings/polynomial/polynomial_quotient_ring.py index f342447c8f0..64cbec3e25d 100644 --- a/src/sage/rings/polynomial/polynomial_quotient_ring.py +++ b/src/sage/rings/polynomial/polynomial_quotient_ring.py @@ -1056,6 +1056,23 @@ def is_field(self, proof = True): return ret def krull_dimension(self): + """ + Return the Krull dimension. + + This is the Krull dimension of the base ring, unless the + quotient is zero. + + EXAMPLES:: + + sage: R = PolynomialRing(ZZ,'x').quotient(x**6-1) + sage: R.krull_dimension() + 1 + sage: R = PolynomialRing(ZZ,'x').quotient(1) + sage: R.krull_dimension() + -1 + """ + if self.is_zero(): + return -1 return self.base_ring().krull_dimension() def modulus(self): From cc60cfebc4576fed8b01f0fc487271bdee3cefed Mon Sep 17 00:00:00 2001 From: Release Manager Date: Fri, 19 Nov 2021 00:39:31 +0100 Subject: [PATCH 122/126] Updated SageMath version to 9.5.beta7 --- .zenodo.json | 8 ++++---- VERSION.txt | 2 +- build/pkgs/configure/checksums.ini | 6 +++--- build/pkgs/configure/package-version.txt | 2 +- build/pkgs/sagelib/package-version.txt | 2 +- src/VERSION.txt | 2 +- src/bin/sage-version.sh | 6 +++--- src/sage/version.py | 6 +++--- 8 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.zenodo.json b/.zenodo.json index 489c739efdd..fd96736f3c1 100644 --- a/.zenodo.json +++ b/.zenodo.json @@ -1,10 +1,10 @@ { "description": "Mirror of the Sage https://sagemath.org/ source tree", "license": "other-open", - "title": "sagemath/sage: 9.5.beta6", - "version": "9.5.beta6", + "title": "sagemath/sage: 9.5.beta7", + "version": "9.5.beta7", "upload_type": "software", - "publication_date": "2021-11-12", + "publication_date": "2021-11-18", "creators": [ { "affiliation": "SageMath.org", @@ -15,7 +15,7 @@ "related_identifiers": [ { "scheme": "url", - "identifier": "https://github.com/sagemath/sage/tree/9.5.beta6", + "identifier": "https://github.com/sagemath/sage/tree/9.5.beta7", "relation": "isSupplementTo" }, { diff --git a/VERSION.txt b/VERSION.txt index b437f328147..be62107d97e 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -SageMath version 9.5.beta6, Release Date: 2021-11-12 +SageMath version 9.5.beta7, Release Date: 2021-11-18 diff --git a/build/pkgs/configure/checksums.ini b/build/pkgs/configure/checksums.ini index 007dd069dce..f97cfada907 100644 --- a/build/pkgs/configure/checksums.ini +++ b/build/pkgs/configure/checksums.ini @@ -1,4 +1,4 @@ tarball=configure-VERSION.tar.gz -sha1=3658781e6dec76acbbcbc405ebc379a8d66438d0 -md5=a9e8b1ee469619a5fcecfda4e61ffc7e -cksum=1864932829 +sha1=d9fff88398cb15f16c7dcb3b6180163bb206a699 +md5=585dece094717b58049a2bfaf9811162 +cksum=3669459096 diff --git a/build/pkgs/configure/package-version.txt b/build/pkgs/configure/package-version.txt index 81a86beb1ab..0cae6c531de 100644 --- a/build/pkgs/configure/package-version.txt +++ b/build/pkgs/configure/package-version.txt @@ -1 +1 @@ -5cb64b3cc4129ec37883c15b81f88fb24fe0bc3d +cdb3614b34926cee3c4cc918313678d3deea4e8d diff --git a/build/pkgs/sagelib/package-version.txt b/build/pkgs/sagelib/package-version.txt index a72129631b5..8f24c817c21 100644 --- a/build/pkgs/sagelib/package-version.txt +++ b/build/pkgs/sagelib/package-version.txt @@ -1 +1 @@ -9.5.beta6 +9.5.beta7 diff --git a/src/VERSION.txt b/src/VERSION.txt index a72129631b5..8f24c817c21 100644 --- a/src/VERSION.txt +++ b/src/VERSION.txt @@ -1 +1 @@ -9.5.beta6 +9.5.beta7 diff --git a/src/bin/sage-version.sh b/src/bin/sage-version.sh index 547dbe14054..5d9a4f586f3 100644 --- a/src/bin/sage-version.sh +++ b/src/bin/sage-version.sh @@ -1,5 +1,5 @@ # Sage version information for shell scripts # This file is auto-generated by the sage-update-version script, do not edit! -SAGE_VERSION='9.5.beta6' -SAGE_RELEASE_DATE='2021-11-12' -SAGE_VERSION_BANNER='SageMath version 9.5.beta6, Release Date: 2021-11-12' +SAGE_VERSION='9.5.beta7' +SAGE_RELEASE_DATE='2021-11-18' +SAGE_VERSION_BANNER='SageMath version 9.5.beta7, Release Date: 2021-11-18' diff --git a/src/sage/version.py b/src/sage/version.py index 7785a1ebba4..60df61416a0 100644 --- a/src/sage/version.py +++ b/src/sage/version.py @@ -1,5 +1,5 @@ # Sage version information for Python scripts # This file is auto-generated by the sage-update-version script, do not edit! -version = '9.5.beta6' -date = '2021-11-12' -banner = 'SageMath version 9.5.beta6, Release Date: 2021-11-12' +version = '9.5.beta7' +date = '2021-11-18' +banner = 'SageMath version 9.5.beta7, Release Date: 2021-11-18' From e0399a10251b2c67642b2be81f9c25634dc0038e Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 24 Nov 2021 23:49:26 -0800 Subject: [PATCH 123/126] pkgs/sagemath-objects: Install a fixed set of scripts, not all of src/bin --- pkgs/sagemath-categories/bin | 2 +- pkgs/sagemath-objects/bin | 1 - pkgs/sagemath-objects/bin/sage | 1 + pkgs/sagemath-objects/bin/sage-env | 1 + pkgs/sagemath-objects/bin/sage-eval | 1 + pkgs/sagemath-objects/bin/sage-fixdoctests | 1 + pkgs/sagemath-objects/bin/sage-ipython | 1 + pkgs/sagemath-objects/bin/sage-python | 1 + pkgs/sagemath-objects/bin/sage-run | 1 + pkgs/sagemath-objects/bin/sage-runtests | 1 + pkgs/sagemath-objects/bin/sage-venv-config | 1 + pkgs/sagemath-objects/bin/sage-version.sh | 1 + pkgs/sagemath-objects/setup.cfg.m4 | 12 ++++++++++++ pkgs/sagemath-objects/setup.py | 6 ------ 14 files changed, 23 insertions(+), 8 deletions(-) delete mode 120000 pkgs/sagemath-objects/bin create mode 120000 pkgs/sagemath-objects/bin/sage create mode 120000 pkgs/sagemath-objects/bin/sage-env create mode 120000 pkgs/sagemath-objects/bin/sage-eval create mode 120000 pkgs/sagemath-objects/bin/sage-fixdoctests create mode 120000 pkgs/sagemath-objects/bin/sage-ipython create mode 120000 pkgs/sagemath-objects/bin/sage-python create mode 120000 pkgs/sagemath-objects/bin/sage-run create mode 120000 pkgs/sagemath-objects/bin/sage-runtests create mode 120000 pkgs/sagemath-objects/bin/sage-venv-config create mode 120000 pkgs/sagemath-objects/bin/sage-version.sh diff --git a/pkgs/sagemath-categories/bin b/pkgs/sagemath-categories/bin index 2f8b9b30ee7..1956438021b 120000 --- a/pkgs/sagemath-categories/bin +++ b/pkgs/sagemath-categories/bin @@ -1 +1 @@ -../../src/bin \ No newline at end of file +../sagemath-objects/bin \ No newline at end of file diff --git a/pkgs/sagemath-objects/bin b/pkgs/sagemath-objects/bin deleted file mode 120000 index 2f8b9b30ee7..00000000000 --- a/pkgs/sagemath-objects/bin +++ /dev/null @@ -1 +0,0 @@ -../../src/bin \ No newline at end of file diff --git a/pkgs/sagemath-objects/bin/sage b/pkgs/sagemath-objects/bin/sage new file mode 120000 index 00000000000..028392920ce --- /dev/null +++ b/pkgs/sagemath-objects/bin/sage @@ -0,0 +1 @@ +../../../src/bin/sage \ No newline at end of file diff --git a/pkgs/sagemath-objects/bin/sage-env b/pkgs/sagemath-objects/bin/sage-env new file mode 120000 index 00000000000..e35bf8a4000 --- /dev/null +++ b/pkgs/sagemath-objects/bin/sage-env @@ -0,0 +1 @@ +../../../src/bin/sage-env \ No newline at end of file diff --git a/pkgs/sagemath-objects/bin/sage-eval b/pkgs/sagemath-objects/bin/sage-eval new file mode 120000 index 00000000000..ac096cd38f1 --- /dev/null +++ b/pkgs/sagemath-objects/bin/sage-eval @@ -0,0 +1 @@ +../../../src/bin/sage-eval \ No newline at end of file diff --git a/pkgs/sagemath-objects/bin/sage-fixdoctests b/pkgs/sagemath-objects/bin/sage-fixdoctests new file mode 120000 index 00000000000..3d394f77c44 --- /dev/null +++ b/pkgs/sagemath-objects/bin/sage-fixdoctests @@ -0,0 +1 @@ +../../../src/bin/sage-fixdoctests \ No newline at end of file diff --git a/pkgs/sagemath-objects/bin/sage-ipython b/pkgs/sagemath-objects/bin/sage-ipython new file mode 120000 index 00000000000..00b3d2b0c50 --- /dev/null +++ b/pkgs/sagemath-objects/bin/sage-ipython @@ -0,0 +1 @@ +../../../src/bin/sage-ipython \ No newline at end of file diff --git a/pkgs/sagemath-objects/bin/sage-python b/pkgs/sagemath-objects/bin/sage-python new file mode 120000 index 00000000000..26d8bde2c71 --- /dev/null +++ b/pkgs/sagemath-objects/bin/sage-python @@ -0,0 +1 @@ +../../../src/bin/sage-python \ No newline at end of file diff --git a/pkgs/sagemath-objects/bin/sage-run b/pkgs/sagemath-objects/bin/sage-run new file mode 120000 index 00000000000..a2bce45f085 --- /dev/null +++ b/pkgs/sagemath-objects/bin/sage-run @@ -0,0 +1 @@ +../../../src/bin/sage-run \ No newline at end of file diff --git a/pkgs/sagemath-objects/bin/sage-runtests b/pkgs/sagemath-objects/bin/sage-runtests new file mode 120000 index 00000000000..8e3dbbaf100 --- /dev/null +++ b/pkgs/sagemath-objects/bin/sage-runtests @@ -0,0 +1 @@ +../../../src/bin/sage-runtests \ No newline at end of file diff --git a/pkgs/sagemath-objects/bin/sage-venv-config b/pkgs/sagemath-objects/bin/sage-venv-config new file mode 120000 index 00000000000..d1e0d8ec19b --- /dev/null +++ b/pkgs/sagemath-objects/bin/sage-venv-config @@ -0,0 +1 @@ +../../../src/bin/sage-venv-config \ No newline at end of file diff --git a/pkgs/sagemath-objects/bin/sage-version.sh b/pkgs/sagemath-objects/bin/sage-version.sh new file mode 120000 index 00000000000..46cfd0287a5 --- /dev/null +++ b/pkgs/sagemath-objects/bin/sage-version.sh @@ -0,0 +1 @@ +../../../src/bin/sage-version.sh \ No newline at end of file diff --git a/pkgs/sagemath-objects/setup.cfg.m4 b/pkgs/sagemath-objects/setup.cfg.m4 index ed1d60e1192..d4dc4402264 100644 --- a/pkgs/sagemath-objects/setup.cfg.m4 +++ b/pkgs/sagemath-objects/setup.cfg.m4 @@ -33,3 +33,15 @@ install_requires = gmpy2 \ cysignals \ | sed "2,\$s/^/ /;"')dnl + +scripts = + bin/sage + bin/sage-env + bin/sage-eval + bin/sage-fixdoctests + bin/sage-ipython + bin/sage-python + bin/sage-run + bin/sage-runtests + bin/sage-venv-config + bin/sage-version.sh diff --git a/pkgs/sagemath-objects/setup.py b/pkgs/sagemath-objects/setup.py index b988cbeaac1..84750b7d3f2 100644 --- a/pkgs/sagemath-objects/setup.py +++ b/pkgs/sagemath-objects/setup.py @@ -44,10 +44,4 @@ packages = python_packages, py_modules = python_modules, ext_modules = cython_modules, - scripts = [## The sage script - 'bin/sage', - 'bin/sage-env', - 'bin/sage-env-config', - 'bin/sage-runtests', - ], ) From 7519048d7af6f8545574e6990e3ca77165f7cee6 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 25 Nov 2021 18:03:32 -0800 Subject: [PATCH 124/126] src/bin/sage[-env]: Put SAGE_ROOT/src/bin in front of path only if run out of this directory --- src/bin/sage | 6 ++++++ src/bin/sage-env | 3 --- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/bin/sage b/src/bin/sage index fcd263029d0..4c0fa174260 100755 --- a/src/bin/sage +++ b/src/bin/sage @@ -298,6 +298,12 @@ if [ -f "${SELF}-env" ]; then fi fi +if [ -f "${SELF}-src-env-config.in" ]; then + # The sage script is being run out of SAGE_ROOT/src/bin. + # In this case, put this directory in the front of the PATH. + export PATH="$SAGE_SRC/bin:$PATH" +fi + if [ -z "$DOT_SAGE" ]; then export DOT_SAGE="$HOME/.sage" fi diff --git a/src/bin/sage-env b/src/bin/sage-env index 6ec3ba4b6ce..4d3c81152a8 100644 --- a/src/bin/sage-env +++ b/src/bin/sage-env @@ -295,9 +295,6 @@ fi if [ -n "$SAGE_VENV" ]; then export PATH="$SAGE_VENV/bin:$PATH" fi -if [ -n "$SAGE_SRC" ]; then - export PATH="$SAGE_SRC/bin:$PATH" -fi if [ -n "$SAGE_ROOT" ]; then export PATH="$SAGE_ROOT/build/bin:$PATH" fi From bfc953b1b4d1049e3dfe052ffc337be8c8d850fa Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 25 Nov 2021 18:31:51 -0800 Subject: [PATCH 125/126] src/sage/doctest/reporting.py: Indicate --environment if not default --- src/sage/doctest/reporting.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/sage/doctest/reporting.py b/src/sage/doctest/reporting.py index f51e347670a..e2dd07f595f 100644 --- a/src/sage/doctest/reporting.py +++ b/src/sage/doctest/reporting.py @@ -188,6 +188,9 @@ def report_head(self, source): cmd += " %.1f" % (warnlong) seed = self.controller.options.random_seed cmd += " --random-seed={}".format(seed) + environment = self.controller.options.environment + if environment != "sage.repl.ipython_kernel.all_jupyter": + cmd += f" --environment={environment}" cmd += " " + source.printpath return cmd From 36d6b097ab164189a244eb8169d2b8efb913972a Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 25 Nov 2021 18:39:34 -0800 Subject: [PATCH 126/126] pkgs/sagemath-categories/setup.cfg.m4: Add scripts --- pkgs/sagemath-categories/setup.cfg.m4 | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/pkgs/sagemath-categories/setup.cfg.m4 b/pkgs/sagemath-categories/setup.cfg.m4 index 70a7f204ef4..bad7e5ffd19 100644 --- a/pkgs/sagemath-categories/setup.cfg.m4 +++ b/pkgs/sagemath-categories/setup.cfg.m4 @@ -33,3 +33,15 @@ install_requires = gmpy2 \ cysignals \ | sed "2,\$s/^/ /;"')dnl + +scripts = + bin/sage + bin/sage-env + bin/sage-eval + bin/sage-fixdoctests + bin/sage-ipython + bin/sage-python + bin/sage-run + bin/sage-runtests + bin/sage-venv-config + bin/sage-version.sh