"""
Workflow:
1. If a new array context is implemented, it should be added to
:func:`initialize_contexts`.
2. If a new function is implemented, it should be added to the
corresponding ``write_section_name`` function.
3. Once everything is added, regenerate the tables using
.. code::
python make_numpy_support_table.py numpy_coverage.rst
"""
from __future__ import annotations
import pathlib
from mako.template import Template
import arraycontext
# {{{ templating
HEADER = """
.. raw:: html
.. role:: red
.. role:: green
"""
TABLE_TEMPLATE = Template("""
${title}
${'~' * len(title)}
.. list-table::
:header-rows: 1
* - Function
% for ctx in contexts:
- :class:`~arraycontext.${type(ctx).__name__}`
% endfor
% for name, (directive, in_context) in numpy_functions_for_context.items():
* - :${directive}:`numpy.${name}`
% for ctx in contexts:
<%
flag = in_context.get(type(ctx), "yes").capitalize()
color = "green" if flag == "Yes" else "red"
%> - :${color}:`${flag}`
% endfor
% endfor
""")
def initialize_contexts():
import pyopencl as cl
ctx = cl.create_some_context()
queue = cl.CommandQueue(ctx)
return [
arraycontext.PyOpenCLArrayContext(queue, force_device_scalars=True),
arraycontext.EagerJAXArrayContext(),
arraycontext.PytatoPyOpenCLArrayContext(queue),
arraycontext.PytatoJAXArrayContext(),
]
def build_supported_functions(funcs, contexts):
import numpy as np
numpy_functions_for_context = {}
for directive, name in funcs:
if not hasattr(np, name):
raise ValueError(f"'{name}' not found in numpy namespace")
in_context = {}
for ctx in contexts:
try:
_ = getattr(ctx.np, name)
except AttributeError:
in_context[type(ctx)] = "No"
numpy_functions_for_context[name] = (directive, in_context)
return numpy_functions_for_context
# }}}
# {{{ writing
def write_array_creation_routines(outf, contexts):
# https://numpy.org/doc/stable/reference/routines.array-creation.html
funcs = (
# (sphinx-directive, name)
("func", "empty_like"),
("func", "ones_like"),
("func", "zeros_like"),
("func", "full_like"),
("func", "copy"),
)
r = TABLE_TEMPLATE.render(
title="Array creation routines",
contexts=contexts,
numpy_functions_for_context=build_supported_functions(funcs, contexts),
)
outf.write(r)
def write_array_manipulation_routines(outf, contexts):
# https://numpy.org/doc/stable/reference/routines.array-manipulation.html
funcs = (
# (sphinx-directive, name)
("func", "reshape"),
("func", "ravel"),
("func", "transpose"),
("func", "broadcast_to"),
("func", "concatenate"),
("func", "stack"),
)
r = TABLE_TEMPLATE.render(
title="Array manipulation routines",
contexts=contexts,
numpy_functions_for_context=build_supported_functions(funcs, contexts),
)
outf.write(r)
def write_linear_algebra(outf, contexts):
# https://numpy.org/doc/stable/reference/routines.linalg.html
funcs = (
# (sphinx-directive, name)
("func", "vdot"),
)
r = TABLE_TEMPLATE.render(
title="Linear algebra",
contexts=contexts,
numpy_functions_for_context=build_supported_functions(funcs, contexts),
)
outf.write(r)
def write_logic_functions(outf, contexts):
# https://numpy.org/doc/stable/reference/routines.logic.html
funcs = (
# (sphinx-directive, name)
("func", "all"),
("func", "any"),
("data", "greater"),
("data", "greater_equal"),
("data", "less"),
("data", "less_equal"),
("data", "equal"),
("data", "not_equal"),
)
r = TABLE_TEMPLATE.render(
title="Logic Functions",
contexts=contexts,
numpy_functions_for_context=build_supported_functions(funcs, contexts),
)
outf.write(r)
def write_mathematical_functions(outf, contexts):
# https://numpy.org/doc/stable/reference/routines.math.html
funcs = (
("data", "sin"),
("data", "cos"),
("data", "tan"),
("data", "arcsin"),
("data", "arccos"),
("data", "arctan"),
("data", "arctan2"),
("data", "sinh"),
("data", "cosh"),
("data", "tanh"),
("data", "floor"),
("data", "ceil"),
("func", "sum"),
("data", "exp"),
("data", "log"),
("data", "log10"),
("func", "real"),
("func", "imag"),
("data", "conjugate"),
("data", "maximum"),
("func", "amax"),
("data", "minimum"),
("func", "amin"),
("data", "sqrt"),
("data", "absolute"),
("data", "fabs"),
)
r = TABLE_TEMPLATE.render(
title="Mathematical functions",
contexts=contexts,
numpy_functions_for_context=build_supported_functions(funcs, contexts),
)
outf.write(r)
def write_searching_sorting_and_counting(outf, contexts):
# https://numpy.org/doc/stable/reference/routines.sort.html
funcs = (
("func", "where"),
)
r = TABLE_TEMPLATE.render(
title="Sorting, searching, and counting",
contexts=contexts,
numpy_functions_for_context=build_supported_functions(funcs, contexts),
)
outf.write(r)
# }}}
if __name__ == "__main__":
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("filename", nargs="?", type=pathlib.Path, default=None)
args = parser.parse_args()
import sys
if args.filename is not None:
outf = open(args.filename, "w")
else:
outf = sys.stdout
ctxs = initialize_contexts()
outf.write(HEADER)
write_array_creation_routines(outf, ctxs)
write_array_manipulation_routines(outf, ctxs)
write_linear_algebra(outf, ctxs)
write_logic_functions(outf, ctxs)
write_mathematical_functions(outf, ctxs)
if args.filename is not None:
outf.close()