Repository navigation
Description
Is this a duplicate?
- I confirmed there appear to be no duplicate issues for this bug and that I agree to the Code of Conduct
Type of Bug
Something else
Component
libcu++
Describe the bug
Testing and verification of <cuda/std/random> and <cuda/random> found the following issues:
Note that these bugs are probably also in llvm.
-
generate_canonicalcan return1, violating[0,1)for bothfloatanddouble. -
uniform_real_distributioncan return its excluded upper bound, even when its canonical input is strictly below1. For example,(1,2)can return2. -
bernoulli_distribution(1.0)can returnfalsebecause of the canonical endpoint defect. - Binomial construction can overflow signed integers.
binomial_distribution<int>(INT_MAX, 0.5)overflows int + 1. - Gamma can fail to terminate for large finite shapes. For
alpha = numeric_limits<T>::max() / 2,3 * alpha - 0.75overflows, preventing acceptance. - Fisher’s F can return NaN for large finite parameters. Examples include
float(m=n=1e20)anddouble(m=n=1e200), where intermediate products produceinfinity / infinity. - Student’s t equality ignores cached normal state. Objects can compare equal but produce different outputs from identical engines.
- Student’s t serialization omits cached normal state, changing the sequence after restoration.
- Normal and lognormal serialization loses precision. Fixed decimal formatting turns tiny positive standard deviations into zero and loses
long doubleprecision. - Bernoulli and binomial serialization loses probability precision and changes the caller’s fill character.
- Poisson serialization loses mean precision.
- Byte-sized uniform-integer and binomial states can fail serialization round-trips because numeric values are streamed as characters.
-
seed_seqtraverses single-pass input twice. Constructing from stream iterators over"1 2 3 4 5"reproduced stored seeds[1,1,1,1,1]. - PCG extraction changes engine state after encountering malformed input. Reading
"123 x"setsfailbitbut commits a changed state. - Feistel operations evaluate undefined shifts at 64-bit sizes:
1ULL << 64and a 32-bit right shift by32. -
random_bijection<signed char>can return negative indices. Narrowing precedes the range check; a ten-element mapping returned-127. - Check byte-state serialization when integrating [libcu++]
linear_congruential_engine: fixm == 0,discardfor largem,operator<<and overflow innext()#12532. The tested PR head streams unsigned-byte state as a character; state9becomes a tab and cannot round-trip. - Fix an out-of-bounds read in the discrete-distribution test helper. It evaluates
samples[i + 1]before checking whetheriis the final sample.
Verification combined source inspection, standalone CPU/GPU reproductions, differential testing, statistical checks, sanitizers, and selected formal models:
- Z3 4.8.12, accessed from Python through
ctypes, checked standalone SMT-LIB models of bit-vector arithmetic and IEEE-754 floating-point operations. Unconstrained symbolic searches independently found canonical-generation and uniform-scaling counterexamples for bothfloatanddouble. The extended pass resolved 328 additional obligations, including proofs of the modeled gamma rejection failure and conditional Fisher NaN behavior. - GCC 13.3 and Clang 18, with UBSan, checked integer overflow, invalid shifts, and floating-point conversions. AddressSanitizer reproduced the test-helper heap-buffer-overflow.
- CUDA 12.9.86, targeting
sm_120, ran tests on two NVIDIA RTX PRO 6000 Blackwell Workstation Edition GPUs. Testing included native and fallback PCG implementations, 10,485,760 fallback-arithmetic comparisons, and 262,144 targeted Fisher samples, all of which returned NaN. - Python arbitrary-precision integers supplied independent PCG reference vectors. LCG checks used exact 128-bit reference arithmetic, while
seed_seqwas compared against libstdc++. The extended pass ran 1,130,496 LCG checks and 30,000 seed-sequence differential cases. - SciPy CDF comparisons screened 12,058,624 GPU samples across all 17 distribution families. Targeted edge tests exposed defects that these ordinary-parameter statistical checks missed.
- State tests exercised serialization, equality, copying, reset, and explicit parameters. The existing 28 runtime test files were also attempted, with compiler-specific replays where necessary.
The primary tested snapshot was 7a915df33570ce6dd70cbaf15a5c3c53d5d8c5ec; LCG checks used the header from #12532 at 655408067f3efb949191b83fbe7ff547ad8b0a8d. The 11 newly implicated non-LCG headers were byte-for-byte identical to fetched main at the time of review.
The formal results verify manually translated expressions and selected failure paths. They do not constitute automatic verification of the complete C++ implementation, compiler lowering, or every distribution’s probability law.
How to Reproduce
.
Expected behavior
.
Reproduction link
No response
Operating System
No response
nvidia-smi output
No response
NVCC version
No response
Activity
roma5087 commentedon Nov 12, 2026
Hi @RAMitchell, Could this issue be assigned to me?
I'd split it into small PRs grouped by area, each with regression tests:
Two questions before I start:
linear_congruential_engine: fixm == 0,discardfor largem,operator<<and overflow innext()#12532 byte-state item stay with that PR?RAMitchell commentedon Nov 12, 2026
@roma5087 at this stage no, but you could go over to llvm and see if the same bugs exist and see if they want help with that.