Describe your issue
In SciPy 1.18.0, stats.Normal.logcdf(low, high) returns negative infinity for several strictly positive finite-width events whose log probability is representable. For a very narrow central interval, cdf(low, high) also returns zero even when the probability is representable.
Reproducing Code Example
import math
from scipy import stats
cases = [
(0.0, 1.0, 0.0, 1e-20),
(0.0, 1.0, 0.0, math.ulp(0.0)),
(-1e18, 1e8, 0.0, 1.0),
]
for mean, sd, low, high in cases:
law = stats.Normal(mu=mean, sigma=sd)
print(law.logcdf(low, high), law.cdf(low, high))
Observed result
The public API probe returned (-inf+0j) and 0.0 for each row, without warnings. These are SciPy outputs, not expected-value fixtures.
Independently derived expectation
For the first row, monotonicity of the standard normal density on the positive half-line puts log probability between log(w) - log(2*pi)/2 - w*w/2 and log(w) - log(2*pi)/2, where w=1e-20. Both bounds round to a finite binary64 value. The ordinary probability is also representable and positive.
For the least-subnormal width, ordinary probability may correctly round to zero, but the same logarithmic density-integral bounds remain finite.
For the third row, the true standardized interval starts at 1e10 and has width 1e-8. Its two separately standardized endpoints round equal. Integrating the density over the original physical width gives a finite log mass near -5e19; density monotonicity bounds its width in log space well below one binary64 ulp at that magnitude. Ordinary probability correctly underflows in this case, but the logarithm need not.
The source inspection at SciPy tag 1.18.0, commit 54ef5423f2e4376230ec3bfda6912a07a50958e3, covered the two-bound CDF/log-CDF dispatch and fallback paths, the Normal standardization, and _log_gauss_mass. This report concerns released 1.18.0; I have not run a development build. Searches for Normal/logcdf, logcdf/interval and narrow intervals found no matching univariate issue; #14286 concerns multivariate normal integration.
SciPy/NumPy/Python version and system information
1.18.0 2.5.2 sys.version_info(major=3, minor=14, micro=7, releaselevel='final', serial=0)
Build Dependencies:
blas:
cython blas ilp64: false
detection method: pkgconfig
found: true
has ilp64: false
include directory: /opt/_internal/cpython-3.14.3/lib/python3.14/site-packages/scipy_openblas32/include
lib directory: /opt/_internal/cpython-3.14.3/lib/python3.14/site-packages/scipy_openblas32/lib
name: scipy-openblas
openblas configuration: OpenBLAS 0.3.31.dev DYNAMIC_ARCH NO_AFFINITY Haswell MAX_THREADS=64
pc file directory: /project/.openblas
version: 0.3.31.dev
lapack:
detection method: pkgconfig
found: true
has ilp64: false
include directory: /opt/_internal/cpython-3.14.3/lib/python3.14/site-packages/scipy_openblas32/include
lib directory: /opt/_internal/cpython-3.14.3/lib/python3.14/site-packages/scipy_openblas32/lib
name: scipy-openblas
openblas configuration: OpenBLAS 0.3.31.dev DYNAMIC_ARCH NO_AFFINITY Haswell MAX_THREADS=64
pc file directory: /project/.openblas
version: 0.3.31.dev
pybind11:
detection method: config-tool
include directory: unknown
name: pybind11
version: 3.0.4
Compilers:
c:
commands: cc
linker: ld.bfd
name: gcc
version: 14.2.1
c++:
commands: c++
linker: ld.bfd
name: gcc
version: 14.2.1
cython:
commands: cython
linker: cython
name: cython
version: 3.2.5
fortran:
commands: gfortran
linker: ld.bfd
name: gcc
version: 14.2.1
pythran:
include directory: ../../../tmp/build-env-0nidrt1y/lib/python3.14/site-packages/pythran
version: 0.18.1
Machine Information:
build:
cpu: x86_64
endian: little
family: x86_64
system: linux
cross-compiled: false
host:
cpu: x86_64
endian: little
family: x86_64
system: linux
Python Information:
path: /tmp/build-env-0nidrt1y/bin/python
version: '3.14'
Describe your issue
In SciPy 1.18.0,
stats.Normal.logcdf(low, high)returns negative infinity for several strictly positive finite-width events whose log probability is representable. For a very narrow central interval,cdf(low, high)also returns zero even when the probability is representable.Reproducing Code Example
Observed result
The public API probe returned
(-inf+0j)and0.0for each row, without warnings. These are SciPy outputs, not expected-value fixtures.Independently derived expectation
For the first row, monotonicity of the standard normal density on the positive half-line puts log probability between
log(w) - log(2*pi)/2 - w*w/2andlog(w) - log(2*pi)/2, wherew=1e-20. Both bounds round to a finite binary64 value. The ordinary probability is also representable and positive.For the least-subnormal width, ordinary probability may correctly round to zero, but the same logarithmic density-integral bounds remain finite.
For the third row, the true standardized interval starts at
1e10and has width1e-8. Its two separately standardized endpoints round equal. Integrating the density over the original physical width gives a finite log mass near-5e19; density monotonicity bounds its width in log space well below one binary64 ulp at that magnitude. Ordinary probability correctly underflows in this case, but the logarithm need not.The source inspection at SciPy tag 1.18.0, commit
54ef5423f2e4376230ec3bfda6912a07a50958e3, covered the two-bound CDF/log-CDF dispatch and fallback paths, the Normal standardization, and_log_gauss_mass. This report concerns released 1.18.0; I have not run a development build. Searches for Normal/logcdf, logcdf/interval and narrow intervals found no matching univariate issue; #14286 concerns multivariate normal integration.SciPy/NumPy/Python version and system information