ARRAY CONTRACT
Bring familiar arrays.
Hyperfold accepts NumPy arrays in host memory and CUDA arrays from CuPy and PyTorch. Results preserve the input framework and device. Multi-array operations require one framework, one dtype and one device across all inputs.
| Framework | Location | Return convention | Interchange |
|---|---|---|---|
| NumPy | CPU host memory | NumPy arrays and NumPy scalars | Direct buffer borrowing |
| CuPy | CUDA device | CuPy arrays, including 0-D reductions | DLPack |
| PyTorch | CUDA device | PyTorch tensors, including 0-D reductions | DLPack |
CPU PyTorch tensors, CUDA NumPy arrays, generic DLPack producers, and implicit host/device transfers are rejected. Inputs are rank-one vectors or rank-two matrices; batching and broadcasting are not part of the v1 interface.
NUMERICAL TYPES
Storage and computation are explicit.
All 32 built-in operations accept the seven production storage dtypes. Ordinary array results retain storage precision, while reductions and solvers may retain the wider compute precision.
| Input storage | Compute / reductions / solve | Ordinary arrays | General eig / LU logdet |
|---|---|---|---|
| float16, bfloat16 | float32 | input dtype | complex64 |
| float32 | float32 | float32 | complex64 |
| float64 | float64 | float64 | complex128 |
| complex32 | complex64 | complex32 | complex64 |
| complex64 | complex64 | complex64 | complex64 |
| complex128 | complex128 | complex128 | complex128 |
norm, Hermitian eigenvalues and positive-definite log-determinants use the real component of compute precision.
vector_equal and is_unitary return booleans.
eigh, eigvalsh, slogdet and Cholesky logdet return compute-precision results.
Inputs to one operation must have identical storage dtypes; convert them explicitly first.
PACKED COMPLEX
Use four-byte complex storage.
complex32 stores real and imaginary IEEE float16 components and computes in
complex64. Input rounding is permanent even though later arithmetic is wider.
import hyperfold as hf
packed = hf.pack_complex32([[3, 1j], [-1j, 3]])
assert packed.dtype == hf.complex32
product = hf.matmul(packed, packed)
ordinary = hf.unpack_complex32(product) # NumPy complex64
values, vectors = hf.eigh(packed) # float32, complex64
| Framework | Representation | Conversion behaviour |
|---|---|---|
| NumPy | hyperfold.complex32, a structured dtype with float16 real and imag fields | The helpers copy between packed storage and complex64; NumPy provides no arithmetic for the structured dtype. |
| PyTorch CUDA | torch.complex32 / torch.chalf | The helpers preserve the CUDA device and return contiguous tensors. |
| CuPy | Unavailable | CuPy has no corresponding dtype; use complex64 or PyTorch complex32. |
hyperfold.pack_complex32
pack_complex32(values: Any) -> AnyCopies real or complex numeric values into complex32 storage. Passing complex32 still returns a fresh contiguous copy. Unsupported objects and CuPy inputs raise TypeError.
hyperfold.unpack_complex32
unpack_complex32(values: Any) -> AnyCopies complex32 storage to complex64 without changing the NumPy or PyTorch framework or the PyTorch device. Other input dtypes raise TypeError.
COPY AND OUTPUT
Control boundary ownership.
| Argument | Contract |
|---|---|
| copy=None | Borrow aligned, native-endian, C-contiguous compatible storage; otherwise create a fresh same-device contiguous input. |
| copy=False | Require borrowing. A layout, alignment, endianness or writability incompatibility that needs normalisation raises an error. |
| copy=True | Always normalise through fresh input storage. |
| out= | Require exact framework, dtype, device and shape. The destination must be writable, aligned, native-endian, C-contiguous and non-overlapping with every input. |
The copy policy applies at the Python boundary. Internal scratch storage, solver
workspaces and complex layout adaptation remain possible in every mode. Supplying
out returns that same object.
DLPACK
Order CUDA work on the selected stream.
Hyperfold passes its execution stream to each producer’s __dlpack__ method,
waits for input readiness on that stream, executes into framework-owned output memory,
and synchronises before returning. An external stream remains caller-owned and must
outlive every call that uses its context.
Arrays from different frameworks, dtypes or devices are rejected before dispatch. Hyperfold never falls back to a NumPy implementation when a backend signature is unavailable.