spb/metrika Public
Stata-class statistics, GPU-accelerated by Apple Silicon. Native Swift — no Electron, no Python runtime, no compromises.
Swift 92.4%
HTML 3.3%
R 3%
Shell 1.3%
1//2// PhiloxTests.swift3// Metrika4//5// Author: Simon-Pierre Boucher6// Contact: contact@spboucher.ai7// Copyright © 2026 Simon-Pierre Boucher. All rights reserved.8//910import Testing11import ZQGPU1213@Suite("Philox4x32-10 RNG")14struct PhiloxTests {1516 @Test("Random123 known-answer vectors")17 func knownAnswers() {18 // Zero counter, zero key.19 let zero = Philox4x32(seed: 0).block(counter: (0, 0, 0, 0))20 #expect(zero.0 == 0x6627_e8d5)21 #expect(zero.1 == 0xe169_c58d)22 #expect(zero.2 == 0xbc57_ac4c)23 #expect(zero.3 == 0x9b00_dbd8)2425 // All-ones counter and key (Random123 kat_vectors).26 let ones = Philox4x32(seed: .max).block(27 counter: (0xffff_ffff, 0xffff_ffff, 0xffff_ffff, 0xffff_ffff)28 )29 #expect(ones.0 == 0x408f_276d)30 #expect(ones.1 == 0x41c8_3b0e)31 #expect(ones.2 == 0xa20b_c7c6)32 #expect(ones.3 == 0x6d54_51fd)33 }3435 @Test("same seed produces identical streams — reproducibility blocker")36 func determinism() {37 let a = Philox4x32(seed: 42)38 let b = Philox4x32(seed: 42)39 for index in [0, 1, 2, 1_000, 1_000_000] as [UInt64] {40 #expect(a.word(at: index) == b.word(at: index))41 #expect(a.uniform(at: index) == b.uniform(at: index))42 }43 }4445 @Test("different seeds diverge")46 func seedsDiffer() {47 let a = Philox4x32(seed: 42)48 let b = Philox4x32(seed: 43)49 let differing = (0..<64).count { a.word(at: UInt64($0)) != b.word(at: UInt64($0)) }50 #expect(differing > 60)51 }5253 @Test("uniforms are in [0, 1) and pass a coarse mean check")54 func uniformRange() {55 let generator = Philox4x32(seed: 7)56 var sum = 0.057 let n = 100_00058 for i in 0..<n {59 let u = generator.uniform(at: UInt64(i))60 #expect(u >= 0 && u < 1)61 sum += u62 }63 let mean = sum / Double(n)64 #expect(abs(mean - 0.5) < 0.005, "mean \(mean) too far from 0.5")65 }6667 @Test("bounded integers stay in range and hit every value")68 func integerBounds() {69 let generator = Philox4x32(seed: 11)70 var seen = Set<Int>()71 for i in 0..<10_000 {72 let value = generator.integer(at: UInt64(i), bound: 10)73 #expect(value >= 0 && value < 10)74 seen.insert(value)75 }76 #expect(seen.count == 10)77 }7879 @Test("bootstrap replicates are independent of computation order")80 func resamplingAddressable() {81 let generator = Philox4x32(seed: 42)82 let early = ZQResampling.pairsBootstrapIndices(83 replicate: 5, sampleSize: 100, generator: generator84 )85 // Recomputing replicate 5 in isolation gives the same draw.86 let again = ZQResampling.pairsBootstrapIndices(87 replicate: 5, sampleSize: 100, generator: Philox4x32(seed: 42)88 )89 #expect(early == again)90 #expect(early.allSatisfy { (0..<100).contains($0) })91 }92}93