Affects: mkl_random.MKLRandomState.geometric, mkl_random.interfaces.numpy_random.geometric, and numpy.random.geometric after mkl_random.patch_numpy_random()
Issue
Every sample from geometric(p) is one less than it should be.
NumPy defines the geometric distribution on k = 1, 2, ... with f(k) = (1 - p)^(k-1) p. mkl_random's docstring (mklrand.pyx:6018-6024) states the same, and the NumPy interface refers users to numpy.random.geometric.
irk_geometric_vec (src/mkl_distributions.cpp:1302) returns the output of viRngGeometric unchanged. oneMKL defines that output as the number of failures before the first success: P(X = k) = p (1 - p)^k for k in {0, 1, 2, ...}. The p == 1.0 branch writes 0 where NumPy returns 1.
test_randomdsit_geometric (tests/test_random.py:864) has 0 in its expected values, so the suite passes with this behaviour.
import numpy as np
import mkl_random
x = mkl_random.interfaces.numpy_random.RandomState(1).geometric(0.3, size=10**7)
print(x.min(), x.mean()) # 0 2.3330
print(np.random.RandomState(1).geometric(0.3, size=10**7).mean()) # 3.3331
mkl_random.patch_numpy_random()
print(np.random.geometric(0.3, size=10**6).min()) # 0
print(mkl_random.interfaces.numpy_random.RandomState(0).geometric(1.0, 3)) # [0 0 0]; NumPy: [1 1 1]
How found
Chi-square goodness-of-fit against the exact k >= 1 pmf, with 10^7 draws and seeds 1, 2 and 3. As a control, an exact inverse-CDF sampler under the same test gives z ~ N(0, 1).
| p |
exact mean |
mkl_random mean |
mkl_random z |
mkl_random + 1, z |
NumPy Generator z |
| 0.01 |
100.000 |
98.975 |
20.7, 20.9, 23.1 |
-1.4, -1.3, 0.8 |
-0.4, -0.7, 0.5 |
| 0.3 |
3.3333 |
2.3325 |
~1.0e5 |
-0.9, 0.3, 0.6 |
-1.7, -0.3, -0.4 |
| 0.5 |
2.0000 |
0.9995 |
~4.0e5 |
-1.0, 0.4, -1.7 |
0.7, -0.5, -0.5 |
| 0.9 |
1.1111 |
0.1109 |
~2.3e6 |
0.3, 0.3, -0.2 |
2.2, 1.3, 0.2 |
The unshifted output fits the k >= 0 pmf (z between -1.4 and 0.3). The output is bit-identical to calling viRngGeometric directly. It is also identical with oneMKL 2023.2, 2024.2.2, 2025.0.1, 2025.3.1, 2026.0 and 2026.1, and on all six BRNGs (MT19937, SFMT19937, MT2203, MCG59, PHILOX4X32X10, ARS5).
Environment: mkl_random 1.5.0 (py313h581662c_0, Intel channel), oneMKL 2026.1.0, NumPy 2.4.3, Linux x86-64.
Impact
With the patch enabled, code calling numpy.random.geometric gets different results: the mean is 1 lower, and 0 appears with probability p although NumPy never returns it. Scalar p, array p and p = 1 are all affected.
Possible fix
- Add 1 to each element after
viRngGeometric in irk_geometric_vec, and write 1 in the p == 1.0 branch.
- Update the expected values in
test_randomdsit_geometric. Add a test that geometric(p).min() >= 1 and that the mean is within tolerance of 1/p.
- Check the other discrete wrappers for the same oneMKL-vs-NumPy support mismatch.
Affects:
mkl_random.MKLRandomState.geometric,mkl_random.interfaces.numpy_random.geometric, andnumpy.random.geometricaftermkl_random.patch_numpy_random()Issue
Every sample from
geometric(p)is one less than it should be.NumPy defines the geometric distribution on k = 1, 2, ... with f(k) = (1 - p)^(k-1) p. mkl_random's docstring (
mklrand.pyx:6018-6024) states the same, and the NumPy interface refers users tonumpy.random.geometric.irk_geometric_vec(src/mkl_distributions.cpp:1302) returns the output ofviRngGeometricunchanged. oneMKL defines that output as the number of failures before the first success: P(X = k) = p (1 - p)^k for k in {0, 1, 2, ...}. Thep == 1.0branch writes 0 where NumPy returns 1.test_randomdsit_geometric(tests/test_random.py:864) has 0 in its expected values, so the suite passes with this behaviour.How found
Chi-square goodness-of-fit against the exact k >= 1 pmf, with 10^7 draws and seeds 1, 2 and 3. As a control, an exact inverse-CDF sampler under the same test gives z ~ N(0, 1).
The unshifted output fits the k >= 0 pmf (z between -1.4 and 0.3). The output is bit-identical to calling
viRngGeometricdirectly. It is also identical with oneMKL 2023.2, 2024.2.2, 2025.0.1, 2025.3.1, 2026.0 and 2026.1, and on all six BRNGs (MT19937, SFMT19937, MT2203, MCG59, PHILOX4X32X10, ARS5).Environment: mkl_random 1.5.0 (
py313h581662c_0, Intel channel), oneMKL 2026.1.0, NumPy 2.4.3, Linux x86-64.Impact
With the patch enabled, code calling
numpy.random.geometricgets different results: the mean is 1 lower, and 0 appears with probability p although NumPy never returns it. Scalarp, arraypandp = 1are all affected.Possible fix
viRngGeometricinirk_geometric_vec, and write 1 in thep == 1.0branch.test_randomdsit_geometric. Add a test thatgeometric(p).min() >= 1and that the mean is within tolerance of 1/p.