tenspec 0.1.0__py3-none-any.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.
- tenspec/__init__.py +39 -0
- tenspec/errors.py +89 -0
- tenspec/numpy.py +343 -0
- tenspec/py.typed +0 -0
- tenspec/pydantic/__init__.py +4 -0
- tenspec/pydantic/annotations.py +407 -0
- tenspec/pydantic/calls.py +136 -0
- tenspec/pydantic/models.py +82 -0
- tenspec/pydantic/standalone.py +99 -0
- tenspec/runtime/__init__.py +1 -0
- tenspec/runtime/arrays.py +313 -0
- tenspec/runtime/bindings.py +168 -0
- tenspec/runtime/validation.py +368 -0
- tenspec/torch.py +276 -0
- tenspec/types/__init__.py +1 -0
- tenspec/types/base.py +13 -0
- tenspec/types/dtypes.py +140 -0
- tenspec/types/operations.py +114 -0
- tenspec/types/properties.py +74 -0
- tenspec/types/shapes.py +289 -0
- tenspec/types/tensor.py +28 -0
- tenspec-0.1.0.dist-info/METADATA +116 -0
- tenspec-0.1.0.dist-info/RECORD +25 -0
- tenspec-0.1.0.dist-info/WHEEL +4 -0
- tenspec-0.1.0.dist-info/licenses/LICENSE +21 -0
tenspec/__init__.py
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""Tenspec: declare what an array must be, and check it at one boundary.
|
|
2
|
+
|
|
3
|
+
Write the declaration once, beside the value it describes. A checked function, a model
|
|
4
|
+
mixin, or a standalone call then holds it. Import a backend module for the array library
|
|
5
|
+
you use: `tenspec.numpy` or `tenspec.torch`. This module loads neither one.
|
|
6
|
+
|
|
7
|
+
This is the common surface. Everything below it keeps its defining module, including
|
|
8
|
+
`tenspec.errors.TensorMismatch`, `tenspec.errors.BindingError`,
|
|
9
|
+
`tenspec.runtime.validation.validate_array`, `tenspec.runtime.bindings.Bindings`,
|
|
10
|
+
`tenspec.runtime.arrays.ArrayBackend`, and `tenspec.pydantic.annotations.prepare_annotation`.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from typing import Literal as Shape
|
|
14
|
+
|
|
15
|
+
from tenspec.errors import AnnotationError, ConstraintEvaluationError
|
|
16
|
+
from tenspec.pydantic.calls import checked
|
|
17
|
+
from tenspec.pydantic.models import TensorContracts
|
|
18
|
+
from tenspec.pydantic.standalone import validate
|
|
19
|
+
from tenspec.runtime.bindings import axis_size
|
|
20
|
+
from tenspec.types.dtypes import DType, Floating
|
|
21
|
+
from tenspec.types.properties import Contiguous, Finite, Materialized, NonEmpty
|
|
22
|
+
|
|
23
|
+
__version__ = "0.1.0"
|
|
24
|
+
|
|
25
|
+
__all__ = [
|
|
26
|
+
"AnnotationError",
|
|
27
|
+
"ConstraintEvaluationError",
|
|
28
|
+
"Contiguous",
|
|
29
|
+
"DType",
|
|
30
|
+
"Finite",
|
|
31
|
+
"Floating",
|
|
32
|
+
"Materialized",
|
|
33
|
+
"NonEmpty",
|
|
34
|
+
"Shape",
|
|
35
|
+
"TensorContracts",
|
|
36
|
+
"axis_size",
|
|
37
|
+
"checked",
|
|
38
|
+
"validate",
|
|
39
|
+
]
|
tenspec/errors.py
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"""The errors Tenspec raises, and what each one reports."""
|
|
2
|
+
|
|
3
|
+
from collections.abc import Mapping
|
|
4
|
+
from enum import StrEnum
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class AnnotationError(TypeError):
|
|
8
|
+
"""A declaration is invalid, unsupported, or never reached Tenspec's preparation."""
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class ConstraintEvaluationError(RuntimeError):
|
|
12
|
+
"""A backend cannot inspect a declared property of this value.
|
|
13
|
+
|
|
14
|
+
This never reports a measured mismatch. It reports that the check could not run.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class BindingReason(StrEnum):
|
|
19
|
+
"""Why a dimension lookup found no extent."""
|
|
20
|
+
|
|
21
|
+
NO_SCOPE = "no_scope"
|
|
22
|
+
UNBOUND = "unbound"
|
|
23
|
+
NOT_SCALAR = "not_scalar"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class BindingError(ValueError):
|
|
27
|
+
"""A required dimension was unavailable, rather than different.
|
|
28
|
+
|
|
29
|
+
The reason says which lookup failed. The name is the dimension the caller asked for.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
def __init__(self, reason: BindingReason, name: str | None = None) -> None:
|
|
33
|
+
self.reason = reason
|
|
34
|
+
self.name = name
|
|
35
|
+
messages = {
|
|
36
|
+
BindingReason.NO_SCOPE: "no Tenspec validation scope is open",
|
|
37
|
+
BindingReason.UNBOUND: f"dimension {name!r} has no binding in this scope",
|
|
38
|
+
BindingReason.NOT_SCALAR: f"dimension {name!r} holds a group of axes, not one extent",
|
|
39
|
+
}
|
|
40
|
+
super().__init__(messages[reason])
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class TensorMismatch(ValueError): # noqa: N818 the accepted contract fixes this name.
|
|
44
|
+
"""An array disagrees with its declared requirement.
|
|
45
|
+
|
|
46
|
+
The requirement, the observed fact, and the relevant bindings stay readable on the
|
|
47
|
+
error. The error holds no array.
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
def __init__(
|
|
51
|
+
self,
|
|
52
|
+
*,
|
|
53
|
+
requirement: str,
|
|
54
|
+
observed: str,
|
|
55
|
+
bindings: Mapping[str, int | tuple[int, ...]] | None = None,
|
|
56
|
+
) -> None:
|
|
57
|
+
self.requirement = requirement
|
|
58
|
+
self.observed = observed
|
|
59
|
+
self.bindings: Mapping[str, int | tuple[int, ...]] = dict(bindings or {})
|
|
60
|
+
detail = f", with {self.bindings}" if self.bindings else ""
|
|
61
|
+
super().__init__(f"expected {requirement}, but the array has {observed}{detail}")
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def describe_empty(shape: tuple[int, ...]) -> str:
|
|
65
|
+
"""What a refusal reports about an array that holds no elements.
|
|
66
|
+
|
|
67
|
+
It reads the shape alone. Axis indices start at 0.
|
|
68
|
+
|
|
69
|
+
describe_empty((2, 0, 0)) returns "shape (2, 0, 0), with no elements at axis 1, axis 2".
|
|
70
|
+
|
|
71
|
+
Returns:
|
|
72
|
+
The observed text for a TensorMismatch.
|
|
73
|
+
"""
|
|
74
|
+
empty = ", ".join(f"axis {index}" for index, extent in enumerate(shape) if extent == 0)
|
|
75
|
+
return f"shape {shape}, with no elements at {empty}"
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
class TransformContractError(RuntimeError):
|
|
79
|
+
"""A transform changed a structural fact that it had to preserve.
|
|
80
|
+
|
|
81
|
+
This reports a defect in the transform, not invalid caller input, so it is a
|
|
82
|
+
RuntimeError and never a ValueError. It names the transform and the one fact that
|
|
83
|
+
changed. Every field is text, so the error holds no array.
|
|
84
|
+
"""
|
|
85
|
+
|
|
86
|
+
def __init__(self, *, transform: str, fact: str, before: str, after: str) -> None:
|
|
87
|
+
self.transform = transform
|
|
88
|
+
self.fact = fact
|
|
89
|
+
super().__init__(f"{transform} changed the {fact} of its input, from {before} to {after}")
|
tenspec/numpy.py
ADDED
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
"""The NumPy backend, and the declarations a NumPy caller writes."""
|
|
2
|
+
|
|
3
|
+
from abc import ABC
|
|
4
|
+
from collections.abc import Hashable, Mapping
|
|
5
|
+
from types import MappingProxyType
|
|
6
|
+
from typing import Annotated, Any, get_args, get_origin
|
|
7
|
+
|
|
8
|
+
import numpy as np
|
|
9
|
+
from numpy.typing import NDArray
|
|
10
|
+
|
|
11
|
+
from tenspec.errors import (
|
|
12
|
+
AnnotationError,
|
|
13
|
+
ConstraintEvaluationError,
|
|
14
|
+
TensorMismatch,
|
|
15
|
+
describe_empty,
|
|
16
|
+
)
|
|
17
|
+
from tenspec.runtime.arrays import ArrayBackend, TensorDeclaration
|
|
18
|
+
from tenspec.types import operations, properties
|
|
19
|
+
from tenspec.types.dtypes import DTypeFamily, DTypeId
|
|
20
|
+
from tenspec.types.operations import derives_from
|
|
21
|
+
|
|
22
|
+
NUMPY_SCALARS: Mapping[DTypeId, type[np.generic]] = {
|
|
23
|
+
DTypeId.BOOL: np.bool_,
|
|
24
|
+
DTypeId.INT8: np.int8,
|
|
25
|
+
DTypeId.INT16: np.int16,
|
|
26
|
+
DTypeId.INT32: np.int32,
|
|
27
|
+
DTypeId.INT64: np.int64,
|
|
28
|
+
DTypeId.UINT8: np.uint8,
|
|
29
|
+
DTypeId.UINT16: np.uint16,
|
|
30
|
+
DTypeId.UINT32: np.uint32,
|
|
31
|
+
DTypeId.UINT64: np.uint64,
|
|
32
|
+
DTypeId.FLOAT16: np.float16,
|
|
33
|
+
DTypeId.FLOAT32: np.float32,
|
|
34
|
+
DTypeId.FLOAT64: np.float64,
|
|
35
|
+
DTypeId.COMPLEX64: np.complex64,
|
|
36
|
+
DTypeId.COMPLEX128: np.complex128,
|
|
37
|
+
}
|
|
38
|
+
"""The native scalar class of every logical format NumPy represents.
|
|
39
|
+
|
|
40
|
+
NumPy has no bfloat16, so that format is absent here and from `supported_formats`.
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class ArrayProperty[D: np.generic](operations.ArrayProperty[NDArray[D]], ABC):
|
|
45
|
+
"""The base a NumPy property derives from. D is the scalar domain it accepts.
|
|
46
|
+
|
|
47
|
+
Write `class NonPositive(ArrayProperty[np.floating[Any]])` and implement `validate`.
|
|
48
|
+
A declaration must guarantee D, so a float64-only check refuses a broad Float
|
|
49
|
+
declaration. Write an exact scalar class, or a family with Any.
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class Finite(ArrayProperty[np.generic]):
|
|
54
|
+
"""Every element of the array is a finite number. An integer array always passes."""
|
|
55
|
+
|
|
56
|
+
@staticmethod
|
|
57
|
+
def validate(values: NDArray[np.generic]) -> None:
|
|
58
|
+
if values.dtype.kind in "fc" and not bool(np.isfinite(values).all()):
|
|
59
|
+
raise TensorMismatch(requirement="Finite", observed="non-finite entries")
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class NonEmpty(ArrayProperty[np.generic]):
|
|
63
|
+
"""The array holds at least one element."""
|
|
64
|
+
|
|
65
|
+
@staticmethod
|
|
66
|
+
def validate(values: NDArray[np.generic]) -> None:
|
|
67
|
+
if values.size == 0:
|
|
68
|
+
raise TensorMismatch(requirement="NonEmpty", observed=describe_empty(values.shape))
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
class Contiguous(ArrayProperty[np.generic]):
|
|
72
|
+
"""The array uses C-contiguous storage."""
|
|
73
|
+
|
|
74
|
+
@staticmethod
|
|
75
|
+
def validate(values: NDArray[np.generic]) -> None:
|
|
76
|
+
if not values.flags.c_contiguous:
|
|
77
|
+
raise TensorMismatch(
|
|
78
|
+
requirement="Contiguous", observed="storage that is not C-contiguous"
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class Materialized(ArrayProperty[np.generic]):
|
|
83
|
+
"""The array holds actual data. Every NumPy array does, so this accepts every array."""
|
|
84
|
+
|
|
85
|
+
@staticmethod
|
|
86
|
+
def validate(values: NDArray[np.generic]) -> None:
|
|
87
|
+
"""Accept every array."""
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
class ReadOnly(ArrayProperty[np.generic]):
|
|
91
|
+
"""This array's own writeable flag is off.
|
|
92
|
+
|
|
93
|
+
It is a check of that flag. It is not a seal, and it never promises that another
|
|
94
|
+
reference to the same storage cannot change the values.
|
|
95
|
+
"""
|
|
96
|
+
|
|
97
|
+
@staticmethod
|
|
98
|
+
def validate(values: NDArray[np.generic]) -> None:
|
|
99
|
+
if values.flags.writeable:
|
|
100
|
+
raise TensorMismatch(requirement="ReadOnly", observed="its writeable flag on")
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
class ArrayTransform[D: np.generic](operations.ArrayTransform[NDArray[D]], ABC):
|
|
104
|
+
"""The base a NumPy transform derives from. D is the scalar domain it accepts.
|
|
105
|
+
|
|
106
|
+
Write `class Owned(ArrayTransform[np.generic])` and implement `transform`. The
|
|
107
|
+
result must keep the concrete class, the shape, the native dtype and the device of
|
|
108
|
+
its input, and must leave the caller's own array unchanged.
|
|
109
|
+
"""
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
class CopyReadOnly(ArrayTransform[np.generic]):
|
|
113
|
+
"""Replace the array with a read-only copy of it, on separate storage.
|
|
114
|
+
|
|
115
|
+
The caller's array keeps its own values and its writeable flag. The stored copy
|
|
116
|
+
shares no memory with it, and refuses an ordinary write. This is not immutability:
|
|
117
|
+
a caller who reaches the copy's base array can still change the values.
|
|
118
|
+
|
|
119
|
+
It copies on every validation, so it costs time and memory each time.
|
|
120
|
+
"""
|
|
121
|
+
|
|
122
|
+
@staticmethod
|
|
123
|
+
def transform[D: np.generic](values: NDArray[D]) -> NDArray[D]:
|
|
124
|
+
"""Copy the array, seal the copy, and return a view of it.
|
|
125
|
+
|
|
126
|
+
Returns:
|
|
127
|
+
A read-only view of a separate copy, with the same class, shape and dtype.
|
|
128
|
+
"""
|
|
129
|
+
owned = values.copy()
|
|
130
|
+
owned.setflags(write=False)
|
|
131
|
+
return owned.view()
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
NUMPY_AUTHOR_BASES = (ArrayProperty, ArrayTransform)
|
|
135
|
+
"""The two bases a NumPy operation derives from. Each one fixes a scalar domain."""
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def scalar_domain(operation: type[operations.Operation[Any]]) -> Any:
|
|
139
|
+
"""The scalar expression one NumPy operation names on its author base.
|
|
140
|
+
|
|
141
|
+
The walk reads each class's own bases, so a subclass of a fixed-domain property
|
|
142
|
+
inherits that domain rather than lose it.
|
|
143
|
+
|
|
144
|
+
Returns:
|
|
145
|
+
The scalar class or family the operation accepts.
|
|
146
|
+
|
|
147
|
+
Raises:
|
|
148
|
+
AnnotationError: when the class is not a NumPy operation, or when it names no
|
|
149
|
+
scalar domain.
|
|
150
|
+
"""
|
|
151
|
+
if not derives_from(operation, *NUMPY_AUTHOR_BASES):
|
|
152
|
+
raise AnnotationError(
|
|
153
|
+
f"{operation.__name__} is not a NumPy operation. Derive it from "
|
|
154
|
+
f"tenspec.numpy.ArrayProperty or tenspec.numpy.ArrayTransform."
|
|
155
|
+
)
|
|
156
|
+
for ancestor in operation.__mro__:
|
|
157
|
+
for base in ancestor.__dict__.get("__orig_bases__", ()):
|
|
158
|
+
if get_origin(base) in NUMPY_AUTHOR_BASES:
|
|
159
|
+
return get_args(base)[0]
|
|
160
|
+
raise AnnotationError(
|
|
161
|
+
f"{operation.__name__} names no scalar domain. Write the author base with an "
|
|
162
|
+
f"exact scalar class, such as ArrayProperty[np.float64]."
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def scalar_formats(scalar: Any) -> frozenset[DTypeId]:
|
|
167
|
+
"""Every logical format one NumPy scalar class or family covers.
|
|
168
|
+
|
|
169
|
+
np.float64 covers float64 alone. np.floating and np.floating[Any] cover every
|
|
170
|
+
floating format NumPy represents. A family whose precision arguments are all Any
|
|
171
|
+
covers the whole family, however many it takes: np.complexfloating takes two, and
|
|
172
|
+
np.complexfloating[Any, Any] is its unrestricted form.
|
|
173
|
+
|
|
174
|
+
A family that restricts any precision argument, such as np.floating[_64Bit], names a
|
|
175
|
+
domain this release cannot read. It refuses, because widening it to the whole family
|
|
176
|
+
would hand float32 values to a check written for float64.
|
|
177
|
+
|
|
178
|
+
Returns:
|
|
179
|
+
The logical formats of that scalar expression.
|
|
180
|
+
|
|
181
|
+
Raises:
|
|
182
|
+
AnnotationError: when the expression is not a NumPy scalar class, or when any
|
|
183
|
+
precision argument is not Any.
|
|
184
|
+
"""
|
|
185
|
+
native = scalar
|
|
186
|
+
if get_origin(scalar) is not None:
|
|
187
|
+
if not all(argument is Any for argument in get_args(scalar)):
|
|
188
|
+
raise AnnotationError(
|
|
189
|
+
f"{scalar!r} names a precision Tenspec does not read. Write the exact "
|
|
190
|
+
f"scalar class, such as np.float64, or the family with Any."
|
|
191
|
+
)
|
|
192
|
+
native = get_origin(scalar)
|
|
193
|
+
if not (isinstance(native, type) and issubclass(native, np.generic)):
|
|
194
|
+
raise AnnotationError(f"{scalar!r} is not a NumPy scalar class, so its formats are unknown")
|
|
195
|
+
return frozenset(
|
|
196
|
+
item for item, scalar_type in NUMPY_SCALARS.items() if issubclass(scalar_type, native)
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
class NumpyArrays(ArrayBackend[np.ndarray[Any, np.dtype[Any]]]):
|
|
201
|
+
"""Reads shape, scalar format, and value properties from a NumPy array."""
|
|
202
|
+
|
|
203
|
+
supported_formats = frozenset(NUMPY_SCALARS)
|
|
204
|
+
builtin_properties = MappingProxyType(
|
|
205
|
+
{
|
|
206
|
+
properties.Finite: Finite,
|
|
207
|
+
properties.NonEmpty: NonEmpty,
|
|
208
|
+
properties.Contiguous: Contiguous,
|
|
209
|
+
properties.Materialized: Materialized,
|
|
210
|
+
}
|
|
211
|
+
)
|
|
212
|
+
reports_device = False
|
|
213
|
+
|
|
214
|
+
def shape(self, value: np.ndarray[Any, np.dtype[Any]]) -> tuple[int, ...]:
|
|
215
|
+
"""The extent of every axis.
|
|
216
|
+
|
|
217
|
+
Returns:
|
|
218
|
+
One extent per axis, in order.
|
|
219
|
+
"""
|
|
220
|
+
return value.shape
|
|
221
|
+
|
|
222
|
+
def dtype(self, value: np.ndarray[Any, np.dtype[Any]]) -> DTypeId:
|
|
223
|
+
"""The logical scalar format of the array.
|
|
224
|
+
|
|
225
|
+
Returns:
|
|
226
|
+
The logical scalar format.
|
|
227
|
+
|
|
228
|
+
Raises:
|
|
229
|
+
ConstraintEvaluationError: for a NumPy dtype with no logical format, such
|
|
230
|
+
as a structured or object dtype.
|
|
231
|
+
"""
|
|
232
|
+
name = value.dtype.name
|
|
233
|
+
try:
|
|
234
|
+
return DTypeId(name)
|
|
235
|
+
except ValueError as cause:
|
|
236
|
+
raise ConstraintEvaluationError(
|
|
237
|
+
f"NumPy dtype {name!r} has no logical scalar format"
|
|
238
|
+
) from cause
|
|
239
|
+
|
|
240
|
+
def device(self, value: np.ndarray[Any, np.dtype[Any]]) -> properties.DeviceId | None: # noqa: ARG002 NumPy reports no placement, so it reads nothing.
|
|
241
|
+
"""NumPy places no array, so it reports no placement.
|
|
242
|
+
|
|
243
|
+
Returns:
|
|
244
|
+
None, which never stands for the CPU.
|
|
245
|
+
"""
|
|
246
|
+
return None
|
|
247
|
+
|
|
248
|
+
def native_dtype(self, value: np.ndarray[Any, np.dtype[Any]]) -> Hashable:
|
|
249
|
+
"""NumPy's own dtype object, which carries byte order as well as format.
|
|
250
|
+
|
|
251
|
+
Returns:
|
|
252
|
+
The array's dtype object.
|
|
253
|
+
"""
|
|
254
|
+
return value.dtype
|
|
255
|
+
|
|
256
|
+
def operation_formats(self, operation: type[operations.Operation[Any]]) -> frozenset[DTypeId]:
|
|
257
|
+
"""Every logical format one NumPy operation accepts, from its declared domain.
|
|
258
|
+
|
|
259
|
+
Returns:
|
|
260
|
+
The logical formats the operation accepts.
|
|
261
|
+
|
|
262
|
+
Raises:
|
|
263
|
+
AnnotationError: when the class is not a NumPy operation, or when its scalar
|
|
264
|
+
domain has no logical format.
|
|
265
|
+
"""
|
|
266
|
+
return scalar_formats(scalar_domain(operation))
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
NUMPY_ARRAYS = NumpyArrays()
|
|
270
|
+
"""The one NumPy backend every NumPy declaration carries."""
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
type Float[S, *C] = Annotated[
|
|
274
|
+
NDArray[np.floating], TensorDeclaration(NUMPY_ARRAYS, DTypeFamily.FLOATING), S, tuple[*C]
|
|
275
|
+
]
|
|
276
|
+
|
|
277
|
+
type Int[S, *C] = Annotated[
|
|
278
|
+
NDArray[np.signedinteger], TensorDeclaration(NUMPY_ARRAYS, DTypeFamily.INTEGER), S, tuple[*C]
|
|
279
|
+
]
|
|
280
|
+
|
|
281
|
+
type UInt[S, *C] = Annotated[
|
|
282
|
+
NDArray[np.unsignedinteger], TensorDeclaration(NUMPY_ARRAYS, DTypeFamily.UNSIGNED), S, tuple[*C]
|
|
283
|
+
]
|
|
284
|
+
|
|
285
|
+
type Complex[S, *C] = Annotated[
|
|
286
|
+
NDArray[np.complexfloating], TensorDeclaration(NUMPY_ARRAYS, DTypeFamily.COMPLEX), S, tuple[*C]
|
|
287
|
+
]
|
|
288
|
+
|
|
289
|
+
type Bool[S, *C] = Annotated[
|
|
290
|
+
NDArray[np.bool_], TensorDeclaration(NUMPY_ARRAYS, DTypeFamily.BOOLEAN), S, tuple[*C]
|
|
291
|
+
]
|
|
292
|
+
|
|
293
|
+
type Float16[S, *C] = Annotated[
|
|
294
|
+
NDArray[np.float16], TensorDeclaration(NUMPY_ARRAYS, DTypeId.FLOAT16), S, tuple[*C]
|
|
295
|
+
]
|
|
296
|
+
|
|
297
|
+
type Float32[S, *C] = Annotated[
|
|
298
|
+
NDArray[np.float32], TensorDeclaration(NUMPY_ARRAYS, DTypeId.FLOAT32), S, tuple[*C]
|
|
299
|
+
]
|
|
300
|
+
|
|
301
|
+
type Float64[S, *C] = Annotated[
|
|
302
|
+
NDArray[np.float64], TensorDeclaration(NUMPY_ARRAYS, DTypeId.FLOAT64), S, tuple[*C]
|
|
303
|
+
]
|
|
304
|
+
|
|
305
|
+
type Int8[S, *C] = Annotated[
|
|
306
|
+
NDArray[np.int8], TensorDeclaration(NUMPY_ARRAYS, DTypeId.INT8), S, tuple[*C]
|
|
307
|
+
]
|
|
308
|
+
|
|
309
|
+
type Int16[S, *C] = Annotated[
|
|
310
|
+
NDArray[np.int16], TensorDeclaration(NUMPY_ARRAYS, DTypeId.INT16), S, tuple[*C]
|
|
311
|
+
]
|
|
312
|
+
|
|
313
|
+
type Int32[S, *C] = Annotated[
|
|
314
|
+
NDArray[np.int32], TensorDeclaration(NUMPY_ARRAYS, DTypeId.INT32), S, tuple[*C]
|
|
315
|
+
]
|
|
316
|
+
|
|
317
|
+
type Int64[S, *C] = Annotated[
|
|
318
|
+
NDArray[np.int64], TensorDeclaration(NUMPY_ARRAYS, DTypeId.INT64), S, tuple[*C]
|
|
319
|
+
]
|
|
320
|
+
|
|
321
|
+
type UInt8[S, *C] = Annotated[
|
|
322
|
+
NDArray[np.uint8], TensorDeclaration(NUMPY_ARRAYS, DTypeId.UINT8), S, tuple[*C]
|
|
323
|
+
]
|
|
324
|
+
|
|
325
|
+
type UInt16[S, *C] = Annotated[
|
|
326
|
+
NDArray[np.uint16], TensorDeclaration(NUMPY_ARRAYS, DTypeId.UINT16), S, tuple[*C]
|
|
327
|
+
]
|
|
328
|
+
|
|
329
|
+
type UInt32[S, *C] = Annotated[
|
|
330
|
+
NDArray[np.uint32], TensorDeclaration(NUMPY_ARRAYS, DTypeId.UINT32), S, tuple[*C]
|
|
331
|
+
]
|
|
332
|
+
|
|
333
|
+
type UInt64[S, *C] = Annotated[
|
|
334
|
+
NDArray[np.uint64], TensorDeclaration(NUMPY_ARRAYS, DTypeId.UINT64), S, tuple[*C]
|
|
335
|
+
]
|
|
336
|
+
|
|
337
|
+
type Complex64[S, *C] = Annotated[
|
|
338
|
+
NDArray[np.complex64], TensorDeclaration(NUMPY_ARRAYS, DTypeId.COMPLEX64), S, tuple[*C]
|
|
339
|
+
]
|
|
340
|
+
|
|
341
|
+
type Complex128[S, *C] = Annotated[
|
|
342
|
+
NDArray[np.complex128], TensorDeclaration(NUMPY_ARRAYS, DTypeId.COMPLEX128), S, tuple[*C]
|
|
343
|
+
]
|
tenspec/py.typed
ADDED
|
File without changes
|