Package root¶
anytensor
¶
get_backend
¶
Return the backend for tensor (e.g. NumPy for numpy.ndarray).
Optional extras (JAX, Torch, TensorFlow) are used only if already imported; this never imports them. NumPy is a required dependency and is the fallback for ndarrays.
Source code in anytensor/backends.py
module_if_loaded
¶
Return name if it is already imported, else None.
Never imports name. If callback is given and the module is
already loaded, it is invoked immediately with the module. If not,
callback is registered first and invoked later when that module is
imported in this process (including when a submodule import loads the
parent).
If raises is true and the module is still absent after that
registration, raise :class:RuntimeError. The pending callback is kept,
so a later import still runs it.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Absolute module name ( |
required |
callback
|
Optional[_Callback]
|
Optional |
None
|
raises
|
bool
|
If true, raise when |
False
|
Returns:
| Type | Description |
|---|---|
ModuleType | None
|
The loaded module, or |
ModuleType | None
|
(only when |
Examples:
Check without importing::
torch = module_if_loaded("torch")
if torch is None:
return
Require an extra that must already be imported::
jax = module_if_loaded("jax", raises=True)
Register a side effect for now-or-later (JAX pytree, TorchScript)::
def _register_jax_pytree(jax):
jax.tree_util.register_pytree_node(Ragged, flatten, unflatten)
module_if_loaded("jax", _register_jax_pytree)
# or module_if_loaded("jax", _register_jax_pytree, raises=True)
# to fail now while still running the callback on a later import.
Source code in anytensor/optional.py
segment_sum
¶
Computes the sum within segments of an array.
Similar to :func:jax.ops.segment_sum and TF unsorted_segment_sum.
Reduces x along axis 0, summing rows that share the same
segment_ids entry.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
SegmentValues
|
Values to sum. The leading axis is the segment axis. |
required |
segment_ids
|
SegmentIds
|
Integer ids with |
required |
num_segments
|
ShapeSize
|
Required shape-size (unlike JAX, where omitting it
defaults to |
required |
sorted
|
bool
|
When True, JAX/TF may use a sorted-ids fast path. No-op on NumPy and Torch (unsorted-safe scatter). |
False
|
Returns:
| Type | Description |
|---|---|
SegmentOut
|
Array of shape |
SegmentOut
|
as |
Notes
Empty-segment identity is 0 for all dtypes
(:mod:anytensor.semantics).
Index width is backend-local: Torch casts ids to int64 at scatter;
JAX without jax_enable_x64 often keeps int32 and may warn on int64
ids.
Under torch.jit.script, import torch in either order relative to
AnyTensor — the divert auto-enables via :func:anytensor.module_if_loaded.
Eager calls still dispatch by tensor type; only the scripted path uses
:mod:anytensor.torchscript.
Examples:
>>> import numpy as np
>>> import anytensor as at
>>> x = np.arange(5.0)
>>> ids = np.array([0, 0, 1, 1, 2])
>>> at.segment_sum(x, ids, num_segments=3)
array([1., 5., 4.])
Source code in anytensor/segment.py
segment_max
¶
Computes the maximum within segments of an array.
Similar to :func:jax.ops.segment_max. Reduces x along axis 0 by
segment_ids.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
SegmentValues
|
Values to reduce. Leading axis is the segment axis. |
required |
segment_ids
|
SegmentIds
|
Integer ids with |
required |
num_segments
|
ShapeSize
|
Required shape-size (Python |
required |
sorted
|
bool
|
Honored on JAX/TF; no-op on NumPy/Torch. |
False
|
Returns:
| Type | Description |
|---|---|
SegmentOut
|
Array of shape |
Notes
Empty-slot identity is -inf / dtype min — not TF's native
unsorted_segment_max finfo fill. Occupied ±inf stays ±inf.
On TensorFlow, scatter ignores NaN updates; AnyTensor ORs NaN back in so a segment that saw any NaN is NaN (matches NumPy/JAX/Torch).
Prefer :func:segment_max_or_constant when empty slots should be a
finite fill instead of -inf.
Under TF XLA (tf.function(jit_compile=True)), NaN in min/max-like
ops may become ±inf instead of NaN — avoid relying on NaN under XLA.
TorchScript: :func:enable_torchscript (eager path stays multi-backend).
Source code in anytensor/segment.py
segment_min
¶
Computes the minimum within segments of an array.
Similar to :func:jax.ops.segment_min. Reduces x along axis 0 by
segment_ids.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
SegmentValues
|
Values to reduce. Leading axis is the segment axis. |
required |
segment_ids
|
SegmentIds
|
Integer ids with |
required |
num_segments
|
ShapeSize
|
Required shape-size (Python |
required |
sorted
|
bool
|
Honored on JAX/TF; no-op on NumPy/Torch. |
False
|
Returns:
| Type | Description |
|---|---|
SegmentOut
|
Array of shape |
Notes
Empty-slot identity is +inf / dtype max — not TF's native
unsorted_segment_min finfo fill. Occupied ±inf stays ±inf.
On TensorFlow, scatter ignores NaN updates; AnyTensor ORs NaN back in so a segment that saw any NaN is NaN (matches NumPy/JAX/Torch).
Prefer :func:segment_min_or_constant when empty slots should be a
finite fill instead of +inf.
Under TF XLA, NaN in min/max-like ops may become ±inf — avoid relying on NaN under XLA.
TorchScript: :func:enable_torchscript (eager path stays multi-backend).
Source code in anytensor/segment.py
segment_mean
¶
Mean of values of x within each segment along axis 0.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
SegmentValues
|
Values to average. Leading axis is the segment axis. |
required |
segment_ids
|
SegmentIds
|
Integer segment ids (see :func: |
required |
num_segments
|
ShapeSize
|
Required shape-size. |
required |
sorted
|
bool
|
Forwarded to underlying segment ops (no-op on NumPy/Torch). |
False
|
Returns:
| Type | Description |
|---|---|
SegmentOut
|
Array of shape |
Notes
Empty segments yield 0 (sum is already 0; the denominator is clamped away from zero only so division stays defined). This differs from a NaN-on-empty mean.
Source code in anytensor/segment.py
segment_count
¶
Count how many elements fall in each segment.
Implemented as segment_sum of ones, so empty slots are 0.0.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
segment_ids
|
SegmentIds
|
Integer ids (same conventions as :func: |
required |
num_segments
|
ShapeSize
|
Required shape-size (Python |
required |
sorted
|
bool
|
Forwarded to :func: |
False
|
Returns:
| Type | Description |
|---|---|
SegmentOut
|
Float vector of shape |
SegmentOut
|
|
SegmentOut
|
float32 on JAX without x64). |
Source code in anytensor/segment.py
segment_variance
¶
Population variance of x within each segment along axis 0.
Computed as the segment mean of squared deviations from the segment mean
(divide by n, not n-1).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
SegmentValues
|
Values. Leading axis is the segment axis. |
required |
segment_ids
|
SegmentIds
|
Integer segment ids (see :func: |
required |
num_segments
|
ShapeSize
|
Required shape-size. |
required |
sorted
|
bool
|
Forwarded to underlying segment ops (no-op on NumPy/Torch). |
False
|
Returns:
| Type | Description |
|---|---|
SegmentOut
|
Array of shape |
SegmentOut
|
|
Source code in anytensor/segment.py
segment_normalize
¶
Divide each value by its segment sum (0/0 → 0).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
SegmentValues
|
Values. Leading axis is the segment axis. |
required |
segment_ids
|
SegmentIds
|
Integer segment ids (see :func: |
required |
num_segments
|
ShapeSize
|
Required shape-size. |
required |
sorted
|
bool
|
Forwarded to :func: |
False
|
Returns:
| Type | Description |
|---|---|
SegmentValues
|
Array with the same shape as |
SegmentValues
|
become |
Source code in anytensor/segment.py
segment_softmax
¶
Softmax within segments (numerically stable).
Subtracts the per-segment max before exp, then normalizes by the
per-segment sum of exps — same pattern as a stable full softmax.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
logits
|
SegmentValues
|
Scores. Leading axis is the segment axis. |
required |
segment_ids
|
SegmentIds
|
Integer segment ids (see :func: |
required |
num_segments
|
ShapeSize
|
Required shape-size (Python |
required |
sorted
|
bool
|
Forwarded to underlying segment ops (no-op on NumPy/Torch). |
False
|
Returns:
| Type | Description |
|---|---|
SegmentValues
|
Array with the same shape as |
SegmentValues
|
sum to |
SegmentValues
|
nothing useful if referenced via ids). |
Notes
Inherits empty-slot segment_max identity (-inf) and TF NaN
OR-in behavior from :func:segment_max / :func:segment_sum.
Not TorchScript-safe today (needs Python dispatch).
Source code in anytensor/segment.py
segment_min_or_constant
¶
Segment min with a finite fill for empty segments.
Like :func:segment_min, but empty slots become constant instead of
+inf / dtype max.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
SegmentValues
|
Values. Leading axis is the segment axis. |
required |
segment_ids
|
SegmentIds
|
Integer segment ids (see :func: |
required |
num_segments
|
ShapeSize
|
Required shape-size. |
required |
constant
|
float
|
Fill for empty segments (default |
0.0
|
sorted
|
bool
|
Forwarded to :func: |
False
|
Returns:
| Type | Description |
|---|---|
SegmentOut
|
Array of shape |
Source code in anytensor/segment.py
segment_max_or_constant
¶
Segment max with a finite fill for empty segments.
Like :func:segment_max, but empty slots become constant instead of
-inf / dtype min.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
SegmentValues
|
Values. Leading axis is the segment axis. |
required |
segment_ids
|
SegmentIds
|
Integer segment ids (see :func: |
required |
num_segments
|
ShapeSize
|
Required shape-size. |
required |
constant
|
float
|
Fill for empty segments (default |
0.0
|
sorted
|
bool
|
Forwarded to :func: |
False
|
Returns:
| Type | Description |
|---|---|
SegmentOut
|
Array of shape |
Source code in anytensor/segment.py
partition_softmax
¶
Softmax within contiguous partitions of lengths partitions.
Convenience: :func:partition_ids then :func:segment_softmax.
num_segments is shape(partitions)[0] — not an argument.
total_length is required (shape(logits)[0], not a data
sum(partitions)). Does not talk to :data:cache itself —
:func:partition_ids does, so a cache hit is shared with every
partition helper. Ids are rebuilt on every call unless that
cache is active. A compiler may CSE the rebuild; eager will not.
If you already have ids, call :func:segment_softmax.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
logits
|
ShapedArray
|
Scores aligned with the flattened partitions (length
|
required |
partitions
|
IntArray
|
1-D integer vector of partition sizes. Length is the number of segments. |
required |
total_length
|
ShapeSize
|
Required shape-size for the flattened length
( |
required |
Returns:
| Type | Description |
|---|---|
ShapedArray
|
Softmax of |
Source code in anytensor/segment.py
partition_sum
¶
Sum within contiguous partitions of lengths partitions.
Convenience: :func:partition_ids then :func:segment_sum.
num_segments is shape(partitions)[0] — not an argument.
total_length is required (shape(x)[0], not a data
sum(partitions)). Does not talk to :data:cache itself —
:func:partition_ids does, so a cache hit is shared with every
partition helper. If you already have ids, call :func:segment_sum.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
ShapedArray
|
Values aligned with the flattened partitions (length
|
required |
partitions
|
IntArray
|
1-D integer vector of partition sizes. Length is the number of segments. |
required |
total_length
|
ShapeSize
|
Required shape-size for the flattened length
( |
required |
Returns:
| Type | Description |
|---|---|
ShapedArray
|
Array of shape |
ShapedArray
|
partitions are |
Source code in anytensor/segment.py
partition_min
¶
Minimum within contiguous partitions of lengths partitions.
Convenience: :func:partition_ids then :func:segment_min. Same
contracts as :func:partition_sum. Empty partitions keep the min
identity (+inf / dtype max). Prefer
:func:segment_min_or_constant after :func:partition_ids for a
finite empty fill.
Source code in anytensor/segment.py
partition_max
¶
Maximum within contiguous partitions of lengths partitions.
Convenience: :func:partition_ids then :func:segment_max. Same
contracts as :func:partition_sum. Empty partitions keep the max
identity (-inf / dtype min). Prefer
:func:segment_max_or_constant after :func:partition_ids for a
finite empty fill.
Source code in anytensor/segment.py
partition_ids
¶
Expand partition lengths to segment ids ([0,0,…,1,1,…,n-1]).
This is the conversion other partition helpers call internally.
num_segments is shape(partitions)[0] (not an argument; not
data-dependent). total_length is the required flattened length
(shape(logits)[0], not a data sum(partitions)). Passed to
:func:repeat as total_repeat_length.
The only partition helper that talks to :data:cache. Uses
:meth:cache.lookup / :meth:cache.store on "partition". Outside
the cache, every call rebuilds ids. Inside, the same partitions
tensor returns the previous ids from cache["partition"] until
the tensor is collected or the block exits — one entry per
partition vector. The flattened total is shape(ids)[0] (not a
separate sum(partitions) cache); on ONNX export that length is a
dim_param. If a cached expansion's length does not match
total_length (in-place edit of a 0-d size, or a stale entry),
that entry is purged, a warning is issued, and ids are recomputed.
The length check uses host Python ints only; tracing skips it.
Passing None for total_length is a TypeError.
Source code in anytensor/segment.py
enable_torchscript
¶
Enable torch.jit.script through public segment_sum / min / max.
Wraps those helpers with a torch.jit.is_scripting() divert to
:mod:anytensor.torchscript. Eager behavior is unchanged: NumPy, JAX,
Torch, and TF tensors still dispatch via backends. Only while scripting
(or inside an already-scripted graph) do we take the pure-Torch kernels.
That lets a third-party library call anytensor.segment_sum in ordinary
Python, while an end user of that library can torch.jit.script their
own code that reaches those calls.
Does not import torch and does not require a particular import order.
If Torch is not loaded yet, a helper is registered with
:func:anytensor.module_if_loaded and the divert enables on a later
import torch. Returns False until then; safe to call more than once.
Source code in anytensor/segment.py
repeat
¶
Repeat elements of x.
Similar to NumPy / JAX repeat. When total_repeat_length is set with
per-element repeats, matches JAX jnp.repeat(..., total_repeat_length=)
(pad or slice the leading axis to that length).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
ShapedArray
|
Input array. |
required |
repeats
|
Any
|
Python |
required |
total_repeat_length
|
Optional[ShapeSize]
|
Optional shape-size (Python |
None
|
axis
|
Optional[int]
|
Axis to repeat along; |
None
|
Returns:
| Type | Description |
|---|---|
ShapedArray
|
Array with repeated elements on the same backend as |
Notes
Under jax.jit, jnp.repeat needs static repeat counts or a
static total_repeat_length. :func:~anytensor.partition_softmax
always passes total_length as that length. Omitting
total_repeat_length on :func:repeat itself is fine eagerly and
on TensorFlow.
Source code in anytensor/core.py
take
¶
Take elements from x along axis (default 0).
Source code in anytensor/core.py
exp
¶
log
¶
sum
¶
Sum over axes; full reduce returns a 0-d array (not a scalar).
min
¶
Minimum over axes; full reduce returns a 0-d array (not a scalar).
Notes
Length-0 reductions are framework-defined (often error) — prefer
nonempty. Under TF XLA (jit_compile=True), NaN inputs may yield
±inf instead of NaN; eager TF / NumPy / JAX usually keep NaN.
Source code in anytensor/core.py
max
¶
Maximum over axes; full reduce returns a 0-d array (not a scalar).
Notes
Length-0 reductions are framework-defined (often error) — prefer
nonempty. Under TF XLA, NaN inputs may yield ±inf instead of NaN.
Source code in anytensor/core.py
mean
¶
Mean over axes; full reduce returns a 0-d array (not a scalar).
Notes
Empty full-reduce (x.size == 0) returns a 0-d NaN on the backend
dtype to avoid NumPy's Mean of empty slice warning path.
Source code in anytensor/core.py
prod
¶
Product over axes; full reduce returns a 0-d array (not a scalar).
Notes
inf * a subnormal or float32-min value may be inf (NumPy /
eager TF) or nan (JAX / TF XLA) when the tiny flushes to 0. Not
standardized — keep finite samples away from the underflow edge if
you need portable results.
Source code in anytensor/core.py
shape
¶
Return the shape of x as a tuple.
Under tracing (tf.function, jax.jit, torch.compile), unknown
dims are backend size tensors / symbols rather than Python None, so
callers can build matching outputs under jit/compile.
Notes
Prefer this over raw x.shape when feeding zeros / full /
*_like under polymorphic TF graphs — tnp.zeros errors on
TensorShape(None,) after retracing.
Source code in anytensor/core.py
cumsum
¶
Cumulative sum along axis (default 0, never flatten).
reshape
¶
transpose
¶
Permute axes of x.
Source code in anytensor/core.py
concatenate
¶
Concatenate a sequence of arrays along axis.
split
¶
Split x along axis (NumPy split semantics).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
ShapedArray
|
Array to split. |
required |
indices_or_sections
|
Any
|
Either an |
required |
axis
|
int
|
Axis along which to split. |
0
|
Returns:
| Type | Description |
|---|---|
list
|
A |
Notes
Dispatches via :func:anytensor.backends.get_backend so Torch uses
tensor_split (index cuts) rather than size-based torch.split.
Source code in anytensor/core.py
stack
¶
maximum
¶
Element-wise maximum. Scalars/NumPy upcast; dtypes via result_type.
Notes
Under TF XLA (jit_compile=True), NaN inputs may yield ±inf
instead of NaN; eager TF / NumPy / JAX usually keep NaN. Not
standardized across backends.
Source code in anytensor/core.py
minimum
¶
Element-wise minimum. Scalars/NumPy upcast; dtypes via result_type.
Notes
Under TF XLA, NaN inputs may yield ±inf instead of NaN. Not
standardized across backends.
Source code in anytensor/core.py
sqrt
¶
rsqrt
¶
Element-wise reciprocal square root (1 / sqrt(x)).
where
¶
Choose from x or y by condition. Scalars/NumPy upcast.
Source code in anytensor/core.py
clip
¶
Clip values to [min, max].
Implemented with :func:maximum / :func:minimum so TF tracing does not
emit BroadcastArgs (tf2onnx cannot lower that op).
Source code in anytensor/core.py
astype
¶
cast
¶
zeros_like
¶
Return zeros with the same shape (and backend) as x.
Built from :func:shape so polymorphic tf.function sees symbolic
sizes instead of None dims (raw tnp.zeros_like / tnp.zeros can
fail after retracing).
Source code in anytensor/core.py
ones_like
¶
Return ones with the same shape (and backend) as x.
Uses :func:shape for graph-safe sizes under tf.function (see
:func:zeros_like).
Source code in anytensor/core.py
full_like
¶
Return an array filled with fill_value matching x.
Uses :func:shape for graph-safe sizes under tf.function (see
:func:zeros_like).
Source code in anytensor/core.py
zeros
¶
Return zeros; pass like= to select the backend.
Source code in anytensor/core.py
ones
¶
Return ones; pass like= to select the backend.
Source code in anytensor/core.py
full
¶
Return a filled array; pass like= to select the backend.
Source code in anytensor/core.py
arange
¶
Evenly spaced values; pass like= to select the backend.
device is forwarded when supported (e.g. Torch).
Source code in anytensor/core.py
matmul
¶
Matrix product of two arrays. NumPy operands upcast onto peers.
inf
¶
ninf
¶
nan
¶
pi
¶
e
¶
finfo
¶
iinfo
¶
dtype
¶
is_nan
¶
is_finite
¶
is_inf
¶
fill_nan
¶
Replace NaNs in x with value (broadcasts). Leaves ±inf unchanged.
Source code in anytensor/core.py
fill_nan_mask
¶
Return (filled, mask): NaNs replaced, plus a boolean NaN mask.
mask is True where x was NaN (same polarity as :func:is_nan /
NumPy masked-array invalid). Boolean, not 0/1 — cast if you need weights.
Equivalent to (fill_nan(x, value), is_nan(x)); not ~is_finite
(±inf is non-NaN).
Source code in anytensor/core.py
nan_to_num
¶
Replace NaN and ±inf (Array API nan_to_num).
Defaults: NaN → nan (0.0); posinf / neginf None → large
finite values from the dtype's finfo (framework-dependent).
Source code in anytensor/core.py
equal_nan
¶
Element-wise equality treating NaN as equal to NaN.
Returns a boolean array: (x == y) | (isnan(x) & isnan(y)).
Non-NaN values compare with ordinary == (so +inf == +inf).
Source code in anytensor/core.py
promote
¶
Decorator: namespace upcast + per-operand dtype policy.
Pass keyword roles for each parameter::
@promote(x="data", y="data")
def maximum(x: ArrayT, y: ArrayT) -> ArrayT: ...
@promote(x="data", indices="index")
def take(x, indices, axis=0): ...
@promote(condition="mask", x="data", y="data")
def where(condition: ArrayT, x: ArrayT, y: ArrayT) -> ArrayT: ...
@promote(x="data", segment_ids="index", num_segments="shape")
def segment_sum(x, segment_ids, num_segments): ...
data operands share Array API result_type (so a NumPy int beside a
float tensor becomes float). index stays integral (width is
backend-local: Torch may cast to int64; JAX/TF often keep int32). mask
becomes bool. shape is a size dim (Python int / symbolic / 0-d integral
tensor) and is not promoted to a 0-d array.
copy / fallback control NumPy→framework buffer sharing (see
:func:promote_options).
Source code in anytensor/core.py
promote_scalars
¶
Upcast named operands as data (namespace + result_type).
Prefer :func:promote when some args are indices/masks. Kept as a short
form of @promote(x="data", y="data").
Source code in anytensor/core.py
promote_options
¶
Temporarily set NumPy-upcast defaults (copy / non-ref fallback).
Example::
with at.promote_options(copy=True):
y = at.maximum(torch_x, numpy_y) # safe if numpy_y will be mutated
Source code in anytensor/core.py
align_arrays
¶
Align operands on one namespace; upcast scalars/NumPy to non-NumPy peers.
None entries are preserved (useful when optional operands share a call).
Source code in anytensor/core.py
empty_segment_identity
¶
Return the AnyTensor empty-segment identity for reduction on dtype.
This is the portable fill used for empty slots in segment_sum /
segment_min / segment_max (and backends that implement them).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dtype
|
Any
|
Target dtype (NumPy / Array API / TF dtype with
|
required |
reduction
|
str
|
One of |
required |
xp
|
Any
|
Array API-ish namespace with |
required |
Returns:
| Type | Description |
|---|---|
Any
|
|
Any
|
|
Notes
Differs from TF unsorted_segment_{min,max}, which fill empties
(and ±inf-only segments) with finfo limits. AnyTensor uses these
identities so empties and occupied ±inf match NumPy/JAX/Torch.
Source code in anytensor/semantics.py
enable_typecheck
¶
Opt-in runtime jaxtyping checks for subsequent anytensor imports.
Must be called before importing the modules you want checked (or use
:func:jaxtyping.install_import_hook yourself at process start). Default
AnyTensor imports do not install this hook.
Hooks core / segment / namespace / semantics / backends /
typing — not :mod:anytensor.torchscript, whose divert wrappers must
remain torch.jit.script-compilable.
Requires the named typechecker package (default: beartype).