Describe the bug
mx.random.randint is documented to sample integers with equal probability
from [low, high). When the bounds are not exactly representable in
float32, it can return the excluded high value, omit valid integers, or
collapse a valid int64 interval to a constant.
To Reproduce
import mlx.core as mx
key = mx.random.key(42)
for stream in (mx.cpu, mx.gpu):
x = mx.random.randint(
2**24, 2**24 + 2, (10_000,),
dtype=mx.int32, key=key, stream=stream,
)
y = mx.random.randint(
2**40, 2**40 + 1024, (10_000,),
dtype=mx.int64, key=key, stream=stream,
)
mx.eval(x, y)
print(stream, sorted(set(x.tolist())), len(set(y.tolist())))
Observed on both CPU and Metal:
cpu [16777216, 16777218] 1
gpu [16777216, 16777218] 1
In the first call, 16777218 is high and should never be returned, while the
valid value 16777217 is absent. The second call produces only 2**40.
Expected behavior
Every result should be in [low, high), and every integer in the interval
should be reachable with equal probability.
Root cause
The current implementation routes randint through a float32 uniform
sample:
auto u = uniform(low, high, shape, float32, key, s);
return astype(maximum(u, low, s), dtype, s);
At 2**24, adjacent float32 values are two integers apart. At 2**40, their
spacing is 2**17, so the integer interval is lost before the final cast. The
relevant implementation is unchanged on current main.
Desktop
- macOS 26.5.2, arm64
- MLX 0.32.0
- Reproduced on
mx.cpu and mx.gpu
Additional context
I searched open and closed issues and PRs for this behavior and did not find a
duplicate. #429 / #457 concern global seeding, #1932 is a docstring fix, and
#2361 concerns floating uniform sampling. The review discussion in #2361
seems relevant because it treats loss of reachable random values as a major
bug and calls for a long-term fix to recurring sampling issues.
A clamp to high - 1 would prevent the out-of-bounds result but would retain
missing values and severe bias. Before preparing a patch, I would like to
confirm whether an exact bounded-integer sampler based on the existing
Threefry words is the preferred direction. If so, I am happy to put up a
focused PR with boundary regression tests.
I put this report together with help from an AI coding assistant, mainly to
research previous issues and PRs and cross-check the relevant implementation.
I verified the reproduction and reviewed the report before posting.
Describe the bug
mx.random.randintis documented to sample integers with equal probabilityfrom
[low, high). When the bounds are not exactly representable infloat32, it can return the excludedhighvalue, omit valid integers, orcollapse a valid
int64interval to a constant.To Reproduce
Observed on both CPU and Metal:
In the first call,
16777218ishighand should never be returned, while thevalid value
16777217is absent. The second call produces only2**40.Expected behavior
Every result should be in
[low, high), and every integer in the intervalshould be reachable with equal probability.
Root cause
The current implementation routes
randintthrough afloat32uniformsample:
At
2**24, adjacentfloat32values are two integers apart. At2**40, theirspacing is
2**17, so the integer interval is lost before the final cast. Therelevant implementation is unchanged on current main.
Desktop
mx.cpuandmx.gpuAdditional context
I searched open and closed issues and PRs for this behavior and did not find a
duplicate. #429 / #457 concern global seeding, #1932 is a docstring fix, and
#2361 concerns floating uniform sampling. The review discussion in #2361
seems relevant because it treats loss of reachable random values as a major
bug and calls for a long-term fix to recurring sampling issues.
A clamp to
high - 1would prevent the out-of-bounds result but would retainmissing values and severe bias. Before preparing a patch, I would like to
confirm whether an exact bounded-integer sampler based on the existing
Threefry words is the preferred direction. If so, I am happy to put up a
focused PR with boundary regression tests.
I put this report together with help from an AI coding assistant, mainly to
research previous issues and PRs and cross-check the relevant implementation.
I verified the reproduction and reviewed the report before posting.