nvmath-python 1.0.0__cp314-cp314t-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- nvmath/__init__.pxd +0 -0
- nvmath/__init__.py +45 -0
- nvmath/_internal/__init__.py +0 -0
- nvmath/_internal/attribute_ifc_factory.py +330 -0
- nvmath/_internal/layout.py +70 -0
- nvmath/_internal/templates.py +130 -0
- nvmath/_internal/threadsafe.py +106 -0
- nvmath/_internal/utils.py +43 -0
- nvmath/_internal/workspace.py +490 -0
- nvmath/_utils.py +147 -0
- nvmath/bindings/__init__.py +60 -0
- nvmath/bindings/_internal/__init__.pxd +0 -0
- nvmath/bindings/_internal/__init__.py +0 -0
- nvmath/bindings/_internal/common_types.pxd +31 -0
- nvmath/bindings/_internal/cublas.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/cublas.pxd +530 -0
- nvmath/bindings/_internal/cublasLt.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/cublasLt.pxd +59 -0
- nvmath/bindings/_internal/cublasMp.pxd +52 -0
- nvmath/bindings/_internal/cudss.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/cudss.pxd +54 -0
- nvmath/bindings/_internal/cufft.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/cufft.pxd +70 -0
- nvmath/bindings/_internal/cufftMp.pxd +77 -0
- nvmath/bindings/_internal/curand.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/curand.pxd +42 -0
- nvmath/bindings/_internal/cusolver.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/cusolver.pxd +15 -0
- nvmath/bindings/_internal/cusolverDn.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/cusolverDn.pxd +406 -0
- nvmath/bindings/_internal/cusolverMp.pxd +71 -0
- nvmath/bindings/_internal/cusolverSp.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/cusolverSp.pxd +75 -0
- nvmath/bindings/_internal/cusparse.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/cusparse.pxd +471 -0
- nvmath/bindings/_internal/cusparseLt.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/cusparseLt.pxd +48 -0
- nvmath/bindings/_internal/cutensor.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/cutensor.pxd +58 -0
- nvmath/bindings/_internal/mathdx.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/mathdx.pxd +116 -0
- nvmath/bindings/_internal/nvshmem.pxd +29 -0
- nvmath/bindings/_internal/utils.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/utils.pxd +174 -0
- nvmath/bindings/_internal/utils.pyi +10 -0
- nvmath/bindings/cublas.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/cublas.pxd +558 -0
- nvmath/bindings/cublas.pyi +812 -0
- nvmath/bindings/cublasLt.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/cublasLt.pxd +109 -0
- nvmath/bindings/cublasLt.pyi +1461 -0
- nvmath/bindings/cublasMp.pxd +85 -0
- nvmath/bindings/cublasMp.pyi +267 -0
- nvmath/bindings/cudss.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/cudss.pxd +98 -0
- nvmath/bindings/cudss.pyi +443 -0
- nvmath/bindings/cufft.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/cufft.pxd +118 -0
- nvmath/bindings/cufft.pyi +301 -0
- nvmath/bindings/cufftMp.pxd +124 -0
- nvmath/bindings/cufftMp.pyi +326 -0
- nvmath/bindings/curand.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/curand.pxd +71 -0
- nvmath/bindings/curand.pyi +189 -0
- nvmath/bindings/cusolver.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/cusolver.pxd +62 -0
- nvmath/bindings/cusolver.pyi +320 -0
- nvmath/bindings/cusolverDn.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/cusolverDn.pxd +430 -0
- nvmath/bindings/cusolverDn.pyi +422 -0
- nvmath/bindings/cusolverMp.pxd +98 -0
- nvmath/bindings/cusolverMp.pyi +114 -0
- nvmath/bindings/cusolverSp.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/cusolverSp.pxd +95 -0
- nvmath/bindings/cusolverSp.pyi +70 -0
- nvmath/bindings/cusparse.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/cusparse.pxd +546 -0
- nvmath/bindings/cusparse.pyi +1017 -0
- nvmath/bindings/cusparseLt.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/cusparseLt.pxd +99 -0
- nvmath/bindings/cusparseLt.pyi +252 -0
- nvmath/bindings/cutensor.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/cutensor.pxd +98 -0
- nvmath/bindings/cutensor.pyi +324 -0
- nvmath/bindings/cycublas.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/cycublas.pxd +664 -0
- nvmath/bindings/cycublasLt.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/cycublasLt.pxd +1045 -0
- nvmath/bindings/cycublasMp.pxd +171 -0
- nvmath/bindings/cycudss.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/cycudss.pxd +277 -0
- nvmath/bindings/cycufft.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/cycufft.pxd +333 -0
- nvmath/bindings/cycufftMp.pxd +342 -0
- nvmath/bindings/cycurand.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/cycurand.pxd +141 -0
- nvmath/bindings/cycusolver.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/cycusolver.pxd +137 -0
- nvmath/bindings/cycusolverDn.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/cycusolverDn.pxd +443 -0
- nvmath/bindings/cycusolverMp.pxd +107 -0
- nvmath/bindings/cycusolverSp.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/cycusolverSp.pxd +93 -0
- nvmath/bindings/cycusparse.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/cycusparse.pxd +679 -0
- nvmath/bindings/cycusparseLt.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/cycusparseLt.pxd +135 -0
- nvmath/bindings/cycutensor.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/cycutensor.pxd +189 -0
- nvmath/bindings/cymathdx.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/cymathdx.pxd +552 -0
- nvmath/bindings/cynvshmem.pxd +118 -0
- nvmath/bindings/mathdx.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/mathdx.pxd +182 -0
- nvmath/bindings/mathdx.pyi +1562 -0
- nvmath/bindings/nvpl/__init__.pxd +0 -0
- nvmath/bindings/nvpl/__init__.py +13 -0
- nvmath/bindings/nvpl/_internal/__init__.pxd +0 -0
- nvmath/bindings/nvpl/_internal/__init__.py +0 -0
- nvmath/bindings/nvpl/_internal/blas.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/nvpl/_internal/blas.pxd +237 -0
- nvmath/bindings/nvpl/_internal/fft.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/nvpl/_internal/fft.pxd +36 -0
- nvmath/bindings/nvpl/blas.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/nvpl/blas.pxd +131 -0
- nvmath/bindings/nvpl/blas.pyi +168 -0
- nvmath/bindings/nvpl/cyblas.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/nvpl/cyblas.pxd +280 -0
- nvmath/bindings/nvpl/cyfft.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/nvpl/cyfft.pxd +93 -0
- nvmath/bindings/nvpl/fft.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/nvpl/fft.pxd +100 -0
- nvmath/bindings/nvpl/fft.pyi +168 -0
- nvmath/bindings/nvshmem.pxd +54 -0
- nvmath/bindings/nvshmem.pyi +191 -0
- nvmath/device/__init__.py +38 -0
- nvmath/device/_deprecated.py +33 -0
- nvmath/device/common.py +315 -0
- nvmath/device/common_backend.py +131 -0
- nvmath/device/common_cuda.py +201 -0
- nvmath/device/common_numba.py +300 -0
- nvmath/device/common_numba_cuda_mlir.py +202 -0
- nvmath/device/common_opaque_tensor.py +201 -0
- nvmath/device/cublasdx.py +1606 -0
- nvmath/device/cublasdx_backend.py +860 -0
- nvmath/device/cublasdx_numba.py +1534 -0
- nvmath/device/cublasdx_numba_cuda_mlir.py +208 -0
- nvmath/device/cufftdx.py +373 -0
- nvmath/device/cufftdx_backend.py +220 -0
- nvmath/device/cufftdx_numba.py +140 -0
- nvmath/device/cufftdx_numba_cuda_mlir.py +79 -0
- nvmath/device/curand_kernel.py +9147 -0
- nvmath/device/cusolverdx.py +2708 -0
- nvmath/device/cusolverdx_backend.py +440 -0
- nvmath/device/cusolverdx_numba.py +567 -0
- nvmath/device/cusolverdx_numba_cuda_mlir.py +604 -0
- nvmath/device/cusolverdx_overload_backend.py +1029 -0
- nvmath/device/llvm_array.py +29 -0
- nvmath/device/random.py +441 -0
- nvmath/device/random_helpers.py +23 -0
- nvmath/device/random_states.py +187 -0
- nvmath/device/types.py +138 -0
- nvmath/device/vector_types_numba.py +259 -0
- nvmath/distributed/__init__.py +200 -0
- nvmath/distributed/_internal/__init__.py +0 -0
- nvmath/distributed/_internal/nccl.py +86 -0
- nvmath/distributed/_internal/nvshmem.py +307 -0
- nvmath/distributed/_internal/symmetric_memory.py +35 -0
- nvmath/distributed/_internal/tensor_ifc.py +70 -0
- nvmath/distributed/_internal/tensor_ifc_cupy.py +68 -0
- nvmath/distributed/_internal/tensor_ifc_host_device.py +172 -0
- nvmath/distributed/_internal/tensor_ifc_numpy.py +46 -0
- nvmath/distributed/_internal/tensor_ifc_torch.py +162 -0
- nvmath/distributed/_internal/tensor_wrapper.py +81 -0
- nvmath/distributed/_utils.py +167 -0
- nvmath/distributed/distribution/__init__.py +30 -0
- nvmath/distributed/distribution/_configuration.py +39 -0
- nvmath/distributed/distribution/distributions.py +1024 -0
- nvmath/distributed/distribution/redistribute.py +1284 -0
- nvmath/distributed/fft/__init__.py +7 -0
- nvmath/distributed/fft/_configuration.py +82 -0
- nvmath/distributed/fft/fft.py +2742 -0
- nvmath/distributed/linalg/__init__.py +22 -0
- nvmath/distributed/linalg/_internal/__init__.py +3 -0
- nvmath/distributed/linalg/_internal/epilog_protocol.py +586 -0
- nvmath/distributed/linalg/_internal/matmul_desc_ifc.py +28 -0
- nvmath/distributed/linalg/advanced/__init__.py +8 -0
- nvmath/distributed/linalg/advanced/_configuration.py +171 -0
- nvmath/distributed/linalg/advanced/matmulmod.py +3573 -0
- nvmath/distributed/linalg/generic/__init__.py +8 -0
- nvmath/distributed/linalg/generic/_caching.py +66 -0
- nvmath/distributed/linalg/generic/_configuration.py +61 -0
- nvmath/distributed/linalg/generic/_factorization.py +172 -0
- nvmath/distributed/linalg/generic/_initialization.py +966 -0
- nvmath/distributed/linalg/generic/_problem_spec.py +511 -0
- nvmath/distributed/linalg/generic/solvermod.py +1368 -0
- nvmath/distributed/process_group.py +408 -0
- nvmath/fft/__init__.py +7 -0
- nvmath/fft/_configuration.py +189 -0
- nvmath/fft/_exec_utils.py +82 -0
- nvmath/fft/_helpers.py +237 -0
- nvmath/fft/fft.py +3122 -0
- nvmath/internal/__init__.pxd +3 -0
- nvmath/internal/__init__.py +10 -0
- nvmath/internal/_bindings.cp314t-win_amd64.pyd +0 -0
- nvmath/internal/_bindings.pxd +18 -0
- nvmath/internal/_device_utils.py +45 -0
- nvmath/internal/_layout/__init__.pxd +3 -0
- nvmath/internal/_layout/__init__.py +7 -0
- nvmath/internal/_layout/_layout.cp314t-win_amd64.pyd +0 -0
- nvmath/internal/_layout/_layout.pxd +1303 -0
- nvmath/internal/_layout/_layout.pyi +1145 -0
- nvmath/internal/enum_utils.py +142 -0
- nvmath/internal/formatters.py +87 -0
- nvmath/internal/mem_limit.py +51 -0
- nvmath/internal/memory.cp314t-win_amd64.pyd +0 -0
- nvmath/internal/memory.pxd +13 -0
- nvmath/internal/memory.pyi +50 -0
- nvmath/internal/ndbuffer/__init__.pxd +3 -0
- nvmath/internal/ndbuffer/__init__.py +9 -0
- nvmath/internal/ndbuffer/_copy_kernel.cp314t-win_amd64.pyd +0 -0
- nvmath/internal/ndbuffer/_copy_kernel.pxd +10 -0
- nvmath/internal/ndbuffer/_jit.cp314t-win_amd64.pyd +0 -0
- nvmath/internal/ndbuffer/_jit.pxd +7 -0
- nvmath/internal/ndbuffer/_ndbuffer.cp314t-win_amd64.pyd +0 -0
- nvmath/internal/ndbuffer/_ndbuffer.pxd +40 -0
- nvmath/internal/ndbuffer/_ndbuffer.pyi +463 -0
- nvmath/internal/ndbuffer/copy_kernel/args.h +34 -0
- nvmath/internal/ndbuffer/copy_kernel/copy_kernel_impl/array_view.h +52 -0
- nvmath/internal/ndbuffer/copy_kernel/copy_kernel_impl/elementwise.h +68 -0
- nvmath/internal/ndbuffer/copy_kernel/copy_kernel_impl/grid_indexer.h +69 -0
- nvmath/internal/ndbuffer/copy_kernel/copy_kernel_impl/transposed.h +242 -0
- nvmath/internal/ndbuffer/copy_kernel/copy_kernel_impl/type_utils.h +39 -0
- nvmath/internal/ndbuffer/copy_kernel/copy_kernel_impl/utils.h +132 -0
- nvmath/internal/ndbuffer/copy_kernel/copy_kernel_impl/vec.h +159 -0
- nvmath/internal/ndbuffer/copy_kernel/elementwise.h +53 -0
- nvmath/internal/ndbuffer/copy_kernel/transposed.h +58 -0
- nvmath/internal/package_ifc.py +168 -0
- nvmath/internal/package_ifc_cuda.py +57 -0
- nvmath/internal/package_ifc_cupy.py +67 -0
- nvmath/internal/package_ifc_torch.py +69 -0
- nvmath/internal/package_wrapper.py +14 -0
- nvmath/internal/tensor_ifc.py +179 -0
- nvmath/internal/tensor_ifc_cupy.py +234 -0
- nvmath/internal/tensor_ifc_ndbuffer.py +147 -0
- nvmath/internal/tensor_ifc_numpy.py +184 -0
- nvmath/internal/tensor_ifc_torch.py +178 -0
- nvmath/internal/tensor_wrapper.py +160 -0
- nvmath/internal/typemaps.py +113 -0
- nvmath/internal/utils.py +805 -0
- nvmath/linalg/__init__.py +56 -0
- nvmath/linalg/_internal/__init__.py +3 -0
- nvmath/linalg/_internal/algo_cap_ifc.py +82 -0
- nvmath/linalg/_internal/algo_config_ifc.py +43 -0
- nvmath/linalg/_internal/batch.py +234 -0
- nvmath/linalg/_internal/enum_to_tuples.py +64 -0
- nvmath/linalg/_internal/epilog_protocol.py +766 -0
- nvmath/linalg/_internal/layout.py +624 -0
- nvmath/linalg/_internal/matmul_desc_ifc.py +28 -0
- nvmath/linalg/_internal/matmul_pref_ifc.py +27 -0
- nvmath/linalg/_internal/matrix_layout_ifc.py +26 -0
- nvmath/linalg/_internal/solver_utils.py +432 -0
- nvmath/linalg/_internal/typemaps.py +144 -0
- nvmath/linalg/_internal/utils.py +157 -0
- nvmath/linalg/advanced/__init__.py +8 -0
- nvmath/linalg/advanced/_algorithmmod.py +170 -0
- nvmath/linalg/advanced/_configuration.py +351 -0
- nvmath/linalg/advanced/helpers/__init__.py +5 -0
- nvmath/linalg/advanced/helpers/matmul.py +1316 -0
- nvmath/linalg/advanced/matmulmod.py +3734 -0
- nvmath/linalg/generic/__init__.py +53 -0
- nvmath/linalg/generic/_configuration/__init__.py +39 -0
- nvmath/linalg/generic/_configuration/layout.py +263 -0
- nvmath/linalg/generic/_configuration/match.py +734 -0
- nvmath/linalg/generic/_configuration/qualifiers.py +493 -0
- nvmath/linalg/generic/_configuration/solver_configuration.py +59 -0
- nvmath/linalg/generic/_configuration/wrap.py +217 -0
- nvmath/linalg/generic/_dtype.py +15 -0
- nvmath/linalg/generic/matmulmod.py +2094 -0
- nvmath/linalg/generic/solvermod.py +1301 -0
- nvmath/memory.py +279 -0
- nvmath/sparse/__init__.py +38 -0
- nvmath/sparse/_internal/__init__.py +21 -0
- nvmath/sparse/_internal/common_utils.py +147 -0
- nvmath/sparse/_internal/cudss_config_ifc.py +702 -0
- nvmath/sparse/_internal/cudss_data_ifc.py +399 -0
- nvmath/sparse/_internal/cudss_utils.py +506 -0
- nvmath/sparse/_internal/cusparse_utils.py +382 -0
- nvmath/sparse/_internal/sparse_bsc_ifc.py +303 -0
- nvmath/sparse/_internal/sparse_bsr_ifc.py +305 -0
- nvmath/sparse/_internal/sparse_coo_ifc.py +256 -0
- nvmath/sparse/_internal/sparse_csc_ifc.py +268 -0
- nvmath/sparse/_internal/sparse_csr_ifc.py +288 -0
- nvmath/sparse/_internal/sparse_dia_ifc.py +242 -0
- nvmath/sparse/_internal/sparse_format_helpers.py +601 -0
- nvmath/sparse/_internal/sparse_tensor_ifc.py +133 -0
- nvmath/sparse/_internal/sparse_ust_ifc.py +141 -0
- nvmath/sparse/_internal/utils.py +56 -0
- nvmath/sparse/advanced/__init__.py +7 -0
- nvmath/sparse/advanced/_configuration.py +227 -0
- nvmath/sparse/advanced/direct_solver.py +2069 -0
- nvmath/sparse/generic/__init__.py +7 -0
- nvmath/sparse/generic/_configuration.py +129 -0
- nvmath/sparse/generic/_helpers.py +137 -0
- nvmath/sparse/generic/_thunks.py +21 -0
- nvmath/sparse/generic/matmulmod.py +2353 -0
- nvmath/sparse/ust/__init__.py +7 -0
- nvmath/sparse/ust/_converters.py +422 -0
- nvmath/sparse/ust/_cpp.py +28 -0
- nvmath/sparse/ust/_drawer.py +565 -0
- nvmath/sparse/ust/_emitter.py +1033 -0
- nvmath/sparse/ust/_jit.py +188 -0
- nvmath/sparse/ust/_kernel.py +282 -0
- nvmath/sparse/ust/_utils.py +149 -0
- nvmath/sparse/ust/interfaces/__init__.py +0 -0
- nvmath/sparse/ust/interfaces/torch_interface.py +476 -0
- nvmath/sparse/ust/tensor.py +1016 -0
- nvmath/sparse/ust/tensor_format.py +957 -0
- nvmath/tensor/__init__.py +6 -0
- nvmath/tensor/_configuration.py +120 -0
- nvmath/tensor/_internal/__init__.py +3 -0
- nvmath/tensor/_internal/cutensor_config_ifc.py +279 -0
- nvmath/tensor/_internal/cutensor_utils.py +230 -0
- nvmath/tensor/_internal/data.py +43 -0
- nvmath/tensor/_internal/einsum_parser.py +444 -0
- nvmath/tensor/_internal/typemaps.py +96 -0
- nvmath/tensor/contract.py +1900 -0
- nvmath_python-1.0.0.dist-info/METADATA +134 -0
- nvmath_python-1.0.0.dist-info/RECORD +332 -0
- nvmath_python-1.0.0.dist-info/WHEEL +5 -0
- nvmath_python-1.0.0.dist-info/licenses/LICENSE +177 -0
- nvmath_python-1.0.0.dist-info/top_level.txt +2 -0
|
@@ -0,0 +1,1145 @@
|
|
|
1
|
+
# Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
5
|
+
import SlicedLayout
|
|
6
|
+
import StridedLayout
|
|
7
|
+
import _cython_3_2_5
|
|
8
|
+
from _typeshed import Incomplete
|
|
9
|
+
from typing import Any, ClassVar, Literal, overload
|
|
10
|
+
|
|
11
|
+
__reduce_cython__: _cython_3_2_5.cython_function_or_method
|
|
12
|
+
__setstate_cython__: _cython_3_2_5.cython_function_or_method
|
|
13
|
+
__test__: dict
|
|
14
|
+
|
|
15
|
+
class SlicedLayout:
|
|
16
|
+
"""SlicedLayout()
|
|
17
|
+
|
|
18
|
+
Result of slicing a :py:class:`StridedLayout`.
|
|
19
|
+
Logically, :class:`SlicedLayout` instance is a :class:`StridedLayout` instance +
|
|
20
|
+
:attr:`slice_offset`, i.e. an offset of the element at index ``(0,) * ndim``.
|
|
21
|
+
|
|
22
|
+
Using algebraic analogy:
|
|
23
|
+
|
|
24
|
+
* :class:`StridedLayout` defines a *linear mapping* from indices to element offsets
|
|
25
|
+
* :class:`SlicedLayout` adds an extra constant term, making the mapping *affine*.
|
|
26
|
+
|
|
27
|
+
Some properties that are clear for linear case, become ambiguous or break
|
|
28
|
+
with the non-zero :attr:`slice_offset`. For example:
|
|
29
|
+
|
|
30
|
+
* Is the layout contiguous/dense/exhaustive if it has a non-zero :attr:`slice_offset`?
|
|
31
|
+
* Should :attr:`~StridedLayout.min_offset` or :attr:`~StridedLayout.max_offset`
|
|
32
|
+
take into account the :attr:`slice_offset`?
|
|
33
|
+
|
|
34
|
+
The answers depend on the use case (and whether the :attr:`slice_offset` is accounted for
|
|
35
|
+
in the data pointer). For this reason, :class:`StridedLayout` and :class:`SlicedLayout` are separate classes,
|
|
36
|
+
and :class:`StridedLayout` is unaware of the :attr:`slice_offset`. It is up to the user to
|
|
37
|
+
make sure the data pointer is adjusted to account for the :attr:`slice_offset`."""
|
|
38
|
+
__pyx_vtable__: ClassVar[PyCapsule] = ...
|
|
39
|
+
layout: SlicedLayout.layout
|
|
40
|
+
slice_offset: Incomplete
|
|
41
|
+
slice_offset_in_bytes: SlicedLayout.slice_offset_in_bytes
|
|
42
|
+
def __init__(self) -> Any:
|
|
43
|
+
"""Initialize self. See help(type(self)) for accurate signature."""
|
|
44
|
+
def __eq__(self, other: object) -> bool:
|
|
45
|
+
"""Return self==value."""
|
|
46
|
+
def __ge__(self, other: object) -> bool:
|
|
47
|
+
"""Return self>=value."""
|
|
48
|
+
def __getitem__(self, index):
|
|
49
|
+
"""Return self[key]."""
|
|
50
|
+
def __gt__(self, other: object) -> bool:
|
|
51
|
+
"""Return self>value."""
|
|
52
|
+
def __le__(self, other: object) -> bool:
|
|
53
|
+
"""Return self<=value."""
|
|
54
|
+
def __lt__(self, other: object) -> bool:
|
|
55
|
+
"""Return self<value."""
|
|
56
|
+
def __ne__(self, other: object) -> bool:
|
|
57
|
+
"""Return self!=value."""
|
|
58
|
+
def __reduce__(self):
|
|
59
|
+
"""SlicedLayout.__reduce_cython__(self)"""
|
|
60
|
+
|
|
61
|
+
class StridedLayout:
|
|
62
|
+
"""StridedLayout(shape: tuple[int] | list[int] | int, strides: tuple[int] | list[int] | int | None, int itemsize: int, bool divide_strides: bool = False) -> None
|
|
63
|
+
|
|
64
|
+
A class describing the layout of a multi-dimensional tensor
|
|
65
|
+
with a shape, strides and itemsize.
|
|
66
|
+
|
|
67
|
+
In Python, the StridedLayout is immutable, all transforming methods
|
|
68
|
+
(e.g. :meth:`reshaped`, :meth:`permuted`, etc.)
|
|
69
|
+
return a new instance or unchanged self. The latter may happen
|
|
70
|
+
if the operation would be a no-op (like reshaping to the same shape).
|
|
71
|
+
|
|
72
|
+
.. warning::
|
|
73
|
+
This API is experimental and may change at any time."""
|
|
74
|
+
dense: ClassVar[method] = ...
|
|
75
|
+
dense_like: ClassVar[method] = ...
|
|
76
|
+
__pyx_vtable__: ClassVar[PyCapsule] = ...
|
|
77
|
+
has_no_negative_stride: StridedLayout.has_no_negative_stride
|
|
78
|
+
is_abs_dense_any: StridedLayout.is_abs_dense_any
|
|
79
|
+
is_abs_dense_c: StridedLayout.is_abs_dense_c
|
|
80
|
+
is_abs_dense_f: StridedLayout.is_abs_dense_f
|
|
81
|
+
is_contiguous_any: StridedLayout.is_contiguous_any
|
|
82
|
+
is_contiguous_c: StridedLayout.is_contiguous_c
|
|
83
|
+
is_contiguous_f: StridedLayout.is_contiguous_f
|
|
84
|
+
is_exhaustive: StridedLayout.is_exhaustive
|
|
85
|
+
is_unique: StridedLayout.is_unique
|
|
86
|
+
itemsize: StridedLayout.itemsize
|
|
87
|
+
max_offset: StridedLayout.max_offset
|
|
88
|
+
max_stride: StridedLayout.max_stride
|
|
89
|
+
memory_range_size: StridedLayout.memory_range_size
|
|
90
|
+
memory_range_size_in_bytes: StridedLayout.memory_range_size_in_bytes
|
|
91
|
+
min_offset: StridedLayout.min_offset
|
|
92
|
+
min_stride: StridedLayout.min_stride
|
|
93
|
+
ndim: StridedLayout.ndim
|
|
94
|
+
offset_bounds: Any
|
|
95
|
+
shape: StridedLayout.shape
|
|
96
|
+
stride_order: StridedLayout.stride_order
|
|
97
|
+
strides: StridedLayout.strides
|
|
98
|
+
strides_in_bytes: StridedLayout.strides_in_bytes
|
|
99
|
+
volume: StridedLayout.volume
|
|
100
|
+
def __init__(self, shape: tuple[int] | list[int] | int, strides: tuple[int] | list[int] | int | None, intitemsize: int, booldivide_strides: bool = ...) -> None:
|
|
101
|
+
"""
|
|
102
|
+
Parameters
|
|
103
|
+
----------
|
|
104
|
+
shape : tuple
|
|
105
|
+
A tuple of non-negative integers.
|
|
106
|
+
strides : tuple or None
|
|
107
|
+
If a tuple, it must be a tuple of integers of the same length as ``shape``.
|
|
108
|
+
If None, the strides are assumed to be C-contiguous.
|
|
109
|
+
itemsize : int
|
|
110
|
+
The number of bytes per single element (dtype size). Must be a power of two.
|
|
111
|
+
divide_strides : bool, optional
|
|
112
|
+
If True, the provided :attr:`strides` will be divided by the :attr:`itemsize`.
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
See also :meth:`dense`.
|
|
116
|
+
"""
|
|
117
|
+
def broadcast_to(self, shape: int | tuple[int] | list[int] | StridedLayout) -> StridedLayout:
|
|
118
|
+
"""StridedLayout.broadcast_to(self: StridedLayout, shape: int | tuple[int] | list[int] | StridedLayout) -> StridedLayout
|
|
119
|
+
|
|
120
|
+
Returns a layout with the new shape, if the old shape can be
|
|
121
|
+
broadcast to the new one.
|
|
122
|
+
|
|
123
|
+
The shapes are compatible if:
|
|
124
|
+
* the new shape has the same or greater number of dimensions
|
|
125
|
+
* starting from the right, each extent in the old shape must be 1 or
|
|
126
|
+
equal to the corresponding extent in the new shape.
|
|
127
|
+
|
|
128
|
+
Strides of the added or modified extents are set to 0, the remaining ones are unchanged.
|
|
129
|
+
If the shapes are not compatible, a ValueError is raised.
|
|
130
|
+
|
|
131
|
+
Parameters
|
|
132
|
+
----------
|
|
133
|
+
shape : int | tuple[int] | list[int] | StridedLayout
|
|
134
|
+
The new shape to broadcast to. If a :class:`StridedLayout` is passed,
|
|
135
|
+
the shape is taken from the provided layout.
|
|
136
|
+
|
|
137
|
+
Returns
|
|
138
|
+
-------
|
|
139
|
+
StridedLayout
|
|
140
|
+
The broadcasted layout."""
|
|
141
|
+
def extended(self, StridedLayoutother: StridedLayout, intaxis: int = ...) -> StridedLayout:
|
|
142
|
+
"""StridedLayout.extended(self: StridedLayout, StridedLayout other: StridedLayout, int axis: int = -1) -> StridedLayout
|
|
143
|
+
|
|
144
|
+
Returns a layout as if the ``other`` layout was inserted before the
|
|
145
|
+
specified ``axis`` into the current layout. The valid range of ``axis`` is
|
|
146
|
+
(inclusive) range ``[0, self.ndim]``."""
|
|
147
|
+
@overload
|
|
148
|
+
def flattened(self, intstart_axis: int = ..., intend_axis: int = ..., intmask: int | None = ...) -> StridedLayout:
|
|
149
|
+
"""StridedLayout.flattened(self: StridedLayout, int start_axis: int = 0, int end_axis: int = -1, int mask: int | None = None) -> StridedLayout
|
|
150
|
+
|
|
151
|
+
Returns a layout where consecutive extents, if possible,
|
|
152
|
+
are merged into a single extent (equal to the product of merged extents).
|
|
153
|
+
Extents are mergeable if the corresponding sub-layout is c-leading-dense,
|
|
154
|
+
i.e. the corresponding strides can be replaced with a single
|
|
155
|
+
(the rightmost, and the smallest) stride.
|
|
156
|
+
Iterating over the indices of the the original and the flattened layout
|
|
157
|
+
in C-order (the rightmost axis incremented first) is equivalent.
|
|
158
|
+
|
|
159
|
+
Note, flattening a scalar turns the layout into 1D array.
|
|
160
|
+
|
|
161
|
+
.. highlight:: python
|
|
162
|
+
.. code-block:: python
|
|
163
|
+
|
|
164
|
+
# the two extents can be merged into a single extent
|
|
165
|
+
# because layout.strides[0] == layout.strides[1] * layout.shape[1]
|
|
166
|
+
layout = StridedLayout((3, 2), (2, 1), 1)
|
|
167
|
+
assert layout.flattened() == StridedLayout((6,), (1,), 1)
|
|
168
|
+
|
|
169
|
+
# the two extents cannot be merged into a single extent
|
|
170
|
+
# because layout.strides[0] != layout.strides[1] * layout.shape[1]
|
|
171
|
+
layout = StridedLayout((3, 2), (1, 3), 1)
|
|
172
|
+
assert layout.flattened() == layout
|
|
173
|
+
|
|
174
|
+
If ``start_axis`` and ``end_axis`` are provided, only the axes in the
|
|
175
|
+
inclusive range ``[start_axis, end_axis]`` are considered for flattening.
|
|
176
|
+
|
|
177
|
+
Alternatively, a mask specifying which axes to consider can be provided.
|
|
178
|
+
A mask of mergeable extents can be obtained using the :meth:`flattened_axis_mask` method.
|
|
179
|
+
Masks for layouts with the same number of dimensions can be combined
|
|
180
|
+
using the logical ``&`` (bitwise AND) operator.
|
|
181
|
+
|
|
182
|
+
.. highlight:: python
|
|
183
|
+
.. code-block:: python
|
|
184
|
+
|
|
185
|
+
layout = StridedLayout.dense((4, 5, 3), 4)
|
|
186
|
+
layout2 = StridedLayout((4, 5, 3), (1, 12, 4), 4)
|
|
187
|
+
# Even though the two layouts have the same shape initially,
|
|
188
|
+
# their shapes differ after flattening.
|
|
189
|
+
assert layout.flattened() == StridedLayout((60,), (1,), 4)
|
|
190
|
+
assert layout2.flattened() == StridedLayout((4, 15), (1, 4), 4)
|
|
191
|
+
# With the mask, only extents that are mergeable in both layouts are flattened
|
|
192
|
+
# and the resulting shape is the same for both layouts.
|
|
193
|
+
mask = layout.flattened_axis_mask() & layout2.flattened_axis_mask()
|
|
194
|
+
assert layout.flattened(mask=mask) == StridedLayout((4, 15), (15, 1), 4)
|
|
195
|
+
assert layout2.flattened(mask=mask) == StridedLayout((4, 15), (1, 4), 4)"""
|
|
196
|
+
@overload
|
|
197
|
+
def flattened(self) -> Any:
|
|
198
|
+
"""StridedLayout.flattened(self: StridedLayout, int start_axis: int = 0, int end_axis: int = -1, int mask: int | None = None) -> StridedLayout
|
|
199
|
+
|
|
200
|
+
Returns a layout where consecutive extents, if possible,
|
|
201
|
+
are merged into a single extent (equal to the product of merged extents).
|
|
202
|
+
Extents are mergeable if the corresponding sub-layout is c-leading-dense,
|
|
203
|
+
i.e. the corresponding strides can be replaced with a single
|
|
204
|
+
(the rightmost, and the smallest) stride.
|
|
205
|
+
Iterating over the indices of the the original and the flattened layout
|
|
206
|
+
in C-order (the rightmost axis incremented first) is equivalent.
|
|
207
|
+
|
|
208
|
+
Note, flattening a scalar turns the layout into 1D array.
|
|
209
|
+
|
|
210
|
+
.. highlight:: python
|
|
211
|
+
.. code-block:: python
|
|
212
|
+
|
|
213
|
+
# the two extents can be merged into a single extent
|
|
214
|
+
# because layout.strides[0] == layout.strides[1] * layout.shape[1]
|
|
215
|
+
layout = StridedLayout((3, 2), (2, 1), 1)
|
|
216
|
+
assert layout.flattened() == StridedLayout((6,), (1,), 1)
|
|
217
|
+
|
|
218
|
+
# the two extents cannot be merged into a single extent
|
|
219
|
+
# because layout.strides[0] != layout.strides[1] * layout.shape[1]
|
|
220
|
+
layout = StridedLayout((3, 2), (1, 3), 1)
|
|
221
|
+
assert layout.flattened() == layout
|
|
222
|
+
|
|
223
|
+
If ``start_axis`` and ``end_axis`` are provided, only the axes in the
|
|
224
|
+
inclusive range ``[start_axis, end_axis]`` are considered for flattening.
|
|
225
|
+
|
|
226
|
+
Alternatively, a mask specifying which axes to consider can be provided.
|
|
227
|
+
A mask of mergeable extents can be obtained using the :meth:`flattened_axis_mask` method.
|
|
228
|
+
Masks for layouts with the same number of dimensions can be combined
|
|
229
|
+
using the logical ``&`` (bitwise AND) operator.
|
|
230
|
+
|
|
231
|
+
.. highlight:: python
|
|
232
|
+
.. code-block:: python
|
|
233
|
+
|
|
234
|
+
layout = StridedLayout.dense((4, 5, 3), 4)
|
|
235
|
+
layout2 = StridedLayout((4, 5, 3), (1, 12, 4), 4)
|
|
236
|
+
# Even though the two layouts have the same shape initially,
|
|
237
|
+
# their shapes differ after flattening.
|
|
238
|
+
assert layout.flattened() == StridedLayout((60,), (1,), 4)
|
|
239
|
+
assert layout2.flattened() == StridedLayout((4, 15), (1, 4), 4)
|
|
240
|
+
# With the mask, only extents that are mergeable in both layouts are flattened
|
|
241
|
+
# and the resulting shape is the same for both layouts.
|
|
242
|
+
mask = layout.flattened_axis_mask() & layout2.flattened_axis_mask()
|
|
243
|
+
assert layout.flattened(mask=mask) == StridedLayout((4, 15), (15, 1), 4)
|
|
244
|
+
assert layout2.flattened(mask=mask) == StridedLayout((4, 15), (1, 4), 4)"""
|
|
245
|
+
@overload
|
|
246
|
+
def flattened(self) -> Any:
|
|
247
|
+
"""StridedLayout.flattened(self: StridedLayout, int start_axis: int = 0, int end_axis: int = -1, int mask: int | None = None) -> StridedLayout
|
|
248
|
+
|
|
249
|
+
Returns a layout where consecutive extents, if possible,
|
|
250
|
+
are merged into a single extent (equal to the product of merged extents).
|
|
251
|
+
Extents are mergeable if the corresponding sub-layout is c-leading-dense,
|
|
252
|
+
i.e. the corresponding strides can be replaced with a single
|
|
253
|
+
(the rightmost, and the smallest) stride.
|
|
254
|
+
Iterating over the indices of the the original and the flattened layout
|
|
255
|
+
in C-order (the rightmost axis incremented first) is equivalent.
|
|
256
|
+
|
|
257
|
+
Note, flattening a scalar turns the layout into 1D array.
|
|
258
|
+
|
|
259
|
+
.. highlight:: python
|
|
260
|
+
.. code-block:: python
|
|
261
|
+
|
|
262
|
+
# the two extents can be merged into a single extent
|
|
263
|
+
# because layout.strides[0] == layout.strides[1] * layout.shape[1]
|
|
264
|
+
layout = StridedLayout((3, 2), (2, 1), 1)
|
|
265
|
+
assert layout.flattened() == StridedLayout((6,), (1,), 1)
|
|
266
|
+
|
|
267
|
+
# the two extents cannot be merged into a single extent
|
|
268
|
+
# because layout.strides[0] != layout.strides[1] * layout.shape[1]
|
|
269
|
+
layout = StridedLayout((3, 2), (1, 3), 1)
|
|
270
|
+
assert layout.flattened() == layout
|
|
271
|
+
|
|
272
|
+
If ``start_axis`` and ``end_axis`` are provided, only the axes in the
|
|
273
|
+
inclusive range ``[start_axis, end_axis]`` are considered for flattening.
|
|
274
|
+
|
|
275
|
+
Alternatively, a mask specifying which axes to consider can be provided.
|
|
276
|
+
A mask of mergeable extents can be obtained using the :meth:`flattened_axis_mask` method.
|
|
277
|
+
Masks for layouts with the same number of dimensions can be combined
|
|
278
|
+
using the logical ``&`` (bitwise AND) operator.
|
|
279
|
+
|
|
280
|
+
.. highlight:: python
|
|
281
|
+
.. code-block:: python
|
|
282
|
+
|
|
283
|
+
layout = StridedLayout.dense((4, 5, 3), 4)
|
|
284
|
+
layout2 = StridedLayout((4, 5, 3), (1, 12, 4), 4)
|
|
285
|
+
# Even though the two layouts have the same shape initially,
|
|
286
|
+
# their shapes differ after flattening.
|
|
287
|
+
assert layout.flattened() == StridedLayout((60,), (1,), 4)
|
|
288
|
+
assert layout2.flattened() == StridedLayout((4, 15), (1, 4), 4)
|
|
289
|
+
# With the mask, only extents that are mergeable in both layouts are flattened
|
|
290
|
+
# and the resulting shape is the same for both layouts.
|
|
291
|
+
mask = layout.flattened_axis_mask() & layout2.flattened_axis_mask()
|
|
292
|
+
assert layout.flattened(mask=mask) == StridedLayout((4, 15), (15, 1), 4)
|
|
293
|
+
assert layout2.flattened(mask=mask) == StridedLayout((4, 15), (1, 4), 4)"""
|
|
294
|
+
@overload
|
|
295
|
+
def flattened(self) -> Any:
|
|
296
|
+
"""StridedLayout.flattened(self: StridedLayout, int start_axis: int = 0, int end_axis: int = -1, int mask: int | None = None) -> StridedLayout
|
|
297
|
+
|
|
298
|
+
Returns a layout where consecutive extents, if possible,
|
|
299
|
+
are merged into a single extent (equal to the product of merged extents).
|
|
300
|
+
Extents are mergeable if the corresponding sub-layout is c-leading-dense,
|
|
301
|
+
i.e. the corresponding strides can be replaced with a single
|
|
302
|
+
(the rightmost, and the smallest) stride.
|
|
303
|
+
Iterating over the indices of the the original and the flattened layout
|
|
304
|
+
in C-order (the rightmost axis incremented first) is equivalent.
|
|
305
|
+
|
|
306
|
+
Note, flattening a scalar turns the layout into 1D array.
|
|
307
|
+
|
|
308
|
+
.. highlight:: python
|
|
309
|
+
.. code-block:: python
|
|
310
|
+
|
|
311
|
+
# the two extents can be merged into a single extent
|
|
312
|
+
# because layout.strides[0] == layout.strides[1] * layout.shape[1]
|
|
313
|
+
layout = StridedLayout((3, 2), (2, 1), 1)
|
|
314
|
+
assert layout.flattened() == StridedLayout((6,), (1,), 1)
|
|
315
|
+
|
|
316
|
+
# the two extents cannot be merged into a single extent
|
|
317
|
+
# because layout.strides[0] != layout.strides[1] * layout.shape[1]
|
|
318
|
+
layout = StridedLayout((3, 2), (1, 3), 1)
|
|
319
|
+
assert layout.flattened() == layout
|
|
320
|
+
|
|
321
|
+
If ``start_axis`` and ``end_axis`` are provided, only the axes in the
|
|
322
|
+
inclusive range ``[start_axis, end_axis]`` are considered for flattening.
|
|
323
|
+
|
|
324
|
+
Alternatively, a mask specifying which axes to consider can be provided.
|
|
325
|
+
A mask of mergeable extents can be obtained using the :meth:`flattened_axis_mask` method.
|
|
326
|
+
Masks for layouts with the same number of dimensions can be combined
|
|
327
|
+
using the logical ``&`` (bitwise AND) operator.
|
|
328
|
+
|
|
329
|
+
.. highlight:: python
|
|
330
|
+
.. code-block:: python
|
|
331
|
+
|
|
332
|
+
layout = StridedLayout.dense((4, 5, 3), 4)
|
|
333
|
+
layout2 = StridedLayout((4, 5, 3), (1, 12, 4), 4)
|
|
334
|
+
# Even though the two layouts have the same shape initially,
|
|
335
|
+
# their shapes differ after flattening.
|
|
336
|
+
assert layout.flattened() == StridedLayout((60,), (1,), 4)
|
|
337
|
+
assert layout2.flattened() == StridedLayout((4, 15), (1, 4), 4)
|
|
338
|
+
# With the mask, only extents that are mergeable in both layouts are flattened
|
|
339
|
+
# and the resulting shape is the same for both layouts.
|
|
340
|
+
mask = layout.flattened_axis_mask() & layout2.flattened_axis_mask()
|
|
341
|
+
assert layout.flattened(mask=mask) == StridedLayout((4, 15), (15, 1), 4)
|
|
342
|
+
assert layout2.flattened(mask=mask) == StridedLayout((4, 15), (1, 4), 4)"""
|
|
343
|
+
@overload
|
|
344
|
+
def flattened(self) -> Any:
|
|
345
|
+
"""StridedLayout.flattened(self: StridedLayout, int start_axis: int = 0, int end_axis: int = -1, int mask: int | None = None) -> StridedLayout
|
|
346
|
+
|
|
347
|
+
Returns a layout where consecutive extents, if possible,
|
|
348
|
+
are merged into a single extent (equal to the product of merged extents).
|
|
349
|
+
Extents are mergeable if the corresponding sub-layout is c-leading-dense,
|
|
350
|
+
i.e. the corresponding strides can be replaced with a single
|
|
351
|
+
(the rightmost, and the smallest) stride.
|
|
352
|
+
Iterating over the indices of the the original and the flattened layout
|
|
353
|
+
in C-order (the rightmost axis incremented first) is equivalent.
|
|
354
|
+
|
|
355
|
+
Note, flattening a scalar turns the layout into 1D array.
|
|
356
|
+
|
|
357
|
+
.. highlight:: python
|
|
358
|
+
.. code-block:: python
|
|
359
|
+
|
|
360
|
+
# the two extents can be merged into a single extent
|
|
361
|
+
# because layout.strides[0] == layout.strides[1] * layout.shape[1]
|
|
362
|
+
layout = StridedLayout((3, 2), (2, 1), 1)
|
|
363
|
+
assert layout.flattened() == StridedLayout((6,), (1,), 1)
|
|
364
|
+
|
|
365
|
+
# the two extents cannot be merged into a single extent
|
|
366
|
+
# because layout.strides[0] != layout.strides[1] * layout.shape[1]
|
|
367
|
+
layout = StridedLayout((3, 2), (1, 3), 1)
|
|
368
|
+
assert layout.flattened() == layout
|
|
369
|
+
|
|
370
|
+
If ``start_axis`` and ``end_axis`` are provided, only the axes in the
|
|
371
|
+
inclusive range ``[start_axis, end_axis]`` are considered for flattening.
|
|
372
|
+
|
|
373
|
+
Alternatively, a mask specifying which axes to consider can be provided.
|
|
374
|
+
A mask of mergeable extents can be obtained using the :meth:`flattened_axis_mask` method.
|
|
375
|
+
Masks for layouts with the same number of dimensions can be combined
|
|
376
|
+
using the logical ``&`` (bitwise AND) operator.
|
|
377
|
+
|
|
378
|
+
.. highlight:: python
|
|
379
|
+
.. code-block:: python
|
|
380
|
+
|
|
381
|
+
layout = StridedLayout.dense((4, 5, 3), 4)
|
|
382
|
+
layout2 = StridedLayout((4, 5, 3), (1, 12, 4), 4)
|
|
383
|
+
# Even though the two layouts have the same shape initially,
|
|
384
|
+
# their shapes differ after flattening.
|
|
385
|
+
assert layout.flattened() == StridedLayout((60,), (1,), 4)
|
|
386
|
+
assert layout2.flattened() == StridedLayout((4, 15), (1, 4), 4)
|
|
387
|
+
# With the mask, only extents that are mergeable in both layouts are flattened
|
|
388
|
+
# and the resulting shape is the same for both layouts.
|
|
389
|
+
mask = layout.flattened_axis_mask() & layout2.flattened_axis_mask()
|
|
390
|
+
assert layout.flattened(mask=mask) == StridedLayout((4, 15), (15, 1), 4)
|
|
391
|
+
assert layout2.flattened(mask=mask) == StridedLayout((4, 15), (1, 4), 4)"""
|
|
392
|
+
@overload
|
|
393
|
+
def flattened(self, mask=...) -> Any:
|
|
394
|
+
"""StridedLayout.flattened(self: StridedLayout, int start_axis: int = 0, int end_axis: int = -1, int mask: int | None = None) -> StridedLayout
|
|
395
|
+
|
|
396
|
+
Returns a layout where consecutive extents, if possible,
|
|
397
|
+
are merged into a single extent (equal to the product of merged extents).
|
|
398
|
+
Extents are mergeable if the corresponding sub-layout is c-leading-dense,
|
|
399
|
+
i.e. the corresponding strides can be replaced with a single
|
|
400
|
+
(the rightmost, and the smallest) stride.
|
|
401
|
+
Iterating over the indices of the the original and the flattened layout
|
|
402
|
+
in C-order (the rightmost axis incremented first) is equivalent.
|
|
403
|
+
|
|
404
|
+
Note, flattening a scalar turns the layout into 1D array.
|
|
405
|
+
|
|
406
|
+
.. highlight:: python
|
|
407
|
+
.. code-block:: python
|
|
408
|
+
|
|
409
|
+
# the two extents can be merged into a single extent
|
|
410
|
+
# because layout.strides[0] == layout.strides[1] * layout.shape[1]
|
|
411
|
+
layout = StridedLayout((3, 2), (2, 1), 1)
|
|
412
|
+
assert layout.flattened() == StridedLayout((6,), (1,), 1)
|
|
413
|
+
|
|
414
|
+
# the two extents cannot be merged into a single extent
|
|
415
|
+
# because layout.strides[0] != layout.strides[1] * layout.shape[1]
|
|
416
|
+
layout = StridedLayout((3, 2), (1, 3), 1)
|
|
417
|
+
assert layout.flattened() == layout
|
|
418
|
+
|
|
419
|
+
If ``start_axis`` and ``end_axis`` are provided, only the axes in the
|
|
420
|
+
inclusive range ``[start_axis, end_axis]`` are considered for flattening.
|
|
421
|
+
|
|
422
|
+
Alternatively, a mask specifying which axes to consider can be provided.
|
|
423
|
+
A mask of mergeable extents can be obtained using the :meth:`flattened_axis_mask` method.
|
|
424
|
+
Masks for layouts with the same number of dimensions can be combined
|
|
425
|
+
using the logical ``&`` (bitwise AND) operator.
|
|
426
|
+
|
|
427
|
+
.. highlight:: python
|
|
428
|
+
.. code-block:: python
|
|
429
|
+
|
|
430
|
+
layout = StridedLayout.dense((4, 5, 3), 4)
|
|
431
|
+
layout2 = StridedLayout((4, 5, 3), (1, 12, 4), 4)
|
|
432
|
+
# Even though the two layouts have the same shape initially,
|
|
433
|
+
# their shapes differ after flattening.
|
|
434
|
+
assert layout.flattened() == StridedLayout((60,), (1,), 4)
|
|
435
|
+
assert layout2.flattened() == StridedLayout((4, 15), (1, 4), 4)
|
|
436
|
+
# With the mask, only extents that are mergeable in both layouts are flattened
|
|
437
|
+
# and the resulting shape is the same for both layouts.
|
|
438
|
+
mask = layout.flattened_axis_mask() & layout2.flattened_axis_mask()
|
|
439
|
+
assert layout.flattened(mask=mask) == StridedLayout((4, 15), (15, 1), 4)
|
|
440
|
+
assert layout2.flattened(mask=mask) == StridedLayout((4, 15), (1, 4), 4)"""
|
|
441
|
+
@overload
|
|
442
|
+
def flattened(self, mask=...) -> Any:
|
|
443
|
+
"""StridedLayout.flattened(self: StridedLayout, int start_axis: int = 0, int end_axis: int = -1, int mask: int | None = None) -> StridedLayout
|
|
444
|
+
|
|
445
|
+
Returns a layout where consecutive extents, if possible,
|
|
446
|
+
are merged into a single extent (equal to the product of merged extents).
|
|
447
|
+
Extents are mergeable if the corresponding sub-layout is c-leading-dense,
|
|
448
|
+
i.e. the corresponding strides can be replaced with a single
|
|
449
|
+
(the rightmost, and the smallest) stride.
|
|
450
|
+
Iterating over the indices of the the original and the flattened layout
|
|
451
|
+
in C-order (the rightmost axis incremented first) is equivalent.
|
|
452
|
+
|
|
453
|
+
Note, flattening a scalar turns the layout into 1D array.
|
|
454
|
+
|
|
455
|
+
.. highlight:: python
|
|
456
|
+
.. code-block:: python
|
|
457
|
+
|
|
458
|
+
# the two extents can be merged into a single extent
|
|
459
|
+
# because layout.strides[0] == layout.strides[1] * layout.shape[1]
|
|
460
|
+
layout = StridedLayout((3, 2), (2, 1), 1)
|
|
461
|
+
assert layout.flattened() == StridedLayout((6,), (1,), 1)
|
|
462
|
+
|
|
463
|
+
# the two extents cannot be merged into a single extent
|
|
464
|
+
# because layout.strides[0] != layout.strides[1] * layout.shape[1]
|
|
465
|
+
layout = StridedLayout((3, 2), (1, 3), 1)
|
|
466
|
+
assert layout.flattened() == layout
|
|
467
|
+
|
|
468
|
+
If ``start_axis`` and ``end_axis`` are provided, only the axes in the
|
|
469
|
+
inclusive range ``[start_axis, end_axis]`` are considered for flattening.
|
|
470
|
+
|
|
471
|
+
Alternatively, a mask specifying which axes to consider can be provided.
|
|
472
|
+
A mask of mergeable extents can be obtained using the :meth:`flattened_axis_mask` method.
|
|
473
|
+
Masks for layouts with the same number of dimensions can be combined
|
|
474
|
+
using the logical ``&`` (bitwise AND) operator.
|
|
475
|
+
|
|
476
|
+
.. highlight:: python
|
|
477
|
+
.. code-block:: python
|
|
478
|
+
|
|
479
|
+
layout = StridedLayout.dense((4, 5, 3), 4)
|
|
480
|
+
layout2 = StridedLayout((4, 5, 3), (1, 12, 4), 4)
|
|
481
|
+
# Even though the two layouts have the same shape initially,
|
|
482
|
+
# their shapes differ after flattening.
|
|
483
|
+
assert layout.flattened() == StridedLayout((60,), (1,), 4)
|
|
484
|
+
assert layout2.flattened() == StridedLayout((4, 15), (1, 4), 4)
|
|
485
|
+
# With the mask, only extents that are mergeable in both layouts are flattened
|
|
486
|
+
# and the resulting shape is the same for both layouts.
|
|
487
|
+
mask = layout.flattened_axis_mask() & layout2.flattened_axis_mask()
|
|
488
|
+
assert layout.flattened(mask=mask) == StridedLayout((4, 15), (15, 1), 4)
|
|
489
|
+
assert layout2.flattened(mask=mask) == StridedLayout((4, 15), (1, 4), 4)"""
|
|
490
|
+
def flattened_axis_mask(self) -> axes_mask_t:
|
|
491
|
+
"""StridedLayout.flattened_axis_mask(self: StridedLayout) -> axes_mask_t
|
|
492
|
+
|
|
493
|
+
A mask describing which axes of this layout are mergeable
|
|
494
|
+
using the :meth:`flattened` method."""
|
|
495
|
+
@overload
|
|
496
|
+
def has_stride_order(self, stride_order: Literal['C', 'F'] | tuple[int]) -> bool:
|
|
497
|
+
'''StridedLayout.has_stride_order(self: StridedLayout, stride_order: Literal[\'C\', \'F\'] | tuple[int]) -> bool
|
|
498
|
+
|
|
499
|
+
Checks if the layout has the specified stride order, i.e.
|
|
500
|
+
the absolute values of the strides are (non-strictly) monotonic in the specified order.
|
|
501
|
+
|
|
502
|
+
Please note, there\'s a subtle difference between
|
|
503
|
+
``layout.stride_order == some_permutation`` and ``layout.has_stride_order(some_permutation)``.
|
|
504
|
+
If the layout has unit extents, its stride is irrelevant and so
|
|
505
|
+
the ``layout.stride_order`` is not unique, so the former may be False,
|
|
506
|
+
while the latter is True.
|
|
507
|
+
|
|
508
|
+
.. highlight:: python
|
|
509
|
+
.. code-block:: python
|
|
510
|
+
|
|
511
|
+
layout = StridedLayout.dense((5, 3, 7), 1, "C")
|
|
512
|
+
assert layout.has_stride_order("C")
|
|
513
|
+
assert not layout.has_stride_order("F")
|
|
514
|
+
assert layout.has_stride_order((0, 1, 2))
|
|
515
|
+
assert not layout.has_stride_order((2, 1, 0))
|
|
516
|
+
|
|
517
|
+
# now, if we slice the layout so that it has unit extents
|
|
518
|
+
# and permute it
|
|
519
|
+
sliced = layout[..., -1:].layout.permuted((0, 2, 1))
|
|
520
|
+
# both (0, 1, 2) and (0, 2, 1) are valid stride orders
|
|
521
|
+
# but stride_order will return only one of them
|
|
522
|
+
assert sliced.stride_order != (0, 1, 2)
|
|
523
|
+
# while has_stride_order will return True for both
|
|
524
|
+
assert sliced.has_stride_order((0, 2, 1))
|
|
525
|
+
assert sliced.has_stride_order((2, 1, 0))
|
|
526
|
+
# and also just "C"
|
|
527
|
+
assert sliced.has_stride_order("C")'''
|
|
528
|
+
@overload
|
|
529
|
+
def has_stride_order(self, some_permutation) -> Any:
|
|
530
|
+
'''StridedLayout.has_stride_order(self: StridedLayout, stride_order: Literal[\'C\', \'F\'] | tuple[int]) -> bool
|
|
531
|
+
|
|
532
|
+
Checks if the layout has the specified stride order, i.e.
|
|
533
|
+
the absolute values of the strides are (non-strictly) monotonic in the specified order.
|
|
534
|
+
|
|
535
|
+
Please note, there\'s a subtle difference between
|
|
536
|
+
``layout.stride_order == some_permutation`` and ``layout.has_stride_order(some_permutation)``.
|
|
537
|
+
If the layout has unit extents, its stride is irrelevant and so
|
|
538
|
+
the ``layout.stride_order`` is not unique, so the former may be False,
|
|
539
|
+
while the latter is True.
|
|
540
|
+
|
|
541
|
+
.. highlight:: python
|
|
542
|
+
.. code-block:: python
|
|
543
|
+
|
|
544
|
+
layout = StridedLayout.dense((5, 3, 7), 1, "C")
|
|
545
|
+
assert layout.has_stride_order("C")
|
|
546
|
+
assert not layout.has_stride_order("F")
|
|
547
|
+
assert layout.has_stride_order((0, 1, 2))
|
|
548
|
+
assert not layout.has_stride_order((2, 1, 0))
|
|
549
|
+
|
|
550
|
+
# now, if we slice the layout so that it has unit extents
|
|
551
|
+
# and permute it
|
|
552
|
+
sliced = layout[..., -1:].layout.permuted((0, 2, 1))
|
|
553
|
+
# both (0, 1, 2) and (0, 2, 1) are valid stride orders
|
|
554
|
+
# but stride_order will return only one of them
|
|
555
|
+
assert sliced.stride_order != (0, 1, 2)
|
|
556
|
+
# while has_stride_order will return True for both
|
|
557
|
+
assert sliced.has_stride_order((0, 2, 1))
|
|
558
|
+
assert sliced.has_stride_order((2, 1, 0))
|
|
559
|
+
# and also just "C"
|
|
560
|
+
assert sliced.has_stride_order("C")'''
|
|
561
|
+
@overload
|
|
562
|
+
def is_almost_equal(self, StridedLayoutother: StridedLayout) -> bool:
|
|
563
|
+
'''StridedLayout.is_almost_equal(self: StridedLayout, StridedLayout other: StridedLayout) -> bool
|
|
564
|
+
|
|
565
|
+
Equality, but with relaxed checks for strides, i.e:
|
|
566
|
+
strides for unit extents are not compared
|
|
567
|
+
|
|
568
|
+
.. highlight:: python
|
|
569
|
+
.. code-block:: python
|
|
570
|
+
|
|
571
|
+
l1 = StridedLayout.dense((3, 1), 1, stride_order="C")
|
|
572
|
+
l2 = StridedLayout.dense((3, 1), 1, stride_order="F")
|
|
573
|
+
assert l1.shape == l2.shape
|
|
574
|
+
assert l1.strides == (1, 1)
|
|
575
|
+
assert l2.strides == (1, 3)
|
|
576
|
+
assert l1 != l2
|
|
577
|
+
assert l1.is_almost_equal(l2)'''
|
|
578
|
+
@overload
|
|
579
|
+
def is_almost_equal(self, l2) -> Any:
|
|
580
|
+
'''StridedLayout.is_almost_equal(self: StridedLayout, StridedLayout other: StridedLayout) -> bool
|
|
581
|
+
|
|
582
|
+
Equality, but with relaxed checks for strides, i.e:
|
|
583
|
+
strides for unit extents are not compared
|
|
584
|
+
|
|
585
|
+
.. highlight:: python
|
|
586
|
+
.. code-block:: python
|
|
587
|
+
|
|
588
|
+
l1 = StridedLayout.dense((3, 1), 1, stride_order="C")
|
|
589
|
+
l2 = StridedLayout.dense((3, 1), 1, stride_order="F")
|
|
590
|
+
assert l1.shape == l2.shape
|
|
591
|
+
assert l1.strides == (1, 1)
|
|
592
|
+
assert l2.strides == (1, 3)
|
|
593
|
+
assert l1 != l2
|
|
594
|
+
assert l1.is_almost_equal(l2)'''
|
|
595
|
+
def is_dense(self, stride_order: Literal['C', 'F', 'K'] | tuple[int] = ..., boolallow_negative_strides: bool = ..., boolallow_leading_dim_stride: bool = ...) -> bool:
|
|
596
|
+
'''StridedLayout.is_dense(self: StridedLayout, stride_order: Literal[\'C\', \'F\', \'K\'] | tuple[int] = \'C\', bool allow_negative_strides: bool = False, bool allow_leading_dim_stride: bool = False) -> bool
|
|
597
|
+
|
|
598
|
+
With the default settings (no negative strides, no padding),
|
|
599
|
+
it is equivalent to :attr:`is_contiguous_any` / :attr:`is_contiguous_c` / :attr:`is_contiguous_f`
|
|
600
|
+
(with stride order "K" / "C" / "F").
|
|
601
|
+
|
|
602
|
+
stride_order : str or tuple, optional
|
|
603
|
+
The order of the strides:
|
|
604
|
+
|
|
605
|
+
* \'C\' - is the layout dense in C-order (from the right to the left)
|
|
606
|
+
* \'F\' - is the layout dense in F-order (from the left to the right)
|
|
607
|
+
* \'K\' - is there any ``stride_order`` such that layout dense
|
|
608
|
+
(eqiv. is the layout dense in :attr:`stride_order` order)
|
|
609
|
+
* A tuple - it must be a permutation of ``tuple(range(len(shape)))``.
|
|
610
|
+
Is the layout dense in the specified order (e.g. for a 3D layout,
|
|
611
|
+
``(0, 1, 2)`` is equivalent to C-order and ``(2, 1, 0)`` is equivalent to F-order)
|
|
612
|
+
|
|
613
|
+
The default notion of "contiguity" (as in :attr:`is_contiguous_any`, :attr:`is_contiguous_c`,
|
|
614
|
+
:attr:`is_contiguous_f`) is rather strict. It enforces that:
|
|
615
|
+
|
|
616
|
+
* the strides can be computed from the shape and stride order only, in particular:
|
|
617
|
+
|
|
618
|
+
- the strides are non-negative
|
|
619
|
+
- the leading dimension stride is 1
|
|
620
|
+
* iterating over indices in the stride order always gives +1 element offset increment
|
|
621
|
+
* the mapping from indices to element offsets is bijective, in particular:
|
|
622
|
+
|
|
623
|
+
- the element offsets range is ``[0, volume - 1]``
|
|
624
|
+
- the mapping is 1-to-1, i.e. the layout is unique (as in :attr:`is_unique`)
|
|
625
|
+
- the mapping is onto, i.e. the layout is exhaustive (as in :attr:`is_exhaustive`)
|
|
626
|
+
|
|
627
|
+
Thanks to the strictness of the definition, layouts reported as C or F have a lot of
|
|
628
|
+
nice properties, and thus should be generally safe to use with other libraries that
|
|
629
|
+
expect contiguous layouts.
|
|
630
|
+
However, there are cases where this notion may be too restrictive.
|
|
631
|
+
|
|
632
|
+
allow_negative_strides : bool, optional, default=False
|
|
633
|
+
If True, it computes the contiguity check on the absolute values of the strides.
|
|
634
|
+
As a result, properties 1. (strides as a function of shape) and 2. (+1 increments)
|
|
635
|
+
no longer hold. However, the mapping from indices to element offsets is still bijective,
|
|
636
|
+
only the element offsets range may now be shifted
|
|
637
|
+
(not ``[0, volume - 1]``, but ``[min_offset, max_offset]``,
|
|
638
|
+
such that max_offset - min_offset + 1 == volume).
|
|
639
|
+
This can still be a useful property - for example, if we want to perform elementwise operation
|
|
640
|
+
on tensors with equal strides that are abs-dense, we can just process them as if they
|
|
641
|
+
were flat arrays containing all elements in the range ``[min_offset, max_offset]``
|
|
642
|
+
|
|
643
|
+
Note, the is_dense("K", allow_negative_strides=True) is True iff
|
|
644
|
+
both :attr:`is_unique` and :attr:`is_exhaustive` are True.
|
|
645
|
+
|
|
646
|
+
allow_leading_dim_stride : bool, optional, default=False
|
|
647
|
+
If True, it allows the leading dimension stride (the stride with smallest abs value)
|
|
648
|
+
to be greater than 1.
|
|
649
|
+
As a result, properties 1. (strides as a function of shape) and 2. (+1 increments)
|
|
650
|
+
no longer hold. However, the mapping from indices to element offsets is still bijective,
|
|
651
|
+
only the element offsets range is now "strided" with the step equal to the leading dimension stride.
|
|
652
|
+
(``[k * ldim_stride for k in range(min_offset // ldim_stride, max_offset // ldim_stride + 1)]``).
|
|
653
|
+
As an example, consider the leading dimension to represent a batch. With this check, we ensure
|
|
654
|
+
that a single sample occupies unique memory offsets and does not introduce any more gaps
|
|
655
|
+
(than the leading dim "step"). If we can combine ``ldim_stride`` consecutive samples,
|
|
656
|
+
we end up with regular contiguous layout.'''
|
|
657
|
+
def max_compatible_itemsize(self, intmax_itemsize: int = ..., intptr_tdata_ptr: intptr_t = ..., intaxis: int = ...) -> int:
|
|
658
|
+
"""StridedLayout.max_compatible_itemsize(self: StridedLayout, int max_itemsize: int = 16, intptr_t data_ptr: intptr_t = 0, int axis: int = -1) -> int
|
|
659
|
+
|
|
660
|
+
Returns the maximum itemsize (but no greater than ``max_itemsize``) that can be used
|
|
661
|
+
with the :meth:`packed` method for the current layout."""
|
|
662
|
+
def packed(self, intitemsize: int, intptr_tdata_ptr: intptr_t = ..., intaxis: int = ..., boolkeep_dim: bool = ...) -> StridedLayout:
|
|
663
|
+
"""StridedLayout.packed(self: StridedLayout, int itemsize: int, intptr_t data_ptr: intptr_t = 0, int axis: int = -1, bool keep_dim: bool = True) -> StridedLayout
|
|
664
|
+
|
|
665
|
+
Converts the layout to the specified itemsize.
|
|
666
|
+
The new itemsize must be greater or equal to the old itemsize.
|
|
667
|
+
Consecutive ``new_itemsize // old_itemsize`` elements in the ``axis`` dimension
|
|
668
|
+
are **packed** into a single element, i.e. the extent at ``axis`` is divided by
|
|
669
|
+
``new_itemsize // old_itemsize``.
|
|
670
|
+
In particular, the volume of the new layout decreases, but
|
|
671
|
+
the ``volume * itemsize`` remains the same.
|
|
672
|
+
|
|
673
|
+
The conversion is subject to the following constraints:
|
|
674
|
+
* The old and new itemsizes must be powers of two.
|
|
675
|
+
* The ``shape[axis]`` must be a positive integer divisible
|
|
676
|
+
by ``new_itemsize // old_itemsize``.
|
|
677
|
+
* The ``strides[axis]`` must be 1.
|
|
678
|
+
* All other ``strides`` must be divisible by ``new_itemsize // old_itemsize``.
|
|
679
|
+
* If ``data_ptr`` is provided, it must be aligned to (divisible by) the new itemsize.
|
|
680
|
+
|
|
681
|
+
A maximum itemsize that satisfies all the above constraints
|
|
682
|
+
can be obtained using the :meth:`max_compatible_itemsize` method.
|
|
683
|
+
|
|
684
|
+
If the ``keep_dim`` is False and the extent at ``axis`` would be reduced to 1,
|
|
685
|
+
it is omitted from the returned layout.
|
|
686
|
+
|
|
687
|
+
.. highlight:: python
|
|
688
|
+
.. code-block:: python
|
|
689
|
+
|
|
690
|
+
layout = StridedLayout.dense((5, 4), 4)
|
|
691
|
+
assert layout.packed(4) is layout
|
|
692
|
+
assert layout.packed(8) == StridedLayout.dense((5, 2), 8)
|
|
693
|
+
assert layout.packed(16) == StridedLayout.dense((5, 1), 16)
|
|
694
|
+
assert layout.packed(16, keep_dim=False) == StridedLayout.dense((5,), 16)
|
|
695
|
+
|
|
696
|
+
|
|
697
|
+
.. highlight:: python
|
|
698
|
+
.. code-block:: python
|
|
699
|
+
|
|
700
|
+
# Viewing (5, 6) float array as (5, 3) complex64 array.
|
|
701
|
+
a_real = numpy.arange(30, dtype=numpy.float32).reshape((5, 6))
|
|
702
|
+
a_complex = a_real.view(numpy.complex64)
|
|
703
|
+
|
|
704
|
+
real_layout = StridedLayout(a_real.shape, a_real.strides, a_real.itemsize, divide_strides=True)
|
|
705
|
+
assert real_layout.shape == a_real.shape == (5, 6)
|
|
706
|
+
assert real_layout.strides_in_bytes == a_real.strides
|
|
707
|
+
assert real_layout.itemsize == a_real.itemsize == 4
|
|
708
|
+
complex_layout = real_layout.packed(8)
|
|
709
|
+
assert complex_layout.shape == a_complex.shape == (5, 3)
|
|
710
|
+
assert complex_layout.strides_in_bytes == a_complex.strides
|
|
711
|
+
assert complex_layout.itemsize == 8"""
|
|
712
|
+
@overload
|
|
713
|
+
def permuted(self, tupleaxis_order: tuple[int], boolinverse: bool = ...) -> StridedLayout:
|
|
714
|
+
"""StridedLayout.permuted(self: StridedLayout, tuple axis_order: tuple[int], bool inverse: bool = False) -> StridedLayout
|
|
715
|
+
|
|
716
|
+
Returns a layout where the shape and strides tuples are permuted
|
|
717
|
+
according to the specified permutation of axes.
|
|
718
|
+
If inverse is set to True, the output layout is permuted by the inverse
|
|
719
|
+
permutation (or, equivalently, permuting the output layout by the specified
|
|
720
|
+
permutation gives the input layout).
|
|
721
|
+
|
|
722
|
+
.. highlight:: python
|
|
723
|
+
.. code-block:: python
|
|
724
|
+
|
|
725
|
+
shape = (3, 4, 5)
|
|
726
|
+
layout = StridedLayout.dense(shape, 1)
|
|
727
|
+
perm = (1, 2, 0)
|
|
728
|
+
inv_perm = (2, 0, 1)
|
|
729
|
+
|
|
730
|
+
layout_perm = layout.permuted(perm)
|
|
731
|
+
assert layout_perm.shape == tuple(shape[p] for p in perm)
|
|
732
|
+
|
|
733
|
+
layout_inv_perm = layout.permuted(perm, inverse=True)
|
|
734
|
+
assert tuple(layout_inv_perm.shape[p] for p in perm) == shape
|
|
735
|
+
assert layout_inv_perm.shape == tuple(shape[p] for p in inv_perm)
|
|
736
|
+
assert layout_inv_perm == layout.permuted(inv_perm)
|
|
737
|
+
|
|
738
|
+
assert layout.permuted(perm).permuted(perm, inverse=True) == layout"""
|
|
739
|
+
@overload
|
|
740
|
+
def permuted(self, perm) -> Any:
|
|
741
|
+
"""StridedLayout.permuted(self: StridedLayout, tuple axis_order: tuple[int], bool inverse: bool = False) -> StridedLayout
|
|
742
|
+
|
|
743
|
+
Returns a layout where the shape and strides tuples are permuted
|
|
744
|
+
according to the specified permutation of axes.
|
|
745
|
+
If inverse is set to True, the output layout is permuted by the inverse
|
|
746
|
+
permutation (or, equivalently, permuting the output layout by the specified
|
|
747
|
+
permutation gives the input layout).
|
|
748
|
+
|
|
749
|
+
.. highlight:: python
|
|
750
|
+
.. code-block:: python
|
|
751
|
+
|
|
752
|
+
shape = (3, 4, 5)
|
|
753
|
+
layout = StridedLayout.dense(shape, 1)
|
|
754
|
+
perm = (1, 2, 0)
|
|
755
|
+
inv_perm = (2, 0, 1)
|
|
756
|
+
|
|
757
|
+
layout_perm = layout.permuted(perm)
|
|
758
|
+
assert layout_perm.shape == tuple(shape[p] for p in perm)
|
|
759
|
+
|
|
760
|
+
layout_inv_perm = layout.permuted(perm, inverse=True)
|
|
761
|
+
assert tuple(layout_inv_perm.shape[p] for p in perm) == shape
|
|
762
|
+
assert layout_inv_perm.shape == tuple(shape[p] for p in inv_perm)
|
|
763
|
+
assert layout_inv_perm == layout.permuted(inv_perm)
|
|
764
|
+
|
|
765
|
+
assert layout.permuted(perm).permuted(perm, inverse=True) == layout"""
|
|
766
|
+
@overload
|
|
767
|
+
def permuted(self, perm, inverse=...) -> Any:
|
|
768
|
+
"""StridedLayout.permuted(self: StridedLayout, tuple axis_order: tuple[int], bool inverse: bool = False) -> StridedLayout
|
|
769
|
+
|
|
770
|
+
Returns a layout where the shape and strides tuples are permuted
|
|
771
|
+
according to the specified permutation of axes.
|
|
772
|
+
If inverse is set to True, the output layout is permuted by the inverse
|
|
773
|
+
permutation (or, equivalently, permuting the output layout by the specified
|
|
774
|
+
permutation gives the input layout).
|
|
775
|
+
|
|
776
|
+
.. highlight:: python
|
|
777
|
+
.. code-block:: python
|
|
778
|
+
|
|
779
|
+
shape = (3, 4, 5)
|
|
780
|
+
layout = StridedLayout.dense(shape, 1)
|
|
781
|
+
perm = (1, 2, 0)
|
|
782
|
+
inv_perm = (2, 0, 1)
|
|
783
|
+
|
|
784
|
+
layout_perm = layout.permuted(perm)
|
|
785
|
+
assert layout_perm.shape == tuple(shape[p] for p in perm)
|
|
786
|
+
|
|
787
|
+
layout_inv_perm = layout.permuted(perm, inverse=True)
|
|
788
|
+
assert tuple(layout_inv_perm.shape[p] for p in perm) == shape
|
|
789
|
+
assert layout_inv_perm.shape == tuple(shape[p] for p in inv_perm)
|
|
790
|
+
assert layout_inv_perm == layout.permuted(inv_perm)
|
|
791
|
+
|
|
792
|
+
assert layout.permuted(perm).permuted(perm, inverse=True) == layout"""
|
|
793
|
+
@overload
|
|
794
|
+
def permuted(self, inv_perm) -> Any:
|
|
795
|
+
"""StridedLayout.permuted(self: StridedLayout, tuple axis_order: tuple[int], bool inverse: bool = False) -> StridedLayout
|
|
796
|
+
|
|
797
|
+
Returns a layout where the shape and strides tuples are permuted
|
|
798
|
+
according to the specified permutation of axes.
|
|
799
|
+
If inverse is set to True, the output layout is permuted by the inverse
|
|
800
|
+
permutation (or, equivalently, permuting the output layout by the specified
|
|
801
|
+
permutation gives the input layout).
|
|
802
|
+
|
|
803
|
+
.. highlight:: python
|
|
804
|
+
.. code-block:: python
|
|
805
|
+
|
|
806
|
+
shape = (3, 4, 5)
|
|
807
|
+
layout = StridedLayout.dense(shape, 1)
|
|
808
|
+
perm = (1, 2, 0)
|
|
809
|
+
inv_perm = (2, 0, 1)
|
|
810
|
+
|
|
811
|
+
layout_perm = layout.permuted(perm)
|
|
812
|
+
assert layout_perm.shape == tuple(shape[p] for p in perm)
|
|
813
|
+
|
|
814
|
+
layout_inv_perm = layout.permuted(perm, inverse=True)
|
|
815
|
+
assert tuple(layout_inv_perm.shape[p] for p in perm) == shape
|
|
816
|
+
assert layout_inv_perm.shape == tuple(shape[p] for p in inv_perm)
|
|
817
|
+
assert layout_inv_perm == layout.permuted(inv_perm)
|
|
818
|
+
|
|
819
|
+
assert layout.permuted(perm).permuted(perm, inverse=True) == layout"""
|
|
820
|
+
def reshaped(self, shape: tuple[int] | StridedLayout | int) -> StridedLayout:
|
|
821
|
+
"""StridedLayout.reshaped(self: StridedLayout, shape: tuple[int] | StridedLayout | int) -> StridedLayout
|
|
822
|
+
|
|
823
|
+
Returns a layout with the new shape, if the new shape is compatible
|
|
824
|
+
with the current layout.
|
|
825
|
+
|
|
826
|
+
The new shape is compatible if:
|
|
827
|
+
* the new and old shapes have the same volume
|
|
828
|
+
* the old strides can be split or flattened to match the new shape,
|
|
829
|
+
assuming indices are iterated in C-order
|
|
830
|
+
|
|
831
|
+
A single extent in the ``shape`` tuple can be set to -1 to indicate
|
|
832
|
+
it should be inferred from the old volume and the other extents.
|
|
833
|
+
|
|
834
|
+
.. highlight:: python
|
|
835
|
+
.. code-block:: python
|
|
836
|
+
|
|
837
|
+
layout = StridedLayout.dense((5, 3, 4), 1)
|
|
838
|
+
assert layout.reshaped((20, 3)) == StridedLayout.dense((20, 3), 1)
|
|
839
|
+
assert layout.reshaped((4, -1)) == StridedLayout.dense((4, 15), 1)
|
|
840
|
+
assert layout.permuted((2, 0, 1)).reshaped((4, 15,)) == StridedLayout((4, 15), (1, 4), 1)
|
|
841
|
+
# layout.permuted((2, 0, 1)).reshaped((20, 3)) -> error"""
|
|
842
|
+
@overload
|
|
843
|
+
def reversed(self) -> StridedLayout:
|
|
844
|
+
"""StridedLayout.reversed(self: StridedLayout) -> StridedLayout
|
|
845
|
+
|
|
846
|
+
Returns ``StridedLayout(reversed(layout.shape), reversed(layout.strides), layout.itemsize)``.
|
|
847
|
+
|
|
848
|
+
.. highlight:: python
|
|
849
|
+
.. code-block:: python
|
|
850
|
+
|
|
851
|
+
layout = StridedLayout.dense((5, 3, 4), 1)
|
|
852
|
+
assert layout == StridedLayout((5, 3, 4), (12, 4, 1), 1)
|
|
853
|
+
assert layout.reversed() == StridedLayout((4, 3, 5), (1, 4, 12), 1)
|
|
854
|
+
assert layout.reversed() == StridedLayout(reversed(layout.shape), reversed(layout.strides), layout.itemsize)"""
|
|
855
|
+
@overload
|
|
856
|
+
def reversed(self) -> Any:
|
|
857
|
+
"""StridedLayout.reversed(self: StridedLayout) -> StridedLayout
|
|
858
|
+
|
|
859
|
+
Returns ``StridedLayout(reversed(layout.shape), reversed(layout.strides), layout.itemsize)``.
|
|
860
|
+
|
|
861
|
+
.. highlight:: python
|
|
862
|
+
.. code-block:: python
|
|
863
|
+
|
|
864
|
+
layout = StridedLayout.dense((5, 3, 4), 1)
|
|
865
|
+
assert layout == StridedLayout((5, 3, 4), (12, 4, 1), 1)
|
|
866
|
+
assert layout.reversed() == StridedLayout((4, 3, 5), (1, 4, 12), 1)
|
|
867
|
+
assert layout.reversed() == StridedLayout(reversed(layout.shape), reversed(layout.strides), layout.itemsize)"""
|
|
868
|
+
def squeezed(self, axis: int | tuple[int] | None = ..., intmask: int | None = ...) -> StridedLayout:
|
|
869
|
+
"""StridedLayout.squeezed(self: StridedLayout, axis: int | tuple[int] | None = None, int mask: int | None = None) -> StridedLayout
|
|
870
|
+
|
|
871
|
+
Returns a layout where all the unit dimensions (extents equal to 1)
|
|
872
|
+
are removed.
|
|
873
|
+
|
|
874
|
+
To limit which axes are considered for squeezing, either the ``axis`` parameter
|
|
875
|
+
or the ``mask`` parameter can be used.
|
|
876
|
+
|
|
877
|
+
* If ``axis`` is provided, it must be an integer or a tuple of unique integers
|
|
878
|
+
in range ``[0, ndim)``, only those axes are considered for squeezing.
|
|
879
|
+
* Otherwise, if ``mask`` is provided, only the axes specified by the mask are considered
|
|
880
|
+
(shape[axis] is removed iff ``shape[axis] == 1 and (mask & (1 << axis))``)."""
|
|
881
|
+
def squeezed_range(self, intstart_axis: int = ..., intend_axis: int = ...) -> StridedLayout:
|
|
882
|
+
"""StridedLayout.squeezed_range(self: StridedLayout, int start_axis: int = 0, int end_axis: int = -1) -> StridedLayout
|
|
883
|
+
|
|
884
|
+
Returns a layout where all the unit dimensions (extents equal to 1)
|
|
885
|
+
in inclusive range ``[start_axis, end_axis]`` are removed."""
|
|
886
|
+
def sub(self, intstart_axis: int = ..., intend_axis: int = ..., tupleaxes: tuple[int] | None = ...) -> StridedLayout:
|
|
887
|
+
"""StridedLayout.sub(self: StridedLayout, int start_axis: int = 0, int end_axis: int = -1, tuple axes: tuple[int] | None = None) -> StridedLayout
|
|
888
|
+
|
|
889
|
+
Returns a sub-layout consisting of the specified axes.
|
|
890
|
+
|
|
891
|
+
The axes to copy can be specified by:
|
|
892
|
+
* The ``axes`` tuple of integers in range ``[0, ndim]``.
|
|
893
|
+
The order of ``axes`` in the tuple determines the order of axes in the sub-layout.
|
|
894
|
+
* If the ``axes`` tuple is not provided, the inclusive range ``[start_axis, end_axis]``
|
|
895
|
+
is copied."""
|
|
896
|
+
def to_dense(self, stride_order=...) -> StridedLayout:
|
|
897
|
+
"""StridedLayout.to_dense(self: StridedLayout, stride_order='K') -> StridedLayout
|
|
898
|
+
|
|
899
|
+
Returns a contiguous layout with the same shape and itemsize,
|
|
900
|
+
but with contiguous strides in the specified order.
|
|
901
|
+
|
|
902
|
+
.. note::
|
|
903
|
+
The returned layout is guaranteed to be contiguous, i.e. :attr:`is_contiguous_any` is True.
|
|
904
|
+
Layout can be dense in a less strict sense (e.g. having negative strides but still bijective),
|
|
905
|
+
such layouts are still converted to meet the strict definition of contiguous layout.
|
|
906
|
+
|
|
907
|
+
See :meth:`dense_like` method documentation for details.
|
|
908
|
+
|
|
909
|
+
See also :meth:`is_contiguous_any`.
|
|
910
|
+
See also :meth:`is_dense`."""
|
|
911
|
+
def transposed(self, intaxis_a: int, intaxis_b: int) -> StridedLayout:
|
|
912
|
+
"""StridedLayout.transposed(self: StridedLayout, int axis_a: int, int axis_b: int) -> StridedLayout
|
|
913
|
+
|
|
914
|
+
Returns a layout where the two specified axes are swapped."""
|
|
915
|
+
def unbroadcast(self) -> StridedLayout:
|
|
916
|
+
"""StridedLayout.unbroadcast(self: StridedLayout) -> StridedLayout
|
|
917
|
+
|
|
918
|
+
Returns a layout where extents with stride 0 are replaced
|
|
919
|
+
with unit extents (extent = 1, stride = 0)."""
|
|
920
|
+
def unit_extents_mask(self) -> axes_mask_t:
|
|
921
|
+
"""StridedLayout.unit_extents_mask(self: StridedLayout) -> axes_mask_t
|
|
922
|
+
|
|
923
|
+
A mask of axes that have extent equal to 1.
|
|
924
|
+
I.e. ``layout.unit_extents & (1 << axis) iff layout.shape[axis] == 1``,
|
|
925
|
+
in particular ``layout.unit_extents == 0`` iff there are no unit extents.
|
|
926
|
+
|
|
927
|
+
:type: axes_mask_t"""
|
|
928
|
+
def unpacked(self, intitemsize: int, intaxis: int = ..., booladd_dim: bool = ...) -> StridedLayout:
|
|
929
|
+
"""StridedLayout.unpacked(self: StridedLayout, int itemsize: int, int axis: int = -1, bool add_dim: bool = False) -> StridedLayout
|
|
930
|
+
|
|
931
|
+
Converts the layout to match the specified itemsize.
|
|
932
|
+
The new itemsize must be less than or equal to the old itemsize.
|
|
933
|
+
Every element in the tensor is **unpacked** into ``old_itemsize // new_itemsize`` elements,
|
|
934
|
+
along the ``axis`` dimension.
|
|
935
|
+
In particular, the volume of the new layout increases, but
|
|
936
|
+
the ``volume * itemsize`` remains the same.
|
|
937
|
+
|
|
938
|
+
If the ``add_dim`` is False, the extent at ``axis`` is multiplied by ``old_itemsize // new_itemsize``.
|
|
939
|
+
Otherwise a new dimension of size ``old_itemsize // new_itemsize`` (and stride 1) is added
|
|
940
|
+
before the ``axis`` dimension.
|
|
941
|
+
|
|
942
|
+
The conversion is subject to the following constraints:
|
|
943
|
+
* The old and new itemsizes must be powers of two.
|
|
944
|
+
If ``add_dim`` is False:
|
|
945
|
+
* The extent at ``axis`` must be a positive integer.
|
|
946
|
+
* The stride at ``axis`` must be 1.
|
|
947
|
+
|
|
948
|
+
.. highlight:: python
|
|
949
|
+
.. code-block:: python
|
|
950
|
+
|
|
951
|
+
layout = StridedLayout.dense((5, 4), 4)
|
|
952
|
+
assert layout.unpacked(4) is layout
|
|
953
|
+
assert layout.unpacked(2) == StridedLayout.dense((5, 8), 2)
|
|
954
|
+
assert layout.unpacked(2, add_dim=True) == StridedLayout.dense((5, 4, 2), 2)
|
|
955
|
+
assert layout.unpacked(1) == StridedLayout.dense((5, 16), 1)
|
|
956
|
+
assert layout.unpacked(1, add_dim=True) == StridedLayout.dense((5, 4, 4), 1)
|
|
957
|
+
|
|
958
|
+
|
|
959
|
+
.. highlight:: python
|
|
960
|
+
.. code-block:: python
|
|
961
|
+
|
|
962
|
+
# Prepare 5x3 complex64 (itemsize = 8) array
|
|
963
|
+
ac = numpy.zeros((5, 3), dtype=numpy.complex64)
|
|
964
|
+
ac.real += numpy.arange(15, dtype=numpy.float32).reshape((5, 3))
|
|
965
|
+
ac.imag -= numpy.arange(15, dtype=numpy.float32).reshape((5, 3))
|
|
966
|
+
complex_l = StridedLayout(ac.shape, ac.strides, ac.itemsize, divide_strides=True)
|
|
967
|
+
|
|
968
|
+
# unpack into 5x6 float32 (itemsize = 4) array
|
|
969
|
+
real_l = complex_l.unpacked(4)
|
|
970
|
+
assert real_l == StridedLayout((5, 6), (6, 1), 4)
|
|
971
|
+
ar = ac.view(numpy.float32)
|
|
972
|
+
assert real_l.shape == ar.shape == (5, 6)
|
|
973
|
+
assert real_l.strides_in_bytes == ar.strides
|
|
974
|
+
assert real_l.itemsize == ar.itemsize == 4
|
|
975
|
+
|
|
976
|
+
# unpack into batch of two float32 5x3 matrices
|
|
977
|
+
real_l_batch = complex_l.unpacked(4, axis=0, add_dim=True)
|
|
978
|
+
assert real_l_batch == StridedLayout((2, 5, 3), (1, 6, 2), 4)
|
|
979
|
+
ar_batch = numpy.lib.stride_tricks.as_strided(
|
|
980
|
+
ar,
|
|
981
|
+
shape=real_l_batch.shape,
|
|
982
|
+
strides=real_l_batch.strides_in_bytes
|
|
983
|
+
)
|
|
984
|
+
numpy.testing.assert_array_equal(ar_batch[0], ac.real)
|
|
985
|
+
numpy.testing.assert_array_equal(ar_batch[1], ac.imag)"""
|
|
986
|
+
@overload
|
|
987
|
+
def unsqueezed(self, axis: int | tuple[int] | None = ..., intmask: int = ...) -> StridedLayout:
|
|
988
|
+
"""StridedLayout.unsqueezed(self: StridedLayout, axis: int | tuple[int] | None = None, int mask: int = 0) -> StridedLayout
|
|
989
|
+
|
|
990
|
+
Returns a layout where the specified axis or axes are added as unit extents.
|
|
991
|
+
The ``axis`` can be either a single integer in range ``[0, ndim]``
|
|
992
|
+
or a tuple of unique integers in range ``[0, ndim + len(axis) - 1]``.
|
|
993
|
+
Alternatively, the axes can be specified as a mask with bits set
|
|
994
|
+
for the axes to be added.
|
|
995
|
+
|
|
996
|
+
Note, squeezing and unsqueezing a layout can be used as a way to normalize
|
|
997
|
+
the strides of unit dimensions.
|
|
998
|
+
|
|
999
|
+
.. highlight:: python
|
|
1000
|
+
.. code-block:: python
|
|
1001
|
+
|
|
1002
|
+
# The three layouts are equvialent, they have the same shape and
|
|
1003
|
+
# differ only in the strides of unit dimensions.
|
|
1004
|
+
l1 = StridedLayout.dense((5, 4, 3), 1)[-1:, :, :1].layout
|
|
1005
|
+
l2 = StridedLayout.dense((5, 4, 3), 1)[::5, :, ::3].layout
|
|
1006
|
+
l3 = StridedLayout.dense((5, 4, 3), 1)[::-1, :, ::-1][-1:, :, :1].layout
|
|
1007
|
+
|
|
1008
|
+
assert l1.shape == l2.shape == l3.shape == (1, 4, 1)
|
|
1009
|
+
assert l1.strides == (12, 3, 1)
|
|
1010
|
+
assert l2.strides == (60, 3, 3)
|
|
1011
|
+
assert l3.strides == (-12, 3, -1)
|
|
1012
|
+
|
|
1013
|
+
l1 = l1.squeezed().unsqueezed(mask=l1.unit_extents_mask())
|
|
1014
|
+
l2 = l2.squeezed().unsqueezed(mask=l2.unit_extents_mask())
|
|
1015
|
+
l3 = l3.squeezed().unsqueezed(mask=l3.unit_extents_mask())
|
|
1016
|
+
|
|
1017
|
+
assert l1.shape == l2.shape == l3.shape == (1, 4, 1)
|
|
1018
|
+
assert l1.strides == l2.strides == l3.strides == (12, 3, 3)"""
|
|
1019
|
+
@overload
|
|
1020
|
+
def unsqueezed(self, mask=...) -> Any:
|
|
1021
|
+
"""StridedLayout.unsqueezed(self: StridedLayout, axis: int | tuple[int] | None = None, int mask: int = 0) -> StridedLayout
|
|
1022
|
+
|
|
1023
|
+
Returns a layout where the specified axis or axes are added as unit extents.
|
|
1024
|
+
The ``axis`` can be either a single integer in range ``[0, ndim]``
|
|
1025
|
+
or a tuple of unique integers in range ``[0, ndim + len(axis) - 1]``.
|
|
1026
|
+
Alternatively, the axes can be specified as a mask with bits set
|
|
1027
|
+
for the axes to be added.
|
|
1028
|
+
|
|
1029
|
+
Note, squeezing and unsqueezing a layout can be used as a way to normalize
|
|
1030
|
+
the strides of unit dimensions.
|
|
1031
|
+
|
|
1032
|
+
.. highlight:: python
|
|
1033
|
+
.. code-block:: python
|
|
1034
|
+
|
|
1035
|
+
# The three layouts are equvialent, they have the same shape and
|
|
1036
|
+
# differ only in the strides of unit dimensions.
|
|
1037
|
+
l1 = StridedLayout.dense((5, 4, 3), 1)[-1:, :, :1].layout
|
|
1038
|
+
l2 = StridedLayout.dense((5, 4, 3), 1)[::5, :, ::3].layout
|
|
1039
|
+
l3 = StridedLayout.dense((5, 4, 3), 1)[::-1, :, ::-1][-1:, :, :1].layout
|
|
1040
|
+
|
|
1041
|
+
assert l1.shape == l2.shape == l3.shape == (1, 4, 1)
|
|
1042
|
+
assert l1.strides == (12, 3, 1)
|
|
1043
|
+
assert l2.strides == (60, 3, 3)
|
|
1044
|
+
assert l3.strides == (-12, 3, -1)
|
|
1045
|
+
|
|
1046
|
+
l1 = l1.squeezed().unsqueezed(mask=l1.unit_extents_mask())
|
|
1047
|
+
l2 = l2.squeezed().unsqueezed(mask=l2.unit_extents_mask())
|
|
1048
|
+
l3 = l3.squeezed().unsqueezed(mask=l3.unit_extents_mask())
|
|
1049
|
+
|
|
1050
|
+
assert l1.shape == l2.shape == l3.shape == (1, 4, 1)
|
|
1051
|
+
assert l1.strides == l2.strides == l3.strides == (12, 3, 3)"""
|
|
1052
|
+
@overload
|
|
1053
|
+
def unsqueezed(self, mask=...) -> Any:
|
|
1054
|
+
"""StridedLayout.unsqueezed(self: StridedLayout, axis: int | tuple[int] | None = None, int mask: int = 0) -> StridedLayout
|
|
1055
|
+
|
|
1056
|
+
Returns a layout where the specified axis or axes are added as unit extents.
|
|
1057
|
+
The ``axis`` can be either a single integer in range ``[0, ndim]``
|
|
1058
|
+
or a tuple of unique integers in range ``[0, ndim + len(axis) - 1]``.
|
|
1059
|
+
Alternatively, the axes can be specified as a mask with bits set
|
|
1060
|
+
for the axes to be added.
|
|
1061
|
+
|
|
1062
|
+
Note, squeezing and unsqueezing a layout can be used as a way to normalize
|
|
1063
|
+
the strides of unit dimensions.
|
|
1064
|
+
|
|
1065
|
+
.. highlight:: python
|
|
1066
|
+
.. code-block:: python
|
|
1067
|
+
|
|
1068
|
+
# The three layouts are equvialent, they have the same shape and
|
|
1069
|
+
# differ only in the strides of unit dimensions.
|
|
1070
|
+
l1 = StridedLayout.dense((5, 4, 3), 1)[-1:, :, :1].layout
|
|
1071
|
+
l2 = StridedLayout.dense((5, 4, 3), 1)[::5, :, ::3].layout
|
|
1072
|
+
l3 = StridedLayout.dense((5, 4, 3), 1)[::-1, :, ::-1][-1:, :, :1].layout
|
|
1073
|
+
|
|
1074
|
+
assert l1.shape == l2.shape == l3.shape == (1, 4, 1)
|
|
1075
|
+
assert l1.strides == (12, 3, 1)
|
|
1076
|
+
assert l2.strides == (60, 3, 3)
|
|
1077
|
+
assert l3.strides == (-12, 3, -1)
|
|
1078
|
+
|
|
1079
|
+
l1 = l1.squeezed().unsqueezed(mask=l1.unit_extents_mask())
|
|
1080
|
+
l2 = l2.squeezed().unsqueezed(mask=l2.unit_extents_mask())
|
|
1081
|
+
l3 = l3.squeezed().unsqueezed(mask=l3.unit_extents_mask())
|
|
1082
|
+
|
|
1083
|
+
assert l1.shape == l2.shape == l3.shape == (1, 4, 1)
|
|
1084
|
+
assert l1.strides == l2.strides == l3.strides == (12, 3, 3)"""
|
|
1085
|
+
@overload
|
|
1086
|
+
def unsqueezed(self, mask=...) -> Any:
|
|
1087
|
+
"""StridedLayout.unsqueezed(self: StridedLayout, axis: int | tuple[int] | None = None, int mask: int = 0) -> StridedLayout
|
|
1088
|
+
|
|
1089
|
+
Returns a layout where the specified axis or axes are added as unit extents.
|
|
1090
|
+
The ``axis`` can be either a single integer in range ``[0, ndim]``
|
|
1091
|
+
or a tuple of unique integers in range ``[0, ndim + len(axis) - 1]``.
|
|
1092
|
+
Alternatively, the axes can be specified as a mask with bits set
|
|
1093
|
+
for the axes to be added.
|
|
1094
|
+
|
|
1095
|
+
Note, squeezing and unsqueezing a layout can be used as a way to normalize
|
|
1096
|
+
the strides of unit dimensions.
|
|
1097
|
+
|
|
1098
|
+
.. highlight:: python
|
|
1099
|
+
.. code-block:: python
|
|
1100
|
+
|
|
1101
|
+
# The three layouts are equvialent, they have the same shape and
|
|
1102
|
+
# differ only in the strides of unit dimensions.
|
|
1103
|
+
l1 = StridedLayout.dense((5, 4, 3), 1)[-1:, :, :1].layout
|
|
1104
|
+
l2 = StridedLayout.dense((5, 4, 3), 1)[::5, :, ::3].layout
|
|
1105
|
+
l3 = StridedLayout.dense((5, 4, 3), 1)[::-1, :, ::-1][-1:, :, :1].layout
|
|
1106
|
+
|
|
1107
|
+
assert l1.shape == l2.shape == l3.shape == (1, 4, 1)
|
|
1108
|
+
assert l1.strides == (12, 3, 1)
|
|
1109
|
+
assert l2.strides == (60, 3, 3)
|
|
1110
|
+
assert l3.strides == (-12, 3, -1)
|
|
1111
|
+
|
|
1112
|
+
l1 = l1.squeezed().unsqueezed(mask=l1.unit_extents_mask())
|
|
1113
|
+
l2 = l2.squeezed().unsqueezed(mask=l2.unit_extents_mask())
|
|
1114
|
+
l3 = l3.squeezed().unsqueezed(mask=l3.unit_extents_mask())
|
|
1115
|
+
|
|
1116
|
+
assert l1.shape == l2.shape == l3.shape == (1, 4, 1)
|
|
1117
|
+
assert l1.strides == l2.strides == l3.strides == (12, 3, 3)"""
|
|
1118
|
+
def unsqueezed_to_ndim(self, intndim: int, intaxis: int = ...) -> StridedLayout:
|
|
1119
|
+
"""StridedLayout.unsqueezed_to_ndim(self: StridedLayout, int ndim: int, int axis: int = 0) -> StridedLayout
|
|
1120
|
+
|
|
1121
|
+
Returns a layout with the specified number of dimensions, by adding unit extents
|
|
1122
|
+
starting from the specified axis.
|
|
1123
|
+
|
|
1124
|
+
The valid range of ``axis`` is (inclusive) range ``[0, ndim]``."""
|
|
1125
|
+
def __add__(self, other): ...
|
|
1126
|
+
def __eq__(self, other: object) -> bool:
|
|
1127
|
+
"""Return self==value."""
|
|
1128
|
+
def __ge__(self, other: object) -> bool:
|
|
1129
|
+
"""Return self>=value."""
|
|
1130
|
+
def __getitem__(self, index):
|
|
1131
|
+
"""Return self[key]."""
|
|
1132
|
+
def __gt__(self, other: object) -> bool:
|
|
1133
|
+
"""Return self>value."""
|
|
1134
|
+
def __le__(self, other: object) -> bool:
|
|
1135
|
+
"""Return self<=value."""
|
|
1136
|
+
def __len__(self) -> int:
|
|
1137
|
+
"""Return len(self)."""
|
|
1138
|
+
def __lt__(self, other: object) -> bool:
|
|
1139
|
+
"""Return self<value."""
|
|
1140
|
+
def __ne__(self, other: object) -> bool:
|
|
1141
|
+
"""Return self!=value."""
|
|
1142
|
+
def __radd__(self, other):
|
|
1143
|
+
"""Return value+self."""
|
|
1144
|
+
def __reduce__(self):
|
|
1145
|
+
"""StridedLayout.__reduce_cython__(self)"""
|