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 { ... };- 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
Pair with APIARY_BUFFER_FROM to actually emit the
.def_buffer()call — buffer_protocol alone only flips the class option.
-
APIARY_BUFFER_PROTOCOL_STD(...)¶
Standard-layout buffer protocol. The codegen emits a per-backend .def_buffer (pybind11) / __dlpack__ (nanobind) lambda that builds the backend-native buffer description from the named member functions on the bound class.
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 element -size_t rank() const;-size_t dim(int) const;// dim along an axis -size_t stride(int) const;// stride in element unitsNote
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")instead ofpy::class_<T>(...). The C++ class must derive fromstd::exception(or whatever pybind11’s register_exception template requires) for the registration to compile.class APIARY_EXPOSE APIARY_EXCEPTION TensorError : public std::exception { ... };Subsequent
raise einsums.TensorError(...)from Python (orthrow einsums::TensorError("...")from C++) crosses the boundary cleanly.Note
Nanobind has a different exception API; this directive is pybind11-specific and is silently dropped under the nanobind target.
-
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.
- 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 (
py::int_,py::tuple), 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)
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
Note
Negative indices (“t[-1]”) are normalized to positive against the dim before being passed to user helpers. Out-of-range raises py::index_error.
Warning
Slice/partial-index reads (returning a view) and buffer bulk-assign are not yet emitted — they need APIARY_INDEX_PROTOCOL_STD’s extended form (with view_type and at_view) to land alongside the RuntimeTensorView binding. Until then, slice access throws a clear “view return not yet bound” error.
- Parameters:
... –
key = valueassignments naming element_type, rank, dim, at_element, set_element
-
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 (py::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