From b54a5c58932b1491a49f8121e678e2d86079a441 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 14 Jun 2023 18:15:05 -0700 Subject: [PATCH 01/11] src/sage/ext/fast_callable.pyx: Fall back to more general interpreter on ImportError --- src/sage/ext/fast_callable.pyx | 93 ++++++++++++++++++++++------------ 1 file changed, 62 insertions(+), 31 deletions(-) diff --git a/src/sage/ext/fast_callable.pyx b/src/sage/ext/fast_callable.pyx index d21bddd5deb..f45e8b31930 100644 --- a/src/sage/ext/fast_callable.pyx +++ b/src/sage/ext/fast_callable.pyx @@ -465,41 +465,72 @@ def fast_callable(x, domain=None, vars=None, etb = ExpressionTreeBuilder(vars=vars, domain=domain) et = x._fast_callable_(etb) - if isinstance(domain, sage.rings.abc.RealField): - from sage.ext.interpreters.wrapper_rr import Wrapper_rr as builder - str = InstructionStream(sage.ext.interpreters.wrapper_rr.metadata, - len(vars), - domain) - - elif isinstance(domain, sage.rings.abc.ComplexField): - from sage.ext.interpreters.wrapper_cc import Wrapper_cc as builder - str = InstructionStream(sage.ext.interpreters.wrapper_cc.metadata, - len(vars), - domain) - - elif isinstance(domain, sage.rings.abc.RealDoubleField) or domain is float: - from sage.ext.interpreters.wrapper_rdf import Wrapper_rdf as builder - str = InstructionStream(sage.ext.interpreters.wrapper_rdf.metadata, - len(vars), - domain) - elif isinstance(domain, sage.rings.abc.ComplexDoubleField): - from sage.ext.interpreters.wrapper_cdf import Wrapper_cdf as builder - str = InstructionStream(sage.ext.interpreters.wrapper_cdf.metadata, - len(vars), - domain) - elif domain is None: - from sage.ext.interpreters.wrapper_py import Wrapper_py as builder - str = InstructionStream(sage.ext.interpreters.wrapper_py.metadata, - len(vars)) - else: - from sage.ext.interpreters.wrapper_el import Wrapper_el as builder - str = InstructionStream(sage.ext.interpreters.wrapper_el.metadata, - len(vars), - domain) + builder, str = _builder_and_stream(vars=vars, domain=domain) + generate_code(et, str) str.instr('return') return builder(str.get_current()) + +def _builder_and_stream(vars, domain): + r""" + Return a builder and a stream. + + INPUT: + + - ``vars`` -- a sequence of variable names + + - ``domain`` -- a Sage parent or Python type or ``None``; if non-``None``, + all arithmetic is done in that domain + + OUTPUT: A :class:`Wrapper`, an class:`InstructionStream` + + EXAMPLES: + + sage: from sage.ext.fast_callable import _builder_and_stream + sage: _builder_and_stream(ZZ, ["x", "y"]) + + """ + if isinstance(domain, sage.rings.abc.RealField): + try: + from sage.ext.interpreters.wrapper_rr import metadata, Wrapper_rr as builder + except ImportError: + pass + else: + return builder, InstructionStream(metadata, len(vars), domain) + + if isinstance(domain, sage.rings.abc.ComplexField): + try: + from sage.ext.interpreters.wrapper_cc import metadata, Wrapper_cc as builder + except ImportError: + pass + else: + return builder, InstructionStream(metadata, len(vars), domain) + + if isinstance(domain, sage.rings.abc.RealDoubleField) or domain is float: + try: + from sage.ext.interpreters.wrapper_rdf import metadata, Wrapper_rdf as builder + except ImportError: + pass + else: + return builder, InstructionStream(metadata, len(vars), domain) + + if isinstance(domain, sage.rings.abc.ComplexDoubleField): + try: + from sage.ext.interpreters.wrapper_cdf import metadata, Wrapper_cdf as builder + except ImportError: + pass + else: + return builder, InstructionStream(metadata, len(vars), domain) + + if domain is None: + from sage.ext.interpreters.wrapper_py import metadata, Wrapper_py as builder + return builder, InstructionStream(metadata, len(vars)) + + from sage.ext.interpreters.wrapper_el import metadata, Wrapper_el as builder + return builder, InstructionStream(metadata, len(vars), domain) + + def function_name(fn): r""" Given a function, return a string giving a name for the function. From c5033e728d77767ce18f2f30731ee493e99b93b5 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 14 Jun 2023 18:15:49 -0700 Subject: [PATCH 02/11] src/sage_setup/autogen/interpreters/__init__.py: Support building a subset of interpreters --- .../autogen/interpreters/__init__.py | 35 +++++++++---------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/src/sage_setup/autogen/interpreters/__init__.py b/src/sage_setup/autogen/interpreters/__init__.py index c3534aeccf9..39f44169ed3 100644 --- a/src/sage_setup/autogen/interpreters/__init__.py +++ b/src/sage_setup/autogen/interpreters/__init__.py @@ -119,25 +119,10 @@ from .instructions import * from .memory import * from .specs.base import * -from .specs.cdf import * -from .specs.element import * -from .specs.python import * -from .specs.rdf import * -from .specs.rr import * -from .specs.cc import * from .storage import * from .utils import * -# Gather up a list of all interpreter classes imported into this module -# A better way might be to recursively iterate InterpreterSpec.__subclasses__ -# or to use a registry, but this is fine for now. -_INTERPRETERS = sorted(filter(lambda c: (isinstance(c, type) and - issubclass(c, InterpreterSpec) and - c.name), - globals().values()), - key=lambda c: c.name) - # Tuple of (filename_root, extension, method) where filename_root is the # root of the filename to be joined with "_".ext and # method is the name of a get_ method on InterpreterGenerator that returns @@ -174,7 +159,7 @@ def build_interp(interp_spec, dir): write_if_changed(path, method()) -def rebuild(dirname, force=False): +def rebuild(dirname, force=False, interpreters=None, distribution=None): r""" Check whether the interpreter and wrapper sources have been written since the last time this module was changed. If not, write them. @@ -194,6 +179,20 @@ def rebuild(dirname, force=False): # you run it). print("Building interpreters for fast_callable") + if interpreters is None: + interpreters = ['CDF', 'Element', 'Python', 'RDF', 'RR', 'CC'] + + from importlib import import_module + + _INTERPRETERS = [getattr(import_module('sage_setup.autogen.interpreters.specs.' + interpreter.lower()), + interpreter + 'Interpreter') + for interpreter in interpreters] + + if distribution is None: + all_py = 'all.py' + else: + all_py = f'all__{distribution.replace("-", "_")}.py' + try: os.makedirs(dirname) except OSError: @@ -213,7 +212,7 @@ class NeedToRebuild(Exception): try: if force: raise NeedToRebuild("-> Force rebuilding interpreters") - gen_file = os.path.join(dirname, 'all.py') + gen_file = os.path.join(dirname, all_py) if not os.path.isfile(gen_file): raise NeedToRebuild("-> First build of interpreters") @@ -235,5 +234,5 @@ class NeedToRebuild(Exception): for interp in _INTERPRETERS: build_interp(interp(), dirname) - with open(os.path.join(dirname, 'all.py'), 'w') as f: + with open(os.path.join(dirname, all_py), 'w') as f: f.write("# " + AUTOGEN_WARN) From 814e264b54f2898711782df6b222e7177d5c54c4 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 14 Jun 2023 22:28:09 -0700 Subject: [PATCH 03/11] sage_setup.autogen.interpreters: Update imports in doctests --- src/sage_setup/autogen/interpreters/__init__.py | 1 + src/sage_setup/autogen/interpreters/generator.py | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/src/sage_setup/autogen/interpreters/__init__.py b/src/sage_setup/autogen/interpreters/__init__.py index 39f44169ed3..20153a3dd19 100644 --- a/src/sage_setup/autogen/interpreters/__init__.py +++ b/src/sage_setup/autogen/interpreters/__init__.py @@ -142,6 +142,7 @@ def build_interp(interp_spec, dir): EXAMPLES:: sage: from sage_setup.autogen.interpreters import * + sage: from sage_setup.autogen.interpreters.specs.rdf import RDFInterpreter sage: testdir = tmp_dir() sage: rdf_interp = RDFInterpreter() sage: build_interp(rdf_interp, testdir) diff --git a/src/sage_setup/autogen/interpreters/generator.py b/src/sage_setup/autogen/interpreters/generator.py index f090f201afd..bec7cae2b47 100644 --- a/src/sage_setup/autogen/interpreters/generator.py +++ b/src/sage_setup/autogen/interpreters/generator.py @@ -43,6 +43,7 @@ def __init__(self, spec): EXAMPLES:: sage: from sage_setup.autogen.interpreters import * + sage: from sage_setup.autogen.interpreters.specs.rdf import RDFInterpreter sage: interp = RDFInterpreter() sage: gen = InterpreterGenerator(interp) sage: gen._spec is interp @@ -72,6 +73,7 @@ def gen_code(self, instr_desc, write): EXAMPLES:: sage: from sage_setup.autogen.interpreters import * + sage: from sage_setup.autogen.interpreters.specs.rdf import RDFInterpreter sage: interp = RDFInterpreter() sage: gen = InterpreterGenerator(interp) sage: from io import StringIO @@ -218,6 +220,7 @@ def func_header(self, cython=False): EXAMPLES:: sage: from sage_setup.autogen.interpreters import * + sage: from sage_setup.autogen.interpreters.specs.element import ElementInterpreter sage: interp = ElementInterpreter() sage: gen = InterpreterGenerator(interp) sage: print(gen.func_header()) @@ -260,6 +263,7 @@ def write_interpreter(self, write): EXAMPLES:: sage: from sage_setup.autogen.interpreters import * + sage: from sage_setup.autogen.interpreters.specs.rdf import RDFInterpreter sage: interp = RDFInterpreter() sage: gen = InterpreterGenerator(interp) sage: from io import StringIO @@ -307,6 +311,7 @@ def write_wrapper(self, write): EXAMPLES:: sage: from sage_setup.autogen.interpreters import * + sage: from sage_setup.autogen.interpreters.specs.rdf import RDFInterpreter sage: interp = RDFInterpreter() sage: gen = InterpreterGenerator(interp) sage: from io import StringIO @@ -476,6 +481,7 @@ def write_pxd(self, write): EXAMPLES:: sage: from sage_setup.autogen.interpreters import * + sage: from sage_setup.autogen.interpreters.specs.rdf import RDFInterpreter sage: interp = RDFInterpreter() sage: gen = InterpreterGenerator(interp) sage: from io import StringIO @@ -527,6 +533,9 @@ def get_interpreter(self): First we get the InterpreterSpec for several interpreters:: sage: from sage_setup.autogen.interpreters import * + sage: from sage_setup.autogen.interpreters.specs.rdf import RDFInterpreter + sage: from sage_setup.autogen.interpreters.specs.rr import RRInterpreter + sage: from sage_setup.autogen.interpreters.specs.element import ElementInterpreter sage: rdf_spec = RDFInterpreter() sage: rr_spec = RRInterpreter() sage: el_spec = ElementInterpreter() @@ -649,6 +658,9 @@ def get_wrapper(self): First we get the InterpreterSpec for several interpreters:: sage: from sage_setup.autogen.interpreters import * + sage: from sage_setup.autogen.interpreters.specs.rdf import RDFInterpreter + sage: from sage_setup.autogen.interpreters.specs.rr import RRInterpreter + sage: from sage_setup.autogen.interpreters.specs.element import ElementInterpreter sage: rdf_spec = RDFInterpreter() sage: rr_spec = RRInterpreter() sage: el_spec = ElementInterpreter() @@ -972,6 +984,9 @@ def get_pxd(self): First we get the InterpreterSpec for several interpreters:: sage: from sage_setup.autogen.interpreters import * + sage: from sage_setup.autogen.interpreters.specs.rdf import RDFInterpreter + sage: from sage_setup.autogen.interpreters.specs.rr import RRInterpreter + sage: from sage_setup.autogen.interpreters.specs.element import ElementInterpreter sage: rdf_spec = RDFInterpreter() sage: rr_spec = RRInterpreter() sage: el_spec = ElementInterpreter() From eb373b0eb8113b36e2f3ed15c791c2b530727a01 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 14 Jun 2023 22:28:25 -0700 Subject: [PATCH 04/11] src/sage/ext/fast_callable.pyx: Fix doctest --- src/sage/ext/fast_callable.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/ext/fast_callable.pyx b/src/sage/ext/fast_callable.pyx index f45e8b31930..7bcd783eaff 100644 --- a/src/sage/ext/fast_callable.pyx +++ b/src/sage/ext/fast_callable.pyx @@ -488,7 +488,7 @@ def _builder_and_stream(vars, domain): EXAMPLES: sage: from sage.ext.fast_callable import _builder_and_stream - sage: _builder_and_stream(ZZ, ["x", "y"]) + sage: _builder_and_stream(["x", "y"], ZZ) """ if isinstance(domain, sage.rings.abc.RealField): From 11c537225b06193934f730808e538ffd8095e0a4 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 15 Jun 2023 08:25:41 -0700 Subject: [PATCH 05/11] src/sage/ext/fast_callable.pyx: Fill in doctest output --- src/sage/ext/fast_callable.pyx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/sage/ext/fast_callable.pyx b/src/sage/ext/fast_callable.pyx index 7bcd783eaff..497a2262a2f 100644 --- a/src/sage/ext/fast_callable.pyx +++ b/src/sage/ext/fast_callable.pyx @@ -489,7 +489,8 @@ def _builder_and_stream(vars, domain): sage: from sage.ext.fast_callable import _builder_and_stream sage: _builder_and_stream(["x", "y"], ZZ) - + (, + ) """ if isinstance(domain, sage.rings.abc.RealField): try: From 15e869852d708bf25e6193c2d21b3afee97f3330 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 15 Jun 2023 08:40:16 -0700 Subject: [PATCH 06/11] src/sage_setup/autogen/interpreters: Add missing imports to doctests --- src/sage_setup/autogen/interpreters/instructions.py | 11 ++++++++++- src/sage_setup/autogen/interpreters/memory.py | 1 + src/sage_setup/autogen/interpreters/specs/base.py | 5 +++++ src/sage_setup/autogen/interpreters/specs/cc.py | 6 ++++++ src/sage_setup/autogen/interpreters/specs/cdf.py | 1 + src/sage_setup/autogen/interpreters/specs/element.py | 3 +++ src/sage_setup/autogen/interpreters/specs/python.py | 10 ++++++++++ src/sage_setup/autogen/interpreters/specs/rdf.py | 11 ++++++----- src/sage_setup/autogen/interpreters/specs/rr.py | 6 ++++++ 9 files changed, 48 insertions(+), 6 deletions(-) diff --git a/src/sage_setup/autogen/interpreters/instructions.py b/src/sage_setup/autogen/interpreters/instructions.py index d45a34e629a..116f598197c 100644 --- a/src/sage_setup/autogen/interpreters/instructions.py +++ b/src/sage_setup/autogen/interpreters/instructions.py @@ -187,6 +187,7 @@ class InstrSpec(object): EXAMPLES:: sage: from sage_setup.autogen.interpreters import * + sage: from sage_setup.autogen.interpreters.specs.rdf import RDFInterpreter sage: pg = RDFInterpreter().pg sage: InstrSpec('add', pg('SS','S'), code='o0 = i0+i1;') add: SS->S = 'o0 = i0+i1;' @@ -213,7 +214,7 @@ def __init__(self, name, io, code=None, uses_error_handler=False, EXAMPLES:: sage: from sage_setup.autogen.interpreters import * - + sage: from sage_setup.autogen.interpreters.specs.rdf import RDFInterpreter sage: pg = RDFInterpreter().pg sage: InstrSpec('add', pg('SS','S'), code='o0 = i0+i1;') add: SS->S = 'o0 = i0+i1;' @@ -288,6 +289,7 @@ def __repr__(self): EXAMPLES:: sage: from sage_setup.autogen.interpreters import * + sage: from sage_setup.autogen.interpreters.specs.rdf import RDFInterpreter sage: pg = RDFInterpreter().pg sage: InstrSpec('add', pg('SS','S'), code='o0 = i0+i1;') add: SS->S = 'o0 = i0+i1;' @@ -310,6 +312,7 @@ def instr_infix(name, io, op): EXAMPLES:: sage: from sage_setup.autogen.interpreters import * + sage: from sage_setup.autogen.interpreters.specs.rdf import RDFInterpreter sage: pg = RDFInterpreter().pg sage: instr_infix('mul', pg('SS', 'S'), '*') mul: SS->S = 'o0 = i0 * i1;' @@ -325,6 +328,7 @@ def instr_funcall_2args(name, io, op): EXAMPLES:: sage: from sage_setup.autogen.interpreters import * + sage: from sage_setup.autogen.interpreters.specs.rdf import RDFInterpreter sage: pg = RDFInterpreter().pg sage: instr_funcall_2args('atan2', pg('SS', 'S'), 'atan2') atan2: SS->S = 'o0 = atan2(i0, i1);' @@ -340,6 +344,7 @@ def instr_unary(name, io, op): EXAMPLES:: sage: from sage_setup.autogen.interpreters import * + sage: from sage_setup.autogen.interpreters.specs.rdf import RDFInterpreter sage: pg = RDFInterpreter().pg sage: instr_unary('sin', pg('S','S'), 'sin(i0)') sin: S->S = 'o0 = sin(i0);' @@ -357,6 +362,7 @@ def instr_funcall_2args_mpfr(name, io, op): EXAMPLES:: sage: from sage_setup.autogen.interpreters import * + sage: from sage_setup.autogen.interpreters.specs.rr import RRInterpreter sage: pg = RRInterpreter().pg sage: instr_funcall_2args_mpfr('add', pg('SS','S'), 'mpfr_add') add: SS->S = 'mpfr_add(o0, i0, i1, MPFR_RNDN);' @@ -372,6 +378,7 @@ def instr_funcall_1arg_mpfr(name, io, op): EXAMPLES:: sage: from sage_setup.autogen.interpreters import * + sage: from sage_setup.autogen.interpreters.specs.rr import RRInterpreter sage: pg = RRInterpreter().pg sage: instr_funcall_1arg_mpfr('exp', pg('S','S'), 'mpfr_exp') exp: S->S = 'mpfr_exp(o0, i0, MPFR_RNDN);' @@ -386,6 +393,7 @@ def instr_funcall_2args_mpc(name, io, op): EXAMPLES:: sage: from sage_setup.autogen.interpreters import * + sage: from sage_setup.autogen.interpreters.specs.cc import CCInterpreter sage: pg = CCInterpreter().pg sage: instr_funcall_2args_mpc('add', pg('SS','S'), 'mpc_add') add: SS->S = 'mpc_add(o0, i0, i1, MPC_RNDNN);' @@ -400,6 +408,7 @@ def instr_funcall_1arg_mpc(name, io, op): EXAMPLES:: sage: from sage_setup.autogen.interpreters import * + sage: from sage_setup.autogen.interpreters.specs.cc import CCInterpreter sage: pg = CCInterpreter().pg sage: instr_funcall_1arg_mpc('exp', pg('S','S'), 'mpc_exp') exp: S->S = 'mpc_exp(o0, i0, MPC_RNDNN);' diff --git a/src/sage_setup/autogen/interpreters/memory.py b/src/sage_setup/autogen/interpreters/memory.py index be6ec531722..e719f47d77a 100644 --- a/src/sage_setup/autogen/interpreters/memory.py +++ b/src/sage_setup/autogen/interpreters/memory.py @@ -172,6 +172,7 @@ class using this memory chunk, to allocate local variables. EXAMPLES:: sage: from sage_setup.autogen.interpreters import * + sage: from sage_setup.autogen.interpreters.specs.rr import * sage: mc = MemoryChunkRRRetval('retval', ty_mpfr) sage: mc.declare_call_locals() ' cdef RealNumber retval = (self.domain)()\n' diff --git a/src/sage_setup/autogen/interpreters/specs/base.py b/src/sage_setup/autogen/interpreters/specs/base.py index 67d75b9bf45..b8c22ae65dd 100644 --- a/src/sage_setup/autogen/interpreters/specs/base.py +++ b/src/sage_setup/autogen/interpreters/specs/base.py @@ -49,6 +49,7 @@ def __init__(self): EXAMPLES:: sage: from sage_setup.autogen.interpreters import * + sage: from sage_setup.autogen.interpreters.specs.rdf import RDFInterpreter sage: interp = RDFInterpreter() sage: interp.c_header '#include ' @@ -84,6 +85,7 @@ def _set_opcodes(self): EXAMPLES:: sage: from sage_setup.autogen.interpreters import * + sage: from sage_setup.autogen.interpreters.specs.rdf import RDFInterpreter sage: interp = RDFInterpreter() sage: interp.instr_descs[5].opcode 5 @@ -128,6 +130,9 @@ def __init__(self, type, mc_retval=None): EXAMPLES:: sage: from sage_setup.autogen.interpreters import * + sage: from sage_setup.autogen.interpreters.specs.rdf import RDFInterpreter + sage: from sage_setup.autogen.interpreters.specs.rr import RRInterpreter + sage: from sage_setup.autogen.interpreters.specs.element import ElementInterpreter sage: rdf = RDFInterpreter() sage: rr = RRInterpreter() sage: el = ElementInterpreter() diff --git a/src/sage_setup/autogen/interpreters/specs/cc.py b/src/sage_setup/autogen/interpreters/specs/cc.py index aa0db45bad1..ea5e8708647 100644 --- a/src/sage_setup/autogen/interpreters/specs/cc.py +++ b/src/sage_setup/autogen/interpreters/specs/cc.py @@ -31,6 +31,7 @@ def declare_class_members(self): EXAMPLES:: sage: from sage_setup.autogen.interpreters import * + sage: from sage_setup.autogen.interpreters.specs.cc import * sage: mc = MemoryChunkCCRetval('retval', ty_mpc) sage: mc.declare_class_members() '' @@ -45,6 +46,7 @@ class using this memory chunk, to allocate local variables. EXAMPLES:: sage: from sage_setup.autogen.interpreters import * + sage: from sage_setup.autogen.interpreters.specs.cc import * sage: mc = MemoryChunkCCRetval('retval', ty_mpc) sage: mc.declare_call_locals() ' cdef ComplexNumber retval = (self.domain_element._new())\n' @@ -62,6 +64,7 @@ def declare_parameter(self): EXAMPLES:: sage: from sage_setup.autogen.interpreters import * + sage: from sage_setup.autogen.interpreters.specs.cc import * sage: mc = MemoryChunkCCRetval('retval', ty_mpc) sage: mc.declare_parameter() 'mpc_t retval' @@ -76,6 +79,7 @@ def pass_argument(self): EXAMPLES:: sage: from sage_setup.autogen.interpreters import * + sage: from sage_setup.autogen.interpreters.specs.cc import * sage: mc = MemoryChunkCCRetval('retval', ty_mpc) sage: mc.pass_argument() '((retval.__re))' @@ -90,6 +94,7 @@ def pass_call_c_argument(self): EXAMPLES:: sage: from sage_setup.autogen.interpreters import * + sage: from sage_setup.autogen.interpreters.specs.cc import * sage: mc = MemoryChunkCCRetval('retval', ty_mpc) sage: mc.pass_call_c_argument() 'result' @@ -111,6 +116,7 @@ def __init__(self): EXAMPLES:: sage: from sage_setup.autogen.interpreters import * + sage: from sage_setup.autogen.interpreters.specs.cc import * sage: interp = CCInterpreter() sage: interp.name 'cc' diff --git a/src/sage_setup/autogen/interpreters/specs/cdf.py b/src/sage_setup/autogen/interpreters/specs/cdf.py index 7f09c3b6a5c..137487e1de2 100644 --- a/src/sage_setup/autogen/interpreters/specs/cdf.py +++ b/src/sage_setup/autogen/interpreters/specs/cdf.py @@ -34,6 +34,7 @@ def __init__(self): EXAMPLES:: sage: from sage_setup.autogen.interpreters import * + sage: from sage_setup.autogen.interpreters.specs.cdf import * sage: interp = CDFInterpreter() sage: interp.name 'cdf' diff --git a/src/sage_setup/autogen/interpreters/specs/element.py b/src/sage_setup/autogen/interpreters/specs/element.py index 3e4e4eca04f..bbb9c21ae57 100644 --- a/src/sage_setup/autogen/interpreters/specs/element.py +++ b/src/sage_setup/autogen/interpreters/specs/element.py @@ -38,6 +38,7 @@ def setup_args(self): EXAMPLES:: sage: from sage_setup.autogen.interpreters import * + sage: from sage_setup.autogen.interpreters.specs.element import * sage: mc = MemoryChunkElementArguments('args', ty_python) sage: mc.setup_args() 'mapped_args = [self._domain(a) for a in args]\n' @@ -51,6 +52,7 @@ def pass_argument(self): EXAMPLES:: sage: from sage_setup.autogen.interpreters import * + sage: from sage_setup.autogen.interpreters.specs.element import * sage: mc = MemoryChunkElementArguments('args', ty_python) sage: mc.pass_argument() '(mapped_args).ob_item' @@ -80,6 +82,7 @@ def __init__(self): EXAMPLES:: sage: from sage_setup.autogen.interpreters import * + sage: from sage_setup.autogen.interpreters.specs.element import * sage: interp = ElementInterpreter() sage: interp.name 'el' diff --git a/src/sage_setup/autogen/interpreters/specs/python.py b/src/sage_setup/autogen/interpreters/specs/python.py index eb4eee56b68..86d0d95f827 100644 --- a/src/sage_setup/autogen/interpreters/specs/python.py +++ b/src/sage_setup/autogen/interpreters/specs/python.py @@ -32,6 +32,7 @@ def declare_class_members(self): EXAMPLES:: sage: from sage_setup.autogen.interpreters import * + sage: from sage_setup.autogen.interpreters.specs.python import * sage: mc = MemoryChunkPythonArguments('args', ty_python) """ return " cdef int _n_%s\n" % self.name @@ -45,6 +46,7 @@ class members. EXAMPLES:: sage: from sage_setup.autogen.interpreters import * + sage: from sage_setup.autogen.interpreters.specs.python import * sage: mc = MemoryChunkPythonArguments('args', ty_python) sage: mc.init_class_members() " count = args['args']\n self._n_args = count\n" @@ -62,6 +64,7 @@ def setup_args(self): EXAMPLES:: sage: from sage_setup.autogen.interpreters import * + sage: from sage_setup.autogen.interpreters.specs.python import * sage: mc = MemoryChunkPythonArguments('args', ty_python) sage: mc.setup_args() '' @@ -75,6 +78,7 @@ def pass_argument(self): EXAMPLES:: sage: from sage_setup.autogen.interpreters import * + sage: from sage_setup.autogen.interpreters.specs.python import * sage: mc = MemoryChunkPythonArguments('args', ty_python) sage: mc.pass_argument() '(args).ob_item' @@ -97,6 +101,7 @@ def __init__(self, name): EXAMPLES:: sage: from sage_setup.autogen.interpreters import * + sage: from sage_setup.autogen.interpreters.specs.python import * sage: mc = MemoryChunkPyConstant('domain') sage: mc.name 'domain' @@ -113,6 +118,7 @@ def declare_class_members(self): EXAMPLES:: sage: from sage_setup.autogen.interpreters import * + sage: from sage_setup.autogen.interpreters.specs.python import * sage: mc = MemoryChunkPyConstant('domain') sage: mc.declare_class_members() ' cdef object _domain\n' @@ -131,6 +137,7 @@ class members. EXAMPLES:: sage: from sage_setup.autogen.interpreters import * + sage: from sage_setup.autogen.interpreters.specs.python import * sage: mc = MemoryChunkPyConstant('domain') sage: mc.init_class_members() " self._domain = args['domain']\n" @@ -148,6 +155,7 @@ def declare_parameter(self): EXAMPLES:: sage: from sage_setup.autogen.interpreters import * + sage: from sage_setup.autogen.interpreters.specs.python import * sage: mc = MemoryChunkPyConstant('domain') sage: mc.declare_parameter() 'PyObject* domain' @@ -162,6 +170,7 @@ def pass_argument(self): EXAMPLES:: sage: from sage_setup.autogen.interpreters import * + sage: from sage_setup.autogen.interpreters.specs.python import * sage: mc = MemoryChunkPyConstant('domain') sage: mc.pass_argument() 'self._domain' @@ -204,6 +213,7 @@ def __init__(self): EXAMPLES:: sage: from sage_setup.autogen.interpreters import * + sage: from sage_setup.autogen.interpreters.specs.python import * sage: interp = PythonInterpreter() sage: interp.name 'py' diff --git a/src/sage_setup/autogen/interpreters/specs/rdf.py b/src/sage_setup/autogen/interpreters/specs/rdf.py index 6f576844d13..367c4cf2c2e 100644 --- a/src/sage_setup/autogen/interpreters/specs/rdf.py +++ b/src/sage_setup/autogen/interpreters/specs/rdf.py @@ -37,6 +37,7 @@ def __init__(self): EXAMPLES:: sage: from sage_setup.autogen.interpreters import * + sage: from sage_setup.autogen.interpreters.specs.rdf import * sage: interp = RDFInterpreter() sage: interp.name 'rdf' @@ -60,14 +61,14 @@ def __init__(self): Make sure that pow behaves reasonably:: - sage: var('x,y') + sage: var('x,y') # optional - sage.symbolic (x, y) - sage: ff = fast_callable(x^y, vars=[x,y], domain=RDF) - sage: ff(1.5, 3) + sage: ff = fast_callable(x^y, vars=[x,y], domain=RDF) # optional - sage.symbolic + sage: ff(1.5, 3) # optional - sage.symbolic 3.375 - sage: ff(-2, 3) + sage: ff(-2, 3) # optional - sage.symbolic -8.0 - sage: ff(-2, 1/3) + sage: ff(-2, 1/3) # optional - sage.symbolic Traceback (most recent call last): ... ValueError: negative number to a fractional power not real diff --git a/src/sage_setup/autogen/interpreters/specs/rr.py b/src/sage_setup/autogen/interpreters/specs/rr.py index d59e1c2bf8e..264b694dfab 100644 --- a/src/sage_setup/autogen/interpreters/specs/rr.py +++ b/src/sage_setup/autogen/interpreters/specs/rr.py @@ -31,6 +31,7 @@ def declare_class_members(self): EXAMPLES:: sage: from sage_setup.autogen.interpreters import * + sage: from sage_setup.autogen.interpreters.specs.rr import * sage: mc = MemoryChunkRRRetval('retval', ty_mpfr) sage: mc.declare_class_members() '' @@ -45,6 +46,7 @@ class using this memory chunk, to allocate local variables. EXAMPLES:: sage: from sage_setup.autogen.interpreters import * + sage: from sage_setup.autogen.interpreters.specs.rr import * sage: mc = MemoryChunkRRRetval('retval', ty_mpfr) sage: mc.declare_call_locals() ' cdef RealNumber retval = (self.domain)()\n' @@ -62,6 +64,7 @@ def declare_parameter(self): EXAMPLES:: sage: from sage_setup.autogen.interpreters import * + sage: from sage_setup.autogen.interpreters.specs.rr import * sage: mc = MemoryChunkRRRetval('retval', ty_mpfr) sage: mc.declare_parameter() 'mpfr_t retval' @@ -76,6 +79,7 @@ def pass_argument(self): EXAMPLES:: sage: from sage_setup.autogen.interpreters import * + sage: from sage_setup.autogen.interpreters.specs.rr import * sage: mc = MemoryChunkRRRetval('retval', ty_mpfr) sage: mc.pass_argument() 'retval.value' @@ -90,6 +94,7 @@ def pass_call_c_argument(self): EXAMPLES:: sage: from sage_setup.autogen.interpreters import * + sage: from sage_setup.autogen.interpreters.specs.rr import * sage: mc = MemoryChunkRRRetval('retval', ty_mpfr) sage: mc.pass_call_c_argument() 'result' @@ -112,6 +117,7 @@ def __init__(self): EXAMPLES:: sage: from sage_setup.autogen.interpreters import * + sage: from sage_setup.autogen.interpreters.specs.rr import * sage: interp = RRInterpreter() sage: interp.name 'rr' From 210f27b796891b30e7341490f1f18eb4bb19978c Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 15 Jun 2023 12:20:06 -0700 Subject: [PATCH 07/11] src/sage_setup/autogen/interpreters: Add another missing imports to doctests --- src/sage_setup/autogen/interpreters/specs/base.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sage_setup/autogen/interpreters/specs/base.py b/src/sage_setup/autogen/interpreters/specs/base.py index b8c22ae65dd..c020c37cdb3 100644 --- a/src/sage_setup/autogen/interpreters/specs/base.py +++ b/src/sage_setup/autogen/interpreters/specs/base.py @@ -50,6 +50,7 @@ def __init__(self): sage: from sage_setup.autogen.interpreters import * sage: from sage_setup.autogen.interpreters.specs.rdf import RDFInterpreter + sage: from sage_setup.autogen.interpreters.specs.rr import RRInterpreter sage: interp = RDFInterpreter() sage: interp.c_header '#include ' From 12c04b899ff90a0739b7b59456c7815026426aaf Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 18 Jun 2023 15:50:17 -0700 Subject: [PATCH 08/11] src/sage_setup/autogen/interpreters/__init__.py: Add doc and test --- .../autogen/interpreters/__init__.py | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/src/sage_setup/autogen/interpreters/__init__.py b/src/sage_setup/autogen/interpreters/__init__.py index 20153a3dd19..13b50e41d8c 100644 --- a/src/sage_setup/autogen/interpreters/__init__.py +++ b/src/sage_setup/autogen/interpreters/__init__.py @@ -165,7 +165,23 @@ def rebuild(dirname, force=False, interpreters=None, distribution=None): Check whether the interpreter and wrapper sources have been written since the last time this module was changed. If not, write them. - EXAMPLES:: + INPUT: + + - ``dirname`` -- name of the target directory for the generated sources + + - ``force`` -- boolean (default ``False``); if ``True``, ignore timestamps + and regenerate the sources unconditionally + + - ``interpreters`` -- an iterable of strings, or ``None`` (the default, + which means all interpreters); which interpreters to generate + + - ``distribution`` -- a string (the distribution name such as + ``"sagemath-categories"``) or ``None`` (the default, which means + the monolithic Sage library) + + EXAMPLES: + + Monolithic build:: sage: from sage_setup.autogen.interpreters import * sage: testdir = tmp_dir() @@ -175,6 +191,17 @@ def rebuild(dirname, force=False, interpreters=None, distribution=None): sage: with open(testdir + '/wrapper_el.pyx') as f: ....: f.readline() '# Automatically generated by ...\n' + + Modularized build:: + + sage: testdir = tmp_dir() + sage: rebuild(testdir, interpreters=['Element', 'Python'], + ....: distribution='sagemath-categories') + Building interpreters for fast_callable + -> First build of interpreters + sage: with open(testdir + '/all__sagemath_categories.py') as f: + ....: f.readline() + '# Automatically generated by ...\n' """ # This line will show up in "sage -b" (once per upgrade, not every time # you run it). From afd3be66e4da91bf1fcac046e48cac29386721ea Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 18 Jun 2023 16:04:48 -0700 Subject: [PATCH 09/11] src/sage/ext/fast_callable.pyx: Add tests --- src/sage/ext/fast_callable.pyx | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/sage/ext/fast_callable.pyx b/src/sage/ext/fast_callable.pyx index 497a2262a2f..8719f0bdeb9 100644 --- a/src/sage/ext/fast_callable.pyx +++ b/src/sage/ext/fast_callable.pyx @@ -476,6 +476,8 @@ def _builder_and_stream(vars, domain): r""" Return a builder and a stream. + This is an internal function used only once, by :func:`fast_callable`. + INPUT: - ``vars`` -- a sequence of variable names @@ -485,12 +487,26 @@ def _builder_and_stream(vars, domain): OUTPUT: A :class:`Wrapper`, an class:`InstructionStream` - EXAMPLES: + EXAMPLES:: sage: from sage.ext.fast_callable import _builder_and_stream sage: _builder_and_stream(["x", "y"], ZZ) (, ) + sage: _builder_and_stream(["x", "y"], RR) # optional - sage.rings.real_mpfr + (, + ) + + Modularized test with sagemath-categories after :issue:`35095`, which has + (a basic version of) ``RDF`` but not the specialized interpreter for it. + In this case, the function falls back to using the :class:`Element` + interpreter:: + + sage: domain = RDF + sage: from sage.structure.element import Element as domain # optional - sage.modules + sage: _builder_and_stream(["x", "y"], domain) + (, + ) """ if isinstance(domain, sage.rings.abc.RealField): try: From d5812e485ae7a8fc6f37d07dec25c67f1e8f1e01 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 18 Jun 2023 20:14:05 -0700 Subject: [PATCH 10/11] src/sage_setup/autogen/interpreters/__init__.py: Fix doctest --- src/sage_setup/autogen/interpreters/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage_setup/autogen/interpreters/__init__.py b/src/sage_setup/autogen/interpreters/__init__.py index 13b50e41d8c..75096d06b80 100644 --- a/src/sage_setup/autogen/interpreters/__init__.py +++ b/src/sage_setup/autogen/interpreters/__init__.py @@ -201,7 +201,7 @@ def rebuild(dirname, force=False, interpreters=None, distribution=None): -> First build of interpreters sage: with open(testdir + '/all__sagemath_categories.py') as f: ....: f.readline() - '# Automatically generated by ...\n' + '# Automatically generated by ...' """ # This line will show up in "sage -b" (once per upgrade, not every time # you run it). From 97135ad4b196272997896f86e8b5d4dd631c278b Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 19 Jun 2023 08:20:54 -0700 Subject: [PATCH 11/11] src/sage_setup/autogen/interpreters/specs/rdf.py: Avoid gratuitous use of symbolics in doctest --- src/sage_setup/autogen/interpreters/specs/rdf.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/sage_setup/autogen/interpreters/specs/rdf.py b/src/sage_setup/autogen/interpreters/specs/rdf.py index 367c4cf2c2e..95894f8d6d2 100644 --- a/src/sage_setup/autogen/interpreters/specs/rdf.py +++ b/src/sage_setup/autogen/interpreters/specs/rdf.py @@ -61,14 +61,16 @@ def __init__(self): Make sure that pow behaves reasonably:: - sage: var('x,y') # optional - sage.symbolic - (x, y) - sage: ff = fast_callable(x^y, vars=[x,y], domain=RDF) # optional - sage.symbolic - sage: ff(1.5, 3) # optional - sage.symbolic + sage: from sage.ext.fast_callable import ExpressionTreeBuilder + sage: etb = ExpressionTreeBuilder(vars=('x','y')) + sage: x = etb.var('x') + sage: y = etb.var('y') + sage: ff = fast_callable(x^y, domain=RDF) + sage: ff(1.5, 3) 3.375 - sage: ff(-2, 3) # optional - sage.symbolic + sage: ff(-2, 3) -8.0 - sage: ff(-2, 1/3) # optional - sage.symbolic + sage: ff(-2, 1/3) Traceback (most recent call last): ... ValueError: negative number to a fractional power not real