Skip to content

typing

triwarp.typing

Warp array type aliases and runtime rank checks for Python wrappers.

Use these aliases in triwarp Python APIs instead of wp.array2d[dtype], which static checkers treat as Warp annotation objects (no .shape / indexing).

Kernels should continue to use wp.array2d[dtype] in @wp.kernel signatures.

T module-attribute

T = TypeVar('T')

Array1dInt32 module-attribute

Array1dInt32: TypeAlias = wp.array[wp.int32, Literal[1]]

Array1dFloat32 module-attribute

Array1dFloat32: TypeAlias = wp.array[wp.float32, Literal[1]]

Array1dFloat64 module-attribute

Array1dFloat64: TypeAlias = wp.array[wp.float64, Literal[1]]

Array2dInt32 module-attribute

Array2dInt32: TypeAlias = wp.array[wp.int32, Literal[2]]

Array2dFloat32 module-attribute

Array2dFloat32: TypeAlias = wp.array[wp.float32, Literal[2]]

Array2dFloat64 module-attribute

Array2dFloat64: TypeAlias = wp.array[wp.float64, Literal[2]]

Array2dVec3 module-attribute

Array2dVec3: TypeAlias = wp.array[wp.vec3, Literal[2]]

Array3dFloat32 module-attribute

Array3dFloat32: TypeAlias = wp.array[wp.float32, Literal[3]]

Array3dBool module-attribute

Array3dBool: TypeAlias = wp.array[wp.bool, Literal[3]]

Array1dInt module-attribute

Array1dInt: TypeAlias = Array1dInt32

Array2dInt module-attribute

Array2dInt: TypeAlias = Array2dInt32

Array1dFloat module-attribute

Array1dFloat: TypeAlias = Array1dFloat32 | Array1dFloat64

Array2dFloat module-attribute

Array2dFloat: TypeAlias = Array2dFloat32 | Array2dFloat64

Array1dScalar module-attribute

Array1dScalar: TypeAlias = Array1dInt32 | Array1dFloat

Array2dScalar module-attribute

Array2dScalar: TypeAlias = Array2dInt32 | Array2dFloat

IntArray module-attribute

IntArray: TypeAlias = Array1dInt | Array2dInt

FloatArray module-attribute

FloatArray: TypeAlias = Array1dFloat | Array2dFloat

ScalarArray module-attribute

ScalarArray: TypeAlias = Array1dScalar | Array2dScalar

ArrayNdInt32 module-attribute

ArrayNdInt32: TypeAlias = wp.array[wp.int32, Any]

ArrayNd module-attribute

ArrayNd: TypeAlias = wp.array[Any, Any]

__all__ module-attribute

__all__ = [
    "Array1dFloat",
    "Array1dFloat32",
    "Array1dFloat64",
    "Array1dInt",
    "Array1dInt32",
    "Array1dScalar",
    "Array2dFloat",
    "Array2dFloat32",
    "Array2dFloat64",
    "Array2dInt",
    "Array2dInt32",
    "Array2dScalar",
    "Array2dVec3",
    "Array3dBool",
    "Array3dFloat32",
    "ArrayNd",
    "ArrayNdInt32",
    "FloatArray",
    "IntArray",
    "ScalarArray",
    "as_array2d",
    "as_array3d",
    "dtype_max",
    "dtype_min",
    "dtype_zero",
    "empty_2d",
    "empty_3d",
    "ensure_edge_pairs",
    "ensure_ndim",
    "sortable_dtype",
]

ensure_ndim

ensure_ndim(
    arr: array[T], ndim: int, *, dtype: type | None = None
) -> wp.array[T]

Validate the rank (and optionally the dtype) of a Warp array.

The runtime counterpart to the aliases in this module: isinstance(x, wp.array2d) is always False, so rank is checked here instead.

Parameters:

Name Type Description Default
arr array[T]

Array to validate.

required
ndim int

Required rank.

required
dtype type | None

When given, the required element dtype.

None

Returns:

Type Description
array

arr unchanged, so this can wrap an argument in place.

Raises:

Type Description
TypeError

If the rank or dtype does not match.

Source code in triwarp/typing.py
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
def ensure_ndim(arr: wp.array[T], ndim: int, *, dtype: type | None = None) -> wp.array[T]:
    """
    Validate the rank (and optionally the dtype) of a Warp array.

    The runtime counterpart to the aliases in this module: `isinstance(x, wp.array2d)` is always
    ``False``, so rank is checked here instead.

    Parameters
    ----------
    arr
        Array to validate.
    ndim
        Required rank.
    dtype
        When given, the required element dtype.

    Returns
    -------
    wp.array
        ``arr`` unchanged, so this can wrap an argument in place.

    Raises
    ------
    TypeError
        If the rank or dtype does not match.
    """
    if int(arr.ndim) != ndim:
        raise TypeError(f"expected {ndim}D array, got ndim={arr.ndim}")
    if dtype is not None and arr.dtype != dtype:
        raise TypeError(f"expected dtype {dtype}, got {arr.dtype}")
    return arr

ensure_edge_pairs

ensure_edge_pairs(arr: array[T], name: str) -> None

Validate that arr is a rank-2 wp.int32 array with exactly two columns.

The shared check every (k, 2) edge-list argument in the package runs before use, factored because six call sites (triangles.corner_normals, seams.cut_along_edges, graph.connected_component_parity_from_edges and graph._validate_edge_list, proximity.closest_point_on_edges, selection.contour_side_mask) wrote it out by hand, with the same two exceptions and only the parameter name differing between them.

Parameters:

Name Type Description Default
arr array[T]

Array to validate.

required
name str

Parameter name to use in the raised message.

required

Raises:

Type Description
TypeError

If arr is not a rank-2 wp.int32 array.

ValueError

If arr does not have exactly two columns.

Source code in triwarp/typing.py
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
def ensure_edge_pairs(arr: wp.array[T], name: str) -> None:
    """
    Validate that ``arr`` is a rank-2 ``wp.int32`` array with exactly two columns.

    The shared check every ``(k, 2)`` edge-list argument in the package runs before use, factored
    because six call sites (``triangles.corner_normals``, ``seams.cut_along_edges``,
    ``graph.connected_component_parity_from_edges`` and ``graph._validate_edge_list``,
    ``proximity.closest_point_on_edges``, ``selection.contour_side_mask``) wrote it out by hand,
    with the same two exceptions and only the parameter name differing between them.

    Parameters
    ----------
    arr
        Array to validate.
    name
        Parameter name to use in the raised message.

    Raises
    ------
    TypeError
        If ``arr`` is not a rank-2 ``wp.int32`` array.
    ValueError
        If ``arr`` does not have exactly two columns.
    """
    ensure_ndim(arr, 2, dtype=wp.int32)
    if int(arr.shape[1]) != 2:
        raise ValueError(f"{name} must have shape (k, 2), got {arr.shape}")

as_array2d

as_array2d(
    arr: array[T], dtype: type[int32]
) -> Array2dInt32
as_array2d(
    arr: array[T], dtype: type[float32]
) -> Array2dFloat32
as_array2d(
    arr: array[T], dtype: type[float64]
) -> Array2dFloat64
as_array2d(arr: array[T], dtype: type[vec3]) -> Array2dVec3
as_array2d(
    arr: array[T], dtype: type
) -> Array2dInt32 | Array2dFloat | Array2dVec3

Validate and narrow a Warp array to the rank-2 alias for dtype.

One function for what used to be as_array2d_int32 / as_array2d_float32 / as_array2d_float: the dtype selects the return alias through overloads, so a call site keeps the narrow type it had -- as_array2d(x, wp.int32) is an Array2dInt32, not a union.

Parameters:

Name Type Description Default
arr array[T]

Warp array expected to be rank-2 with element type dtype.

required
dtype type

Expected element type: wp.int32, wp.float32, wp.float64 or wp.vec3.

required

Returns:

Type Description
Array2dInt32 | Array2dFloat32 | Array2dFloat64 | Array2dVec3

arr unchanged, narrowed to the checked alias.

Raises:

Type Description
TypeError

If arr is not rank-2 with element type dtype.

Source code in triwarp/typing.py
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
def as_array2d(arr: wp.array[T], dtype: type) -> Array2dInt32 | Array2dFloat | Array2dVec3:
    """
    Validate and narrow a Warp array to the rank-2 alias for ``dtype``.

    One function for what used to be ``as_array2d_int32`` / ``as_array2d_float32`` /
    ``as_array2d_float``: the dtype selects the return alias through overloads, so a call site keeps
    the narrow type it had -- ``as_array2d(x, wp.int32)`` is an
    [`Array2dInt32`][triwarp.typing.Array2dInt32], not a union.

    Parameters
    ----------
    arr
        Warp array expected to be rank-2 with element type ``dtype``.
    dtype
        Expected element type: ``wp.int32``, ``wp.float32``, ``wp.float64`` or ``wp.vec3``.

    Returns
    -------
    Array2dInt32 | Array2dFloat32 | Array2dFloat64 | Array2dVec3
        ``arr`` unchanged, narrowed to the checked alias.

    Raises
    ------
    TypeError
        If ``arr`` is not rank-2 with element type ``dtype``.
    """
    ensure_ndim(arr, 2, dtype=dtype)
    return cast(Array2dInt32 | Array2dFloat, arr)

as_array3d

as_array3d(
    arr: array[T], dtype: type[float32]
) -> Array3dFloat32
as_array3d(arr: array[T], dtype: type[bool]) -> Array3dBool
as_array3d(
    arr: array[T], dtype: type
) -> Array3dFloat32 | Array3dBool

Validate and narrow a Warp array to the rank-3 alias for dtype.

The rank-3 counterpart of as_array2d.

Parameters:

Name Type Description Default
arr array[T]

Warp array expected to be rank-3 with scalar type dtype.

required
dtype type

Expected scalar type: wp.float32 or wp.bool.

required

Returns:

Type Description
Array3dFloat32 | Array3dBool

arr unchanged, narrowed to the checked alias.

Raises:

Type Description
TypeError

If arr is not rank-3 with scalar type dtype.

Source code in triwarp/typing.py
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
def as_array3d(arr: wp.array[T], dtype: type) -> Array3dFloat32 | Array3dBool:
    """
    Validate and narrow a Warp array to the rank-3 alias for ``dtype``.

    The rank-3 counterpart of [`as_array2d`][triwarp.typing.as_array2d].

    Parameters
    ----------
    arr
        Warp array expected to be rank-3 with scalar type ``dtype``.
    dtype
        Expected scalar type: ``wp.float32`` or ``wp.bool``.

    Returns
    -------
    Array3dFloat32 | Array3dBool
        ``arr`` unchanged, narrowed to the checked alias.

    Raises
    ------
    TypeError
        If ``arr`` is not rank-3 with scalar type ``dtype``.
    """
    ensure_ndim(arr, 3, dtype=dtype)
    return cast(Array3dFloat32 | Array3dBool, arr)

dtype_max

dtype_max(dtype: type[Int]) -> int
dtype_max(dtype: type[Float]) -> float
dtype_max(dtype: type[Scalar]) -> int | float

Largest representable value for a Warp scalar type.

Parameters:

Name Type Description Default
dtype type[Scalar]

A Warp integer or floating-point scalar type.

required

Returns:

Type Description
int | float

float("inf") for floating-point types; the maximum representable integer for integer types.

Source code in triwarp/typing.py
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
def dtype_max(dtype: type[wp.Scalar]) -> int | float:
    """
    Largest representable value for a Warp scalar type.

    Parameters
    ----------
    dtype
        A Warp integer or floating-point scalar type.

    Returns
    -------
    int | float
        ``float("inf")`` for floating-point types; the maximum representable
        integer for integer types.
    """
    if not wp.types.type_is_int(dtype):
        return float("inf")
    bits = wp.types.type_size_in_bytes(dtype) * 8
    if not dtype.__name__.lower().startswith("u"):
        bits -= 1
    return (1 << bits) - 1

dtype_min

dtype_min(dtype: type[Int]) -> int
dtype_min(dtype: type[Float]) -> float
dtype_min(dtype: type[Scalar]) -> int | float

Smallest representable value for a Warp scalar type.

Parameters:

Name Type Description Default
dtype type[Scalar]

A Warp integer or floating-point scalar type.

required

Returns:

Type Description
int | float

float("-inf") for floating-point types; the minimum representable integer for integer types.

Source code in triwarp/typing.py
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
def dtype_min(dtype: type[wp.Scalar]) -> int | float:
    """
    Smallest representable value for a Warp scalar type.

    Parameters
    ----------
    dtype
        A Warp integer or floating-point scalar type.

    Returns
    -------
    int | float
        ``float("-inf")`` for floating-point types; the minimum representable
        integer for integer types.
    """
    if not wp.types.type_is_int(dtype):
        return float("-inf")
    bits = wp.types.type_size_in_bytes(dtype) * 8
    if dtype.__name__.lower().startswith("u"):
        return 0
    return -(1 << (bits - 1))

dtype_zero

dtype_zero(dtype: type[Scalar]) -> int | float

Zero value for a Warp scalar type, typed to match Python's int/float split.

Parameters:

Name Type Description Default
dtype type[Scalar]

A Warp integer or floating-point scalar type.

required

Returns:

Type Description
int | float

0 for integer types, 0.0 for floating-point types.

Source code in triwarp/typing.py
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
def dtype_zero(dtype: type[wp.Scalar]) -> int | float:
    """
    Zero value for a Warp scalar type, typed to match Python's ``int``/``float`` split.

    Parameters
    ----------
    dtype
        A Warp integer or floating-point scalar type.

    Returns
    -------
    int | float
        ``0`` for integer types, ``0.0`` for floating-point types.
    """
    if wp.types.type_is_int(dtype):
        return 0
    return 0.0

sortable_dtype

sortable_dtype(dtype: type[Scalar]) -> type[wp.Scalar]

Same-width dtype that warp.utils.radix_sort_pairs accepts, preserving dtype's order.

The single widening rule for every radix sort in this package. Sorting a sub-32-bit dtype is not supported by Warp, and sorting the reinterpreted bits of a float or an unsigned value gets the order wrong, so callers ask here rather than widening ad hoc.

The hash table works in one common signed-integer key space (see bitcast_to_int), which is fine for equality but wrong for ordering: negative floats have descending bit patterns, and a uint64 with its top bit set reads as a negative int64. Warp sorts int32 / int64 / uint32 / uint64 / float32 / float64 keys directly, so the sort is done in this dtype instead of on the reinterpreted bits. Every narrower width -- int8 / uint8 / int16 / uint16 / float16 -- raises Unsupported keys and values data types, so the widening table below has a case for each of them.

Parameters:

Name Type Description Default
dtype type[Scalar]

Any Warp scalar dtype.

required

Returns:

Type Description
type[Scalar]

dtype itself when Warp can already sort it, otherwise the narrowest same-signedness, same-kind dtype it can (float32 / float64, uint32 / uint64, int32 / int64), chosen by whether dtype is wider than four bytes.

See Also

sort_and_argsort bitcast_to_int

Source code in triwarp/typing.py
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
def sortable_dtype(dtype: type[wp.Scalar]) -> type[wp.Scalar]:
    """
    Same-width dtype that ``warp.utils.radix_sort_pairs`` accepts, preserving ``dtype``'s order.

    The single widening rule for every radix sort in this package. Sorting a sub-32-bit dtype is
    not supported by Warp, and sorting the reinterpreted *bits* of a float or an unsigned value
    gets the order wrong, so callers ask here rather than widening ad hoc.

    The hash table works in one common signed-integer key space (see
    [`bitcast_to_int`][triwarp.array.bitcast_to_int]), which is fine for equality but wrong for
    ordering: negative floats have descending bit patterns, and a ``uint64`` with its top bit set
    reads as a negative ``int64``. Warp sorts ``int32`` / ``int64`` / ``uint32`` / ``uint64`` /
    ``float32`` / ``float64`` keys directly, so the sort is done in this dtype instead of on the
    reinterpreted bits. Every narrower width -- ``int8`` / ``uint8`` / ``int16`` / ``uint16`` /
    ``float16`` -- raises ``Unsupported keys and values data types``, so the widening table below
    has a case for each of them.

    Parameters
    ----------
    dtype
        Any Warp scalar dtype.

    Returns
    -------
    type[wp.Scalar]
        ``dtype`` itself when Warp can already sort it, otherwise the narrowest same-signedness,
        same-kind dtype it can (``float32`` / ``float64``, ``uint32`` / ``uint64``, ``int32`` /
        ``int64``), chosen by whether ``dtype`` is wider than four bytes.

    See Also
    --------
    [`sort_and_argsort`][triwarp.array.sort_and_argsort]
    [`bitcast_to_int`][triwarp.array.bitcast_to_int]
    """
    wide = wp.types.type_size_in_bytes(dtype) > 4
    if wp.types.type_is_float(dtype):
        return wp.float64 if wide else wp.float32
    if dtype.__name__.lower().startswith("u"):
        return wp.uint64 if wide else wp.uint32
    return wp.int64 if wide else wp.int32

empty_2d

empty_2d(
    shape: tuple[int, int] | list[int],
    dtype: type[int32],
    *,
    device: DeviceLike = None,
) -> Array2dInt32
empty_2d(
    shape: tuple[int, int] | list[int],
    dtype: type[float32],
    *,
    device: DeviceLike = None,
) -> Array2dFloat32
empty_2d(
    shape: tuple[int, int] | list[int],
    dtype: type[float64],
    *,
    device: DeviceLike = None,
) -> Array2dFloat64
empty_2d(
    shape: tuple[int, int] | list[int],
    dtype: type[vec3],
    *,
    device: DeviceLike = None,
) -> Array2dVec3
empty_2d(
    shape: tuple[int, int] | list[int],
    dtype: type,
    *,
    device: DeviceLike = None,
) -> Array2dInt32 | Array2dFloat | Array2dVec3

Allocate an uninitialized rank-2 Warp array of the given element type.

One function for what used to be empty_int32_2d / empty_float32_2d / empty_float_2d. The dtype selects the return alias through overloads, so a call site keeps the narrow type it had rather than falling back to a union.

Parameters:

Name Type Description Default
shape tuple[int, int] | list[int]

(rows, cols) shape of the allocated array.

required
dtype type

Element type: wp.int32, wp.float32, wp.float64 or wp.vec3. The last is what an (m, 2) table of segment endpoints wants, and it has an overload like the scalars do -- triwarp.intersection's two public segment returns are the callers.

required
device DeviceLike

Target Warp device.

None

Returns:

Type Description
Array2dInt32 | Array2dFloat32 | Array2dFloat64 | Array2dVec3

Uninitialized (rows, cols) array of element type dtype on device.

Source code in triwarp/typing.py
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
def empty_2d(
    shape: tuple[int, int] | list[int], dtype: type, *, device: wp.DeviceLike = None
) -> Array2dInt32 | Array2dFloat | Array2dVec3:
    """
    Allocate an uninitialized rank-2 Warp array of the given element type.

    One function for what used to be ``empty_int32_2d`` / ``empty_float32_2d`` / ``empty_float_2d``.
    The dtype selects the return alias through overloads, so a call site keeps the narrow type it
    had rather than falling back to a union.

    Parameters
    ----------
    shape
        ``(rows, cols)`` shape of the allocated array.
    dtype
        Element type: ``wp.int32``, ``wp.float32``, ``wp.float64`` or ``wp.vec3``. The last is
        what an ``(m, 2)`` table of segment endpoints wants, and it has an overload like the
        scalars do -- ``triwarp.intersection``'s two public segment returns are the callers.
    device
        Target Warp device.

    Returns
    -------
    Array2dInt32 | Array2dFloat32 | Array2dFloat64 | Array2dVec3
        Uninitialized ``(rows, cols)`` array of element type ``dtype`` on ``device``.
    """
    return cast(Array2dInt32 | Array2dFloat, wp.empty(_shape_2d(shape), dtype=dtype, device=device))

empty_3d

empty_3d(
    shape: tuple[int, int, int] | list[int],
    dtype: type[float32],
    *,
    device: DeviceLike = None,
) -> Array3dFloat32
empty_3d(
    shape: tuple[int, int, int] | list[int],
    dtype: type[bool],
    *,
    device: DeviceLike = None,
) -> Array3dBool
empty_3d(
    shape: tuple[int, int, int] | list[int],
    dtype: type,
    *,
    device: DeviceLike = None,
) -> Array3dFloat32 | Array3dBool

Allocate an uninitialized rank-3 Warp array of the given scalar type.

The rank-3 counterpart of empty_2d.

Parameters:

Name Type Description Default
shape tuple[int, int, int] | list[int]

(nx, ny, nz) shape of the allocated array.

required
dtype type

Scalar type: wp.float32 or wp.bool.

required
device DeviceLike

Target Warp device.

None

Returns:

Type Description
Array3dFloat32 | Array3dBool

Uninitialized (nx, ny, nz) array of scalar type dtype on device.

Source code in triwarp/typing.py
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
def empty_3d(
    shape: tuple[int, int, int] | list[int], dtype: type, *, device: wp.DeviceLike = None
) -> Array3dFloat32 | Array3dBool:
    """
    Allocate an uninitialized rank-3 Warp array of the given scalar type.

    The rank-3 counterpart of [`empty_2d`][triwarp.typing.empty_2d].

    Parameters
    ----------
    shape
        ``(nx, ny, nz)`` shape of the allocated array.
    dtype
        Scalar type: ``wp.float32`` or ``wp.bool``.
    device
        Target Warp device.

    Returns
    -------
    Array3dFloat32 | Array3dBool
        Uninitialized ``(nx, ny, nz)`` array of scalar type ``dtype`` on ``device``.
    """
    return cast(
        Array3dFloat32 | Array3dBool, wp.empty(_shape_3d(shape), dtype=dtype, device=device)
    )