Annotations (APIARY_* macros)¶
Note
Generated from the C++ headers by apiary --emit-cpp-docs-json.
-
APIARY_BUFFER_FROM(...)¶
Designate a free function (or static member) that takes the bound type and returns
py::buffer_infodescribing its memory layout.The codegen wraps the call in a
.def_buffer([](T &self) { return helper(self); })lambda. The helper is your responsibility — it has to know the concrete instantiation’s element type, rank, and stride representation, and produce a valid buffer_info.namespace einsums::pybuf { template <typename T, size_t N, typename A> pybind11::buffer_info make(GeneralTensor<T, N, A> &t); } APIARY_BUFFER_PROTOCOL APIARY_BUFFER_FROM(einsums::pybuf::make) struct GeneralTensor { ... };Note
pybind11 only, since the helper is written against pybind11’s API; under nanobind it is refused with the
unsupported-on-targetdiagnostic. Prefer APIARY_BUFFER_PROTOCOL_STD, which works under both.- Parameters:
... – the helper function name
-
APIARY_BUFFER_PROTOCOL¶
Enable the pybind11 buffer protocol for this class (required for NumPy zero-copy interop on tensor types).
Note
Implied by APIARY_BUFFER_FROM and APIARY_BUFFER_PROTOCOL_STD, which are what actually export a buffer; on its own it only flips the pybind11 class option, and under nanobind it does nothing.
-
APIARY_BUFFER_PROTOCOL_STD(...)¶
Standard-layout buffer protocol. The codegen emits a per-backend buffer exporter (a .def_buffer lambda under pybind11, a bf_getbuffer type slot under nanobind) that describes the object’s memory from the named member functions on the bound class. Either way memoryview(), numpy.asarray() and numpy.array() see the memory zero copy, and it implies APIARY_BUFFER_PROTOCOL.
All four method names are required.
element_typenames the class template parameter that gives the element type; the codegen substitutes it per instantiation when emitting the format string and sizeof().template <typename T, typename Alloc> APIARY_EXPOSE APIARY_BUFFER_PROTOCOL_STD( data = data, rank = rank, dim = dim, stride = stride, element_type = T) struct GeneralRuntimeTensor { ... };The named methods must satisfy:
T* data();// pointer to first elementsize_t rank() const;size_t dim(int) const;// dim along an axissize_t stride(int) const;// stride in element units
Note
Stride conversion to byte units happens inside the codegen lambda.
- Parameters:
... –
key = valueassignments naming data, rank, dim, stride, and element_type
-
APIARY_DETAIL_ANNOTATE(payload)¶
Expand a payload to a Clang annotate attribute; a no-op on non-Clang compilers.
- Parameters:
payload – string literal payload appended after the
apiary:prefix
-
APIARY_DOC(text)¶
Override the docstring extracted from the doxygen comment block above this declaration.
- Parameters:
text – string literal docstring to use instead
-
APIARY_DYNAMIC_ATTR¶
Allow Python instances to carry arbitrary attributes (py::dynamic_attr()).
-
APIARY_EXCEPTION¶
Mark a class as a Python exception type rather than a regular bound class.
The codegen emits
py::register_exception<T>(m, "name")(pybind11) ornb::exception<T>(m, "name")(nanobind) instead of a class_<T>. Both need only awhat()returning the message.class APIARY_EXPOSE APIARY_EXCEPTION TensorError : public std::exception { ... };Subsequent
raise einsums.TensorError(...)from Python (orthrow einsums::TensorError("...")from C++) crosses the boundary cleanly.
-
APIARY_EXPOSE¶
Mark a declaration for binding. Without this, the codegen tool ignores it.
-
APIARY_GETTER(py_name)¶
Bind a method as the getter of a Python property.
- Parameters:
py_name – string literal naming the Python property
-
APIARY_HIDE¶
Suppress binding for a declaration that would otherwise be exposed.
Note
For example, an inherited member from a base flagged APIARY_EXPOSE.
-
APIARY_HOLDER(...)¶
Override the pybind11 holder type. Default is std::unique_ptr.
Note
Under nanobind,
std::shared_ptrandstd::unique_ptrneed no holder (its smart-pointer casters work for any bound class), and any other holder is refused with theunsupported-on-targetdiagnostic.- Parameters:
... – the holder type, e.g.
APIARY_HOLDER(std::shared_ptr)
-
APIARY_IMPLICIT_FROM(...)¶
Register a one-way implicit conversion from
Sourceto the annotated class.Emits
py::implicitly_convertible<Source, Class>()after the class definition. Useful for ergonomic factory ctors:APIARY_EXPOSE APIARY_IMPLICIT_FROM(int) class Tensor { Tensor(int n); ... }; // can call Python f(t=42)- Parameters:
... – the source type to convert from
-
APIARY_INDEX_PROTOCOL_STD(...)¶
Standard index protocol — scalar reads/writes via __getitem__/__setitem__.
The codegen emits per-backend lambdas dispatching on Python type (int, tuple, slice, Ellipsis), normalizing negative indices, bounds-checking, and calling the user’s pure-C++ helpers.
element_type — the class template parameter naming the scalar type rank — member function returning the tensor’s runtime rank dim — member function (size_t i) → size_t (axis size) at_element — T (std::vector<int64_t> const &idx) const set_element — void(std::vector<int64_t> const &idx, T value)
Optional, for slicing to views:
at_view — ViewType(std::vector<SliceSpec> const &specs) const view_type — the bound type at_view returns slice_spec — the SliceSpec type at_view takes; default einsums::SliceSpec. Any struct with its members works: an enum
KindofIndex,RangeandFull,kind, and int64index,start,stopandstep.template <typename T, typename Alloc> APIARY_EXPOSE APIARY_INDEX_PROTOCOL_STD( element_type = T, rank = rank, dim = dim, at_element = at_element, set_element = set_element) struct GeneralRuntimeTensor { T at_element(std::vector<int64_t> const &) const; void set_element(std::vector<int64_t> const &, T); };Python: t[5] → scalar (rank-1 tensor) t[0, 1] → scalar (full int-indexing) t[5] = 1.0 → write scalar t[0, 1] = 2.0 → write scalar
With at_view and view_type, also: t[1] → view collapsing axis 0 (rank > 1) t[1:3], t[::-1] → view sliced along axis 0 t[:, 0], t[…] → view from a mixed tuple / the whole tensor
Note
Negative indices (“t[-1]”) are normalized to positive against the dim before being passed to user helpers. Out-of-range raises IndexError.
Warning
Assignment through a slice (
t[1:3] = ...) is not emitted; only full integer indices can be written. Without at_view, a slice or partial index raises TypeError.- Parameters:
... –
key = valueassignments naming element_type, rank, dim, at_element, set_element, and optionally at_view, view_type and slice_spec
-
APIARY_INSTANTIATE(...)¶
Cross-product template instantiation.
Each
Param(values...)group’s keyword must match one of the C++ template-parameter names; the codegen tool errors out on mismatch, duplicates, missing parameters, or arity mismatches. Python identifiers for the resulting bindings are auto-derived (Tensor_float_2etc.); useAPIARY_INSTANTIATE_TEMPLATEif you want to control the name explicitly.template <typename T, size_t rank> APIARY_INSTANTIATE(Tensor, T(float, double, std::complex<float>, std::complex<double>), rank(1, 2, 3, 4)) struct Tensor;Note
Reordering is allowed; this is equivalent to the above:
APIARY_INSTANTIATE(Tensor, rank(1, 2, 3, 4), T(float, double, std::complex<float>, std::complex<double>))Note
Non-type parameters may be of enum type. Name the enumerators in the group (scope-qualified
Layout::RowMajoror bareRowMajor); the codegen rewrites each to its fully-qualified form so the binding compiles at module scope, names the instantiation after the enumerator leaf (Storage_float_RowMajor), and errors if a value is not a real enumerator of that parameter’s enum:enum class Layout { RowMajor, ColumnMajor }; template <typename T, Layout L> APIARY_INSTANTIATE(Storage, T(float, double), L(Layout::RowMajor, Layout::ColumnMajor)) struct Storage;- Parameters:
... – the class name followed by
Param(values...)groups
-
APIARY_INSTANTIATE_AS(py_name, ...)¶
Single-instance instantiation with an explicit Python-side name.
Use this when:
You want a specific Python identifier that isn’t a function of the template arguments;
Or one template parameter depends on another (e.g.
Alloc=std::allocator<T>), which a flat cross-product can’t express.
The Python name comes first so the C++ type, whose template arguments may contain commas, can occupy the variadic tail.
APIARY_INSTANTIATE_AS("Tensor2d_double", GeneralTensor<double, 2, std::allocator<double>>)- Parameters:
py_name – string literal naming the Python binding
... – the fully-qualified C++ type to instantiate
-
APIARY_INSTANTIATE_BOOLS(py_name, ...)¶
Cross-product instantiation over the leading bool template parameters.
Requires
APIARY_TEMPLATE_KWARGSto declare how many leading template params are bool flags. Expands to 2^NAPIARY_INSTANTIATE_ASentries with every false/true combination prepended in lexicographic order ((false,false), (false,true), (true,false), (true,true) for N=2).The variadic tail is the comma-separated
non-booltemplate arguments for one dtype slice — same syntax asAPIARY_INSTANTIATE_ASminus the leading bool prefix. Repeat the directive once per dtype.APIARY_TEMPLATE_KWARGS("trans_a", "trans_b") APIARY_INSTANTIATE_BOOLS("gemm", einsums::GeneralRuntimeTensor<float, std::allocator<float>>, float) APIARY_INSTANTIATE_BOOLS("gemm", einsums::GeneralRuntimeTensor<double, std::allocator<double>>, double) ...Note
Use
APIARY_INSTANTIATE_ASdirectly if you need to omit a particular bool combination for a given dtype (rare escape hatch).- Parameters:
py_name – string literal naming the Python binding
... – the comma-separated non-bool template arguments for one dtype slice
-
APIARY_INSTANTIATE_MEMBER(...)¶
Pin a member-template parameter to a concrete type for binding purposes.
pybind11 cannot bind a member template directly — you must specify which instantiation to expose. Apply this directive on a method or constructor that itself has template parameters (distinct from the enclosing class’s template parameters); the codegen substitutes the binding into the emitted signature and into static_cast<>’d method-pointer expressions.
Note
Multiple member-template parameters: stack the directive once per parameter. Position-independent — the codegen matches by name.
template <typename T, typename Alloc> struct GeneralRuntimeTensor { template <Container Dim> APIARY_EXPOSE APIARY_INSTANTIATE_MEMBER(Dim = std::vector<size_t>) GeneralRuntimeTensor(std::string name, Dim const &dims); };For
GeneralRuntimeTensor<float, std::allocator<float>>this binds a constructor with signature(std::string, std::vector<size_t> const &).- Parameters:
... –
Param = Typeassignment pinning the member-template parameter
-
APIARY_INSTANTIATE_MEMBER_AS(py_name, ...)¶
Multi-instantiation form of APIARY_INSTANTIATE_MEMBER.
Each directive defines one Python binding for a templated method; multiple directives stack to fan a method out across dtypes / ranks (mirror of APIARY_INSTANTIATE_AS for free functions).
The first argument is the Python name. Subsequent arguments are
Param = Typeassignments pinning each member-template parameter to a concrete type for this instantiation.template <typename T, typename Alloc = std::allocator<T>> APIARY_EXPOSE APIARY_INSTANTIATE_MEMBER_AS("declare_runtime_tensor", T = float, Alloc = std::allocator<float>) APIARY_INSTANTIATE_MEMBER_AS("declare_runtime_tensor", T = double, Alloc = std::allocator<double>) GeneralRuntimeTensor<T, Alloc> &declare_runtime_tensor(...);Note
Sharing a Python name across directives produces a pybind11 overload set; py_name disambiguation is the user’s responsibility.
- Parameters:
py_name – string literal naming the Python binding
... –
Param = Typeassignments pinning each member-template parameter
-
APIARY_INSTANTIATE_TEMPLATE(name_template, ...)¶
Cross-product instantiation with a Python-name template.
Same matching rules as
APIARY_INSTANTIATE: each parameter list keyword must be a C++ template-parameter name. Placeholders in the name template use those same names.template <typename Element, int Rank> class Block; APIARY_INSTANTIATE_TEMPLATE("Block_{Element}_{Rank}", Block, Element(float, double), Rank(1, 2))Produces
Block_float_1,Block_float_2,Block_double_1,Block_double_2. Placeholder values are sanitized to valid Python identifiers (std::complex<double>->std_complex_double).- Parameters:
name_template – string literal name template with
{Param}placeholders... – the class name followed by
Param(values...)groups
-
APIARY_ITERATOR_STD(...)¶
Standard iterator protocol. The codegen emits a per-backend __iter__ binding that returns a Python iterator over the half-open range [begin(), end()). User-side methods stay STL-style; no pybind11 in their signatures.
All values name member functions that satisfy the standard LegacyForwardIterator (or stronger) requirements:
Iter begin();Iter end();
template <typename T, typename Alloc> APIARY_EXPOSE APIARY_ITERATOR_STD(begin = begin, end = end) struct GeneralRuntimeTensor { Iter begin(); // pure C++ Iter end(); };Note
The Python iterator borrows a reference to the underlying object (keep_alive<0, 1>) so iteration is safe across the parent’s lifetime.
- Parameters:
... –
key = valueassignments naming the begin and end member functions
-
APIARY_KEEP_ALIVE(nurse, patient)¶
Emit py::keep_alive<nurse, patient>() for this call.
- Parameters:
nurse – index of the object kept alive
patient – index of the object whose lifetime is tied to the nurse
-
APIARY_MODULE(submodule)¶
Place the binding inside a Python submodule (e.g. “tensor”, “linalg”).
- Parameters:
submodule – string literal naming the target submodule
-
APIARY_NOCOPY¶
Skip generation of the copy constructor binding.
-
APIARY_NOMOVE¶
Skip generation of the move constructor binding.
-
APIARY_NO_BASES¶
Force-skip emission of base-class arguments to
py::class_<>.Note
Usually unnecessary: by default the emitter only forwards bases that are themselves bound in this run, so unbound internal bases are silently dropped. Use this directive only when you want to explicitly hide a bound base from the Python class hierarchy.
-
APIARY_OPERATOR(py_name)¶
Bind this method as a Python operator (e.g. “__add__”, “__matmul__”) instead of an ordinary named function.
- Parameters:
py_name – string literal naming the Python operator
-
APIARY_READONLY¶
Bind a class field as read-only (
def_readonly).Note
Without this, fields marked APIARY_EXPOSE bind read-write.
-
APIARY_RELEASE_GIL¶
Wrap the call in py::call_guard<py::gil_scoped_release>().
-
APIARY_RENAME(py_name)¶
Override the Python identifier used for the binding.
- Parameters:
py_name – string literal naming the Python identifier
-
APIARY_RVP(policy)¶
Override return_value_policy. Argument is the unqualified policy name.
- Parameters:
policy – the unqualified policy name, e.g.
APIARY_RVP(reference_internal)
-
APIARY_SETTER(py_name)¶
Bind a method as the setter of a Python property.
Note
Pair with a matching APIARY_GETTER on the read accessor.
- Parameters:
py_name – string literal naming the Python property
-
APIARY_TEMPLATE_KWARGS(...)¶
Declare Python kwarg names for the leading bool template parameters of a templated free function.
The count of names tells the codegen how many leading template params are bool flags; their values become Python keyword-only arguments with the supplied names. Required when using
APIARY_INSTANTIATE_BOOLS.template <bool TransA, bool TransB, MatrixConcept T, typename U> APIARY_EXPOSE APIARY_TEMPLATE_KWARGS("trans_a", "trans_b") APIARY_INSTANTIATE_BOOLS("gemm", einsums::GeneralRuntimeTensor<float, std::allocator<float>>, float) void gemm(U const alpha, T const &A, T const &B, U const beta, T *C);The Python signature becomes
gemm(alpha, A, B, beta, C, *, trans_a=False, trans_b=False)and dispatches at runtime to the rightgemm<TA, TB, T, U>instantiation.- Parameters:
... – string literals naming the leading bool template parameters
-
APIARY_VARIADIC_FROM(param_name, element_type)¶
Variadic-pack expansion for templated method/ctor binding.
Indicates that the (assumed-last) parameter is a parameter pack, and that the expanded arity is given by the template parameter named
param_name. Each expanded slot has typeelement_type.template <typename T, size_t rank> struct Tensor; template <typename... Dims> APIARY_EXPOSE APIARY_VARIADIC_FROM(rank, size_t) Tensor(std::string name, Dims... dims);
For
Tensor<double, 2>, this binds a ctor with signature(std::string, size_t, size_t).- Parameters:
param_name – template parameter that gives the expanded arity
element_type – type of each expanded slot