tandem rng tandem-c GitHub

Tests

make test
make stats                # the distribution of 10^8 f64 normals, about 15 s
make test-target          # the OpenMP target fills against the host fills

Suite

tests/test_vectors.c checks every vector of the specification. tests/test_stream.c compares long fills, scalar draws, and random access against reference stream dumps in tests/data. tests/test_api.c checks the functions that are not part of the specification's draws. The bounded integers (scalar and fill) and f32 normals are compared, values and stream position, with fixtures from the shared core of tandem-cuda. The f32 normals match bit for bit, because the host core runs the same explicit-fma loop. Device f32 normals from the device-derived fill fixtures of tandem-cuda match within 16 ulps, and their f64 ziggurat rows match bit for bit. Exponential fills and scalar draws must match the same core bit for bit from five start positions, unaligned ones included.

tests/test_api.c also checks that an f64 fill equals the scalar draws and that fills cut at odd elements and at a missed element equal the whole fill, over 40000 elements, and that an empty fill only aligns the position. tests/test_normal_bits.c checks the FNV-1a hash a61cfa844c85f7c1 of 10^6 f64 normals from each of five positions. It also checks 2 x 10^5 f64 normals from two positions against a Python implementation written from the text of Appendix A, and the FNV-1a hash aa1ea656ce73a4fb of the f32 normals from the five positions. tests/test_normal_stats.c checks 10^8 f64 normals against the standard normal: raw moments 1 to 6 and the counts beyond 3, 3.5, 4, 4.5 and 5 within four standard errors, and Kolmogorov-Smirnov and Anderson-Darling p-values above 0.001.

tests/test_api.c also cuts exponential fills at several elements and compares them with the whole fill and the scalar draws, and checks 10^7 f64 and 10^7 f32 exponentials against Exp(1): the first four raw moments within five standard errors and a Kolmogorov-Smirnov statistic below the 0.1 % point. tests/test_exponential_bits.c checks the FNV-1a hash 1c761a2d471073c2 of 10^6 f64 and 10^6 f32 exponentials from each of five positions.

tests/test_cpp.cpp checks that the C++ wrapper, including at, below, normal, normal2, exponential, set_position and the extra draw types, agrees with the C API and runs <random>. Compiled as C++20 it also checks std::uniform_random_bit_generator.

tests/test_target.c compares the four OpenMP target fills bit for bit with the host fills over four chunk lengths, aligned and unaligned starts, and sizes from 0 to 2^20.

Fixtures

tests/vectors.h is generated from the spec repository's vectors.json by tools/gen_vectors.py. The stream dumps in tests/data are written by tools/dump_streams.jl.

tools/gen_cross.cpp computes the bounded integer, f32 normal and exponential fixtures from the shared core of tandem-cuda. tests/cross_exponential.h holds exponentials of that core from five start positions, unaligned ones included. The device-derived fill fixtures of tandem-cuda are copied to tests/cuda_fill_*.h. make cross regenerates the fixtures.

This library is the reference of the f64 normals. tools/gen_cross.cpp writes their rows of tests/cross_normal.h from it: fills of 64 elements from the key of seed 42 at bits 0, 1 and 12345, and at three more unaligned starts that put a wedge accept, a wedge reject and a tail draw at element 20. Ports check against this file, whose SHA-256 is 3cd7c8f9178711255718288eb712eaccb33a1726d2a185f412f13590398ad3ac.

This library is also the reference of weighted choice, Appendix C. tests/cross_choice.h holds fills of 64 indices from six weight tables, zero, subnormal and near-overflow weights and 100 weights among them, from the key of seed 42 at bits 0, 1 and 12345. Its SHA-256 is 73c0badade569b913eb01a2883ae4ae995e90f5b04e8bb7adaa3f42a957eb0bc. The spec's choice vectors, which tests/test_vectors.c checks, were computed apart from this library from the spec text and the stream dump. tests/test_api.c runs a chi-square test on 10^7 indices.

tools/dump_normals.c writes the bytes that tests/test_normal_bits.c hashes, whose SHA-256 is 700ec4d2f4d6b82aaa56c6eff18a4e5919585fdbd093988773383d580ea610d1. tools/dump_exponentials.c writes the bytes that tests/test_exponential_bits.c hashes, whose SHA-256 is 7b12b7c36baf14ab42f7736a5a67925c3c7b1bfafc8d50f078ba1af927044dd5. tools/dump_derived.c maps the derived draws back to uniform bits for PractRand and TestU01. The results are in docs/statistics.md of the spec repository.

CI