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.0 KB · 62 lines swift
Raw Blame History
1//2//  FixtureSupport.swift3//  Metrika4//5//  Author:  Simon-Pierre Boucher6//  Contact: contact@spboucher.ai7//  Copyright © 2026 Simon-Pierre Boucher. All rights reserved.8//910import Foundation11import Testing1213/// Golden values produced by Tests/Fixtures/generate.R.14struct Fixtures {15    let expected: [String: Double]16    let datasetURL: URL1718    init() throws {19        guard let tsv = Bundle.module.url(20            forResource: "expected", withExtension: "tsv", subdirectory: "Fixtures"21        ), let csv = Bundle.module.url(22            forResource: "regression", withExtension: "csv", subdirectory: "Fixtures"23        ) else {24            throw NSError(domain: "Fixtures", code: 1, userInfo: [25                NSLocalizedDescriptionKey: "fixture resources missing — run Tests/Fixtures/generate.R",26            ])27        }28        var values: [String: Double] = [:]29        for line in try String(contentsOf: tsv, encoding: .utf8)30            .split(separator: "\n") {31            let parts = line.split(separator: "\t")32            guard parts.count == 2, let value = Double(parts[1]) else { continue }33            values[String(parts[0])] = value34        }35        self.expected = values36        self.datasetURL = csv37    }3839    subscript(key: String) -> Double {40        guard let value = expected[key] else {41            Issue.record("missing fixture key '\(key)'")42            return .nan43        }44        return value45    }46}4748/// Relative-tolerance comparison (CLAUDE.md §0: CPU paths match reference49/// implementations to at least 1e-10 relative tolerance).50func expectClose(51    _ actual: Double, _ expected: Double, rtol: Double = 1e-10,52    _ label: String = "", sourceLocation: SourceLocation = #_sourceLocation53) {54    let scale = max(abs(expected), abs(actual), 1e-300)55    let relative = abs(actual - expected) / scale56    #expect(57        relative <= rtol,58        "\(label): actual \(actual) vs expected \(expected) (rel. err. \(relative))",59        sourceLocation: sourceLocation60    )61}62