SPB Git

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%
2.9 KB · 93 lines swift
Raw Blame History
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